From 97b9dbc1e667dc5b99544fa7148c0b6e0cf21623 Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Sun, 8 Mar 2026 23:30:05 -0500 Subject: [PATCH] tablet-and-touch: removed This coupled patch was likely only of use to me (@fauxmight) At present, it does not cleanly apply with other patches I am using and is thus no longer likely of use to anyone. --- patches/tablet-and-touch/README.md | 13 - .../tablet-and-touch-0.8.patch | 584 ------------------ ...ablet-and-touch-wlroots-next-f4249db.patch | 584 ------------------ 3 files changed, 1181 deletions(-) delete mode 100644 patches/tablet-and-touch/README.md delete mode 100644 patches/tablet-and-touch/tablet-and-touch-0.8.patch delete mode 100644 patches/tablet-and-touch/tablet-and-touch-wlroots-next-f4249db.patch diff --git a/patches/tablet-and-touch/README.md b/patches/tablet-and-touch/README.md deleted file mode 100644 index 426ae81..0000000 --- a/patches/tablet-and-touch/README.md +++ /dev/null @@ -1,13 +0,0 @@ -### Description -This combines -[tablet-input](../tablet-input) and -[touch-input](../touch-input) -into a single appliable patch. -The two patches modify similar code areas in `dwl.c` and will conflict if one attempts to direcly apply both. - - -### Download -- [tablet-and-touch-wlroots-next-f4249db.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tablet-and-touch/tablet-and-touch-wlroots-next-f4249db.patch) -- [tablet-and-touch-0.8.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tablet-and-touch/tablet-and-touch-0.8.patch) -### Authors -- [fauxmight](https://codeberg.org/fauxmight) diff --git a/patches/tablet-and-touch/tablet-and-touch-0.8.patch b/patches/tablet-and-touch/tablet-and-touch-0.8.patch deleted file mode 100644 index 16ece16..0000000 --- a/patches/tablet-and-touch/tablet-and-touch-0.8.patch +++ /dev/null @@ -1,584 +0,0 @@ -From f0f797f8abebc4624c7e6bdfbb1ec2a3122f3914 Mon Sep 17 00:00:00 2001 -From: A Frederick Christensen -Date: Thu, 26 Feb 2026 23:20:03 -0600 -Subject: [PATCH] Apply tablet-and-touch patch - ---- - Makefile | 6 +- - config.def.h | 1 + - dwl.c | 398 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 404 insertions(+), 1 deletion(-) - -diff --git a/Makefile b/Makefile -index 578194f..e0d1835 100644 ---- a/Makefile -+++ b/Makefile -@@ -21,7 +21,8 @@ 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 \ - 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 -+ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h \ -+ tablet-v2-protocol.h - util.o: util.c util.h - - # wayland-scanner is a tool which generates C headers and rigging for Wayland -@@ -45,6 +46,9 @@ wlr-output-power-management-unstable-v1-protocol.h: - xdg-shell-protocol.h: - $(WAYLAND_SCANNER) server-header \ - $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ -+tablet-v2-protocol.h: -+ $(WAYLAND_SCANNER) server-header \ -+ $(WAYLAND_PROTOCOLS)/unstable/tablet/tablet-unstable-v2.xml $@ - - config.h: - cp config.def.h $@ -diff --git a/config.def.h b/config.def.h -index 8a6eda0..1f20dfd 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -4,6 +4,7 @@ - ((hex >> 8) & 0xFF) / 255.0f, \ - (hex & 0xFF) / 255.0f } - /* appearance */ -+static const int tabletmaptosurface = 0; /* map tablet input to surface(1) or monitor(0) */ - static const int sloppyfocus = 1; /* focus follows mouse */ - 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 44f3ad9..5ed467d 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -51,6 +51,10 @@ - #include - #include - #include -+#include -+#include -+#include -+#include - #include - #include - #include -@@ -161,6 +165,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 +278,10 @@ 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 createtablet(struct wlr_input_device *device); -+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); -@@ -281,6 +294,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 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); -+static void destroytablettool(struct wl_listener *listener, void *data); - static Monitor *dirtomon(enum wlr_direction dir); - static void focusclient(Client *c, int lift); - static void focusmon(const Arg *arg); -@@ -333,11 +349,20 @@ static void spawn(const Arg *arg); - static void startdrag(struct wl_listener *listener, void *data); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); -+static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, double x, double y, double dx, double dy); -+static void tablettoolproximity(struct wl_listener *listener, void *data); -+static void tablettoolaxis(struct wl_listener *listener, void *data); -+static void tablettoolbutton(struct wl_listener *listener, void *data); -+static void tablettooltip(struct wl_listener *listener, void *data); - static void tile(Monitor *m); - 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); -@@ -390,6 +415,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint; - static struct wlr_cursor *cursor; - static struct wlr_xcursor_manager *cursor_mgr; - -+static struct wlr_tablet_manager_v2 *tablet_mgr; -+static struct wlr_tablet_v2_tablet *tablet = NULL; -+static struct wlr_tablet_v2_tablet_tool *tablet_tool = NULL; -+static struct wlr_tablet_v2_tablet_pad *tablet_pad = NULL; -+static struct wlr_surface *tablet_curr_surface = NULL; -+static struct wl_listener destroy_tablet_surface_listener = {.notify = destroytabletsurfacenotify}; -+ - static struct wlr_scene_rect *root_bg; - static struct wlr_session_lock_manager_v1 *session_lock_mgr; - static struct wlr_scene_rect *locked_bg; -@@ -405,6 +437,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}; -@@ -412,6 +445,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}; -@@ -434,6 +473,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 -@@ -781,6 +824,10 @@ cleanuplisteners(void) - wl_list_remove(&request_set_cursor_shape.link); - wl_list_remove(&request_start_drag.link); - wl_list_remove(&start_drag.link); -+ wl_list_remove(&touch_down.link); -+ wl_list_remove(&touch_frame.link); -+ wl_list_remove(&touch_motion.link); -+ wl_list_remove(&touch_up.link); - wl_list_remove(&new_session_lock.link); - #ifdef XWAYLAND - wl_list_remove(&new_xwayland_surface.link); -@@ -1199,6 +1246,38 @@ createpopup(struct wl_listener *listener, void *data) - LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); - } - -+void -+createtablet(struct wlr_input_device *device) -+{ -+ if (!tablet) { -+ struct libinput_device *device_handle = NULL; -+ if (!wlr_input_device_is_libinput(device) || -+ !(device_handle = wlr_libinput_get_device_handle(device))) -+ return; -+ -+ tablet = wlr_tablet_create(tablet_mgr, seat, device); -+ 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); -+ } -+ } else if (device == tablet->wlr_device) { -+ wlr_log(WLR_ERROR, "createtablet: duplicate device"); -+ } else { -+ wlr_log(WLR_ERROR, "createtablet: already have one tablet"); -+ } -+} -+ -+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) - { -@@ -1383,6 +1462,29 @@ destroykeyboardgroup(struct wl_listener *listener, void *data) - free(group); - } - -+void -+destroytablet(struct wl_listener *listener, void *data) -+{ -+ wl_list_remove(&tablet_device_destroy.link); -+ wlr_cursor_detach_input_device(cursor, tablet->wlr_device); -+ tablet = NULL; -+} -+ -+void -+destroytabletsurfacenotify(struct wl_listener *listener, void *data) -+{ -+ if (tablet_curr_surface) -+ wl_list_remove(&destroy_tablet_surface_listener.link); -+ tablet_curr_surface = NULL; -+} -+ -+void -+destroytablettool(struct wl_listener *listener, void *data) -+{ -+ destroytabletsurfacenotify(NULL, NULL); -+ tablet_tool = NULL; -+} -+ - Monitor * - dirtomon(enum wlr_direction dir) - { -@@ -1590,6 +1692,15 @@ inputdevice(struct wl_listener *listener, void *data) - case WLR_INPUT_DEVICE_POINTER: - createpointer(wlr_pointer_from_input_device(device)); - break; -+ case WLR_INPUT_DEVICE_TABLET: -+ createtablet(device); -+ break; -+ case WLR_INPUT_DEVICE_TABLET_PAD: -+ tablet_pad = wlr_tablet_pad_create(tablet_mgr, seat, device); -+ break; -+ case WLR_INPUT_DEVICE_TOUCH: -+ createtouch(wlr_touch_from_input_device(device)); -+ break; - default: - /* TODO handle other input device types */ - break; -@@ -1602,6 +1713,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); - } - -@@ -2585,6 +2698,8 @@ setup(void) - - relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); - -+ tablet_mgr = wlr_tablet_v2_create(dpy); -+ - /* - * Creates a cursor, which is a wlroots utility for tracking the cursor - * image shown on screen. -@@ -2614,6 +2729,18 @@ 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); -+ -+ -+ 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); -@@ -2709,6 +2836,163 @@ tagmon(const Arg *arg) - setmon(sel, dirtomon(arg->i), 0); - } - -+void -+tabletapplymap(double x, double y, struct wlr_input_device *dev) -+{ -+ Client *p; -+ struct wlr_box geom = {0}; -+ if (tabletmaptosurface && tablet_curr_surface) { -+ toplevel_from_wlr_surface(tablet_curr_surface, &p, NULL); -+ if (p) { -+ for (; client_get_parent(p); p = client_get_parent(p)); -+ geom.x = p->geom.x + p->bw; -+ geom.y = p->geom.y + p->bw; -+ geom.width = p->geom.width - 2 * p->bw; -+ geom.height = p->geom.height - 2 * p->bw; -+ } -+ } -+ wlr_cursor_map_input_to_region(cursor, dev, &geom); -+ wlr_cursor_map_input_to_output(cursor, dev, selmon->wlr_output); -+} -+ -+void -+tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, -+ double x, double y, double dx, double dy) -+{ -+ struct wlr_surface *surface = NULL; -+ double sx, sy; -+ -+ if (!change_x && !change_y) -+ return; -+ -+ tabletapplymap(x, y, tablet->wlr_device); -+ -+ // TODO: apply constraints -+ switch (tablet_tool->wlr_tool->type) { -+ case WLR_TABLET_TOOL_TYPE_LENS: -+ case WLR_TABLET_TOOL_TYPE_MOUSE: -+ wlr_cursor_move(cursor, tablet->wlr_device, dx, dy); -+ break; -+ default: -+ wlr_cursor_warp_absolute(cursor, tablet->wlr_device, change_x ? x : NAN, change_y ? y : NAN); -+ break; -+ } -+ -+ motionnotify(0, NULL, 0, 0, 0, 0); -+ -+ xytonode(cursor->x, cursor->y, &surface, NULL, NULL, &sx, &sy); -+ if (surface && !wlr_surface_accepts_tablet_v2(surface, tablet)) -+ surface = NULL; -+ -+ if (surface != tablet_curr_surface) { -+ if (tablet_curr_surface) { -+ // TODO: wait until all buttons released before leaving -+ if (tablet_tool) -+ wlr_tablet_v2_tablet_tool_notify_proximity_out(tablet_tool); -+ if (tablet_pad) -+ wlr_tablet_v2_tablet_pad_notify_leave(tablet_pad, tablet_curr_surface); -+ wl_list_remove(&destroy_tablet_surface_listener.link); -+ } -+ if (surface) { -+ if (tablet_pad) -+ wlr_tablet_v2_tablet_pad_notify_enter(tablet_pad, tablet, surface); -+ if (tablet_tool) -+ wlr_tablet_v2_tablet_tool_notify_proximity_in(tablet_tool, tablet, surface); -+ wl_signal_add(&surface->events.destroy, &destroy_tablet_surface_listener); -+ } -+ tablet_curr_surface = surface; -+ } -+ -+ if (surface) -+ wlr_tablet_v2_tablet_tool_notify_motion(tablet_tool, sx, sy); -+} -+ -+void -+tablettoolproximity(struct wl_listener *listener, void *data) -+{ -+ struct wlr_tablet_tool_proximity_event *event = data; -+ struct wlr_tablet_tool *tool = event->tool; -+ -+ if (!tablet_tool) { -+ tablet_tool = wlr_tablet_tool_create(tablet_mgr, seat, tool); -+ 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) { -+ case WLR_TABLET_TOOL_PROXIMITY_OUT: -+ wlr_tablet_v2_tablet_tool_notify_proximity_out(tablet_tool); -+ destroytabletsurfacenotify(NULL, NULL); -+ break; -+ case WLR_TABLET_TOOL_PROXIMITY_IN: -+ tablettoolmotion(tablet_tool, true, true, event->x, event->y, 0, 0); -+ break; -+ } -+} -+ -+double tilt_x = 0; -+double tilt_y = 0; -+ -+void -+tablettoolaxis(struct wl_listener *listener, void *data) -+{ -+ struct wlr_tablet_tool_axis_event *event = data; -+ -+ tablettoolmotion(tablet_tool, -+ event->updated_axes & WLR_TABLET_TOOL_AXIS_X, -+ event->updated_axes & WLR_TABLET_TOOL_AXIS_Y, -+ event->x, event->y, event->dx, event->dy); -+ -+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE) -+ wlr_tablet_v2_tablet_tool_notify_pressure(tablet_tool, event->pressure); -+ 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) -+ tilt_x = event->tilt_x; -+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_TILT_Y) -+ tilt_y = event->tilt_y; -+ if (event->updated_axes & (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y)) -+ wlr_tablet_v2_tablet_tool_notify_tilt(tablet_tool, tilt_x, 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) -+ wlr_tablet_v2_tablet_tool_notify_slider(tablet_tool, event->slider); -+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_WHEEL) -+ wlr_tablet_v2_tablet_tool_notify_wheel(tablet_tool, event->wheel_delta, 0); -+} -+ -+void -+tablettoolbutton(struct wl_listener *listener, void *data) -+{ -+ struct wlr_tablet_tool_button_event *event = data; -+ wlr_tablet_v2_tablet_tool_notify_button(tablet_tool, event->button, -+ (enum zwp_tablet_pad_v2_button_state)event->state); -+} -+ -+void -+tablettooltip(struct wl_listener *listener, void *data) -+{ -+ struct wlr_tablet_tool_tip_event *event = data; -+ -+ if (!tablet_curr_surface) { -+ struct wlr_pointer_button_event fakeptrbtnevent = { -+ .button = BTN_LEFT, -+ .state = event->state == WLR_TABLET_TOOL_TIP_UP ? -+ WL_POINTER_BUTTON_STATE_RELEASED : WL_POINTER_BUTTON_STATE_PRESSED, -+ .time_msec = event->time_msec, -+ }; -+ buttonpress(NULL, (void *)&fakeptrbtnevent); -+ } -+ -+ if (event->state == WLR_TABLET_TOOL_TIP_UP) { -+ wlr_tablet_v2_tablet_tool_notify_up(tablet_tool); -+ return; -+ } -+ -+ wlr_tablet_v2_tablet_tool_notify_down(tablet_tool); -+ wlr_tablet_tool_v2_start_implicit_grab(tablet_tool); -+} -+ - void - tile(Monitor *m) - { -@@ -2787,6 +3071,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.52.0 - diff --git a/patches/tablet-and-touch/tablet-and-touch-wlroots-next-f4249db.patch b/patches/tablet-and-touch/tablet-and-touch-wlroots-next-f4249db.patch deleted file mode 100644 index bf577d4..0000000 --- a/patches/tablet-and-touch/tablet-and-touch-wlroots-next-f4249db.patch +++ /dev/null @@ -1,584 +0,0 @@ -From 78eda59b86ca01188fd645fe4062dda75d60acb1 Mon Sep 17 00:00:00 2001 -From: A Frederick Christensen -Date: Thu, 26 Feb 2026 23:23:49 -0600 -Subject: [PATCH] Apply tablet-and-touch patch - ---- - Makefile | 6 +- - config.def.h | 1 + - dwl.c | 398 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 404 insertions(+), 1 deletion(-) - -diff --git a/Makefile b/Makefile -index 578194f..e0d1835 100644 ---- a/Makefile -+++ b/Makefile -@@ -21,7 +21,8 @@ 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 \ - 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 -+ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h \ -+ tablet-v2-protocol.h - util.o: util.c util.h - - # wayland-scanner is a tool which generates C headers and rigging for Wayland -@@ -45,6 +46,9 @@ wlr-output-power-management-unstable-v1-protocol.h: - xdg-shell-protocol.h: - $(WAYLAND_SCANNER) server-header \ - $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ -+tablet-v2-protocol.h: -+ $(WAYLAND_SCANNER) server-header \ -+ $(WAYLAND_PROTOCOLS)/unstable/tablet/tablet-unstable-v2.xml $@ - - config.h: - cp config.def.h $@ -diff --git a/config.def.h b/config.def.h -index 8a6eda0..1f20dfd 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -4,6 +4,7 @@ - ((hex >> 8) & 0xFF) / 255.0f, \ - (hex & 0xFF) / 255.0f } - /* appearance */ -+static const int tabletmaptosurface = 0; /* map tablet input to surface(1) or monitor(0) */ - static const int sloppyfocus = 1; /* focus follows mouse */ - 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 8a9715d..6dc462a 100644 ---- a/dwl.c -+++ b/dwl.c -@@ -52,6 +52,10 @@ - #include - #include - #include -+#include -+#include -+#include -+#include - #include - #include - #include -@@ -163,6 +167,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 */ -@@ -270,7 +280,10 @@ 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 createtablet(struct wlr_input_device *device); -+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); -@@ -283,6 +296,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 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); -+static void destroytablettool(struct wl_listener *listener, void *data); - static Monitor *dirtomon(enum wlr_direction dir); - static void focusclient(Client *c, int lift); - static void focusmon(const Arg *arg); -@@ -335,11 +351,20 @@ static void spawn(const Arg *arg); - static void startdrag(struct wl_listener *listener, void *data); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); -+static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, double x, double y, double dx, double dy); -+static void tablettoolproximity(struct wl_listener *listener, void *data); -+static void tablettoolaxis(struct wl_listener *listener, void *data); -+static void tablettoolbutton(struct wl_listener *listener, void *data); -+static void tablettooltip(struct wl_listener *listener, void *data); - static void tile(Monitor *m); - 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); -@@ -392,6 +417,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint; - static struct wlr_cursor *cursor; - static struct wlr_xcursor_manager *cursor_mgr; - -+static struct wlr_tablet_manager_v2 *tablet_mgr; -+static struct wlr_tablet_v2_tablet *tablet = NULL; -+static struct wlr_tablet_v2_tablet_tool *tablet_tool = NULL; -+static struct wlr_tablet_v2_tablet_pad *tablet_pad = NULL; -+static struct wlr_surface *tablet_curr_surface = NULL; -+static struct wl_listener destroy_tablet_surface_listener = {.notify = destroytabletsurfacenotify}; -+ - static struct wlr_scene_rect *root_bg; - static struct wlr_session_lock_manager_v1 *session_lock_mgr; - static struct wlr_scene_rect *locked_bg; -@@ -407,6 +439,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}; -@@ -414,6 +447,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}; -@@ -436,6 +475,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 -@@ -783,6 +826,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); -@@ -1201,6 +1248,38 @@ createpopup(struct wl_listener *listener, void *data) - LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); - } - -+void -+createtablet(struct wlr_input_device *device) -+{ -+ if (!tablet) { -+ struct libinput_device *device_handle = NULL; -+ if (!wlr_input_device_is_libinput(device) || -+ !(device_handle = wlr_libinput_get_device_handle(device))) -+ return; -+ -+ tablet = wlr_tablet_create(tablet_mgr, seat, device); -+ 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); -+ } -+ } else if (device == tablet->wlr_device) { -+ wlr_log(WLR_ERROR, "createtablet: duplicate device"); -+ } else { -+ wlr_log(WLR_ERROR, "createtablet: already have one tablet"); -+ } -+} -+ -+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) - { -@@ -1385,6 +1464,29 @@ destroykeyboardgroup(struct wl_listener *listener, void *data) - free(group); - } - -+void -+destroytablet(struct wl_listener *listener, void *data) -+{ -+ wl_list_remove(&tablet_device_destroy.link); -+ wlr_cursor_detach_input_device(cursor, tablet->wlr_device); -+ tablet = NULL; -+} -+ -+void -+destroytabletsurfacenotify(struct wl_listener *listener, void *data) -+{ -+ if (tablet_curr_surface) -+ wl_list_remove(&destroy_tablet_surface_listener.link); -+ tablet_curr_surface = NULL; -+} -+ -+void -+destroytablettool(struct wl_listener *listener, void *data) -+{ -+ destroytabletsurfacenotify(NULL, NULL); -+ tablet_tool = NULL; -+} -+ - Monitor * - dirtomon(enum wlr_direction dir) - { -@@ -1592,6 +1694,15 @@ inputdevice(struct wl_listener *listener, void *data) - case WLR_INPUT_DEVICE_POINTER: - createpointer(wlr_pointer_from_input_device(device)); - break; -+ case WLR_INPUT_DEVICE_TABLET: -+ createtablet(device); -+ break; -+ case WLR_INPUT_DEVICE_TABLET_PAD: -+ tablet_pad = wlr_tablet_pad_create(tablet_mgr, seat, device); -+ break; -+ case WLR_INPUT_DEVICE_TOUCH: -+ createtouch(wlr_touch_from_input_device(device)); -+ break; - default: - /* TODO handle other input device types */ - break; -@@ -1604,6 +1715,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); - } - -@@ -2588,6 +2701,8 @@ setup(void) - - relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); - -+ tablet_mgr = wlr_tablet_v2_create(dpy); -+ - /* - * Creates a cursor, which is a wlroots utility for tracking the cursor - * image shown on screen. -@@ -2617,6 +2732,18 @@ 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); -+ -+ -+ 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); -@@ -2712,6 +2839,163 @@ tagmon(const Arg *arg) - setmon(sel, dirtomon(arg->i), 0); - } - -+void -+tabletapplymap(double x, double y, struct wlr_input_device *dev) -+{ -+ Client *p; -+ struct wlr_box geom = {0}; -+ if (tabletmaptosurface && tablet_curr_surface) { -+ toplevel_from_wlr_surface(tablet_curr_surface, &p, NULL); -+ if (p) { -+ for (; client_get_parent(p); p = client_get_parent(p)); -+ geom.x = p->geom.x + p->bw; -+ geom.y = p->geom.y + p->bw; -+ geom.width = p->geom.width - 2 * p->bw; -+ geom.height = p->geom.height - 2 * p->bw; -+ } -+ } -+ wlr_cursor_map_input_to_region(cursor, dev, &geom); -+ wlr_cursor_map_input_to_output(cursor, dev, selmon->wlr_output); -+} -+ -+void -+tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, -+ double x, double y, double dx, double dy) -+{ -+ struct wlr_surface *surface = NULL; -+ double sx, sy; -+ -+ if (!change_x && !change_y) -+ return; -+ -+ tabletapplymap(x, y, tablet->wlr_device); -+ -+ // TODO: apply constraints -+ switch (tablet_tool->wlr_tool->type) { -+ case WLR_TABLET_TOOL_TYPE_LENS: -+ case WLR_TABLET_TOOL_TYPE_MOUSE: -+ wlr_cursor_move(cursor, tablet->wlr_device, dx, dy); -+ break; -+ default: -+ wlr_cursor_warp_absolute(cursor, tablet->wlr_device, change_x ? x : NAN, change_y ? y : NAN); -+ break; -+ } -+ -+ motionnotify(0, NULL, 0, 0, 0, 0); -+ -+ xytonode(cursor->x, cursor->y, &surface, NULL, NULL, &sx, &sy); -+ if (surface && !wlr_surface_accepts_tablet_v2(surface, tablet)) -+ surface = NULL; -+ -+ if (surface != tablet_curr_surface) { -+ if (tablet_curr_surface) { -+ // TODO: wait until all buttons released before leaving -+ if (tablet_tool) -+ wlr_tablet_v2_tablet_tool_notify_proximity_out(tablet_tool); -+ if (tablet_pad) -+ wlr_tablet_v2_tablet_pad_notify_leave(tablet_pad, tablet_curr_surface); -+ wl_list_remove(&destroy_tablet_surface_listener.link); -+ } -+ if (surface) { -+ if (tablet_pad) -+ wlr_tablet_v2_tablet_pad_notify_enter(tablet_pad, tablet, surface); -+ if (tablet_tool) -+ wlr_tablet_v2_tablet_tool_notify_proximity_in(tablet_tool, tablet, surface); -+ wl_signal_add(&surface->events.destroy, &destroy_tablet_surface_listener); -+ } -+ tablet_curr_surface = surface; -+ } -+ -+ if (surface) -+ wlr_tablet_v2_tablet_tool_notify_motion(tablet_tool, sx, sy); -+} -+ -+void -+tablettoolproximity(struct wl_listener *listener, void *data) -+{ -+ struct wlr_tablet_tool_proximity_event *event = data; -+ struct wlr_tablet_tool *tool = event->tool; -+ -+ if (!tablet_tool) { -+ tablet_tool = wlr_tablet_tool_create(tablet_mgr, seat, tool); -+ 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) { -+ case WLR_TABLET_TOOL_PROXIMITY_OUT: -+ wlr_tablet_v2_tablet_tool_notify_proximity_out(tablet_tool); -+ destroytabletsurfacenotify(NULL, NULL); -+ break; -+ case WLR_TABLET_TOOL_PROXIMITY_IN: -+ tablettoolmotion(tablet_tool, true, true, event->x, event->y, 0, 0); -+ break; -+ } -+} -+ -+double tilt_x = 0; -+double tilt_y = 0; -+ -+void -+tablettoolaxis(struct wl_listener *listener, void *data) -+{ -+ struct wlr_tablet_tool_axis_event *event = data; -+ -+ tablettoolmotion(tablet_tool, -+ event->updated_axes & WLR_TABLET_TOOL_AXIS_X, -+ event->updated_axes & WLR_TABLET_TOOL_AXIS_Y, -+ event->x, event->y, event->dx, event->dy); -+ -+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE) -+ wlr_tablet_v2_tablet_tool_notify_pressure(tablet_tool, event->pressure); -+ 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) -+ tilt_x = event->tilt_x; -+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_TILT_Y) -+ tilt_y = event->tilt_y; -+ if (event->updated_axes & (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y)) -+ wlr_tablet_v2_tablet_tool_notify_tilt(tablet_tool, tilt_x, 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) -+ wlr_tablet_v2_tablet_tool_notify_slider(tablet_tool, event->slider); -+ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_WHEEL) -+ wlr_tablet_v2_tablet_tool_notify_wheel(tablet_tool, event->wheel_delta, 0); -+} -+ -+void -+tablettoolbutton(struct wl_listener *listener, void *data) -+{ -+ struct wlr_tablet_tool_button_event *event = data; -+ wlr_tablet_v2_tablet_tool_notify_button(tablet_tool, event->button, -+ (enum zwp_tablet_pad_v2_button_state)event->state); -+} -+ -+void -+tablettooltip(struct wl_listener *listener, void *data) -+{ -+ struct wlr_tablet_tool_tip_event *event = data; -+ -+ if (!tablet_curr_surface) { -+ struct wlr_pointer_button_event fakeptrbtnevent = { -+ .button = BTN_LEFT, -+ .state = event->state == WLR_TABLET_TOOL_TIP_UP ? -+ WL_POINTER_BUTTON_STATE_RELEASED : WL_POINTER_BUTTON_STATE_PRESSED, -+ .time_msec = event->time_msec, -+ }; -+ buttonpress(NULL, (void *)&fakeptrbtnevent); -+ } -+ -+ if (event->state == WLR_TABLET_TOOL_TIP_UP) { -+ wlr_tablet_v2_tablet_tool_notify_up(tablet_tool); -+ return; -+ } -+ -+ wlr_tablet_v2_tablet_tool_notify_down(tablet_tool); -+ wlr_tablet_tool_v2_start_implicit_grab(tablet_tool); -+} -+ - void - tile(Monitor *m) - { -@@ -2790,6 +3074,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.52.0 -