mirror of
https://codeberg.org/dwl/dwl-patches.git
synced 2025-09-07 11:44:51 +00:00
Merge pull request 'main' (#1) from dwl/dwl-patches:main into main
Reviewed-on: https://codeberg.org/MayOrMayNotBeACat/dwl-patches/pulls/1
This commit is contained in:
commit
71afcd34fb
@ -18,6 +18,9 @@ Reloading the compositor will replace all functionality except for `main`, `setu
|
||||
Note that you're responsible yourself for reloading ressources like fonts, which may only get acquired once.
|
||||
A lot of components of dwl will also only get run on a trigger (the tiling for example).
|
||||
So not every change will be immediate.
|
||||
Furthermore, any patch adding more global state to dwl cannot currently be reloaded properly since
|
||||
we keep state in the cold part. These patches will still work and their functionality will (hopefully) be
|
||||
reloadable but you will need to restart the compositor once.
|
||||
|
||||
#### Notes
|
||||
##### reduce compile errors
|
||||
@ -28,12 +31,79 @@ So you may want to disable this compile option in order to get readable compiler
|
||||
This does depend on you having a notification daemon like `dunst` or `mako` running as well as
|
||||
having `notify-send` installed in order for the compositor to inform you of the reload.
|
||||
|
||||
|
||||
#### How?
|
||||
Most of all dwl functionality is moved into a shared object file `dwl.so`, which can be reloaded at runtime.
|
||||
|
||||
#### How do I make this work with other patches?
|
||||
Most patches should already put everything in more or less the correct place but if they don't, then here is
|
||||
where you learn how to fix it.
|
||||
|
||||
The concept itself is quite simple. We compile dwl.c twice once normally and once with the `HOT` macro defined.
|
||||
The first run will yield the executable and the second will yield a shared object file to be reloaded at runtime.
|
||||
From the cold part there are some newly available macros:
|
||||
> symbol names are written as-is, never as string literals
|
||||
* `TSYM(T, s)` dynamically loads the symbol `s` with type `T` from the shared object file use this if you need to call functions in the cold part (i.e. the `setup` function).
|
||||
* `CSYM(T, v)` dynamically accesses the value of the symbol `v` of type `T` from the shared object. Use this to query values from config.h for example.
|
||||
* `LISTEN_GLOBAL(E, L)` is similar to the `LISTEN` macro. `E` is an event and `L` the name of a global
|
||||
listener. Current implementation is a bit messy and I may fix it if someone bothers me about it.
|
||||
* `UNLISTEN(L)` takes a listener and unregisteres it. This is important for reloading.
|
||||
|
||||
When adding new code there are some considerations to be made. Since dwl decorates all symbols with `static` by default, we cannot access them as-is.
|
||||
C's macro system is a bit too powerful though and we use this to our advantage. We will repeatedly define and
|
||||
undefine a macro called `static` in order to replace the `static` keyword inside some sections.
|
||||
This allows us to do less refactoring and preserve a lot of the original patch compatability since we're only
|
||||
strategically adding lines. We're tring to be as minimally invasive as we can.
|
||||
As a general guide:
|
||||
* global state should be global for the cold part and `extern` in the cold part meaning it should be inside a block like this:
|
||||
```C
|
||||
#ifdef HOT
|
||||
#define static extern
|
||||
#else
|
||||
#define static
|
||||
#endif
|
||||
... // your global variables go here
|
||||
#undef static
|
||||
```
|
||||
* function declarations should be visible in the hot part but not included in the cold part meaning they should be enclosed like this:
|
||||
```C
|
||||
#ifdef HOT
|
||||
#define static
|
||||
... // your function declarations go here
|
||||
#undef static
|
||||
#endif
|
||||
```
|
||||
* static data like the event handler structs in the current `main` branch are a bit more difficult but we will let them reside inside the hot part.
|
||||
Thus, we enclose them the same way we do functions:
|
||||
```C
|
||||
#ifdef HOT
|
||||
#define static
|
||||
... // your struct wl_listener event handlers go here
|
||||
#undef static
|
||||
#endif
|
||||
```
|
||||
* function definitions should go in the hot part, so they need to be inside a big block like this:
|
||||
```C
|
||||
#ifdef HOT
|
||||
... // function definitions here
|
||||
#endif
|
||||
* enfore use of the `LISTEN_GLOBAL` and `UNLISTEN` macros (I know this sucks but what can I do, I need to get
|
||||
access to the callbacks somehow). So you want
|
||||
* `wl_list_remove(listener.link)` to become `UNLISTEN(listener)` and
|
||||
* `wl_signal_add(event, global_listener)` to become `LISTEN_GLOBAL(event, global_listener)`.
|
||||
* Make sure that any patch you're using also uses static everywhere.
|
||||
* If a patch adds any config variables that are accessed in the cold part (i.e. probably `setup`),
|
||||
then you'll have to manually remove the `static` keyword from them.
|
||||
|
||||
Note that usually you do not have to create the big `#ifdef` blocks yourself.
|
||||
There is for example already a huge `#ifdef HOT`-delimited codeblock at the bottom
|
||||
of dwl.c where all the function definitions go.
|
||||
|
||||
If you have any troubles, feel free to reach out.
|
||||
|
||||
### Download
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/hot-reload/hot-reload-0.7.patch)
|
||||
- [main 2025-02-14](/dwl/dwl-patches/raw/branch/main/patches/hot-reload/hot-reload.patch)
|
||||
- [main 2025-05-30](/dwl/dwl-patches/raw/branch/main/patches/hot-reload/hot-reload.patch)
|
||||
- find the repo for the patch [here](/Sivecano/dwl/src/branch/hot-reload)
|
||||
### Authors
|
||||
- [Sivecano](https://codeberg.org/Sivecano)
|
||||
|
@ -1,4 +1,4 @@
|
||||
From caa1adaf02ab4f9a326761ade5d1346149bc7c59 Mon Sep 17 00:00:00 2001
|
||||
From 559c635056f23d55df3f83c12d1201a7328f648f Mon Sep 17 00:00:00 2001
|
||||
From: Sivecano <sivecano@gmail.com>
|
||||
Date: Sun, 26 Jan 2025 18:30:02 +0100
|
||||
Subject: [PATCH] redo hot-reloading in one file
|
||||
@ -12,7 +12,7 @@ Subject: [PATCH] redo hot-reloading in one file
|
||||
5 files changed, 351 insertions(+), 50 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 3358bae..70d3d0f 100644
|
||||
index 3358bae..e7ee9ff 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -13,13 +13,16 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \
|
||||
@ -28,7 +28,7 @@ index 3358bae..70d3d0f 100644
|
||||
dwl: dwl.o util.o
|
||||
$(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@
|
||||
-dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
|
||||
+dwl.o: dwl.c cursor-shape-v1-protocol.h \
|
||||
+dwl.o: dwl.c config.mk cursor-shape-v1-protocol.h \
|
||||
+ pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \
|
||||
+ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h
|
||||
+dwl.so: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
|
||||
@ -99,7 +99,7 @@ index 22d2171..6e3dda1 100644
|
||||
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index def2562..7e059ad 100644
|
||||
index def2562..1c9ab67 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1,6 +1,15 @@
|
||||
@ -652,7 +652,7 @@ index def2562..7e059ad 100644
|
||||
+ wlr_log(WLR_ERROR, "couldn't load new dwl module from %s", get_module_path());
|
||||
+
|
||||
+ if (fork() == 0)
|
||||
+ execl("/bin/env", "--", "Notify-send", "-u", "low", "failed to reload dwl", NULL);
|
||||
+ execl("/bin/env", "--", "notify-send", "-u", "low", "failed to reload dwl", NULL);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
@ -766,5 +766,5 @@ index 226980d..11aab34 100644
|
||||
+struct listens* append_listener(struct wl_listener* l, struct listens* ls);
|
||||
+struct listens* remove_listener(struct wl_listener* l, struct listens* ls);
|
||||
--
|
||||
2.48.1
|
||||
2.49.0
|
||||
|
||||
|
@ -1,18 +1,18 @@
|
||||
From 79fbc2405919a049a35dd58e860b6519ebb7943b Mon Sep 17 00:00:00 2001
|
||||
From 44ce31430dd7d2c0a6c1dc29534f22fb33b25bca Mon Sep 17 00:00:00 2001
|
||||
From: Sivecano <sivecano@gmail.com>
|
||||
Date: Sun, 26 Jan 2025 18:30:02 +0100
|
||||
Subject: [PATCH] redo hot-reloading in one file
|
||||
|
||||
---
|
||||
Makefile | 19 ++-
|
||||
Makefile | 19 +-
|
||||
config.def.h | 5 +-
|
||||
dwl.c | 475 +++++++++++++++++++++++++++++++++++++++------------
|
||||
dwl.c | 484 +++++++++++++++++++++++++++++++++++++++------------
|
||||
util.c | 34 ++++
|
||||
util.h | 6 +
|
||||
5 files changed, 421 insertions(+), 118 deletions(-)
|
||||
5 files changed, 433 insertions(+), 115 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 578194f..0714ed1 100644
|
||||
index 578194f..69c1b54 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -13,13 +13,16 @@ DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \
|
||||
@ -28,7 +28,7 @@ index 578194f..0714ed1 100644
|
||||
dwl: dwl.o util.o
|
||||
$(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@
|
||||
-dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
|
||||
+dwl.o: dwl.c cursor-shape-v1-protocol.h \
|
||||
+dwl.o: dwl.c config.mk cursor-shape-v1-protocol.h \
|
||||
+ pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \
|
||||
+ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h
|
||||
+dwl.so: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
|
||||
@ -99,7 +99,7 @@ index 22d2171..6e3dda1 100644
|
||||
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ec4ca86..8d1eceb 100644
|
||||
index 4816159..70e99be 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1,6 +1,15 @@
|
||||
@ -265,14 +265,37 @@ index ec4ca86..8d1eceb 100644
|
||||
static struct wl_listener request_set_psel = {.notify = setpsel};
|
||||
static struct wl_listener request_set_sel = {.notify = setsel};
|
||||
static struct wl_listener request_set_cursor_shape = {.notify = setcursorshape};
|
||||
@@ -449,8 +535,38 @@ static struct wl_listener xwayland_ready = {.notify = xwaylandready};
|
||||
static struct wlr_xwayland *xwayland;
|
||||
#endif
|
||||
@@ -436,7 +522,15 @@ 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};
|
||||
|
||||
+/* undoes the shadowing of static from above */
|
||||
+#endif
|
||||
+#undef static
|
||||
+
|
||||
+
|
||||
#ifdef XWAYLAND
|
||||
+#ifdef HOT
|
||||
+#define static
|
||||
+
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
static void associatex11(struct wl_listener *listener, void *data);
|
||||
static void configurex11(struct wl_listener *listener, void *data);
|
||||
@@ -446,11 +540,45 @@ static void sethints(struct wl_listener *listener, void *data);
|
||||
static void xwaylandready(struct wl_listener *listener, void *data);
|
||||
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
|
||||
static struct wl_listener xwayland_ready = {.notify = xwaylandready};
|
||||
+
|
||||
+#define static extern
|
||||
+#else
|
||||
+#define static
|
||||
+#endif
|
||||
+
|
||||
static struct wlr_xwayland *xwayland;
|
||||
+
|
||||
+#undef static
|
||||
+#endif
|
||||
+
|
||||
+/* this is where we put global hot-reload state */
|
||||
+#ifdef HOT
|
||||
+#define COLD extern
|
||||
@ -292,8 +315,8 @@ index ec4ca86..8d1eceb 100644
|
||||
+#ifndef HOT
|
||||
+static char* runpath;
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
#endif
|
||||
|
||||
+
|
||||
+#ifdef HOT
|
||||
+
|
||||
@ -304,7 +327,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
/* attempt to encapsulate suck into one file */
|
||||
#include "client.h"
|
||||
@@ -692,10 +808,12 @@ checkidleinhibitor(struct wlr_surface *exclude)
|
||||
@@ -695,10 +823,12 @@ checkidleinhibitor(struct wlr_surface *exclude)
|
||||
wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited);
|
||||
}
|
||||
|
||||
@ -318,7 +341,7 @@ index ec4ca86..8d1eceb 100644
|
||||
#ifdef XWAYLAND
|
||||
wlr_xwayland_destroy(xwayland);
|
||||
xwayland = NULL;
|
||||
@@ -707,7 +825,7 @@ cleanup(void)
|
||||
@@ -710,7 +840,7 @@ cleanup(void)
|
||||
}
|
||||
wlr_xcursor_manager_destroy(cursor_mgr);
|
||||
|
||||
@ -327,7 +350,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
/* If it's not destroyed manually it will cause a use-after-free of wlr_seat.
|
||||
* Destroy it until it's fixed in the wlroots side */
|
||||
@@ -719,6 +837,8 @@ cleanup(void)
|
||||
@@ -722,6 +852,8 @@ cleanup(void)
|
||||
wlr_scene_node_destroy(&scene->tree.node);
|
||||
}
|
||||
|
||||
@ -336,7 +359,7 @@ index ec4ca86..8d1eceb 100644
|
||||
void
|
||||
cleanupmon(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -732,10 +852,10 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
@@ -735,10 +867,10 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
wlr_layer_surface_v1_destroy(l->layer_surface);
|
||||
}
|
||||
|
||||
@ -350,7 +373,7 @@ index ec4ca86..8d1eceb 100644
|
||||
m->wlr_output->data = NULL;
|
||||
wlr_output_layout_remove(output_layout, m->wlr_output);
|
||||
wlr_scene_output_destroy(m->scene_output);
|
||||
@@ -748,37 +868,37 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
@@ -751,37 +883,37 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
void
|
||||
cleanuplisteners(void)
|
||||
{
|
||||
@ -418,17 +441,16 @@ index ec4ca86..8d1eceb 100644
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -905,8 +1025,7 @@ commitpopup(struct wl_listener *listener, void *data)
|
||||
@@ -908,7 +1040,7 @@ commitpopup(struct wl_listener *listener, void *data)
|
||||
box.x -= (type == LayerShell ? l->scene->node.x : c->geom.x);
|
||||
box.y -= (type == LayerShell ? l->scene->node.y : c->geom.y);
|
||||
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
||||
- wl_list_remove(&listener->link);
|
||||
- free(listener);
|
||||
+ UNLISTEN(listener);
|
||||
free(listener);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1236,8 +1355,8 @@ destroydecoration(struct wl_listener *listener, void *data)
|
||||
@@ -1239,8 +1371,8 @@ destroydecoration(struct wl_listener *listener, void *data)
|
||||
{
|
||||
Client *c = wl_container_of(listener, c, destroy_decoration);
|
||||
|
||||
@ -439,27 +461,25 @@ index ec4ca86..8d1eceb 100644
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1246,8 +1365,7 @@ destroydragicon(struct wl_listener *listener, void *data)
|
||||
@@ -1249,7 +1381,7 @@ destroydragicon(struct wl_listener *listener, void *data)
|
||||
/* Focus enter isn't sent during drag, so refocus the focused node. */
|
||||
focusclient(focustop(selmon), 1);
|
||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
- wl_list_remove(&listener->link);
|
||||
- free(listener);
|
||||
+ UNLISTEN(listener);
|
||||
free(listener);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1256,8 +1374,7 @@ destroyidleinhibitor(struct wl_listener *listener, void *data)
|
||||
@@ -1259,7 +1391,7 @@ destroyidleinhibitor(struct wl_listener *listener, void *data)
|
||||
/* `data` is the wlr_surface of the idle inhibitor being destroyed,
|
||||
* at this point the idle inhibitor is still in the list of the manager */
|
||||
checkidleinhibitor(wlr_surface_get_root_surface(data));
|
||||
- wl_list_remove(&listener->link);
|
||||
- free(listener);
|
||||
+ UNLISTEN(listener);
|
||||
free(listener);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1266,9 +1383,9 @@ destroylayersurfacenotify(struct wl_listener *listener, void *data)
|
||||
@@ -1269,9 +1401,9 @@ destroylayersurfacenotify(struct wl_listener *listener, void *data)
|
||||
LayerSurface *l = wl_container_of(listener, l, destroy);
|
||||
|
||||
wl_list_remove(&l->link);
|
||||
@ -472,7 +492,7 @@ index ec4ca86..8d1eceb 100644
|
||||
wlr_scene_node_destroy(&l->scene->node);
|
||||
wlr_scene_node_destroy(&l->popups->node);
|
||||
free(l);
|
||||
@@ -1287,9 +1404,9 @@ destroylock(SessionLock *lock, int unlock)
|
||||
@@ -1290,9 +1422,9 @@ destroylock(SessionLock *lock, int unlock)
|
||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
|
||||
destroy:
|
||||
@ -485,7 +505,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
wlr_scene_node_destroy(&lock->scene->node);
|
||||
cur_lock = NULL;
|
||||
@@ -1303,7 +1420,7 @@ destroylocksurface(struct wl_listener *listener, void *data)
|
||||
@@ -1306,7 +1438,7 @@ destroylocksurface(struct wl_listener *listener, void *data)
|
||||
struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface;
|
||||
|
||||
m->lock_surface = NULL;
|
||||
@ -494,7 +514,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
if (lock_surface->surface != seat->keyboard_state.focused_surface)
|
||||
return;
|
||||
@@ -1323,23 +1440,23 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
@@ -1326,23 +1458,23 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
Client *c = wl_container_of(listener, c, destroy);
|
||||
@ -530,7 +550,7 @@ index ec4ca86..8d1eceb 100644
|
||||
}
|
||||
free(c);
|
||||
}
|
||||
@@ -1354,7 +1471,7 @@ destroypointerconstraint(struct wl_listener *listener, void *data)
|
||||
@@ -1357,7 +1489,7 @@ destroypointerconstraint(struct wl_listener *listener, void *data)
|
||||
active_constraint = NULL;
|
||||
}
|
||||
|
||||
@ -539,7 +559,7 @@ index ec4ca86..8d1eceb 100644
|
||||
free(pointer_constraint);
|
||||
}
|
||||
|
||||
@@ -1370,9 +1487,9 @@ destroykeyboardgroup(struct wl_listener *listener, void *data)
|
||||
@@ -1373,9 +1505,9 @@ destroykeyboardgroup(struct wl_listener *listener, void *data)
|
||||
{
|
||||
KeyboardGroup *group = wl_container_of(listener, group, destroy);
|
||||
wl_event_source_remove(group->key_repeat_source);
|
||||
@ -552,7 +572,7 @@ index ec4ca86..8d1eceb 100644
|
||||
wlr_keyboard_group_destroy(group->wlr_group);
|
||||
free(group);
|
||||
}
|
||||
@@ -1538,8 +1655,8 @@ gpureset(struct wl_listener *listener, void *data)
|
||||
@@ -1541,8 +1673,8 @@ gpureset(struct wl_listener *listener, void *data)
|
||||
if (!(alloc = wlr_allocator_autocreate(backend, drw)))
|
||||
die("couldn't recreate allocator");
|
||||
|
||||
@ -563,7 +583,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
wlr_compositor_set_renderer(compositor, drw);
|
||||
|
||||
@@ -2229,6 +2346,8 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
@@ -2232,6 +2364,8 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
|
||||
}
|
||||
|
||||
@ -572,7 +592,7 @@ index ec4ca86..8d1eceb 100644
|
||||
void
|
||||
run(char *startup_cmd)
|
||||
{
|
||||
@@ -2268,11 +2387,11 @@ run(char *startup_cmd)
|
||||
@@ -2271,11 +2405,11 @@ run(char *startup_cmd)
|
||||
if (fd_set_nonblock(STDOUT_FILENO) < 0)
|
||||
close(STDOUT_FILENO);
|
||||
|
||||
@ -586,7 +606,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
/* TODO hack to get cursor to display in its initial location (100, 100)
|
||||
* instead of (0, 0) and then jumping. still may not be fully
|
||||
@@ -2288,6 +2407,9 @@ run(char *startup_cmd)
|
||||
@@ -2291,6 +2425,9 @@ run(char *startup_cmd)
|
||||
wl_display_run(dpy);
|
||||
}
|
||||
|
||||
@ -596,7 +616,7 @@ index ec4ca86..8d1eceb 100644
|
||||
void
|
||||
setcursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2434,17 +2556,19 @@ setsel(struct wl_listener *listener, void *data)
|
||||
@@ -2437,17 +2574,19 @@ setsel(struct wl_listener *listener, void *data)
|
||||
wlr_seat_set_selection(seat, event->source, event->serial);
|
||||
}
|
||||
|
||||
@ -618,7 +638,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
/* The Wayland display is managed by libwayland. It handles accepting
|
||||
* clients from the Unix socket, manging Wayland globals, and so on. */
|
||||
@@ -2460,7 +2584,7 @@ setup(void)
|
||||
@@ -2463,7 +2602,7 @@ setup(void)
|
||||
|
||||
/* Initialize the scene graph used to lay out windows */
|
||||
scene = wlr_scene_create();
|
||||
@ -627,7 +647,7 @@ index ec4ca86..8d1eceb 100644
|
||||
for (i = 0; i < NUM_LAYERS; i++)
|
||||
layers[i] = wlr_scene_tree_create(&scene->tree);
|
||||
drag_icon = wlr_scene_tree_create(&scene->tree);
|
||||
@@ -2472,7 +2596,7 @@ setup(void)
|
||||
@@ -2475,7 +2614,7 @@ setup(void)
|
||||
* supports for shared memory, this configures that for clients. */
|
||||
if (!(drw = wlr_renderer_autocreate(backend)))
|
||||
die("couldn't create renderer");
|
||||
@ -636,7 +656,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
/* Create shm, drm and linux_dmabuf interfaces by ourselves.
|
||||
* The simplest way is call:
|
||||
@@ -2519,24 +2643,24 @@ setup(void)
|
||||
@@ -2522,24 +2661,24 @@ setup(void)
|
||||
|
||||
/* Initializes the interface used to implement urgency hints */
|
||||
activation = wlr_xdg_activation_v1_create(dpy);
|
||||
@ -665,7 +685,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
/* Set up our client lists, the xdg-shell and the layer-shell. The xdg-shell is a
|
||||
* Wayland protocol which is used for application windows. For more
|
||||
@@ -2548,19 +2672,19 @@ setup(void)
|
||||
@@ -2551,19 +2690,19 @@ setup(void)
|
||||
wl_list_init(&fstack);
|
||||
|
||||
xdg_shell = wlr_xdg_shell_create(dpy, 6);
|
||||
@ -690,7 +710,7 @@ index ec4ca86..8d1eceb 100644
|
||||
locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height,
|
||||
(float [4]){0.1f, 0.1f, 0.1f, 1.0f});
|
||||
wlr_scene_node_set_enabled(&locked_bg->node, 0);
|
||||
@@ -2570,10 +2694,10 @@ setup(void)
|
||||
@@ -2573,10 +2712,10 @@ setup(void)
|
||||
wlr_server_decoration_manager_create(dpy),
|
||||
WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
|
||||
xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy);
|
||||
@ -703,7 +723,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy);
|
||||
|
||||
@@ -2601,14 +2725,14 @@ setup(void)
|
||||
@@ -2604,14 +2743,14 @@ setup(void)
|
||||
*
|
||||
* And more comments are sprinkled throughout the notify functions above.
|
||||
*/
|
||||
@ -724,7 +744,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
/*
|
||||
* Configures a seat, which is a single "seat" at which a user sits and
|
||||
@@ -2616,27 +2740,27 @@ setup(void)
|
||||
@@ -2619,27 +2758,27 @@ setup(void)
|
||||
* pointer, touch, and drawing tablet device. We also rig up a listener to
|
||||
* let us know when new input devices are available on the backend.
|
||||
*/
|
||||
@ -765,7 +785,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
/* Make sure XWayland clients don't connect to the parent X server,
|
||||
* e.g when running in the x11 backend or the wayland backend and the
|
||||
@@ -2648,8 +2772,8 @@ setup(void)
|
||||
@@ -2651,8 +2790,8 @@ setup(void)
|
||||
* It will be started when the first X client is started.
|
||||
*/
|
||||
if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) {
|
||||
@ -776,7 +796,7 @@ index ec4ca86..8d1eceb 100644
|
||||
|
||||
setenv("DISPLAY", xwayland->display_name, 1);
|
||||
} else {
|
||||
@@ -2658,6 +2782,9 @@ setup(void)
|
||||
@@ -2661,6 +2800,9 @@ setup(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -786,7 +806,7 @@ index ec4ca86..8d1eceb 100644
|
||||
void
|
||||
spawn(const Arg *arg)
|
||||
{
|
||||
@@ -3139,8 +3266,8 @@ void
|
||||
@@ -3142,8 +3284,8 @@ void
|
||||
dissociatex11(struct wl_listener *listener, void *data)
|
||||
{
|
||||
Client *c = wl_container_of(listener, c, dissociate);
|
||||
@ -797,7 +817,7 @@ index ec4ca86..8d1eceb 100644
|
||||
}
|
||||
|
||||
void
|
||||
@@ -3175,17 +3302,141 @@ xwaylandready(struct wl_listener *listener, void *data)
|
||||
@@ -3178,17 +3320,141 @@ xwaylandready(struct wl_listener *listener, void *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -891,7 +911,7 @@ index ec4ca86..8d1eceb 100644
|
||||
+ wlr_log(WLR_ERROR, "couldn't load new dwl module from %s", get_module_path());
|
||||
+
|
||||
+ if (fork() == 0)
|
||||
+ execl("/bin/env", "--", "Notify-send", "-u", "low", "failed to reload dwl", NULL);
|
||||
+ execl("/bin/env", "--", "notify-send", "-u", "low", "failed to reload dwl", NULL);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
@ -940,7 +960,7 @@ index ec4ca86..8d1eceb 100644
|
||||
else if (c == 'v')
|
||||
die("dwl " VERSION);
|
||||
else
|
||||
@@ -3205,3 +3456,5 @@ main(int argc, char *argv[])
|
||||
@@ -3208,3 +3474,5 @@ main(int argc, char *argv[])
|
||||
usage:
|
||||
die("Usage: %s [-v] [-d] [-s startup command]", argv[0]);
|
||||
}
|
||||
@ -1005,5 +1025,5 @@ index 226980d..11aab34 100644
|
||||
+struct listens* append_listener(struct wl_listener* l, struct listens* ls);
|
||||
+struct listens* remove_listener(struct wl_listener* l, struct listens* ls);
|
||||
--
|
||||
2.48.1
|
||||
2.49.0
|
||||
|
||||
|
14
patches/rotate-clients/README.md
Normal file
14
patches/rotate-clients/README.md
Normal file
@ -0,0 +1,14 @@
|
||||
### Description
|
||||
Rotate clients on current monitor.
|
||||
|
||||
Example Configuration:
|
||||
```c
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, rotate_clients, {.i = +1} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, rotate_clients, {.i = -1} },
|
||||
```
|
||||
|
||||
### Download
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/rotate-clients/rotate-clients.patch)
|
||||
|
||||
### Authors
|
||||
- [folk](https://codeberg.org/folk)
|
56
patches/rotate-clients/rotate-clients.patch
Normal file
56
patches/rotate-clients/rotate-clients.patch
Normal file
@ -0,0 +1,56 @@
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..6029666 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -129,6 +129,8 @@ static const Key keys[] = {
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
||||
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, rotate_clients, {.i = +1} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, rotate_clients, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index a2711f6..6dfd87d 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -355,6 +355,7 @@ static Monitor *xytomon(double x, double y);
|
||||
static void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||
static void zoom(const Arg *arg);
|
||||
+static void rotate_clients(const Arg *arg);
|
||||
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
@@ -3054,6 +3055,30 @@ zoom(const Arg *arg)
|
||||
arrange(selmon);
|
||||
}
|
||||
|
||||
+static void rotate_clients(const Arg *arg) {
|
||||
+ Monitor* m = selmon;
|
||||
+ Client *c;
|
||||
+ Client *first = NULL;
|
||||
+ Client *last = NULL;
|
||||
+
|
||||
+ if (arg->i == 0)
|
||||
+ return;
|
||||
+
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) {
|
||||
+ if (first == NULL) first = c;
|
||||
+ last = c;
|
||||
+ }
|
||||
+ }
|
||||
+ if (first != last) {
|
||||
+ struct wl_list *append_to = (arg->i > 0) ? &last->link : first->link.prev;
|
||||
+ struct wl_list *elem = (arg->i > 0) ? &first->link : &last->link;
|
||||
+ wl_list_remove(elem);
|
||||
+ wl_list_insert(append_to, elem);
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#ifdef XWAYLAND
|
||||
void
|
||||
activatex11(struct wl_listener *listener, void *data)
|
@ -16,7 +16,7 @@ There was discussion of this matter in [Issue #141](https://codeberg.org/dwl/dwl
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/fauxmight/dwl/src/branch/tablet-input)
|
||||
- [main 2025-01-01](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tablet-input/tablet-input.patch)
|
||||
- [main 2025-05-18](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tablet-input/tablet-input.patch)
|
||||
- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tablet-input/tablet-input-0.7.patch)
|
||||
|
||||
### Authors
|
||||
|
@ -1,16 +1,16 @@
|
||||
From e504dc0fccfc3994962f03dc824d8907c6afc64f Mon Sep 17 00:00:00 2001
|
||||
From: choc <notchoc@proton.me>
|
||||
Date: Sat, 4 May 2024 01:16:12 +0800
|
||||
Subject: [PATCH] implement wlr-tablet-v2
|
||||
From 0659663b7eb9cafbd4f86779084765aa838e29cd Mon Sep 17 00:00:00 2001
|
||||
From: A Frederick Christensen <dwl@ivories.org>
|
||||
Date: Sat, 17 May 2025 23:26:15 -0500
|
||||
Subject: [PATCH] Add tablet input
|
||||
|
||||
---
|
||||
Makefile | 6 +-
|
||||
config.def.h | 1 +
|
||||
dwl.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 230 insertions(+), 1 deletion(-)
|
||||
dwl.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 237 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index f955e7b..ce1b556 100644
|
||||
index 578194f..e0d1835 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -21,7 +21,8 @@ dwl: dwl.o util.o
|
||||
@ -46,10 +46,10 @@ index 22d2171..3ad98ef 100644
|
||||
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ac9c36b..b8d129f 100644
|
||||
index 4816159..e8d36ac 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -50,6 +50,9 @@
|
||||
@@ -51,6 +51,9 @@
|
||||
#include <wlr/types/wlr_session_lock_v1.h>
|
||||
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
@ -59,7 +59,7 @@ index ac9c36b..b8d129f 100644
|
||||
#include <wlr/types/wlr_viewporter.h>
|
||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
@@ -270,6 +273,7 @@ static void createnotify(struct wl_listener *listener, void *data);
|
||||
@@ -268,6 +271,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);
|
||||
@ -67,9 +67,9 @@ index ac9c36b..b8d129f 100644
|
||||
static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
|
||||
static void cursorframe(struct wl_listener *listener, void *data);
|
||||
static void cursorwarptohint(void);
|
||||
@@ -284,6 +288,9 @@ static void destroypointerconstraint(struct wl_listener *listener, void *data);
|
||||
@@ -281,6 +285,9 @@ static void destroynotify(struct wl_listener *listener, void *data);
|
||||
static void destroypointerconstraint(struct wl_listener *listener, void *data);
|
||||
static void destroysessionlock(struct wl_listener *listener, void *data);
|
||||
static void destroysessionmgr(struct wl_listener *listener, void *data);
|
||||
static void destroykeyboardgroup(struct wl_listener *listener, void *data);
|
||||
+static void destroytablet(struct wl_listener *listener, void *data);
|
||||
+static void destroytabletsurfacenotify(struct wl_listener *listener, void *data);
|
||||
@ -77,7 +77,7 @@ index ac9c36b..b8d129f 100644
|
||||
static Monitor *dirtomon(enum wlr_direction dir);
|
||||
static void focusclient(Client *c, int lift);
|
||||
static void focusmon(const Arg *arg);
|
||||
@@ -337,6 +344,11 @@ static void spawn(const Arg *arg);
|
||||
@@ -333,6 +340,11 @@ 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);
|
||||
@ -89,7 +89,7 @@ index ac9c36b..b8d129f 100644
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
@@ -396,6 +408,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint;
|
||||
@@ -390,6 +402,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint;
|
||||
static struct wlr_cursor *cursor;
|
||||
static struct wlr_xcursor_manager *cursor_mgr;
|
||||
|
||||
@ -103,7 +103,20 @@ index ac9c36b..b8d129f 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;
|
||||
@@ -1133,6 +1152,28 @@ createpopup(struct wl_listener *listener, void *data)
|
||||
@@ -412,6 +431,12 @@ static struct wl_listener cursor_button = {.notify = buttonpress};
|
||||
static struct wl_listener cursor_frame = {.notify = cursorframe};
|
||||
static struct wl_listener cursor_motion = {.notify = motionrelative};
|
||||
static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute};
|
||||
+static struct wl_listener tablet_device_destroy = {.notify = destroytablet};
|
||||
+static struct wl_listener tablet_tool_axis = {.notify = tablettoolaxis};
|
||||
+static struct wl_listener tablet_tool_button = {.notify = tablettoolbutton};
|
||||
+static struct wl_listener tablet_tool_destroy = {.notify = destroytablettool};
|
||||
+static struct wl_listener tablet_tool_proximity = {.notify = tablettoolproximity};
|
||||
+static struct wl_listener tablet_tool_tip = {.notify = tablettooltip};
|
||||
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};
|
||||
@@ -1196,6 +1221,28 @@ createpopup(struct wl_listener *listener, void *data)
|
||||
LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup);
|
||||
}
|
||||
|
||||
@ -117,7 +130,7 @@ index ac9c36b..b8d129f 100644
|
||||
+ return;
|
||||
+
|
||||
+ tablet = wlr_tablet_create(tablet_mgr, seat, device);
|
||||
+ LISTEN_STATIC(&tablet->wlr_device->events.destroy, destroytablet);
|
||||
+ wl_signal_add(&tablet->wlr_device->events.destroy, &tablet_device_destroy);
|
||||
+ if (libinput_device_config_send_events_get_modes(device_handle)) {
|
||||
+ libinput_device_config_send_events_set_mode(device_handle, send_events_mode);
|
||||
+ wlr_cursor_attach_input_device(cursor, device);
|
||||
@ -132,7 +145,7 @@ index ac9c36b..b8d129f 100644
|
||||
void
|
||||
cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)
|
||||
{
|
||||
@@ -1321,6 +1362,27 @@ destroykeyboardgroup(struct wl_listener *listener, void *data)
|
||||
@@ -1380,6 +1427,27 @@ destroykeyboardgroup(struct wl_listener *listener, void *data)
|
||||
free(group);
|
||||
}
|
||||
|
||||
@ -160,7 +173,7 @@ index ac9c36b..b8d129f 100644
|
||||
Monitor *
|
||||
dirtomon(enum wlr_direction dir)
|
||||
{
|
||||
@@ -1540,6 +1602,12 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
@@ -1587,6 +1655,12 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
case WLR_INPUT_DEVICE_POINTER:
|
||||
createpointer(wlr_pointer_from_input_device(device));
|
||||
break;
|
||||
@ -173,7 +186,7 @@ index ac9c36b..b8d129f 100644
|
||||
default:
|
||||
/* TODO handle other input device types */
|
||||
break;
|
||||
@@ -2567,6 +2635,8 @@ setup(void)
|
||||
@@ -2580,6 +2654,8 @@ setup(void)
|
||||
|
||||
relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy);
|
||||
|
||||
@ -182,18 +195,19 @@ index ac9c36b..b8d129f 100644
|
||||
/*
|
||||
* Creates a cursor, which is a wlroots utility for tracking the cursor
|
||||
* image shown on screen.
|
||||
@@ -2596,6 +2666,10 @@ setup(void)
|
||||
LISTEN_STATIC(&cursor->events.button, buttonpress);
|
||||
LISTEN_STATIC(&cursor->events.axis, axisnotify);
|
||||
LISTEN_STATIC(&cursor->events.frame, cursorframe);
|
||||
+ LISTEN_STATIC(&cursor->events.tablet_tool_proximity, tablettoolproximity);
|
||||
+ LISTEN_STATIC(&cursor->events.tablet_tool_axis, tablettoolaxis);
|
||||
+ LISTEN_STATIC(&cursor->events.tablet_tool_button, tablettoolbutton);
|
||||
+ LISTEN_STATIC(&cursor->events.tablet_tool_tip, tablettooltip);
|
||||
@@ -2609,6 +2685,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);
|
||||
+ wl_signal_add(&cursor->events.tablet_tool_proximity, &tablet_tool_proximity);
|
||||
+ wl_signal_add(&cursor->events.tablet_tool_axis, &tablet_tool_axis);
|
||||
+ wl_signal_add(&cursor->events.tablet_tool_button, &tablet_tool_button);
|
||||
+ wl_signal_add(&cursor->events.tablet_tool_tip, &tablet_tool_tip);
|
||||
+
|
||||
|
||||
cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
|
||||
LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape);
|
||||
@@ -2689,6 +2763,156 @@ tagmon(const Arg *arg)
|
||||
wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape);
|
||||
@@ -2704,6 +2785,159 @@ tagmon(const Arg *arg)
|
||||
setmon(sel, dirtomon(arg->i), 0);
|
||||
}
|
||||
|
||||
@ -276,8 +290,8 @@ index ac9c36b..b8d129f 100644
|
||||
+
|
||||
+ if (!tablet_tool) {
|
||||
+ tablet_tool = wlr_tablet_tool_create(tablet_mgr, seat, tool);
|
||||
+ LISTEN_STATIC(&tablet_tool->wlr_tool->events.destroy, destroytablettool);
|
||||
+ LISTEN_STATIC(&tablet_tool->events.set_cursor, setcursor);
|
||||
+ wl_signal_add(&tablet_tool->wlr_tool->events.destroy, &tablet_tool_destroy);
|
||||
+ wl_signal_add(&tablet_tool->events.set_cursor, &request_cursor);
|
||||
+ }
|
||||
+
|
||||
+ switch (event->state) {
|
||||
@ -306,7 +320,10 @@ index ac9c36b..b8d129f 100644
|
||||
+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE)
|
||||
+ wlr_tablet_v2_tablet_tool_notify_distance(tablet_tool, event->distance);
|
||||
+ if (event->updated_axes & (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y))
|
||||
+ {
|
||||
+ printf("DEBUGGING: In axis event handling\n");
|
||||
+ wlr_tablet_v2_tablet_tool_notify_tilt(tablet_tool, event->tilt_x, event->tilt_y);
|
||||
+ }
|
||||
+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_ROTATION)
|
||||
+ wlr_tablet_v2_tablet_tool_notify_rotation(tablet_tool, event->rotation);
|
||||
+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_SLIDER)
|
||||
@ -351,5 +368,5 @@ index ac9c36b..b8d129f 100644
|
||||
tile(Monitor *m)
|
||||
{
|
||||
--
|
||||
2.43.0
|
||||
2.49.0
|
||||
|
||||
|
15
patches/tmux-borders/README.md
Normal file
15
patches/tmux-borders/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
### Description
|
||||
This patch replaces the window borders of tiled windows with borders that are similar to those found in tmux. The result is that there are no more unnecessary borders along the monitor edges in tiled mode. Borders of floating windows are not affected.
|
||||
|
||||
### Preview
|
||||

|
||||
|
||||

|
||||
|
||||
### Download
|
||||
- [git branch](/kerberoge/dwl/src/branch/tmux-borders)
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/tmux-borders/tmux-borders-0.7.patch)
|
||||
|
||||
### Authors
|
||||
- [kerberoge](https://codeberg.org/kerberoge)\
|
||||
kerberoge at [dwl Discord](https://discord.gg/jJxZnrGPWN)
|
BIN
patches/tmux-borders/screenshot1.png
Normal file
BIN
patches/tmux-borders/screenshot1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 472 KiB |
BIN
patches/tmux-borders/screenshot2.png
Normal file
BIN
patches/tmux-borders/screenshot2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 481 KiB |
489
patches/tmux-borders/tmux-borders-0.7.patch
Normal file
489
patches/tmux-borders/tmux-borders-0.7.patch
Normal file
@ -0,0 +1,489 @@
|
||||
From 464259603cb3b7346670cc33fd9afa0f8fe0cd49 Mon Sep 17 00:00:00 2001
|
||||
From: kerberoge <sjoerdenjh@gmail.com>
|
||||
Date: Sun, 1 Jun 2025 17:03:09 +0200
|
||||
Subject: [PATCH 1/1] Created tmux-borders patch for stock dwl
|
||||
|
||||
---
|
||||
client.h | 6 ++
|
||||
dwl.c | 298 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
2 files changed, 280 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/client.h b/client.h
|
||||
index 42f225f..007ab7d 100644
|
||||
--- a/client.h
|
||||
+++ b/client.h
|
||||
@@ -291,6 +291,12 @@ client_is_unmanaged(Client *c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static inline int
|
||||
+client_needs_borders(Client *c)
|
||||
+{
|
||||
+ return c->isfloating || !c->mon->lt[c->mon->sellt]->arrange;
|
||||
+}
|
||||
+
|
||||
static inline void
|
||||
client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb)
|
||||
{
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index a2711f6..c092c0e 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -191,6 +191,7 @@ struct Monitor {
|
||||
struct wlr_output *wlr_output;
|
||||
struct wlr_scene_output *scene_output;
|
||||
struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */
|
||||
+ struct wlr_scene_tree *borders, *fborders, *uborders;
|
||||
struct wl_listener frame;
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener request_state;
|
||||
@@ -255,10 +256,12 @@ static void chvt(const Arg *arg);
|
||||
static void checkidleinhibitor(struct wlr_surface *exclude);
|
||||
static void cleanup(void);
|
||||
static void cleanupmon(struct wl_listener *listener, void *data);
|
||||
+static int clientindex(Monitor *m, Client *c);
|
||||
static void closemon(Monitor *m);
|
||||
static void commitlayersurfacenotify(struct wl_listener *listener, void *data);
|
||||
static void commitnotify(struct wl_listener *listener, void *data);
|
||||
static void commitpopup(struct wl_listener *listener, void *data);
|
||||
+static int countclients(Monitor *m);
|
||||
static void createdecoration(struct wl_listener *listener, void *data);
|
||||
static void createidleinhibitor(struct wl_listener *listener, void *data);
|
||||
static void createkeyboard(struct wlr_keyboard *keyboard);
|
||||
@@ -273,6 +276,7 @@ static void createpopup(struct wl_listener *listener, void *data);
|
||||
static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
|
||||
static void cursorframe(struct wl_listener *listener, void *data);
|
||||
static void cursorwarptohint(void);
|
||||
+static void destroyborders(struct wlr_scene_tree *t);
|
||||
static void destroydecoration(struct wl_listener *listener, void *data);
|
||||
static void destroydragicon(struct wl_listener *listener, void *data);
|
||||
static void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
||||
@@ -285,6 +289,13 @@ static void destroysessionlock(struct wl_listener *listener, void *data);
|
||||
static void destroysessionmgr(struct wl_listener *listener, void *data);
|
||||
static void destroykeyboardgroup(struct wl_listener *listener, void *data);
|
||||
static Monitor *dirtomon(enum wlr_direction dir);
|
||||
+static void drawclientborders(struct wlr_scene_tree *t, Client *c,
|
||||
+ int cidx, int n, const float color[static 4]);
|
||||
+static void drawrect(struct wlr_scene_tree *t,
|
||||
+ int x, int y, int w, int h, const float color[static 4]);
|
||||
+static void drawborders(Monitor *m);
|
||||
+static void drawfborders(Monitor *m);
|
||||
+static void drawuborders(Monitor *m);
|
||||
static void focusclient(Client *c, int lift);
|
||||
static void focusmon(const Arg *arg);
|
||||
static void focusstack(const Arg *arg);
|
||||
@@ -517,6 +528,11 @@ arrange(Monitor *m)
|
||||
|
||||
if (m->lt[m->sellt]->arrange)
|
||||
m->lt[m->sellt]->arrange(m);
|
||||
+
|
||||
+ drawborders(m);
|
||||
+ drawuborders(m);
|
||||
+ drawfborders(m);
|
||||
+
|
||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
checkidleinhibitor(NULL);
|
||||
}
|
||||
@@ -721,10 +737,34 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
wlr_scene_output_destroy(m->scene_output);
|
||||
|
||||
closemon(m);
|
||||
+ wlr_scene_node_destroy(&m->borders->node);
|
||||
+ wlr_scene_node_destroy(&m->fborders->node);
|
||||
+ wlr_scene_node_destroy(&m->uborders->node);
|
||||
wlr_scene_node_destroy(&m->fullscreen_bg->node);
|
||||
free(m);
|
||||
}
|
||||
|
||||
+int
|
||||
+clientindex(Monitor *m, Client *c)
|
||||
+{
|
||||
+ unsigned int i = 0;
|
||||
+ Client *ci;
|
||||
+
|
||||
+ if (!c || m->lt[m->sellt]->arrange != tile)
|
||||
+ return -1;
|
||||
+
|
||||
+ wl_list_for_each(ci, &clients, link) {
|
||||
+ if (VISIBLEON(ci, m) && !ci->isfloating && !ci->isfullscreen) {
|
||||
+ if (ci == c)
|
||||
+ return i;
|
||||
+ else
|
||||
+ i++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
void
|
||||
closemon(Monitor *m)
|
||||
{
|
||||
@@ -743,6 +783,10 @@ closemon(Monitor *m)
|
||||
selmon = NULL;
|
||||
}
|
||||
|
||||
+ destroyborders(m->borders);
|
||||
+ destroyborders(m->fborders);
|
||||
+ destroyborders(m->uborders);
|
||||
+
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
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,
|
||||
@@ -849,6 +893,19 @@ commitpopup(struct wl_listener *listener, void *data)
|
||||
wl_list_remove(&listener->link);
|
||||
}
|
||||
|
||||
+int
|
||||
+countclients(Monitor *m)
|
||||
+{
|
||||
+ unsigned int n = 0;
|
||||
+ Client *c;
|
||||
+
|
||||
+ wl_list_for_each(c, &clients, link)
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
|
||||
+ n++;
|
||||
+
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
void
|
||||
createdecoration(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -985,6 +1042,9 @@ createmon(struct wl_listener *listener, void *data)
|
||||
|
||||
m = wlr_output->data = ecalloc(1, sizeof(*m));
|
||||
m->wlr_output = wlr_output;
|
||||
+ m->borders = wlr_scene_tree_create(layers[LyrTile]);
|
||||
+ m->fborders = wlr_scene_tree_create(layers[LyrTile]);
|
||||
+ m->uborders = wlr_scene_tree_create(layers[LyrTile]);
|
||||
|
||||
for (i = 0; i < LENGTH(m->layers); i++)
|
||||
wl_list_init(&m->layers[i]);
|
||||
@@ -1171,6 +1231,15 @@ cursorwarptohint(void)
|
||||
}
|
||||
}
|
||||
|
||||
+void
|
||||
+destroyborders(struct wlr_scene_tree *t)
|
||||
+{
|
||||
+ struct wlr_scene_node *node, *tmp;
|
||||
+
|
||||
+ wl_list_for_each_safe(node, tmp, &t->children, link)
|
||||
+ wlr_scene_node_destroy(node);
|
||||
+}
|
||||
+
|
||||
void
|
||||
destroydecoration(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -1336,6 +1405,154 @@ dirtomon(enum wlr_direction dir)
|
||||
return selmon;
|
||||
}
|
||||
|
||||
+void
|
||||
+drawclientborders(struct wlr_scene_tree *t, Client *c, int cidx, int n, const float color[static 4])
|
||||
+{
|
||||
+ Monitor *m;
|
||||
+ int mw, x, y, w, h;
|
||||
+
|
||||
+ m = c->mon;
|
||||
+ mw = (int)round(m->w.width * m->mfact - 0.5 * borderpx);
|
||||
+
|
||||
+ if (m->nmaster == 1 && n == 2) {
|
||||
+ /* Half vertical center line */
|
||||
+ y = m->w.y + (cidx == 1 ? m->w.height / 2 : 0);
|
||||
+ h = (int)round(0.5 * m->w.height);
|
||||
+ drawrect(t, m->w.x + mw, y, borderpx, h, color);
|
||||
+ } else if (m->nmaster != 1 && n == 2) {
|
||||
+ /* Half horizontal center line */
|
||||
+ x = m->w.x + (cidx == 1 ? m->w.width / 2 : 0);
|
||||
+ y = m->w.y + (int)round(0.5 * m->w.height - 0.5 * borderpx);
|
||||
+ w = (int)round(0.5 * m->w.width);
|
||||
+ drawrect(t, x, y, w, borderpx, color);
|
||||
+ } else {
|
||||
+ if (m->nmaster && n > m->nmaster)
|
||||
+ /* Vertical line next to client */
|
||||
+ drawrect(t, m->w.x + mw, c->geom.y, borderpx, c->geom.height, color);
|
||||
+
|
||||
+ if (n > m->nmaster && cidx < m->nmaster) {
|
||||
+ /* Left half */
|
||||
+ x = m->w.x;
|
||||
+ w = mw + borderpx;
|
||||
+ } else if (m->nmaster && cidx >= m->nmaster) {
|
||||
+ /* Right half */
|
||||
+ x = m->w.x + mw;
|
||||
+ w = m->w.width - mw;
|
||||
+ } else {
|
||||
+ /* Full width */
|
||||
+ x = m->w.x;
|
||||
+ w = m->w.width;
|
||||
+ }
|
||||
+
|
||||
+ if ((cidx > 0 && cidx < m->nmaster) || (cidx > m->nmaster))
|
||||
+ /* Line above client */
|
||||
+ drawrect(t, x, c->geom.y - borderpx, w, borderpx, color);
|
||||
+
|
||||
+ if ((cidx < m->nmaster - 1) || (cidx >= m->nmaster && cidx < n - 1))
|
||||
+ /* Line below client */
|
||||
+ drawrect(t, x, c->geom.y + c->geom.height, w, borderpx, color);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+drawrect(struct wlr_scene_tree *t, int x, int y, int w, int h, const float color[static 4])
|
||||
+{
|
||||
+ struct wlr_scene_rect *r;
|
||||
+
|
||||
+ r = wlr_scene_rect_create(t, w, h, color);
|
||||
+ wlr_scene_node_set_position(&r->node, x, y);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+drawborders(Monitor *m)
|
||||
+{
|
||||
+ int n, i;
|
||||
+ int mw, tw, my = 0, ty = 0;
|
||||
+
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ destroyborders(m->borders);
|
||||
+ n = countclients(m);
|
||||
+
|
||||
+ if (n <= 1 || m->lt[m->sellt]->arrange != tile)
|
||||
+ return;
|
||||
+
|
||||
+ if (m->nmaster > 0 && n > m->nmaster)
|
||||
+ mw = (int)round(m->w.width * m->mfact - 0.5 * borderpx);
|
||||
+ else if (n <= m->nmaster)
|
||||
+ mw = m->w.width;
|
||||
+ else
|
||||
+ mw = 0;
|
||||
+
|
||||
+ if (mw > 0)
|
||||
+ tw = m->w.width - mw - borderpx;
|
||||
+ else
|
||||
+ tw = m->w.width;
|
||||
+
|
||||
+ /* Vertical center line */
|
||||
+ if (mw > 0 && mw < m->w.width)
|
||||
+ drawrect(m->borders, m->w.x + mw, m->w.y, borderpx, m->w.height, bordercolor);
|
||||
+
|
||||
+ /* Lines between master clients */
|
||||
+ for (i = 0; i < MIN(n, m->nmaster) - 1; i++) {
|
||||
+ my += (m->w.height - my - borderpx * (MIN(n, m->nmaster) - i - 1))
|
||||
+ / (MIN(n, m->nmaster) - i);
|
||||
+ drawrect(m->borders, m->w.x, m->w.y + my, mw, borderpx, bordercolor);
|
||||
+ my += borderpx;
|
||||
+ }
|
||||
+
|
||||
+ /* Lines between clients on the stack */
|
||||
+ for (i = m->nmaster; i < n - 1; i++) {
|
||||
+ ty += (m->w.height - ty - borderpx * (n - i - 1)) / (n - i);
|
||||
+ drawrect(m->borders, m->m.x + (mw ? mw + borderpx : 0), m->w.y + ty,
|
||||
+ tw, borderpx, bordercolor);
|
||||
+ ty += borderpx;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+drawfborders(Monitor *m)
|
||||
+{
|
||||
+ Client *fc;
|
||||
+ int n, cidx;
|
||||
+
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ destroyborders(m->fborders);
|
||||
+ n = countclients(m);
|
||||
+ fc = focustop(m);
|
||||
+ cidx = clientindex(m, fc);
|
||||
+
|
||||
+ if (n <= 1 || cidx == -1)
|
||||
+ return;
|
||||
+
|
||||
+ drawclientborders(m->fborders, fc, cidx, n, focuscolor);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+drawuborders(Monitor *m)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ int n, cidx;
|
||||
+
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ destroyborders(m->uborders);
|
||||
+ n = countclients(m);
|
||||
+
|
||||
+ if (n <= 1)
|
||||
+ return;
|
||||
+
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ cidx = clientindex(m, c);
|
||||
+ if (cidx != -1 && c->isurgent)
|
||||
+ drawclientborders(m->uborders, c, cidx, n, urgentcolor);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void
|
||||
focusclient(Client *c, int lift)
|
||||
{
|
||||
@@ -1366,12 +1583,15 @@ focusclient(Client *c, int lift)
|
||||
wl_list_insert(&fstack, &c->flink);
|
||||
selmon = c->mon;
|
||||
c->isurgent = 0;
|
||||
+ drawuborders(c->mon);
|
||||
client_restack_surface(c);
|
||||
|
||||
/* Don't change border color if there is an exclusive focus or we are
|
||||
* handling a drag operation */
|
||||
- if (!exclusive_focus && !seat->drag)
|
||||
+ if (!exclusive_focus && !seat->drag) {
|
||||
client_set_border_color(c, focuscolor);
|
||||
+ drawfborders(c->mon);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Deactivate old client if focus is changing */
|
||||
@@ -1389,7 +1609,8 @@ focusclient(Client *c, int lift)
|
||||
* and probably other clients */
|
||||
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
|
||||
client_set_border_color(old_c, bordercolor);
|
||||
-
|
||||
+ if (old_c->mon && (!c || c->mon != old_c->mon))
|
||||
+ destroyborders(old_c->mon->fborders);
|
||||
client_activate_surface(old, 0);
|
||||
}
|
||||
}
|
||||
@@ -2193,15 +2414,20 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
applybounds(c, bbox);
|
||||
|
||||
/* Update scene-graph, including borders */
|
||||
+ c->bw = client_needs_borders(c) ? borderpx : 0;
|
||||
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
||||
- wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw);
|
||||
- wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw);
|
||||
- wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw);
|
||||
- wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw);
|
||||
- wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
|
||||
- wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
||||
- wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
||||
+ for (int i = 0; i < 4; i++)
|
||||
+ wlr_scene_node_set_enabled(&c->border[i]->node, c->bw);
|
||||
+ if (c->bw) {
|
||||
+ wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw);
|
||||
+ wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw);
|
||||
+ wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw);
|
||||
+ wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw);
|
||||
+ wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
|
||||
+ wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
||||
+ wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
||||
+ }
|
||||
|
||||
/* this is a no-op if size hasn't changed */
|
||||
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
|
||||
@@ -2359,8 +2585,13 @@ setlayout(const Arg *arg)
|
||||
return;
|
||||
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
|
||||
selmon->sellt ^= 1;
|
||||
+ else
|
||||
+ return;
|
||||
if (arg && arg->v)
|
||||
selmon->lt[selmon->sellt] = (Layout *)arg->v;
|
||||
+ if (selmon->lt[selmon->sellt ^ 1]->arrange == tile && !selmon->lt[selmon->sellt]->arrange)
|
||||
+ /* Tiled -> floating, remove monitor borders and enable client borders */
|
||||
+ tile(selmon);
|
||||
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol));
|
||||
arrange(selmon);
|
||||
printstatus();
|
||||
@@ -2692,31 +2923,46 @@ void
|
||||
tile(Monitor *m)
|
||||
{
|
||||
unsigned int mw, my, ty;
|
||||
- int i, n = 0;
|
||||
+ int i, n;
|
||||
Client *c;
|
||||
+ struct wlr_box wb;
|
||||
+ int borders = m->lt[m->sellt]->arrange == tile ? 1 : 0;
|
||||
|
||||
- wl_list_for_each(c, &clients, link)
|
||||
- if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
|
||||
- n++;
|
||||
+ n = countclients(m);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
- if (n > m->nmaster)
|
||||
- mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0;
|
||||
- else
|
||||
+ if (n > m->nmaster && m->nmaster) {
|
||||
+ mw = (int)round(m->w.width * m->mfact - (borders ? 0.5 * borderpx : 0));
|
||||
+ } else if (m->nmaster)
|
||||
mw = m->w.width;
|
||||
+ else
|
||||
+ mw = 0;
|
||||
i = my = ty = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
continue;
|
||||
if (i < m->nmaster) {
|
||||
- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
|
||||
- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0);
|
||||
- my += c->geom.height;
|
||||
+ wb.x = m->w.x;
|
||||
+ wb.y = m->w.y + my;
|
||||
+ wb.width = mw;
|
||||
+ if (borders)
|
||||
+ wb.height = (m->w.height - my - borderpx * (MIN(n, m->nmaster) - i - 1))
|
||||
+ / (MIN(n, m->nmaster) - i);
|
||||
+ else
|
||||
+ wb.height = (m->w.height - my) / (MIN(n, m->nmaster) - i);
|
||||
+ resize(c, wb, 0);
|
||||
+ my += wb.height + (borders ? borderpx : 0);
|
||||
} else {
|
||||
- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty,
|
||||
- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0);
|
||||
- ty += c->geom.height;
|
||||
+ wb.x = m->w.x + mw + (mw && borders ? borderpx : 0);
|
||||
+ wb.y = m->w.y + ty;
|
||||
+ wb.width = m->w.width - mw - (mw && borders ? borderpx : 0);
|
||||
+ if (borders)
|
||||
+ wb.height = (m->w.height - ty - borderpx * (n - i - 1)) / (n - i);
|
||||
+ else
|
||||
+ wb.height = (m->w.height - ty) / (n - i);
|
||||
+ resize(c, wb, 0);
|
||||
+ ty += wb.height + (borders ? borderpx : 0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -2941,8 +3187,10 @@ urgent(struct wl_listener *listener, void *data)
|
||||
c->isurgent = 1;
|
||||
printstatus();
|
||||
|
||||
- if (client_surface(c)->mapped)
|
||||
+ if (client_surface(c)->mapped) {
|
||||
client_set_border_color(c, urgentcolor);
|
||||
+ drawuborders(c->mon);
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
@@ -3147,8 +3395,10 @@ sethints(struct wl_listener *listener, void *data)
|
||||
c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints);
|
||||
printstatus();
|
||||
|
||||
- if (c->isurgent && surface && surface->mapped)
|
||||
+ if (c->isurgent && surface && surface->mapped) {
|
||||
client_set_border_color(c, urgentcolor);
|
||||
+ drawuborders(c->mon);
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
--
|
||||
2.49.0
|
||||
|
@ -6,7 +6,7 @@ KNOWN BUGS:
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/fauxmight/dwl/src/branch/touch-input)
|
||||
- [2025-01-01](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/touch-input/touch-input.patch)
|
||||
- [2025-05-17](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/touch-input/touch-input.patch)
|
||||
|
||||
### Authors
|
||||
- [fauxmight](https://codeberg.org/fauxmight)
|
||||
|
@ -1,260 +0,0 @@
|
||||
From 49503be07eea1b4422288323aa87a9ba7ebdefc3 Mon Sep 17 00:00:00 2001
|
||||
From: Micah N Gorrell <m@minego.net>
|
||||
Date: Fri, 9 Feb 2024 17:08:20 -0700
|
||||
Subject: [PATCH] Add support for touch screen input devices, and send the
|
||||
appropriate events to clients
|
||||
|
||||
---
|
||||
dwl.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 158 insertions(+)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ad21e1b..73fbd0d 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -51,6 +51,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 +162,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 */
|
||||
@@ -268,7 +275,9 @@ 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);
|
||||
+static void createtouch(struct wlr_touch *touch);
|
||||
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
|
||||
@@ -775,6 +793,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);
|
||||
@@ -1192,6 +1214,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)
|
||||
{
|
||||
@@ -1581,6 +1613,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;
|
||||
@@ -1593,6 +1628,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);
|
||||
}
|
||||
|
||||
@@ -2604,6 +2641,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);
|
||||
|
||||
@@ -2776,6 +2820,120 @@ 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;
|
||||
+ uint32_t serial = 0;
|
||||
+ Monitor *m;
|
||||
+
|
||||
+ wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
+
|
||||
+ // Map the input to the appropriate output, to ensure that rotation is
|
||||
+ // handled.
|
||||
+ 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 pointer and send the event along. */
|
||||
+ xytonode(lx, ly, &surface, &c, NULL, &sx, &sy);
|
||||
+ if (sloppyfocus)
|
||||
+ focusclient(c, 0);
|
||||
+
|
||||
+ if (surface != NULL) {
|
||||
+ serial = wlr_seat_touch_notify_down(seat, surface, event->time_msec, event->touch_id, sx, sy);
|
||||
+ }
|
||||
+
|
||||
+ if (serial && wlr_seat_touch_num_points(seat) == 1) {
|
||||
+ /* Emulate a mouse click if the touch event wasn't handled */
|
||||
+ struct wlr_pointer_button_event *button_event = data;
|
||||
+ struct wlr_pointer_motion_absolute_event *motion_event = data;
|
||||
+ double dx, dy;
|
||||
+
|
||||
+ wlr_cursor_absolute_to_layout_coords(cursor, &motion_event->pointer->base, motion_event->x, motion_event->y, &lx, &ly);
|
||||
+ wlr_cursor_warp_closest(cursor, &motion_event->pointer->base, lx, ly);
|
||||
+ dx = lx - cursor->x;
|
||||
+ dy = ly - cursor->y;
|
||||
+ motionnotify(motion_event->time_msec, &motion_event->pointer->base, dx, dy, dx, dy);
|
||||
+
|
||||
+ button_event->button = BTN_LEFT;
|
||||
+ button_event->state = WL_POINTER_BUTTON_STATE_PRESSED;
|
||||
+ buttonpress(listener, button_event);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+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;
|
||||
+ }
|
||||
+
|
||||
+ if (wlr_seat_touch_num_points(seat) == 1) {
|
||||
+ struct wlr_pointer_button_event *button_event = data;
|
||||
+
|
||||
+ button_event->button = BTN_LEFT;
|
||||
+ button_event->state = WL_POINTER_BUTTON_STATE_RELEASED;
|
||||
+ buttonpress(listener, button_event);
|
||||
+ }
|
||||
+
|
||||
+ wlr_seat_touch_notify_up(seat, event->time_msec, event->touch_id);
|
||||
+ 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);
|
||||
+ 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)
|
||||
{
|
||||
--
|
||||
2.47.0
|
||||
|
@ -1,15 +1,15 @@
|
||||
From 0eda173488e6ef3b0c7744e8cef0b3e0dfc81605 Mon Sep 17 00:00:00 2001
|
||||
From: Micah N Gorrell <m@minego.net>
|
||||
Date: Fri, 9 Feb 2024 17:08:20 -0700
|
||||
Subject: [PATCH] Add support for touch screen input devices, and send the
|
||||
appropriate events to clients
|
||||
From f133af7120e28f3d8bda4d4e14b3bfd477b46426 Mon Sep 17 00:00:00 2001
|
||||
From: A Frederick Christensen <dwl@ivories.org>
|
||||
Date: Sat, 17 May 2025 21:59:37 -0500
|
||||
Subject: [PATCH] Add support for touchscreen input devices
|
||||
|
||||
and send the appropriate events to clients
|
||||
---
|
||||
dwl.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 150 insertions(+)
|
||||
dwl.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 158 insertions(+)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 0eba3e9..c9eb7fb 100644
|
||||
index 4816159..3a378f9 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -51,6 +51,7 @@
|
||||
@ -20,7 +20,7 @@ index 0eba3e9..c9eb7fb 100644
|
||||
#include <wlr/types/wlr_viewporter.h>
|
||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
@@ -165,6 +166,12 @@ typedef struct {
|
||||
@@ -161,6 +162,12 @@ typedef struct {
|
||||
struct wl_listener destroy;
|
||||
} KeyboardGroup;
|
||||
|
||||
@ -33,7 +33,7 @@ index 0eba3e9..c9eb7fb 100644
|
||||
typedef struct {
|
||||
/* Must keep this field first */
|
||||
unsigned int type; /* LayerShell */
|
||||
@@ -271,7 +278,9 @@ static void createnotify(struct wl_listener *listener, void *data);
|
||||
@@ -268,7 +275,9 @@ 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);
|
||||
@ -43,7 +43,7 @@ index 0eba3e9..c9eb7fb 100644
|
||||
static void cursorframe(struct wl_listener *listener, void *data);
|
||||
static void cursorwarptohint(void);
|
||||
static void destroydecoration(struct wl_listener *listener, void *data);
|
||||
@@ -342,6 +351,10 @@ static void togglefloating(const Arg *arg);
|
||||
@@ -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);
|
||||
@ -54,15 +54,37 @@ index 0eba3e9..c9eb7fb 100644
|
||||
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);
|
||||
@@ -410,6 +423,7 @@ static struct wlr_output_layout *output_layout;
|
||||
@@ -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
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
@@ -1129,6 +1143,16 @@ createpopup(struct wl_listener *listener, void *data)
|
||||
@@ -778,6 +796,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);
|
||||
@@ -1196,6 +1218,16 @@ createpopup(struct wl_listener *listener, void *data)
|
||||
LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup);
|
||||
}
|
||||
|
||||
@ -79,7 +101,7 @@ index 0eba3e9..c9eb7fb 100644
|
||||
void
|
||||
cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)
|
||||
{
|
||||
@@ -1534,6 +1558,9 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
@@ -1587,6 +1619,9 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
case WLR_INPUT_DEVICE_POINTER:
|
||||
createpointer(wlr_pointer_from_input_device(device));
|
||||
break;
|
||||
@ -89,7 +111,7 @@ index 0eba3e9..c9eb7fb 100644
|
||||
default:
|
||||
/* TODO handle other input device types */
|
||||
break;
|
||||
@@ -1546,6 +1573,8 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||
@@ -1599,6 +1634,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;
|
||||
@ -98,21 +120,21 @@ index 0eba3e9..c9eb7fb 100644
|
||||
wlr_seat_set_capabilities(seat, caps);
|
||||
}
|
||||
|
||||
@@ -2557,6 +2586,13 @@ setup(void)
|
||||
LISTEN_STATIC(&cursor->events.axis, axisnotify);
|
||||
LISTEN_STATIC(&cursor->events.frame, cursorframe);
|
||||
@@ -2610,6 +2647,13 @@ setup(void)
|
||||
wl_signal_add(&cursor->events.axis, &cursor_axis);
|
||||
wl_signal_add(&cursor->events.frame, &cursor_frame);
|
||||
|
||||
+ wl_list_init(&touches);
|
||||
+
|
||||
+ LISTEN_STATIC(&cursor->events.touch_down, touchdown);
|
||||
+ LISTEN_STATIC(&cursor->events.touch_frame, touchframe);
|
||||
+ LISTEN_STATIC(&cursor->events.touch_motion, touchmotion);
|
||||
+ LISTEN_STATIC(&cursor->events.touch_up, touchup);
|
||||
+ 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);
|
||||
LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape);
|
||||
wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape);
|
||||
|
||||
@@ -2727,6 +2763,120 @@ toggleview(const Arg *arg)
|
||||
@@ -2782,6 +2826,120 @@ toggleview(const Arg *arg)
|
||||
printstatus();
|
||||
}
|
||||
|
||||
@ -234,5 +256,5 @@ index 0eba3e9..c9eb7fb 100644
|
||||
unlocksession(struct wl_listener *listener, void *data)
|
||||
{
|
||||
--
|
||||
2.47.0
|
||||
2.49.0
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user