summaryrefslogtreecommitdiffstats
path: root/dwl-patches/patches/touch-input
diff options
context:
space:
mode:
authorLeonard Kugis <leonard@kug.is>2025-05-23 11:41:09 +0000
committerLeonard Kugis <leonard@kug.is>2025-05-23 11:41:09 +0000
commitc70505d7c7b7b48600f273357694b56ccf5d2a15 (patch)
tree21c27ac6ffced8d6d904e35bdb39baa5d685d829 /dwl-patches/patches/touch-input
downloaddotfiles-master.tar.gz
dotfiles-master.tar.bz2
dotfiles-master.zip
Initial commitHEADmaster
Diffstat (limited to 'dwl-patches/patches/touch-input')
-rw-r--r--dwl-patches/patches/touch-input/README.md20
-rw-r--r--dwl-patches/patches/touch-input/touch-input.patch260
2 files changed, 280 insertions, 0 deletions
diff --git a/dwl-patches/patches/touch-input/README.md b/dwl-patches/patches/touch-input/README.md
new file mode 100644
index 0000000..3d37fc2
--- /dev/null
+++ b/dwl-patches/patches/touch-input/README.md
@@ -0,0 +1,20 @@
+### Description
+Adds touchscreen functionality.
+
+KNOWN BUGS:
+- Sometimes, the pointer moves to where the screen is pressed, but the button press doesn't occur until the screen is touched AGAIN. This means that if you touch to click button 'Q' on the screen (for instance), nothing happens; then you touch elsewhere on the screen and THEN button 'Q' registers a click. This is annoying, doesn't always happen, and I don't yet know how to fix it.
+
+### Download
+- [git branch](https://codeberg.org/fauxmight/dwl/src/branch/touch-input)
+- [2025-05-17](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/touch-input/touch-input.patch)
+
+### Authors
+- [fauxmight](https://codeberg.org/fauxmight)
+- [minego](https://codeberg.org/minego)
+- [Unprex](https://github.com/Unprex)
+
+### Changelog
+- 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
+- 2024-03-26 Rebased, and removed #ifdef's for the pointer constraints patch which has been merged into upstream
+- 2024-03-28 Removed debug
diff --git a/dwl-patches/patches/touch-input/touch-input.patch b/dwl-patches/patches/touch-input/touch-input.patch
new file mode 100644
index 0000000..bfd33e7
--- /dev/null
+++ b/dwl-patches/patches/touch-input/touch-input.patch
@@ -0,0 +1,260 @@
+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 | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 158 insertions(+)
+
+diff --git a/dwl.c b/dwl.c
+index 4816159..3a378f9 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
+@@ -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);
+ }
+
++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)
+ {
+@@ -1587,6 +1619,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;
+@@ -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;
++ if (!wl_list_empty(&touches))
++ caps |= WL_SEAT_CAPABILITY_TOUCH;
+ wlr_seat_set_capabilities(seat, caps);
+ }
+
+@@ -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);
++
++ 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);
+
+@@ -2782,6 +2826,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.49.0
+