void
unmap_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
{
- struct ds_xdg_surface_v6_configure *configure, *tmp;
+ surface->mapped = false;
+
+ wl_signal_emit_mutable(&surface->events.unmap, surface);
+}
- // TODO handle popup
+void
+reset_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
+{
+ struct ds_xdg_surface_v6_configure *configure, *tmp;
- if (surface->mapped)
- wl_signal_emit_mutable(&surface->events.unmap, surface);
+ surface->configured = false;
switch (surface->role) {
case DS_XDG_SURFACE_V6_ROLE_TOPLEVEL:
- if (surface->toplevel->parent) {
- wl_list_remove(&surface->toplevel->parent_unmap.link);
- surface->toplevel->parent = NULL;
- }
- free(surface->toplevel->title);
- surface->toplevel->title = NULL;
- free(surface->toplevel->app_id);
- surface->toplevel->app_id = NULL;
+ reset_xdg_toplevel_v6(surface->toplevel);
break;
case DS_XDG_SURFACE_V6_ROLE_POPUP:
// TODO
break;
case DS_XDG_SURFACE_V6_ROLE_NONE:
- DS_ASSERT_NOT_REACHED();
+ break;
}
- wl_list_for_each_safe(configure, tmp, &surface->configure_list, link)
+ wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
xdg_surface_v6_configure_destroy(configure);
+ }
if (surface->configure_idle) {
wl_event_source_remove(surface->configure_idle);
surface->configure_idle = NULL;
}
-
- surface->configured = false;
- surface->mapped = false;
}
void
-reset_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
+destroy_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
{
- struct ds_xdg_toplevel_v6_requested *req;
+ destroy_xdg_surface_v6_role(surface);
+
+ wl_list_remove(&surface->link);
+ wl_list_remove(&surface->listener.surface_destroy.link);
+ wl_list_remove(&surface->listener.surface_commit.link);
+
+ wl_resource_set_user_data(surface->resource, NULL);
+ free(surface);
+}
- if (surface->role != DS_XDG_SURFACE_V6_ROLE_NONE)
+void
+destroy_xdg_surface_v6_role(struct ds_xdg_surface_v6 *surface)
+{
+ if (surface->configured && surface->mapped)
unmap_xdg_surface_v6(surface);
+ reset_xdg_surface_v6(surface);
+
if (surface->added) {
wl_signal_emit_mutable(&surface->events.destroy, surface);
surface->added = false;
switch (surface->role) {
case DS_XDG_SURFACE_V6_ROLE_TOPLEVEL:
- wl_resource_set_user_data(surface->toplevel->resource, NULL);
- surface->toplevel->resource = NULL;
- req = &surface->toplevel->requested;
- if (req->fullscreen_output)
- wl_list_remove(&req->fullscreen_output_destroy.link);
- free(surface->toplevel);
+ destroy_xdg_toplevel_v6(surface->toplevel);
surface->toplevel = NULL;
break;
case DS_XDG_SURFACE_V6_ROLE_POPUP:
// TODO
break;
- case DS_XDG_SURFACE_V6_ROLE_NONE:
- // This space is intentionally left blank
+ default:
break;
}
}
void
-destroy_xdg_surface_v6(struct ds_xdg_surface_v6 *surface)
-{
- reset_xdg_surface_v6(surface);
-
- wl_resource_set_user_data(surface->resource, NULL);
-
- ds_surface_reset_role_data(surface->ds_surface);
-
- wl_list_remove(&surface->link);
- wl_list_remove(&surface->listener.surface_destroy.link);
- wl_list_remove(&surface->listener.surface_commit.link);
-
- free(surface);
-}
-
-void
handle_xdg_surface_v6_commit(struct ds_surface *ds_surface)
{
struct ds_xdg_surface_v6 *surface;
// inert toplevel or popup
break;
case DS_XDG_SURFACE_V6_ROLE_TOPLEVEL:
- handle_xdg_surface_v6_toplevel_committed(surface);
- // TODO
+ handle_xdg_toplevel_v6_committed(surface->toplevel);
break;
case DS_XDG_SURFACE_V6_ROLE_POPUP:
// TODO
static const struct zxdg_toplevel_v6_interface xdg_toplevel_v6_impl;
static void xdg_toplevel_v6_handle_resource_destroy(struct wl_resource *resource);
+static void xdg_toplevel_v6_set_parent(struct ds_xdg_toplevel_v6 *toplevel,
+ struct ds_xdg_toplevel_v6 *parent);
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_set_parent_listener(struct ds_xdg_toplevel_v6 *toplevel,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&toplevel->events.set_parent, listener);
+}
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_request_move_listener(struct ds_xdg_toplevel_v6 *toplevel,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&toplevel->events.request_move, listener);
+}
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_request_resize_listener(struct ds_xdg_toplevel_v6 *toplevel,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&toplevel->events.request_resize, listener);
+}
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_request_maximize_listener(
+ struct ds_xdg_toplevel_v6 *toplevel,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&toplevel->events.request_maximize, listener);
+}
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_request_fullscreen_listener(
+ struct ds_xdg_toplevel_v6 *toplevel,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&toplevel->events.request_fullscreen, listener);
+}
+
+WL_EXPORT void
+ds_xdg_toplevel_v6_add_request_minimize_listener(
+ struct ds_xdg_toplevel_v6 *toplevel,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&toplevel->events.request_minimize, listener);
+}
WL_EXPORT uint32_t
ds_xdg_toplevel_v6_set_size(struct ds_xdg_toplevel_v6 *toplevel,
}
void
-handle_xdg_surface_v6_toplevel_committed(struct ds_xdg_surface_v6 *surface)
+handle_xdg_toplevel_v6_committed(struct ds_xdg_toplevel_v6 *toplevel)
{
- if (!surface->toplevel->added) {
- ds_xdg_surface_v6_schedule_configure(surface);
- surface->toplevel->added = true;
- return;
- }
+ toplevel->current = toplevel->pending;
- surface->toplevel->current = surface->toplevel->pending;
+ if (!toplevel->sent_initial_configure) {
+ ds_xdg_surface_v6_schedule_configure(toplevel->base);
+ toplevel->sent_initial_configure = true;
+ }
}
void
}
void
-destroy_xdg_toplevel_v6(struct ds_xdg_surface_v6 *xdg_surface_v6)
+destroy_xdg_toplevel_v6(struct ds_xdg_toplevel_v6 *toplevel)
{
- reset_xdg_surface_v6(xdg_surface_v6);
+ wl_resource_set_user_data(toplevel->resource, NULL);
+ free(toplevel);
+}
+
+void
+reset_xdg_toplevel_v6(struct ds_xdg_toplevel_v6 *toplevel)
+{
+ if (toplevel->parent) {
+ wl_list_remove(&toplevel->parent_unmap.link);
+ toplevel->parent = NULL;
+ }
+
+ free(toplevel->title);
+ toplevel->title = NULL;
+
+ free(toplevel->app_id);
+ toplevel->app_id = NULL;
+
+ if (toplevel->requested.fullscreen_output) {
+ wl_list_remove(&toplevel->requested.fullscreen_output_destroy.link);
+ toplevel->requested.fullscreen_output = NULL;
+ }
+
+ toplevel->requested.fullscreen = false;
+ toplevel->requested.maximized = false;
+ toplevel->requested.minimized = false;
+
+ toplevel->sent_initial_configure = false;
}
static void
xdg_toplevel_v6_handle_set_parent(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *parent_resource)
{
- // TODO
+ struct ds_xdg_toplevel_v6 *toplevel, *parent = NULL;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
+ if (parent_resource)
+ parent = wl_resource_get_user_data(parent_resource);
+
+ xdg_toplevel_v6_set_parent(toplevel, parent);
}
static void
char *tmp;
toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
tmp = strdup(title);
if (!tmp) {
wl_resource_post_no_memory(resource);
char *tmp;
toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
tmp = strdup(app_id);
if (!tmp) {
wl_resource_post_no_memory(resource);
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial)
{
- // TODO
+ struct ds_xdg_toplevel_v6 *toplevel;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
+ if (!toplevel->base->configured) {
+ wl_resource_post_error(toplevel->base->resource,
+ ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+ "surface has not been configured yet");
+ return;
+ }
+
+ struct ds_xdg_toplevel_v6_event_request_move event = {
+ .toplevel = toplevel,
+ .seat_resource = seat_resource,
+ .serial = serial,
+ };
+ wl_signal_emit_mutable(&toplevel->events.request_move, &event);
}
static void
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial, uint32_t edges)
{
- // TODO
+ struct ds_xdg_toplevel_v6 *toplevel;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
+ if (!toplevel->base->configured) {
+ wl_resource_post_error(toplevel->base->resource,
+ ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+ "surface has not been configured yet");
+ return;
+ }
+
+ struct ds_xdg_toplevel_v6_event_request_resize event = {
+ .toplevel = toplevel,
+ .seat_resource = seat_resource,
+ .serial = serial,
+ .edges = edges,
+ };
+ wl_signal_emit_mutable(&toplevel->events.request_resize, &event);
}
static void
struct ds_xdg_toplevel_v6 *toplevel;
toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
toplevel->pending.max_width = width;
toplevel->pending.max_height = height;
}
struct ds_xdg_toplevel_v6 *toplevel;
toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
toplevel->pending.min_width = width;
toplevel->pending.min_height = height;
}
struct ds_xdg_toplevel_v6 *toplevel;
toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
toplevel->requested.maximized = true;
wl_signal_emit_mutable(&toplevel->events.request_maximize, toplevel);
- ds_xdg_surface_v6_schedule_configure(toplevel->base);
}
static void
struct ds_xdg_toplevel_v6 *toplevel;
toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
toplevel->requested.maximized = false;
wl_signal_emit_mutable(&toplevel->events.request_maximize, toplevel);
- ds_xdg_surface_v6_schedule_configure(toplevel->base);
}
static void
xdg_toplevel_v6_handle_set_fullscreen(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *output_resource)
{
- // TODO
+ struct ds_xdg_toplevel_v6 *toplevel;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
+ // TODO get a ds_output from an output_resource
+
+ toplevel->requested.fullscreen = true;
+ wl_signal_emit_mutable(&toplevel->events.request_fullscreen, toplevel);
}
static void
xdg_toplevel_v6_handle_unset_fullscreen(struct wl_client *client,
struct wl_resource *resource)
{
- // TODO
+ struct ds_xdg_toplevel_v6 *toplevel;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
+ toplevel->requested.fullscreen = false;
+ wl_signal_emit_mutable(&toplevel->events.request_fullscreen, toplevel);
}
static void
struct ds_xdg_toplevel_v6 *toplevel;
toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ return;
+
toplevel->requested.minimized = true;
wl_signal_emit_mutable(&toplevel->events.request_maximize, toplevel);
}
if (!toplevel)
return;
- destroy_xdg_toplevel_v6(toplevel->base);
+ destroy_xdg_surface_v6_role(toplevel->base);
+}
+
+static void
+xdg_toplevel_v6_handle_parent_unmap(struct wl_listener *listener, void *data)
+{
+ struct ds_xdg_toplevel_v6 *toplevel;
+
+ toplevel = wl_container_of(listener, toplevel, parent_unmap);
+ xdg_toplevel_v6_set_parent(toplevel, toplevel->parent->parent);
+}
+
+static void
+xdg_toplevel_v6_set_parent(struct ds_xdg_toplevel_v6 *toplevel,
+ struct ds_xdg_toplevel_v6 *parent)
+{
+ struct ds_xdg_toplevel_v6 *iter = parent;
+
+ while (iter) {
+ if (iter == toplevel)
+ return;
+ iter = iter->parent;
+ }
+
+ if (toplevel->parent)
+ wl_list_remove(&toplevel->parent_unmap.link);
+
+ if (parent && parent->base->mapped) {
+ toplevel->parent = parent;
+ toplevel->parent_unmap.notify = xdg_toplevel_v6_handle_parent_unmap;
+ wl_signal_add(&toplevel->parent->base->events.unmap,
+ &toplevel->parent_unmap);
+ }
+ else {
+ toplevel->parent = NULL;
+ }
+
+ wl_signal_emit_mutable(&toplevel->events.set_parent, NULL);
}