From 45e3694fc8e91642cf970bd1586bd1a16dbc8a31 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Sun, 28 Jan 2024 09:01:09 +0100 Subject: remove useless wlr_scene_node_reparent() calls These don't do anything because wlr_scene_node_reparent() is immediately called again by setfloating() through setmon(). They are also a source of confusion because if you change the wlr_scene_node_reparent() call in applyrules() it takes a while to understand why it doesn't work. --- dwl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/dwl.c b/dwl.c index ae8df11..f407477 100644 --- a/dwl.c +++ b/dwl.c @@ -453,7 +453,6 @@ applyrules(Client *c) } } } - wlr_scene_node_reparent(&c->scene->node, layers[c->isfloating ? LyrFloat : LyrTile]); setmon(c, mon, newtags); } @@ -1546,7 +1545,6 @@ mapnotify(struct wl_listener *listener, void *data) /* TODO: https://github.com/djpohly/dwl/pull/334#issuecomment-1330166324 */ if (c->type == XDGShell && (p = client_get_parent(c))) { c->isfloating = 1; - wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]); setmon(c, p->mon, p->tags); } else { applyrules(c); -- cgit v1.2.3 From 17c5cbbf7b6c3a5373f46e6fb6e88daada325479 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Sun, 28 Jan 2024 09:06:20 +0100 Subject: make XWayland clients inherit tags and monitors Revert 3213088 because the linked bug can no longer be reproduced with wlroots 0.17, and update client_get_parent() so it doesn't segfault with XWayland surfaces. This also allows reusing the p variable in the next commit. --- client.h | 7 +++++-- dwl.c | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/client.h b/client.h index 0753da8..8a379d0 100644 --- a/client.h +++ b/client.h @@ -172,8 +172,11 @@ client_get_parent(Client *c) { Client *p = NULL; #ifdef XWAYLAND - if (client_is_x11(c) && c->surface.xwayland->parent) - toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL); + if (client_is_x11(c)) { + if (c->surface.xwayland->parent) + toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL); + return p; + } #endif if (c->surface.xdg->toplevel->parent) toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL); diff --git a/dwl.c b/dwl.c index f407477..b04b66a 100644 --- a/dwl.c +++ b/dwl.c @@ -1542,8 +1542,7 @@ mapnotify(struct wl_listener *listener, void *data) * we always consider floating, clients that have parent and thus * we set the same tags and monitor than its parent, if not * try to apply rules for them */ - /* TODO: https://github.com/djpohly/dwl/pull/334#issuecomment-1330166324 */ - if (c->type == XDGShell && (p = client_get_parent(c))) { + if ((p = client_get_parent(c))) { c->isfloating = 1; setmon(c, p->mon, p->tags); } else { -- cgit v1.2.3 From 298949bbc4eae8cedb9cdd11cfc9ebd139ac5d5f Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Sun, 28 Jan 2024 18:30:36 +0100 Subject: place child clients above fullscreen clients When a child window of a fullscreen client is mapped, the fullscreen is disabled, and if the previously fullscreen client is floating the child window is rendered below it and cannot be seen, causing confusion, though it is still focused and interactable. Fix this by putting children of fullscreen clients in LyrFS instead of LyrFloat, and by returning before the unset_fullscreen code is called when they are mapped. focusstack() now lets you switch focus from a fullscreen client to its child windows, otherwise if you switch focus from the child window to the fullscreen client you could not focus the child window again and the fullscreen client would stay unresponsive. Child clients are not reparented to LyrFloat after leaving fullscreen, so you could spawn a child window, focus back the fullscreen client, unfullscreen it, and the child window would still be drawn above other floating clients. Avoid dealing with this edge case to keep the line count low. These cases can be tested by pressing Ctrl+o in applications with an open file dialog. --- client.h | 12 ++++++++++++ dwl.c | 13 ++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/client.h b/client.h index 8a379d0..fe9dffc 100644 --- a/client.h +++ b/client.h @@ -183,6 +183,18 @@ client_get_parent(Client *c) return p; } +static inline int +client_has_children(Client *c) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return !wl_list_empty(&c->surface.xwayland->children); +#endif + /* surface.xdg->link is never empty because it always contains at least the + * surface itself. */ + return wl_list_length(&c->surface.xdg->link) > 1; +} + static inline const char * client_get_title(Client *c) { diff --git a/dwl.c b/dwl.c index b04b66a..95ebee8 100644 --- a/dwl.c +++ b/dwl.c @@ -1256,7 +1256,7 @@ focusstack(const Arg *arg) { /* Focus the next or previous client (in tiling order) on selmon */ Client *c, *sel = focustop(selmon); - if (!sel || sel->isfullscreen) + if (!sel || (sel->isfullscreen && !client_has_children(sel))) return; if (arg->i > 0) { wl_list_for_each(c, &sel->link, link) { @@ -1496,7 +1496,8 @@ void mapnotify(struct wl_listener *listener, void *data) { /* Called when the surface is mapped, or ready to display on-screen. */ - Client *p, *w, *c = wl_container_of(listener, c, map); + Client *p = NULL; + Client *w, *c = wl_container_of(listener, c, map); Monitor *m; int i; @@ -1553,7 +1554,7 @@ mapnotify(struct wl_listener *listener, void *data) unset_fullscreen: m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); wl_list_for_each(w, &clients, link) { - if (w != c && w->isfullscreen && m == w->mon && (w->tags & c->tags)) + if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) setfullscreen(w, 0); } } @@ -2044,11 +2045,13 @@ setcursorshape(struct wl_listener *listener, void *data) void setfloating(Client *c, int floating) { + Client *p = client_get_parent(c); c->isfloating = floating; if (!c->mon) return; - wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen - ? LyrFS : c->isfloating ? LyrFloat : LyrTile]); + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); arrange(c->mon); printstatus(); } -- cgit v1.2.3 From 3c98c4c24de39dea298bbf289b8fd8e7942a6901 Mon Sep 17 00:00:00 2001 From: Benjamin Chausse Date: Tue, 6 Feb 2024 00:39:01 +0000 Subject: Fix link to patches website Signed-off-by: Benjamin Chausse --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d22cf3..09233c7 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Wayland without restarting the entire display server, so any changes will take effect the next time dwl is executed. As in the dwm community, we encourage users to share patches they have created. -Check out the [patches page on our wiki]! +Check out the [patches repository]! ## Running dwl @@ -169,6 +169,7 @@ inspiration, and to the various contributors to the project, including: [Wayland]: https://wayland.freedesktop.org/ [wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots/ [wlroots-next branch]: https://codeberg.org/dwl/dwl/src/branch/wlroots-next +[patches repository]: https://codeberg.org/dwl/dwl-patches [patches page on our wiki]: https://codeberg.org/dwl/dwl/wiki/Patches [s6]: https://skarnet.org/software/s6/ [anopa]: https://jjacky.com/anopa/ -- cgit v1.2.3 From 089480e0b674156928e63a1db7888c312eeea68b Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Tue, 6 Feb 2024 01:25:56 +0000 Subject: Update and correct patches/patches-wiki links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leonardo Hernández Hernández --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 09233c7..5b3d4f6 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Wayland without restarting the entire display server, so any changes will take effect the next time dwl is executed. As in the dwm community, we encourage users to share patches they have created. -Check out the [patches repository]! +Check out the dwl [patches repository] and [patches wiki]! ## Running dwl @@ -170,7 +170,7 @@ inspiration, and to the various contributors to the project, including: [wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots/ [wlroots-next branch]: https://codeberg.org/dwl/dwl/src/branch/wlroots-next [patches repository]: https://codeberg.org/dwl/dwl-patches -[patches page on our wiki]: https://codeberg.org/dwl/dwl/wiki/Patches +[patches wiki]: https://codeberg.org/dwl/dwl-patches/wiki [s6]: https://skarnet.org/software/s6/ [anopa]: https://jjacky.com/anopa/ [runit]: http://smarden.org/runit/faq.html#userservices -- cgit v1.2.3 From 5ae245beedd587a2c9748168ef494abd5a92469c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 7 Feb 2024 02:21:26 +0000 Subject: fix minimum size continuation of 4043fc3093a73174cb63653ba9e742b4738f2ee5 --- dwl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index 95ebee8..e999923 100644 --- a/dwl.c +++ b/dwl.c @@ -412,8 +412,8 @@ void applybounds(Client *c, struct wlr_box *bbox) { /* set minimum possible */ - c->geom.width = MAX(1, c->geom.width); - c->geom.height = MAX(1, c->geom.height); + c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width); + c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height); if (c->geom.x >= bbox->x + bbox->width) c->geom.x = bbox->x + bbox->width - c->geom.width; -- cgit v1.2.3 From 8006e7920085947673517c3e296a1e308f935f75 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Tue, 16 Jan 2024 19:11:18 +0100 Subject: allow toggling the layout before selecting a different one --- dwl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index e999923..fa76db2 100644 --- a/dwl.c +++ b/dwl.c @@ -871,7 +871,8 @@ createmon(struct wl_listener *listener, void *data) m->m.y = r->y; m->mfact = r->mfact; m->nmaster = r->nmaster; - m->lt[0] = m->lt[1] = r->lt; + m->lt[0] = r->lt; + m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); wlr_output_state_set_scale(&state, r->scale); wlr_output_state_set_transform(&state, r->rr); -- cgit v1.2.3 From ea33ce9ae68e41a22a2fca3b6d17e071b9325a69 Mon Sep 17 00:00:00 2001 From: Forrest Bushstone Date: Mon, 26 Feb 2024 16:43:01 -0500 Subject: Support pointer constraints and relative pointer protocols Fixes: https://codeberg.org/dwl/dwl/issues/489 FIxes: https://codeberg.org/dwl/dwl/issues/317 --- Makefile | 13 +++--- dwl.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 127 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 0822ddc..a67fdd3 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 cursor-shape-v1-protocol.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 pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h util.o: util.c util.h # wayland-scanner is a tool which generates C headers and rigging for Wayland @@ -25,15 +25,18 @@ util.o: util.c util.h WAYLAND_SCANNER = `$(PKG_CONFIG) --variable=wayland_scanner wayland-scanner` WAYLAND_PROTOCOLS = `$(PKG_CONFIG) --variable=pkgdatadir wayland-protocols` -xdg-shell-protocol.h: +cursor-shape-v1-protocol.h: $(WAYLAND_SCANNER) server-header \ - $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ + $(WAYLAND_PROTOCOLS)/staging/cursor-shape/cursor-shape-v1.xml $@ +pointer-constraints-unstable-v1-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml $@ wlr-layer-shell-unstable-v1-protocol.h: $(WAYLAND_SCANNER) server-header \ protocols/wlr-layer-shell-unstable-v1.xml $@ -cursor-shape-v1-protocol.h: +xdg-shell-protocol.h: $(WAYLAND_SCANNER) server-header \ - $(WAYLAND_PROTOCOLS)/staging/cursor-shape/cursor-shape-v1.xml $@ + $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ config.h: cp config.def.h $@ diff --git a/dwl.c b/dwl.c index fa76db2..d508d79 100644 --- a/dwl.c +++ b/dwl.c @@ -35,9 +35,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -54,6 +56,7 @@ #include #include #include +#include #include #ifdef XWAYLAND #include @@ -214,6 +217,11 @@ typedef struct { int x, y; } MonitorRule; +typedef struct { + struct wlr_pointer_constraint_v1 *constraint; + struct wl_listener destroy; +} PointerConstraint; + typedef struct { const char *id; const char *title; @@ -255,7 +263,10 @@ static void createlocksurface(struct wl_listener *listener, void *data); static void createmon(struct wl_listener *listener, void *data); static void createnotify(struct wl_listener *listener, void *data); static void createpointer(struct wlr_pointer *pointer); +static void createpointerconstraint(struct wl_listener *listener, void *data); +static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); static void cursorframe(struct wl_listener *listener, void *data); +static void cursorwarptohint(void); static void destroydecoration(struct wl_listener *listener, void *data); static void destroydragicon(struct wl_listener *listener, void *data); static void destroyidleinhibitor(struct wl_listener *listener, void *data); @@ -263,6 +274,7 @@ static void destroylayersurfacenotify(struct wl_listener *listener, void *data); static void destroylock(SessionLock *lock, int unlocked); static void destroylocksurface(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data); +static void destroypointerconstraint(struct wl_listener *listener, void *data); static void destroysessionlock(struct wl_listener *listener, void *data); static void destroysessionmgr(struct wl_listener *listener, void *data); static Monitor *dirtomon(enum wlr_direction dir); @@ -285,7 +297,8 @@ static void mapnotify(struct wl_listener *listener, void *data); static void maximizenotify(struct wl_listener *listener, void *data); static void monocle(Monitor *m); static void motionabsolute(struct wl_listener *listener, void *data); -static void motionnotify(uint32_t time); +static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, + double sy, double sx_unaccel, double sy_unaccel); static void motionrelative(struct wl_listener *listener, void *data); static void moveresize(const Arg *arg); static void outputmgrapply(struct wl_listener *listener, void *data); @@ -366,6 +379,10 @@ static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; +static struct wlr_pointer_constraints_v1 *pointer_constraints; +static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; +static struct wlr_pointer_constraint_v1 *active_constraint; + static struct wlr_cursor *cursor; static struct wlr_xcursor_manager *cursor_mgr; @@ -478,7 +495,7 @@ arrange(Monitor *m) if (m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); - motionnotify(0); + motionnotify(0, NULL, 0, 0, 0, 0); checkidleinhibitor(NULL); } @@ -1015,6 +1032,28 @@ createpointer(struct wlr_pointer *pointer) wlr_cursor_attach_input_device(cursor, &pointer->base); } +void +createpointerconstraint(struct wl_listener *listener, void *data) +{ + PointerConstraint *pointer_constraint = ecalloc(1, sizeof(*pointer_constraint)); + pointer_constraint->constraint = data; + LISTEN(&pointer_constraint->constraint->events.destroy, + &pointer_constraint->destroy, destroypointerconstraint); +} + +void +cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) +{ + if (active_constraint == constraint) + return; + + if (active_constraint) + wlr_pointer_constraint_v1_send_deactivated(active_constraint); + + active_constraint = constraint; + wlr_pointer_constraint_v1_send_activated(constraint); +} + void cursorframe(struct wl_listener *listener, void *data) { @@ -1026,6 +1065,21 @@ cursorframe(struct wl_listener *listener, void *data) wlr_seat_pointer_notify_frame(seat); } +void +cursorwarptohint(void) +{ + Client *c = NULL; + double sx = active_constraint->current.cursor_hint.x; + double sy = active_constraint->current.cursor_hint.y; + + toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); + /* TODO: wlroots 0.18: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4478 */ + if (c && (active_constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT )) { + wlr_cursor_warp(cursor, NULL, sx + c->geom.x + c->bw, sy + c->geom.y + c->bw); + wlr_seat_pointer_warp(active_constraint->seat, sx, sy); + } +} + void destroydecoration(struct wl_listener *listener, void *data) { @@ -1040,7 +1094,7 @@ destroydragicon(struct wl_listener *listener, void *data) { /* Focus enter isn't sent during drag, so refocus the focused node. */ focusclient(focustop(selmon), 1); - motionnotify(0); + motionnotify(0, NULL, 0, 0, 0, 0); } void @@ -1076,7 +1130,7 @@ destroylock(SessionLock *lock, int unlock) wlr_scene_node_set_enabled(&locked_bg->node, 0); focusclient(focustop(selmon), 0); - motionnotify(0); + motionnotify(0, NULL, 0, 0, 0, 0); destroy: wl_list_remove(&lock->new_surface.link); @@ -1135,6 +1189,20 @@ destroynotify(struct wl_listener *listener, void *data) free(c); } +void +destroypointerconstraint(struct wl_listener *listener, void *data) +{ + PointerConstraint *pointer_constraint = wl_container_of(listener, pointer_constraint, destroy); + + if (active_constraint == pointer_constraint->constraint) { + cursorwarptohint(); + active_constraint = NULL; + } + + wl_list_remove(&pointer_constraint->destroy.link); + free(pointer_constraint); +} + void destroysessionlock(struct wl_listener *listener, void *data) { @@ -1231,7 +1299,7 @@ focusclient(Client *c, int lift) } /* Change cursor surface */ - motionnotify(0); + motionnotify(0, NULL, 0, 0, 0, 0); /* Have a client, so focus its top-level wlr_surface */ client_notify_enter(client_surface(c), wlr_seat_get_keyboard(seat)); @@ -1490,7 +1558,7 @@ locksession(struct wl_listener *listener, void *data) void maplayersurfacenotify(struct wl_listener *listener, void *data) { - motionnotify(0); + motionnotify(0, NULL, 0, 0, 0, 0); } void @@ -1605,20 +1673,50 @@ motionabsolute(struct wl_listener *listener, void *data) * so we have to warp the mouse there. There is also some hardware which * emits these events. */ struct wlr_pointer_motion_absolute_event *event = data; - wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x, event->y); - motionnotify(event->time_msec); + double lx, ly, dx, dy; + + wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, event->y, &lx, &ly); + dx = lx - cursor->x; + dy = ly - cursor->y; + motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); } void -motionnotify(uint32_t time) +motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, + double dx_unaccel, double dy_unaccel) { - double sx = 0, sy = 0; + double sx = 0, sy = 0, sx_confined, sy_confined; Client *c = NULL, *w = NULL; LayerSurface *l = NULL; struct wlr_surface *surface = NULL; + struct wlr_pointer_constraint_v1 *constraint; /* time is 0 in internal calls meant to restore pointer focus. */ if (time) { + wlr_relative_pointer_manager_v1_send_relative_motion( + relative_pointer_mgr, seat, (uint64_t)time * 1000, + dx, dy, dx_unaccel, dy_unaccel); + + wl_list_for_each(constraint, &pointer_constraints->constraints, link) + cursorconstrain(constraint); + + if (active_constraint && cursor_mode != CurResize && cursor_mode != CurMove) { + toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); + if (c && active_constraint->surface == seat->pointer_state.focused_surface) { + sx = cursor->x - c->geom.x - c->bw; + sy = cursor->y - c->geom.y - c->bw; + if (wlr_region_confine(&active_constraint->region, sx, sy, + sx + dx, sy + dy, &sx_confined, &sy_confined)) { + dx = sx_confined - sx; + dy = sy_confined - sy; + } + + if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) + return; + } + } + + wlr_cursor_move(cursor, device, dx, dy); wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); /* Update selmon (even while dragging a window) */ @@ -1672,8 +1770,8 @@ motionrelative(struct wl_listener *listener, void *data) * special configuration applied for the specific input device which * generated the event. You can pass NULL for the device if you want to move * the cursor around without any input. */ - wlr_cursor_move(cursor, &event->pointer->base, event->delta_x, event->delta_y); - motionnotify(event->time_msec); + motionnotify(event->time_msec, &event->pointer->base, event->delta_x, event->delta_y, + event->unaccel_dx, event->unaccel_dy); } void @@ -1781,7 +1879,8 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, { struct timespec now; - if (sloppyfocus && time && c && !client_is_unmanaged(c)) + if ((!active_constraint || active_constraint->surface != surface) && + sloppyfocus && time && c && !client_is_unmanaged(c)) focusclient(c, 0); /* If surface is NULL, clear pointer focus */ @@ -1800,7 +1899,6 @@ 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 @@ -2295,6 +2393,11 @@ setup(void) xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy); LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration); + pointer_constraints = wlr_pointer_constraints_v1_create(dpy); + LISTEN_STATIC(&pointer_constraints->events.new_constraint, createpointerconstraint); + + relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); + /* * Creates a cursor, which is a wlroots utility for tracking the cursor * image shown on screen. @@ -2561,7 +2664,7 @@ unmaplayersurfacenotify(struct wl_listener *listener, void *data) arrangelayers(l->mon); if (l->layer_surface->surface == seat->keyboard_state.focused_surface) focusclient(focustop(selmon), 1); - motionnotify(0); + motionnotify(0, NULL, 0, 0, 0, 0); } void @@ -2587,7 +2690,7 @@ unmapnotify(struct wl_listener *listener, void *data) wlr_scene_node_destroy(&c->scene->node); printstatus(); - motionnotify(0); + motionnotify(0, NULL, 0, 0, 0, 0); } void -- cgit v1.2.3 From 2b171fd5010379a8674afa012245fea5a590e472 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Mon, 11 Mar 2024 19:01:13 +0100 Subject: fix virtual pointers When motionabsolute() is called from warpd, event->time_msec is 0, so motionnotify() doesn't call wlr_cursor_move(). Fix this by explicitly warping the cursor in this case, like it was done before implementing pointer constraints. I don't know if this is a bug in warpd or time_msec is always 0 with virtual pointers, since the only other software that uses the virtual pointer protocol I know of is wl-kbptr, and I can't get that to work with dwl at all. --- dwl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dwl.c b/dwl.c index d508d79..5867b0c 100644 --- a/dwl.c +++ b/dwl.c @@ -1675,6 +1675,9 @@ motionabsolute(struct wl_listener *listener, void *data) struct wlr_pointer_motion_absolute_event *event = data; double lx, ly, dx, dy; + if (!event->time_msec) /* this is 0 with virtual pointers */ + wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x, event->y); + wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, event->y, &lx, &ly); dx = lx - cursor->x; dy = ly - cursor->y; -- cgit v1.2.3 From 3a95d4ed03bb506658382f1c5dc4e3d002a90464 Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Tue, 26 Mar 2024 20:00:46 -0500 Subject: Fix rule examples; minimize newbie surprises Make example rules be actual EXAMPLES. Now newcomers should not have to ask, "When I start firefox, nothing happens. What is going on?" Also clarified a minor typo and a consistency in spacing. --- config.def.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config.def.h b/config.def.h index 9009517..8847e58 100644 --- a/config.def.h +++ b/config.def.h @@ -11,7 +11,7 @@ static const float rootcolor[] = COLOR(0x222222ff); static const float bordercolor[] = COLOR(0x444444ff); static const float focuscolor[] = COLOR(0x005577ff); static const float urgentcolor[] = COLOR(0xff0000ff); -/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */ +/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ /* tagging - TAGCOUNT must be no greater than 31 */ @@ -21,11 +21,10 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca static int log_level = WLR_ERROR; static const Rule rules[] = { - /* app_id title tags mask isfloating monitor */ - /* examples: - { "Gimp", NULL, 0, 1, -1 }, - */ - { "firefox", NULL, 1 << 8, 0, -1 }, + /* app_id title tags mask isfloating monitor */ + /* examples: */ + { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ + { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ }; /* layout(s) */ @@ -95,6 +94,7 @@ LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE */ static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; static const double accel_speed = 0.0; + /* You can choose between: LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right -- cgit v1.2.3 From f7154d539d09b4aa5b92371c296d9aa7a045bac0 Mon Sep 17 00:00:00 2001 From: korei999 Date: Sun, 24 Mar 2024 12:54:32 +0200 Subject: properly resize on configurex11 --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 5867b0c..39ce68c 100644 --- a/dwl.c +++ b/dwl.c @@ -2962,7 +2962,7 @@ configurex11(struct wl_listener *listener, void *data) } if (c->isfloating || client_is_unmanaged(c)) resize(c, (struct wlr_box){.x = event->x, .y = event->y, - .width = event->width, .height = event->height}, 0); + .width = event->width + c->bw * 2, .height = event->height + c->bw * 2}, 0); else arrange(c->mon); } -- cgit v1.2.3 From dd00d994ce4c53829d0b871622dc05e90a6f58c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sun, 31 Mar 2024 21:41:12 -0600 Subject: do not set withdrawn state for xwayland clients Closes: https://codeberg.org/dwl/dwl/issues/573 --- client.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client.h b/client.h index fe9dffc..800b867 100644 --- a/client.h +++ b/client.h @@ -379,10 +379,8 @@ static inline void client_set_suspended(Client *c, int suspended) { #ifdef XWAYLAND - if (client_is_x11(c)) { - wlr_xwayland_surface_set_withdrawn(c->surface.xwayland, suspended); + if (client_is_x11(c)) return; - } #endif wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended); -- cgit v1.2.3 From 577d8da6d17dad5f847795582ebf813f3c5c04a7 Mon Sep 17 00:00:00 2001 From: choc Date: Thu, 4 Apr 2024 18:48:16 +0800 Subject: put wlr_layer_shell top layer below fullscreen fixes wlr_layer_shell top clients showing over fullscreen clients --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 39ce68c..bf763df 100644 --- a/dwl.c +++ b/dwl.c @@ -81,7 +81,7 @@ /* enums */ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ enum { XDGShell, LayerShell, X11 }; /* client types */ -enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrFS, LyrTop, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ +enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ #ifdef XWAYLAND enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ -- cgit v1.2.3