]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Chase wlroots: Unified mapping
authorChristopher Snowhill <kode54@gmail.com>
Thu, 15 Jun 2023 09:35:43 +0000 (02:35 -0700)
committerJohan Malm <johanmalm@users.noreply.github.com>
Mon, 27 Nov 2023 21:01:53 +0000 (21:01 +0000)
Need to handle new unified mapping, where mapping is attached to the
wlr_surface objects instead of their parents. Also, most of them require
a new associate event for xsurface objects, their surface member will be
NULL before this event is received.

Refactored by jlindgren:
- add struct mappable
- unify map/unmap logic

include/view.h
include/xwayland.h
src/dnd.c
src/layers.c
src/session-lock.c
src/view.c
src/xdg.c
src/xwayland-unmanaged.c
src/xwayland.c
subprojects/wlroots.wrap

index f747252c8f6d790921b2f639d80fdab3d09b03dc..f7329fdc67d9bb71b2394416071bac210bcb60ac 100644 (file)
@@ -70,6 +70,13 @@ enum view_wants_focus {
 struct view;
 struct wlr_surface;
 
+/* Common to struct view and struct xwayland_unmanaged */
+struct mappable {
+       bool connected;
+       struct wl_listener map;
+       struct wl_listener unmap;
+};
+
 /* Basic size hints (subset of XSizeHints from X11) */
 struct view_size_hints {
        int min_width;
@@ -194,8 +201,8 @@ struct view {
                struct wl_listener destroy;
        } toplevel;
 
-       struct wl_listener map;
-       struct wl_listener unmap;
+       struct mappable mappable;
+
        struct wl_listener destroy;
        struct wl_listener surface_destroy;
        struct wl_listener commit;
@@ -345,6 +352,10 @@ view_is_focusable(struct view *view) {
        return view_is_focusable_from(view, NULL);
 }
 
+void mappable_connect(struct mappable *mappable, struct wlr_surface *surface,
+       wl_notify_func_t notify_map, wl_notify_func_t notify_unmap);
+void mappable_disconnect(struct mappable *mappable);
+
 void view_toggle_keybinds(struct view *view);
 
 void view_set_activated(struct view *view, bool activated);
@@ -427,6 +438,7 @@ void view_adjust_size(struct view *view, int *w, int *h);
 
 void view_evacuate_region(struct view *view);
 void view_on_output_destroy(struct view *view);
+void view_connect_map(struct view *view, struct wlr_surface *surface);
 void view_destroy(struct view *view);
 
 enum view_axis view_axis_parse(const char *direction);
index 8bb475ba5a7bf6ac28738eda28e74fdb250b8b33..76e48ca5179a51af157c6079f46a886898bf84f7 100644 (file)
@@ -13,12 +13,14 @@ struct xwayland_unmanaged {
        struct wlr_scene_node *node;
        struct wl_list link;
 
+       struct mappable mappable;
+
+       struct wl_listener associate;
+       struct wl_listener dissociate;
        struct wl_listener request_activate;
        struct wl_listener request_configure;
 /*     struct wl_listener request_fullscreen; */
        struct wl_listener set_geometry;
-       struct wl_listener map;
-       struct wl_listener unmap;
        struct wl_listener destroy;
        struct wl_listener set_override_redirect;
 };
@@ -28,6 +30,8 @@ struct xwayland_view {
        struct wlr_xwayland_surface *xwayland_surface;
 
        /* Events unique to XWayland views */
+       struct wl_listener associate;
+       struct wl_listener dissociate;
        struct wl_listener request_activate;
        struct wl_listener request_configure;
        struct wl_listener set_class;
index e69a85483bbfb26417e9da4f96d53a95cae3684d..695096f45d7a1c0f2a11fd2b2aeb69e529a53623 100644 (file)
--- a/src/dnd.c
+++ b/src/dnd.c
@@ -89,9 +89,9 @@ drag_icon_create(struct seat *seat, struct wlr_drag_icon *wlr_icon)
        self->events.unmap.notify = handle_icon_unmap;
        self->events.destroy.notify = handle_icon_destroy;
 
-       wl_signal_add(&wlr_icon->events.map, &self->events.map);
+       wl_signal_add(&wlr_icon->surface->events.map, &self->events.map);
        wl_signal_add(&wlr_icon->surface->events.commit, &self->events.commit);
-       wl_signal_add(&wlr_icon->events.unmap, &self->events.unmap);
+       wl_signal_add(&wlr_icon->surface->events.unmap, &self->events.unmap);
        wl_signal_add(&wlr_icon->events.destroy, &self->events.destroy);
 }
 
index 634e3727b79933b17dcd31b922c23ef2e167dd55..16a4be584b61bb35f426fc605d3f7c189e3b720d 100644 (file)
@@ -175,8 +175,8 @@ handle_surface_commit(struct wl_listener *listener, void *data)
                process_keyboard_interactivity(layer);
        }
 
-       if (committed || layer->mapped != layer_surface->mapped) {
-               layer->mapped = layer_surface->mapped;
+       if (committed || layer->mapped != layer_surface->surface->mapped) {
+               layer->mapped = layer_surface->surface->mapped;
                output_update_usable_area(output);
                /*
                 * Update cursor focus here to ensure we
@@ -401,10 +401,10 @@ handle_new_layer_surface(struct wl_listener *listener, void *data)
                &surface->surface_commit);
 
        surface->map.notify = handle_map;
-       wl_signal_add(&layer_surface->events.map, &surface->map);
+       wl_signal_add(&layer_surface->surface->events.map, &surface->map);
 
        surface->unmap.notify = handle_unmap;
-       wl_signal_add(&layer_surface->events.unmap, &surface->unmap);
+       wl_signal_add(&layer_surface->surface->events.unmap, &surface->unmap);
 
        surface->new_popup.notify = handle_new_popup;
        wl_signal_add(&layer_surface->events.new_popup, &surface->new_popup);
index 0f4f8ef6c172d50dbd1dd3fe2077539c90341a6f..00676577b63ecd9c5fa9a5d63fec91a25a3b07f9 100644 (file)
@@ -42,10 +42,10 @@ refocus_output(struct session_lock_output *output)
 
        struct session_lock_output *iter;
        wl_list_for_each(iter, &output->lock->session_lock_outputs, link) {
-               if (iter == output || !iter->surface) {
+               if (iter == output || !iter->surface || !iter->surface->surface) {
                        continue;
                }
-               if (iter->surface->mapped) {
+               if (iter->surface->surface->mapped) {
                        focus_surface(output->lock, iter->surface->surface);
                        return;
                }
@@ -110,7 +110,7 @@ found_lock_output:
        wl_signal_add(&lock_surface->events.destroy, &lock_output->surface_destroy);
 
        lock_output->surface_map.notify = handle_surface_map;
-       wl_signal_add(&lock_surface->events.map, &lock_output->surface_map);
+       wl_signal_add(&lock_surface->surface->events.map, &lock_output->surface_map);
 
        lock_output_reconfigure(lock_output);
 }
index 8c77dcdaefc9d1014b3e57766742bbef733976ad..4a2008df1a481da014bc74eb8b72cdf77d4ca7ee 100644 (file)
@@ -1605,6 +1605,55 @@ view_toggle_keybinds(struct view *view)
        }
 }
 
+void
+mappable_connect(struct mappable *mappable, struct wlr_surface *surface,
+               wl_notify_func_t notify_map, wl_notify_func_t notify_unmap)
+{
+       assert(mappable);
+       assert(!mappable->connected);
+       mappable->map.notify = notify_map;
+       wl_signal_add(&surface->events.map, &mappable->map);
+       mappable->unmap.notify = notify_unmap;
+       wl_signal_add(&surface->events.unmap, &mappable->unmap);
+       mappable->connected = true;
+}
+
+void
+mappable_disconnect(struct mappable *mappable)
+{
+       assert(mappable);
+       assert(mappable->connected);
+       wl_list_remove(&mappable->map.link);
+       wl_list_remove(&mappable->unmap.link);
+       mappable->connected = false;
+}
+
+static void
+handle_map(struct wl_listener *listener, void *data)
+{
+       struct view *view = wl_container_of(listener, view, mappable.map);
+       view->impl->map(view);
+}
+
+static void
+handle_unmap(struct wl_listener *listener, void *data)
+{
+       struct view *view = wl_container_of(listener, view, mappable.unmap);
+       view->impl->unmap(view, /* client_request */ true);
+}
+
+/*
+ * TODO: after the release of wlroots 0.17, consider incorporating this
+ * function into a more general view_set_surface() function, which could
+ * connect other surface event handlers (like commit) as well.
+ */
+void
+view_connect_map(struct view *view, struct wlr_surface *surface)
+{
+       assert(view);
+       mappable_connect(&view->mappable, surface, handle_map, handle_unmap);
+}
+
 void
 view_destroy(struct view *view)
 {
@@ -1612,8 +1661,10 @@ view_destroy(struct view *view)
        struct server *server = view->server;
        bool need_cursor_update = false;
 
-       wl_list_remove(&view->map.link);
-       wl_list_remove(&view->unmap.link);
+       if (view->mappable.connected) {
+               mappable_disconnect(&view->mappable);
+       }
+
        wl_list_remove(&view->request_move.link);
        wl_list_remove(&view->request_resize.link);
        wl_list_remove(&view->request_minimize.link);
index a02c8aaa963094a59ca0c3fef6e7382d231962d7..713eccd1bdc2fa3995db51de6cecbbfe16918358 100644 (file)
--- a/src/xdg.c
+++ b/src/xdg.c
@@ -163,20 +163,6 @@ set_pending_configure_serial(struct view *view, uint32_t serial)
                CONFIGURE_TIMEOUT_MS);
 }
 
-static void
-handle_map(struct wl_listener *listener, void *data)
-{
-       struct view *view = wl_container_of(listener, view, map);
-       view->impl->map(view);
-}
-
-static void
-handle_unmap(struct wl_listener *listener, void *data)
-{
-       struct view *view = wl_container_of(listener, view, unmap);
-       view->impl->unmap(view, /* client_request */ true);
-}
-
 static void
 handle_destroy(struct wl_listener *listener, void *data)
 {
@@ -688,8 +674,7 @@ xdg_surface_new(struct wl_listener *listener, void *data)
        /* In support of xdg popups */
        xdg_surface->surface->data = tree;
 
-       CONNECT_SIGNAL(xdg_surface, view, map);
-       CONNECT_SIGNAL(xdg_surface, view, unmap);
+       view_connect_map(view, xdg_surface->surface);
        CONNECT_SIGNAL(xdg_surface, view, destroy);
 
        struct wlr_xdg_toplevel *toplevel = xdg_surface->toplevel;
index 21df12ba3ad9394ea40f8882ea150ff41e6637fc..3910eb2a0d95c72566c92156c51290109b1e3407 100644 (file)
@@ -37,7 +37,7 @@ static void
 handle_map(struct wl_listener *listener, void *data)
 {
        struct xwayland_unmanaged *unmanaged =
-               wl_container_of(listener, unmanaged, map);
+               wl_container_of(listener, unmanaged, mappable.map);
        struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
        assert(!unmanaged->node);
 
@@ -95,7 +95,7 @@ static void
 handle_unmap(struct wl_listener *listener, void *data)
 {
        struct xwayland_unmanaged *unmanaged =
-               wl_container_of(listener, unmanaged, unmap);
+               wl_container_of(listener, unmanaged, mappable.unmap);
        struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
        struct seat *seat = &unmanaged->server->seat;
        assert(unmanaged->node);
@@ -116,16 +116,43 @@ handle_unmap(struct wl_listener *listener, void *data)
        }
 }
 
+static void
+handle_associate(struct wl_listener *listener, void *data)
+{
+       struct xwayland_unmanaged *unmanaged =
+               wl_container_of(listener, unmanaged, associate);
+       assert(unmanaged->xwayland_surface &&
+               unmanaged->xwayland_surface->surface);
+
+       mappable_connect(&unmanaged->mappable,
+               unmanaged->xwayland_surface->surface,
+               handle_map, handle_unmap);
+}
+
+static void
+handle_dissociate(struct wl_listener *listener, void *data)
+{
+       struct xwayland_unmanaged *unmanaged =
+               wl_container_of(listener, unmanaged, dissociate);
+
+       mappable_disconnect(&unmanaged->mappable);
+}
+
 static void
 handle_destroy(struct wl_listener *listener, void *data)
 {
        struct xwayland_unmanaged *unmanaged =
                wl_container_of(listener, unmanaged, destroy);
+
+       if (unmanaged->mappable.connected) {
+               mappable_disconnect(&unmanaged->mappable);
+       }
+
+       wl_list_remove(&unmanaged->associate.link);
+       wl_list_remove(&unmanaged->dissociate.link);
        wl_list_remove(&unmanaged->request_configure.link);
        wl_list_remove(&unmanaged->set_override_redirect.link);
        wl_list_remove(&unmanaged->request_activate.link);
-       wl_list_remove(&unmanaged->map.link);
-       wl_list_remove(&unmanaged->unmap.link);
        wl_list_remove(&unmanaged->destroy.link);
        free(unmanaged);
 }
@@ -139,9 +166,9 @@ handle_set_override_redirect(struct wl_listener *listener, void *data)
        struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
        struct server *server = unmanaged->server;
 
-       bool mapped = xsurface->mapped;
+       bool mapped = xsurface->surface && xsurface->surface->mapped;
        if (mapped) {
-               handle_unmap(&unmanaged->unmap, NULL);
+               handle_unmap(&unmanaged->mappable.unmap, NULL);
        }
        handle_destroy(&unmanaged->destroy, NULL);
 
@@ -155,7 +182,7 @@ handle_request_activate(struct wl_listener *listener, void *data)
        struct xwayland_unmanaged *unmanaged =
                wl_container_of(listener, unmanaged, request_activate);
        struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
-       if (!xsurface->mapped) {
+       if (!xsurface->surface || !xsurface->surface->mapped) {
                return;
        }
        struct server *server = unmanaged->server;
@@ -191,14 +218,14 @@ xwayland_unmanaged_create(struct server *server,
         */
        assert(!xsurface->data);
 
-       CONNECT_SIGNAL(xsurface, unmanaged, map);
-       CONNECT_SIGNAL(xsurface, unmanaged, unmap);
+       CONNECT_SIGNAL(xsurface, unmanaged, associate);
+       CONNECT_SIGNAL(xsurface, unmanaged, dissociate);
        CONNECT_SIGNAL(xsurface, unmanaged, destroy);
        CONNECT_SIGNAL(xsurface, unmanaged, request_activate);
        CONNECT_SIGNAL(xsurface, unmanaged, request_configure);
        CONNECT_SIGNAL(xsurface, unmanaged, set_override_redirect);
 
        if (mapped) {
-               handle_map(&unmanaged->map, xsurface);
+               handle_map(&unmanaged->mappable.map, NULL);
        }
 }
index c0888236f873a5fee25d2695088b0c4c63ef7f62..0753f1dedcb413efba3bfa52885312d0b91d33fa 100644 (file)
@@ -15,6 +15,8 @@
 #include "workspaces.h"
 #include "xwayland.h"
 
+static void xwayland_view_unmap(struct view *view, bool client_request);
+
 static struct view_size_hints
 xwayland_view_get_size_hints(struct view *view)
 {
@@ -225,17 +227,24 @@ handle_request_resize(struct wl_listener *listener, void *data)
 }
 
 static void
-handle_map(struct wl_listener *listener, void *data)
+handle_associate(struct wl_listener *listener, void *data)
 {
-       struct view *view = wl_container_of(listener, view, map);
-       view->impl->map(view);
+       struct xwayland_view *xwayland_view =
+               wl_container_of(listener, xwayland_view, associate);
+       assert(xwayland_view->xwayland_surface &&
+               xwayland_view->xwayland_surface->surface);
+
+       view_connect_map(&xwayland_view->base,
+               xwayland_view->xwayland_surface->surface);
 }
 
 static void
-handle_unmap(struct wl_listener *listener, void *data)
+handle_dissociate(struct wl_listener *listener, void *data)
 {
-       struct view *view = wl_container_of(listener, view, unmap);
-       view->impl->unmap(view, /* client_request */ true);
+       struct xwayland_view *xwayland_view =
+               wl_container_of(listener, xwayland_view, dissociate);
+
+       mappable_disconnect(&xwayland_view->base.mappable);
 }
 
 static void
@@ -275,6 +284,8 @@ handle_destroy(struct wl_listener *listener, void *data)
        xwayland_view->xwayland_surface = NULL;
 
        /* Remove XWayland view specific listeners */
+       wl_list_remove(&xwayland_view->associate.link);
+       wl_list_remove(&xwayland_view->dissociate.link);
        wl_list_remove(&xwayland_view->request_activate.link);
        wl_list_remove(&xwayland_view->request_configure.link);
        wl_list_remove(&xwayland_view->set_class.link);
@@ -434,9 +445,9 @@ handle_set_override_redirect(struct wl_listener *listener, void *data)
        struct wlr_xwayland_surface *xsurface = xwayland_view->xwayland_surface;
 
        struct server *server = view->server;
-       bool mapped = xsurface->mapped;
+       bool mapped = xsurface->surface && xsurface->surface->mapped;
        if (mapped) {
-               handle_unmap(&view->unmap, xsurface);
+               xwayland_view_unmap(view, /* client_request */ true);
        }
        handle_destroy(&view->destroy, xsurface);
        /* view is invalid after this point */
@@ -770,8 +781,6 @@ xwayland_view_create(struct server *server,
        view->scene_tree = wlr_scene_tree_create(view->workspace->tree);
        node_descriptor_create(&view->scene_tree->node, LAB_NODE_DESC_VIEW, view);
 
-       CONNECT_SIGNAL(xsurface, view, map);
-       CONNECT_SIGNAL(xsurface, view, unmap);
        CONNECT_SIGNAL(xsurface, view, destroy);
        CONNECT_SIGNAL(xsurface, view, request_minimize);
        CONNECT_SIGNAL(xsurface, view, request_maximize);
@@ -781,6 +790,8 @@ xwayland_view_create(struct server *server,
        CONNECT_SIGNAL(xsurface, view, set_title);
 
        /* Events specific to XWayland views */
+       CONNECT_SIGNAL(xsurface, xwayland_view, associate);
+       CONNECT_SIGNAL(xsurface, xwayland_view, dissociate);
        CONNECT_SIGNAL(xsurface, xwayland_view, request_activate);
        CONNECT_SIGNAL(xsurface, xwayland_view, request_configure);
        CONNECT_SIGNAL(xsurface, xwayland_view, set_class);
index 6003c8c1f2bc84999d149ba4539b0427461db83c..91b514df763feaba16f9eda7f7c33aa0bc45b94d 100644 (file)
@@ -1,6 +1,6 @@
 [wrap-git]
 url = https://gitlab.freedesktop.org/wlroots/wlroots.git
-revision = 0bb574239d3b164596677bf4cec371ff0671dc4f
+revision = 26676c8c072f813dc2d7e2b2dfe9e2701ce361a7
 
 [provide]
 dependency_names = wlroots