struct xdg_deco {
struct wlr_xdg_toplevel_decoration_v1 *wlr_xdg_decoration;
+ enum wlr_xdg_toplevel_decoration_v1_mode client_mode;
struct view *view;
struct wl_listener destroy;
struct wl_listener request_mode;
+ struct wl_listener surface_commit;
};
static void
struct xdg_deco *xdg_deco = wl_container_of(listener, xdg_deco, destroy);
wl_list_remove(&xdg_deco->destroy.link);
wl_list_remove(&xdg_deco->request_mode.link);
+ if (xdg_deco->surface_commit.notify) {
+ wl_list_remove(&xdg_deco->surface_commit.link);
+ xdg_deco->surface_commit.notify = NULL;
+ }
free(xdg_deco);
}
+static void
+handle_surface_commit(struct wl_listener *listener, void *data)
+{
+ struct xdg_deco *xdg_deco = wl_container_of(listener, xdg_deco, surface_commit);
+ struct wlr_xdg_toplevel_decoration_v1 *deco = xdg_deco->wlr_xdg_decoration;
+
+ if (deco->toplevel->base->initial_commit) {
+ wlr_xdg_toplevel_decoration_v1_set_mode(deco, xdg_deco->client_mode);
+ wl_list_remove(&xdg_deco->surface_commit.link);
+ xdg_deco->surface_commit.notify = NULL;
+ }
+}
+
static void
xdg_deco_request_mode(struct wl_listener *listener, void *data)
{
"requested: %u", client_mode);
}
- wlr_xdg_toplevel_decoration_v1_set_mode(xdg_deco->wlr_xdg_decoration,
- client_mode);
+ /*
+ * We may get multiple request_mode calls in an unitialized state.
+ * Just update the last requested mode and only add the commit
+ * handler on the first uninitialized state call.
+ */
+ xdg_deco->client_mode = client_mode;
+
+ if (xdg_deco->wlr_xdg_decoration->toplevel->base->initialized) {
+ wlr_xdg_toplevel_decoration_v1_set_mode(xdg_deco->wlr_xdg_decoration,
+ client_mode);
+ } else if (!xdg_deco->surface_commit.notify) {
+ xdg_deco->surface_commit.notify = handle_surface_commit;
+ wl_signal_add(
+ &xdg_deco->wlr_xdg_decoration->toplevel->base->surface->events.commit,
+ &xdg_deco->surface_commit);
+ }
if (client_mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) {
view_set_ssd_mode(xdg_deco->view, LAB_SSD_MODE_FULL);
} else {
struct wlr_xdg_surface *xdg_surface = xdg_surface_from_view(view);
assert(view->surface);
+ if (xdg_surface->initial_commit) {
+ wlr_log(WLR_DEBUG, "scheduling configure");
+ wlr_xdg_surface_schedule_configure(xdg_surface);
+ return;
+ }
+
struct wlr_box size;
wlr_xdg_surface_get_geometry(xdg_surface, &size);
/* Remove xdg-shell view specific listeners */
wl_list_remove(&xdg_toplevel_view->set_app_id.link);
wl_list_remove(&xdg_toplevel_view->new_popup.link);
+ wl_list_remove(&view->commit.link);
if (view->pending_configure_timeout) {
wl_event_source_remove(view->pending_configure_timeout);
view_set_output(view, output_nearest_to_cursor(view->server));
}
struct wlr_xdg_surface *xdg_surface = xdg_surface_from_view(view);
- view->surface = xdg_surface->surface;
wlr_scene_node_set_enabled(&view->scene_tree->node, true);
if (!view->been_mapped) {
struct wlr_xdg_toplevel_requested *requested =
view_moved(view);
}
- view->commit.notify = handle_commit;
- wl_signal_add(&xdg_surface->surface->events.commit, &view->commit);
-
view_impl_map(view);
view->been_mapped = true;
}
if (view->mapped) {
view->mapped = false;
wlr_scene_node_set_enabled(&view->scene_tree->node, false);
- wl_list_remove(&view->commit.link);
view_impl_unmap(view);
}
}
kde_server_decoration_set_view(view, xdg_surface->surface);
/* In support of xdg popups and IME popup */
- xdg_surface->surface->data = tree;
+ view->surface = xdg_surface->surface;
+ view->surface->data = tree;
view_connect_map(view, xdg_surface->surface);
CONNECT_SIGNAL(toplevel, view, request_maximize);
CONNECT_SIGNAL(toplevel, view, request_fullscreen);
CONNECT_SIGNAL(toplevel, view, set_title);
+ CONNECT_SIGNAL(view->surface, view, commit);
/* Events specific to XDG toplevel views */
CONNECT_SIGNAL(toplevel, xdg_toplevel_view, set_app_id);