]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Add xwayland-unmanaged.c
authorJohan Malm <jgm323@gmail.com>
Fri, 4 Sep 2020 19:25:20 +0000 (20:25 +0100)
committerJohan Malm <jgm323@gmail.com>
Fri, 4 Sep 2020 19:25:20 +0000 (20:25 +0100)
Handle xwayland override_direct surfaces separately from the view
struct - in order to simplify code, particularly in view.c

include/labwc.h
src/meson.build
src/output.c
src/seat.c [new file with mode: 0644]
src/server.c
src/view.c
src/xwayland-unmanaged.c [new file with mode: 0644]
src/xwl.c

index 204c952dcc7c4ac327159e4b025085dfc0811881..8c2b5fc48aca4bf1f748027d1fd1af6d63a1288d 100644 (file)
@@ -52,6 +52,7 @@ struct server {
        struct wlr_xwayland *xwayland;
        struct wl_listener new_xwayland_surface;
        struct wl_list views;
+       struct wl_list unmanaged_surfaces;
 
        struct wlr_cursor *cursor;
        struct wlr_xcursor_manager *cursor_mgr;
@@ -78,10 +79,12 @@ struct server {
        struct wl_list outputs;
        struct wl_listener new_output;
 
-       /* For use in cycle (alt-tab) mode */
+       /* Set when in cycle (alt-tab) mode */
        struct view *cycle_view;
 };
 
+extern struct server server;
+
 struct output {
        struct wl_list link;
        struct server *server;
@@ -137,6 +140,18 @@ struct view {
        struct wl_listener request_configure;
 };
 
+struct xwayland_unmanaged {
+       struct wlr_xwayland_surface *xwayland_surface;
+       struct wl_list link;
+       int lx, ly;
+
+       struct wl_listener request_configure;
+       struct wl_listener commit;
+       struct wl_listener map;
+       struct wl_listener unmap;
+       struct wl_listener destroy;
+};
+
 struct keyboard {
        struct wl_list link;
        struct server *server;
@@ -150,6 +165,7 @@ void xdg_toplevel_decoration(struct wl_listener *listener, void *data);
 void xdg_surface_new(struct wl_listener *listener, void *data);
 
 void xwl_surface_new(struct wl_listener *listener, void *data);
+void xwayland_unmanaged_create(struct wlr_xwayland_surface *xsurface);
 
 void view_init_position(struct view *view);
 /**
@@ -169,6 +185,8 @@ struct view *view_at(struct server *server, double lx, double ly,
                     struct wlr_surface **surface, double *sx, double *sy,
                     int *view_area);
 
+void seat_focus_surface(struct wlr_surface *surface);
+
 void interactive_begin(struct view *view, enum cursor_mode mode,
                       uint32_t edges);
 
index 3b8cabe9578a3cc2ad1902e500075f3a13ed4302..26cd31eccac74a19c616b5a56af420acf600d369 100644 (file)
@@ -7,9 +7,11 @@ labwc_sources = files(
   'keyboard.c',
   'main.c',
   'output.c',
+  'seat.c',
   'server.c',
   'view.c',
   'xdg.c',
+  'xwayland-unmanaged.c',
   'xwl.c',
 )
 
index 756b2cdb89d43af72d0511a2aee933e9de01180b..9b150abcb7d3a23aec6aa9ca7919363ef723c09d 100644 (file)
@@ -88,7 +88,7 @@ static void render_decorations(struct wlr_output *output, struct view *view)
 struct render_data {
        struct wlr_output *output;
        struct wlr_renderer *renderer;
-       struct view *view;
+       int lx, ly;
        struct timespec *when;
 };
 
@@ -98,7 +98,6 @@ static void render_surface(struct wlr_surface *surface, int sx, int sy,
        /* This function is called for every surface that needs to be rendered.
         */
        struct render_data *rdata = data;
-       struct view *view = rdata->view;
        struct wlr_output *output = rdata->output;
 
        /* We first obtain a wlr_texture, which is a GPU resource. wlroots
@@ -117,10 +116,9 @@ static void render_surface(struct wlr_surface *surface, int sx, int sy,
         * display might have layout coordinates of 2000,100. We need to
         * translate that to output-local coordinates, or (2000 - 1920). */
        double ox = 0, oy = 0;
-       wlr_output_layout_output_coords(view->server->output_layout, output,
-                                       &ox, &oy);
-       ox += view->x + sx;
-       oy += view->y + sy;
+       wlr_output_layout_output_coords(server.output_layout, output, &ox, &oy);
+       ox += rdata->lx + sx;
+       oy += rdata->ly + sy;
 
        /* TODO: Support HiDPI */
        struct wlr_box box = {
@@ -188,22 +186,21 @@ void output_frame(struct wl_listener *listener, void *data)
         * backwards. */
        struct view *view;
        wl_list_for_each_reverse (view, &output->server->views, link) {
-               if (!view->mapped) {
-                       /* An unmapped view should not be rendered. */
+               if (!view->mapped)
                        continue;
-               }
+
                struct render_data rdata = {
                        .output = output->wlr_output,
-                       .view = view,
+                       .lx = view->x,
+                       .ly = view->y,
                        .renderer = renderer,
                        .when = &now,
                };
 
                render_decorations(output->wlr_output, view);
 
-               /* This calls our render_surface function for each surface among
-                * the xdg_surface's toplevel and popups. */
                if (view->type == LAB_XDG_SHELL_VIEW) {
+                       /* render each xdg toplevel and popup surface */
                        wlr_xdg_surface_for_each_surface(
                                view->xdg_surface, render_surface, &rdata);
                } else if (view->type == LAB_XWAYLAND_VIEW) {
@@ -215,6 +212,21 @@ void output_frame(struct wl_listener *listener, void *data)
        /* If in cycle (alt-tab) mode, highlight selected view */
        render_cycle_box(output);
 
+       /* Render xwayland override_redirect surfaces */
+       struct xwayland_unmanaged *unmanaged;
+       wl_list_for_each_reverse (unmanaged, &server.unmanaged_surfaces, link) {
+               struct render_data rdata = {
+                       .output = output->wlr_output,
+                       .lx = unmanaged->lx,
+                       .ly = unmanaged->ly,
+                       .renderer = renderer,
+                       .when = &now,
+               };
+
+               struct wlr_surface *s = unmanaged->xwayland_surface->surface;
+               render_surface(s, 0, 0, &rdata);
+       }
+
        /* Hardware cursors are rendered by the GPU on a separate plane, and can
         * be moved around without re-rendering what's beneath them - which is
         * more efficient. However, not all hardware supports hardware cursors.
diff --git a/src/seat.c b/src/seat.c
new file mode 100644 (file)
index 0000000..62e4aca
--- /dev/null
@@ -0,0 +1,11 @@
+#include "labwc.h"
+
+void seat_focus_surface(struct wlr_surface *surface)
+{
+       if (!surface) {
+               wlr_seat_keyboard_notify_clear_focus(server.seat);
+               return;
+       }
+       /* TODO: add keyboard stuff */
+       wlr_seat_keyboard_notify_enter(server.seat, surface, NULL, 0, NULL);
+}
index 6db7e1c738393121e7cb7a822105149798b29d73..b144e1c4a004339d884203f86bd529b4b46e1e85 100644 (file)
@@ -105,6 +105,7 @@ void server_init(struct server *server)
        wlr_renderer_init_wl_display(server->renderer, server->wl_display);
 
        wl_list_init(&server->views);
+       wl_list_init(&server->unmanaged_surfaces);
        wl_list_init(&server->outputs);
 
        /*
index 8f8e6c7a4dbe02ae8d90fb7628509a6eb14d60aa..d4034f47b872f6cb87532689c1dd80e3c8f0508c 100644 (file)
@@ -150,6 +150,8 @@ void view_focus(struct view *view)
        /* Note: this function only deals with keyboard focus. */
        if (!view)
                return;
+
+       /* TODO: messy - sort out */
        if (!view->mapped) {
                view->impl->map(view);
                return;
diff --git a/src/xwayland-unmanaged.c b/src/xwayland-unmanaged.c
new file mode 100644 (file)
index 0000000..2d8d0e4
--- /dev/null
@@ -0,0 +1,86 @@
+#include "labwc.h"
+
+static void unmanaged_handle_request_configure(struct wl_listener *listener,
+                                              void *data)
+{
+       struct xwayland_unmanaged *unmanaged =
+               wl_container_of(listener, unmanaged, request_configure);
+       struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
+       struct wlr_xwayland_surface_configure_event *ev = data;
+       wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, ev->width,
+                                      ev->height);
+}
+
+static void unmanaged_handle_commit(struct wl_listener *listener, void *data)
+{
+       struct xwayland_unmanaged *unmanaged =
+               wl_container_of(listener, unmanaged, commit);
+       struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
+       unmanaged->lx = xsurface->x;
+       unmanaged->ly = xsurface->y;
+}
+
+static void unmanaged_handle_map(struct wl_listener *listener, void *data)
+{
+       struct xwayland_unmanaged *unmanaged =
+               wl_container_of(listener, unmanaged, map);
+       struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
+
+       wl_list_insert(server.unmanaged_surfaces.prev, &unmanaged->link);
+
+       wl_signal_add(&xsurface->surface->events.commit, &unmanaged->commit);
+       unmanaged->commit.notify = unmanaged_handle_commit;
+
+       unmanaged->lx = xsurface->x;
+       unmanaged->ly = xsurface->y;
+
+       if (wlr_xwayland_or_surface_wants_focus(xsurface))
+               seat_focus_surface(xsurface->surface);
+}
+
+static void unmanaged_handle_unmap(struct wl_listener *listener, void *data)
+{
+       struct xwayland_unmanaged *unmanaged =
+               wl_container_of(listener, unmanaged, unmap);
+       struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
+       wl_list_remove(&unmanaged->link);
+       wl_list_remove(&unmanaged->commit.link);
+
+       if (server.seat->keyboard_state.focused_surface == xsurface->surface) {
+               struct xwayland_unmanaged *u;
+               wl_list_for_each (u, &server.unmanaged_surfaces, link) {
+                       struct wlr_xwayland_surface *prev = u->xwayland_surface;
+                       if (!wlr_xwayland_or_surface_wants_focus(prev))
+                               continue;
+                       seat_focus_surface(prev->surface);
+                       return;
+               }
+       }
+}
+
+static void unmanaged_handle_destroy(struct wl_listener *listener, void *data)
+{
+       struct xwayland_unmanaged *unmanaged =
+               wl_container_of(listener, unmanaged, destroy);
+       wl_list_remove(&unmanaged->map.link);
+       wl_list_remove(&unmanaged->unmap.link);
+       wl_list_remove(&unmanaged->destroy.link);
+       free(unmanaged);
+}
+
+void xwayland_unmanaged_create(struct wlr_xwayland_surface *xsurface)
+{
+       struct xwayland_unmanaged *unmanaged;
+       unmanaged = calloc(1, sizeof(struct xwayland_unmanaged));
+       unmanaged->xwayland_surface = xsurface;
+       wl_signal_add(&xsurface->events.request_configure,
+                     &unmanaged->request_configure);
+       unmanaged->request_configure.notify =
+               unmanaged_handle_request_configure;
+       wl_signal_add(&xsurface->events.map, &unmanaged->map);
+       unmanaged->map.notify = unmanaged_handle_map;
+       wl_signal_add(&xsurface->events.unmap, &unmanaged->unmap);
+       unmanaged->unmap.notify = unmanaged_handle_unmap;
+       wl_signal_add(&xsurface->events.destroy, &unmanaged->destroy);
+       unmanaged->destroy.notify = unmanaged_handle_destroy;
+}
index 3b9dae5ad5b94109ba18fabf1e6ac468cdd612d8..bd426047c26806b3f8aa0f01c4e168639e77dc23 100644 (file)
--- a/src/xwl.c
+++ b/src/xwl.c
@@ -79,10 +79,7 @@ static void map(struct view *view)
        }
        view->been_mapped = true;
 
-       /*
-        * Add commit listener here, because xwayland map/unmap can change
-        * the wlr_surface
-        */
+       /* Add commit here, as xwayland map/unmap can change the wlr_surface */
        wl_signal_add(&view->xwayland_surface->surface->events.commit,
                      &view->commit);
        view->commit.notify = handle_commit;
@@ -108,22 +105,31 @@ void xwl_surface_new(struct wl_listener *listener, void *data)
 {
        struct server *server =
                wl_container_of(listener, server, new_xwayland_surface);
-       struct wlr_xwayland_surface *xwayland_surface = data;
-       wlr_xwayland_surface_ping(xwayland_surface);
+       struct wlr_xwayland_surface *xsurface = data;
+       wlr_xwayland_surface_ping(xsurface);
+
+       /*
+        * We do not create 'views' for xwayland override_redirect surfaces,
+        * but add them to server.unmanaged_surfaces so that we can render them
+        */
+       if (xsurface->override_redirect) {
+               xwayland_unmanaged_create(xsurface);
+               return;
+       }
 
        struct view *view = calloc(1, sizeof(struct view));
        view->server = server;
        view->type = LAB_XWAYLAND_VIEW;
        view->impl = &xwl_view_impl;
-       view->xwayland_surface = xwayland_surface;
+       view->xwayland_surface = xsurface;
 
        view->map.notify = handle_map;
-       wl_signal_add(&xwayland_surface->events.map, &view->map);
+       wl_signal_add(&xsurface->events.map, &view->map);
        view->unmap.notify = handle_unmap;
-       wl_signal_add(&xwayland_surface->events.unmap, &view->unmap);
+       wl_signal_add(&xsurface->events.unmap, &view->unmap);
        view->destroy.notify = handle_destroy;
-       wl_signal_add(&xwayland_surface->events.destroy, &view->destroy);
+       wl_signal_add(&xsurface->events.destroy, &view->destroy);
        view->request_configure.notify = handle_request_configure;
-       wl_signal_add(&xwayland_surface->events.request_configure,
+       wl_signal_add(&xsurface->events.request_configure,
                      &view->request_configure);
 }