mirror of
https://codeberg.org/dwl/dwl-patches.git
synced 2026-06-20 15:02:45 +00:00
Compare commits
15 Commits
39f54a89fa
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d8046ab6ec | |||
| 0935f95e01 | |||
| e2ba7017ea | |||
| 493dc4c408 | |||
| 33acb045a8 | |||
| bbe1199e40 | |||
| 1f0e82bf5d | |||
| 5483e1d437 | |||
| 30c33ed26c | |||
| 03de6e2ada | |||
| 7f06b4c1a3 | |||
| d7471ef29e | |||
| 5d2f27a9f9 | |||
| 2bfdd50f98 | |||
| ea5c2c7439 |
@@ -4,7 +4,7 @@
|
||||
|
||||
It provides a focus-driven, mouse- and keyboard-friendly tiling layout that grants you granular control over how clients are placed and resized.
|
||||
|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
From f5d7fe287bd4405879a92d649243d3f646652617 Mon Sep 17 00:00:00 2001
|
||||
From 1520d1f200ef0fb381683c1bcd58e553b52ac289 Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Thu, 19 Mar 2026 00:08:10 +0200
|
||||
Subject: [PATCH] Refactor btrtile-gaps to v0.8
|
||||
Date: Thu, 21 May 2026 00:42:07 +0300
|
||||
Subject: [PATCH] btrtile: Spring update pt2
|
||||
|
||||
- Simplified the resizing logic to avoid full arrange calls from
|
||||
motionnotify
|
||||
- Minor intend fixes
|
||||
---
|
||||
btrtile.c | 584 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
btrtile.c | 583 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
config.def.h | 12 ++
|
||||
dwl.c | 148 ++++++++++---
|
||||
3 files changed, 717 insertions(+), 27 deletions(-)
|
||||
dwl.c | 152 +++++++++++---
|
||||
3 files changed, 720 insertions(+), 27 deletions(-)
|
||||
create mode 100644 btrtile.c
|
||||
|
||||
diff --git a/btrtile.c b/btrtile.c
|
||||
new file mode 100644
|
||||
index 0000000..afe3c8f
|
||||
index 0000000..f05a30f
|
||||
--- /dev/null
|
||||
+++ b/btrtile.c
|
||||
@@ -0,0 +1,584 @@
|
||||
@@ -0,0 +1,583 @@
|
||||
+/* ************************************************************************** */
|
||||
+/* @@@ @@@@@@@@ */
|
||||
+/* @@@ @@@@@@@@@@ */
|
||||
@@ -26,7 +29,7 @@ index 0000000..afe3c8f
|
||||
+/* By: julmajustus <julmajustus@tutanota.com> !!: !!:! !!! */
|
||||
+/* ::! :!: !:! */
|
||||
+/* Created: 2024/12/15 00:26:07 by julmajustus :: ::::::: :: */
|
||||
+/* Updated: 2026/03/19 00:07:19 by julmajustus : : : : : : */
|
||||
+/* Updated: 2026/05/20 22:38:02 by julmajustus : : : : : : */
|
||||
+/* */
|
||||
+/* ************************************************************************** */
|
||||
+
|
||||
@@ -49,7 +52,8 @@ index 0000000..afe3c8f
|
||||
+static void destroy_node(LayoutNode *node);
|
||||
+static void destroy_tree(Monitor *m);
|
||||
+static LayoutNode *find_client_node(LayoutNode *node, Client *c);
|
||||
+static LayoutNode *find_suitable_split(LayoutNode *start, unsigned int need_vert);
|
||||
+static LayoutNode *find_suitable_split(Monitor *m, LayoutNode *start,
|
||||
+ unsigned int need_vertical, int focused_on_left);
|
||||
+static void init_tree(Monitor *m);
|
||||
+static void insert_client(Monitor *m, Client *focused_client, Client *new_client);
|
||||
+static LayoutNode *remove_client_node(LayoutNode *node, Client *c);
|
||||
@@ -60,7 +64,6 @@ index 0000000..afe3c8f
|
||||
+static unsigned int visible_count(LayoutNode *node, Monitor *m);
|
||||
+static Client *xytoclient(double x, double y);
|
||||
+
|
||||
+static int resizing_from_mouse = 0;
|
||||
+static double resize_last_update_x, resize_last_update_y;
|
||||
+static uint32_t last_resize_time = 0;
|
||||
+
|
||||
@@ -88,6 +91,9 @@ index 0000000..afe3c8f
|
||||
+ c = node->client;
|
||||
+ if (!c || !VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ return;
|
||||
+ if (area.x == c->old_geom.x && area.y == c->old_geom.y &&
|
||||
+ area.width == c->old_geom.width && area.height == c->old_geom.height)
|
||||
+ return;
|
||||
+ resize(c, area, 0);
|
||||
+ c->old_geom = area;
|
||||
+ return;
|
||||
@@ -166,7 +172,7 @@ index 0000000..afe3c8f
|
||||
+ LayoutNode *found;
|
||||
+ struct wlr_box full_area;
|
||||
+
|
||||
+ if (!m || !m->root)
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ /* Remove non tiled clients from tree. */
|
||||
@@ -268,29 +274,36 @@ index 0000000..afe3c8f
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+find_suitable_split(LayoutNode *start_node, unsigned int need_vertical)
|
||||
+find_suitable_split(Monitor *m, LayoutNode *start_node,
|
||||
+ unsigned int need_vertical, int focused_on_left)
|
||||
+{
|
||||
+ LayoutNode *n = start_node;
|
||||
+ /* if we started from a client node, jump to its parent: */
|
||||
+ if (n && n->is_client_node)
|
||||
+ LayoutNode *n = start_node, *child = NULL;
|
||||
+
|
||||
+ if (!m)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (n && n->is_client_node) {
|
||||
+ child = n;
|
||||
+ n = n->split_node;
|
||||
+ }
|
||||
+
|
||||
+ while (n) {
|
||||
+ if (!n->is_client_node && n->is_split_vertically == need_vertical &&
|
||||
+ visible_count(n->left, selmon) > 0 && visible_count(n->right, selmon) > 0)
|
||||
+ if (!n->is_client_node && n->is_split_vertically == need_vertical
|
||||
+ && visible_count(n->left, m) > 0
|
||||
+ && visible_count(n->right, m) > 0) {
|
||||
+ if ((focused_on_left && n->left == child) ||
|
||||
+ (!focused_on_left && n->right == child))
|
||||
+ return n;
|
||||
+ }
|
||||
+ child = n;
|
||||
+ n = n->split_node;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+init_tree(Monitor *m)
|
||||
+{
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+ m->root = calloc(1, sizeof(LayoutNode));
|
||||
+ if (!m->root)
|
||||
+ if (m)
|
||||
+ m->root = NULL;
|
||||
+}
|
||||
+
|
||||
@@ -415,21 +428,31 @@ index 0000000..afe3c8f
|
||||
+ m->root = remove_client_node(m->root, c);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_h(const Arg *arg)
|
||||
+static void
|
||||
+setratio(unsigned int need_vertical, const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ Client *sel;
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+ int focused_on_left;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ if (!selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ sel = focustop(selmon);
|
||||
+ if (!sel)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 1);
|
||||
+ focused_on_left = (arg->f >= 0.0f);
|
||||
+
|
||||
+ split_node = find_suitable_split(selmon, client_node, need_vertical, focused_on_left);
|
||||
+
|
||||
+ if (!split_node)
|
||||
+ split_node = find_suitable_split(selmon, client_node, need_vertical, !focused_on_left);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
@@ -440,43 +463,21 @@ index 0000000..afe3c8f
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+ apply_layout(selmon, selmon->root, selmon->w, 1);
|
||||
+ /* Skip the arrange when called from motionnotify; that path calls
|
||||
+ * arrange itself after rate-limiting. */
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_h(const Arg *arg)
|
||||
+{
|
||||
+ setratio(1, arg);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_v(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 0);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
+ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f;
|
||||
+ if (new_ratio < 0.05f)
|
||||
+ new_ratio = 0.05f;
|
||||
+ if (new_ratio > 0.95f)
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+ setratio(0, arg);
|
||||
+}
|
||||
+
|
||||
+void swapclients(const Arg *arg) {
|
||||
@@ -565,11 +566,12 @@ index 0000000..afe3c8f
|
||||
+
|
||||
+Client *
|
||||
+xytoclient(double x, double y) {
|
||||
+ Monitor *m = xytomon(x, y);
|
||||
+ Client *c, *closest = NULL;
|
||||
+ double dist, mindist = INT_MAX, dx, dy;
|
||||
+
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen &&
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen &&
|
||||
+ x >= c->geom.x && x <= (c->geom.x + c->geom.width) &&
|
||||
+ y >= c->geom.y && y <= (c->geom.y + c->geom.height)){
|
||||
+ return c;
|
||||
@@ -578,7 +580,7 @@ index 0000000..afe3c8f
|
||||
+
|
||||
+ /* If no client was found at cursor position fallback to closest. */
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen) {
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) {
|
||||
+ dx = 0, dy = 0;
|
||||
+
|
||||
+ if (x < c->geom.x)
|
||||
@@ -591,7 +593,7 @@ index 0000000..afe3c8f
|
||||
+ else if (y > (c->geom.y + c->geom.height))
|
||||
+ dy = y - (c->geom.y + c->geom.height);
|
||||
+
|
||||
+ dist = sqrt(dx * dx + dy * dy);
|
||||
+ dist = dx * dx + dy * dy;
|
||||
+ if (dist < mindist) {
|
||||
+ mindist = dist;
|
||||
+ closest = c;
|
||||
@@ -639,7 +641,7 @@ index 8a6eda0..bc04e3f 100644
|
||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 44f3ad9..f74d9a1 100644
|
||||
index 44f3ad9..a121efc 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1,6 +1,7 @@
|
||||
@@ -721,7 +723,7 @@ index 44f3ad9..f74d9a1 100644
|
||||
b->func(&b->arg);
|
||||
return;
|
||||
}
|
||||
@@ -655,6 +664,27 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
@@ -655,6 +664,21 @@ 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) {
|
||||
@@ -736,20 +738,14 @@ index 44f3ad9..f74d9a1 100644
|
||||
+ selmon->root = create_client_node(c);
|
||||
+
|
||||
+ setfloating(c, 0);
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ } else if (cursor_mode == CurResize && !c->isfloating) {
|
||||
+ resizing_from_mouse = 0;
|
||||
+ apply_layout(selmon, selmon->root, selmon->w, 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (cursor_mode == CurResize && resizing_from_mouse)
|
||||
+ resizing_from_mouse = 0;
|
||||
+ }
|
||||
+ /* Default behaviour */
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
cursor_mode = CurNormal;
|
||||
/* Drop the window off on its new monitor */
|
||||
@@ -746,6 +776,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
@@ -746,6 +770,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
wlr_output_layout_remove(output_layout, m->wlr_output);
|
||||
wlr_scene_output_destroy(m->scene_output);
|
||||
|
||||
@@ -757,7 +753,7 @@ index 44f3ad9..f74d9a1 100644
|
||||
closemon(m);
|
||||
wlr_scene_node_destroy(&m->fullscreen_bg->node);
|
||||
free(m);
|
||||
@@ -1090,6 +1121,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
@@ -1090,6 +1115,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
|
||||
wl_list_insert(&mons, &m->link);
|
||||
printstatus();
|
||||
@@ -765,18 +761,25 @@ index 44f3ad9..f74d9a1 100644
|
||||
|
||||
/* The xdg-protocol specifies:
|
||||
*
|
||||
@@ -1332,6 +1364,10 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
@@ -1329,9 +1355,17 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
Client *c = wl_container_of(listener, c, destroy);
|
||||
+ Monitor *mon;
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
+ /* We check if the destroyed client was part of any tiled_list, to catch
|
||||
+ * client removals even if they would not be currently managed by btrtile */
|
||||
+ if (selmon && selmon->root)
|
||||
+ remove_client(selmon, c);
|
||||
+ wl_list_for_each(mon, &mons, link) {
|
||||
+ if (mon->root) {
|
||||
+ remove_client(mon, c);
|
||||
+ }
|
||||
+ }
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->activate.link);
|
||||
@@ -1862,7 +1898,8 @@ void
|
||||
@@ -1862,7 +1896,8 @@ void
|
||||
motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy,
|
||||
double dx_unaccel, double dy_unaccel)
|
||||
{
|
||||
@@ -786,13 +789,13 @@ index 44f3ad9..f74d9a1 100644
|
||||
Client *c = NULL, *w = NULL;
|
||||
LayerSurface *l = NULL;
|
||||
struct wlr_surface *surface = NULL;
|
||||
@@ -1916,18 +1953,56 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
@@ -1916,18 +1951,55 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
/* Update drag icon's position */
|
||||
wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y));
|
||||
|
||||
- /* If we are currently grabbing the mouse, handle and return */
|
||||
+ /* Skip if internal call or already resizing */
|
||||
+ if (time == 0 && resizing_from_mouse)
|
||||
+ /* Skip if internal call */
|
||||
+ if (time == 0)
|
||||
+ goto focus;
|
||||
+
|
||||
+ tiled = grabc && !grabc->isfloating && !grabc->isfullscreen;
|
||||
@@ -814,7 +817,7 @@ index 44f3ad9..f74d9a1 100644
|
||||
- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
|
||||
- return;
|
||||
+ if (tiled && resizing_from_mouse) {
|
||||
+ if (tiled) {
|
||||
+ dx_total = cursor->x - resize_last_update_x;
|
||||
+ dy_total = cursor->y - resize_last_update_y;
|
||||
+
|
||||
@@ -827,7 +830,6 @@ index 44f3ad9..f74d9a1 100644
|
||||
+ a.f = (float)(dy_total * resize_factor);
|
||||
+ setratio_v(&a);
|
||||
+ }
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ last_resize_time = time;
|
||||
+ resize_last_update_x = cursor->x;
|
||||
@@ -850,7 +852,7 @@ index 44f3ad9..f74d9a1 100644
|
||||
/* 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. */
|
||||
@@ -1961,22 +2036,41 @@ moveresize(const Arg *arg)
|
||||
@@ -1961,22 +2033,40 @@ moveresize(const Arg *arg)
|
||||
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
|
||||
return;
|
||||
|
||||
@@ -885,7 +887,6 @@ index 44f3ad9..f74d9a1 100644
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
+ resize_last_update_x = cursor->x;
|
||||
+ resize_last_update_y = cursor->y;
|
||||
+ resizing_from_mouse = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
@@ -908,6 +909,21 @@ index 44f3ad9..f74d9a1 100644
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2826,6 +2916,14 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
focusclient(focustop(selmon), 1);
|
||||
}
|
||||
} else {
|
||||
+ /* btrtile remove clients for each monitor */
|
||||
+ Monitor *mon;
|
||||
+ wl_list_for_each(mon, &mons, link) {
|
||||
+ if (mon->root) {
|
||||
+ remove_client(mon, c);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
wl_list_remove(&c->link);
|
||||
setmon(c, NULL, 0);
|
||||
wl_list_remove(&c->flink);
|
||||
--
|
||||
2.52.0
|
||||
2.53.0
|
||||
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
From 1b75163aac16942a715c6fc0aaf5d508e778dd6a Mon Sep 17 00:00:00 2001
|
||||
From 618e3b70204520b6eb2c5040e072087ac0a3b3f7 Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Wed, 18 Mar 2026 20:23:00 +0200
|
||||
Subject: [PATCH] Refactor btrtile for v0.8
|
||||
Date: Thu, 21 May 2026 00:40:54 +0300
|
||||
Subject: [PATCH] btrtile: Spring update pt2
|
||||
|
||||
- Simplified the resizing logic to avoid full arrange calls from
|
||||
motionnotify
|
||||
- Minor intend fixes
|
||||
---
|
||||
btrtile.c | 565 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
btrtile.c | 564 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
config.def.h | 12 ++
|
||||
dwl.c | 148 +++++++++++---
|
||||
3 files changed, 698 insertions(+), 27 deletions(-)
|
||||
dwl.c | 152 +++++++++++---
|
||||
3 files changed, 701 insertions(+), 27 deletions(-)
|
||||
create mode 100644 btrtile.c
|
||||
|
||||
diff --git a/btrtile.c b/btrtile.c
|
||||
new file mode 100644
|
||||
index 0000000..d706c3b
|
||||
index 0000000..357ffb9
|
||||
--- /dev/null
|
||||
+++ b/btrtile.c
|
||||
@@ -0,0 +1,565 @@
|
||||
@@ -0,0 +1,564 @@
|
||||
+/* ************************************************************************** */
|
||||
+/* @@@ @@@@@@@@ */
|
||||
+/* @@@ @@@@@@@@@@ */
|
||||
@@ -26,7 +29,7 @@ index 0000000..d706c3b
|
||||
+/* By: julmajustus <julmajustus@tutanota.com> !!: !!:! !!! */
|
||||
+/* ::! :!: !:! */
|
||||
+/* Created: 2024/12/15 00:26:07 by julmajustus :: ::::::: :: */
|
||||
+/* Updated: 2026/03/18 20:26:17 by julmajustus : : : : : : */
|
||||
+/* Updated: 2026/05/20 22:51:54 by julmajustus : : : : : : */
|
||||
+/* */
|
||||
+/* ************************************************************************** */
|
||||
+
|
||||
@@ -49,7 +52,8 @@ index 0000000..d706c3b
|
||||
+static void destroy_node(LayoutNode *node);
|
||||
+static void destroy_tree(Monitor *m);
|
||||
+static LayoutNode *find_client_node(LayoutNode *node, Client *c);
|
||||
+static LayoutNode *find_suitable_split(LayoutNode *start, unsigned int need_vert);
|
||||
+static LayoutNode *find_suitable_split(Monitor *m, LayoutNode *start,
|
||||
+ unsigned int need_vertical, int focused_on_left);
|
||||
+static void init_tree(Monitor *m);
|
||||
+static void insert_client(Monitor *m, Client *focused_client, Client *new_client);
|
||||
+static LayoutNode *remove_client_node(LayoutNode *node, Client *c);
|
||||
@@ -60,7 +64,6 @@ index 0000000..d706c3b
|
||||
+static unsigned int visible_count(LayoutNode *node, Monitor *m);
|
||||
+static Client *xytoclient(double x, double y);
|
||||
+
|
||||
+static int resizing_from_mouse = 0;
|
||||
+static double resize_last_update_x, resize_last_update_y;
|
||||
+static uint32_t last_resize_time = 0;
|
||||
+
|
||||
@@ -81,6 +84,9 @@ index 0000000..d706c3b
|
||||
+ c = node->client;
|
||||
+ if (!c || !VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ return;
|
||||
+ if (area.x == c->old_geom.x && area.y == c->old_geom.y &&
|
||||
+ area.width == c->old_geom.width && area.height == c->old_geom.height)
|
||||
+ return;
|
||||
+ resize(c, area, 0);
|
||||
+ c->old_geom = area;
|
||||
+ return;
|
||||
@@ -147,7 +153,7 @@ index 0000000..d706c3b
|
||||
+ LayoutNode *found;
|
||||
+ struct wlr_box full_area;
|
||||
+
|
||||
+ if (!m || !m->root)
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ /* Remove non tiled clients from tree. */
|
||||
@@ -249,29 +255,36 @@ index 0000000..d706c3b
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+find_suitable_split(LayoutNode *start_node, unsigned int need_vertical)
|
||||
+find_suitable_split(Monitor *m, LayoutNode *start_node,
|
||||
+ unsigned int need_vertical, int focused_on_left)
|
||||
+{
|
||||
+ LayoutNode *n = start_node;
|
||||
+ /* if we started from a client node, jump to its parent: */
|
||||
+ if (n && n->is_client_node)
|
||||
+ LayoutNode *n = start_node, *child = NULL;
|
||||
+
|
||||
+ if (!m)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (n && n->is_client_node) {
|
||||
+ child = n;
|
||||
+ n = n->split_node;
|
||||
+ }
|
||||
+
|
||||
+ while (n) {
|
||||
+ if (!n->is_client_node && n->is_split_vertically == need_vertical &&
|
||||
+ visible_count(n->left, selmon) > 0 && visible_count(n->right, selmon) > 0)
|
||||
+ if (!n->is_client_node && n->is_split_vertically == need_vertical
|
||||
+ && visible_count(n->left, m) > 0
|
||||
+ && visible_count(n->right, m) > 0) {
|
||||
+ if ((focused_on_left && n->left == child) ||
|
||||
+ (!focused_on_left && n->right == child))
|
||||
+ return n;
|
||||
+ }
|
||||
+ child = n;
|
||||
+ n = n->split_node;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+init_tree(Monitor *m)
|
||||
+{
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+ m->root = calloc(1, sizeof(LayoutNode));
|
||||
+ if (!m->root)
|
||||
+ if (m)
|
||||
+ m->root = NULL;
|
||||
+}
|
||||
+
|
||||
@@ -396,21 +409,31 @@ index 0000000..d706c3b
|
||||
+ m->root = remove_client_node(m->root, c);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_h(const Arg *arg)
|
||||
+static void
|
||||
+setratio(unsigned int need_vertical, const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ Client *sel;
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+ int focused_on_left;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ if (!selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ sel = focustop(selmon);
|
||||
+ if (!sel)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 1);
|
||||
+ focused_on_left = (arg->f >= 0.0f);
|
||||
+
|
||||
+ split_node = find_suitable_split(selmon, client_node, need_vertical, focused_on_left);
|
||||
+
|
||||
+ if (!split_node)
|
||||
+ split_node = find_suitable_split(selmon, client_node, need_vertical, !focused_on_left);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
@@ -421,43 +444,21 @@ index 0000000..d706c3b
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+ apply_layout(selmon, selmon->root, selmon->w, 1);
|
||||
+ /* Skip the arrange when called from motionnotify; that path calls
|
||||
+ * arrange itself after rate-limiting. */
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_h(const Arg *arg)
|
||||
+{
|
||||
+ setratio(1, arg);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_v(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 0);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
+ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f;
|
||||
+ if (new_ratio < 0.05f)
|
||||
+ new_ratio = 0.05f;
|
||||
+ if (new_ratio > 0.95f)
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+ setratio(0, arg);
|
||||
+}
|
||||
+
|
||||
+void swapclients(const Arg *arg) {
|
||||
@@ -546,11 +547,12 @@ index 0000000..d706c3b
|
||||
+
|
||||
+Client *
|
||||
+xytoclient(double x, double y) {
|
||||
+ Monitor *m = xytomon(x, y);
|
||||
+ Client *c, *closest = NULL;
|
||||
+ double dist, mindist = INT_MAX, dx, dy;
|
||||
+
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen &&
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen &&
|
||||
+ x >= c->geom.x && x <= (c->geom.x + c->geom.width) &&
|
||||
+ y >= c->geom.y && y <= (c->geom.y + c->geom.height)){
|
||||
+ return c;
|
||||
@@ -559,7 +561,7 @@ index 0000000..d706c3b
|
||||
+
|
||||
+ /* If no client was found at cursor position fallback to closest. */
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen) {
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) {
|
||||
+ dx = 0, dy = 0;
|
||||
+
|
||||
+ if (x < c->geom.x)
|
||||
@@ -572,7 +574,7 @@ index 0000000..d706c3b
|
||||
+ else if (y > (c->geom.y + c->geom.height))
|
||||
+ dy = y - (c->geom.y + c->geom.height);
|
||||
+
|
||||
+ dist = sqrt(dx * dx + dy * dy);
|
||||
+ dist = dx * dx + dy * dy;
|
||||
+ if (dist < mindist) {
|
||||
+ mindist = dist;
|
||||
+ closest = c;
|
||||
@@ -620,7 +622,7 @@ index 8a6eda0..bc04e3f 100644
|
||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 44f3ad9..f74d9a1 100644
|
||||
index 44f3ad9..a121efc 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1,6 +1,7 @@
|
||||
@@ -702,7 +704,7 @@ index 44f3ad9..f74d9a1 100644
|
||||
b->func(&b->arg);
|
||||
return;
|
||||
}
|
||||
@@ -655,6 +664,27 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
@@ -655,6 +664,21 @@ 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) {
|
||||
@@ -717,20 +719,14 @@ index 44f3ad9..f74d9a1 100644
|
||||
+ selmon->root = create_client_node(c);
|
||||
+
|
||||
+ setfloating(c, 0);
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ } else if (cursor_mode == CurResize && !c->isfloating) {
|
||||
+ resizing_from_mouse = 0;
|
||||
+ apply_layout(selmon, selmon->root, selmon->w, 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (cursor_mode == CurResize && resizing_from_mouse)
|
||||
+ resizing_from_mouse = 0;
|
||||
+ }
|
||||
+ /* Default behaviour */
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
cursor_mode = CurNormal;
|
||||
/* Drop the window off on its new monitor */
|
||||
@@ -746,6 +776,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
@@ -746,6 +770,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
wlr_output_layout_remove(output_layout, m->wlr_output);
|
||||
wlr_scene_output_destroy(m->scene_output);
|
||||
|
||||
@@ -738,7 +734,7 @@ index 44f3ad9..f74d9a1 100644
|
||||
closemon(m);
|
||||
wlr_scene_node_destroy(&m->fullscreen_bg->node);
|
||||
free(m);
|
||||
@@ -1090,6 +1121,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
@@ -1090,6 +1115,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
|
||||
wl_list_insert(&mons, &m->link);
|
||||
printstatus();
|
||||
@@ -746,18 +742,25 @@ index 44f3ad9..f74d9a1 100644
|
||||
|
||||
/* The xdg-protocol specifies:
|
||||
*
|
||||
@@ -1332,6 +1364,10 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
@@ -1329,9 +1355,17 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
Client *c = wl_container_of(listener, c, destroy);
|
||||
+ Monitor *mon;
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
+ /* We check if the destroyed client was part of any tiled_list, to catch
|
||||
+ * client removals even if they would not be currently managed by btrtile */
|
||||
+ if (selmon && selmon->root)
|
||||
+ remove_client(selmon, c);
|
||||
+ wl_list_for_each(mon, &mons, link) {
|
||||
+ if (mon->root) {
|
||||
+ remove_client(mon, c);
|
||||
+ }
|
||||
+ }
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->activate.link);
|
||||
@@ -1862,7 +1898,8 @@ void
|
||||
@@ -1862,7 +1896,8 @@ void
|
||||
motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy,
|
||||
double dx_unaccel, double dy_unaccel)
|
||||
{
|
||||
@@ -767,13 +770,13 @@ index 44f3ad9..f74d9a1 100644
|
||||
Client *c = NULL, *w = NULL;
|
||||
LayerSurface *l = NULL;
|
||||
struct wlr_surface *surface = NULL;
|
||||
@@ -1916,18 +1953,56 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
@@ -1916,18 +1951,55 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
/* Update drag icon's position */
|
||||
wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y));
|
||||
|
||||
- /* If we are currently grabbing the mouse, handle and return */
|
||||
+ /* Skip if internal call or already resizing */
|
||||
+ if (time == 0 && resizing_from_mouse)
|
||||
+ /* Skip if internal call */
|
||||
+ if (time == 0)
|
||||
+ goto focus;
|
||||
+
|
||||
+ tiled = grabc && !grabc->isfloating && !grabc->isfullscreen;
|
||||
@@ -795,7 +798,7 @@ index 44f3ad9..f74d9a1 100644
|
||||
- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
|
||||
- return;
|
||||
+ if (tiled && resizing_from_mouse) {
|
||||
+ if (tiled) {
|
||||
+ dx_total = cursor->x - resize_last_update_x;
|
||||
+ dy_total = cursor->y - resize_last_update_y;
|
||||
+
|
||||
@@ -808,7 +811,6 @@ index 44f3ad9..f74d9a1 100644
|
||||
+ a.f = (float)(dy_total * resize_factor);
|
||||
+ setratio_v(&a);
|
||||
+ }
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ last_resize_time = time;
|
||||
+ resize_last_update_x = cursor->x;
|
||||
@@ -831,7 +833,7 @@ index 44f3ad9..f74d9a1 100644
|
||||
/* 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. */
|
||||
@@ -1961,22 +2036,41 @@ moveresize(const Arg *arg)
|
||||
@@ -1961,22 +2033,40 @@ moveresize(const Arg *arg)
|
||||
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
|
||||
return;
|
||||
|
||||
@@ -866,7 +868,6 @@ index 44f3ad9..f74d9a1 100644
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
+ resize_last_update_x = cursor->x;
|
||||
+ resize_last_update_y = cursor->y;
|
||||
+ resizing_from_mouse = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
@@ -889,6 +890,21 @@ index 44f3ad9..f74d9a1 100644
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2826,6 +2916,14 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
focusclient(focustop(selmon), 1);
|
||||
}
|
||||
} else {
|
||||
+ /* btrtile remove clients for each monitor */
|
||||
+ Monitor *mon;
|
||||
+ wl_list_for_each(mon, &mons, link) {
|
||||
+ if (mon->root) {
|
||||
+ remove_client(mon, c);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
wl_list_remove(&c->link);
|
||||
setmon(c, NULL, 0);
|
||||
wl_list_remove(&c->flink);
|
||||
--
|
||||
2.52.0
|
||||
2.53.0
|
||||
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
From a9329abe48083a4c5b64eee726ceefdb4bf0bb9f Mon Sep 17 00:00:00 2001
|
||||
From c11b1a8c93c27fad3782e9dbc1b094a4a7b78088 Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Thu, 19 Mar 2026 22:59:49 +0200
|
||||
Subject: [PATCH] Refactor btrtile-gaps to wlroots-next
|
||||
Date: Thu, 21 May 2026 00:38:45 +0300
|
||||
Subject: [PATCH] btrtile: Spring update pt2
|
||||
|
||||
- Simplified the resizing logic to avoid full arrange calls from
|
||||
motionnotify
|
||||
- Minor intend fixes
|
||||
---
|
||||
btrtile.c | 584 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
btrtile.c | 583 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
config.def.h | 12 ++
|
||||
dwl.c | 148 ++++++++++---
|
||||
3 files changed, 717 insertions(+), 27 deletions(-)
|
||||
dwl.c | 152 +++++++++++---
|
||||
3 files changed, 720 insertions(+), 27 deletions(-)
|
||||
create mode 100644 btrtile.c
|
||||
|
||||
diff --git a/btrtile.c b/btrtile.c
|
||||
new file mode 100644
|
||||
index 0000000..8703617
|
||||
index 0000000..f05a30f
|
||||
--- /dev/null
|
||||
+++ b/btrtile.c
|
||||
@@ -0,0 +1,584 @@
|
||||
@@ -0,0 +1,583 @@
|
||||
+/* ************************************************************************** */
|
||||
+/* @@@ @@@@@@@@ */
|
||||
+/* @@@ @@@@@@@@@@ */
|
||||
@@ -26,7 +29,7 @@ index 0000000..8703617
|
||||
+/* By: julmajustus <julmajustus@tutanota.com> !!: !!:! !!! */
|
||||
+/* ::! :!: !:! */
|
||||
+/* Created: 2024/12/15 00:26:07 by julmajustus :: ::::::: :: */
|
||||
+/* Updated: 2026/03/19 22:59:12 by julmajustus : : : : : : */
|
||||
+/* Updated: 2026/05/20 22:38:02 by julmajustus : : : : : : */
|
||||
+/* */
|
||||
+/* ************************************************************************** */
|
||||
+
|
||||
@@ -49,7 +52,8 @@ index 0000000..8703617
|
||||
+static void destroy_node(LayoutNode *node);
|
||||
+static void destroy_tree(Monitor *m);
|
||||
+static LayoutNode *find_client_node(LayoutNode *node, Client *c);
|
||||
+static LayoutNode *find_suitable_split(LayoutNode *start, unsigned int need_vert);
|
||||
+static LayoutNode *find_suitable_split(Monitor *m, LayoutNode *start,
|
||||
+ unsigned int need_vertical, int focused_on_left);
|
||||
+static void init_tree(Monitor *m);
|
||||
+static void insert_client(Monitor *m, Client *focused_client, Client *new_client);
|
||||
+static LayoutNode *remove_client_node(LayoutNode *node, Client *c);
|
||||
@@ -60,7 +64,6 @@ index 0000000..8703617
|
||||
+static unsigned int visible_count(LayoutNode *node, Monitor *m);
|
||||
+static Client *xytoclient(double x, double y);
|
||||
+
|
||||
+static int resizing_from_mouse = 0;
|
||||
+static double resize_last_update_x, resize_last_update_y;
|
||||
+static uint32_t last_resize_time = 0;
|
||||
+
|
||||
@@ -88,6 +91,9 @@ index 0000000..8703617
|
||||
+ c = node->client;
|
||||
+ if (!c || !VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ return;
|
||||
+ if (area.x == c->old_geom.x && area.y == c->old_geom.y &&
|
||||
+ area.width == c->old_geom.width && area.height == c->old_geom.height)
|
||||
+ return;
|
||||
+ resize(c, area, 0);
|
||||
+ c->old_geom = area;
|
||||
+ return;
|
||||
@@ -166,7 +172,7 @@ index 0000000..8703617
|
||||
+ LayoutNode *found;
|
||||
+ struct wlr_box full_area;
|
||||
+
|
||||
+ if (!m || !m->root)
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ /* Remove non tiled clients from tree. */
|
||||
@@ -268,29 +274,36 @@ index 0000000..8703617
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+find_suitable_split(LayoutNode *start_node, unsigned int need_vertical)
|
||||
+find_suitable_split(Monitor *m, LayoutNode *start_node,
|
||||
+ unsigned int need_vertical, int focused_on_left)
|
||||
+{
|
||||
+ LayoutNode *n = start_node;
|
||||
+ /* if we started from a client node, jump to its parent: */
|
||||
+ if (n && n->is_client_node)
|
||||
+ LayoutNode *n = start_node, *child = NULL;
|
||||
+
|
||||
+ if (!m)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (n && n->is_client_node) {
|
||||
+ child = n;
|
||||
+ n = n->split_node;
|
||||
+ }
|
||||
+
|
||||
+ while (n) {
|
||||
+ if (!n->is_client_node && n->is_split_vertically == need_vertical &&
|
||||
+ visible_count(n->left, selmon) > 0 && visible_count(n->right, selmon) > 0)
|
||||
+ if (!n->is_client_node && n->is_split_vertically == need_vertical
|
||||
+ && visible_count(n->left, m) > 0
|
||||
+ && visible_count(n->right, m) > 0) {
|
||||
+ if ((focused_on_left && n->left == child) ||
|
||||
+ (!focused_on_left && n->right == child))
|
||||
+ return n;
|
||||
+ }
|
||||
+ child = n;
|
||||
+ n = n->split_node;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+init_tree(Monitor *m)
|
||||
+{
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+ m->root = calloc(1, sizeof(LayoutNode));
|
||||
+ if (!m->root)
|
||||
+ if (m)
|
||||
+ m->root = NULL;
|
||||
+}
|
||||
+
|
||||
@@ -415,21 +428,31 @@ index 0000000..8703617
|
||||
+ m->root = remove_client_node(m->root, c);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_h(const Arg *arg)
|
||||
+static void
|
||||
+setratio(unsigned int need_vertical, const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ Client *sel;
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+ int focused_on_left;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ if (!selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ sel = focustop(selmon);
|
||||
+ if (!sel)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 1);
|
||||
+ focused_on_left = (arg->f >= 0.0f);
|
||||
+
|
||||
+ split_node = find_suitable_split(selmon, client_node, need_vertical, focused_on_left);
|
||||
+
|
||||
+ if (!split_node)
|
||||
+ split_node = find_suitable_split(selmon, client_node, need_vertical, !focused_on_left);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
@@ -440,43 +463,21 @@ index 0000000..8703617
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+ apply_layout(selmon, selmon->root, selmon->w, 1);
|
||||
+ /* Skip the arrange when called from motionnotify; that path calls
|
||||
+ * arrange itself after rate-limiting. */
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_h(const Arg *arg)
|
||||
+{
|
||||
+ setratio(1, arg);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_v(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 0);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
+ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f;
|
||||
+ if (new_ratio < 0.05f)
|
||||
+ new_ratio = 0.05f;
|
||||
+ if (new_ratio > 0.95f)
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+ setratio(0, arg);
|
||||
+}
|
||||
+
|
||||
+void swapclients(const Arg *arg) {
|
||||
@@ -565,11 +566,12 @@ index 0000000..8703617
|
||||
+
|
||||
+Client *
|
||||
+xytoclient(double x, double y) {
|
||||
+ Monitor *m = xytomon(x, y);
|
||||
+ Client *c, *closest = NULL;
|
||||
+ double dist, mindist = INT_MAX, dx, dy;
|
||||
+
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen &&
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen &&
|
||||
+ x >= c->geom.x && x <= (c->geom.x + c->geom.width) &&
|
||||
+ y >= c->geom.y && y <= (c->geom.y + c->geom.height)){
|
||||
+ return c;
|
||||
@@ -578,7 +580,7 @@ index 0000000..8703617
|
||||
+
|
||||
+ /* If no client was found at cursor position fallback to closest. */
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen) {
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) {
|
||||
+ dx = 0, dy = 0;
|
||||
+
|
||||
+ if (x < c->geom.x)
|
||||
@@ -591,7 +593,7 @@ index 0000000..8703617
|
||||
+ else if (y > (c->geom.y + c->geom.height))
|
||||
+ dy = y - (c->geom.y + c->geom.height);
|
||||
+
|
||||
+ dist = sqrt(dx * dx + dy * dy);
|
||||
+ dist = dx * dx + dy * dy;
|
||||
+ if (dist < mindist) {
|
||||
+ mindist = dist;
|
||||
+ closest = c;
|
||||
@@ -639,7 +641,7 @@ index 8a6eda0..bc04e3f 100644
|
||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 8101ffa..e4e7074 100644
|
||||
index 8101ffa..c9650c1 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1,6 +1,7 @@
|
||||
@@ -721,7 +723,7 @@ index 8101ffa..e4e7074 100644
|
||||
b->func(&b->arg);
|
||||
return;
|
||||
}
|
||||
@@ -659,6 +668,27 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
@@ -659,6 +668,21 @@ 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) {
|
||||
@@ -736,20 +738,14 @@ index 8101ffa..e4e7074 100644
|
||||
+ selmon->root = create_client_node(c);
|
||||
+
|
||||
+ setfloating(c, 0);
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ } else if (cursor_mode == CurResize && !c->isfloating) {
|
||||
+ resizing_from_mouse = 0;
|
||||
+ apply_layout(selmon, selmon->root, selmon->w, 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (cursor_mode == CurResize && resizing_from_mouse)
|
||||
+ resizing_from_mouse = 0;
|
||||
+ }
|
||||
+ /* Default behaviour */
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
cursor_mode = CurNormal;
|
||||
/* Drop the window off on its new monitor */
|
||||
@@ -750,6 +780,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
@@ -750,6 +774,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
wlr_output_layout_remove(output_layout, m->wlr_output);
|
||||
wlr_scene_output_destroy(m->scene_output);
|
||||
|
||||
@@ -757,7 +753,7 @@ index 8101ffa..e4e7074 100644
|
||||
closemon(m);
|
||||
wlr_scene_node_destroy(&m->fullscreen_bg->node);
|
||||
free(m);
|
||||
@@ -1094,6 +1125,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
@@ -1094,6 +1119,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
|
||||
wl_list_insert(&mons, &m->link);
|
||||
printstatus();
|
||||
@@ -765,18 +761,26 @@ index 8101ffa..e4e7074 100644
|
||||
|
||||
/* The xdg-protocol specifies:
|
||||
*
|
||||
@@ -1336,6 +1368,10 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
@@ -1332,10 +1358,18 @@ void
|
||||
destroynotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
+ Monitor *mon;
|
||||
Client *c = wl_container_of(listener, c, destroy);
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
+ /* We check if the destroyed client was part of any tiled_list, to catch
|
||||
+ * client removals even if they would not be currently managed by btrtile */
|
||||
+ if (selmon && selmon->root)
|
||||
+ remove_client(selmon, c);
|
||||
+ wl_list_for_each(mon, &mons, link) {
|
||||
+ if (mon->root) {
|
||||
+ remove_client(mon, c);
|
||||
+ }
|
||||
+ }
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->activate.link);
|
||||
@@ -1866,7 +1902,8 @@ void
|
||||
@@ -1866,7 +1900,8 @@ void
|
||||
motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy,
|
||||
double dx_unaccel, double dy_unaccel)
|
||||
{
|
||||
@@ -786,13 +790,13 @@ index 8101ffa..e4e7074 100644
|
||||
Client *c = NULL, *w = NULL;
|
||||
LayerSurface *l = NULL;
|
||||
struct wlr_surface *surface = NULL;
|
||||
@@ -1920,18 +1957,56 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
@@ -1920,18 +1955,55 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
/* Update drag icon's position */
|
||||
wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y));
|
||||
|
||||
- /* If we are currently grabbing the mouse, handle and return */
|
||||
+ /* Skip if internal call or already resizing */
|
||||
+ if (time == 0 && resizing_from_mouse)
|
||||
+ /* Skip if internal call */
|
||||
+ if (time == 0)
|
||||
+ goto focus;
|
||||
+
|
||||
+ tiled = grabc && !grabc->isfloating && !grabc->isfullscreen;
|
||||
@@ -814,7 +818,7 @@ index 8101ffa..e4e7074 100644
|
||||
- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
|
||||
- return;
|
||||
+ if (tiled && resizing_from_mouse) {
|
||||
+ if (tiled) {
|
||||
+ dx_total = cursor->x - resize_last_update_x;
|
||||
+ dy_total = cursor->y - resize_last_update_y;
|
||||
+
|
||||
@@ -827,7 +831,6 @@ index 8101ffa..e4e7074 100644
|
||||
+ a.f = (float)(dy_total * resize_factor);
|
||||
+ setratio_v(&a);
|
||||
+ }
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ last_resize_time = time;
|
||||
+ resize_last_update_x = cursor->x;
|
||||
@@ -850,7 +853,7 @@ index 8101ffa..e4e7074 100644
|
||||
/* 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. */
|
||||
@@ -1965,22 +2040,41 @@ moveresize(const Arg *arg)
|
||||
@@ -1965,22 +2037,40 @@ moveresize(const Arg *arg)
|
||||
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
|
||||
return;
|
||||
|
||||
@@ -885,7 +888,6 @@ index 8101ffa..e4e7074 100644
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
+ resize_last_update_x = cursor->x;
|
||||
+ resize_last_update_y = cursor->y;
|
||||
+ resizing_from_mouse = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
@@ -908,6 +910,21 @@ index 8101ffa..e4e7074 100644
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2833,6 +2923,14 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
focusclient(focustop(selmon), 1);
|
||||
}
|
||||
} else {
|
||||
+ /* btrtile remove clients for each monitor */
|
||||
+ Monitor *mon;
|
||||
+ wl_list_for_each(mon, &mons, link) {
|
||||
+ if (mon->root) {
|
||||
+ remove_client(mon, c);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
wl_list_remove(&c->link);
|
||||
setmon(c, NULL, 0);
|
||||
wl_list_remove(&c->flink);
|
||||
--
|
||||
2.52.0
|
||||
2.53.0
|
||||
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
From 912701a41b19c013a9adcb176a7b6503aa1cf9c1 Mon Sep 17 00:00:00 2001
|
||||
From 47cb7ad9f669643765cafa4c2ecd1a4850bca893 Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Thu, 19 Mar 2026 22:56:45 +0200
|
||||
Subject: [PATCH] Refactor btrtile to wlroots-next
|
||||
Date: Thu, 21 May 2026 00:39:56 +0300
|
||||
Subject: [PATCH] btrtile: Spring update pt2
|
||||
|
||||
- Simplified the resizing logic to avoid full arrange calls from
|
||||
motionnotify
|
||||
- Minor intend fixes
|
||||
---
|
||||
btrtile.c | 565 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
btrtile.c | 564 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
config.def.h | 12 ++
|
||||
dwl.c | 148 +++++++++++---
|
||||
3 files changed, 698 insertions(+), 27 deletions(-)
|
||||
dwl.c | 152 +++++++++++---
|
||||
3 files changed, 701 insertions(+), 27 deletions(-)
|
||||
create mode 100644 btrtile.c
|
||||
|
||||
diff --git a/btrtile.c b/btrtile.c
|
||||
new file mode 100644
|
||||
index 0000000..d706c3b
|
||||
index 0000000..357ffb9
|
||||
--- /dev/null
|
||||
+++ b/btrtile.c
|
||||
@@ -0,0 +1,565 @@
|
||||
@@ -0,0 +1,564 @@
|
||||
+/* ************************************************************************** */
|
||||
+/* @@@ @@@@@@@@ */
|
||||
+/* @@@ @@@@@@@@@@ */
|
||||
@@ -26,7 +29,7 @@ index 0000000..d706c3b
|
||||
+/* By: julmajustus <julmajustus@tutanota.com> !!: !!:! !!! */
|
||||
+/* ::! :!: !:! */
|
||||
+/* Created: 2024/12/15 00:26:07 by julmajustus :: ::::::: :: */
|
||||
+/* Updated: 2026/03/18 20:26:17 by julmajustus : : : : : : */
|
||||
+/* Updated: 2026/05/20 22:51:54 by julmajustus : : : : : : */
|
||||
+/* */
|
||||
+/* ************************************************************************** */
|
||||
+
|
||||
@@ -49,7 +52,8 @@ index 0000000..d706c3b
|
||||
+static void destroy_node(LayoutNode *node);
|
||||
+static void destroy_tree(Monitor *m);
|
||||
+static LayoutNode *find_client_node(LayoutNode *node, Client *c);
|
||||
+static LayoutNode *find_suitable_split(LayoutNode *start, unsigned int need_vert);
|
||||
+static LayoutNode *find_suitable_split(Monitor *m, LayoutNode *start,
|
||||
+ unsigned int need_vertical, int focused_on_left);
|
||||
+static void init_tree(Monitor *m);
|
||||
+static void insert_client(Monitor *m, Client *focused_client, Client *new_client);
|
||||
+static LayoutNode *remove_client_node(LayoutNode *node, Client *c);
|
||||
@@ -60,7 +64,6 @@ index 0000000..d706c3b
|
||||
+static unsigned int visible_count(LayoutNode *node, Monitor *m);
|
||||
+static Client *xytoclient(double x, double y);
|
||||
+
|
||||
+static int resizing_from_mouse = 0;
|
||||
+static double resize_last_update_x, resize_last_update_y;
|
||||
+static uint32_t last_resize_time = 0;
|
||||
+
|
||||
@@ -81,6 +84,9 @@ index 0000000..d706c3b
|
||||
+ c = node->client;
|
||||
+ if (!c || !VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ return;
|
||||
+ if (area.x == c->old_geom.x && area.y == c->old_geom.y &&
|
||||
+ area.width == c->old_geom.width && area.height == c->old_geom.height)
|
||||
+ return;
|
||||
+ resize(c, area, 0);
|
||||
+ c->old_geom = area;
|
||||
+ return;
|
||||
@@ -147,7 +153,7 @@ index 0000000..d706c3b
|
||||
+ LayoutNode *found;
|
||||
+ struct wlr_box full_area;
|
||||
+
|
||||
+ if (!m || !m->root)
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ /* Remove non tiled clients from tree. */
|
||||
@@ -249,29 +255,36 @@ index 0000000..d706c3b
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+find_suitable_split(LayoutNode *start_node, unsigned int need_vertical)
|
||||
+find_suitable_split(Monitor *m, LayoutNode *start_node,
|
||||
+ unsigned int need_vertical, int focused_on_left)
|
||||
+{
|
||||
+ LayoutNode *n = start_node;
|
||||
+ /* if we started from a client node, jump to its parent: */
|
||||
+ if (n && n->is_client_node)
|
||||
+ LayoutNode *n = start_node, *child = NULL;
|
||||
+
|
||||
+ if (!m)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (n && n->is_client_node) {
|
||||
+ child = n;
|
||||
+ n = n->split_node;
|
||||
+ }
|
||||
+
|
||||
+ while (n) {
|
||||
+ if (!n->is_client_node && n->is_split_vertically == need_vertical &&
|
||||
+ visible_count(n->left, selmon) > 0 && visible_count(n->right, selmon) > 0)
|
||||
+ if (!n->is_client_node && n->is_split_vertically == need_vertical
|
||||
+ && visible_count(n->left, m) > 0
|
||||
+ && visible_count(n->right, m) > 0) {
|
||||
+ if ((focused_on_left && n->left == child) ||
|
||||
+ (!focused_on_left && n->right == child))
|
||||
+ return n;
|
||||
+ }
|
||||
+ child = n;
|
||||
+ n = n->split_node;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+init_tree(Monitor *m)
|
||||
+{
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+ m->root = calloc(1, sizeof(LayoutNode));
|
||||
+ if (!m->root)
|
||||
+ if (m)
|
||||
+ m->root = NULL;
|
||||
+}
|
||||
+
|
||||
@@ -396,21 +409,31 @@ index 0000000..d706c3b
|
||||
+ m->root = remove_client_node(m->root, c);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_h(const Arg *arg)
|
||||
+static void
|
||||
+setratio(unsigned int need_vertical, const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ Client *sel;
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+ int focused_on_left;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ if (!selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ sel = focustop(selmon);
|
||||
+ if (!sel)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 1);
|
||||
+ focused_on_left = (arg->f >= 0.0f);
|
||||
+
|
||||
+ split_node = find_suitable_split(selmon, client_node, need_vertical, focused_on_left);
|
||||
+
|
||||
+ if (!split_node)
|
||||
+ split_node = find_suitable_split(selmon, client_node, need_vertical, !focused_on_left);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
@@ -421,43 +444,21 @@ index 0000000..d706c3b
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+ apply_layout(selmon, selmon->root, selmon->w, 1);
|
||||
+ /* Skip the arrange when called from motionnotify; that path calls
|
||||
+ * arrange itself after rate-limiting. */
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_h(const Arg *arg)
|
||||
+{
|
||||
+ setratio(1, arg);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_v(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 0);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
+ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f;
|
||||
+ if (new_ratio < 0.05f)
|
||||
+ new_ratio = 0.05f;
|
||||
+ if (new_ratio > 0.95f)
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+ setratio(0, arg);
|
||||
+}
|
||||
+
|
||||
+void swapclients(const Arg *arg) {
|
||||
@@ -546,11 +547,12 @@ index 0000000..d706c3b
|
||||
+
|
||||
+Client *
|
||||
+xytoclient(double x, double y) {
|
||||
+ Monitor *m = xytomon(x, y);
|
||||
+ Client *c, *closest = NULL;
|
||||
+ double dist, mindist = INT_MAX, dx, dy;
|
||||
+
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen &&
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen &&
|
||||
+ x >= c->geom.x && x <= (c->geom.x + c->geom.width) &&
|
||||
+ y >= c->geom.y && y <= (c->geom.y + c->geom.height)){
|
||||
+ return c;
|
||||
@@ -559,7 +561,7 @@ index 0000000..d706c3b
|
||||
+
|
||||
+ /* If no client was found at cursor position fallback to closest. */
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen) {
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) {
|
||||
+ dx = 0, dy = 0;
|
||||
+
|
||||
+ if (x < c->geom.x)
|
||||
@@ -572,7 +574,7 @@ index 0000000..d706c3b
|
||||
+ else if (y > (c->geom.y + c->geom.height))
|
||||
+ dy = y - (c->geom.y + c->geom.height);
|
||||
+
|
||||
+ dist = sqrt(dx * dx + dy * dy);
|
||||
+ dist = dx * dx + dy * dy;
|
||||
+ if (dist < mindist) {
|
||||
+ mindist = dist;
|
||||
+ closest = c;
|
||||
@@ -620,7 +622,7 @@ index 8a6eda0..bc04e3f 100644
|
||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 8101ffa..e4e7074 100644
|
||||
index 8101ffa..bf52c6c 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1,6 +1,7 @@
|
||||
@@ -702,7 +704,7 @@ index 8101ffa..e4e7074 100644
|
||||
b->func(&b->arg);
|
||||
return;
|
||||
}
|
||||
@@ -659,6 +668,27 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
@@ -659,6 +668,21 @@ 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) {
|
||||
@@ -717,20 +719,14 @@ index 8101ffa..e4e7074 100644
|
||||
+ selmon->root = create_client_node(c);
|
||||
+
|
||||
+ setfloating(c, 0);
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ } else if (cursor_mode == CurResize && !c->isfloating) {
|
||||
+ resizing_from_mouse = 0;
|
||||
+ apply_layout(selmon, selmon->root, selmon->w, 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (cursor_mode == CurResize && resizing_from_mouse)
|
||||
+ resizing_from_mouse = 0;
|
||||
+ }
|
||||
+ /* Default behaviour */
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
cursor_mode = CurNormal;
|
||||
/* Drop the window off on its new monitor */
|
||||
@@ -750,6 +780,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
@@ -750,6 +774,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
wlr_output_layout_remove(output_layout, m->wlr_output);
|
||||
wlr_scene_output_destroy(m->scene_output);
|
||||
|
||||
@@ -738,7 +734,7 @@ index 8101ffa..e4e7074 100644
|
||||
closemon(m);
|
||||
wlr_scene_node_destroy(&m->fullscreen_bg->node);
|
||||
free(m);
|
||||
@@ -1094,6 +1125,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
@@ -1094,6 +1119,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
|
||||
wl_list_insert(&mons, &m->link);
|
||||
printstatus();
|
||||
@@ -746,18 +742,25 @@ index 8101ffa..e4e7074 100644
|
||||
|
||||
/* The xdg-protocol specifies:
|
||||
*
|
||||
@@ -1336,6 +1368,10 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
@@ -1333,9 +1359,17 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
Client *c = wl_container_of(listener, c, destroy);
|
||||
+ Monitor *mon;
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
+ /* We check if the destroyed client was part of any tiled_list, to catch
|
||||
+ * client removals even if they would not be currently managed by btrtile */
|
||||
+ if (selmon && selmon->root)
|
||||
+ remove_client(selmon, c);
|
||||
+ wl_list_for_each(mon, &mons, link) {
|
||||
+ if (mon->root) {
|
||||
+ remove_client(mon, c);
|
||||
+ }
|
||||
+ }
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->activate.link);
|
||||
@@ -1866,7 +1902,8 @@ void
|
||||
@@ -1866,7 +1900,8 @@ void
|
||||
motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy,
|
||||
double dx_unaccel, double dy_unaccel)
|
||||
{
|
||||
@@ -767,13 +770,13 @@ index 8101ffa..e4e7074 100644
|
||||
Client *c = NULL, *w = NULL;
|
||||
LayerSurface *l = NULL;
|
||||
struct wlr_surface *surface = NULL;
|
||||
@@ -1920,18 +1957,56 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
@@ -1920,18 +1955,55 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
/* Update drag icon's position */
|
||||
wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y));
|
||||
|
||||
- /* If we are currently grabbing the mouse, handle and return */
|
||||
+ /* Skip if internal call or already resizing */
|
||||
+ if (time == 0 && resizing_from_mouse)
|
||||
+ /* Skip if internal call */
|
||||
+ if (time == 0)
|
||||
+ goto focus;
|
||||
+
|
||||
+ tiled = grabc && !grabc->isfloating && !grabc->isfullscreen;
|
||||
@@ -795,7 +798,7 @@ index 8101ffa..e4e7074 100644
|
||||
- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
|
||||
- return;
|
||||
+ if (tiled && resizing_from_mouse) {
|
||||
+ if (tiled) {
|
||||
+ dx_total = cursor->x - resize_last_update_x;
|
||||
+ dy_total = cursor->y - resize_last_update_y;
|
||||
+
|
||||
@@ -808,7 +811,6 @@ index 8101ffa..e4e7074 100644
|
||||
+ a.f = (float)(dy_total * resize_factor);
|
||||
+ setratio_v(&a);
|
||||
+ }
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ last_resize_time = time;
|
||||
+ resize_last_update_x = cursor->x;
|
||||
@@ -831,7 +833,7 @@ index 8101ffa..e4e7074 100644
|
||||
/* 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. */
|
||||
@@ -1965,22 +2040,41 @@ moveresize(const Arg *arg)
|
||||
@@ -1965,22 +2037,40 @@ moveresize(const Arg *arg)
|
||||
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
|
||||
return;
|
||||
|
||||
@@ -866,7 +868,6 @@ index 8101ffa..e4e7074 100644
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
+ resize_last_update_x = cursor->x;
|
||||
+ resize_last_update_y = cursor->y;
|
||||
+ resizing_from_mouse = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
@@ -889,6 +890,21 @@ index 8101ffa..e4e7074 100644
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2833,6 +2923,14 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
focusclient(focustop(selmon), 1);
|
||||
}
|
||||
} else {
|
||||
+ /* btrtile remove clients for each monitor */
|
||||
+ Monitor *mon;
|
||||
+ wl_list_for_each(mon, &mons, link) {
|
||||
+ if (mon->root) {
|
||||
+ remove_client(mon, c);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
wl_list_remove(&c->link);
|
||||
setmon(c, NULL, 0);
|
||||
wl_list_remove(&c->flink);
|
||||
--
|
||||
2.52.0
|
||||
2.53.0
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ The opacity levels can be change by short cuts.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/Hansvon/dwl/src/branch/client-opacity-focus)
|
||||
- [2025-12-11](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/client-opacity-focus/client-opacity-focus.patch)
|
||||
- [2026-04-27](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/client-opacity-focus/client-opacity-focus.patch)
|
||||
|
||||
### Authors
|
||||
- [Hansvon](https://codeberg.org/Hansvon)
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
From 694751a31a437bbb28c3a75c917ed922231ab366 Mon Sep 17 00:00:00 2001
|
||||
From 57c5475d7f715b77ec05d69a2bda808b224cf0b4 Mon Sep 17 00:00:00 2001
|
||||
From: Hans von Hohenstaufen <Hans.von.Hohenstaufen@protonmail.com>
|
||||
Date: Mon, 22 Dec 2025 01:43:50 +0000
|
||||
Subject: [PATCH] Add client opacity focus
|
||||
|
||||
---
|
||||
config.def.h | 12 +++++++---
|
||||
dwl.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 72 insertions(+), 3 deletions(-)
|
||||
dwl.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 74 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 95c2afa..b7002f5 100644
|
||||
index 95c2afa..55abf84 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -13,6 +13,8 @@ static const float focuscolor[] = COLOR(0x005577ff);
|
||||
@@ -26,12 +26,12 @@ index 95c2afa..b7002f5 100644
|
||||
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
|
||||
static const Rule rules[] = {
|
||||
- /* app_id title tags mask isfloating monitor */
|
||||
+ /* app_id title tags mask isfloating alpha unfocus monitor */
|
||||
+ /* app_id title tags mask isfloating alpha focus alpha unfocus 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" */
|
||||
+ { "Gimp_EXAMPLE", NULL, 0, 1, default_opacity_unfocus, -1 }, /* Start on currently visible tags floating, not tiled */
|
||||
+ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 1.00, -1 }, /* Start on ONLY tag "9" */
|
||||
+ { "Gimp_EXAMPLE", NULL, 0, 1, 1.00, 0.20, -1 }, /* Start on currently visible tags floating, not tiled */
|
||||
+ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 1.00, 1.00, -1 }, /* Start on ONLY tag "9" */
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
@@ -47,7 +47,7 @@ index 95c2afa..b7002f5 100644
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 12f441e..7539738 100644
|
||||
index 12f441e..e45e420 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -138,6 +138,9 @@ typedef struct {
|
||||
@@ -60,15 +60,16 @@ index 12f441e..7539738 100644
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
|
||||
@@ -227,6 +230,7 @@ typedef struct {
|
||||
@@ -227,6 +230,8 @@ typedef struct {
|
||||
const char *title;
|
||||
uint32_t tags;
|
||||
int isfloating;
|
||||
+ float opacity_focus;
|
||||
+ float opacity_unfocus;
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
@@ -319,6 +323,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
@@ -319,6 +324,7 @@ 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);
|
||||
@@ -76,7 +77,7 @@ index 12f441e..7539738 100644
|
||||
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);
|
||||
@@ -326,6 +331,8 @@ static void setfullscreen(Client *c, int fullscreen);
|
||||
@@ -326,6 +332,8 @@ static void setfullscreen(Client *c, int fullscreen);
|
||||
static void setlayout(const Arg *arg);
|
||||
static void setmfact(const Arg *arg);
|
||||
static void setmon(Client *c, Monitor *m, uint32_t newtags);
|
||||
@@ -85,15 +86,16 @@ index 12f441e..7539738 100644
|
||||
static void setpsel(struct wl_listener *listener, void *data);
|
||||
static void setsel(struct wl_listener *listener, void *data);
|
||||
static void setup(void);
|
||||
@@ -490,6 +497,7 @@ applyrules(Client *c)
|
||||
@@ -490,6 +498,8 @@ applyrules(Client *c)
|
||||
if ((!r->title || strstr(title, r->title))
|
||||
&& (!r->id || strstr(appid, r->id))) {
|
||||
c->isfloating = r->isfloating;
|
||||
+ c->opacity = r->opacity_unfocus;
|
||||
+ c->opacity_unfocus = r->opacity_unfocus;
|
||||
+ c->opacity_focus = r->opacity_focus;
|
||||
newtags |= r->tags;
|
||||
i = 0;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
@@ -1127,6 +1135,10 @@ createnotify(struct wl_listener *listener, void *data)
|
||||
@@ -1127,6 +1137,10 @@ createnotify(struct wl_listener *listener, void *data)
|
||||
c = toplevel->base->data = ecalloc(1, sizeof(*c));
|
||||
c->surface.xdg = toplevel->base;
|
||||
c->bw = borderpx;
|
||||
@@ -104,7 +106,7 @@ index 12f441e..7539738 100644
|
||||
|
||||
LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify);
|
||||
LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify);
|
||||
@@ -1429,6 +1441,7 @@ focusclient(Client *c, int lift)
|
||||
@@ -1429,6 +1443,7 @@ focusclient(Client *c, int lift)
|
||||
wl_list_insert(&fstack, &c->flink);
|
||||
selmon = c->mon;
|
||||
c->isurgent = 0;
|
||||
@@ -112,7 +114,7 @@ index 12f441e..7539738 100644
|
||||
|
||||
/* Don't change border color if there is an exclusive focus or we are
|
||||
* handling a drag operation */
|
||||
@@ -1453,6 +1466,7 @@ focusclient(Client *c, int lift)
|
||||
@@ -1453,6 +1468,7 @@ focusclient(Client *c, int lift)
|
||||
client_set_border_color(old_c, bordercolor);
|
||||
|
||||
client_activate_surface(old, 0);
|
||||
@@ -120,7 +122,7 @@ index 12f441e..7539738 100644
|
||||
}
|
||||
}
|
||||
printstatus();
|
||||
@@ -2159,6 +2173,7 @@ rendermon(struct wl_listener *listener, void *data)
|
||||
@@ -2159,6 +2175,7 @@ rendermon(struct wl_listener *listener, void *data)
|
||||
/* Render if no XDG clients have an outstanding resize and are visible on
|
||||
* this monitor. */
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
@@ -128,7 +130,7 @@ index 12f441e..7539738 100644
|
||||
if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
|
||||
goto skip;
|
||||
}
|
||||
@@ -2295,6 +2310,15 @@ run(char *startup_cmd)
|
||||
@@ -2295,6 +2312,15 @@ run(char *startup_cmd)
|
||||
wl_display_run(dpy);
|
||||
}
|
||||
|
||||
@@ -144,7 +146,7 @@ index 12f441e..7539738 100644
|
||||
void
|
||||
setcursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2363,6 +2387,7 @@ setfullscreen(Client *c, int fullscreen)
|
||||
@@ -2363,6 +2389,7 @@ setfullscreen(Client *c, int fullscreen)
|
||||
* client positions are set by the user and cannot be recalculated */
|
||||
resize(c, c->prev, 0);
|
||||
}
|
||||
@@ -152,7 +154,7 @@ index 12f441e..7539738 100644
|
||||
arrange(c->mon);
|
||||
printstatus();
|
||||
}
|
||||
@@ -2419,6 +2444,44 @@ setmon(Client *c, Monitor *m, uint32_t newtags)
|
||||
@@ -2419,6 +2446,44 @@ setmon(Client *c, Monitor *m, uint32_t newtags)
|
||||
focusclient(focustop(selmon), 1);
|
||||
}
|
||||
|
||||
@@ -198,5 +200,5 @@ index 12f441e..7539738 100644
|
||||
setpsel(struct wl_listener *listener, void *data)
|
||||
{
|
||||
--
|
||||
2.51.2
|
||||
2.53.0
|
||||
|
||||
|
||||
@@ -22,8 +22,10 @@ Adds a function that automatically enables adaptive sync/VRR when a fullscreen c
|
||||
- Enabled by default.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/julmajustus/dwl/src/branch/fullscreenadaptivesync)
|
||||
- [git branch](https://codeberg.org/julmajustus/dwl/src/branch/fullscreenadaptivesync-wlroots-next)
|
||||
- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/fullscreenadaptivesync/fullscreenadaptivesync-v0.7.patch)
|
||||
- [0.8](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/fullscreenadaptivesync/fullscreenadaptivesync-v0.8.patch)
|
||||
- [wlroots-next-d41ecb7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/fullscreenadaptivesync/fullscreenadaptivesync-wlroots-next-d41ecb7.patch)
|
||||
|
||||
### Authors
|
||||
- [julmajustus](https://codeberg.org/julmajustus)
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
From c003f450c197a0c960bbb355511f8dca7a35e3c3 Mon Sep 17 00:00:00 2001
|
||||
From 85dccbec7e6d2e967646a8c182a7a24224632c68 Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Sat, 4 Jan 2025 14:24:59 +0200
|
||||
Subject: [PATCH] add fullscreenadaptivesync
|
||||
Date: Mon, 18 May 2026 00:03:41 +0300
|
||||
Subject: [PATCH] fullscreen_adaptive_sync: Minor bug fixes
|
||||
|
||||
- Fixed logic error inside unmapnotify
|
||||
- Added no-op guards inside set_adaptive_sync
|
||||
- Added extra check for the config commit success
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwl.c | 40 ++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 41 insertions(+)
|
||||
dwl.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 53 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..886f1ab 100644
|
||||
@@ -21,7 +24,7 @@ index 22d2171..886f1ab 100644
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index a2711f6..7be05ef 100644
|
||||
index a2711f6..1b0682d 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -322,6 +322,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
@@ -49,11 +52,10 @@ index a2711f6..7be05ef 100644
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
static void associatex11(struct wl_listener *listener, void *data);
|
||||
@@ -2269,6 +2273,31 @@ run(char *startup_cmd)
|
||||
@@ -2269,6 +2273,42 @@ run(char *startup_cmd)
|
||||
wl_display_run(dpy);
|
||||
}
|
||||
|
||||
+void
|
||||
+set_adaptive_sync(Monitor *m, int enable)
|
||||
+{
|
||||
+ struct wlr_output_state state;
|
||||
@@ -64,13 +66,25 @@ index a2711f6..7be05ef 100644
|
||||
+ || !fullscreen_adaptive_sync_enabled)
|
||||
+ return;
|
||||
+
|
||||
+ if (enable && m->wlr_output->adaptive_sync_status
|
||||
+ == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED)
|
||||
+ return;
|
||||
+
|
||||
+ if (!enable && m->wlr_output->adaptive_sync_status
|
||||
+ == WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED)
|
||||
+ return;
|
||||
+
|
||||
+ config = wlr_output_configuration_v1_create();
|
||||
+ config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output);
|
||||
+
|
||||
+ /* Set and commit the adaptive sync state change */
|
||||
+ wlr_output_state_init(&state);
|
||||
+ wlr_output_state_set_adaptive_sync_enabled(&state, enable);
|
||||
+ wlr_output_commit_state(m->wlr_output, &state);
|
||||
+ if (!wlr_output_commit_state(m->wlr_output, &state)) {
|
||||
+ wlr_output_state_finish(&state);
|
||||
+ wlr_output_configuration_v1_destroy(config);
|
||||
+ return;
|
||||
+ }
|
||||
+ wlr_output_state_finish(&state);
|
||||
+
|
||||
+ /* Broadcast the adaptive sync state change to output_mgr */
|
||||
@@ -81,7 +95,7 @@ index a2711f6..7be05ef 100644
|
||||
void
|
||||
setcursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2332,10 +2361,12 @@ setfullscreen(Client *c, int fullscreen)
|
||||
@@ -2332,10 +2372,12 @@ setfullscreen(Client *c, int fullscreen)
|
||||
if (fullscreen) {
|
||||
c->prev = c->geom;
|
||||
resize(c, c->mon->m, 0);
|
||||
@@ -94,7 +108,7 @@ index a2711f6..7be05ef 100644
|
||||
}
|
||||
arrange(c->mon);
|
||||
printstatus();
|
||||
@@ -2739,6 +2770,12 @@ togglefullscreen(const Arg *arg)
|
||||
@@ -2739,6 +2781,12 @@ togglefullscreen(const Arg *arg)
|
||||
setfullscreen(sel, !sel->isfullscreen);
|
||||
}
|
||||
|
||||
@@ -107,16 +121,24 @@ index a2711f6..7be05ef 100644
|
||||
void
|
||||
toggletag(const Arg *arg)
|
||||
{
|
||||
@@ -2809,6 +2846,9 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
@@ -2794,6 +2842,7 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is unmapped, and should no longer be shown. */
|
||||
Client *c = wl_container_of(listener, c, unmap);
|
||||
+ Monitor *lastmon = c->mon; // fullscreen_adaptive_sync
|
||||
if (c == grabc) {
|
||||
cursor_mode = CurNormal;
|
||||
grabc = NULL;
|
||||
@@ -2809,6 +2858,9 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
setmon(c, NULL, 0);
|
||||
wl_list_remove(&c->flink);
|
||||
}
|
||||
+ /* Toggle adaptive sync off when fullscreen client is unmapped */
|
||||
+ if (c->isfullscreen)
|
||||
+ set_adaptive_sync(selmon, 0);
|
||||
+ set_adaptive_sync(lastmon, 0);
|
||||
|
||||
wlr_scene_node_destroy(&c->scene->node);
|
||||
printstatus();
|
||||
--
|
||||
2.45.2
|
||||
2.53.0
|
||||
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
From 60af6f9dab09710234475b51393a104c21918db3 Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Mon, 18 May 2026 00:12:31 +0300
|
||||
Subject: [PATCH] fullscreen_adaptive_sync: Minor bug fixes
|
||||
|
||||
- Fixed logic error inside unmapnotify
|
||||
- Added no-op guards inside set_adaptive_sync
|
||||
- Added extra check for the config commit success
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwl.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 53 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8a6eda0..06b3153 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -138,6 +138,7 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY, XKB_KEY_F5, togglefullscreenadaptivesync, {0} },
|
||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 44f3ad9..737f089 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -319,6 +319,7 @@ 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 void set_adaptive_sync(Monitor *m, int enabled);
|
||||
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);
|
||||
@@ -336,6 +337,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
+static void togglefullscreenadaptivesync(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unlocksession(struct wl_listener *listener, void *data);
|
||||
@@ -436,6 +438,8 @@ static struct wl_listener request_start_drag = {.notify = requeststartdrag};
|
||||
static struct wl_listener start_drag = {.notify = startdrag};
|
||||
static struct wl_listener new_session_lock = {.notify = locksession};
|
||||
|
||||
+static int fullscreen_adaptive_sync_enabled = 1;
|
||||
+
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
static void associatex11(struct wl_listener *listener, void *data);
|
||||
@@ -2296,6 +2300,42 @@ run(char *startup_cmd)
|
||||
wl_display_run(dpy);
|
||||
}
|
||||
|
||||
+set_adaptive_sync(Monitor *m, int enable)
|
||||
+{
|
||||
+ struct wlr_output_state state;
|
||||
+ struct wlr_output_configuration_v1 *config;
|
||||
+ struct wlr_output_configuration_head_v1 *config_head;
|
||||
+
|
||||
+ if (!m || !m->wlr_output || !m->wlr_output->enabled
|
||||
+ || !fullscreen_adaptive_sync_enabled)
|
||||
+ return;
|
||||
+
|
||||
+ if (enable && m->wlr_output->adaptive_sync_status
|
||||
+ == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED)
|
||||
+ return;
|
||||
+
|
||||
+ if (!enable && m->wlr_output->adaptive_sync_status
|
||||
+ == WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED)
|
||||
+ return;
|
||||
+
|
||||
+ config = wlr_output_configuration_v1_create();
|
||||
+ config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output);
|
||||
+
|
||||
+ /* Set and commit the adaptive sync state change */
|
||||
+ wlr_output_state_init(&state);
|
||||
+ wlr_output_state_set_adaptive_sync_enabled(&state, enable);
|
||||
+ if (!wlr_output_commit_state(m->wlr_output, &state)) {
|
||||
+ wlr_output_state_finish(&state);
|
||||
+ wlr_output_configuration_v1_destroy(config);
|
||||
+ return;
|
||||
+ }
|
||||
+ wlr_output_state_finish(&state);
|
||||
+
|
||||
+ /* Broadcast the adaptive sync state change to output_mgr */
|
||||
+ config_head->state.adaptive_sync_enabled = enable;
|
||||
+ wlr_output_manager_v1_set_configuration(output_mgr, config);
|
||||
+}
|
||||
+
|
||||
void
|
||||
setcursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2359,10 +2399,12 @@ setfullscreen(Client *c, int fullscreen)
|
||||
if (fullscreen) {
|
||||
c->prev = c->geom;
|
||||
resize(c, c->mon->m, 0);
|
||||
+ set_adaptive_sync(c->mon, 1);
|
||||
} else {
|
||||
/* restore previous size instead of arrange for floating windows since
|
||||
* client positions are set by the user and cannot be recalculated */
|
||||
resize(c, c->prev, 0);
|
||||
+ set_adaptive_sync(c->mon, 0);
|
||||
}
|
||||
arrange(c->mon);
|
||||
printstatus();
|
||||
@@ -2760,6 +2802,12 @@ togglefullscreen(const Arg *arg)
|
||||
setfullscreen(sel, !sel->isfullscreen);
|
||||
}
|
||||
|
||||
+void
|
||||
+togglefullscreenadaptivesync(const Arg *arg)
|
||||
+{
|
||||
+ fullscreen_adaptive_sync_enabled = !fullscreen_adaptive_sync_enabled;
|
||||
+}
|
||||
+
|
||||
void
|
||||
toggletag(const Arg *arg)
|
||||
{
|
||||
@@ -2815,6 +2863,7 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is unmapped, and should no longer be shown. */
|
||||
Client *c = wl_container_of(listener, c, unmap);
|
||||
+ Monitor *lastmon = c->mon; // fullscreen_adaptive_sync
|
||||
if (c == grabc) {
|
||||
cursor_mode = CurNormal;
|
||||
grabc = NULL;
|
||||
@@ -2830,6 +2879,9 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
setmon(c, NULL, 0);
|
||||
wl_list_remove(&c->flink);
|
||||
}
|
||||
+ /* Toggle adaptive sync off when fullscreen client is unmapped */
|
||||
+ if (c->isfullscreen)
|
||||
+ set_adaptive_sync(lastmon, 0);
|
||||
|
||||
wlr_scene_node_destroy(&c->scene->node);
|
||||
printstatus();
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
From cf817259dbb1235d1ffc073d4e0f128676552666 Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Mon, 18 May 2026 00:15:18 +0300
|
||||
Subject: [PATCH] fullscreen_adaptive_sync: Minor bug fixes
|
||||
|
||||
- Fixed logic error inside unmapnotify
|
||||
- Added no-op guards inside set_adaptive_sync
|
||||
- Added extra check for the config commit success
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwl.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 53 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8a6eda0..06b3153 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -138,6 +138,7 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY, XKB_KEY_F5, togglefullscreenadaptivesync, {0} },
|
||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 8101ffa..2f1c80b 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -323,6 +323,7 @@ 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 void set_adaptive_sync(Monitor *m, int enabled);
|
||||
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);
|
||||
@@ -340,6 +341,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
+static void togglefullscreenadaptivesync(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unlocksession(struct wl_listener *listener, void *data);
|
||||
@@ -440,6 +442,8 @@ static struct wl_listener request_start_drag = {.notify = requeststartdrag};
|
||||
static struct wl_listener start_drag = {.notify = startdrag};
|
||||
static struct wl_listener new_session_lock = {.notify = locksession};
|
||||
|
||||
+static int fullscreen_adaptive_sync_enabled = 1;
|
||||
+
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
static void associatex11(struct wl_listener *listener, void *data);
|
||||
@@ -2300,6 +2304,42 @@ run(char *startup_cmd)
|
||||
wl_display_run(dpy);
|
||||
}
|
||||
|
||||
+set_adaptive_sync(Monitor *m, int enable)
|
||||
+{
|
||||
+ struct wlr_output_state state;
|
||||
+ struct wlr_output_configuration_v1 *config;
|
||||
+ struct wlr_output_configuration_head_v1 *config_head;
|
||||
+
|
||||
+ if (!m || !m->wlr_output || !m->wlr_output->enabled
|
||||
+ || !fullscreen_adaptive_sync_enabled)
|
||||
+ return;
|
||||
+
|
||||
+ if (enable && m->wlr_output->adaptive_sync_status
|
||||
+ == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED)
|
||||
+ return;
|
||||
+
|
||||
+ if (!enable && m->wlr_output->adaptive_sync_status
|
||||
+ == WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED)
|
||||
+ return;
|
||||
+
|
||||
+ config = wlr_output_configuration_v1_create();
|
||||
+ config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output);
|
||||
+
|
||||
+ /* Set and commit the adaptive sync state change */
|
||||
+ wlr_output_state_init(&state);
|
||||
+ wlr_output_state_set_adaptive_sync_enabled(&state, enable);
|
||||
+ if (!wlr_output_commit_state(m->wlr_output, &state)) {
|
||||
+ wlr_output_state_finish(&state);
|
||||
+ wlr_output_configuration_v1_destroy(config);
|
||||
+ return;
|
||||
+ }
|
||||
+ wlr_output_state_finish(&state);
|
||||
+
|
||||
+ /* Broadcast the adaptive sync state change to output_mgr */
|
||||
+ config_head->state.adaptive_sync_enabled = enable;
|
||||
+ wlr_output_manager_v1_set_configuration(output_mgr, config);
|
||||
+}
|
||||
+
|
||||
void
|
||||
setcursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2363,10 +2403,12 @@ setfullscreen(Client *c, int fullscreen)
|
||||
if (fullscreen) {
|
||||
c->prev = c->geom;
|
||||
resize(c, c->mon->m, 0);
|
||||
+ set_adaptive_sync(c->mon, 1);
|
||||
} else {
|
||||
/* restore previous size instead of arrange for floating windows since
|
||||
* client positions are set by the user and cannot be recalculated */
|
||||
resize(c, c->prev, 0);
|
||||
+ set_adaptive_sync(c->mon, 0);
|
||||
}
|
||||
arrange(c->mon);
|
||||
printstatus();
|
||||
@@ -2767,6 +2809,12 @@ togglefullscreen(const Arg *arg)
|
||||
setfullscreen(sel, !sel->isfullscreen);
|
||||
}
|
||||
|
||||
+void
|
||||
+togglefullscreenadaptivesync(const Arg *arg)
|
||||
+{
|
||||
+ fullscreen_adaptive_sync_enabled = !fullscreen_adaptive_sync_enabled;
|
||||
+}
|
||||
+
|
||||
void
|
||||
toggletag(const Arg *arg)
|
||||
{
|
||||
@@ -2822,6 +2870,7 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is unmapped, and should no longer be shown. */
|
||||
Client *c = wl_container_of(listener, c, unmap);
|
||||
+ Monitor *lastmon = c->mon; // fullscreen_adaptive_sync
|
||||
if (c == grabc) {
|
||||
cursor_mode = CurNormal;
|
||||
grabc = NULL;
|
||||
@@ -2837,6 +2886,9 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
setmon(c, NULL, 0);
|
||||
wl_list_remove(&c->flink);
|
||||
}
|
||||
+ /* Toggle adaptive sync off when fullscreen client is unmapped */
|
||||
+ if (c->isfullscreen)
|
||||
+ set_adaptive_sync(lastmon, 0);
|
||||
|
||||
wlr_scene_node_destroy(&c->scene->node);
|
||||
printstatus();
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@@ -13,8 +13,8 @@ This allows the user to change size and placement of floating windows using only
|
||||
| <kbd>MODKEY</kbd> + <kbd>Shift</kbd> + <kbd>Right</kbd> | grow width 40px |
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/moveresizekb)
|
||||
- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/moveresizekb/moveresizekb.patch)
|
||||
- [v0.8](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/moveresizekb/moveresizekb.patch)
|
||||
|
||||
### Authors
|
||||
- [cana](https://codeberg.org/cana)
|
||||
- [wochap](https://codeberg.org/wochap)
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
From c8af428f964679089599e4ffbe7d28d08a4e875f Mon Sep 17 00:00:00 2001
|
||||
From: wochap <gean.marroquin@gmail.com>
|
||||
Date: Tue, 5 Mar 2024 23:42:55 -0500
|
||||
Subject: [PATCH] implement keybindings to move and resize focused floating
|
||||
window
|
||||
From f19c162ba64c2c4860e5d16e48e08cebd7a7e46c Mon Sep 17 00:00:00 2001
|
||||
From: C4FE1 <heitorcdesousa13@gmail.com>
|
||||
Date: Wed, 10 Jun 2026 19:50:26 -0300
|
||||
Subject: [PATCH] Change moveresizekb logic to allow it's use in floating
|
||||
(NULL) Layout
|
||||
|
||||
---
|
||||
config.def.h | 8 ++++++++
|
||||
dwl.c | 19 +++++++++++++++++++
|
||||
2 files changed, 27 insertions(+)
|
||||
dwl.c | 23 +++++++++++++++++++++++
|
||||
2 files changed, 31 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index db0babc..d0570b8 100644
|
||||
index 8a6eda0..b8398f9 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -135,6 +135,14 @@ static const Key keys[] = {
|
||||
@@ -138,6 +138,14 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
@@ -29,10 +29,10 @@ index db0babc..d0570b8 100644
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ef27a1d..251472b 100644
|
||||
index 44f3ad9..a6450f5 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -313,6 +313,7 @@ static void tagmon(const Arg *arg);
|
||||
@@ -336,6 +336,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
@@ -40,7 +40,7 @@ index ef27a1d..251472b 100644
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unlocksession(struct wl_listener *listener, void *data);
|
||||
@@ -2454,6 +2455,24 @@ togglefullscreen(const Arg *arg)
|
||||
@@ -2760,6 +2761,28 @@ togglefullscreen(const Arg *arg)
|
||||
setfullscreen(sel, !sel->isfullscreen);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,11 @@ index ef27a1d..251472b 100644
|
||||
+ Client *c = focustop(selmon);
|
||||
+ Monitor *m = selmon;
|
||||
+
|
||||
+ if(!(m && arg && arg->v && c && c->isfloating)) {
|
||||
+ if(!(m && arg && arg->v && c)){
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if(!(c->isfloating || m->lt[m->sellt]->arrange == NULL)){
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
@@ -66,5 +70,5 @@ index ef27a1d..251472b 100644
|
||||
toggletag(const Arg *arg)
|
||||
{
|
||||
--
|
||||
2.42.0
|
||||
2.54.0
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
Moves clients to their old output when it is reattached.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/eyusupov/dwl/src/branch/restore-monitor)
|
||||
- [2024-04-07](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/restore-monitor/restore-monitor.patch)
|
||||
- [git branch](https://codeberg.org/6z7y/dwl-patches/src/branch/restore-monitor)
|
||||
- [2026-06-20](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/restore-monitor/restore-monitor.patch)
|
||||
### Authors
|
||||
#### Current
|
||||
- [6z7y](https://codeberg.org/6z7y)
|
||||
#### Historic
|
||||
- [eyusupov](https://codeberg.org/eyusupov)
|
||||
|
||||
|
||||
@@ -1,25 +1,40 @@
|
||||
From e42ca1c539437d3098d80983cfe2ad6f938d7a08 Mon Sep 17 00:00:00 2001
|
||||
From: Eldar Yusupov <eyusupov@gmail.com>
|
||||
Date: Sun, 17 Mar 2024 19:12:29 +0300
|
||||
Subject: [PATCH] Restore correct monitor for client when it is reattached
|
||||
Subject: [PATCH] Restore correct monitor and floating position when reattached
|
||||
|
||||
---
|
||||
dwl.c | 24 ++++++++++++++++++++++--
|
||||
1 file changed, 22 insertions(+), 2 deletions(-)
|
||||
dwl.c | 33 ++++++++++++++++++++++++++++++---
|
||||
1 file changed, 30 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf763df..d8d8139 100644
|
||||
index 44f3ad9..41548cd 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -107,6 +107,7 @@ typedef struct {
|
||||
@@ -106,6 +106,8 @@ typedef struct {
|
||||
unsigned int type; /* XDGShell or X11* */
|
||||
struct wlr_box geom; /* layout-relative, includes border */
|
||||
|
||||
Monitor *mon;
|
||||
+ char *output;
|
||||
+ struct wlr_box floatgeom; /* saved geom for floating restore after monitor reconnect */
|
||||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
@@ -869,6 +870,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
@@ -807,6 +809,13 @@ closemon(Monitor *m)
|
||||
}
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
+
|
||||
+ /* Save floating geom now, before destroymon modifies it below.
|
||||
+ * destroymon subtracts m->w.width from c->geom.x for floating
|
||||
+ * windows, which corrupts the layout-absolute position we need
|
||||
+ * to restore on reconnect. */
|
||||
+ if (c->isfloating && c->mon == m) c->floatgeom = c->geom;
|
||||
+
|
||||
if (c->isfloating && c->geom.x > m->m.width)
|
||||
resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y,
|
||||
.width = c->geom.width, .height = c->geom.height}, 0);
|
||||
@@ -1045,6 +1054,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
size_t i;
|
||||
struct wlr_output_state state;
|
||||
Monitor *m;
|
||||
@@ -27,53 +42,54 @@ index bf763df..d8d8139 100644
|
||||
|
||||
if (!wlr_output_init_render(wlr_output, alloc, drw))
|
||||
return;
|
||||
@@ -938,6 +940,13 @@ createmon(struct wl_listener *listener, void *data)
|
||||
@@ -1114,6 +1124,15 @@ createmon(struct wl_listener *listener, void *data)
|
||||
wlr_output_layout_add_auto(output_layout, wlr_output);
|
||||
else
|
||||
wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
|
||||
+
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (strcmp(wlr_output->name, c->output) == 0) {
|
||||
+ if (!c->output || strcmp(wlr_output->name, c->output) != 0)
|
||||
+ continue;
|
||||
+ c->mon = m;
|
||||
+ }
|
||||
+ if (c->isfloating)
|
||||
+ resize(c, c->floatgeom, 0);
|
||||
+ }
|
||||
+ updatemons(NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1186,6 +1195,7 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
wl_list_remove(&c->map.link);
|
||||
@@ -1347,7 +1366,8 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
wl_list_remove(&c->unmap.link);
|
||||
wl_list_remove(&c->maximize.link);
|
||||
}
|
||||
- free(c);
|
||||
+ free(c->output);
|
||||
free(c);
|
||||
+ free(c);
|
||||
}
|
||||
|
||||
@@ -1618,6 +1628,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
void
|
||||
@@ -1792,6 +1812,9 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
} else {
|
||||
applyrules(c);
|
||||
}
|
||||
+ c->output = strdup(c->mon->wlr_output->name);
|
||||
+ if (c->output == NULL) {
|
||||
+ die("oom");
|
||||
+ }
|
||||
+ if (c->output == NULL) die("oom");
|
||||
+
|
||||
printstatus();
|
||||
|
||||
unset_fullscreen:
|
||||
@@ -2565,8 +2579,14 @@ void
|
||||
@@ -2705,8 +2728,12 @@ void
|
||||
tagmon(const Arg *arg)
|
||||
{
|
||||
Client *sel = focustop(selmon);
|
||||
- if (sel)
|
||||
- setmon(sel, dirtomon(arg->i), 0);
|
||||
+ if (!sel)
|
||||
+ return;
|
||||
+ if (!sel) return;
|
||||
+
|
||||
+ setmon(sel, dirtomon(arg->i), 0);
|
||||
+ free(sel->output);
|
||||
+ sel->output = strdup(sel->mon->wlr_output->name);
|
||||
+ if (sel->output == NULL) {
|
||||
+ die("oom");
|
||||
+ }
|
||||
+ if (sel->output == NULL) die("oom");
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
# simple_scratchpad — A very simple scratchpad utility.
|
||||
|
||||
Adds functions to add, toggle and remove clients to/from scratchpad client list.
|
||||

|
||||
Adds functions to add, toggle and remove clients to/from scratchpad client lists.
|
||||

|
||||
|
||||
---
|
||||
|
||||
@@ -16,11 +16,14 @@ Adds functions to add, toggle and remove clients to/from scratchpad client list.
|
||||
3. **removescratchpad**
|
||||
- Removes client from scratchpad client list.
|
||||
|
||||
4. **setscratchpad**
|
||||
- Sets current scratchpad number
|
||||
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/julmajustus/dwl/src/branch/simple_scratchpad)
|
||||
- [scratchpad-wlroots-next-f4249db.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/simple_scratchpad/simple_scratchpad-f4249db.patch)
|
||||
- [scratchpad-0.8.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/simple_scratchpad/simple_scratchpad-0.8.patch)
|
||||
- [scratchpad-wlroots-next-d41ecb7.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/simple_scratchpad/simple_scratchpad-wlroots-next-d41ecb7.patch)
|
||||
- [scratchpad-v0.8.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/simple_scratchpad/simple_scratchpad-v0.8.patch)
|
||||
|
||||
### Authors
|
||||
- [julmajustus](https://codeberg.org/julmajustus)
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
From 0d603b179ccccbb4270fd202a14a2db18d0a5413 Mon Sep 17 00:00:00 2001
|
||||
From: A Frederick Christensen <dwl@ivories.org>
|
||||
Date: Thu, 26 Feb 2026 17:09:28 -0600
|
||||
Subject: [PATCH] Apply simple_scratchpad patch
|
||||
|
||||
---
|
||||
config.def.h | 3 ++
|
||||
dwl.c | 34 +++++++++++++++++++++--
|
||||
simple_scratchpad.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 103 insertions(+), 2 deletions(-)
|
||||
create mode 100644 simple_scratchpad.c
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8a6eda0..6254fc9 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -132,6 +132,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_c, killclient, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_z, addscratchpad, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_z, togglescratchpad, {0} },
|
||||
+ { MODKEY, XKB_KEY_z, removescratchpad, {0} },
|
||||
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 44f3ad9..215f630 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -139,6 +139,7 @@ typedef struct {
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
+ struct wl_list link_temp;
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
@@ -240,6 +241,7 @@ typedef struct {
|
||||
} SessionLock;
|
||||
|
||||
/* function declarations */
|
||||
+static void addscratchpad(const Arg *arg);
|
||||
static void applybounds(Client *c, struct wlr_box *bbox);
|
||||
static void applyrules(Client *c);
|
||||
static void arrange(Monitor *m);
|
||||
@@ -314,6 +316,7 @@ static void printstatus(void);
|
||||
static void powermgrsetmode(struct wl_listener *listener, void *data);
|
||||
static void quit(const Arg *arg);
|
||||
static void rendermon(struct wl_listener *listener, void *data);
|
||||
+static void removescratchpad(const Arg *arg);
|
||||
static void requestdecorationmode(struct wl_listener *listener, void *data);
|
||||
static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||
@@ -336,6 +339,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
+static void togglescratchpad(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unlocksession(struct wl_listener *listener, void *data);
|
||||
@@ -406,6 +410,9 @@ static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
|
||||
+static struct wl_list scratchpad_clients;
|
||||
+static int scratchpad_visible = 1;
|
||||
+
|
||||
/* global event handlers */
|
||||
static struct wl_listener cursor_axis = {.notify = axisnotify};
|
||||
static struct wl_listener cursor_button = {.notify = buttonpress};
|
||||
@@ -455,6 +462,8 @@ static struct wlr_xwayland *xwayland;
|
||||
/* attempt to encapsulate suck into one file */
|
||||
#include "client.h"
|
||||
|
||||
+#include "simple_scratchpad.c"
|
||||
+
|
||||
/* function implementations */
|
||||
void
|
||||
applybounds(Client *c, struct wlr_box *bbox)
|
||||
@@ -1328,10 +1337,20 @@ void
|
||||
destroynotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
- Client *c = wl_container_of(listener, c, destroy);
|
||||
+ Client *sc, *c = wl_container_of(listener, c, destroy);
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
+ /* Check if destroyed client was part of scratchpad_clients
|
||||
+ * and clean it from the list if so. */
|
||||
+ if (c && wl_list_length(&scratchpad_clients) > 0) {
|
||||
+ wl_list_for_each(sc, &scratchpad_clients, link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->activate.link);
|
||||
@@ -2333,11 +2352,21 @@ setcursorshape(struct wl_listener *listener, void *data)
|
||||
void
|
||||
setfloating(Client *c, int floating)
|
||||
{
|
||||
- Client *p = client_get_parent(c);
|
||||
+ Client *sc, *p = client_get_parent(c);
|
||||
c->isfloating = floating;
|
||||
/* If in floating layout do not change the client's layer */
|
||||
if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange)
|
||||
return;
|
||||
+ /* Check if unfloated client was part of scratchpad_clients
|
||||
+ * and remove it from scratchpad_clients list if so */
|
||||
+ if (!floating && wl_list_length(&scratchpad_clients) > 0) {
|
||||
+ wl_list_for_each(sc, &scratchpad_clients, link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
|
||||
(p && p->isfullscreen) ? LyrFS
|
||||
: c->isfloating ? LyrFloat : LyrTile]);
|
||||
@@ -2554,6 +2583,7 @@ setup(void)
|
||||
*/
|
||||
wl_list_init(&clients);
|
||||
wl_list_init(&fstack);
|
||||
+ wl_list_init(&scratchpad_clients);
|
||||
|
||||
xdg_shell = wlr_xdg_shell_create(dpy, 6);
|
||||
wl_signal_add(&xdg_shell->events.new_toplevel, &new_xdg_toplevel);
|
||||
diff --git a/simple_scratchpad.c b/simple_scratchpad.c
|
||||
new file mode 100644
|
||||
index 0000000..26d6b66
|
||||
--- /dev/null
|
||||
+++ b/simple_scratchpad.c
|
||||
@@ -0,0 +1,68 @@
|
||||
+/* ************************************************************************** */
|
||||
+/* */
|
||||
+/* ::: :::::::: */
|
||||
+/* simple_scratchpad.c :+: :+: :+: */
|
||||
+/* +:+ +:+ +:+ */
|
||||
+/* By: jmakkone <jmakkone@student.hive.fi> +#+ +:+ +#+ */
|
||||
+/* +#+#+#+#+#+ +#+ */
|
||||
+/* Created: 2024/12/19 19:35:02 by jmakkone #+# #+# */
|
||||
+/* Updated: 2025/01/04 13:35:50 by jmakkone ### ########.fr */
|
||||
+/* */
|
||||
+/* ************************************************************************** */
|
||||
+
|
||||
+void
|
||||
+addscratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *cc, *c = focustop(selmon);
|
||||
+
|
||||
+ if (!c)
|
||||
+ return;
|
||||
+ /* Check if the added client is already a scratchpad client */
|
||||
+ wl_list_for_each(cc, &scratchpad_clients, link_temp) {
|
||||
+ if (cc == c)
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!c->isfloating) {
|
||||
+ setfloating(c, 1);
|
||||
+ }
|
||||
+ wl_list_insert(&scratchpad_clients, &c->link_temp);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+togglescratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ Monitor *m = selmon;
|
||||
+
|
||||
+ scratchpad_visible = !scratchpad_visible;
|
||||
+ if (scratchpad_visible) {
|
||||
+ wl_list_for_each(c, &scratchpad_clients, link_temp) {
|
||||
+ c->mon = m;
|
||||
+ c->tags = m->tagset[m->seltags];
|
||||
+ arrange(m);
|
||||
+ focusclient(c, 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ wl_list_for_each(c, &scratchpad_clients, link_temp) {
|
||||
+ c->tags = 0;
|
||||
+ focusclient(focustop(m), 1);
|
||||
+ arrange(m);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+removescratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *sc, *c = focustop(selmon);
|
||||
+
|
||||
+ if (c && wl_list_length(&scratchpad_clients) > 0) {
|
||||
+ /* Check if c is in scratchpad_clients */
|
||||
+ wl_list_for_each(sc, &scratchpad_clients, link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
From 09c708876afe3675f68f7b35c3f17263b134ceee Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Thu, 21 May 2026 00:28:15 +0300
|
||||
Subject: [PATCH] simple_scratchpad: Spring update scratchpad V2
|
||||
|
||||
- Added support for multiple scratchpads
|
||||
---
|
||||
config.def.h | 7 ++++
|
||||
dwl.c | 43 +++++++++++++++++++++--
|
||||
simple_scratchpad.c | 85 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 133 insertions(+), 2 deletions(-)
|
||||
create mode 100644 simple_scratchpad.c
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8a6eda0..a527e09 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -14,6 +14,7 @@ static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */
|
||||
|
||||
+#define SCRATCHPAD_COUNT 3
|
||||
/* tagging - TAGCOUNT must be no greater than 31 */
|
||||
#define TAGCOUNT (9)
|
||||
|
||||
@@ -132,6 +133,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_c, killclient, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_z, addscratchpad, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_z, togglescratchpad, {0} },
|
||||
+ { MODKEY, XKB_KEY_z, removescratchpad, {0} },
|
||||
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
@@ -144,6 +148,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
+ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_1, setscratchpad, {.i = 0} },
|
||||
+ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_2, setscratchpad, {.i = 1} },
|
||||
+ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_3, setscratchpad, {.i = 2} },
|
||||
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 44f3ad9..f54bbda 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -139,6 +139,7 @@ typedef struct {
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
+ struct wl_list link_temp;
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
@@ -240,6 +241,7 @@ typedef struct {
|
||||
} SessionLock;
|
||||
|
||||
/* function declarations */
|
||||
+static void addscratchpad(const Arg *arg);
|
||||
static void applybounds(Client *c, struct wlr_box *bbox);
|
||||
static void applyrules(Client *c);
|
||||
static void arrange(Monitor *m);
|
||||
@@ -314,6 +316,7 @@ static void printstatus(void);
|
||||
static void powermgrsetmode(struct wl_listener *listener, void *data);
|
||||
static void quit(const Arg *arg);
|
||||
static void rendermon(struct wl_listener *listener, void *data);
|
||||
+static void removescratchpad(const Arg *arg);
|
||||
static void requestdecorationmode(struct wl_listener *listener, void *data);
|
||||
static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||
@@ -327,6 +330,7 @@ static void setlayout(const Arg *arg);
|
||||
static void setmfact(const Arg *arg);
|
||||
static void setmon(Client *c, Monitor *m, uint32_t newtags);
|
||||
static void setpsel(struct wl_listener *listener, void *data);
|
||||
+static void setscratchpad(const Arg *arg);
|
||||
static void setsel(struct wl_listener *listener, void *data);
|
||||
static void setup(void);
|
||||
static void spawn(const Arg *arg);
|
||||
@@ -336,6 +340,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
+static void togglescratchpad(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unlocksession(struct wl_listener *listener, void *data);
|
||||
@@ -455,6 +460,11 @@ static struct wlr_xwayland *xwayland;
|
||||
/* attempt to encapsulate suck into one file */
|
||||
#include "client.h"
|
||||
|
||||
+static struct wl_list scratchpad_clients[SCRATCHPAD_COUNT];
|
||||
+static int scratchpad_visible[SCRATCHPAD_COUNT];
|
||||
+static int scratchpad_sel = 0;
|
||||
+#include "simple_scratchpad.c"
|
||||
+
|
||||
/* function implementations */
|
||||
void
|
||||
applybounds(Client *c, struct wlr_box *bbox)
|
||||
@@ -1328,10 +1338,21 @@ void
|
||||
destroynotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
- Client *c = wl_container_of(listener, c, destroy);
|
||||
+ Client *sc, *c = wl_container_of(listener, c, destroy);
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
+ /* Check if destroyed client was part of any scratchpad slot
|
||||
+ * and clean it from the list if so. */
|
||||
+ for (int i = 0; i < SCRATCHPAD_COUNT; i++) {
|
||||
+ wl_list_for_each(sc, &scratchpad_clients[i], link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ goto scratchpad_destroy_done;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+scratchpad_destroy_done:;
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->activate.link);
|
||||
@@ -2333,11 +2354,24 @@ setcursorshape(struct wl_listener *listener, void *data)
|
||||
void
|
||||
setfloating(Client *c, int floating)
|
||||
{
|
||||
- Client *p = client_get_parent(c);
|
||||
+ Client *sc, *p = client_get_parent(c);
|
||||
c->isfloating = floating;
|
||||
/* If in floating layout do not change the client's layer */
|
||||
if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange)
|
||||
return;
|
||||
+ /* Check if unfloated client was part of any scratchpad slot
|
||||
+ * and remove it from that slot if so */
|
||||
+ if (!floating) {
|
||||
+ for (int i = 0; i < SCRATCHPAD_COUNT; i++) {
|
||||
+ wl_list_for_each(sc, &scratchpad_clients[i], link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ goto scratchpad_float_done;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+scratchpad_float_done:;
|
||||
+ }
|
||||
wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
|
||||
(p && p->isfullscreen) ? LyrFS
|
||||
: c->isfloating ? LyrFloat : LyrTile]);
|
||||
@@ -2554,6 +2588,11 @@ setup(void)
|
||||
*/
|
||||
wl_list_init(&clients);
|
||||
wl_list_init(&fstack);
|
||||
+ wl_list_init(&fstack);
|
||||
+ for (int j = 0; j < SCRATCHPAD_COUNT; j++) {
|
||||
+ wl_list_init(&scratchpad_clients[j]);
|
||||
+ scratchpad_visible[j] = 1;
|
||||
+ }
|
||||
|
||||
xdg_shell = wlr_xdg_shell_create(dpy, 6);
|
||||
wl_signal_add(&xdg_shell->events.new_toplevel, &new_xdg_toplevel);
|
||||
diff --git a/simple_scratchpad.c b/simple_scratchpad.c
|
||||
new file mode 100644
|
||||
index 0000000..cd62d83
|
||||
--- /dev/null
|
||||
+++ b/simple_scratchpad.c
|
||||
@@ -0,0 +1,85 @@
|
||||
+/* ************************************************************************** */
|
||||
+/* @@@ @@@@@@@@ */
|
||||
+/* @@@ @@@@@@@@@@ */
|
||||
+/* @@! @@! @@@@ */
|
||||
+/* !@! !@! @!@!@ */
|
||||
+/* simple_scratchpad.c @!! @!@ @! !@! */
|
||||
+/* !!! !@!!! !!! */
|
||||
+/* By: julmajustus <julmajustus@tutanota.com> !!: !!:! !!! */
|
||||
+/* ::! :!: !:! */
|
||||
+/* Created: 2024/12/19 19:35:02 by jmakkone :: ::::::: :: */
|
||||
+/* Updated: 2026/05/20 23:58:16 by julmajustus : : : : : : */
|
||||
+/* */
|
||||
+/* ************************************************************************** */
|
||||
+
|
||||
+void
|
||||
+addscratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *cc, *c = focustop(selmon);
|
||||
+
|
||||
+ if (!c)
|
||||
+ return;
|
||||
+ /* Check if the added client is already a scratchpad client */
|
||||
+ for (int i = 0; i < SCRATCHPAD_COUNT; i++) {
|
||||
+ wl_list_for_each(cc, &scratchpad_clients[i], link_temp) {
|
||||
+ if (cc == c)
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!c->isfloating) {
|
||||
+ setfloating(c, 1);
|
||||
+ }
|
||||
+ wl_list_insert(&scratchpad_clients[scratchpad_sel], &c->link_temp);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+togglescratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ Monitor *m = selmon;
|
||||
+
|
||||
+ scratchpad_visible[scratchpad_sel] = !scratchpad_visible[scratchpad_sel];
|
||||
+ if (scratchpad_visible[scratchpad_sel]) {
|
||||
+ wl_list_for_each(c, &scratchpad_clients[scratchpad_sel], link_temp) {
|
||||
+ c->mon = m;
|
||||
+ c->tags = m->tagset[m->seltags];
|
||||
+ arrange(m);
|
||||
+ focusclient(c, 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ wl_list_for_each(c, &scratchpad_clients[scratchpad_sel], link_temp) {
|
||||
+ c->tags = 0;
|
||||
+ focusclient(focustop(m), 1);
|
||||
+ arrange(m);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+removescratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *sc, *c = focustop(selmon);
|
||||
+ if (!c)
|
||||
+ return;
|
||||
+ for (int i = 0; i < SCRATCHPAD_COUNT; i++) {
|
||||
+ /* Check if c is in scratchpad_clients */
|
||||
+ wl_list_for_each(sc, &scratchpad_clients[i], link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setscratchpad(const Arg *arg)
|
||||
+{
|
||||
+ int idx = arg->i;
|
||||
+
|
||||
+ if (idx < 0)
|
||||
+ idx = 0;
|
||||
+ else if (idx >= SCRATCHPAD_COUNT)
|
||||
+ idx = SCRATCHPAD_COUNT - 1;
|
||||
+ scratchpad_sel = idx;
|
||||
+}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
From be4f7488eac6ea502e0e9d1cc5595e01d97cb345 Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Thu, 21 May 2026 00:28:41 +0300
|
||||
Subject: [PATCH] simple_scratchpad: Spring update scratchpad V2
|
||||
|
||||
- Added support for multiple scratchpads
|
||||
---
|
||||
config.def.h | 7 ++++
|
||||
dwl.c | 43 +++++++++++++++++++++--
|
||||
simple_scratchpad.c | 85 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 133 insertions(+), 2 deletions(-)
|
||||
create mode 100644 simple_scratchpad.c
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8a6eda0..a527e09 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -14,6 +14,7 @@ static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */
|
||||
|
||||
+#define SCRATCHPAD_COUNT 3
|
||||
/* tagging - TAGCOUNT must be no greater than 31 */
|
||||
#define TAGCOUNT (9)
|
||||
|
||||
@@ -132,6 +133,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_c, killclient, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_z, addscratchpad, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_z, togglescratchpad, {0} },
|
||||
+ { MODKEY, XKB_KEY_z, removescratchpad, {0} },
|
||||
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
@@ -144,6 +148,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
+ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_1, setscratchpad, {.i = 0} },
|
||||
+ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_2, setscratchpad, {.i = 1} },
|
||||
+ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_3, setscratchpad, {.i = 2} },
|
||||
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 8101ffa..1c858a8 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -143,6 +143,7 @@ typedef struct {
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
+ struct wl_list link_temp;
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
@@ -244,6 +245,7 @@ typedef struct {
|
||||
} SessionLock;
|
||||
|
||||
/* function declarations */
|
||||
+static void addscratchpad(const Arg *arg);
|
||||
static void applybounds(Client *c, struct wlr_box *bbox);
|
||||
static void applyrules(Client *c);
|
||||
static void arrange(Monitor *m);
|
||||
@@ -318,6 +320,7 @@ static void printstatus(void);
|
||||
static void powermgrsetmode(struct wl_listener *listener, void *data);
|
||||
static void quit(const Arg *arg);
|
||||
static void rendermon(struct wl_listener *listener, void *data);
|
||||
+static void removescratchpad(const Arg *arg);
|
||||
static void requestdecorationmode(struct wl_listener *listener, void *data);
|
||||
static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||
@@ -331,6 +334,7 @@ static void setlayout(const Arg *arg);
|
||||
static void setmfact(const Arg *arg);
|
||||
static void setmon(Client *c, Monitor *m, uint32_t newtags);
|
||||
static void setpsel(struct wl_listener *listener, void *data);
|
||||
+static void setscratchpad(const Arg *arg);
|
||||
static void setsel(struct wl_listener *listener, void *data);
|
||||
static void setup(void);
|
||||
static void spawn(const Arg *arg);
|
||||
@@ -340,6 +344,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
+static void togglescratchpad(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unlocksession(struct wl_listener *listener, void *data);
|
||||
@@ -459,6 +464,11 @@ static struct wlr_xwayland *xwayland;
|
||||
/* attempt to encapsulate suck into one file */
|
||||
#include "client.h"
|
||||
|
||||
+static struct wl_list scratchpad_clients[SCRATCHPAD_COUNT];
|
||||
+static int scratchpad_visible[SCRATCHPAD_COUNT];
|
||||
+static int scratchpad_sel = 0;
|
||||
+#include "simple_scratchpad.c"
|
||||
+
|
||||
/* function implementations */
|
||||
void
|
||||
applybounds(Client *c, struct wlr_box *bbox)
|
||||
@@ -1332,10 +1342,21 @@ void
|
||||
destroynotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
- Client *c = wl_container_of(listener, c, destroy);
|
||||
+ Client *sc, *c = wl_container_of(listener, c, destroy);
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
+ /* Check if destroyed client was part of any scratchpad slot
|
||||
+ * and clean it from the list if so. */
|
||||
+ for (int i = 0; i < SCRATCHPAD_COUNT; i++) {
|
||||
+ wl_list_for_each(sc, &scratchpad_clients[i], link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ goto scratchpad_destroy_done;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+scratchpad_destroy_done:;
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->activate.link);
|
||||
@@ -2337,11 +2358,24 @@ setcursorshape(struct wl_listener *listener, void *data)
|
||||
void
|
||||
setfloating(Client *c, int floating)
|
||||
{
|
||||
- Client *p = client_get_parent(c);
|
||||
+ Client *sc, *p = client_get_parent(c);
|
||||
c->isfloating = floating;
|
||||
/* If in floating layout do not change the client's layer */
|
||||
if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange)
|
||||
return;
|
||||
+ /* Check if unfloated client was part of any scratchpad slot
|
||||
+ * and remove it from that slot if so */
|
||||
+ if (!floating) {
|
||||
+ for (int i = 0; i < SCRATCHPAD_COUNT; i++) {
|
||||
+ wl_list_for_each(sc, &scratchpad_clients[i], link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ goto scratchpad_float_done;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+scratchpad_float_done:;
|
||||
+ }
|
||||
wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
|
||||
(p && p->isfullscreen) ? LyrFS
|
||||
: c->isfloating ? LyrFloat : LyrTile]);
|
||||
@@ -2561,6 +2595,11 @@ setup(void)
|
||||
*/
|
||||
wl_list_init(&clients);
|
||||
wl_list_init(&fstack);
|
||||
+ wl_list_init(&fstack);
|
||||
+ for (int j = 0; j < SCRATCHPAD_COUNT; j++) {
|
||||
+ wl_list_init(&scratchpad_clients[j]);
|
||||
+ scratchpad_visible[j] = 1;
|
||||
+ }
|
||||
|
||||
xdg_shell = wlr_xdg_shell_create(dpy, 6);
|
||||
wl_signal_add(&xdg_shell->events.new_toplevel, &new_xdg_toplevel);
|
||||
diff --git a/simple_scratchpad.c b/simple_scratchpad.c
|
||||
new file mode 100644
|
||||
index 0000000..0e23ddd
|
||||
--- /dev/null
|
||||
+++ b/simple_scratchpad.c
|
||||
@@ -0,0 +1,85 @@
|
||||
+/* ************************************************************************** */
|
||||
+/* @@@ @@@@@@@@ */
|
||||
+/* @@@ @@@@@@@@@@ */
|
||||
+/* @@! @@! @@@@ */
|
||||
+/* !@! !@! @!@!@ */
|
||||
+/* simple_scratchpad.c @!! @!@ @! !@! */
|
||||
+/* !!! !@!!! !!! */
|
||||
+/* By: julmajustus <julmajustus@tutanota.com> !!: !!:! !!! */
|
||||
+/* ::! :!: !:! */
|
||||
+/* Created: 2024/12/19 19:35:02 by jmakkone :: ::::::: :: */
|
||||
+/* Updated: 2026/05/20 23:56:35 by julmajustus : : : : : : */
|
||||
+/* */
|
||||
+/* ************************************************************************** */
|
||||
+
|
||||
+void
|
||||
+addscratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *cc, *c = focustop(selmon);
|
||||
+
|
||||
+ if (!c)
|
||||
+ return;
|
||||
+ /* Check if the added client is already a scratchpad client */
|
||||
+ for (int i = 0; i < SCRATCHPAD_COUNT; i++) {
|
||||
+ wl_list_for_each(cc, &scratchpad_clients[i], link_temp) {
|
||||
+ if (cc == c)
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!c->isfloating) {
|
||||
+ setfloating(c, 1);
|
||||
+ }
|
||||
+ wl_list_insert(&scratchpad_clients[scratchpad_sel], &c->link_temp);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+togglescratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ Monitor *m = selmon;
|
||||
+
|
||||
+ scratchpad_visible[scratchpad_sel] = !scratchpad_visible[scratchpad_sel];
|
||||
+ if (scratchpad_visible[scratchpad_sel]) {
|
||||
+ wl_list_for_each(c, &scratchpad_clients[scratchpad_sel], link_temp) {
|
||||
+ c->mon = m;
|
||||
+ c->tags = m->tagset[m->seltags];
|
||||
+ arrange(m);
|
||||
+ focusclient(c, 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ wl_list_for_each(c, &scratchpad_clients[scratchpad_sel], link_temp) {
|
||||
+ c->tags = 0;
|
||||
+ focusclient(focustop(m), 1);
|
||||
+ arrange(m);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+removescratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *sc, *c = focustop(selmon);
|
||||
+ if (!c)
|
||||
+ return;
|
||||
+ for (int i = 0; i < SCRATCHPAD_COUNT; i++) {
|
||||
+ /* Check if c is in scratchpad_clients */
|
||||
+ wl_list_for_each(sc, &scratchpad_clients[i], link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setscratchpad(const Arg *arg)
|
||||
+{
|
||||
+ int idx = arg->i;
|
||||
+
|
||||
+ if (idx < 0)
|
||||
+ idx = 0;
|
||||
+ else if (idx >= SCRATCHPAD_COUNT)
|
||||
+ idx = SCRATCHPAD_COUNT - 1;
|
||||
+ scratchpad_sel = idx;
|
||||
+}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
From 94e649317328c7af091516fe3441ea80a814d1e4 Mon Sep 17 00:00:00 2001
|
||||
From: A Frederick Christensen <dwl@ivories.org>
|
||||
Date: Thu, 26 Feb 2026 17:18:17 -0600
|
||||
Subject: [PATCH] Apply simple_scratchpad patch
|
||||
|
||||
---
|
||||
config.def.h | 4 ++-
|
||||
dwl.c | 34 +++++++++++++++++++++--
|
||||
simple_scratchpad.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 103 insertions(+), 3 deletions(-)
|
||||
create mode 100644 simple_scratchpad.c
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8a6eda0..bd6cb40 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -132,6 +132,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_c, killclient, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_z, addscratchpad, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_z, togglescratchpad, {0} },
|
||||
+ { MODKEY, XKB_KEY_z, removescratchpad, {0} },
|
||||
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
@@ -154,7 +157,6 @@ static const Key keys[] = {
|
||||
TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7),
|
||||
TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8),
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_q, quit, {0} },
|
||||
-
|
||||
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
|
||||
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} },
|
||||
/* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 8a9715d..6ae7707 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -141,6 +141,7 @@ typedef struct {
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
+ struct wl_list link_temp;
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
@@ -242,6 +243,7 @@ typedef struct {
|
||||
} SessionLock;
|
||||
|
||||
/* function declarations */
|
||||
+static void addscratchpad(const Arg *arg);
|
||||
static void applybounds(Client *c, struct wlr_box *bbox);
|
||||
static void applyrules(Client *c);
|
||||
static void arrange(Monitor *m);
|
||||
@@ -316,6 +318,7 @@ static void printstatus(void);
|
||||
static void powermgrsetmode(struct wl_listener *listener, void *data);
|
||||
static void quit(const Arg *arg);
|
||||
static void rendermon(struct wl_listener *listener, void *data);
|
||||
+static void removescratchpad(const Arg *arg);
|
||||
static void requestdecorationmode(struct wl_listener *listener, void *data);
|
||||
static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||
@@ -338,6 +341,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
+static void togglescratchpad(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unlocksession(struct wl_listener *listener, void *data);
|
||||
@@ -408,6 +412,9 @@ static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
|
||||
+static struct wl_list scratchpad_clients;
|
||||
+static int scratchpad_visible = 1;
|
||||
+
|
||||
/* global event handlers */
|
||||
static struct wl_listener cursor_axis = {.notify = axisnotify};
|
||||
static struct wl_listener cursor_button = {.notify = buttonpress};
|
||||
@@ -457,6 +464,8 @@ static struct wlr_xwayland *xwayland;
|
||||
/* attempt to encapsulate suck into one file */
|
||||
#include "client.h"
|
||||
|
||||
+#include "simple_scratchpad.c"
|
||||
+
|
||||
/* function implementations */
|
||||
void
|
||||
applybounds(Client *c, struct wlr_box *bbox)
|
||||
@@ -1330,10 +1339,20 @@ void
|
||||
destroynotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
- Client *c = wl_container_of(listener, c, destroy);
|
||||
+ Client *sc, *c = wl_container_of(listener, c, destroy);
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
+ /* Check if destroyed client was part of scratchpad_clients
|
||||
+ * and clean it from the list if so. */
|
||||
+ if (c && wl_list_length(&scratchpad_clients) > 0) {
|
||||
+ wl_list_for_each(sc, &scratchpad_clients, link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->activate.link);
|
||||
@@ -2335,11 +2354,21 @@ setcursorshape(struct wl_listener *listener, void *data)
|
||||
void
|
||||
setfloating(Client *c, int floating)
|
||||
{
|
||||
- Client *p = client_get_parent(c);
|
||||
+ Client *sc, *p = client_get_parent(c);
|
||||
c->isfloating = floating;
|
||||
/* If in floating layout do not change the client's layer */
|
||||
if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange)
|
||||
return;
|
||||
+ /* Check if unfloated client was part of scratchpad_clients
|
||||
+ * and remove it from scratchpad_clients list if so */
|
||||
+ if (!floating && wl_list_length(&scratchpad_clients) > 0) {
|
||||
+ wl_list_for_each(sc, &scratchpad_clients, link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
|
||||
(p && p->isfullscreen) ? LyrFS
|
||||
: c->isfloating ? LyrFloat : LyrTile]);
|
||||
@@ -2557,6 +2586,7 @@ setup(void)
|
||||
*/
|
||||
wl_list_init(&clients);
|
||||
wl_list_init(&fstack);
|
||||
+ wl_list_init(&scratchpad_clients);
|
||||
|
||||
xdg_shell = wlr_xdg_shell_create(dpy, 6);
|
||||
wl_signal_add(&xdg_shell->events.new_toplevel, &new_xdg_toplevel);
|
||||
diff --git a/simple_scratchpad.c b/simple_scratchpad.c
|
||||
new file mode 100644
|
||||
index 0000000..26d6b66
|
||||
--- /dev/null
|
||||
+++ b/simple_scratchpad.c
|
||||
@@ -0,0 +1,68 @@
|
||||
+/* ************************************************************************** */
|
||||
+/* */
|
||||
+/* ::: :::::::: */
|
||||
+/* simple_scratchpad.c :+: :+: :+: */
|
||||
+/* +:+ +:+ +:+ */
|
||||
+/* By: jmakkone <jmakkone@student.hive.fi> +#+ +:+ +#+ */
|
||||
+/* +#+#+#+#+#+ +#+ */
|
||||
+/* Created: 2024/12/19 19:35:02 by jmakkone #+# #+# */
|
||||
+/* Updated: 2025/01/04 13:35:50 by jmakkone ### ########.fr */
|
||||
+/* */
|
||||
+/* ************************************************************************** */
|
||||
+
|
||||
+void
|
||||
+addscratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *cc, *c = focustop(selmon);
|
||||
+
|
||||
+ if (!c)
|
||||
+ return;
|
||||
+ /* Check if the added client is already a scratchpad client */
|
||||
+ wl_list_for_each(cc, &scratchpad_clients, link_temp) {
|
||||
+ if (cc == c)
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!c->isfloating) {
|
||||
+ setfloating(c, 1);
|
||||
+ }
|
||||
+ wl_list_insert(&scratchpad_clients, &c->link_temp);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+togglescratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ Monitor *m = selmon;
|
||||
+
|
||||
+ scratchpad_visible = !scratchpad_visible;
|
||||
+ if (scratchpad_visible) {
|
||||
+ wl_list_for_each(c, &scratchpad_clients, link_temp) {
|
||||
+ c->mon = m;
|
||||
+ c->tags = m->tagset[m->seltags];
|
||||
+ arrange(m);
|
||||
+ focusclient(c, 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ wl_list_for_each(c, &scratchpad_clients, link_temp) {
|
||||
+ c->tags = 0;
|
||||
+ focusclient(focustop(m), 1);
|
||||
+ arrange(m);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+removescratchpad(const Arg *arg)
|
||||
+{
|
||||
+ Client *sc, *c = focustop(selmon);
|
||||
+
|
||||
+ if (c && wl_list_length(&scratchpad_clients) > 0) {
|
||||
+ /* Check if c is in scratchpad_clients */
|
||||
+ wl_list_for_each(sc, &scratchpad_clients, link_temp) {
|
||||
+ if (sc == c) {
|
||||
+ wl_list_remove(&c->link_temp);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
### Description
|
||||
Swapfocus adds a new function on dwl: a shortcut to change the focus to the last focused window. If the last focused window is in another tag, then the focus will change to that tag.
|
||||
Swapfocus adds a new function on dwl: a shortcut to change the focus to the last focused window.
|
||||
- If the last focused window is in another tag, then the focus will change to that tag.
|
||||
- Alternatively: edit the patch and uncomment and comment out the lines instructed to keep the swapfocus shortcut from changing to another tag.
|
||||
|
||||
### Download
|
||||
- [v0.8](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/swapfocus/swapfocus.patch)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
From c4a9254ef63bbe1bae9ed525250e0b187668397f Mon Sep 17 00:00:00 2001
|
||||
From 364b9f20b830886b9c0e6539ddba2cc206a286eb Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Andr=C3=A9=20Desgualdo=20Pereira?= <desgua@gmail.com>
|
||||
Date: Fri, 1 May 2026 08:17:28 -0300
|
||||
Subject: [PATCH] swapfocus patch improvement
|
||||
Date: Thu, 21 May 2026 09:50:03 -0300
|
||||
Subject: [PATCH] swapfocus patch
|
||||
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwl.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 48 insertions(+)
|
||||
dwl.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 91 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8a6eda0..23e502d 100644
|
||||
@@ -21,7 +21,7 @@ index 8a6eda0..23e502d 100644
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 101a45f..5e78719 100644
|
||||
index 101a45f..c512323 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -332,6 +332,7 @@ static void setsel(struct wl_listener *listener, void *data);
|
||||
@@ -61,7 +61,7 @@ index 101a45f..5e78719 100644
|
||||
/* Put the new client atop the focus stack and select its monitor */
|
||||
if (c && !client_is_unmanaged(c)) {
|
||||
wl_list_remove(&c->flink);
|
||||
@@ -2679,6 +2688,44 @@ spawn(const Arg *arg)
|
||||
@@ -2679,6 +2688,87 @@ spawn(const Arg *arg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,13 +93,56 @@ index 101a45f..5e78719 100644
|
||||
+ Arg a = {.ui = prevclient->tags};
|
||||
+ selmon = prevclient->mon;
|
||||
+ view(&a);
|
||||
+
|
||||
+ /* Comment out the 3 lines above and
|
||||
+ * uncommment the following lines
|
||||
+ * if changing tags isn't desired */
|
||||
+
|
||||
+// int current_tag_clients = 0;
|
||||
+// Client *tmp;
|
||||
+// wl_list_for_each(tmp, &clients, link) {
|
||||
+// /* Make sure it's on the current monitor, visible on the current tag, and mapped */
|
||||
+// if (tmp->mon == selmon && (tmp->tags & selmon->tagset[selmon->seltags]) && !client_is_unmanaged(tmp)) {
|
||||
+// current_tag_clients++;
|
||||
+// }
|
||||
+// }
|
||||
+//
|
||||
+// /* If there's more than 1 window here, mimic Mod+k instead of switching tags */
|
||||
+// if (current_tag_clients > 1) {
|
||||
+// Arg arg_focus = {.i = -1};
|
||||
+// focusstack(&arg_focus);
|
||||
+// }
|
||||
+
|
||||
+ /* End of not changing tags logic */
|
||||
+ } else {
|
||||
+ /* Tag IS visible: Just swap focus within the same view */
|
||||
+ focusclient(prevclient, 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ Arg a = {.ui = 0};
|
||||
+ selmon = prevclient->mon;
|
||||
+ view(&a);
|
||||
+
|
||||
+ /* Comment out the 3 lines above and
|
||||
+ * uncommment the following lines
|
||||
+ * if changing tags isn't desired */
|
||||
+
|
||||
+ /* use the following if changing tags isn't desired */
|
||||
+// int current_tag_clients = 0;
|
||||
+// Client *tmp;
|
||||
+// wl_list_for_each(tmp, &clients, link) {
|
||||
+// /* Make sure it's on the current monitor, visible on the current tag, and mapped */
|
||||
+// if (tmp->mon == selmon && (tmp->tags & selmon->tagset[selmon->seltags]) && !client_is_unmanaged(tmp)) {
|
||||
+// current_tag_clients++;
|
||||
+// }
|
||||
+// }
|
||||
+//
|
||||
+// /* If there's more than 1 window here, mimic Mod+k instead of switching tags */
|
||||
+// if (current_tag_clients > 1) {
|
||||
+// Arg arg_focus = {.i = -1};
|
||||
+// focusstack(&arg_focus);
|
||||
+// }
|
||||
+ /* end of not changing tags logic */
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From a14dff19f38fffa498f3de4679952b39b4323502 Mon Sep 17 00:00:00 2001
|
||||
From 3a142ab58c5a66d2d71a8184b7e318d0f9d048c6 Mon Sep 17 00:00:00 2001
|
||||
From: pi66 <pixel2176@proton.me>
|
||||
Date: Wed, 8 Apr 2026 21:47:41 +0100
|
||||
Subject: [PATCH] feat: add pad/tool bindings and pen region
|
||||
Date: Mon, 27 Apr 2026 21:13:38 +0100
|
||||
Subject: [PATCH] fix: enable focus-follow-mouse for tablet pen input
|
||||
|
||||
---
|
||||
Makefile | 6 +-
|
||||
@@ -34,7 +34,7 @@ index 578194f..e0d1835 100644
|
||||
config.h:
|
||||
cp config.def.h $@
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8a6eda0..288494e 100644
|
||||
index 8a6eda0..9c678d4 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -4,6 +4,7 @@
|
||||
@@ -75,7 +75,7 @@ index 8a6eda0..288494e 100644
|
||||
+ { 0, 0, NULL, {0} }
|
||||
+};
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 44f3ad9..7572756 100644
|
||||
index 44f3ad9..a5ae8e7 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -51,6 +51,9 @@
|
||||
@@ -132,7 +132,7 @@ index 44f3ad9..7572756 100644
|
||||
static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
+static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, double x, double y, double dx, double dy);
|
||||
+static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, double x, double y, double dx, double dy, uint32_t time);
|
||||
+static void tablettoolproximity(struct wl_listener *listener, void *data);
|
||||
+static void tabletpadbutton(struct wl_listener *listener, void *data);
|
||||
+static void tablettoolaxis(struct wl_listener *listener, void *data);
|
||||
@@ -326,7 +326,7 @@ index 44f3ad9..7572756 100644
|
||||
+
|
||||
+void
|
||||
+tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y,
|
||||
+ double x, double y, double dx, double dy)
|
||||
+ double x, double y, double dx, double dy, uint32_t time)
|
||||
+{
|
||||
+ struct wlr_surface *surface = NULL;
|
||||
+ double sx, sy;
|
||||
@@ -351,7 +351,7 @@ index 44f3ad9..7572756 100644
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
+ motionnotify(time, NULL, 0, 0, 0, 0);
|
||||
+
|
||||
+ xytonode(cursor->x, cursor->y, &surface, NULL, NULL, &sx, &sy);
|
||||
+ if (surface && !wlr_surface_accepts_tablet_v2(surface, tablet))
|
||||
@@ -398,7 +398,7 @@ index 44f3ad9..7572756 100644
|
||||
+ destroytabletsurfacenotify(NULL, NULL);
|
||||
+ break;
|
||||
+ case WLR_TABLET_TOOL_PROXIMITY_IN:
|
||||
+ tablettoolmotion(tablet_tool, true, true, event->x, event->y, 0, 0);
|
||||
+ tablettoolmotion(tablet_tool, true, true, event->x, event->y, 0, 0, event->time_msec);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
@@ -414,7 +414,7 @@ index 44f3ad9..7572756 100644
|
||||
+ tablettoolmotion(tablet_tool,
|
||||
+ event->updated_axes & WLR_TABLET_TOOL_AXIS_X,
|
||||
+ event->updated_axes & WLR_TABLET_TOOL_AXIS_Y,
|
||||
+ event->x, event->y, event->dx, event->dy);
|
||||
+ event->x, event->y, event->dx, event->dy, event->time_msec);
|
||||
+
|
||||
+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE)
|
||||
+ wlr_tablet_v2_tablet_tool_notify_pressure(tablet_tool, event->pressure);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From a14dff19f38fffa498f3de4679952b39b4323502 Mon Sep 17 00:00:00 2001
|
||||
From 63b62ff508ecd2e74d95ba0550b3ec856b478bbb Mon Sep 17 00:00:00 2001
|
||||
From: pi66 <pixel2176@proton.me>
|
||||
Date: Wed, 8 Apr 2026 21:47:41 +0100
|
||||
Subject: [PATCH] feat: add pad/tool bindings and pen region
|
||||
Date: Mon, 27 Apr 2026 21:21:52 +0100
|
||||
Subject: [PATCH] fix: enable focus-follow-mouse for tablet pen input
|
||||
|
||||
---
|
||||
Makefile | 6 +-
|
||||
@@ -34,7 +34,7 @@ index 578194f..e0d1835 100644
|
||||
config.h:
|
||||
cp config.def.h $@
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8a6eda0..288494e 100644
|
||||
index 8a6eda0..9c678d4 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -4,6 +4,7 @@
|
||||
@@ -75,10 +75,10 @@ index 8a6eda0..288494e 100644
|
||||
+ { 0, 0, NULL, {0} }
|
||||
+};
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 44f3ad9..7572756 100644
|
||||
index 101a45f..f09b662 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -51,6 +51,9 @@
|
||||
@@ -52,6 +52,9 @@
|
||||
#include <wlr/types/wlr_session_lock_v1.h>
|
||||
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
@@ -88,7 +88,7 @@ index 44f3ad9..7572756 100644
|
||||
#include <wlr/types/wlr_viewporter.h>
|
||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
@@ -239,6 +242,20 @@ typedef struct {
|
||||
@@ -240,6 +243,20 @@ typedef struct {
|
||||
struct wl_listener destroy;
|
||||
} SessionLock;
|
||||
|
||||
@@ -109,7 +109,7 @@ index 44f3ad9..7572756 100644
|
||||
/* function declarations */
|
||||
static void applybounds(Client *c, struct wlr_box *bbox);
|
||||
static void applyrules(Client *c);
|
||||
@@ -268,6 +285,7 @@ static void createnotify(struct wl_listener *listener, void *data);
|
||||
@@ -269,6 +286,7 @@ 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 createpopup(struct wl_listener *listener, void *data);
|
||||
@@ -117,7 +117,7 @@ index 44f3ad9..7572756 100644
|
||||
static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
|
||||
static void cursorframe(struct wl_listener *listener, void *data);
|
||||
static void cursorwarptohint(void);
|
||||
@@ -281,6 +299,10 @@ static void destroynotify(struct wl_listener *listener, void *data);
|
||||
@@ -282,6 +300,10 @@ 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 destroykeyboardgroup(struct wl_listener *listener, void *data);
|
||||
@@ -128,11 +128,11 @@ index 44f3ad9..7572756 100644
|
||||
static Monitor *dirtomon(enum wlr_direction dir);
|
||||
static void focusclient(Client *c, int lift);
|
||||
static void focusmon(const Arg *arg);
|
||||
@@ -333,6 +355,12 @@ static void spawn(const Arg *arg);
|
||||
@@ -334,6 +356,12 @@ static void spawn(const Arg *arg);
|
||||
static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
+static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, double x, double y, double dx, double dy);
|
||||
+static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, double x, double y, double dx, double dy, uint32_t time);
|
||||
+static void tablettoolproximity(struct wl_listener *listener, void *data);
|
||||
+static void tabletpadbutton(struct wl_listener *listener, void *data);
|
||||
+static void tablettoolaxis(struct wl_listener *listener, void *data);
|
||||
@@ -141,7 +141,7 @@ index 44f3ad9..7572756 100644
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
@@ -390,6 +418,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint;
|
||||
@@ -391,6 +419,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint;
|
||||
static struct wlr_cursor *cursor;
|
||||
static struct wlr_xcursor_manager *cursor_mgr;
|
||||
|
||||
@@ -155,7 +155,7 @@ index 44f3ad9..7572756 100644
|
||||
static struct wlr_scene_rect *root_bg;
|
||||
static struct wlr_session_lock_manager_v1 *session_lock_mgr;
|
||||
static struct wlr_scene_rect *locked_bg;
|
||||
@@ -412,6 +447,14 @@ static struct wl_listener cursor_button = {.notify = buttonpress};
|
||||
@@ -413,6 +448,14 @@ 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};
|
||||
@@ -170,7 +170,7 @@ index 44f3ad9..7572756 100644
|
||||
static struct wl_listener gpu_reset = {.notify = gpureset};
|
||||
static struct wl_listener layout_change = {.notify = updatemons};
|
||||
static struct wl_listener new_idle_inhibitor = {.notify = createidleinhibitor};
|
||||
@@ -1199,6 +1242,27 @@ createpopup(struct wl_listener *listener, void *data)
|
||||
@@ -1200,6 +1243,27 @@ createpopup(struct wl_listener *listener, void *data)
|
||||
LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup);
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ index 44f3ad9..7572756 100644
|
||||
void
|
||||
cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)
|
||||
{
|
||||
@@ -1383,6 +1447,37 @@ destroykeyboardgroup(struct wl_listener *listener, void *data)
|
||||
@@ -1384,6 +1448,37 @@ destroykeyboardgroup(struct wl_listener *listener, void *data)
|
||||
free(group);
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ index 44f3ad9..7572756 100644
|
||||
Monitor *
|
||||
dirtomon(enum wlr_direction dir)
|
||||
{
|
||||
@@ -1581,6 +1676,7 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
@@ -1582,6 +1677,7 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
/* This event is raised by the backend when a new input device becomes
|
||||
* available. */
|
||||
struct wlr_input_device *device = data;
|
||||
@@ -244,7 +244,7 @@ index 44f3ad9..7572756 100644
|
||||
uint32_t caps;
|
||||
|
||||
switch (device->type) {
|
||||
@@ -1590,6 +1686,15 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
@@ -1591,6 +1687,15 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
case WLR_INPUT_DEVICE_POINTER:
|
||||
createpointer(wlr_pointer_from_input_device(device));
|
||||
break;
|
||||
@@ -260,7 +260,7 @@ index 44f3ad9..7572756 100644
|
||||
default:
|
||||
/* TODO handle other input device types */
|
||||
break;
|
||||
@@ -2585,6 +2690,8 @@ setup(void)
|
||||
@@ -2587,6 +2692,8 @@ setup(void)
|
||||
|
||||
relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy);
|
||||
|
||||
@@ -269,7 +269,7 @@ index 44f3ad9..7572756 100644
|
||||
/*
|
||||
* Creates a cursor, which is a wlroots utility for tracking the cursor
|
||||
* image shown on screen.
|
||||
@@ -2614,6 +2721,11 @@ setup(void)
|
||||
@@ -2616,6 +2723,11 @@ setup(void)
|
||||
wl_signal_add(&cursor->events.button, &cursor_button);
|
||||
wl_signal_add(&cursor->events.axis, &cursor_axis);
|
||||
wl_signal_add(&cursor->events.frame, &cursor_frame);
|
||||
@@ -281,7 +281,7 @@ index 44f3ad9..7572756 100644
|
||||
|
||||
cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
|
||||
wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape);
|
||||
@@ -2709,6 +2821,197 @@ tagmon(const Arg *arg)
|
||||
@@ -2711,6 +2823,197 @@ tagmon(const Arg *arg)
|
||||
setmon(sel, dirtomon(arg->i), 0);
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ index 44f3ad9..7572756 100644
|
||||
+
|
||||
+void
|
||||
+tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y,
|
||||
+ double x, double y, double dx, double dy)
|
||||
+ double x, double y, double dx, double dy, uint32_t time)
|
||||
+{
|
||||
+ struct wlr_surface *surface = NULL;
|
||||
+ double sx, sy;
|
||||
@@ -351,7 +351,7 @@ index 44f3ad9..7572756 100644
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
+ motionnotify(time, NULL, 0, 0, 0, 0);
|
||||
+
|
||||
+ xytonode(cursor->x, cursor->y, &surface, NULL, NULL, &sx, &sy);
|
||||
+ if (surface && !wlr_surface_accepts_tablet_v2(surface, tablet))
|
||||
@@ -398,7 +398,7 @@ index 44f3ad9..7572756 100644
|
||||
+ destroytabletsurfacenotify(NULL, NULL);
|
||||
+ break;
|
||||
+ case WLR_TABLET_TOOL_PROXIMITY_IN:
|
||||
+ tablettoolmotion(tablet_tool, true, true, event->x, event->y, 0, 0);
|
||||
+ tablettoolmotion(tablet_tool, true, true, event->x, event->y, 0, 0, event->time_msec);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
@@ -414,7 +414,7 @@ index 44f3ad9..7572756 100644
|
||||
+ tablettoolmotion(tablet_tool,
|
||||
+ event->updated_axes & WLR_TABLET_TOOL_AXIS_X,
|
||||
+ event->updated_axes & WLR_TABLET_TOOL_AXIS_Y,
|
||||
+ event->x, event->y, event->dx, event->dy);
|
||||
+ event->x, event->y, event->dx, event->dy, event->time_msec);
|
||||
+
|
||||
+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE)
|
||||
+ wlr_tablet_v2_tablet_tool_notify_pressure(tablet_tool, event->pressure);
|
||||
|
||||
@@ -8,13 +8,19 @@ KNOWN BUGS:
|
||||
- [git branch](https://codeberg.org/fauxmight/dwl/src/branch/touch-input)
|
||||
- [touch-input-wlroots-next-f4249db.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/touch-input/touch-input-wlroots-next-f4249db.patch)
|
||||
- [touch-input-0.8.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/touch-input/touch-input-0.8.patch)
|
||||
- [touch-input-0.8-osu-ver.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/touch-input/touch-input-0.8-osu-ver.patch)
|
||||
|
||||
### Authors
|
||||
#### Current
|
||||
- [fauxmight](https://codeberg.org/fauxmight)
|
||||
- [6z7y](https://codeberg.org/6z7y) -- maintaining `osu!` version of the `touch-input` patch
|
||||
#### Historic
|
||||
- [minego](https://codeberg.org/minego)
|
||||
- [Unprex](https://github.com/Unprex)
|
||||
|
||||
|
||||
### Changelog
|
||||
- 2026-06-15 Add support for osu! fullscreen touch input (fix cursor stuck issue)
|
||||
- 2026-02-26 Update patch for dwl v0.8 and dwl wlroots-next branch commit f4249db
|
||||
- 2025-01-01 @fauxmight took over maintenance. Previous maintainer @minego notes [lack of available time](https://codeberg.org/dwl/dwl-patches/pulls/102#issuecomment-2557944)
|
||||
- 2024-02-11 Corrected issue where motion events where not sending notifications for unfocused clients such as an on screen keyboard
|
||||
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 44f3ad9..977f2c8 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <wlr/types/wlr_data_device.h>
|
||||
#include <wlr/types/wlr_drm.h>
|
||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||
+#include <wlr/types/wlr_ext_data_control_v1.h>
|
||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||
@@ -51,6 +52,7 @@
|
||||
#include <wlr/types/wlr_session_lock_v1.h>
|
||||
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
+#include <wlr/types/wlr_touch.h>
|
||||
#include <wlr/types/wlr_viewporter.h>
|
||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
@@ -161,6 +163,12 @@ typedef struct {
|
||||
struct wl_listener destroy;
|
||||
} KeyboardGroup;
|
||||
|
||||
+typedef struct TouchGroup {
|
||||
+ struct wl_list link;
|
||||
+ struct wlr_touch *touch;
|
||||
+ Monitor *m;
|
||||
+} TouchGroup;
|
||||
+
|
||||
typedef struct {
|
||||
/* Must keep this field first */
|
||||
unsigned int type; /* LayerShell */
|
||||
@@ -269,6 +277,7 @@ static void createpointer(struct wlr_pointer *pointer);
|
||||
static void createpointerconstraint(struct wl_listener *listener, void *data);
|
||||
static void createpopup(struct wl_listener *listener, void *data);
|
||||
static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
|
||||
+static void createtouch(struct wlr_touch *touch);
|
||||
static void cursorframe(struct wl_listener *listener, void *data);
|
||||
static void cursorwarptohint(void);
|
||||
static void destroydecoration(struct wl_listener *listener, void *data);
|
||||
@@ -338,6 +347,10 @@ static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
+static void touchdown(struct wl_listener *listener, void *data);
|
||||
+static void touchup(struct wl_listener *listener, void *data);
|
||||
+static void touchframe(struct wl_listener *listener, void *data);
|
||||
+static void touchmotion(struct wl_listener *listener, void *data);
|
||||
static void unlocksession(struct wl_listener *listener, void *data);
|
||||
static void unmaplayersurfacenotify(struct wl_listener *listener, void *data);
|
||||
static void unmapnotify(struct wl_listener *listener, void *data);
|
||||
@@ -405,6 +418,7 @@ static struct wlr_output_layout *output_layout;
|
||||
static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
+static struct wl_list touches;
|
||||
|
||||
/* global event handlers */
|
||||
static struct wl_listener cursor_axis = {.notify = axisnotify};
|
||||
@@ -434,6 +448,10 @@ static struct wl_listener request_set_sel = {.notify = setsel};
|
||||
static struct wl_listener request_set_cursor_shape = {.notify = setcursorshape};
|
||||
static struct wl_listener request_start_drag = {.notify = requeststartdrag};
|
||||
static struct wl_listener start_drag = {.notify = startdrag};
|
||||
+static struct wl_listener touch_down = {.notify = touchdown};
|
||||
+static struct wl_listener touch_frame = {.notify = touchframe};
|
||||
+static struct wl_listener touch_motion = {.notify = touchmotion};
|
||||
+static struct wl_listener touch_up = {.notify = touchup};
|
||||
static struct wl_listener new_session_lock = {.notify = locksession};
|
||||
|
||||
#ifdef XWAYLAND
|
||||
@@ -585,7 +603,7 @@ arrangelayers(Monitor *m)
|
||||
arrange(m);
|
||||
}
|
||||
|
||||
- /* Arrange non-exlusive surfaces from top->bottom */
|
||||
+ /* Arrange non-exclusive surfaces from top->bottom */
|
||||
for (i = 3; i >= 0; i--)
|
||||
arrangelayer(m, &m->layers[i], &usable_area, 0);
|
||||
|
||||
@@ -781,6 +799,10 @@ cleanuplisteners(void)
|
||||
wl_list_remove(&request_set_cursor_shape.link);
|
||||
wl_list_remove(&request_start_drag.link);
|
||||
wl_list_remove(&start_drag.link);
|
||||
+ wl_list_remove(&touch_down.link);
|
||||
+ wl_list_remove(&touch_frame.link);
|
||||
+ wl_list_remove(&touch_motion.link);
|
||||
+ wl_list_remove(&touch_up.link);
|
||||
wl_list_remove(&new_session_lock.link);
|
||||
#ifdef XWAYLAND
|
||||
wl_list_remove(&new_xwayland_surface.link);
|
||||
@@ -1199,6 +1221,16 @@ createpopup(struct wl_listener *listener, void *data)
|
||||
LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup);
|
||||
}
|
||||
|
||||
+void
|
||||
+createtouch(struct wlr_touch *wlr_touch)
|
||||
+{
|
||||
+ TouchGroup *touch = ecalloc(1, sizeof(TouchGroup));
|
||||
+
|
||||
+ touch->touch = wlr_touch;
|
||||
+ wl_list_insert(&touches, &touch->link);
|
||||
+ wlr_cursor_attach_input_device(cursor, &wlr_touch->base);
|
||||
+}
|
||||
+
|
||||
void
|
||||
cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)
|
||||
{
|
||||
@@ -1590,6 +1622,9 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
case WLR_INPUT_DEVICE_POINTER:
|
||||
createpointer(wlr_pointer_from_input_device(device));
|
||||
break;
|
||||
+ case WLR_INPUT_DEVICE_TOUCH:
|
||||
+ createtouch(wlr_touch_from_input_device(device));
|
||||
+ break;
|
||||
default:
|
||||
/* TODO handle other input device types */
|
||||
break;
|
||||
@@ -1602,6 +1637,8 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
caps = WL_SEAT_CAPABILITY_POINTER;
|
||||
if (!wl_list_empty(&kb_group->wlr_group->devices))
|
||||
caps |= WL_SEAT_CAPABILITY_KEYBOARD;
|
||||
+ if (!wl_list_empty(&touches))
|
||||
+ caps |= WL_SEAT_CAPABILITY_TOUCH;
|
||||
wlr_seat_set_capabilities(seat, caps);
|
||||
}
|
||||
|
||||
@@ -2133,7 +2170,7 @@ powermgrsetmode(struct wl_listener *listener, void *data)
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
- m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the ouput */
|
||||
+ m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the output */
|
||||
wlr_output_state_set_enabled(&state, event->mode);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
|
||||
@@ -2455,7 +2492,7 @@ setup(void)
|
||||
wlr_log_init(log_level, NULL);
|
||||
|
||||
/* The Wayland display is managed by libwayland. It handles accepting
|
||||
- * clients from the Unix socket, manging Wayland globals, and so on. */
|
||||
+ * clients from the Unix socket, managing Wayland globals, and so on. */
|
||||
dpy = wl_display_create();
|
||||
event_loop = wl_display_get_event_loop(dpy);
|
||||
|
||||
@@ -2518,6 +2555,7 @@ setup(void)
|
||||
wlr_export_dmabuf_manager_v1_create(dpy);
|
||||
wlr_screencopy_manager_v1_create(dpy);
|
||||
wlr_data_control_manager_v1_create(dpy);
|
||||
+ wlr_ext_data_control_manager_v1_create(dpy, 1);
|
||||
wlr_primary_selection_v1_device_manager_create(dpy);
|
||||
wlr_viewporter_create(dpy);
|
||||
wlr_single_pixel_buffer_manager_v1_create(dpy);
|
||||
@@ -2615,6 +2653,13 @@ setup(void)
|
||||
wl_signal_add(&cursor->events.axis, &cursor_axis);
|
||||
wl_signal_add(&cursor->events.frame, &cursor_frame);
|
||||
|
||||
+ wl_list_init(&touches);
|
||||
+
|
||||
+ wl_signal_add(&cursor->events.touch_down, &touch_down);
|
||||
+ wl_signal_add(&cursor->events.touch_frame, &touch_frame);
|
||||
+ wl_signal_add(&cursor->events.touch_motion, &touch_motion);
|
||||
+ wl_signal_add(&cursor->events.touch_up, &touch_up);
|
||||
+
|
||||
cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
|
||||
wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape);
|
||||
|
||||
@@ -2787,6 +2832,111 @@ toggleview(const Arg *arg)
|
||||
printstatus();
|
||||
}
|
||||
|
||||
+void
|
||||
+touchdown(struct wl_listener *listener, void *data)
|
||||
+{
|
||||
+ struct wlr_touch_down_event *event = data;
|
||||
+ double lx, ly;
|
||||
+ double sx, sy;
|
||||
+ struct wlr_surface *surface;
|
||||
+ Client *c = NULL;
|
||||
+ Monitor *m;
|
||||
+
|
||||
+ wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
+
|
||||
+ // Map the input to the appropriate output
|
||||
+ wl_list_for_each(m, &mons, link) {
|
||||
+ if (m == NULL || m->wlr_output == NULL)
|
||||
+ continue;
|
||||
+ if (event->touch->output_name != NULL &&
|
||||
+ 0 != strcmp(event->touch->output_name, m->wlr_output->name))
|
||||
+ continue;
|
||||
+ wlr_cursor_map_input_to_output(cursor, &event->touch->base, m->wlr_output);
|
||||
+ }
|
||||
+
|
||||
+ wlr_cursor_absolute_to_layout_coords(cursor, &event->touch->base,
|
||||
+ event->x, event->y, &lx, &ly);
|
||||
+
|
||||
+ /* Find the client under the touch point */
|
||||
+ xytonode(lx, ly, &surface, &c, NULL, &sx, &sy);
|
||||
+ if (sloppyfocus && c)
|
||||
+ focusclient(c, 0);
|
||||
+
|
||||
+ // Send touch event to client (if any)
|
||||
+ if (surface != NULL) {
|
||||
+ wlr_seat_touch_notify_down(seat, surface, event->time_msec,
|
||||
+ event->touch_id, sx, sy);
|
||||
+ }
|
||||
+
|
||||
+ // ALWAYS move cursor and send click - no conditions!
|
||||
+ wlr_cursor_warp_closest(cursor, NULL, lx, ly);
|
||||
+ motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
+
|
||||
+ wlr_seat_pointer_notify_button(seat, event->time_msec,
|
||||
+ BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
|
||||
+ wlr_seat_pointer_notify_frame(seat);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+touchup(struct wl_listener *listener, void *data)
|
||||
+{
|
||||
+ struct wlr_touch_up_event *event = data;
|
||||
+
|
||||
+ if (!wlr_seat_touch_get_point(seat, event->touch_id))
|
||||
+ return;
|
||||
+
|
||||
+ wlr_seat_touch_notify_up(seat, event->time_msec, event->touch_id);
|
||||
+
|
||||
+ // Always send click release
|
||||
+ wlr_seat_pointer_notify_button(seat, event->time_msec,
|
||||
+ BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
|
||||
+ wlr_seat_pointer_notify_frame(seat);
|
||||
+
|
||||
+ wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+touchframe(struct wl_listener *listener, void *data)
|
||||
+{
|
||||
+ wlr_seat_touch_notify_frame(seat);
|
||||
+ wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+touchmotion(struct wl_listener *listener, void *data)
|
||||
+{
|
||||
+ struct wlr_touch_motion_event *event = data;
|
||||
+ double lx, ly;
|
||||
+ double sx, sy;
|
||||
+ struct wlr_surface *surface;
|
||||
+ Client *c = NULL;
|
||||
+
|
||||
+ if (!wlr_seat_touch_get_point(seat, event->touch_id)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ wlr_cursor_absolute_to_layout_coords(cursor, &event->touch->base, event->x, event->y, &lx, &ly);
|
||||
+ wlr_cursor_warp_closest(cursor, NULL, lx, ly);
|
||||
+ motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
+ wlr_seat_pointer_notify_frame(seat);
|
||||
+
|
||||
+ xytonode(lx, ly, &surface, &c, NULL, &sx, &sy);
|
||||
+
|
||||
+ if (c != NULL && surface != NULL) {
|
||||
+ if (sloppyfocus)
|
||||
+ focusclient(c, 0);
|
||||
+ wlr_seat_touch_point_focus(seat, surface, event->time_msec, event->touch_id, sx, sy);
|
||||
+ } else {
|
||||
+ if (sloppyfocus)
|
||||
+ focusclient(NULL, 0);
|
||||
+ wlr_seat_touch_point_clear_focus(seat, event->time_msec, event->touch_id);
|
||||
+ }
|
||||
+ wlr_seat_touch_notify_motion(seat, event->time_msec, event->touch_id, sx, sy);
|
||||
+
|
||||
+ wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
+}
|
||||
+
|
||||
+
|
||||
void
|
||||
unlocksession(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -0,0 +1,17 @@
|
||||
# Description
|
||||
Make tag 0 a regular tag
|
||||
|
||||
### Dependencies
|
||||
|
||||
This patch comes in **two versions**:
|
||||
|
||||
- **`bar_zerotag.patch`** - Depends on the [bar](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/bar/) patch.
|
||||
- **`zerotag.patch`** - No dependencies.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/6z7y/dwl-patches/raw/branch/zerotag/patches/zerotag/zerotag.patch)
|
||||
- [main 2026-02-25](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/zerotag/zerotag.patch)
|
||||
|
||||
### Authors
|
||||
- [6z7y](https://codeberg.org/6z7y)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 7da50d2..f058a17 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -21,7 +21,7 @@ static uint32_t colors[][3] = {
|
||||
};
|
||||
|
||||
/* tagging */
|
||||
-static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||
+static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
|
||||
|
||||
/* logging */
|
||||
static int log_level = WLR_ERROR;
|
||||
@@ -145,8 +145,6 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
- { MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
@@ -160,8 +158,10 @@ static const Key keys[] = {
|
||||
TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6),
|
||||
TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7),
|
||||
TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8),
|
||||
+ TAGKEYS( XKB_KEY_0, XKB_KEY_parenright, 9),
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_q, quit, {0} },
|
||||
|
||||
+
|
||||
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
|
||||
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} },
|
||||
/* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is
|
||||
@@ -0,0 +1,30 @@
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8a6eda0..b0fdfe8 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -15,7 +15,7 @@ static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */
|
||||
|
||||
/* tagging - TAGCOUNT must be no greater than 31 */
|
||||
-#define TAGCOUNT (9)
|
||||
+#define TAGCOUNT (10)
|
||||
|
||||
/* logging */
|
||||
static int log_level = WLR_ERROR;
|
||||
@@ -138,8 +138,6 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
- { MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
@@ -153,6 +151,7 @@ static const Key keys[] = {
|
||||
TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6),
|
||||
TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7),
|
||||
TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8),
|
||||
+ TAGKEYS( XKB_KEY_0, XKB_KEY_parenright, 9),
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_q, quit, {0} },
|
||||
|
||||
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
|
||||
Reference in New Issue
Block a user