From 25dfdcc4337a8b6ca40a5848ef1d49160105f568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 15 Nov 2022 23:04:02 -0600 Subject: [PATCH 01/64] specify layer shell version --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 6d44c52..bfac6b5 100644 --- a/dwl.c +++ b/dwl.c @@ -2038,7 +2038,7 @@ setup(void) idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); wl_signal_add(&idle_inhibit_mgr->events.new_inhibitor, &idle_inhibitor_create); - layer_shell = wlr_layer_shell_v1_create(dpy); + layer_shell = wlr_layer_shell_v1_create(dpy, 3); wl_signal_add(&layer_shell->events.new_surface, &new_layer_shell_surface); xdg_shell = wlr_xdg_shell_create(dpy, 4); From 359e7edc52c38a0eb1bbc33aa238561efaf28d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 15 Nov 2022 23:04:39 -0600 Subject: [PATCH 02/64] update for wlroots!3814 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3814 --- dwl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index bfac6b5..5d484dc 100644 --- a/dwl.c +++ b/dwl.c @@ -305,6 +305,7 @@ static struct wlr_scene_tree *layers[NUM_LAYERS]; static struct wlr_renderer *drw; static struct wlr_allocator *alloc; static struct wlr_compositor *compositor; +static struct wlr_session *session; static struct wlr_xdg_shell *xdg_shell; static struct wlr_xdg_activation_v1 *activation; @@ -582,7 +583,8 @@ buttonpress(struct wl_listener *listener, void *data) void chvt(const Arg *arg) { - wlr_session_change_vt(wlr_backend_get_session(backend), arg->ui); + if (session) + wlr_session_change_vt(session, arg->ui); } void @@ -1969,7 +1971,7 @@ setup(void) * backend uses the renderer, for example, to fall back to software cursors * if the backend does not support hardware cursors (some older GPUs * don't). */ - if (!(backend = wlr_backend_autocreate(dpy))) + if (!(backend = wlr_backend_autocreate(dpy, &session))) die("couldn't create backend"); /* Initialize the scene graph used to lay out windows */ From 5eb352927575bd45c75d6d7f5e3f7a6e3499a85f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 15 Nov 2022 23:07:21 -0600 Subject: [PATCH 03/64] use the new scene helper for drag icons --- dwl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dwl.c b/dwl.c index 5d484dc..d8cee36 100644 --- a/dwl.c +++ b/dwl.c @@ -990,8 +990,6 @@ cursorframe(struct wl_listener *listener, void *data) void destroydragicon(struct wl_listener *listener, void *data) { - struct wlr_drag_icon *icon = data; - wlr_scene_node_destroy(icon->data); /* Focus enter isn't sent during drag, so refocus the focused node. */ focusclient(selclient(), 1); motionnotify(0); @@ -2148,7 +2146,7 @@ startdrag(struct wl_listener *listener, void *data) if (!drag->icon) return; - drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrDragIcon], drag->icon->surface); + drag->icon->data = wlr_scene_drag_icon_create(layers[LyrDragIcon], drag->icon); motionnotify(0); wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); } From dae00caaddee6d14cb566ee750c976543788d5fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 15 Nov 2022 23:07:45 -0600 Subject: [PATCH 04/64] update for wlroots!3861 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3861 --- dwl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index d8cee36..386763a 100644 --- a/dwl.c +++ b/dwl.c @@ -1439,8 +1439,8 @@ motionnotify(uint32_t time) /* Update drag icon's position if any */ if (seat->drag && (icon = seat->drag->icon)) - wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->sx, - cursor->y + icon->surface->sy); + wlr_scene_node_set_position(icon->data, cursor->x + icon->surface->current.dx, + cursor->y + icon->surface->current.dy); /* If we are currently grabbing the mouse, handle and return */ if (cursor_mode == CurMove) { /* Move the grabbed client to the new position. */ From 21ef004886be1092becba61abb71e9fd86b85c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 15 Nov 2022 23:52:21 -0600 Subject: [PATCH 05/64] listen to the output request_state event; References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/2693 --- dwl.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dwl.c b/dwl.c index 386763a..d630d06 100644 --- a/dwl.c +++ b/dwl.c @@ -173,6 +173,7 @@ struct Monitor { struct wlr_scene_output *scene_output; struct wl_listener frame; struct wl_listener destroy; + struct wl_listener request_state; struct wlr_box m; /* monitor area, layout-relative */ struct wlr_box w; /* window area, layout-relative */ struct wl_list layers[4]; /* LayerSurface::link */ @@ -260,6 +261,7 @@ static void quit(const Arg *arg); static void quitsignal(int signo); static void rendermon(struct wl_listener *listener, void *data); static void requeststartdrag(struct wl_listener *listener, void *data); +static void requestmonstate(struct wl_listener *listener, void *data); static void resize(Client *c, struct wlr_box geo, int interact); static void run(char *startup_cmd); static Client *selclient(void); @@ -865,6 +867,7 @@ createmon(struct wl_listener *listener, void *data) /* Set up event listeners */ LISTEN(&wlr_output->events.frame, &m->frame, rendermon); LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon); + LISTEN(&wlr_output->events.request_state, &m->request_state, requestmonstate); wlr_output_enable(wlr_output, 1); if (!wlr_output_commit(wlr_output)) @@ -1708,6 +1711,13 @@ requeststartdrag(struct wl_listener *listener, void *data) wlr_data_source_destroy(event->drag->source); } +void +requestmonstate(struct wl_listener *listener, void *data) +{ + struct wlr_output_event_request_state *event = data; + wlr_output_commit_state(event->output, event->state); +} + void resize(Client *c, struct wlr_box geo, int interact) { From 27ab9cf1b1230e6e839a6a10eb85c670c59d6f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 2 Dec 2022 23:17:05 -0600 Subject: [PATCH 06/64] call updatemons() in requestmonstate() This way we make sure that the Monitor's boxes are updated correctly --- dwl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwl.c b/dwl.c index 255a334..c9d79d9 100644 --- a/dwl.c +++ b/dwl.c @@ -1738,6 +1738,7 @@ requestmonstate(struct wl_listener *listener, void *data) { struct wlr_output_event_request_state *event = data; wlr_output_commit_state(event->output, event->state); + updatemons(NULL, NULL); } void From 02c257e0b163430401c87fc62937a454e883359b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 5 Dec 2022 20:21:38 -0600 Subject: [PATCH 07/64] update for wlroots!3627 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3627 --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index c9d79d9..0408951 100644 --- a/dwl.c +++ b/dwl.c @@ -1580,7 +1580,7 @@ outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test) /* Don't move monitors if position wouldn't change, this to avoid * wlroots marking the output as manually configured */ if (m->m.x != config_head->state.x || m->m.y != config_head->state.y) - wlr_output_layout_move(output_layout, wlr_output, + wlr_output_layout_add(output_layout, wlr_output, config_head->state.x, config_head->state.y); wlr_output_set_transform(wlr_output, config_head->state.transform); wlr_output_set_scale(wlr_output, config_head->state.scale); From 7ae5039b4f35c6f5fd09f2d650c62dc7304ce6fe Mon Sep 17 00:00:00 2001 From: Job79 Date: Wed, 1 Feb 2023 20:09:45 +0100 Subject: [PATCH 08/64] follow upstream xwayland_surface changes wlroots removed the `wlr_surface_is_xwayland_surface` function, and renamed `wlr_xwayland_surface_from_wlr_surface` to `wlr_xwayland_surface_try_from_wlr_surface`. related commit: https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/fbf5982e3838ee28b5345e98832f6956c402b225 --- client.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client.h b/client.h index 5a45edc..558dd03 100644 --- a/client.h +++ b/client.h @@ -69,8 +69,7 @@ toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl) root_surface = wlr_surface_get_root_surface(s); #ifdef XWAYLAND - if (wlr_surface_is_xwayland_surface(root_surface) - && (xsurface = wlr_xwayland_surface_from_wlr_surface(root_surface))) { + if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(root_surface))) { c = xsurface->data; type = c->type; goto end; @@ -121,8 +120,7 @@ client_activate_surface(struct wlr_surface *s, int activated) struct wlr_xdg_surface *surface; #ifdef XWAYLAND struct wlr_xwayland_surface *xsurface; - if (wlr_surface_is_xwayland_surface(s) - && (xsurface = wlr_xwayland_surface_from_wlr_surface(s))) { + if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) { wlr_xwayland_surface_activate(xsurface, activated); return; } From e7f736ccc9435138d9921ba1f3ba5ebed142523b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 2 Feb 2023 10:30:24 -0600 Subject: [PATCH 09/64] chase wlroots!3391 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3991 --- client.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/client.h b/client.h index 558dd03..5fe31b1 100644 --- a/client.h +++ b/client.h @@ -76,24 +76,22 @@ toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl) } #endif - if (wlr_surface_is_layer_surface(root_surface) - && (layer_surface = wlr_layer_surface_v1_from_wlr_surface(root_surface))) { + if ((layer_surface = wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) { l = layer_surface->data; type = LayerShell; goto end; } - if (wlr_surface_is_xdg_surface(root_surface) - && (xdg_surface = wlr_xdg_surface_from_wlr_surface(root_surface))) { + if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(root_surface))) { while (1) { switch (xdg_surface->role) { case WLR_XDG_SURFACE_ROLE_POPUP: if (!xdg_surface->popup->parent) return -1; - else if (!wlr_surface_is_xdg_surface(xdg_surface->popup->parent)) + else if (!wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent)) return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl); - xdg_surface = wlr_xdg_surface_from_wlr_surface(xdg_surface->popup->parent); + xdg_surface = wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent); break; case WLR_XDG_SURFACE_ROLE_TOPLEVEL: c = xdg_surface->data; @@ -125,8 +123,7 @@ client_activate_surface(struct wlr_surface *s, int activated) return; } #endif - if (wlr_surface_is_xdg_surface(s) - && (surface = wlr_xdg_surface_from_wlr_surface(s)) + if ((surface = wlr_xdg_surface_try_from_wlr_surface(s)) && surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) wlr_xdg_toplevel_set_activated(surface->toplevel, activated); } From fbe89a929f8465a288630ebe27bd656cd9ce8282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sun, 5 Feb 2023 10:03:09 -0600 Subject: [PATCH 10/64] chase wlroots!4000 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4000 --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 360708f..42086af 100644 --- a/dwl.c +++ b/dwl.c @@ -2582,7 +2582,7 @@ xytonode(double x, double y, struct wlr_surface **psurface, for (layer = focus_order; layer < END(focus_order); layer++) { if ((node = wlr_scene_node_at(&layers[*layer]->node, x, y, nx, ny))) { if (node->type == WLR_SCENE_NODE_BUFFER) - surface = wlr_scene_surface_from_buffer( + surface = wlr_scene_surface_try_from_buffer( wlr_scene_buffer_from_node(node))->surface; /* Walk the tree to find a node that knows the client */ for (pnode = node; pnode && !c; pnode = &pnode->parent->node) From 04fdf1a29545641a23e5c586d6b3dfa3a0103d97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 8 Feb 2023 22:25:41 -0600 Subject: [PATCH 11/64] add support for wp-fractional-scale-v1 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3511 --- dwl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dwl.c b/dwl.c index 42086af..0eb11c2 100644 --- a/dwl.c +++ b/dwl.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -2137,6 +2138,7 @@ setup(void) wlr_primary_selection_v1_device_manager_create(dpy); wlr_viewporter_create(dpy); wlr_single_pixel_buffer_manager_v1_create(dpy); + wlr_fractional_scale_manager_v1_create(dpy, 1); wlr_subcompositor_create(dpy); /* Initializes the interface used to implement urgency hints */ From d1b36925c9e08aa26f72c4199c4046b0800c2266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 20 Feb 2023 21:24:18 -0600 Subject: [PATCH 12/64] add support for linux-dmabuf-unstable-v1 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3726 References: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml --- dwl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dwl.c b/dwl.c index 0e02530..d028b95 100644 --- a/dwl.c +++ b/dwl.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -2302,6 +2303,9 @@ setup(void) wl_signal_add(&output_mgr->events.test, &output_mgr_test); wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend)); + wlr_scene_set_linux_dmabuf_v1(scene, + wlr_linux_dmabuf_v1_create_with_renderer(dpy, 4, drw)); + #ifdef XWAYLAND /* From eaf6dd2cd2f8c25a8cbce0e57221f73168a2bdc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 7 Mar 2023 22:04:32 -0600 Subject: [PATCH 13/64] do not call dmabuf_create twice it is called automatically by `wlr_renderer_init_wl_display()` but since we need a pointer to wlr_linux_dmabuf_v1 to integrate it with scene API we need to recreate that function. Bug: https://github.com/emersion/xdg-desktop-portal-wlr/issues/216 Fixes: https://github.com/djpohly/dwl/issues/398 --- dwl.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/dwl.c b/dwl.c index d028b95..935babe 100644 --- a/dwl.c +++ b/dwl.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -2174,7 +2175,19 @@ setup(void) /* Create a renderer with the default implementation */ if (!(drw = wlr_renderer_autocreate(backend))) die("couldn't create renderer"); - wlr_renderer_init_wl_display(drw, dpy); + + /* Create shm, drm and linux_dmabuf interfaces by ourselves. + * The simplest way is call: + * wlr_renderer_init_wl_display(drw); + * but we need to create manually the linux_dmabuf interface to integrate it + * with wlr_scene. */ + wlr_renderer_init_wl_shm(drw, dpy); + + if (wlr_renderer_get_dmabuf_texture_formats(drw)) { + wlr_drm_create(dpy, drw); + wlr_scene_set_linux_dmabuf_v1(scene, + wlr_linux_dmabuf_v1_create_with_renderer(dpy, 4, drw)); + } /* Create a default allocator */ if (!(alloc = wlr_allocator_autocreate(backend, drw))) @@ -2303,9 +2316,6 @@ setup(void) wl_signal_add(&output_mgr->events.test, &output_mgr_test); wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend)); - wlr_scene_set_linux_dmabuf_v1(scene, - wlr_linux_dmabuf_v1_create_with_renderer(dpy, 4, drw)); - #ifdef XWAYLAND /* From 2d1a40caf27d15f809b301fb2e597a0937e6d298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 14 Apr 2023 12:14:11 -0600 Subject: [PATCH 14/64] pass version to wlr_compositor_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3696 Signed-off-by: Leonardo Hernández Hernández --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index f94059a..e481930 100644 --- a/dwl.c +++ b/dwl.c @@ -2204,7 +2204,7 @@ setup(void) * to dig your fingers in and play with their behavior if you want. Note that * the clients cannot set the selection directly without compositor approval, * see the setsel() function. */ - compositor = wlr_compositor_create(dpy, drw); + compositor = wlr_compositor_create(dpy, 5, drw); wlr_export_dmabuf_manager_v1_create(dpy); wlr_screencopy_manager_v1_create(dpy); wlr_data_control_manager_v1_create(dpy); From 06bc65549f42bcfa2f0b119149eacb7e5adc9073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 2 Jun 2023 21:34:22 -0600 Subject: [PATCH 15/64] chase wlroots map logic unification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leonardo Hernández Hernández --- client.h | 10 ---------- dwl.c | 55 ++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/client.h b/client.h index 5fe31b1..ef56ee6 100644 --- a/client.h +++ b/client.h @@ -225,16 +225,6 @@ client_is_float_type(Client *c) && (min.width == max.width || min.height == max.height)); } -static inline int -client_is_mapped(Client *c) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->mapped; -#endif - return c->surface.xdg->mapped; -} - static inline int client_is_rendered_on_mon(Client *c, Monitor *m) { diff --git a/dwl.c b/dwl.c index fd93ec5..c28ce42 100644 --- a/dwl.c +++ b/dwl.c @@ -122,6 +122,8 @@ typedef struct { struct wlr_box prev; /* layout-relative, includes border */ #ifdef XWAYLAND struct wl_listener activate; + struct wl_listener associate; + struct wl_listener dissociate; struct wl_listener configure; struct wl_listener set_hints; #endif @@ -399,8 +401,10 @@ static struct wl_listener session_lock_mgr_destroy = {.notify = destroysessionmg #ifdef XWAYLAND static void activatex11(struct wl_listener *listener, void *data); +static void associatex11(struct wl_listener *listener, void *data); static void configurex11(struct wl_listener *listener, void *data); static void createnotifyx11(struct wl_listener *listener, void *data); +static void dissociatex11(struct wl_listener *listener, void *data); static Atom getatom(xcb_connection_t *xc, const char *name); static void sethints(struct wl_listener *listener, void *data); static void sigchld(int unused); @@ -762,9 +766,9 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) wlr_scene_node_reparent(&layersurface->popups->node, layers[LyrTop]); if (wlr_layer_surface->current.committed == 0 - && layersurface->mapped == wlr_layer_surface->mapped) + && layersurface->mapped == wlr_layer_surface->surface->mapped) return; - layersurface->mapped = wlr_layer_surface->mapped; + layersurface->mapped = wlr_layer_surface->surface->mapped; arrangelayers(layersurface->mon); } @@ -854,9 +858,9 @@ createlayersurface(struct wl_listener *listener, void *data) &layersurface->surface_commit, commitlayersurfacenotify); LISTEN(&wlr_layer_surface->events.destroy, &layersurface->destroy, destroylayersurfacenotify); - LISTEN(&wlr_layer_surface->events.map, &layersurface->map, + LISTEN(&wlr_layer_surface->surface->events.map, &layersurface->map, maplayersurfacenotify); - LISTEN(&wlr_layer_surface->events.unmap, &layersurface->unmap, + LISTEN(&wlr_layer_surface->surface->events.unmap, &layersurface->unmap, unmaplayersurfacenotify); layersurface->layer_surface = wlr_layer_surface; @@ -1017,8 +1021,8 @@ createnotify(struct wl_listener *listener, void *data) c->surface.xdg = xdg_surface; c->bw = borderpx; - LISTEN(&xdg_surface->events.map, &c->map, mapnotify); - LISTEN(&xdg_surface->events.unmap, &c->unmap, unmapnotify); + LISTEN(&xdg_surface->surface->events.map, &c->map, mapnotify); + LISTEN(&xdg_surface->surface->events.unmap, &c->unmap, unmapnotify); LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify); LISTEN(&xdg_surface->toplevel->events.set_title, &c->set_title, updatetitle); LISTEN(&xdg_surface->toplevel->events.request_fullscreen, &c->fullscreen, @@ -1055,7 +1059,7 @@ createpointer(struct wlr_pointer *pointer) if (libinput_device_config_scroll_get_methods(libinput_device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) libinput_device_config_scroll_set_method (libinput_device, scroll_method); - + if (libinput_device_config_click_get_methods(libinput_device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE) libinput_device_config_click_set_method (libinput_device, click_method); @@ -1160,18 +1164,22 @@ destroynotify(struct wl_listener *listener, void *data) { /* Called when the surface is destroyed and should never be shown again. */ Client *c = wl_container_of(listener, c, destroy); - wl_list_remove(&c->map.link); - wl_list_remove(&c->unmap.link); wl_list_remove(&c->destroy.link); wl_list_remove(&c->set_title.link); wl_list_remove(&c->fullscreen.link); #ifdef XWAYLAND if (c->type != XDGShell) { - wl_list_remove(&c->configure.link); - wl_list_remove(&c->set_hints.link); wl_list_remove(&c->activate.link); - } + wl_list_remove(&c->associate.link); + wl_list_remove(&c->configure.link); + wl_list_remove(&c->dissociate.link); + wl_list_remove(&c->set_hints.link); + } else #endif + { + wl_list_remove(&c->map.link); + wl_list_remove(&c->unmap.link); + } free(c); } @@ -2597,7 +2605,7 @@ updatemons(struct wl_listener *listener, void *data) if (selmon && selmon->wlr_output->enabled) { wl_list_for_each(c, &clients, link) - if (!c->mon && client_is_mapped(c)) + if (!c->mon && client_surface(c)->mapped) setmon(c, selmon, c->tags); focusclient(focustop(selmon), 1); if (selmon->lock_surface) { @@ -2734,6 +2742,15 @@ activatex11(struct wl_listener *listener, void *data) wlr_xwayland_surface_activate(c->surface.xwayland, 1); } +void +associatex11(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, associate); + + LISTEN(&client_surface(c)->events.map, &c->map, mapnotify); + LISTEN(&client_surface(c)->events.unmap, &c->unmap, unmapnotify); +} + void configurex11(struct wl_listener *listener, void *data) { @@ -2761,8 +2778,8 @@ createnotifyx11(struct wl_listener *listener, void *data) c->bw = borderpx; /* Listen to the various events it can emit */ - LISTEN(&xsurface->events.map, &c->map, mapnotify); - LISTEN(&xsurface->events.unmap, &c->unmap, unmapnotify); + LISTEN(&xsurface->events.associate, &c->associate, associatex11); + LISTEN(&xsurface->events.dissociate, &c->dissociate, dissociatex11); LISTEN(&xsurface->events.request_activate, &c->activate, activatex11); LISTEN(&xsurface->events.request_configure, &c->configure, configurex11); LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints); @@ -2771,6 +2788,14 @@ createnotifyx11(struct wl_listener *listener, void *data) LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify); } +void +dissociatex11(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, dissociate); + wl_list_remove(&c->map.link); + wl_list_remove(&c->unmap.link); +} + Atom getatom(xcb_connection_t *xc, const char *name) { From f3d017077a1328e7d327304772cf186f2e7ae0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 2 Jun 2023 22:08:17 -0600 Subject: [PATCH 16/64] use the new {a,di}ssociate events to handle xwayland commit listener --- dwl.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/dwl.c b/dwl.c index c28ce42..5edb12c 100644 --- a/dwl.c +++ b/dwl.c @@ -1021,6 +1021,7 @@ createnotify(struct wl_listener *listener, void *data) c->surface.xdg = xdg_surface; c->bw = borderpx; + LISTEN(&xdg_surface->surface->events.commit, &c->commit, commitnotify); LISTEN(&xdg_surface->surface->events.map, &c->map, mapnotify); LISTEN(&xdg_surface->surface->events.unmap, &c->unmap, unmapnotify); LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify); @@ -1177,6 +1178,7 @@ destroynotify(struct wl_listener *listener, void *data) } else #endif { + wl_list_remove(&c->commit.link); wl_list_remove(&c->map.link); wl_list_remove(&c->unmap.link); } @@ -1541,12 +1543,7 @@ mapnotify(struct wl_listener *listener, void *data) c->scene_surface = c->type == XDGShell ? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg) : wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); - if (client_surface(c)) { - client_surface(c)->data = c->scene; - /* Ideally we should do this in createnotify{,x11} but at that moment - * wlr_xwayland_surface doesn't have wlr_surface yet. */ - LISTEN(&client_surface(c)->events.commit, &c->commit, commitnotify); - } + client_surface(c)->data = c->scene; c->scene->node.data = c->scene_surface->node.data = c; /* Handle unmanaged clients first so we can return prior create borders */ @@ -2525,7 +2522,6 @@ unmapnotify(struct wl_listener *listener, void *data) wl_list_remove(&c->flink); } - wl_list_remove(&c->commit.link); wlr_scene_node_destroy(&c->scene->node); printstatus(); motionnotify(0); @@ -2747,6 +2743,7 @@ associatex11(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, associate); + LISTEN(&client_surface(c)->events.commit, &c->commit, commitnotify); LISTEN(&client_surface(c)->events.map, &c->map, mapnotify); LISTEN(&client_surface(c)->events.unmap, &c->unmap, unmapnotify); } @@ -2792,6 +2789,7 @@ void dissociatex11(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, dissociate); + wl_list_remove(&c->commit.link); wl_list_remove(&c->map.link); wl_list_remove(&c->unmap.link); } From 24a337e6ec4711d28789abc90cb42ce3e7277309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 8 Jun 2023 23:35:46 -0600 Subject: [PATCH 17/64] handle gamma-control-v1 set_gamma event References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4046 --- dwl.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 5edb12c..1c6de4e 100644 --- a/dwl.c +++ b/dwl.c @@ -298,6 +298,7 @@ static void run(char *startup_cmd); static void setcursor(struct wl_listener *listener, void *data); static void setfloating(Client *c, int floating); static void setfullscreen(Client *c, int fullscreen); +static void setgamma(struct wl_listener *listener, void *data); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setmon(Client *c, Monitor *m, uint32_t newtags); @@ -352,6 +353,7 @@ static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; static struct wlr_input_inhibit_manager *input_inhibit_mgr; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; +static struct wlr_gamma_control_manager_v1 *gamma_control_mgr; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; static struct wlr_cursor *cursor; @@ -392,6 +394,7 @@ static struct wl_listener output_mgr_apply = {.notify = outputmgrapply}; static struct wl_listener output_mgr_test = {.notify = outputmgrtest}; static struct wl_listener request_activate = {.notify = urgent}; static struct wl_listener request_cursor = {.notify = setcursor}; +static struct wl_listener request_gamma = {.notify = setgamma}; static struct wl_listener request_set_psel = {.notify = setpsel}; static struct wl_listener request_set_sel = {.notify = setsel}; static struct wl_listener request_start_drag = {.notify = requeststartdrag}; @@ -2067,6 +2070,21 @@ setfullscreen(Client *c, int fullscreen) printstatus(); } +void +setgamma(struct wl_listener *listener, void *data) +{ + struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; + if (!wlr_gamma_control_v1_apply(event->control, &event->output->pending)) + return; + + if (!wlr_output_test(event->output)) { + wlr_output_rollback(event->output); + wlr_gamma_control_v1_send_failed_and_destroy(event->control); + } + + wlr_output_schedule_frame(event->output); +} + void setlayout(const Arg *arg) { @@ -2222,7 +2240,6 @@ setup(void) wlr_screencopy_manager_v1_create(dpy); wlr_data_control_manager_v1_create(dpy); wlr_data_device_manager_create(dpy); - wlr_gamma_control_manager_v1_create(dpy); wlr_primary_selection_v1_device_manager_create(dpy); wlr_viewporter_create(dpy); wlr_single_pixel_buffer_manager_v1_create(dpy); @@ -2233,6 +2250,9 @@ setup(void) activation = wlr_xdg_activation_v1_create(dpy); wl_signal_add(&activation->events.request_activate, &request_activate); + gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy); + wl_signal_add(&gamma_control_mgr->events.set_gamma, &request_gamma); + /* Creates an output layout, which a wlroots utility for working with an * arrangement of screens in a physical layout. */ output_layout = wlr_output_layout_create(); From 1eb8a82ac4d3a0fa76affff591c6a6667cb12cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sun, 7 May 2023 14:59:48 -0600 Subject: [PATCH 18/64] Revert "avoid setting duplicate cursor image" This reverts commit b5776e5180010ead5232efb36b2490f4fc9e1366. See next commit for details --- dwl.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/dwl.c b/dwl.c index 1c6de4e..c73ce2a 100644 --- a/dwl.c +++ b/dwl.c @@ -329,7 +329,6 @@ static void zoom(const Arg *arg); /* variables */ static const char broken[] = "broken"; -static const char *cursor_image = "left_ptr"; static pid_t child_pid = -1; static int locked; static void *exclusive_focus; @@ -613,13 +612,10 @@ buttonpress(struct wl_listener *listener, void *data) break; case WLR_BUTTON_RELEASED: /* If you released any buttons, we exit interactive move/resize mode. */ + /* TODO should reset to the pointer focus's current setcursor */ if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { + wlr_xcursor_manager_set_cursor_image(cursor_mgr, "left_ptr", cursor); cursor_mode = CurNormal; - /* Clear the pointer focus, this way if the cursor is over a surface - * we will send an enter event after which the client will provide us - * a cursor surface */ - wlr_seat_pointer_clear_focus(seat); - motionnotify(0); /* Drop the window off on its new monitor */ selmon = xytomon(cursor->x, cursor->y); setmon(grabc, selmon, 0); @@ -1694,8 +1690,8 @@ motionnotify(uint32_t time) /* If there's no client surface under the cursor, set the cursor image to a * default. This is what makes the cursor image appear when you move it * off of a client or over its border. */ - if (!surface && !seat->drag && (!cursor_image || strcmp(cursor_image, "left_ptr"))) - wlr_xcursor_manager_set_cursor_image(cursor_mgr, (cursor_image = "left_ptr"), cursor); + if (!surface && !seat->drag) + wlr_xcursor_manager_set_cursor_image(cursor_mgr, "left_ptr", cursor); pointerfocus(c, surface, sx, sy, time); } @@ -1730,7 +1726,7 @@ moveresize(const Arg *arg) case CurMove: grabcx = cursor->x - grabc->geom.x; grabcy = cursor->y - grabc->geom.y; - wlr_xcursor_manager_set_cursor_image(cursor_mgr, (cursor_image = "fleur"), cursor); + wlr_xcursor_manager_set_cursor_image(cursor_mgr, "fleur", cursor); break; case CurResize: /* Doesn't work for X11 output - the next absolute motion event @@ -1739,7 +1735,7 @@ moveresize(const Arg *arg) grabc->geom.x + grabc->geom.width, grabc->geom.y + grabc->geom.height); wlr_xcursor_manager_set_cursor_image(cursor_mgr, - (cursor_image = "bottom_right_corner"), cursor); + "bottom_right_corner", cursor); break; } } @@ -1840,6 +1836,7 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, * wlroots makes this a no-op if surface is already focused */ wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); + } void @@ -2008,7 +2005,7 @@ run(char *startup_cmd) * initialized, as the image/coordinates are not transformed for the * monitor when displayed here */ wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); - wlr_xcursor_manager_set_cursor_image(cursor_mgr, cursor_image, cursor); + wlr_xcursor_manager_set_cursor_image(cursor_mgr, "left_ptr", cursor); /* Run the Wayland event loop. This does not return until you exit the * compositor. Starting the backend rigged up all of the necessary event @@ -2027,7 +2024,6 @@ setcursor(struct wl_listener *listener, void *data) * event, which will result in the client requesting set the cursor surface */ if (cursor_mode != CurNormal && cursor_mode != CurPressed) return; - cursor_image = NULL; /* This can be sent by any client, so we check to make sure this one is * actually has pointer focus first. If so, we can tell the cursor to * use the provided surface as the cursor image. It will set the From 96ab92cdb16dfbae724e96eea6fb72d1bec20021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 15 Jun 2023 12:12:22 -0600 Subject: [PATCH 19/64] use wlr_cursor_set_xcursor() This avoids re-upload the cursor image in each motion event Managing the scale is done by the function itself References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4170 --- dwl.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/dwl.c b/dwl.c index c73ce2a..1538ed7 100644 --- a/dwl.c +++ b/dwl.c @@ -614,7 +614,7 @@ buttonpress(struct wl_listener *listener, void *data) /* If you released any buttons, we exit interactive move/resize mode. */ /* TODO should reset to the pointer focus's current setcursor */ if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { - wlr_xcursor_manager_set_cursor_image(cursor_mgr, "left_ptr", cursor); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "left_ptr"); cursor_mode = CurNormal; /* Drop the window off on its new monitor */ selmon = xytomon(cursor->x, cursor->y); @@ -928,7 +928,6 @@ createmon(struct wl_listener *listener, void *data) m->mfact = r->mfact; m->nmaster = r->nmaster; wlr_output_set_scale(wlr_output, r->scale); - wlr_xcursor_manager_load(cursor_mgr, r->scale); m->lt[0] = m->lt[1] = r->lt; wlr_output_set_transform(wlr_output, r->rr); m->m.x = r->x; @@ -1691,7 +1690,7 @@ motionnotify(uint32_t time) * default. This is what makes the cursor image appear when you move it * off of a client or over its border. */ if (!surface && !seat->drag) - wlr_xcursor_manager_set_cursor_image(cursor_mgr, "left_ptr", cursor); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "left_ptr"); pointerfocus(c, surface, sx, sy, time); } @@ -1726,7 +1725,7 @@ moveresize(const Arg *arg) case CurMove: grabcx = cursor->x - grabc->geom.x; grabcy = cursor->y - grabc->geom.y; - wlr_xcursor_manager_set_cursor_image(cursor_mgr, "fleur", cursor); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); break; case CurResize: /* Doesn't work for X11 output - the next absolute motion event @@ -1734,8 +1733,7 @@ moveresize(const Arg *arg) wlr_cursor_warp_closest(cursor, NULL, grabc->geom.x + grabc->geom.width, grabc->geom.y + grabc->geom.height); - wlr_xcursor_manager_set_cursor_image(cursor_mgr, - "bottom_right_corner", cursor); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "bottom_right_corner"); break; } } @@ -2005,7 +2003,7 @@ run(char *startup_cmd) * initialized, as the image/coordinates are not transformed for the * monitor when displayed here */ wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); - wlr_xcursor_manager_set_cursor_image(cursor_mgr, "left_ptr", cursor); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "left_ptr"); /* Run the Wayland event loop. This does not return until you exit the * compositor. Starting the backend rigged up all of the necessary event From 65f68e76437275a0c1c25279af646f726e213b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 12 Jun 2023 22:46:39 -0600 Subject: [PATCH 20/64] use wlr_scene_output_build_state() to set gamma --- dwl.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/dwl.c b/dwl.c index 1538ed7..1b2027c 100644 --- a/dwl.c +++ b/dwl.c @@ -2068,15 +2068,26 @@ void setgamma(struct wl_listener *listener, void *data) { struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; - if (!wlr_gamma_control_v1_apply(event->control, &event->output->pending)) + Monitor *m = event->output->data; + struct wlr_output_state pending = {0}; + if (!m) return; - if (!wlr_output_test(event->output)) { - wlr_output_rollback(event->output); + if (!wlr_scene_output_build_state(m->scene_output, &pending)) + return; + + if (!wlr_gamma_control_v1_apply(event->control, &pending)) + goto out; + + if (!wlr_output_commit_state(m->wlr_output, &pending)) { wlr_gamma_control_v1_send_failed_and_destroy(event->control); + goto out; } - wlr_output_schedule_frame(event->output); + wlr_damage_ring_rotate(&m->scene_output->damage_ring); + +out: + wlr_output_state_finish(&pending); } void From dfb6b97159ab8780674be9bea103227e68505c7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 9 Jun 2023 13:36:56 -0600 Subject: [PATCH 21/64] drop support for wlr-input-inhibitor-unstable-v1 deprecated in favor of ext-session-lock-v1 References: https://gitlab.freedesktop.org/wlroots/wlr-protocols/-/commit/4aa366e3ddf5e9b67950a94b9fb299bbfe05eef8 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3848 --- dwl.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dwl.c b/dwl.c index 1b2027c..77303d2 100644 --- a/dwl.c +++ b/dwl.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -349,7 +348,6 @@ static struct wl_list fstack; /* focus order */ static struct wlr_idle *idle; static struct wlr_idle_notifier_v1 *idle_notifier; static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; -static struct wlr_input_inhibit_manager *input_inhibit_mgr; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; static struct wlr_gamma_control_manager_v1 *gamma_control_mgr; @@ -1428,8 +1426,7 @@ keypress(struct wl_listener *listener, void *data) /* On _press_ if there is no active screen locker, * attempt to process a compositor keybinding. */ - if (!locked && !input_inhibit_mgr->active_inhibitor - && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) + if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) for (i = 0; i < nsyms; i++) handled = keybinding(mods, syms[i]) || handled; @@ -2290,7 +2287,6 @@ setup(void) xdg_shell = wlr_xdg_shell_create(dpy, 4); wl_signal_add(&xdg_shell->events.new_surface, &new_xdg_surface); - input_inhibit_mgr = wlr_input_inhibit_manager_create(dpy); session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); wl_signal_add(&session_lock_mgr->events.new_lock, &session_lock_create_lock); wl_signal_add(&session_lock_mgr->events.destroy, &session_lock_mgr_destroy); From 1e1811f95368c0848ba13137452153e01862c301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 9 Jun 2023 13:45:40 -0600 Subject: [PATCH 22/64] drop KDE idle support use ext-idle-notify-v1 instead --- dwl.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/dwl.c b/dwl.c index 77303d2..3c2f2f6 100644 --- a/dwl.c +++ b/dwl.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -71,7 +70,6 @@ #define END(A) ((A) + LENGTH(A)) #define TAGMASK ((1u << tagcount) - 1) #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) -#define IDLE_NOTIFY_ACTIVITY wlr_idle_notify_activity(idle, seat), wlr_idle_notifier_v1_notify_activity(idle_notifier, seat) /* enums */ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ @@ -345,7 +343,6 @@ static struct wlr_xdg_activation_v1 *activation; static struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr; static struct wl_list clients; /* tiling order */ static struct wl_list fstack; /* focus order */ -static struct wlr_idle *idle; static struct wlr_idle_notifier_v1 *idle_notifier; static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; static struct wlr_layer_shell_v1 *layer_shell; @@ -567,7 +564,7 @@ axisnotify(struct wl_listener *listener, void *data) /* This event is forwarded by the cursor when a pointer emits an axis event, * for example when you move the scroll wheel. */ struct wlr_pointer_axis_event *event = data; - IDLE_NOTIFY_ACTIVITY; + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); /* TODO: allow usage of scroll whell for mousebindings, it can be implemented * checking the event's orientation and the delta of the event */ /* Notify the client with pointer focus of the axis event. */ @@ -585,7 +582,7 @@ buttonpress(struct wl_listener *listener, void *data) Client *c; const Button *b; - IDLE_NOTIFY_ACTIVITY; + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); switch (event->state) { case WLR_BUTTON_PRESSED: @@ -651,7 +648,6 @@ checkidleinhibitor(struct wlr_surface *exclude) } } - wlr_idle_set_enabled(idle, NULL, !inhibited); wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited); } @@ -1422,7 +1418,7 @@ keypress(struct wl_listener *listener, void *data) int handled = 0; uint32_t mods = wlr_keyboard_get_modifiers(kb->wlr_keyboard); - IDLE_NOTIFY_ACTIVITY; + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); /* On _press_ if there is no active screen locker, * attempt to process a compositor keybinding. */ @@ -1647,7 +1643,7 @@ motionnotify(uint32_t time) /* time is 0 in internal calls meant to restore pointer focus. */ if (time) { - IDLE_NOTIFY_ACTIVITY; + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); /* Update selmon (even while dragging a window) */ if (sloppyfocus) @@ -2275,7 +2271,6 @@ setup(void) wl_list_init(&clients); wl_list_init(&fstack); - idle = wlr_idle_create(dpy); idle_notifier = wlr_idle_notifier_v1_create(dpy); idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); From 6095ff84d2f8141f5bcedb41af75c95109e24fdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 23 Jun 2023 13:30:43 -0600 Subject: [PATCH 23/64] Revert "use wlr_scene_output_build_state() to set gamma" This reverts commit 65f68e76437275a0c1c25279af646f726e213b6d. --- dwl.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/dwl.c b/dwl.c index 3c2f2f6..2a16ef7 100644 --- a/dwl.c +++ b/dwl.c @@ -2061,26 +2061,15 @@ void setgamma(struct wl_listener *listener, void *data) { struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; - Monitor *m = event->output->data; - struct wlr_output_state pending = {0}; - if (!m) + if (!wlr_gamma_control_v1_apply(event->control, &event->output->pending)) return; - if (!wlr_scene_output_build_state(m->scene_output, &pending)) - return; - - if (!wlr_gamma_control_v1_apply(event->control, &pending)) - goto out; - - if (!wlr_output_commit_state(m->wlr_output, &pending)) { + if (!wlr_output_test(event->output)) { + wlr_output_rollback(event->output); wlr_gamma_control_v1_send_failed_and_destroy(event->control); - goto out; } - wlr_damage_ring_rotate(&m->scene_output->damage_ring); - -out: - wlr_output_state_finish(&pending); + wlr_output_schedule_frame(event->output); } void From fdb66ccfa3a035202369bb366a401d49bcce22a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 23 Jun 2023 13:42:44 -0600 Subject: [PATCH 24/64] use detached output states to set gamma --- dwl.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/dwl.c b/dwl.c index 2a16ef7..4ebceab 100644 --- a/dwl.c +++ b/dwl.c @@ -2061,15 +2061,20 @@ void setgamma(struct wl_listener *listener, void *data) { struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; - if (!wlr_gamma_control_v1_apply(event->control, &event->output->pending)) + struct wlr_output_state state; + wlr_output_state_init(&state); + if (!wlr_gamma_control_v1_apply(event->control, &state)) { + wlr_output_state_finish(&state); return; - - if (!wlr_output_test(event->output)) { - wlr_output_rollback(event->output); - wlr_gamma_control_v1_send_failed_and_destroy(event->control); } - wlr_output_schedule_frame(event->output); + if (!wlr_output_test_state(event->output, &state)) { + wlr_gamma_control_v1_send_failed_and_destroy(event->control); + wlr_output_state_finish(&state); + return; + } + + wlr_output_commit_state(event->output, &state); } void From 733114f0ca5a09b471514d54dbced4a9a6068e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sat, 24 Jun 2023 10:09:49 -0600 Subject: [PATCH 25/64] schedule a frame after commmiting gamma not doing it, may freeze the output or do not actually change the gamma until creating a client --- dwl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwl.c b/dwl.c index 4ebceab..8cdcd49 100644 --- a/dwl.c +++ b/dwl.c @@ -2075,6 +2075,7 @@ setgamma(struct wl_listener *listener, void *data) } wlr_output_commit_state(event->output, &state); + wlr_output_schedule_frame(event->output); } void From a01e402c5dc2e9fe6af58e4921a1c28179e253b7 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 3 Jul 2023 17:48:45 -0500 Subject: [PATCH 26/64] Line saver: follow "local = wlr->data = obj" pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There were still a couple of places where we could use this handy multiple assignment to save a line. ΔSLOC = -3 --- dwl.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/dwl.c b/dwl.c index 740e543..0c08bfd 100644 --- a/dwl.c +++ b/dwl.c @@ -847,7 +847,7 @@ createlayersurface(struct wl_listener *listener, void *data) return; } - layersurface = ecalloc(1, sizeof(LayerSurface)); + layersurface = wlr_layer_surface->data = ecalloc(1, sizeof(LayerSurface)); layersurface->type = LayerShell; LISTEN(&wlr_layer_surface->surface->events.commit, &layersurface->surface_commit, commitlayersurfacenotify); @@ -860,8 +860,6 @@ createlayersurface(struct wl_listener *listener, void *data) layersurface->layer_surface = wlr_layer_surface; layersurface->mon = wlr_layer_surface->output->data; - wlr_layer_surface->data = layersurface; - layersurface->scene_layer = wlr_scene_layer_surface_v1_create(l, wlr_layer_surface); layersurface->scene = layersurface->scene_layer->tree; layersurface->popups = wlr_layer_surface->surface->data = wlr_scene_tree_create(l); @@ -1497,13 +1495,12 @@ locksession(struct wl_listener *listener, void *data) wlr_session_lock_v1_destroy(session_lock); return; } - lock = ecalloc(1, sizeof(*lock)); + lock = session_lock->data = ecalloc(1, sizeof(*lock)); focusclient(NULL, 0); lock->scene = wlr_scene_tree_create(layers[LyrBlock]); cur_lock = lock->lock = session_lock; locked = 1; - session_lock->data = lock; LISTEN(&session_lock->events.new_surface, &lock->new_surface, createlocksurface); LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock); @@ -1529,12 +1526,11 @@ mapnotify(struct wl_listener *listener, void *data) int i; /* Create scene tree for this client and its border */ - c->scene = wlr_scene_tree_create(layers[LyrTile]); + c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]); wlr_scene_node_set_enabled(&c->scene->node, c->type != XDGShell); c->scene_surface = c->type == XDGShell ? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg) : wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); - client_surface(c)->data = c->scene; c->scene->node.data = c->scene_surface->node.data = c; /* Handle unmanaged clients first so we can return prior create borders */ @@ -2393,7 +2389,7 @@ startdrag(struct wl_listener *listener, void *data) if (!drag->icon) return; - drag->icon->data = icon = wlr_scene_drag_icon_create(&scene->tree, drag->icon); + icon = drag->icon->data = wlr_scene_drag_icon_create(&scene->tree, drag->icon); wlr_scene_node_place_below(&icon->node, &layers[LyrBlock]->node); motionnotify(0); wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); From 33bcd2e4ca892bb0b558660c99ed63a3dfdd9011 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 3 Jul 2023 17:35:44 -0500 Subject: [PATCH 27/64] Line saver: LISTEN_STATIC macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This parallels the LISTEN macro for statically allocated listeners, and it allows us to remove almost all of the global wl_listener declarations. This also fixes a bug with the axisnotify listener, which was declared with a compound literal. At block scope, these have automatic storage duration [1], so the listener was no longer valid after setup() returned. (The option to declare it static explicitly was standardized in C23, if that ever gains suckless traction.) ΔSLOC: -27 [1]: https://en.cppreference.com/w/c/language/compound_literal#Explanation --- dwl.c | 93 ++++++++++++++++++++--------------------------------------- 1 file changed, 32 insertions(+), 61 deletions(-) diff --git a/dwl.c b/dwl.c index 0c08bfd..0e788a4 100644 --- a/dwl.c +++ b/dwl.c @@ -70,6 +70,7 @@ #define END(A) ((A) + LENGTH(A)) #define TAGMASK ((1u << tagcount) - 1) #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) +#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) /* enums */ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ @@ -359,6 +360,7 @@ static struct wlr_xcursor_manager *cursor_mgr; static struct wlr_session_lock_manager_v1 *session_lock_mgr; static struct wlr_scene_rect *locked_bg; static struct wlr_session_lock_v1 *cur_lock; +static struct wl_listener lock_listener = {.notify = locksession}; static struct wlr_seat *seat; static struct wl_list keyboards; @@ -371,34 +373,6 @@ static struct wlr_box sgeom; static struct wl_list mons; static Monitor *selmon; -/* global event handlers */ -static struct wl_listener cursor_axis = {.notify = axisnotify}; -static struct wl_listener cursor_button = {.notify = buttonpress}; -static struct wl_listener cursor_frame = {.notify = cursorframe}; -static struct wl_listener cursor_motion = {.notify = motionrelative}; -static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute}; -static struct wl_listener drag_icon_destroy = {.notify = destroydragicon}; -static struct wl_listener idle_inhibitor_create = {.notify = createidleinhibitor}; -static struct wl_listener idle_inhibitor_destroy = {.notify = destroyidleinhibitor}; -static struct wl_listener layout_change = {.notify = updatemons}; -static struct wl_listener new_input = {.notify = inputdevice}; -static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard}; -static struct wl_listener new_output = {.notify = createmon}; -static struct wl_listener new_xdg_surface = {.notify = createnotify}; -static struct wl_listener new_xdg_decoration = {.notify = createdecoration}; -static struct wl_listener new_layer_shell_surface = {.notify = createlayersurface}; -static struct wl_listener output_mgr_apply = {.notify = outputmgrapply}; -static struct wl_listener output_mgr_test = {.notify = outputmgrtest}; -static struct wl_listener request_activate = {.notify = urgent}; -static struct wl_listener request_cursor = {.notify = setcursor}; -static struct wl_listener request_gamma = {.notify = setgamma}; -static struct wl_listener request_set_psel = {.notify = setpsel}; -static struct wl_listener request_set_sel = {.notify = setsel}; -static struct wl_listener request_start_drag = {.notify = requeststartdrag}; -static struct wl_listener start_drag = {.notify = startdrag}; -static struct wl_listener session_lock_create_lock = {.notify = locksession}; -static struct wl_listener session_lock_mgr_destroy = {.notify = destroysessionmgr}; - #ifdef XWAYLAND static void activatex11(struct wl_listener *listener, void *data); static void associatex11(struct wl_listener *listener, void *data); @@ -408,8 +382,6 @@ static void dissociatex11(struct wl_listener *listener, void *data); static Atom getatom(xcb_connection_t *xc, const char *name); static void sethints(struct wl_listener *listener, void *data); static void xwaylandready(struct wl_listener *listener, void *data); -static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11}; -static struct wl_listener xwayland_ready = {.notify = xwaylandready}; static struct wlr_xwayland *xwayland; static Atom netatom[NetLast]; #endif @@ -794,7 +766,7 @@ void createidleinhibitor(struct wl_listener *listener, void *data) { struct wlr_idle_inhibitor_v1 *idle_inhibitor = data; - wl_signal_add(&idle_inhibitor->events.destroy, &idle_inhibitor_destroy); + LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor); checkidleinhibitor(NULL); } @@ -1185,8 +1157,8 @@ destroysessionlock(struct wl_listener *listener, void *data) void destroysessionmgr(struct wl_listener *listener, void *data) { - wl_list_remove(&session_lock_create_lock.link); - wl_list_remove(&session_lock_mgr_destroy.link); + wl_list_remove(&lock_listener.link); + wl_list_remove(&listener->link); } Monitor * @@ -2224,21 +2196,21 @@ setup(void) /* Initializes the interface used to implement urgency hints */ activation = wlr_xdg_activation_v1_create(dpy); - wl_signal_add(&activation->events.request_activate, &request_activate); + LISTEN_STATIC(&activation->events.request_activate, urgent); gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy); - wl_signal_add(&gamma_control_mgr->events.set_gamma, &request_gamma); + LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma); /* Creates an output layout, which a wlroots utility for working with an * arrangement of screens in a physical layout. */ output_layout = wlr_output_layout_create(); - wl_signal_add(&output_layout->events.change, &layout_change); + LISTEN_STATIC(&output_layout->events.change, updatemons); wlr_xdg_output_manager_v1_create(dpy, output_layout); /* Configure a listener to be notified when new outputs are available on the * backend. */ wl_list_init(&mons); - wl_signal_add(&backend->events.new_output, &new_output); + LISTEN_STATIC(&backend->events.new_output, createmon); /* Set up our client lists and the xdg-shell. The xdg-shell is a * Wayland protocol which is used for application windows. For more @@ -2252,17 +2224,17 @@ setup(void) idle_notifier = wlr_idle_notifier_v1_create(dpy); idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); - wl_signal_add(&idle_inhibit_mgr->events.new_inhibitor, &idle_inhibitor_create); + LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor); layer_shell = wlr_layer_shell_v1_create(dpy, 3); - wl_signal_add(&layer_shell->events.new_surface, &new_layer_shell_surface); + LISTEN_STATIC(&layer_shell->events.new_surface, createlayersurface); xdg_shell = wlr_xdg_shell_create(dpy, 4); - wl_signal_add(&xdg_shell->events.new_surface, &new_xdg_surface); + LISTEN_STATIC(&xdg_shell->events.new_surface, createnotify); session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); - wl_signal_add(&session_lock_mgr->events.new_lock, &session_lock_create_lock); - wl_signal_add(&session_lock_mgr->events.destroy, &session_lock_mgr_destroy); + wl_signal_add(&session_lock_mgr->events.new_lock, &lock_listener); + LISTEN_STATIC(&session_lock_mgr->events.destroy, destroysessionmgr); locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height, (float [4]){0.1, 0.1, 0.1, 1.0}); wlr_scene_node_set_enabled(&locked_bg->node, 0); @@ -2272,7 +2244,7 @@ setup(void) wlr_server_decoration_manager_create(dpy), WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy); - wl_signal_add(&xdg_decoration_mgr->events.new_toplevel_decoration, &new_xdg_decoration); + LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration); /* * Creates a cursor, which is a wlroots utility for tracking the cursor @@ -2300,11 +2272,11 @@ setup(void) * * And more comments are sprinkled throughout the notify functions above. */ - wl_signal_add(&cursor->events.motion, &cursor_motion); - wl_signal_add(&cursor->events.motion_absolute, &cursor_motion_absolute); - wl_signal_add(&cursor->events.button, &cursor_button); - wl_signal_add(&cursor->events.axis, &cursor_axis); - wl_signal_add(&cursor->events.frame, &cursor_frame); + LISTEN_STATIC(&cursor->events.motion, motionrelative); + LISTEN_STATIC(&cursor->events.motion_absolute, motionabsolute); + LISTEN_STATIC(&cursor->events.button, buttonpress); + LISTEN_STATIC(&cursor->events.axis, axisnotify); + LISTEN_STATIC(&cursor->events.frame, cursorframe); /* * Configures a seat, which is a single "seat" at which a user sits and @@ -2313,20 +2285,19 @@ setup(void) * let us know when new input devices are available on the backend. */ wl_list_init(&keyboards); - wl_signal_add(&backend->events.new_input, &new_input); + LISTEN_STATIC(&backend->events.new_input, inputdevice); virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); - wl_signal_add(&virtual_keyboard_mgr->events.new_virtual_keyboard, - &new_virtual_keyboard); + LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard); seat = wlr_seat_create(dpy, "seat0"); - wl_signal_add(&seat->events.request_set_cursor, &request_cursor); - wl_signal_add(&seat->events.request_set_selection, &request_set_sel); - wl_signal_add(&seat->events.request_set_primary_selection, &request_set_psel); - wl_signal_add(&seat->events.request_start_drag, &request_start_drag); - wl_signal_add(&seat->events.start_drag, &start_drag); + LISTEN_STATIC(&seat->events.request_set_cursor, setcursor); + LISTEN_STATIC(&seat->events.request_set_selection, setsel); + LISTEN_STATIC(&seat->events.request_set_primary_selection, setpsel); + LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag); + LISTEN_STATIC(&seat->events.start_drag, startdrag); output_mgr = wlr_output_manager_v1_create(dpy); - wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); - wl_signal_add(&output_mgr->events.test, &output_mgr_test); + LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); + LISTEN_STATIC(&output_mgr->events.test, outputmgrtest); wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend)); @@ -2337,8 +2308,8 @@ setup(void) */ xwayland = wlr_xwayland_create(dpy, compositor, 1); if (xwayland) { - wl_signal_add(&xwayland->events.ready, &xwayland_ready); - wl_signal_add(&xwayland->events.new_surface, &new_xwayland_surface); + LISTEN_STATIC(&xwayland->events.ready, xwaylandready); + LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11); setenv("DISPLAY", xwayland->display_name, 1); } else { @@ -2392,7 +2363,7 @@ startdrag(struct wl_listener *listener, void *data) icon = drag->icon->data = wlr_scene_drag_icon_create(&scene->tree, drag->icon); wlr_scene_node_place_below(&icon->node, &layers[LyrBlock]->node); motionnotify(0); - wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); + LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); } void From ff7c0e9508a380bb271886c2780e6f21679da1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 10 Jul 2023 11:23:19 -0600 Subject: [PATCH 28/64] chase wlroots!4220 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4220 --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 0e788a4..7a2c323 100644 --- a/dwl.c +++ b/dwl.c @@ -1865,7 +1865,7 @@ rendermon(struct wl_listener *listener, void *data) wl_list_for_each(c, &clients, link) if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c)) goto skip; - wlr_scene_output_commit(m->scene_output); + wlr_scene_output_commit(m->scene_output, NULL); skip: /* Let clients know a frame has been rendered */ From 0bb1a1cc5c31b8375d3c64a50e7ada57994fd2a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sat, 15 Jul 2023 10:11:47 -0600 Subject: [PATCH 29/64] increase wl_compositor version Now scene will handle sending the preferred buffer scale References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4269 --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 11bc510..fcd3612 100644 --- a/dwl.c +++ b/dwl.c @@ -2191,7 +2191,7 @@ setup(void) * to dig your fingers in and play with their behavior if you want. Note that * the clients cannot set the selection directly without compositor approval, * see the setsel() function. */ - compositor = wlr_compositor_create(dpy, 5, drw); + compositor = wlr_compositor_create(dpy, 6, drw); wlr_export_dmabuf_manager_v1_create(dpy); wlr_screencopy_manager_v1_create(dpy); wlr_data_control_manager_v1_create(dpy); From 0e5405610ea2c7f07675c7d22bf6991a0d947803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 27 Jun 2023 18:21:58 -0600 Subject: [PATCH 30/64] add support for cursor-shape-v1 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4106 --- Makefile | 5 ++++- dwl.c | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ccca079..63b52f0 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS) all: dwl dwl: dwl.o util.o $(CC) dwl.o util.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) -o $@ -dwl.o: dwl.c config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h +dwl.o: dwl.c config.mk config.h client.h cursor-shape-v1-protocol.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h util.o: util.c util.h # wayland-scanner is a tool which generates C headers and rigging for Wayland @@ -31,6 +31,9 @@ xdg-shell-protocol.h: wlr-layer-shell-unstable-v1-protocol.h: $(WAYLAND_SCANNER) server-header \ protocols/wlr-layer-shell-unstable-v1.xml $@ +cursor-shape-v1-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/staging/cursor-shape/cursor-shape-v1.xml $@ config.h: cp config.def.h $@ diff --git a/dwl.c b/dwl.c index fcd3612..456648b 100644 --- a/dwl.c +++ b/dwl.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -294,6 +295,7 @@ static void requestmonstate(struct wl_listener *listener, void *data); static void resize(Client *c, struct wlr_box geo, int interact); static void run(char *startup_cmd); static void setcursor(struct wl_listener *listener, void *data); +static void setcursorshape(struct wl_listener *listener, void *data); static void setfloating(Client *c, int floating); static void setfullscreen(Client *c, int fullscreen); static void setgamma(struct wl_listener *listener, void *data); @@ -353,6 +355,7 @@ static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; static struct wlr_gamma_control_manager_v1 *gamma_control_mgr; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; +static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; static struct wlr_cursor *cursor; static struct wlr_xcursor_manager *cursor_mgr; @@ -2003,6 +2006,20 @@ setcursor(struct wl_listener *listener, void *data) event->hotspot_x, event->hotspot_y); } +void +setcursorshape(struct wl_listener *listener, void *data) +{ + struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data; + if (cursor_mode != CurNormal && cursor_mode != CurPressed) + return; + /* This can be sent by any client, so we check to make sure this one is + * actually has pointer focus first. If so, we can tell the cursor to + * use the provided cursor shape. */ + if (event->seat_client == seat->pointer_state.focused_client) + wlr_cursor_set_xcursor(cursor, cursor_mgr, + wlr_cursor_shape_v1_name(event->shape)); +} + void setfloating(Client *c, int floating) { @@ -2286,6 +2303,9 @@ setup(void) LISTEN_STATIC(&cursor->events.axis, axisnotify); LISTEN_STATIC(&cursor->events.frame, cursorframe); + cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); + LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape); + /* * Configures a seat, which is a single "seat" at which a user sits and * operates the computer. This conceptually includes up to one keyboard, From ce997c4a21e96716982f491718eef08f95425ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 19:07:21 -0600 Subject: [PATCH 31/64] update to xdg-shell v5 --- dwl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 456648b..436d082 100644 --- a/dwl.c +++ b/dwl.c @@ -987,6 +987,9 @@ createnotify(struct wl_listener *listener, void *data) c->surface.xdg = xdg_surface; c->bw = borderpx; + wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); + LISTEN(&xdg_surface->surface->events.commit, &c->commit, commitnotify); LISTEN(&xdg_surface->surface->events.map, &c->map, mapnotify); LISTEN(&xdg_surface->surface->events.unmap, &c->unmap, unmapnotify); @@ -2254,7 +2257,7 @@ setup(void) layer_shell = wlr_layer_shell_v1_create(dpy, 3); LISTEN_STATIC(&layer_shell->events.new_surface, createlayersurface); - xdg_shell = wlr_xdg_shell_create(dpy, 4); + xdg_shell = wlr_xdg_shell_create(dpy, 5); LISTEN_STATIC(&xdg_shell->events.new_surface, createnotify); session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); From 78cf88670f3410782f5c90895c3c4586d3485a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 20:59:29 -0600 Subject: [PATCH 32/64] add support for xdg-shell v6 --- client.h | 11 +++++++++++ dwl.c | 9 ++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/client.h b/client.h index ef56ee6..fc999f1 100644 --- a/client.h +++ b/client.h @@ -346,6 +346,17 @@ client_set_tiled(Client *c, uint32_t edges) wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges); } +static inline void +client_set_suspended(Client *c, int suspended) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return; +#endif + + wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended); +} + static inline struct wlr_surface * client_surface_at(Client *c, double cx, double cy, double *sx, double *sy) { diff --git a/dwl.c b/dwl.c index 436d082..91abe11 100644 --- a/dwl.c +++ b/dwl.c @@ -457,9 +457,12 @@ void arrange(Monitor *m) { Client *c; - wl_list_for_each(c, &clients, link) - if (c->mon == m) + wl_list_for_each(c, &clients, link) { + if (c->mon == m) { wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m)); + client_set_suspended(c, !VISIBLEON(c, m)); + } + } wlr_scene_node_set_enabled(&m->fullscreen_bg->node, (c = focustop(m)) && c->isfullscreen); @@ -2257,7 +2260,7 @@ setup(void) layer_shell = wlr_layer_shell_v1_create(dpy, 3); LISTEN_STATIC(&layer_shell->events.new_surface, createlayersurface); - xdg_shell = wlr_xdg_shell_create(dpy, 5); + xdg_shell = wlr_xdg_shell_create(dpy, 6); LISTEN_STATIC(&xdg_shell->events.new_surface, createnotify); session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); From 25db04539216fa6bf05ad39cdeeeca6df6b69e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 25 Jul 2023 19:45:18 -0600 Subject: [PATCH 33/64] set withdrawn state for xwayland invisible clients --- client.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client.h b/client.h index fc999f1..6a46151 100644 --- a/client.h +++ b/client.h @@ -350,8 +350,10 @@ static inline void client_set_suspended(Client *c, int suspended) { #ifdef XWAYLAND - if (client_is_x11(c)) + if (client_is_x11(c)) { + wlr_xwayland_surface_set_withdrawn(c->surface.xwayland, suspended); return; + } #endif wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended); From d4f2c6bfd638d45736512691f06081cf314370bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 21 Aug 2023 17:53:24 -0600 Subject: [PATCH 34/64] chase wlroots!4288 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4288 --- client.h | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/client.h b/client.h index 6a46151..80152cc 100644 --- a/client.h +++ b/client.h @@ -54,7 +54,7 @@ client_surface(Client *c) static inline int toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl) { - struct wlr_xdg_surface *xdg_surface; + struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface; struct wlr_surface *root_surface; struct wlr_layer_surface_v1 *layer_surface; Client *c = NULL; @@ -82,24 +82,27 @@ toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl) goto end; } - if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(root_surface))) { - while (1) { - switch (xdg_surface->role) { - case WLR_XDG_SURFACE_ROLE_POPUP: - if (!xdg_surface->popup->parent) - return -1; - else if (!wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent)) - return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl); - - xdg_surface = wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent); - break; - case WLR_XDG_SURFACE_ROLE_TOPLEVEL: - c = xdg_surface->data; - type = c->type; - goto end; - case WLR_XDG_SURFACE_ROLE_NONE: + xdg_surface = wlr_xdg_surface_try_from_wlr_surface(root_surface); + while (xdg_surface) { + tmp_xdg_surface = NULL; + switch (xdg_surface->role) { + case WLR_XDG_SURFACE_ROLE_POPUP: + if (!xdg_surface->popup || !xdg_surface->popup->parent) return -1; - } + + tmp_xdg_surface = wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent); + + if (!tmp_xdg_surface) + return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl); + + xdg_surface = tmp_xdg_surface; + break; + case WLR_XDG_SURFACE_ROLE_TOPLEVEL: + c = xdg_surface->data; + type = c->type; + goto end; + case WLR_XDG_SURFACE_ROLE_NONE: + return -1; } } From e5e74acfce05502181a0eaa6e252140e1572d925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 1 Nov 2023 12:04:59 -0600 Subject: [PATCH 35/64] send maximized if tiled isn't supported (XDG shell) wlroots doesn't do it automatically anymore References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4409 --- client.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client.h b/client.h index 6fc7c93..b49032e 100644 --- a/client.h +++ b/client.h @@ -354,7 +354,12 @@ client_set_tiled(Client *c, uint32_t edges) if (client_is_x11(c)) return; #endif - wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges); + if (wl_resource_get_version(c->surface.xdg->resource) + >= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { + wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges); + } else { + wlr_xdg_toplevel_set_maximized(c->surface.xdg->toplevel, edges != 0); + } } static inline void From e45ded7eea0c77db8ff13148a51a910bac13b48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 1 Nov 2023 12:16:02 -0600 Subject: [PATCH 36/64] ignore maximize events for clients using xdg-shell v5 and newer --- dwl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 6db82d6..cde99fe 100644 --- a/dwl.c +++ b/dwl.c @@ -1587,9 +1587,14 @@ maximizenotify(struct wl_listener *listener, void *data) * typically because the user clicked on the maximize button on * client-side decorations. dwl doesn't support maximization, but * to conform to xdg-shell protocol we still must send a configure. + * Since xdg-shell protocol v5 we should ignore request of unsupported + * capabilities, just schedule a empty configure when the client uses <5 + * protocol version * wlr_xdg_surface_schedule_configure() is used to send an empty reply. */ Client *c = wl_container_of(listener, c, maximize); - wlr_xdg_surface_schedule_configure(c->surface.xdg); + if (wl_resource_get_version(c->surface.xdg->resource) + < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) + wlr_xdg_surface_schedule_configure(c->surface.xdg); } void From a4a83e95e69afd45ff1770149810d79de39b8467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 1 Nov 2023 12:28:19 -0600 Subject: [PATCH 37/64] use newer cursor naming spec References: https://www.freedesktop.org/wiki/Specifications/cursor-spec/ References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4416 --- dwl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dwl.c b/dwl.c index cde99fe..5d3c63d 100644 --- a/dwl.c +++ b/dwl.c @@ -589,7 +589,7 @@ buttonpress(struct wl_listener *listener, void *data) /* If you released any buttons, we exit interactive move/resize mode. */ /* TODO should reset to the pointer focus's current setcursor */ if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { - wlr_cursor_set_xcursor(cursor, cursor_mgr, "left_ptr"); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); cursor_mode = CurNormal; /* Drop the window off on its new monitor */ selmon = xytomon(cursor->x, cursor->y); @@ -1679,7 +1679,7 @@ motionnotify(uint32_t time) * default. This is what makes the cursor image appear when you move it * off of a client or over its border. */ if (!surface && !seat->drag) - wlr_cursor_set_xcursor(cursor, cursor_mgr, "left_ptr"); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); pointerfocus(c, surface, sx, sy, time); } @@ -1722,7 +1722,7 @@ moveresize(const Arg *arg) wlr_cursor_warp_closest(cursor, NULL, grabc->geom.x + grabc->geom.width, grabc->geom.y + grabc->geom.height); - wlr_cursor_set_xcursor(cursor, cursor_mgr, "bottom_right_corner"); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); break; } } @@ -1982,7 +1982,7 @@ run(char *startup_cmd) * initialized, as the image/coordinates are not transformed for the * monitor when displayed here */ wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); - wlr_cursor_set_xcursor(cursor, cursor_mgr, "left_ptr"); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); /* Run the Wayland event loop. This does not return until you exit the * compositor. Starting the backend rigged up all of the necessary event @@ -2847,7 +2847,7 @@ xwaylandready(struct wl_listener *listener, void *data) wlr_xwayland_set_seat(xwayland, seat); /* Set the default XWayland cursor to match the rest of dwl. */ - if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "left_ptr", 1))) + if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1))) wlr_xwayland_set_cursor(xwayland, xcursor->images[0]->buffer, xcursor->images[0]->width * 4, xcursor->images[0]->width, xcursor->images[0]->height, From 31bf1cbaf6418a6fb39e41b21cadc5c20826a663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sat, 8 Jul 2023 20:07:27 -0600 Subject: [PATCH 38/64] Revert "respect size hints" This reverts commit 72e0a560d9836c5e8658003f548203bcd722e565. --- client.h | 53 +++++++++++++++++++---------------------------------- dwl.c | 16 +++------------- 2 files changed, 22 insertions(+), 47 deletions(-) diff --git a/client.h b/client.h index b49032e..6a870b4 100644 --- a/client.h +++ b/client.h @@ -16,31 +16,6 @@ client_is_x11(Client *c) #endif } -static inline void -client_get_size_hints(Client *c, struct wlr_box *max, struct wlr_box *min) -{ - struct wlr_xdg_toplevel *toplevel; - struct wlr_xdg_toplevel_state *state; -#ifdef XWAYLAND - if (client_is_x11(c)) { - xcb_size_hints_t *size_hints = c->surface.xwayland->size_hints; - if (size_hints) { - max->width = size_hints->max_width; - max->height = size_hints->max_height; - min->width = size_hints->min_width; - min->height = size_hints->min_height; - } - return; - } -#endif - toplevel = c->surface.xdg->toplevel; - state = &toplevel->current; - max->width = state->max_width; - max->height = state->max_height; - min->width = state->min_width; - min->height = state->min_height; -} - static inline struct wlr_surface * client_surface(Client *c) { @@ -190,7 +165,6 @@ client_get_parent(Client *c) #endif if (c->surface.xdg->toplevel->parent) toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL); - return p; } @@ -207,25 +181,36 @@ client_get_title(Client *c) static inline int client_is_float_type(Client *c) { - struct wlr_box min = {0}, max = {0}; - client_get_size_hints(c, &max, &min); + struct wlr_xdg_toplevel *toplevel; + struct wlr_xdg_toplevel_state state; #ifdef XWAYLAND if (client_is_x11(c)) { struct wlr_xwayland_surface *surface = c->surface.xwayland; + xcb_size_hints_t *size_hints; if (surface->modal) return 1; for (size_t i = 0; i < surface->window_type_len; i++) - if (surface->window_type[i] == netatom[NetWMWindowTypeDialog] - || surface->window_type[i] == netatom[NetWMWindowTypeSplash] - || surface->window_type[i] == netatom[NetWMWindowTypeToolbar] - || surface->window_type[i] == netatom[NetWMWindowTypeUtility]) + if (surface->window_type[i] == netatom[NetWMWindowTypeDialog] || + surface->window_type[i] == netatom[NetWMWindowTypeSplash] || + surface->window_type[i] == netatom[NetWMWindowTypeToolbar] || + surface->window_type[i] == netatom[NetWMWindowTypeUtility]) return 1; + + size_hints = surface->size_hints; + return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0 + && (size_hints->max_width == size_hints->min_width + || size_hints->max_height == size_hints->min_height); } #endif - return ((min.width > 0 || min.height > 0 || max.width > 0 || max.height > 0) - && (min.width == max.width || min.height == max.height)); + + toplevel = c->surface.xdg->toplevel; + state = toplevel->current; + return (state.min_width != 0 && state.min_height != 0 + && (state.min_width == state.max_width + || state.min_height == state.max_height)) + || toplevel->parent; } static inline int diff --git a/dwl.c b/dwl.c index 5d3c63d..b379305 100644 --- a/dwl.c +++ b/dwl.c @@ -399,19 +399,9 @@ static xcb_atom_t netatom[NetLast]; void applybounds(Client *c, struct wlr_box *bbox) { - if (!c->isfullscreen) { - struct wlr_box min = {0}, max = {0}; - client_get_size_hints(c, &max, &min); - /* try to set size hints */ - c->geom.width = MAX(min.width + (2 * (int)c->bw), c->geom.width); - c->geom.height = MAX(min.height + (2 * (int)c->bw), c->geom.height); - /* Some clients set their max size to INT_MAX, which does not violate the - * protocol but it's unnecesary, as they can set their max size to zero. */ - if (max.width > 0 && !(2 * c->bw > INT_MAX - max.width)) /* Checks for overflow */ - c->geom.width = MIN(max.width + (2 * c->bw), c->geom.width); - if (max.height > 0 && !(2 * c->bw > INT_MAX - max.height)) /* Checks for overflow */ - c->geom.height = MIN(max.height + (2 * c->bw), c->geom.height); - } + /* set minimum possible */ + c->geom.width = MAX(1, c->geom.width); + c->geom.height = MAX(1, c->geom.height); if (c->geom.x >= bbox->x + bbox->width) c->geom.x = bbox->x + bbox->width - c->geom.width; From e1f3983bf8a548f0357a92d9023c90aa4c273f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sat, 8 Jul 2023 20:08:45 -0600 Subject: [PATCH 39/64] use wlr_scene_subsurface_tree_set_clip References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4131 Closes: https://github.com/djpohly/dwl/issues/411 --- client.h | 22 ++++++++++++++++++++++ dwl.c | 3 +++ 2 files changed, 25 insertions(+) diff --git a/client.h b/client.h index 6a870b4..012ba74 100644 --- a/client.h +++ b/client.h @@ -140,6 +140,28 @@ client_get_appid(Client *c) return c->surface.xdg->toplevel->app_id; } +static inline void +client_get_clip(Client *c, struct wlr_box *clip) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) { + *clip = (struct wlr_box){ + .x = 0, + .y = 0, + .width = c->geom.width - c->bw, + .height = c->geom.height - c->bw}; + return; + } +#endif + + *clip = (struct wlr_box){ + .x = c->surface.xdg->pending.geometry.x, + .y = c->surface.xdg->pending.geometry.y, + .width = c->geom.width - c->bw, + .height = c->geom.height - c->bw}; + +} + static inline void client_get_geometry(Client *c, struct wlr_box *geom) { diff --git a/dwl.c b/dwl.c index b379305..00d22e8 100644 --- a/dwl.c +++ b/dwl.c @@ -1909,6 +1909,7 @@ void resize(Client *c, struct wlr_box geo, int interact) { struct wlr_box *bbox = interact ? &sgeom : &c->mon->w; + struct wlr_box clip; client_set_bounds(c, geo.width, geo.height); c->geom = geo; applybounds(c, bbox); @@ -1927,6 +1928,8 @@ resize(Client *c, struct wlr_box geo, int interact) /* this is a no-op if size hasn't changed */ c->resize = client_set_size(c, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw); + client_get_clip(c, &clip); + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); } void From 6f8a3f93749aae35b863946d333043d4779d2b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 20:58:45 -0600 Subject: [PATCH 40/64] fix screen artifacts when setting gamma the artifacts were caused because we tried to set the gamma right after receiving the event, this resulted in two pending page-flips, which not always play well together. This also seems to fix a screen freeze when turning on a monitor that has gamma. Additionally the current method won't work once [0] is merged [0]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4423 --- dwl.c | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/dwl.c b/dwl.c index 00d22e8..e6d7914 100644 --- a/dwl.c +++ b/dwl.c @@ -194,6 +194,7 @@ struct Monitor { unsigned int sellt; uint32_t tagset[2]; double mfact; + int gamma_lut_changed; int nmaster; char ltsymbol[16]; }; @@ -1870,6 +1871,8 @@ rendermon(struct wl_listener *listener, void *data) * generally at the output's refresh rate (e.g. 60Hz). */ Monitor *m = wl_container_of(listener, m, frame); Client *c; + struct wlr_output_state pending = {0}; + struct wlr_gamma_control_v1 *gamma_control; struct timespec now; /* Render if no XDG clients have an outstanding resize and are visible on @@ -1877,12 +1880,38 @@ rendermon(struct wl_listener *listener, void *data) wl_list_for_each(c, &clients, link) if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c)) goto skip; + + /* + * HACK: The "correct" way to set the gamma is to commit it together with + * the rest of the state in one go, but to do that we would need to rewrite + * wlr_scene_output_commit() in order to add the gamma to the pending + * state before committing, instead try to commit the gamma in one frame, + * and commit the rest of the state in the next one (or in the same frame if + * the gamma can not be committed). + */ + if (m->gamma_lut_changed) { + gamma_control = wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output); + m->gamma_lut_changed = 0; + + if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) + goto commit; + + if (!wlr_output_test_state(m->wlr_output, &pending)) { + wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); + goto commit; + } + wlr_output_commit_state(m->wlr_output, &pending); + wlr_output_schedule_frame(m->wlr_output); + } else { +commit: wlr_scene_output_commit(m->scene_output, NULL); + } skip: /* Let clients know a frame has been rendered */ clock_gettime(CLOCK_MONOTONIC, &now); wlr_scene_output_send_frame_done(m->scene_output, &now); + wlr_output_state_finish(&pending); } void @@ -2057,21 +2086,9 @@ void setgamma(struct wl_listener *listener, void *data) { struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; - struct wlr_output_state state; - wlr_output_state_init(&state); - if (!wlr_gamma_control_v1_apply(event->control, &state)) { - wlr_output_state_finish(&state); - return; - } - - if (!wlr_output_test_state(event->output, &state)) { - wlr_gamma_control_v1_send_failed_and_destroy(event->control); - wlr_output_state_finish(&state); - return; - } - - wlr_output_commit_state(event->output, &state); - wlr_output_schedule_frame(event->output); + Monitor *m = event->output->data; + m->gamma_lut_changed = 1; + wlr_output_schedule_frame(m->wlr_output); } void From 2212363225510d11988f5ddc49bf9454f4455fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 20:47:29 -0600 Subject: [PATCH 41/64] make sure fullscreen clients have the right size --- dwl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dwl.c b/dwl.c index e6d7914..eca0860 100644 --- a/dwl.c +++ b/dwl.c @@ -2604,6 +2604,9 @@ updatemons(struct wl_listener *listener, void *data) arrangelayers(m); /* Don't move clients to the left output when plugging monitors */ arrange(m); + /* make sure fullscreen clients have the right size */ + if ((c = focustop(m)) && c->isfullscreen) + resize(c, m->m, 0); config_head->state.enabled = 1; config_head->state.mode = m->wlr_output->current_mode; From 8e3f5364d366fcabc16e142fbb09b0d9c376f3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 20:47:59 -0600 Subject: [PATCH 42/64] do not compute layout box twice --- dwl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index eca0860..37dc27f 100644 --- a/dwl.c +++ b/dwl.c @@ -2586,8 +2586,8 @@ updatemons(struct wl_listener *listener, void *data) config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); /* Get the effective monitor geometry to use for surfaces */ - wlr_output_layout_get_box(output_layout, m->wlr_output, &(m->m)); - wlr_output_layout_get_box(output_layout, m->wlr_output, &(m->w)); + wlr_output_layout_get_box(output_layout, m->wlr_output, &m->m); + m->w = m->m; wlr_scene_output_set_position(m->scene_output, m->m.x, m->m.y); wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y); From 4f4c540bb9ec47c77ff30e1a7ddd7d00d63c67b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 21:00:16 -0600 Subject: [PATCH 43/64] prevent a use-after-free at exit --- dwl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwl.c b/dwl.c index 37dc27f..82b7248 100644 --- a/dwl.c +++ b/dwl.c @@ -627,6 +627,7 @@ cleanup(void) { #ifdef XWAYLAND wlr_xwayland_destroy(xwayland); + xwayland = NULL; #endif wl_display_destroy_clients(dpy); if (child_pid > 0) { From 6d0ec595d3f3ba6977ea117681861713fbc1de5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 21:12:50 -0600 Subject: [PATCH 44/64] simplify client_get_clip the clips for xwayland and xdg clients are pretty similar, after all we only need to adjust x and y for xdg clients --- client.h | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/client.h b/client.h index 012ba74..2ffb92c 100644 --- a/client.h +++ b/client.h @@ -143,23 +143,22 @@ client_get_appid(Client *c) static inline void client_get_clip(Client *c, struct wlr_box *clip) { + struct wlr_box xdg_geom = {0}; + *clip = (struct wlr_box){ + .x = 0, + .y = 0, + .width = c->geom.width - c->bw, + .height = c->geom.height - c->bw, + }; + #ifdef XWAYLAND - if (client_is_x11(c)) { - *clip = (struct wlr_box){ - .x = 0, - .y = 0, - .width = c->geom.width - c->bw, - .height = c->geom.height - c->bw}; + if (client_is_x11(c)) return; - } #endif - *clip = (struct wlr_box){ - .x = c->surface.xdg->pending.geometry.x, - .y = c->surface.xdg->pending.geometry.y, - .width = c->geom.width - c->bw, - .height = c->geom.height - c->bw}; - + wlr_xdg_surface_get_geometry(c->surface.xdg, &xdg_geom); + clip->x = xdg_geom.x; + clip->y = xdg_geom.y; } static inline void From 0e897608a151da10f4ddcd2a528c618e5f60d9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 21:17:39 -0600 Subject: [PATCH 45/64] do not use magical numbers to check edges the interface is declared stable, which means we could just use 0 anyway --- client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client.h b/client.h index 2ffb92c..0fdd774 100644 --- a/client.h +++ b/client.h @@ -364,7 +364,7 @@ client_set_tiled(Client *c, uint32_t edges) >= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges); } else { - wlr_xdg_toplevel_set_maximized(c->surface.xdg->toplevel, edges != 0); + wlr_xdg_toplevel_set_maximized(c->surface.xdg->toplevel, edges != WLR_EDGE_NONE); } } From d6c102d9db2a2f3dc9d1da96d87e306129237a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 21:21:40 -0600 Subject: [PATCH 46/64] correctly check if the scene node is enabled in client_is_rendered_on_mon --- client.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client.h b/client.h index 0fdd774..a5bec71 100644 --- a/client.h +++ b/client.h @@ -241,7 +241,8 @@ client_is_rendered_on_mon(Client *c, Monitor *m) * but rather actual displaying of the pixels. * Usually VISIBLEON suffices and is also faster. */ struct wlr_surface_output *s; - if (!c->scene->node.enabled) + int unused_lx, unused_ly; + if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly)) return 0; wl_list_for_each(s, &client_surface(c)->current_outputs, link) if (s->output == m->wlr_output) From 22d21676b016a03fe3f2d988618d0c2acca48de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 21:27:49 -0600 Subject: [PATCH 47/64] style fixes in client_is_float_type --- client.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/client.h b/client.h index a5bec71..7d9ff8c 100644 --- a/client.h +++ b/client.h @@ -208,18 +208,18 @@ client_is_float_type(Client *c) #ifdef XWAYLAND if (client_is_x11(c)) { struct wlr_xwayland_surface *surface = c->surface.xwayland; - xcb_size_hints_t *size_hints; + xcb_size_hints_t *size_hints = surface->size_hints; + size_t i; if (surface->modal) return 1; - for (size_t i = 0; i < surface->window_type_len; i++) - if (surface->window_type[i] == netatom[NetWMWindowTypeDialog] || - surface->window_type[i] == netatom[NetWMWindowTypeSplash] || - surface->window_type[i] == netatom[NetWMWindowTypeToolbar] || - surface->window_type[i] == netatom[NetWMWindowTypeUtility]) + for (i = 0; i < surface->window_type_len; i++) + if (surface->window_type[i] == netatom[NetWMWindowTypeDialog] + || surface->window_type[i] == netatom[NetWMWindowTypeSplash] + || surface->window_type[i] == netatom[NetWMWindowTypeToolbar] + || surface->window_type[i] == netatom[NetWMWindowTypeUtility]) return 1; - size_hints = surface->size_hints; return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0 && (size_hints->max_width == size_hints->min_width || size_hints->max_height == size_hints->min_height); @@ -228,10 +228,9 @@ client_is_float_type(Client *c) toplevel = c->surface.xdg->toplevel; state = toplevel->current; - return (state.min_width != 0 && state.min_height != 0 + return toplevel->parent || (state.min_width != 0 && state.min_height != 0 && (state.min_width == state.max_width - || state.min_height == state.max_height)) - || toplevel->parent; + || state.min_height == state.max_height)); } static inline int From 0067c76caba464c0636183a8318fee6d63cd2b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 21:43:31 -0600 Subject: [PATCH 48/64] delete unused functions --- client.h | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/client.h b/client.h index 7d9ff8c..186c23d 100644 --- a/client.h +++ b/client.h @@ -119,17 +119,6 @@ client_set_bounds(Client *c, int32_t width, int32_t height) return 0; } -static inline void -client_for_each_surface(Client *c, wlr_surface_iterator_func_t fn, void *data) -{ - wlr_surface_for_each_surface(client_surface(c), fn, data); -#ifdef XWAYLAND - if (client_is_x11(c)) - return; -#endif - wlr_xdg_surface_for_each_popup_surface(c->surface.xdg, fn, data); -} - static inline const char * client_get_appid(Client *c) { @@ -381,17 +370,6 @@ client_set_suspended(Client *c, int suspended) wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended); } -static inline struct wlr_surface * -client_surface_at(Client *c, double cx, double cy, double *sx, double *sy) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - return wlr_surface_surface_at(c->surface.xwayland->surface, - cx, cy, sx, sy); -#endif - return wlr_xdg_surface_surface_at(c->surface.xdg, cx, cy, sx, sy); -} - static inline int client_wants_focus(Client *c) { From b1740056d5e9f81888fc9cb3e016bdb8eff054c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 21:45:08 -0600 Subject: [PATCH 49/64] do not use #ifdef -> #else -> #endif in client_is_x11 all other funcions use #ifdef -> #endif --- client.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client.h b/client.h index 186c23d..efb3e0d 100644 --- a/client.h +++ b/client.h @@ -11,9 +11,8 @@ client_is_x11(Client *c) { #ifdef XWAYLAND return c->type == X11Managed || c->type == X11Unmanaged; -#else - return 0; #endif + return 0; } static inline struct wlr_surface * From caac2d664db998beddeeececd7253a11a665c162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 21:46:46 -0600 Subject: [PATCH 50/64] explicitly return -1 in the first check in toplevel_from_wlr_surface --- client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client.h b/client.h index efb3e0d..9a9f0e0 100644 --- a/client.h +++ b/client.h @@ -39,7 +39,7 @@ toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl) #endif if (!s) - return type; + return -1; root_surface = wlr_surface_get_root_surface(s); #ifdef XWAYLAND From dd25cdb56e00586281b6d8e79f3af91db2f747ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 21:47:29 -0600 Subject: [PATCH 51/64] use the new wlroots function to get a toplevel from a wlr_surface References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4419 --- client.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client.h b/client.h index 9a9f0e0..7a77df0 100644 --- a/client.h +++ b/client.h @@ -92,7 +92,7 @@ end: static inline void client_activate_surface(struct wlr_surface *s, int activated) { - struct wlr_xdg_surface *surface; + struct wlr_xdg_toplevel *toplevel; #ifdef XWAYLAND struct wlr_xwayland_surface *xsurface; if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) { @@ -100,9 +100,8 @@ client_activate_surface(struct wlr_surface *s, int activated) return; } #endif - if ((surface = wlr_xdg_surface_try_from_wlr_surface(s)) - && surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) - wlr_xdg_toplevel_set_activated(surface->toplevel, activated); + if ((toplevel = wlr_xdg_toplevel_try_from_wlr_surface(s))) + wlr_xdg_toplevel_set_activated(toplevel, activated); } static inline uint32_t From 7bdbab04000c23638afeb8dbeddd628c4f15117c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 21:48:56 -0600 Subject: [PATCH 52/64] check toplevel resource instead of client's xdg_shell to set bounds --- client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client.h b/client.h index 7a77df0..b0f2900 100644 --- a/client.h +++ b/client.h @@ -111,7 +111,7 @@ client_set_bounds(Client *c, int32_t width, int32_t height) if (client_is_x11(c)) return 0; #endif - if (c->surface.xdg->client->shell->version >= + if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >= XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && width >= 0 && height >= 0) return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height); return 0; From bca1b779aae29437e920e64562da14eff3bc80c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 22:23:26 -0600 Subject: [PATCH 53/64] fix destroynotify() docs References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4421 --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 82b7248..b6f9389 100644 --- a/dwl.c +++ b/dwl.c @@ -1122,7 +1122,7 @@ destroylocksurface(struct wl_listener *listener, void *data) void destroynotify(struct wl_listener *listener, void *data) { - /* Called when the surface is destroyed and should never be shown again. */ + /* Called when the xdg_toplevel is destroyed. */ Client *c = wl_container_of(listener, c, destroy); wl_list_remove(&c->destroy.link); wl_list_remove(&c->set_title.link); From e95f14541a55c6e71881faebd1a7197b6d9bf20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 23:05:18 -0600 Subject: [PATCH 54/64] fix docs copied from tinywl --- dwl.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/dwl.c b/dwl.c index b6f9389..3fcdf07 100644 --- a/dwl.c +++ b/dwl.c @@ -2185,11 +2185,7 @@ setup(void) /* The backend is a wlroots feature which abstracts the underlying input and * output hardware. The autocreate option will choose the most suitable * backend based on the current environment, such as opening an X11 window - * if an X11 server is running. The NULL argument here optionally allows you - * to pass in a custom renderer if wlr_renderer doesn't meet your needs. The - * backend uses the renderer, for example, to fall back to software cursors - * if the backend does not support hardware cursors (some older GPUs - * don't). */ + * if an X11 server is running. */ if (!(backend = wlr_backend_autocreate(dpy, &session))) die("couldn't create backend"); @@ -2200,7 +2196,10 @@ setup(void) drag_icon = wlr_scene_tree_create(&scene->tree); wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node); - /* Create a renderer with the default implementation */ + /* Autocreates a renderer, either Pixman, GLES2 or Vulkan for us. The user + * can also specify a renderer using the WLR_RENDERER env var. + * The renderer is responsible for defining the various pixel formats it + * supports for shared memory, this configures that for clients. */ if (!(drw = wlr_renderer_autocreate(backend))) die("couldn't create renderer"); @@ -2217,7 +2216,10 @@ setup(void) wlr_linux_dmabuf_v1_create_with_renderer(dpy, 4, drw)); } - /* Create a default allocator */ + /* Autocreates an allocator for us. + * The allocator is the bridge between the renderer and the backend. It + * handles the buffer creation, allowing wlroots to render onto the + * screen */ if (!(alloc = wlr_allocator_autocreate(backend, drw))) die("couldn't create allocator"); @@ -2228,15 +2230,15 @@ setup(void) * the clients cannot set the selection directly without compositor approval, * see the setsel() function. */ compositor = wlr_compositor_create(dpy, 6, drw); + wlr_subcompositor_create(dpy); + wlr_data_device_manager_create(dpy); wlr_export_dmabuf_manager_v1_create(dpy); wlr_screencopy_manager_v1_create(dpy); wlr_data_control_manager_v1_create(dpy); - wlr_data_device_manager_create(dpy); wlr_primary_selection_v1_device_manager_create(dpy); wlr_viewporter_create(dpy); wlr_single_pixel_buffer_manager_v1_create(dpy); wlr_fractional_scale_manager_v1_create(dpy, 1); - wlr_subcompositor_create(dpy); /* Initializes the interface used to implement urgency hints */ activation = wlr_xdg_activation_v1_create(dpy); @@ -2256,7 +2258,7 @@ setup(void) wl_list_init(&mons); LISTEN_STATIC(&backend->events.new_output, createmon); - /* Set up our client lists and the xdg-shell. The xdg-shell is a + /* Set up our client lists, the xdg-shell and the layer-shell. The xdg-shell is a * Wayland protocol which is used for application windows. For more * detail on shells, refer to the article: * @@ -2265,16 +2267,16 @@ setup(void) wl_list_init(&clients); wl_list_init(&fstack); - idle_notifier = wlr_idle_notifier_v1_create(dpy); - - idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); - LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor); + xdg_shell = wlr_xdg_shell_create(dpy, 6); + LISTEN_STATIC(&xdg_shell->events.new_surface, createnotify); layer_shell = wlr_layer_shell_v1_create(dpy, 3); LISTEN_STATIC(&layer_shell->events.new_surface, createlayersurface); - xdg_shell = wlr_xdg_shell_create(dpy, 6); - LISTEN_STATIC(&xdg_shell->events.new_surface, createnotify); + idle_notifier = wlr_idle_notifier_v1_create(dpy); + + idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); + LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor); session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); wl_signal_add(&session_lock_mgr->events.new_lock, &lock_listener); @@ -2309,9 +2311,7 @@ setup(void) * when the pointer moves. However, we can attach input devices to it, and * it will generate aggregate events for all of them. In these events, we * can choose how we want to process them, forwarding them to clients and - * moving the cursor around. More detail on this process is described in my - * input handling blog post: - * + * moving the cursor around. More detail on this process is described in * https://drewdevault.com/2018/07/17/Input-handling-in-wlroots.html * * And more comments are sprinkled throughout the notify functions above. From 7611dc91d7f5211071fe1ecca3179a9ca6be9f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 23:06:21 -0600 Subject: [PATCH 55/64] enable debug symbols by default they does not affect performance and the size's increase is negligible --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d7082fd..6cde460 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ include config.mk # flags for compiling DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XWAYLAND) -DWLDEVCFLAGS = -pedantic -Wall -Wextra -Wdeclaration-after-statement -Wno-unused-parameter -Wno-sign-compare -Wshadow -Wunused-macros\ +DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement -Wno-unused-parameter -Wno-sign-compare -Wshadow -Wunused-macros\ -Werror=strict-prototypes -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types # CFLAGS / LDFLAGS From 6bcd5d8d87a972f72e23f37b94cc59d77d76c4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 23:23:08 -0600 Subject: [PATCH 56/64] do not explicitly destroy some wlroots interfaces they are destroyed when the wayland display is destroyed --- dwl.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/dwl.c b/dwl.c index 3fcdf07..5347af6 100644 --- a/dwl.c +++ b/dwl.c @@ -634,15 +634,12 @@ cleanup(void) kill(child_pid, SIGTERM); waitpid(child_pid, NULL, 0); } - wlr_backend_destroy(backend); - wlr_scene_node_destroy(&scene->tree.node); - wlr_renderer_destroy(drw); - wlr_allocator_destroy(alloc); wlr_xcursor_manager_destroy(cursor_mgr); - wlr_cursor_destroy(cursor); wlr_output_layout_destroy(output_layout); - wlr_seat_destroy(seat); wl_display_destroy(dpy); + /* Destroy after the wayland display (when the monitors are already destroyed) + to avoid destroying them with an invalid scene output. */ + wlr_scene_node_destroy(&scene->tree.node); } void From 1044a21555776969d9e3d72bbb2fff2bc0f90eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 16 Nov 2023 23:29:40 -0600 Subject: [PATCH 57/64] do not check if `session` is non-NULL wlr_session_change_vt() is a no-op if session == NULL --- dwl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index 5347af6..443c2c4 100644 --- a/dwl.c +++ b/dwl.c @@ -600,8 +600,7 @@ buttonpress(struct wl_listener *listener, void *data) void chvt(const Arg *arg) { - if (session) - wlr_session_change_vt(session, arg->ui); + wlr_session_change_vt(session, arg->ui); } void From b8e933b9a9bcbdb9c1f07f077d12cfec03cd5b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 17 Nov 2023 00:11:53 -0600 Subject: [PATCH 58/64] remove unused #include --- dwl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/dwl.c b/dwl.c index 443c2c4..60a2c7c 100644 --- a/dwl.c +++ b/dwl.c @@ -3,7 +3,6 @@ */ #include #include -#include #include #include #include From fcf324be6c661617a835ee504cb160c7d415d2e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 17 Nov 2023 19:03:23 -0600 Subject: [PATCH 59/64] fix the position of the cursor image after turning all the monitors on --- dwl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dwl.c b/dwl.c index 60a2c7c..11ecc42 100644 --- a/dwl.c +++ b/dwl.c @@ -2622,6 +2622,13 @@ updatemons(struct wl_listener *listener, void *data) } } + /* FIXME: figure out why the cursor image is at 0,0 after turning all + * the monitors on. + * Move the cursor image where it used to be. It does not generate a + * wl_pointer.motion event for the clients, it's only the image what it's + * at the wrong position after all. */ + wlr_cursor_move(cursor, NULL, 0, 0); + wlr_output_manager_v1_set_configuration(output_mgr, config); } From 2751a6195d5b659c8538b2b16fa157e7b920c8c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sat, 18 Nov 2023 11:20:56 -0600 Subject: [PATCH 60/64] do not try to enable adaptive sync --- dwl.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dwl.c b/dwl.c index 11ecc42..51ada7d 100644 --- a/dwl.c +++ b/dwl.c @@ -903,11 +903,6 @@ createmon(struct wl_listener *listener, void *data) if (!wlr_output_commit(wlr_output)) return; - /* Try to enable adaptive sync, note that not all monitors support it. - * wlr_output_commit() will deactivate it in case it cannot be enabled */ - wlr_output_enable_adaptive_sync(wlr_output, 1); - wlr_output_commit(wlr_output); - wl_list_insert(&mons, &m->link); printstatus(); From 32e66f45827cc8016ca2cef65ba61840f43fcc85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 21 Nov 2023 19:20:49 -0600 Subject: [PATCH 61/64] resize clients on commit Fixes: https://github.com/djpohly/dwl/issues/515 This reverts commit 4567979b16b0509bb80b6102ecb9b601b3cf6fa1. --- dwl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dwl.c b/dwl.c index 51ada7d..517062a 100644 --- a/dwl.c +++ b/dwl.c @@ -738,6 +738,9 @@ commitnotify(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, commit); + if (client_surface(c)->mapped) + resize(c, c->geom, (c->isfloating && !c->isfullscreen)); + /* mark a pending resize as completed */ if (c->resize && c->resize <= c->surface.xdg->current.configure_serial) c->resize = 0; From a0e79d81452049aaad2d3081d9c689fb9f4253a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 21 Nov 2023 20:08:20 -0600 Subject: [PATCH 62/64] Do not send repeated xdg_toplevel.configure_bounds Fixes: 32e66f45827cc8016ca2cef65ba61840f43fcc85 --- client.h | 6 +++++- dwl.c | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/client.h b/client.h index b0f2900..71c7d76 100644 --- a/client.h +++ b/client.h @@ -112,8 +112,12 @@ client_set_bounds(Client *c, int32_t width, int32_t height) return 0; #endif if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >= - XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && width >= 0 && height >= 0) + XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && width >= 0 && height >= 0 + && (c->bounds.width != width || c->bounds.height != height)) { + c->bounds.width = width; + c->bounds.height = height; return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height); + } return 0; } diff --git a/dwl.c b/dwl.c index 517062a..9e870cc 100644 --- a/dwl.c +++ b/dwl.c @@ -118,6 +118,7 @@ typedef struct { struct wl_listener set_title; struct wl_listener fullscreen; struct wlr_box prev; /* layout-relative, includes border */ + struct wlr_box bounds; #ifdef XWAYLAND struct wl_listener activate; struct wl_listener associate; From d2dd2f49862dfc4c2f7164026e7421bf91d2325e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 21 Nov 2023 20:11:06 -0600 Subject: [PATCH 63/64] ignore wl_surface.commit for xwayland clients This is no longer needed --- dwl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/dwl.c b/dwl.c index 9e870cc..4eac1fd 100644 --- a/dwl.c +++ b/dwl.c @@ -2760,7 +2760,6 @@ associatex11(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, associate); - LISTEN(&client_surface(c)->events.commit, &c->commit, commitnotify); LISTEN(&client_surface(c)->events.map, &c->map, mapnotify); LISTEN(&client_surface(c)->events.unmap, &c->unmap, unmapnotify); } @@ -2806,7 +2805,6 @@ void dissociatex11(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, dissociate); - wl_list_remove(&c->commit.link); wl_list_remove(&c->map.link); wl_list_remove(&c->unmap.link); } From 6838f909bd58e6f9775dcc463566c2c3ad3d4279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 21 Nov 2023 20:38:07 -0600 Subject: [PATCH 64/64] try to apply gamma LUT in updatemons this in the case the output was re-enabled --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 4eac1fd..762f147 100644 --- a/dwl.c +++ b/dwl.c @@ -2567,7 +2567,6 @@ updatemons(struct wl_listener *listener, void *data) if (m->wlr_output->enabled && !wlr_output_layout_get(output_layout, m->wlr_output)) wlr_output_layout_add_auto(output_layout, m->wlr_output); - /* Now that we update the output layout we can get its box */ wlr_output_layout_get_box(output_layout, NULL, &sgeom); @@ -2603,6 +2602,7 @@ updatemons(struct wl_listener *listener, void *data) if ((c = focustop(m)) && c->isfullscreen) resize(c, m->m, 0); + m->gamma_lut_changed = 1; config_head->state.enabled = 1; config_head->state.mode = m->wlr_output->current_mode; config_head->state.x = m->m.x;