less-simple-touch-input: rename to touch-input

Former maintainer @fauxmight taking over patch maintenance. @minego notes
a lack of available time: https://codeberg.org/dwl/dwl-patches/pulls/102#issuecomment-2557944
Thank you for all your work, @minego!
This commit is contained in:
A Frederick Christensen 2025-01-01 16:36:24 -06:00
parent 3c43c107ca
commit af2391cb80
No known key found for this signature in database
GPG Key ID: 6183FA655784FC36
2 changed files with 324 additions and 0 deletions

View File

@ -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)
- [2024-03-26](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/less-simple-touch-input/less-simple-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

View File

@ -0,0 +1,304 @@
From adc8734017644f44443db30e976cf03147c7c3c4 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 1/3] Add support for touch screen input devices, and send the
appropriate events to clients
Send notification of touch motition events even if there is no client to focus. This is important for swiping on an OSK.
Add support for touch screen input devices, and send the appropriate events to clients
Removed #ifdef around code that needs pointer constraints now that that is merged to upstream
---
dwl.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 145 insertions(+)
diff --git a/dwl.c b/dwl.c
index 5867b0c..fe447fb 100644
--- a/dwl.c
+++ b/dwl.c
@@ -47,6 +47,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 key;
} KeyboardGroup;
+typedef struct TouchGroup {
+ struct wl_list link;
+ struct wlr_touch *touch;
+ Monitor *m;
+} TouchGroup;
+
typedef struct {
/* Must keep these three elements in this order */
unsigned int type; /* LayerShell */
@@ -264,7 +271,9 @@ static void createmon(struct wl_listener *listener, void *data);
static void createnotify(struct wl_listener *listener, void *data);
static void createpointer(struct wlr_pointer *pointer);
static void createpointerconstraint(struct wl_listener *listener, void *data);
+static void 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);
@@ -334,6 +343,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);
@@ -404,6 +417,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;
#ifdef XWAYLAND
static void activatex11(struct wl_listener *listener, void *data);
@@ -1041,6 +1055,16 @@ createpointerconstraint(struct wl_listener *listener, void *data)
&pointer_constraint->destroy, destroypointerconstraint);
}
+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)
{
@@ -1412,6 +1436,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;
@@ -1424,6 +1451,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);
}
@@ -2431,6 +2460,13 @@ setup(void)
LISTEN_STATIC(&cursor->events.axis, axisnotify);
LISTEN_STATIC(&cursor->events.frame, cursorframe);
+ 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);
+
cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape);
@@ -2647,6 +2683,115 @@ 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);
+ // fprintf(stderr, "touch_down at %lf, %lf\n", lx, ly);
+
+ 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 = WLR_BUTTON_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 = WLR_BUTTON_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) {
+ wlr_seat_touch_point_focus(seat, surface, event->time_msec, event->touch_id, sx, sy);
+ } else {
+ 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.44.0
From c2e4ff7253f33c80552abe9126e3c57d0aa23560 Mon Sep 17 00:00:00 2001
From: Micah N Gorrell <m@minego.net>
Date: Thu, 28 Mar 2024 11:25:59 -0600
Subject: [PATCH 2/3] Removed debug
---
dwl.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/dwl.c b/dwl.c
index fe447fb..c26c581 100644
--- a/dwl.c
+++ b/dwl.c
@@ -2713,7 +2713,6 @@ touchdown(struct wl_listener *listener, void *data)
/* Find the client under the pointer and send the event along. */
xytonode(lx, ly, &surface, &c, NULL, &sx, &sy);
- // fprintf(stderr, "touch_down at %lf, %lf\n", lx, ly);
if (surface != NULL) {
serial = wlr_seat_touch_notify_down(seat, surface, event->time_msec, event->touch_id, sx, sy);
--
2.44.0
From ae64e0c3b51c8600de7c081034ea267c08134635 Mon Sep 17 00:00:00 2001
From: anabasis <anabasis@noreply.codeberg.org>
Date: Sat, 11 May 2024 20:19:18 -0400
Subject: [PATCH 3/3] fix bug and focus client according to sloppyfocus
---
dwl.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/dwl.c b/dwl.c
index c26c581..75b44d7 100644
--- a/dwl.c
+++ b/dwl.c
@@ -2713,6 +2713,8 @@ touchdown(struct wl_listener *listener, void *data)
/* 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);
@@ -2780,9 +2782,13 @@ touchmotion(struct wl_listener *listener, void *data)
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) {
+ 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);
--
2.44.0