]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Handle wlr_surface->events.new_subsurface
authorJohan Malm <jgm323@gmail.com>
Tue, 2 Mar 2021 20:37:23 +0000 (20:37 +0000)
committerJohan Malm <jgm323@gmail.com>
Tue, 2 Mar 2021 20:37:23 +0000 (20:37 +0000)
Add view-child.c, xdg-popup.c, subsurface.c in order to track damage
associated with new XDG subsurfaces.

include/labwc.h
src/meson.build
src/subsurface.c [new file with mode: 0644]
src/view-child.c [new file with mode: 0644]
src/view.c
src/xdg-popup.c [new file with mode: 0644]
src/xdg.c

index 30359aef850dbcb4601fa4023e38ceff9aadf869..1891af7fc9f4450ac89178b980941aa2607144d7 100644 (file)
@@ -230,7 +230,8 @@ struct view {
        struct wl_listener request_resize;
        struct wl_listener request_configure;
        struct wl_listener request_maximize;
-       struct wl_listener new_popup; /* xdg-shell only */
+       struct wl_listener new_popup;           /* xdg-shell only */
+       struct wl_listener new_subsurface;      /* xdg-shell only */
 };
 
 #if HAVE_XWAYLAND
@@ -248,18 +249,33 @@ struct xwayland_unmanaged {
 };
 #endif
 
+struct view_child {
+       struct wlr_surface *surface;
+       struct view *parent;
+       struct wl_listener commit;
+       struct wl_listener new_subsurface;
+};
+
+struct view_subsurface {
+       struct view_child view_child;
+       struct wlr_subsurface *subsurface;
+       struct wl_listener destroy;
+};
+
 struct xdg_popup {
+       struct view_child view_child;
        struct wlr_xdg_popup *wlr_popup;
-       struct view *view;
 
        struct wl_listener destroy;
-       struct wl_listener commit;
        struct wl_listener map;
        struct wl_listener unmap;
        struct wl_listener new_popup;
 };
 
+void xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup);
+
 void xdg_toplevel_decoration(struct wl_listener *listener, void *data);
+
 void xdg_surface_new(struct wl_listener *listener, void *data);
 
 #if HAVE_XWAYLAND
@@ -268,6 +284,11 @@ void xwayland_unmanaged_create(struct server *server,
        struct wlr_xwayland_surface *xsurface);
 #endif
 
+void view_child_init(struct view_child *child, struct view *view,
+       struct wlr_surface *wlr_surface);
+void view_child_finish(struct view_child *child);
+void subsurface_create(struct view *view, struct wlr_subsurface *wlr_subsurface);
+
 void view_move_resize(struct view *view, struct wlr_box geo);
 void view_move(struct view *view, double x, double y);
 void view_minimize(struct view *view);
index 8808657af6afcdb4037b5790b4d53095b5321284..2220eb249415c8647a48da17723b6e15d766eba9 100644 (file)
@@ -12,9 +12,12 @@ labwc_sources = files(
   'output.c',
   'seat.c',
   'server.c',
+  'subsurface.c',
   'theme.c',
   'view.c',
+  'view-child.c',
   'xdg.c',
+  'xdg-popup.c',
 )
 
 if have_xwayland
diff --git a/src/subsurface.c b/src/subsurface.c
new file mode 100644 (file)
index 0000000..2e49e71
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 the sway authors
+ * This file is only needed in support of tracking damage
+ */
+
+#include "labwc.h"
+
+static void
+subsurface_handle_destroy(struct wl_listener *listener, void *data)
+{
+       struct view_subsurface *subsurface = wl_container_of(listener,
+               subsurface, destroy);
+       struct view_child *view_child = (struct view_child *)subsurface;
+       if (!view_child) {
+               return;
+       }
+       wl_list_remove(&subsurface->destroy.link);
+       view_child_finish(&subsurface->view_child);
+       free(subsurface);
+}
+
+void
+subsurface_create(struct view *view, struct wlr_subsurface *wlr_subsurface)
+{
+       struct view_subsurface *subsurface = calloc(1, sizeof(struct view_subsurface));
+       if (!subsurface) {
+               return;
+       }
+       view_child_init(&subsurface->view_child, view, wlr_subsurface->surface);
+       subsurface->subsurface = wlr_subsurface;
+
+       subsurface->destroy.notify = subsurface_handle_destroy;
+       wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
+}
diff --git a/src/view-child.c b/src/view-child.c
new file mode 100644 (file)
index 0000000..d1b0b90
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 the sway authors
+ * This file is only needed in support of tracking damage
+ */
+
+#include "labwc.h"
+
+static void
+view_child_handle_commit(struct wl_listener *listener, void *data)
+{
+       struct view_child *child = wl_container_of(listener, child, commit);
+       damage_view_part(child->parent);
+}
+
+static void
+view_child_handle_new_subsurface(struct wl_listener *listener, void *data)
+{
+       struct view_child *child;
+       child = wl_container_of(listener, child, new_subsurface);
+       struct wlr_subsurface *wlr_subsurface = data;
+       subsurface_create(child->parent, wlr_subsurface);
+}
+
+void
+view_child_finish(struct view_child *child)
+{
+       if (!child) {
+               return;
+       }
+       damage_view_whole(child->parent);
+       wl_list_remove(&child->commit.link);
+       wl_list_remove(&child->new_subsurface.link);
+}
+
+void
+view_child_init(struct view_child *child, struct view *view,
+               struct wlr_surface *wlr_surface)
+{
+       child->parent = view;
+       child->surface = wlr_surface;
+
+       child->commit.notify = view_child_handle_commit;
+       wl_signal_add(&wlr_surface->events.commit, &child->commit);
+       child->new_subsurface.notify = view_child_handle_new_subsurface;
+       wl_signal_add(&wlr_surface->events.new_subsurface, &child->new_subsurface);
+}
index 56aef3f33b300fe6ccd4e094a494820832d564a4..cc7ac1db196c19d6e555558e68a554ffe15b4344 100644 (file)
@@ -1,7 +1,7 @@
 #include "labwc.h"
 
 #include <stdio.h>
-#include <assert.h>
+
 void
 view_move_resize(struct view *view, struct wlr_box geo)
 {
diff --git a/src/xdg-popup.c b/src/xdg-popup.c
new file mode 100644 (file)
index 0000000..f4b9b18
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 the sway authors
+ * This file is only needed in support of tracking damage
+ */
+
+#include "labwc.h"
+
+static void
+xdg_popup_destroy(struct view_child *view_child)
+{
+       if (!view_child) {
+               return;
+       }
+       struct xdg_popup *popup = (struct xdg_popup *)view_child;
+       wl_list_remove(&popup->destroy.link);
+       wl_list_remove(&popup->map.link);
+       wl_list_remove(&popup->unmap.link);
+       wl_list_remove(&popup->new_popup.link);
+       view_child_finish(&popup->view_child);
+       free(popup);
+}
+
+static void
+handle_xdg_popup_map(struct wl_listener *listener, void *data)
+{
+       struct xdg_popup *popup = wl_container_of(listener, popup, map);
+       damage_view_whole(popup->view_child.parent);
+}
+
+static void
+handle_xdg_popup_unmap(struct wl_listener *listener, void *data)
+{
+       struct xdg_popup *popup = wl_container_of(listener, popup, unmap);
+       damage_view_whole(popup->view_child.parent);
+}
+
+static void
+handle_xdg_popup_destroy(struct wl_listener *listener, void *data)
+{
+       struct xdg_popup *popup = wl_container_of(listener, popup, destroy);
+       struct view_child *view_child = (struct view_child *)popup;
+       xdg_popup_destroy(view_child);
+}
+
+static void
+popup_handle_new_xdg_popup(struct wl_listener *listener, void *data)
+{
+       struct xdg_popup *popup = wl_container_of(listener, popup, new_popup);
+       struct wlr_xdg_popup *wlr_popup = data;
+       xdg_popup_create(popup->view_child.parent, wlr_popup);
+}
+
+void
+xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
+{
+       struct xdg_popup *popup = calloc(1, sizeof(struct xdg_popup));
+       if (!popup) {
+               return;
+       }
+
+       popup->wlr_popup = wlr_popup;
+       view_child_init(&popup->view_child, view, wlr_popup->base->surface);
+
+       popup->destroy.notify = handle_xdg_popup_destroy;
+       wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
+       popup->map.notify = handle_xdg_popup_map;
+       wl_signal_add(&wlr_popup->base->events.map, &popup->map);
+       popup->unmap.notify = handle_xdg_popup_unmap;
+       wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
+       popup->new_popup.notify = popup_handle_new_xdg_popup;
+       wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
+
+       /* TODO: popup_unconstrain() */
+}
index 3b70f56cc2fa3b46b7601bba69be3e0b7b2bf2c7..73923291f72c94d704e37f5b311650ac2417894f 100644 (file)
--- a/src/xdg.c
+++ b/src/xdg.c
@@ -52,78 +52,6 @@ xdg_toplevel_decoration(struct wl_listener *listener, void *data)
        xdg_deco_request_mode(&xdg_deco->request_mode, wlr_decoration);
 }
 
-static void
-handle_xdg_popup_commit(struct wl_listener *listener, void *data)
-{
-       struct xdg_popup *popup = wl_container_of(listener, popup, map);
-       /* TODO */
-}
-
-static void
-handle_xdg_popup_map(struct wl_listener *listener, void *data)
-{
-       struct xdg_popup *popup = wl_container_of(listener, popup, map);
-       /* damagage whole output here as popup might go outside view */
-       damage_all_outputs(popup->view->server);
-}
-
-static void
-handle_xdg_popup_unmap(struct wl_listener *listener, void *data)
-{
-       struct xdg_popup *popup = wl_container_of(listener, popup, unmap);
-       damage_all_outputs(popup->view->server);
-}
-
-static void
-handle_xdg_popup_destroy(struct wl_listener *listener, void *data)
-{
-       struct xdg_popup *popup = wl_container_of(listener, popup, destroy);
-       wl_list_remove(&popup->destroy.link);
-       wl_list_remove(&popup->commit.link);
-       wl_list_remove(&popup->map.link);
-       wl_list_remove(&popup->unmap.link);
-       wl_list_remove(&popup->new_popup.link);
-       free(popup);
-}
-
-static void xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup);
-
-static void
-popup_handle_new_xdg_popup(struct wl_listener *listener, void *data)
-{
-       struct xdg_popup *popup = wl_container_of(listener, popup, new_popup);
-       struct wlr_xdg_popup *wlr_popup = data;
-       xdg_popup_create(popup->view, wlr_popup);
-}
-
-/*
- * We need to pass view to this function for damage tracking.
- * TODO: Could we just damage surface or whole output?
- *       That would allow us to only have one 'handle_new_*'
- */
-static void
-xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
-{
-       struct xdg_popup *popup = calloc(1, sizeof(struct xdg_popup));
-       if (!popup) {
-               return;
-       }
-
-       popup->wlr_popup = wlr_popup;
-       popup->view = view;
-
-       popup->destroy.notify = handle_xdg_popup_destroy;
-       wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
-       popup->commit.notify = handle_xdg_popup_commit;
-       wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
-       popup->map.notify = handle_xdg_popup_map;
-       wl_signal_add(&wlr_popup->base->events.map, &popup->map);
-       popup->unmap.notify = handle_xdg_popup_unmap;
-       wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
-       popup->new_popup.notify = popup_handle_new_xdg_popup;
-       wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
-}
-
 /* This is merely needed to track damage */
 static void
 handle_new_xdg_popup(struct wl_listener *listener, void *data)
@@ -133,6 +61,14 @@ handle_new_xdg_popup(struct wl_listener *listener, void *data)
        xdg_popup_create(view, wlr_popup);
 }
 
+static void
+new_subsurface_notify(struct wl_listener *listener, void *data)
+{
+       struct view *view = wl_container_of(listener, view, new_subsurface);
+       struct wlr_subsurface *wlr_subsurface = data;
+       subsurface_create(view, wlr_subsurface);
+}
+
 static bool
 has_ssd(struct view *view)
 {
@@ -348,9 +284,12 @@ xdg_toplevel_view_map(struct view *view)
        }
        view->been_mapped = true;
 
-       wl_signal_add(&view->xdg_surface->surface->events.commit,
-                     &view->commit);
        view->commit.notify = handle_commit;
+       wl_signal_add(&view->xdg_surface->surface->events.commit,
+               &view->commit);
+       view->new_subsurface.notify = new_subsurface_notify;
+       wl_signal_add(&view->surface->events.new_subsurface,
+               &view->new_subsurface);
 
        desktop_focus_view(&view->server->seat, view);
        damage_all_outputs(view->server);
@@ -362,6 +301,7 @@ xdg_toplevel_view_unmap(struct view *view)
        view->mapped = false;
        damage_all_outputs(view->server);
        wl_list_remove(&view->commit.link);
+       wl_list_remove(&view->new_subsurface.link);
        desktop_focus_topmost_mapped_view(view->server);
 }