From 42f97e88bd901d81b81da61c44a790b583706308 Mon Sep 17 00:00:00 2001 From: wochap Date: Fri, 5 Jul 2024 11:18:49 -0500 Subject: [PATCH] implement gestures --- config.def.h | 9 +++++++ dwl.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/config.def.h b/config.def.h index 22d2171..8b75564 100644 --- a/config.def.h +++ b/config.def.h @@ -14,6 +14,8 @@ 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.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ +static const unsigned int swipe_min_threshold = 0; + /* tagging - TAGCOUNT must be no greater than 31 */ #define TAGCOUNT (9) @@ -174,3 +176,10 @@ static const Button buttons[] = { { MODKEY, BTN_MIDDLE, togglefloating, {0} }, { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, }; + +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} }, +}; diff --git a/dwl.c b/dwl.c index ded83e2..5d861e8 100644 --- a/dwl.c +++ b/dwl.c @@ -88,6 +88,7 @@ enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ #endif +enum { SWIPE_LEFT, SWIPE_RIGHT, SWIPE_DOWN, SWIPE_UP }; typedef union { int i; @@ -103,6 +104,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 Monitor Monitor; typedef struct { /* Must keep these three elements in this order */ @@ -251,6 +260,7 @@ 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 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); @@ -416,6 +426,10 @@ static struct wlr_box sgeom; static struct wl_list mons; static Monitor *selmon; +static uint32_t swipe_fingers = 0; +static double swipe_dx = 0; +static double swipe_dy = 0; + #ifdef XWAYLAND static void activatex11(struct wl_listener *listener, void *data); static void associatex11(struct wl_listener *listener, void *data); @@ -435,6 +449,8 @@ static xcb_atom_t netatom[NetLast]; /* attempt to encapsulate suck into one file */ #include "client.h" +static const unsigned int abzsquare = swipe_min_threshold * swipe_min_threshold; + /* function implementations */ void applybounds(Client *c, struct wlr_box *bbox) @@ -657,6 +673,11 @@ 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, @@ -671,6 +692,11 @@ 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, @@ -681,11 +707,53 @@ swipe_update(struct wl_listener *listener, void *data) ); } +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, -- 2.45.1