From 9ff28360f6c9f039fd5b04f993e8a656b282879e Mon Sep 17 00:00:00 2001 From: Leonardo Hernandez Hernandez Date: Fri, 29 Oct 2021 18:38:24 -0500 Subject: [PATCH 1/6] use wlr_scene_xdg_popup_create() --- dwl.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 58a1bd95e..09ca500e6 100644 --- a/dwl.c +++ b/dwl.c @@ -253,6 +253,7 @@ static void motionabsolute(struct wl_listener *listener, void *data); static void motionnotify(uint32_t time); static void motionrelative(struct wl_listener *listener, void *data); static void moveresize(const Arg *arg); +static Client *popupgetclient(struct wlr_xdg_popup *popup); static void outputmgrapply(struct wl_listener *listener, void *data); static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); static void outputmgrtest(struct wl_listener *listener, void *data); @@ -876,7 +877,14 @@ createnotify(struct wl_listener *listener, void *data) struct wlr_xdg_surface *xdg_surface = data; Client *c; - if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) + if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { + if (!(c = popupgetclient(xdg_surface->popup))) + return; + + wlr_scene_xdg_popup_create(c->scene_surface, xdg_surface->popup); + + return; + } else if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE) return; /* Allocate a Client for this surface */ @@ -1445,6 +1453,27 @@ moveresize(const Arg *arg) } } +Client * +popupgetclient(struct wlr_xdg_popup *popup) +{ + struct wlr_xdg_surface *surface = popup->base; + + while (true) { + switch (surface->role) { + case WLR_XDG_SURFACE_ROLE_POPUP: + if (!wlr_surface_is_xdg_surface(surface->popup->parent)) { + return NULL; + } + surface = wlr_xdg_surface_from_wlr_surface(surface->popup->parent); + break; + case WLR_XDG_SURFACE_ROLE_TOPLEVEL: + return surface->data; + case WLR_XDG_SURFACE_ROLE_NONE: + return NULL; + } + } +} + void outputmgrapply(struct wl_listener *listener, void *data) { From f4c656073ac287bea6e41527e825c97a9d5a361e Mon Sep 17 00:00:00 2001 From: Leonardo Hernandez Hernandez Date: Sat, 30 Oct 2021 12:07:06 -0500 Subject: [PATCH 2/6] fix popups appearing in wrong position --- dwl.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/dwl.c b/dwl.c index 09ca500e6..5298298d2 100644 --- a/dwl.c +++ b/dwl.c @@ -253,7 +253,6 @@ static void motionabsolute(struct wl_listener *listener, void *data); static void motionnotify(uint32_t time); static void motionrelative(struct wl_listener *listener, void *data); static void moveresize(const Arg *arg); -static Client *popupgetclient(struct wlr_xdg_popup *popup); static void outputmgrapply(struct wl_listener *listener, void *data); static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); static void outputmgrtest(struct wl_listener *listener, void *data); @@ -878,11 +877,8 @@ createnotify(struct wl_listener *listener, void *data) Client *c; if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { - if (!(c = popupgetclient(xdg_surface->popup))) - return; - - wlr_scene_xdg_popup_create(c->scene_surface, xdg_surface->popup); - + xdg_surface->surface->data = wlr_scene_xdg_popup_create( + xdg_surface->popup->parent->data, xdg_surface->popup); return; } else if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE) return; @@ -1308,7 +1304,8 @@ mapnotify(struct wl_listener *listener, void *data) /* Create scene tree for this client and its border */ c->scene = &wlr_scene_tree_create(layers[LyrTile])->node; - c->scene_surface = wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); + c->scene_surface = client_surface(c)->data = + wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); c->scene_surface->data = c; for (i = 0; i < 4; i++) { c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, bordercolor); @@ -1453,27 +1450,6 @@ moveresize(const Arg *arg) } } -Client * -popupgetclient(struct wlr_xdg_popup *popup) -{ - struct wlr_xdg_surface *surface = popup->base; - - while (true) { - switch (surface->role) { - case WLR_XDG_SURFACE_ROLE_POPUP: - if (!wlr_surface_is_xdg_surface(surface->popup->parent)) { - return NULL; - } - surface = wlr_xdg_surface_from_wlr_surface(surface->popup->parent); - break; - case WLR_XDG_SURFACE_ROLE_TOPLEVEL: - return surface->data; - case WLR_XDG_SURFACE_ROLE_NONE: - return NULL; - } - } -} - void outputmgrapply(struct wl_listener *listener, void *data) { From a9ff16412e196bde3e7d649a72fb716596c27c96 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 16 Dec 2021 11:50:11 -0600 Subject: [PATCH 3/6] explicitly create renderer and allocator autocreate was removed --- dwl.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/dwl.c b/dwl.c index 58a1bd95e..159d22e1d 100644 --- a/dwl.c +++ b/dwl.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -304,6 +305,7 @@ static struct wlr_backend *backend; static struct wlr_scene *scene; static struct wlr_scene_node *layers[NUM_LAYERS]; static struct wlr_renderer *drw; +static struct wlr_allocator *alloc; static struct wlr_compositor *compositor; static struct wlr_xdg_shell *xdg_shell; @@ -824,6 +826,8 @@ createmon(struct wl_listener *listener, void *data) Monitor *m = wlr_output->data = calloc(1, sizeof(*m)); m->wlr_output = wlr_output; + wlr_output_init_render(wlr_output, alloc, drw); + /* Initialize monitor state using configured rules */ for (size_t i = 0; i < LENGTH(m->layers); i++) wl_list_init(&m->layers[i]); @@ -1844,12 +1848,15 @@ setup(void) layers[LyrTop] = &wlr_scene_tree_create(&scene->node)->node; layers[LyrOverlay] = &wlr_scene_tree_create(&scene->node)->node; - /* If we don't provide a renderer, autocreate makes a GLES2 renderer for us. - * The renderer is responsible for defining the various pixel formats it - * supports for shared memory, this configures that for clients. */ - drw = wlr_backend_get_renderer(backend); + /* Create a renderer with the default implementation */ + if (!(drw = wlr_renderer_autocreate(backend))) + BARF("couldn't create renderer"); wlr_renderer_init_wl_display(drw, dpy); + /* Create a default allocator */ + if (!(alloc = wlr_allocator_autocreate(backend, drw))) + BARF("couldn't create allocator"); + /* This creates some hands-off wlroots interfaces. The compositor is * necessary for clients to allocate surfaces and the data device manager * handles the clipboard. Each of these wlroots interfaces has room for you From b7e5fcd48bcb73416e41bc6e2f83ce8e3f7ebdda Mon Sep 17 00:00:00 2001 From: Leonardo Hernandez Hernandez Date: Sun, 23 Jan 2022 21:29:12 -0600 Subject: [PATCH 4/6] replace `wlr_scene_xdg_popup_create` `wlr_scene_xdg_surface_create` --- dwl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index 42954d312..fcf81d98e 100644 --- a/dwl.c +++ b/dwl.c @@ -881,8 +881,8 @@ createnotify(struct wl_listener *listener, void *data) Client *c; if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { - xdg_surface->surface->data = wlr_scene_xdg_popup_create( - xdg_surface->popup->parent->data, xdg_surface->popup); + xdg_surface->surface->data = wlr_scene_xdg_surface_create( + xdg_surface->popup->parent->data, xdg_surface); return; } else if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE) return; From 0ee5512fa85c1942a50e6b028bf7bf3c9e4d4e16 Mon Sep 17 00:00:00 2001 From: Leonardo Hernandez Hernandez Date: Mon, 31 Jan 2022 14:02:59 -0600 Subject: [PATCH 5/6] add support for xwayland popups they were already displaying but in a bad position and crashing, for example, when selecting an option in a menu in chromium or trying to move or resize popups --- dwl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dwl.c b/dwl.c index fcf81d98e..f6b390f7c 100644 --- a/dwl.c +++ b/dwl.c @@ -1084,7 +1084,7 @@ focusclient(Client *c, int lift) return; /* Put the new client atop the focus stack and select its monitor */ - if (c) { + if (c && c->type != X11Unmanaged) { wl_list_remove(&c->flink); wl_list_insert(&fstack, &c->flink); selmon = c->mon; @@ -1108,7 +1108,8 @@ focusclient(Client *c, int lift) )) return; } else { - client_activate_surface(old, 0); + /* If client is unmanaged then we shoudn't deactivate old surface */ + client_activate_surface(old, c && c->type == X11Unmanaged); } } @@ -1317,8 +1318,10 @@ mapnotify(struct wl_listener *listener, void *data) } if (client_is_unmanaged(c)) { + client_get_geometry(c, &c->geom); /* Floating, no border */ wlr_scene_node_reparent(c->scene, layers[LyrFloat]); + wlr_scene_node_set_position(c->scene, c->geom.x, c->geom.y); c->bw = 0; /* Insert this independent into independents lists. */ @@ -1431,7 +1434,7 @@ moveresize(const Arg *arg) if (cursor_mode != CurNormal) return; xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); - if (!grabc) + if (!grabc || grabc->type == X11Unmanaged) return; /* Float the window and tell motionnotify to grab it */ From d9200d5950047e4572865b2c153aadbe319ded4f Mon Sep 17 00:00:00 2001 From: Leonardo Hernandez Hernandez Date: Tue, 1 Feb 2022 01:16:56 -0600 Subject: [PATCH 6/6] add support for layer_shell popups --- dwl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dwl.c b/dwl.c index f6b390f7c..cafafe18b 100644 --- a/dwl.c +++ b/dwl.c @@ -876,7 +876,10 @@ void createnotify(struct wl_listener *listener, void *data) { /* This event is raised when wlr_xdg_shell receives a new xdg surface from a - * client, either a toplevel (application window) or popup. */ + * client, either a toplevel (application window) or popup. + * or when wlr_layer_shell receives a new popup from a layer, so if you want + * to do something tricky you should check if the parent is wlr_xdg_shell or + * wlr_layer_shell */ struct wlr_xdg_surface *xdg_surface = data; Client *c; @@ -929,8 +932,8 @@ createlayersurface(struct wl_listener *listener, void *data) wlr_layer_surface->data = layersurface; m = wlr_layer_surface->output->data; - layersurface->scene = wlr_scene_subsurface_tree_create( - layers[wlr_layer_surface->pending.layer], + layersurface->scene = wlr_layer_surface->surface->data = + wlr_scene_subsurface_tree_create(layers[wlr_layer_surface->pending.layer], wlr_layer_surface->surface); layersurface->scene->data = layersurface;