diff --git a/config.def.h b/config.def.h index 19804ee..6120e1a 100644 --- a/config.def.h +++ b/config.def.h @@ -16,6 +16,7 @@ static const float urgentcolor[] = COLOR(0xff0000ff); static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ static int enableautoswallow = 0; /* enables autoswallowing newly spawned clients */ static float swallowborder = 1.0f; /* add this multiplied by borderpx to border when a client is swallowed */ +static const unsigned int swipe_min_threshold = 0; /* tagging - TAGCOUNT must be no greater than 31 */ #define TAGCOUNT (10) @@ -169,6 +170,13 @@ static const int cursor_timeout = 5; /* helper for spawning shell commands in the pre dwm-5.0 fashion */ #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } +static const Gesture gestures[] = { + // { MODKEY, SWIPE_LEFT, 4, shiftview, { .i = 1 } }, + // { MODKEY, SWIPE_RIGHT, 4, shiftview, { .i = -1 } }, + { MODKEY, SWIPE_UP, 3, focusstack, {.i = 1} }, + { MODKEY, SWIPE_DOWN, 3, focusstack, {.i = -1} }, +}; + /* commands */ static const char *termcmd[] = { "st", NULL }; static const char *filecmd[] = { "st", "-e", "vifmrun", NULL }; diff --git a/dwl.c b/dwl.c index 7a615d2..3918ead 100644 --- a/dwl.c +++ b/dwl.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +92,8 @@ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ enum { XDGShell, LayerShell, X11 }; /* client types */ enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ +enum { SWIPE_LEFT, SWIPE_RIGHT, SWIPE_DOWN, SWIPE_UP }; + typedef union { int i; uint32_t ui; @@ -105,6 +108,14 @@ typedef struct { const Arg arg; } Button; +typedef struct { + unsigned int mod; + unsigned int motion; + unsigned int fingers_count; + void (*func)(const Arg *); + const Arg arg; +} Gesture; + typedef struct Pertag Pertag; typedef struct Monitor Monitor; typedef struct Client Client; @@ -288,6 +299,15 @@ static void arrangelayers(Monitor *m); static void assignkeymap(struct wlr_keyboard *keyboard); static void axisnotify(struct wl_listener *listener, void *data); static void buttonpress(struct wl_listener *listener, void *data); +static int ongesture(struct wlr_pointer_swipe_end_event *event); +static void swipe_begin(struct wl_listener *listener, void *data); +static void swipe_update(struct wl_listener *listener, void *data); +static void swipe_end(struct wl_listener *listener, void *data); +static void pinch_begin(struct wl_listener *listener, void *data); +static void pinch_update(struct wl_listener *listener, void *data); +static void pinch_end(struct wl_listener *listener, void *data); +static void hold_begin(struct wl_listener *listener, void *data); +static void hold_end(struct wl_listener *listener, void *data); static void chvt(const Arg *arg); static void checkidleinhibitor(struct wlr_surface *exclude); static void cleanup(void); @@ -465,6 +485,7 @@ static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; static struct wlr_output_power_manager_v1 *power_mgr; +static struct wlr_pointer_gestures_v1 *pointer_gestures; static struct wlr_pointer_constraints_v1 *pointer_constraints; static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; @@ -501,6 +522,10 @@ static struct wl_list mons; static Monitor *selmon; static struct wl_list touches; +static uint32_t swipe_fingers = 0; +static double swipe_dx = 0; +static double swipe_dy = 0; + /* global event handlers */ static struct wl_listener cursor_axis = {.notify = axisnotify}; static struct wl_listener cursor_button = {.notify = buttonpress}; @@ -571,6 +596,8 @@ struct Pertag { const Layout *ltidxs[TAGCOUNT + 1][2]; /* matrix of tags and layouts indexes */ }; +static const unsigned int abzsquare = swipe_min_threshold * swipe_min_threshold; + /* function implementations */ void applybounds(Client *c, struct wlr_box *bbox) @@ -840,6 +867,174 @@ buttonpress(struct wl_listener *listener, void *data) event->time_msec, event->button, event->state); } +void +swipe_begin(struct wl_listener *listener, void *data) +{ + struct wlr_pointer_swipe_begin_event *event = data; + + swipe_fingers = event->fingers; + // Reset swipe distance at the beginning of a swipe + swipe_dx = 0; + swipe_dy = 0; + + // Forward swipe begin event to client + wlr_pointer_gestures_v1_send_swipe_begin( + pointer_gestures, + seat, + event->time_msec, + event->fingers + ); +} + +void +swipe_update(struct wl_listener *listener, void *data) +{ + struct wlr_pointer_swipe_update_event *event = data; + + swipe_fingers = event->fingers; + // Accumulate swipe distance + swipe_dx += event->dx; + swipe_dy += event->dy; + + // Forward swipe update event to client + wlr_pointer_gestures_v1_send_swipe_update( + pointer_gestures, + seat, + event->time_msec, + event->dx, + event->dy + ); +} + +int +ongesture(struct wlr_pointer_swipe_end_event *event) +{ + struct wlr_keyboard *keyboard; + uint32_t mods; + const Gesture *g; + unsigned int motion; + unsigned int adx = (int)round(fabs(swipe_dx)); + unsigned int ady = (int)round(fabs(swipe_dy)); + int handled = 0; + + if (event->cancelled) { + return handled; + } + + // Require absolute distance movement beyond a small thresh-hold + if (adx * adx + ady * ady < abzsquare) { + return handled; + } + + if (adx > ady) { + motion = swipe_dx < 0 ? SWIPE_LEFT : SWIPE_RIGHT; + } else { + motion = swipe_dy < 0 ? SWIPE_UP : SWIPE_DOWN; + } + + keyboard = wlr_seat_get_keyboard(seat); + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (g = gestures; g < END(gestures); g++) { + if (CLEANMASK(mods) == CLEANMASK(g->mod) && + swipe_fingers == g->fingers_count && + motion == g->motion && g->func) { + g->func(&g->arg); + handled = 1; + } + } + return handled; +} + +void +swipe_end(struct wl_listener *listener, void *data) +{ + struct wlr_pointer_swipe_end_event *event = data; + + // TODO: should we stop here if the event has been handled? + ongesture(event); + + // Forward swipe end event to client + wlr_pointer_gestures_v1_send_swipe_end( + pointer_gestures, + seat, + event->time_msec, + event->cancelled + ); +} + +void +pinch_begin(struct wl_listener *listener, void *data) +{ + struct wlr_pointer_pinch_begin_event *event = data; + + // Forward pinch begin event to client + wlr_pointer_gestures_v1_send_pinch_begin( + pointer_gestures, + seat, + event->time_msec, + event->fingers + ); +} + +void +pinch_update(struct wl_listener *listener, void *data) +{ + struct wlr_pointer_pinch_update_event *event = data; + + // Forward pinch update event to client + wlr_pointer_gestures_v1_send_pinch_update( + pointer_gestures, + seat, + event->time_msec, + event->dx, + event->dy, + event->scale, + event->rotation + ); +} + +void +pinch_end(struct wl_listener *listener, void *data) +{ + struct wlr_pointer_pinch_end_event *event = data; + + // Forward pinch end event to client + wlr_pointer_gestures_v1_send_pinch_end( + pointer_gestures, + seat, + event->time_msec, + event->cancelled + ); +} + +void +hold_begin(struct wl_listener *listener, void *data) +{ + struct wlr_pointer_hold_begin_event *event = data; + + // Forward hold begin event to client + wlr_pointer_gestures_v1_send_hold_begin( + pointer_gestures, + seat, + event->time_msec, + event->fingers + ); +} + +void +hold_end(struct wl_listener *listener, void *data) +{ + struct wlr_pointer_hold_end_event *event = data; + + // Forward hold end event to client + wlr_pointer_gestures_v1_send_hold_end( + pointer_gestures, + seat, + event->time_msec, + event->cancelled + ); +} + void chvt(const Arg *arg) { @@ -3221,6 +3416,17 @@ setup(void) wl_signal_add(&virtual_pointer_mgr->events.new_virtual_pointer, &new_virtual_pointer); + pointer_gestures = wlr_pointer_gestures_v1_create(dpy); + LISTEN_STATIC(&cursor->events.swipe_begin, swipe_begin); + LISTEN_STATIC(&cursor->events.swipe_update, swipe_update); + LISTEN_STATIC(&cursor->events.swipe_end, swipe_end); + LISTEN_STATIC(&cursor->events.pinch_begin, pinch_begin); + LISTEN_STATIC(&cursor->events.pinch_update, pinch_update); + LISTEN_STATIC(&cursor->events.pinch_end, pinch_end); + LISTEN_STATIC(&cursor->events.hold_begin, hold_begin); + LISTEN_STATIC(&cursor->events.hold_end, hold_end); + + seat = wlr_seat_create(dpy, "seat0"); wl_signal_add(&seat->events.request_set_cursor, &request_cursor); wl_signal_add(&seat->events.request_set_selection, &request_set_sel); diff --git a/pointer-gestures-unstable-v1.patch b/pointer-gestures-unstable-v1.patch new file mode 100644 index 0000000..f76648a --- /dev/null +++ b/pointer-gestures-unstable-v1.patch @@ -0,0 +1,186 @@ +From be7e98d28fc59aab67026e7d5efdcaeb26029713 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Fri, 12 Jul 2024 11:30:17 -0500 +Subject: [PATCH] implement pointer-gestures-unstable-v1 + +--- + dwl.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 136 insertions(+) + +diff --git a/dwl.c b/dwl.c +index dc0437e..e5805b1 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -250,6 +251,14 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); ++static void swipe_begin(struct wl_listener *listener, void *data); ++static void swipe_update(struct wl_listener *listener, void *data); ++static void swipe_end(struct wl_listener *listener, void *data); ++static void pinch_begin(struct wl_listener *listener, void *data); ++static void pinch_update(struct wl_listener *listener, void *data); ++static void pinch_end(struct wl_listener *listener, void *data); ++static void hold_begin(struct wl_listener *listener, void *data); ++static void hold_end(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); + static void cleanup(void); +@@ -383,6 +392,7 @@ static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; + static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; + static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; + static struct wlr_output_power_manager_v1 *power_mgr; ++static struct wlr_pointer_gestures_v1 *pointer_gestures; + + static struct wlr_pointer_constraints_v1 *pointer_constraints; + static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; +@@ -644,6 +654,122 @@ buttonpress(struct wl_listener *listener, void *data) + event->time_msec, event->button, event->state); + } + ++void ++swipe_begin(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_swipe_begin_event *event = data; ++ ++ // Forward swipe begin event to client ++ wlr_pointer_gestures_v1_send_swipe_begin( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->fingers ++ ); ++} ++ ++void ++swipe_update(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_swipe_update_event *event = data; ++ ++ // Forward swipe update event to client ++ wlr_pointer_gestures_v1_send_swipe_update( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->dx, ++ event->dy ++ ); ++} ++ ++void ++swipe_end(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_swipe_end_event *event = data; ++ ++ // Forward swipe end event to client ++ wlr_pointer_gestures_v1_send_swipe_end( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->cancelled ++ ); ++} ++ ++void ++pinch_begin(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_pinch_begin_event *event = data; ++ ++ // Forward pinch begin event to client ++ wlr_pointer_gestures_v1_send_pinch_begin( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->fingers ++ ); ++} ++ ++void ++pinch_update(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_pinch_update_event *event = data; ++ ++ // Forward pinch update event to client ++ wlr_pointer_gestures_v1_send_pinch_update( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->dx, ++ event->dy, ++ event->scale, ++ event->rotation ++ ); ++} ++ ++void ++pinch_end(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_pinch_end_event *event = data; ++ ++ // Forward pinch end event to client ++ wlr_pointer_gestures_v1_send_pinch_end( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->cancelled ++ ); ++} ++ ++void ++hold_begin(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_hold_begin_event *event = data; ++ ++ // Forward hold begin event to client ++ wlr_pointer_gestures_v1_send_hold_begin( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->fingers ++ ); ++} ++ ++void ++hold_end(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_hold_end_event *event = data; ++ ++ // Forward hold end event to client ++ wlr_pointer_gestures_v1_send_hold_end( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->cancelled ++ ); ++} ++ + void + chvt(const Arg *arg) + { +@@ -2556,6 +2682,16 @@ setup(void) + virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy); + LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer); + ++ pointer_gestures = wlr_pointer_gestures_v1_create(dpy); ++ LISTEN_STATIC(&cursor->events.swipe_begin, swipe_begin); ++ LISTEN_STATIC(&cursor->events.swipe_update, swipe_update); ++ LISTEN_STATIC(&cursor->events.swipe_end, swipe_end); ++ LISTEN_STATIC(&cursor->events.pinch_begin, pinch_begin); ++ LISTEN_STATIC(&cursor->events.pinch_update, pinch_update); ++ LISTEN_STATIC(&cursor->events.pinch_end, pinch_end); ++ LISTEN_STATIC(&cursor->events.hold_begin, hold_begin); ++ LISTEN_STATIC(&cursor->events.hold_end, hold_end); ++ + seat = wlr_seat_create(dpy, "seat0"); + LISTEN_STATIC(&seat->events.request_set_cursor, setcursor); + LISTEN_STATIC(&seat->events.request_set_selection, setsel); +-- +2.45.1