feat: add pad/tool bindings and pen region

This commit is contained in:
pi66 2026-04-04 02:00:47 +01:00
parent 2d4463dd83
commit c59295865b
3 changed files with 282 additions and 65 deletions

View File

@ -1,14 +1,19 @@
### Description
implements wlr-tablet-v2 for drawing tablets and supports cursor emulation
Implements wlr-tablet-v2 for drawing tablets with cursor emulation.
Inspired by @guyuming76's [branch](https://codeberg.org/guyuming76/dwl/commits/branch/graphic_tablet), with coding help from @Palanix and testing by @Thanatos.
inspired by @guyuming76's [branch](https://codeberg.org/guyuming76/dwl/commits/branch/graphic_tablet), with coding help from @Palanix and testing by @Thanatos
- **Tablet area**: define the active drawing zone using the `tablet_pad` array
`{x, y, width, height}`, values range from 0.0 to 1.0 (as a fraction of the
tablet's full surface). Only input within this area is mapped to the screen.
- **Button bindings**: bind tablet pad and stylus buttons to compositor actions.
### Download
- [git branch](https://codeberg.org/fauxmight/dwl/src/branch/tablet-input)
- [tablet-input-wlroots-next-f4249db.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tablet-input/tablet-input-wlroots-next-f4249db.patch)
- [git branch](https://codeberg.org/pi66/dwl/src/branch/tablet-input)
- [tablet-input-main-a2d03cf.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tablet-input/tablet-input-main-a2d03cf.patch)
- [tablet-input-0.8.patch](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tablet-input/tablet-input-0.8.patch)
### Authors
- [fauxmight](https://codeberg.org/fauxmight)
- [notchoc](https://codeberg.org/notchoc)
- [Palanix](https://codeberg.org/Palanix)
- [pi66](https://codeberg.org/pi66)

View File

@ -1,13 +1,13 @@
From 1069919d0252e554faddccc1f9da154e171ccdda Mon Sep 17 00:00:00 2001
From: A Frederick Christensen <dwl@ivories.org>
Date: Thu, 26 Feb 2026 21:56:13 -0600
Subject: [PATCH] Apply tablet-input patch
From a14dff19f38fffa498f3de4679952b39b4323502 Mon Sep 17 00:00:00 2001
From: pi66 <pixel2176@proton.me>
Date: Wed, 8 Apr 2026 21:47:41 +0100
Subject: [PATCH] feat: add pad/tool bindings and pen region
---
Makefile | 6 +-
config.def.h | 1 +
dwl.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 246 insertions(+), 1 deletion(-)
config.def.h | 19 ++++
dwl.c | 303 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 327 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 578194f..e0d1835 100644
@ -34,19 +34,48 @@ index 578194f..e0d1835 100644
config.h:
cp config.def.h $@
diff --git a/config.def.h b/config.def.h
index 8a6eda0..1f20dfd 100644
index 8a6eda0..288494e 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 tabletmaptosurface = 1; /* 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 */
@@ -13,6 +14,8 @@ static const float focuscolor[] = COLOR(0x005577ff);
static const float urgentcolor[] = COLOR(0xff0000ff);
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */
+/* Pen active area: value 0.0 => 1.0 { x, y, width, height } */
+static const double tablet_area[4] = { 0.4, 0.4, 0.4, 0.4 };
/* tagging - TAGCOUNT must be no greater than 31 */
#define TAGCOUNT (9)
@@ -170,3 +173,19 @@ static const Button buttons[] = {
{ MODKEY, BTN_MIDDLE, togglefloating, {0} },
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
};
+
+static const TabletButton tabletbuttons[] = {
+ /* button state function argument */
+/* { BTN_STYLUS, WLR_BUTTON_PRESSED, spawn, {.v = termcmd} }, */
+/* { BTN_STYLUS2, WLR_BUTTON_PRESSED, killclient, {0} }, */
+ { 0, 0, NULL, {0} }
+};
+
+static const TabletPadButton tabletpadbuttons[] = {
+ /* button state function argument */
+/* { 0, WLR_BUTTON_PRESSED, spawn, {.v = termcmd} }, */
+/* { 1, WLR_BUTTON_PRESSED, killclient, {0} },*/
+/* { 2, WLR_BUTTON_PRESSED, togglefloating, {0} },*/
+/* { 3, WLR_BUTTON_PRESSED, zoom, {0} },*/
+ { 0, 0, NULL, {0} }
+};
diff --git a/dwl.c b/dwl.c
index 44f3ad9..4ef2cc8 100644
index 44f3ad9..7572756 100644
--- a/dwl.c
+++ b/dwl.c
@@ -51,6 +51,9 @@
@ -59,7 +88,28 @@ index 44f3ad9..4ef2cc8 100644
#include <wlr/types/wlr_viewporter.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h>
@@ -268,6 +271,7 @@ static void createnotify(struct wl_listener *listener, void *data);
@@ -239,6 +242,20 @@ typedef struct {
struct wl_listener destroy;
} SessionLock;
+typedef struct {
+ uint32_t button;
+ uint32_t state;
+ void (*func)(const Arg *);
+ const Arg arg;
+} TabletPadButton;
+
+typedef struct {
+ uint32_t button;
+ uint32_t state;
+ void (*func)(const Arg *);
+ const Arg arg;
+} TabletButton;
+
/* function declarations */
static void applybounds(Client *c, struct wlr_box *bbox);
static void applyrules(Client *c);
@@ -268,6 +285,7 @@ static void createnotify(struct wl_listener *listener, void *data);
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,29 +117,31 @@ index 44f3ad9..4ef2cc8 100644
static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
static void cursorframe(struct wl_listener *listener, void *data);
static void cursorwarptohint(void);
@@ -281,6 +285,9 @@ static void destroynotify(struct wl_listener *listener, void *data);
@@ -281,6 +299,10 @@ static void destroynotify(struct wl_listener *listener, void *data);
static void destroypointerconstraint(struct wl_listener *listener, void *data);
static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroykeyboardgroup(struct wl_listener *listener, void *data);
+static void destroytablet(struct wl_listener *listener, void *data);
+static void destroytabletpad(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,6 +340,11 @@ static void spawn(const Arg *arg);
@@ -333,6 +355,12 @@ static void spawn(const Arg *arg);
static void startdrag(struct wl_listener *listener, void *data);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
+static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, double x, double y, double dx, double dy);
+static void tablettoolproximity(struct wl_listener *listener, void *data);
+static void tabletpadbutton(struct wl_listener *listener, void *data);
+static void tablettoolaxis(struct wl_listener *listener, void *data);
+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);
@@ -390,6 +402,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint;
@@ -390,6 +418,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint;
static struct wlr_cursor *cursor;
static struct wlr_xcursor_manager *cursor_mgr;
@ -103,11 +155,13 @@ index 44f3ad9..4ef2cc8 100644
static struct wlr_scene_rect *root_bg;
static struct wlr_session_lock_manager_v1 *session_lock_mgr;
static struct wlr_scene_rect *locked_bg;
@@ -412,6 +431,12 @@ static struct wl_listener cursor_button = {.notify = buttonpress};
@@ -412,6 +447,14 @@ static struct wl_listener cursor_button = {.notify = buttonpress};
static struct wl_listener cursor_frame = {.notify = cursorframe};
static struct wl_listener cursor_motion = {.notify = motionrelative};
static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute};
+static struct wl_listener tablet_device_destroy = {.notify = destroytablet};
+static struct wl_listener tablet_pad_destroy = {.notify = destroytabletpad};
+static struct wl_listener tablet_pad_button = {.notify = tabletpadbutton};
+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};
@ -116,7 +170,7 @@ index 44f3ad9..4ef2cc8 100644
static struct wl_listener gpu_reset = {.notify = gpureset};
static struct wl_listener layout_change = {.notify = updatemons};
static struct wl_listener new_idle_inhibitor = {.notify = createidleinhibitor};
@@ -1199,6 +1224,28 @@ createpopup(struct wl_listener *listener, void *data)
@@ -1199,6 +1242,27 @@ createpopup(struct wl_listener *listener, void *data)
LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup);
}
@ -128,7 +182,6 @@ index 44f3ad9..4ef2cc8 100644
+ 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)) {
@ -145,19 +198,27 @@ index 44f3ad9..4ef2cc8 100644
void
cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)
{
@@ -1383,6 +1430,29 @@ destroykeyboardgroup(struct wl_listener *listener, void *data)
@@ -1383,6 +1447,37 @@ 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);
+ wl_list_remove(&tablet_device_destroy.link);
+ wlr_cursor_detach_input_device(cursor, tablet->wlr_device);
+ tablet = NULL;
+}
+
+void
+destroytabletpad(struct wl_listener *listener, void *data)
+{
+ wl_list_remove(&tablet_pad_button.link);
+ wl_list_remove(&tablet_pad_destroy.link);
+ tablet_pad = NULL;
+}
+
+void
+destroytabletsurfacenotify(struct wl_listener *listener, void *data)
+{
+ if (tablet_curr_surface)
@ -175,7 +236,15 @@ index 44f3ad9..4ef2cc8 100644
Monitor *
dirtomon(enum wlr_direction dir)
{
@@ -1590,6 +1660,12 @@ inputdevice(struct wl_listener *listener, void *data)
@@ -1581,6 +1676,7 @@ inputdevice(struct wl_listener *listener, void *data)
/* This event is raised by the backend when a new input device becomes
* available. */
struct wlr_input_device *device = data;
+ struct wlr_tablet_pad *pad = NULL;
uint32_t caps;
switch (device->type) {
@@ -1590,6 +1686,15 @@ inputdevice(struct wl_listener *listener, void *data)
case WLR_INPUT_DEVICE_POINTER:
createpointer(wlr_pointer_from_input_device(device));
break;
@ -183,12 +252,15 @@ index 44f3ad9..4ef2cc8 100644
+ createtablet(device);
+ break;
+ case WLR_INPUT_DEVICE_TABLET_PAD:
+ tablet_pad = wlr_tablet_pad_create(tablet_mgr, seat, device);
+ pad = wlr_tablet_pad_from_input_device(device);
+ tablet_pad = wlr_tablet_pad_create(tablet_mgr, seat, device);
+ wl_signal_add(&pad->events.button, &tablet_pad_button);
+ wl_signal_add(&device->events.destroy, &tablet_pad_destroy);
+ break;
default:
/* TODO handle other input device types */
break;
@@ -2585,6 +2661,8 @@ setup(void)
@@ -2585,6 +2690,8 @@ setup(void)
relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy);
@ -197,7 +269,7 @@ index 44f3ad9..4ef2cc8 100644
/*
* Creates a cursor, which is a wlroots utility for tracking the cursor
* image shown on screen.
@@ -2614,6 +2692,11 @@ setup(void)
@@ -2614,6 +2721,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);
@ -209,7 +281,7 @@ index 44f3ad9..4ef2cc8 100644
cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape);
@@ -2709,6 +2792,163 @@ tagmon(const Arg *arg)
@@ -2709,6 +2821,197 @@ tagmon(const Arg *arg)
setmon(sel, dirtomon(arg->i), 0);
}
@ -226,13 +298,33 @@ index 44f3ad9..4ef2cc8 100644
+ 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_region(cursor, dev, &geom);
+ wlr_cursor_map_input_to_output(cursor, dev, selmon->wlr_output);
+}
+
+void
+tabletpadbutton(struct wl_listener *listener, void *data)
+{
+ struct wlr_tablet_pad_button_event *event = data;
+ const TabletPadButton *pb;
+
+ for (pb = tabletpadbuttons; pb < END(tabletpadbuttons); pb++) {
+ if (event->button == pb->button
+ && event->state == pb->state
+ && pb->func) {
+ pb->func(&pb->arg);
+ }
+ }
+
+ if (tablet_pad)
+ wlr_tablet_v2_tablet_pad_notify_button(tablet_pad,
+ event->button, event->time_msec,
+ (enum zwp_tablet_pad_v2_button_state)event->state);
+}
+
+void
+tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y,
+ double x, double y, double dx, double dy)
+{
@ -244,6 +336,10 @@ index 44f3ad9..4ef2cc8 100644
+
+ tabletapplymap(x, y, tablet->wlr_device);
+
+ x = (MAX(tablet_area[0], MIN(tablet_area[0] + tablet_area[2], x)) - tablet_area[0]) / tablet_area[2];
+ y = (MAX(tablet_area[1], MIN(tablet_area[1] + tablet_area[3], y)) - tablet_area[1]) / tablet_area[3];
+
+
+ // TODO: apply constraints
+ switch (tablet_tool->wlr_tool->type) {
+ case WLR_TABLET_TOOL_TYPE_LENS:
@ -341,9 +437,19 @@ index 44f3ad9..4ef2cc8 100644
+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);
+ struct wlr_tablet_tool_button_event *event = data;
+ const TabletButton *tb;
+
+ for (tb = tabletbuttons; tb < END(tabletbuttons); tb++) {
+ if (event->button == tb->button
+ && event->state == tb->state
+ && tb->func) {
+ tb->func(&tb->arg);
+ }
+ }
+
+ wlr_tablet_v2_tablet_tool_notify_button(tablet_tool, event->button,
+ (enum zwp_tablet_pad_v2_button_state)event->state);
+}
+
+void
@ -374,5 +480,5 @@ index 44f3ad9..4ef2cc8 100644
tile(Monitor *m)
{
--
2.52.0
2.53.0

View File

@ -1,13 +1,13 @@
From 55f35863fa9c5a379c9315192c6bc072c3b2ebb6 Mon Sep 17 00:00:00 2001
From: A Frederick Christensen <dwl@ivories.org>
Date: Thu, 26 Feb 2026 21:58:37 -0600
Subject: [PATCH] Apply tablet-input patch
From a14dff19f38fffa498f3de4679952b39b4323502 Mon Sep 17 00:00:00 2001
From: pi66 <pixel2176@proton.me>
Date: Wed, 8 Apr 2026 21:47:41 +0100
Subject: [PATCH] feat: add pad/tool bindings and pen region
---
Makefile | 6 +-
config.def.h | 1 +
dwl.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 246 insertions(+), 1 deletion(-)
config.def.h | 19 ++++
dwl.c | 303 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 327 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 578194f..e0d1835 100644
@ -34,22 +34,51 @@ index 578194f..e0d1835 100644
config.h:
cp config.def.h $@
diff --git a/config.def.h b/config.def.h
index 8a6eda0..1f20dfd 100644
index 8a6eda0..288494e 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 tabletmaptosurface = 1; /* 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 */
@@ -13,6 +14,8 @@ static const float focuscolor[] = COLOR(0x005577ff);
static const float urgentcolor[] = COLOR(0xff0000ff);
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */
+/* Pen active area: value 0.0 => 1.0 { x, y, width, height } */
+static const double tablet_area[4] = { 0.4, 0.4, 0.4, 0.4 };
/* tagging - TAGCOUNT must be no greater than 31 */
#define TAGCOUNT (9)
@@ -170,3 +173,19 @@ static const Button buttons[] = {
{ MODKEY, BTN_MIDDLE, togglefloating, {0} },
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
};
+
+static const TabletButton tabletbuttons[] = {
+ /* button state function argument */
+/* { BTN_STYLUS, WLR_BUTTON_PRESSED, spawn, {.v = termcmd} }, */
+/* { BTN_STYLUS2, WLR_BUTTON_PRESSED, killclient, {0} }, */
+ { 0, 0, NULL, {0} }
+};
+
+static const TabletPadButton tabletpadbuttons[] = {
+ /* button state function argument */
+/* { 0, WLR_BUTTON_PRESSED, spawn, {.v = termcmd} }, */
+/* { 1, WLR_BUTTON_PRESSED, killclient, {0} },*/
+/* { 2, WLR_BUTTON_PRESSED, togglefloating, {0} },*/
+/* { 3, WLR_BUTTON_PRESSED, zoom, {0} },*/
+ { 0, 0, NULL, {0} }
+};
diff --git a/dwl.c b/dwl.c
index 8a9715d..e7d796b 100644
index 44f3ad9..7572756 100644
--- a/dwl.c
+++ b/dwl.c
@@ -52,6 +52,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 +88,28 @@ index 8a9715d..e7d796b 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);
@@ -239,6 +242,20 @@ typedef struct {
struct wl_listener destroy;
} SessionLock;
+typedef struct {
+ uint32_t button;
+ uint32_t state;
+ void (*func)(const Arg *);
+ const Arg arg;
+} TabletPadButton;
+
+typedef struct {
+ uint32_t button;
+ uint32_t state;
+ void (*func)(const Arg *);
+ const Arg arg;
+} TabletButton;
+
/* function declarations */
static void applybounds(Client *c, struct wlr_box *bbox);
static void applyrules(Client *c);
@@ -268,6 +285,7 @@ static void createnotify(struct wl_listener *listener, void *data);
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,29 +117,31 @@ index 8a9715d..e7d796b 100644
static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
static void cursorframe(struct wl_listener *listener, void *data);
static void cursorwarptohint(void);
@@ -283,6 +287,9 @@ static void destroynotify(struct wl_listener *listener, void *data);
@@ -281,6 +299,10 @@ static void destroynotify(struct wl_listener *listener, void *data);
static void destroypointerconstraint(struct wl_listener *listener, void *data);
static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroykeyboardgroup(struct wl_listener *listener, void *data);
+static void destroytablet(struct wl_listener *listener, void *data);
+static void destroytabletpad(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,6 +342,11 @@ static void spawn(const Arg *arg);
@@ -333,6 +355,12 @@ static void spawn(const Arg *arg);
static void startdrag(struct wl_listener *listener, void *data);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
+static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, double x, double y, double dx, double dy);
+static void tablettoolproximity(struct wl_listener *listener, void *data);
+static void tabletpadbutton(struct wl_listener *listener, void *data);
+static void tablettoolaxis(struct wl_listener *listener, void *data);
+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);
@@ -392,6 +404,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint;
@@ -390,6 +418,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint;
static struct wlr_cursor *cursor;
static struct wlr_xcursor_manager *cursor_mgr;
@ -103,11 +155,13 @@ index 8a9715d..e7d796b 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;
@@ -414,6 +433,12 @@ static struct wl_listener cursor_button = {.notify = buttonpress};
@@ -412,6 +447,14 @@ static struct wl_listener cursor_button = {.notify = buttonpress};
static struct wl_listener cursor_frame = {.notify = cursorframe};
static struct wl_listener cursor_motion = {.notify = motionrelative};
static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute};
+static struct wl_listener tablet_device_destroy = {.notify = destroytablet};
+static struct wl_listener tablet_pad_destroy = {.notify = destroytabletpad};
+static struct wl_listener tablet_pad_button = {.notify = tabletpadbutton};
+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};
@ -116,7 +170,7 @@ index 8a9715d..e7d796b 100644
static struct wl_listener gpu_reset = {.notify = gpureset};
static struct wl_listener layout_change = {.notify = updatemons};
static struct wl_listener new_idle_inhibitor = {.notify = createidleinhibitor};
@@ -1201,6 +1226,28 @@ createpopup(struct wl_listener *listener, void *data)
@@ -1199,6 +1242,27 @@ createpopup(struct wl_listener *listener, void *data)
LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup);
}
@ -128,7 +182,6 @@ index 8a9715d..e7d796b 100644
+ 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)) {
@ -145,19 +198,27 @@ index 8a9715d..e7d796b 100644
void
cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)
{
@@ -1385,6 +1432,29 @@ destroykeyboardgroup(struct wl_listener *listener, void *data)
@@ -1383,6 +1447,37 @@ 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);
+ wl_list_remove(&tablet_device_destroy.link);
+ wlr_cursor_detach_input_device(cursor, tablet->wlr_device);
+ tablet = NULL;
+}
+
+void
+destroytabletpad(struct wl_listener *listener, void *data)
+{
+ wl_list_remove(&tablet_pad_button.link);
+ wl_list_remove(&tablet_pad_destroy.link);
+ tablet_pad = NULL;
+}
+
+void
+destroytabletsurfacenotify(struct wl_listener *listener, void *data)
+{
+ if (tablet_curr_surface)
@ -175,7 +236,15 @@ index 8a9715d..e7d796b 100644
Monitor *
dirtomon(enum wlr_direction dir)
{
@@ -1592,6 +1662,12 @@ inputdevice(struct wl_listener *listener, void *data)
@@ -1581,6 +1676,7 @@ inputdevice(struct wl_listener *listener, void *data)
/* This event is raised by the backend when a new input device becomes
* available. */
struct wlr_input_device *device = data;
+ struct wlr_tablet_pad *pad = NULL;
uint32_t caps;
switch (device->type) {
@@ -1590,6 +1686,15 @@ inputdevice(struct wl_listener *listener, void *data)
case WLR_INPUT_DEVICE_POINTER:
createpointer(wlr_pointer_from_input_device(device));
break;
@ -183,12 +252,15 @@ index 8a9715d..e7d796b 100644
+ createtablet(device);
+ break;
+ case WLR_INPUT_DEVICE_TABLET_PAD:
+ tablet_pad = wlr_tablet_pad_create(tablet_mgr, seat, device);
+ pad = wlr_tablet_pad_from_input_device(device);
+ tablet_pad = wlr_tablet_pad_create(tablet_mgr, seat, device);
+ wl_signal_add(&pad->events.button, &tablet_pad_button);
+ wl_signal_add(&device->events.destroy, &tablet_pad_destroy);
+ break;
default:
/* TODO handle other input device types */
break;
@@ -2588,6 +2664,8 @@ setup(void)
@@ -2585,6 +2690,8 @@ setup(void)
relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy);
@ -197,7 +269,7 @@ index 8a9715d..e7d796b 100644
/*
* Creates a cursor, which is a wlroots utility for tracking the cursor
* image shown on screen.
@@ -2617,6 +2695,11 @@ setup(void)
@@ -2614,6 +2721,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);
@ -209,7 +281,7 @@ index 8a9715d..e7d796b 100644
cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape);
@@ -2712,6 +2795,163 @@ tagmon(const Arg *arg)
@@ -2709,6 +2821,197 @@ tagmon(const Arg *arg)
setmon(sel, dirtomon(arg->i), 0);
}
@ -226,13 +298,33 @@ index 8a9715d..e7d796b 100644
+ 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_region(cursor, dev, &geom);
+ wlr_cursor_map_input_to_output(cursor, dev, selmon->wlr_output);
+}
+
+void
+tabletpadbutton(struct wl_listener *listener, void *data)
+{
+ struct wlr_tablet_pad_button_event *event = data;
+ const TabletPadButton *pb;
+
+ for (pb = tabletpadbuttons; pb < END(tabletpadbuttons); pb++) {
+ if (event->button == pb->button
+ && event->state == pb->state
+ && pb->func) {
+ pb->func(&pb->arg);
+ }
+ }
+
+ if (tablet_pad)
+ wlr_tablet_v2_tablet_pad_notify_button(tablet_pad,
+ event->button, event->time_msec,
+ (enum zwp_tablet_pad_v2_button_state)event->state);
+}
+
+void
+tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y,
+ double x, double y, double dx, double dy)
+{
@ -244,6 +336,10 @@ index 8a9715d..e7d796b 100644
+
+ tabletapplymap(x, y, tablet->wlr_device);
+
+ x = (MAX(tablet_area[0], MIN(tablet_area[0] + tablet_area[2], x)) - tablet_area[0]) / tablet_area[2];
+ y = (MAX(tablet_area[1], MIN(tablet_area[1] + tablet_area[3], y)) - tablet_area[1]) / tablet_area[3];
+
+
+ // TODO: apply constraints
+ switch (tablet_tool->wlr_tool->type) {
+ case WLR_TABLET_TOOL_TYPE_LENS:
@ -341,9 +437,19 @@ index 8a9715d..e7d796b 100644
+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);
+ struct wlr_tablet_tool_button_event *event = data;
+ const TabletButton *tb;
+
+ for (tb = tabletbuttons; tb < END(tabletbuttons); tb++) {
+ if (event->button == tb->button
+ && event->state == tb->state
+ && tb->func) {
+ tb->func(&tb->arg);
+ }
+ }
+
+ wlr_tablet_v2_tablet_tool_notify_button(tablet_tool, event->button,
+ (enum zwp_tablet_pad_v2_button_state)event->state);
+}
+
+void
@ -374,5 +480,5 @@ index 8a9715d..e7d796b 100644
tile(Monitor *m)
{
--
2.52.0
2.53.0