Maarten van Gompel: 1 implementing support for gestures with edge and corner detection 3 files changed, 212 insertions(+), 33 deletions(-)
Maarten, I have tried almost full set of your changes. And I have to say I like it very much!
Thanks! I'm glad you like it.
Here I want comment on UX aspect of Gesture system and Keyboard. The latter looks great and functionality has been improved considerably. I'll definitely stick with it. New Gestures are great relief as well. No more triple click! ;) And customization with hooks is much more appealing to me. I have immediately swapped 2f horizontal gesture to send a window in the direction of the gesture not into opposite one. :) In addition, I have found several moments to discuss. Upper set of gestures interferes with status bar. If I open terminal it almost 100% ends up on the first screen. Brightness is very tricky in general.
Yes, good point, I noticed that as well, the top-left hotcorner is pretty useless because of the conflict with the workspace switcher in the bar. I guess we should just not use the top-left hotcorner.
Hmm..I guess it also conflicts with the bar too often?
Kill window, Left, Right those are my favorite. On the other hand I experience some problems with left side. Probably due to protective screen is few pixels shifted to the right. For instance, mute never works for me. So, the question here is if it would be reasonable (implementation, other usage) to widen threshold of and edge? For upper zone may be under status bar?
Yes, that would be quite possible. I currently have the edge size set in config.h (and equal for all edges, 50px), but we can easily split that out to it can be defined per edge. Having the top edge bigger by default makes sense to avoid conflicts with the bar. The caveat is that we don't want to interfere too much with normal non-edge swipes of course.
For the keyboard I saw only startup configuration which variant to use. Does it accept context argument aka window type? For instance, layout with dot for terminal, Czech for navigation and messaging, etc.
You can select a starting layout, but svkbd itself doesn't test what the active window type is, I guess such functionality should best go in a wrapper script (test window type -> invoke svkbd with the proper keyboard) rather than svkbd itself. I do like the idea of context-sensitive keyboards, we should then introduce some kind of sxmo_keyboard.sh for that and call that instead of calling $KEYBOARD directly.It seems custom gesture could be just enough to envoke custom svkbd based on WMCLASS argument. I like this introduced customization more and more. :D-- Maarten van Gompel proycon@anaproy.nl https://proycon.anaproy.nl https://github.com/proycon GnuPG key: 0x39FE11201A31555C XMPP: proycon@anaproy.nl Matrix: @proycon:matrix.anaproy.nl Telegram: proycon IRC: proycon (freenode) Discord: proycon#8272 Mastodon: https://social.anaproy.nl/@proycon (@proycon@social.anaproy.nl) Twitter: https://twitter.com/proycon Bitcoin: 1BRptZsKQtqRGSZ5qKbX2azbfiygHxJPsd
I guess I have a solution to upper zone without further intervention into gestures. I returned volume to "Volume buttons", power to Power one. And I don't need conflicting gestures any more. :) BTW, unmute won't work as it is implemented now. I'll send you PR shortly. Dmytro
Hi Miles, Thanks for the review!
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~mil/sxmo-devel/patches/11923/mbox | git am -3Learn more about email & git
This is a big patch that allows for more fine-tuned gestures in lisgd. I implemented edge and distance as extra features. This patch is the required companion to a patch in sxmo-utils that reworks the entire gesture system. --- Makefile | 5 +- config.def.h | 26 ++++--- lisgd.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 212 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index b2ab358..4c86c8f 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,9 @@ SRC = lisgd.c OBJ = ${SRC:.c=.o} LDFLAGS = -linput -lm +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib
Right now lisgd has no depedency on X11 and if possible I'd like to keep it that way and just depend on libinput. I know there is another project using lisgd on Wayland too. I'm not positive how things will calibrate (mm vs px); but libinput does have a call to get the screensize (libinput_device_get_size): https://wayland.freedesktop.org/libinput/doc/latest/api/group__device.html
+ all: options lisgd options: @@ -19,7 +22,7 @@ config.h: cp config.def.h $@ lisgd: ${OBJ} - ${CC} -g -o $@ ${OBJ} ${LDFLAGS} + ${CC} -g -o $@ ${OBJ} -I${X11INC} -lX11 ${LDFLAGS} install: all mkdir -p ${DESTDIR}${PREFIX}/bin diff --git a/config.def.h b/config.def.h index 641de0d..659ad5b 100644 --- a/config.def.h +++ b/config.def.h @@ -1,5 +1,5 @@ -/* - distancethreshold: Minimum cutoff for a gestures to take effect +/* + distancethreshold: Minimum cutoff for a gestures to take effect degreesleniency: Offset degrees within which gesture is recognized (max=45) timeoutms: Maximum duration for a gesture to take place in miliseconds orientation: Number of 90 degree turns to shift gestures by @@ -15,18 +15,20 @@ unsigned int degreesleniency = 15; unsigned int timeoutms = 800; unsigned int orientation = 0; unsigned int verbose = 0; +double edgesize_x = 50.0; +double edgesize_y = 50.0;
Let's keep with the style of no underscores. So edgesize{x,y} works here.
char *device = "/dev/input/event1"; Gesture gestures[] = { /* nfingers gesturetype command */ - { 1, SwipeLR, "xdotool key --clearmodifiers Alt+Shift+e" }, - { 1, SwipeRL, "xdotool key --clearmodifiers Alt+Shift+r" }, - { 1, SwipeDLUR, "sxmo_vol.sh up" }, - { 1, SwipeURDL, "sxmo_vol.sh down" }, - { 1, SwipeDRUL, "sxmo_brightness.sh up" }, - { 1, SwipeULDR, "sxmo_brightness.sh down" }, - { 2, SwipeLR, "xdotool key --clearmodifiers Alt+e" }, - { 2, SwipeRL, "xdotool key --clearmodifiers Alt+r" }, - { 2, SwipeDU, "pidof svkbd-sxmo || svkbd-sxmo &" }, - { 2, SwipeUD, "pkill -9 svkbd-sxmo" }, + { 1, SwipeLR, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+Shift+e" }, + { 1, SwipeRL, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+Shift+r" }, + { 1, SwipeDLUR, AnyEdge, AnyDistance, "sxmo_vol.sh up" }, + { 1, SwipeURDL, AnyEdge, AnyDistance, "sxmo_vol.sh down" }, + { 1, SwipeDRUL, AnyEdge, AnyDistance, "sxmo_brightness.sh up" }, + { 1, SwipeULDR, AnyEdge, AnyDistance, "sxmo_brightness.sh down" }, + { 2, SwipeLR, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+e" }, + { 2, SwipeRL, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+r" }, + { 2, SwipeDU, AnyEdge, AnyDistance, "pidof svkbd-sxmo || svkbd-sxmo &" }, + { 2, SwipeUD, AnyEdge, AnyDistance, "pkill -9 svkbd-sxmo" }, }; diff --git a/lisgd.c b/lisgd.c index 5adfbfa..bf83143 100644 --- a/lisgd.c +++ b/lisgd.c @@ -10,6 +10,7 @@ #include <sys/select.h> #include <time.h> #include <unistd.h> +#include <X11/Xlib.h>
See note above on X11.
/* Defines */ #define MAXSLOTS 20 @@ -26,11 +27,35 @@ enum { SwipeURDL, SwipeULDR }; - typedef int Swipe; + +enum { + AnyEdge, + NoEdge, + LeftEdge, + RightEdge, + TopEdge, + BottomEdge, + TopLeftCorner, + TopRightCorner, + BottomLeftCorner, + BottomRightCorner, +}; +typedef int Edge;
Similar to Swipe<Identifier>; for consistency we should use Edge<Identifier>. So instead of TopEdge, we should use EdgeTop.
+ +enum { + AnyDistance, + ShortDistance, + MediumDistance, + LongDistance,
Same feeback here - should be DistanceShort not ShortDistance.
+}; +typedef int Distance; + typedef struct { int nfswipe; Swipe swipe; + Edge edge; + Distance distance; char *command; } Gesture; @@ -41,9 +66,14 @@ typedef struct { Gesture *gestsarr; int gestsarrlen; Swipe pendingswipe; +Edge pendingedge; +Distance pendingdistance; double xstart[MAXSLOTS], xend[MAXSLOTS], ystart[MAXSLOTS], yend[MAXSLOTS]; unsigned nfdown = 0, nfpendingswipe = 0; struct timespec timedown; +static Display *dpy; +static int screen; +static int screenwidth, screenheight; void die(char * msg) @@ -91,31 +121,119 @@ gesturecalculateswipe(double x0, double y0, double x1, double y1) { return -1; } +Distance +gesturecalculatedistance(double x0, double y0, double x1, double y1, Swipe swipe) { + double dist = sqrt(pow(x1 - x0, 2) + pow(y1 - y0, 2)); + double diag = sqrt(pow(screenwidth,2) + pow(screenheight,2)); + switch (swipe) { + case SwipeDU: + case SwipeUD: + if (dist >= screenheight * 0.66) { + return LongDistance; + } else if (dist >= screenheight * 0.33) { + return MediumDistance; + } else { + return ShortDistance; + } + break; + case SwipeLR: + case SwipeRL: + if (dist >= screenwidth * 0.66) { + return LongDistance; + } else if (dist >= screenwidth * 0.33) { + return MediumDistance; + } else { + return ShortDistance; + } + break; + case SwipeULDR: + case SwipeDRUL: + case SwipeDLUR: + case SwipeURDL: + if (dist >= diag * 0.66) { + return LongDistance; + } else if (dist >= diag * 0.33) { + return MediumDistance; + } else { + return ShortDistance; + } + break; + } + + return 0; //shouldn't happen +} + +Edge +gesturecalculateedge(double x0, double y0, double x1, double y1) { + Edge horizontal = NoEdge; + Edge vertical = NoEdge; + if (x0 <= edgesize_x) { + horizontal = LeftEdge;
Does the ordering matter here - if not it would be nice to combine theses conditions to be less verbose like: if (x0 <= edgesize_x || x1 <= edgesize_x) horizontal = LeftEdge; else if (x0 >= screenwidth - edgesize_x || x1 >= screenwidth - edgesize_x) horizontal = RightEdge;
+ } else if (x0 >= screenwidth - edgesize_x) { + horizontal = RightEdge; + } else if (x1 <= edgesize_x) { + horizontal = LeftEdge; + } else if (x1 >= screenwidth - edgesize_x) { + horizontal = RightEdge; + } + if (y0 <= edgesize_y) { + vertical = TopEdge; + } else if (y0 >= screenheight - edgesize_y) { + vertical = BottomEdge; + } else if (y1 <= edgesize_y) { + vertical = TopEdge; + } else if (y1 >= screenheight - edgesize_y) { + vertical = BottomEdge; + } + if (horizontal == LeftEdge && vertical == TopEdge) { + return TopLeftCorner; + } else if (horizontal == RightEdge && vertical == TopEdge) { + return TopRightCorner; + } else if (horizontal == LeftEdge && vertical == BottomEdge) { + return BottomLeftCorner; + } else if (horizontal == RightEdge && vertical == BottomEdge) { + return BottomRightCorner; + } else if (horizontal != NoEdge) { + return horizontal; + } else { + return vertical; + } +} + void -gestureexecute(Swipe swipe, int nfingers) { +gestureexecute(Swipe swipe, int nfingers, Edge edge, Distance distance) { int i; for (i = 0; i < gestsarrlen; i++) { if (verbose) { - fprintf(stderr, - "[Nfswipe/SwipeId]: Cfg (%d/%d) <=> Evt (%d/%d)\n", - gestsarr[i].nfswipe, gestsarr[i].swipe, nfingers, swipe + fprintf(stderr, + "[swipe]: Cfg(f=%d/s=%d/e=%d/d=%d) <=> Evt(f=%d/s=%d/e=%d/d=%d)\n", + gestsarr[i].nfswipe, gestsarr[i].swipe, gestsarr[i].edge, gestsarr[i].distance, nfingers, swipe, edge, distance ); } - if (gestsarr[i].nfswipe == nfingers && gestsarr[i].swipe == swipe) { + if (gestsarr[i].nfswipe == nfingers && gestsarr[i].swipe == swipe + && gestsarr[i].distance <= distance + && (gestsarr[i].edge == AnyEdge || gestsarr[i].edge == edge || + ((edge == TopLeftCorner || edge == TopRightCorner) && gestsarr[i].edge == TopEdge) || + ((edge == BottomLeftCorner || edge == BottomRightCorner) && gestsarr[i].edge == BottomEdge) || + ((edge == TopLeftCorner || edge == BottomLeftCorner) && gestsarr[i].edge == LeftEdge) || + ((edge == TopRightCorner || edge == BottomRightCorner) && gestsarr[i].edge == RightEdge) + ) + ) { if (verbose) fprintf(stderr, "Execute %s\n", gestsarr[i].command); execcommand(gestsarr[i].command); + break; //execute first match only } } } -static int +static int libinputopenrestricted(const char *path, int flags, void *user_data) { int fd = open(path, flags); return fd < 0 ? -errno : fd; } - + static void libinputcloserestricted(int fd, void *user_data) { @@ -141,6 +259,25 @@ swipereorient(Swipe swipe, int orientation) { return swipe; } +Edge +edgereorient(Edge edge, int orientation) { + while (orientation > 0) { + switch(edge) { + // 90deg per turn + case LeftEdge: edge = TopEdge; break; + case RightEdge: edge = BottomEdge; break; + case TopEdge: edge = RightEdge; break; + case BottomEdge: edge = LeftEdge; break; + case TopLeftCorner: edge = TopRightCorner; break; + case TopRightCorner: edge = BottomRightCorner; break; + case BottomLeftCorner: edge = TopLeftCorner; break; + case BottomRightCorner: edge = BottomLeftCorner; break; + } + orientation--; + } + return edge; +} + void touchdown(struct libinput_event *e) { @@ -197,17 +334,27 @@ touchup(struct libinput_event *e) Swipe swipe = gesturecalculateswipe( xstart[slot], ystart[slot], xend[slot], yend[slot] ); - if (nfpendingswipe == 0) pendingswipe = swipe; + Edge edge = gesturecalculateedge( + xstart[slot], ystart[slot], xend[slot], yend[slot] + ); + Distance distance = gesturecalculatedistance( + xstart[slot], ystart[slot], xend[slot], yend[slot], swipe + ); + if (nfpendingswipe == 0) { + pendingswipe = swipe; + pendingedge = edge; + pendingdistance = distance; + } if (pendingswipe == swipe) nfpendingswipe++; resetslot(slot); // All fingers up - check if within milisecond limit, exec, & reset if (nfdown == 0) { if ( - timeoutms > + timeoutms > ((now.tv_sec - timedown.tv_sec) * 1000000 + (now.tv_nsec - timedown.tv_nsec) / 1000) / 1000 - ) gestureexecute(swipe, nfpendingswipe); - + ) gestureexecute(swipe, nfpendingswipe, edge, distance); + nfpendingswipe = 0; } } @@ -238,7 +385,7 @@ run() die("Couldn't set mode to capture events"); } - // E.g. initially invalidate every slot + // E.g. initially invalidate every slot for (i = 0; i < MAXSLOTS; i++) { xend[i] = NOMOTION; yend[i] = NOMOTION; @@ -266,7 +413,7 @@ run() } libinput_unref(li); } - + int main(int argc, char *argv[]) { @@ -300,10 +447,10 @@ main(int argc, char *argv[]) exit(EXIT_FAILURE); } gestpt = strtok(argv[++i], ","); - for (j = 0; gestpt != NULL && j < 3; gestpt = strtok(NULL, ","), j++) { + for (j = 0; gestpt != NULL && j < 5; gestpt = strtok(NULL, ","), j++) { switch(j) { case 0: gestsarr[gestsarrlen - 1].nfswipe = atoi(gestpt); break; - case 1: + case 1: if (!strcmp(gestpt, "LR")) gestsarr[gestsarrlen-1].swipe = SwipeLR; if (!strcmp(gestpt, "RL")) gestsarr[gestsarrlen-1].swipe = SwipeRL; if (!strcmp(gestpt, "DU")) gestsarr[gestsarrlen-1].swipe = SwipeDU; @@ -313,15 +460,40 @@ main(int argc, char *argv[]) if (!strcmp(gestpt, "ULDR")) gestsarr[gestsarrlen-1].swipe = SwipeULDR; if (!strcmp(gestpt, "DRUL")) gestsarr[gestsarrlen-1].swipe = SwipeDRUL; break; - case 2: gestsarr[gestsarrlen - 1].command = gestpt; break; + case 2: + if (!strcmp(gestpt, "L")) gestsarr[gestsarrlen-1].edge = LeftEdge; + if (!strcmp(gestpt, "R")) gestsarr[gestsarrlen-1].edge = RightEdge; + if (!strcmp(gestpt, "T")) gestsarr[gestsarrlen-1].edge = TopEdge; + if (!strcmp(gestpt, "B")) gestsarr[gestsarrlen-1].edge = BottomEdge; + if (!strcmp(gestpt, "TL")) gestsarr[gestsarrlen-1].edge = TopLeftCorner; + if (!strcmp(gestpt, "TR")) gestsarr[gestsarrlen-1].edge = TopRightCorner; + if (!strcmp(gestpt, "BL")) gestsarr[gestsarrlen-1].edge = BottomLeftCorner; + if (!strcmp(gestpt, "BR")) gestsarr[gestsarrlen-1].edge = BottomRightCorner; + if (!strcmp(gestpt, "N")) gestsarr[gestsarrlen-1].edge = NoEdge; + if (!strcmp(gestpt, "*")) gestsarr[gestsarrlen-1].edge = AnyEdge; + break; + case 3: + if (!strcmp(gestpt, "L")) gestsarr[gestsarrlen-1].distance = LongDistance; + if (!strcmp(gestpt, "M")) gestsarr[gestsarrlen-1].distance = MediumDistance; + if (!strcmp(gestpt, "S")) gestsarr[gestsarrlen-1].distance = ShortDistance; + if (!strcmp(gestpt, "*")) gestsarr[gestsarrlen-1].distance = AnyDistance; + break; + case 4: gestsarr[gestsarrlen - 1].command = gestpt; break; } } } else { - fprintf(stderr, "lisgd [-v] [-d /dev/input/0] [-o 0] [-t 200] [-r 20] [-m 400] [-g '1,LR,notify-send swiped left to right']\n"); + fprintf(stderr, "lisgd [-v] [-d /dev/input/0] [-o 0] [-t 200] [-r 20] [-m 400] [-g '1,LR,L,notify-send swiped left to right from left edge']\n"); exit(1); } } + //get display size + if (!(dpy = XOpenDisplay(0))) + die("cannot open display"); + screen = DefaultScreen(dpy); + screenwidth = DisplayWidth(dpy, screen); + screenheight = DisplayHeight(dpy, screen);
See note above on not depending on X11.
+ // E.g. no gestures passed on CLI - used gestures defined in config.def.h if (gestsarrlen == 0) { gestsarr = malloc(sizeof(gestures)); @@ -329,9 +501,11 @@ main(int argc, char *argv[]) memcpy(gestsarr, gestures, sizeof(gestures)); } - // Modify gestures swipes based on orientation provided - for (i = 0; i < gestsarrlen; i++) + // Modify gestures swipes based on orientation provided + for (i = 0; i < gestsarrlen; i++) { gestsarr[i].swipe = swipereorient(gestsarr[i].swipe, orientation); + gestsarr[i].edge = edgereorient(gestsarr[i].edge, orientation); + } run(); return 0; -- 2.28.0
Hi Maarten - thanks again for sending. I finally got around to reviewing this and testing locally. Sorry about the delay - been caught up in a few other things. Overall this looks good - some style things and cleanup but I'd like to get this merged soon as this does greatly improve functionality in a backwards compatible way; and the implementation here is simple to read. Comments are inline below. Also one other note - it'd be great if you could update the manpage and README documentation. Maarten van Gompel <proycon@anaproy.nl> wrote: > This is a big patch that allows for more fine-tuned gestures in lisgd. > I implemented edge and distance as extra features. This patch is the > required companion to a patch in sxmo-utils that reworks the entire > gesture system. > > --- > Makefile | 5 +- > config.def.h | 26 ++++--- > lisgd.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++----- > 3 files changed, 212 insertions(+), 33 deletions(-) > > diff --git a/Makefile b/Makefile > index b2ab358..4c86c8f 100644 > --- a/Makefile > +++ b/Makefile > @@ -2,6 +2,9 @@ SRC = lisgd.c > OBJ = ${SRC:.c=.o} > LDFLAGS = -linput -lm > > +X11INC = /usr/X11R6/include > +X11LIB = /usr/X11R6/lib Right now lisgd has no depedency on X11 and if possible I'd like to keep it that way and just depend on libinput. I know there is another project using lisgd on Wayland too. I'm not positive how things will calibrate (mm vs px); but libinput does have a call to get the screensize (libinput_device_get_size): https://wayland.freedesktop.org/libinput/doc/latest/api/group__device.html > + > all: options lisgd > > options: > @@ -19,7 +22,7 @@ config.h: > cp config.def.h $@ > > lisgd: ${OBJ} > - ${CC} -g -o $@ ${OBJ} ${LDFLAGS} > + ${CC} -g -o $@ ${OBJ} -I${X11INC} -lX11 ${LDFLAGS} > > install: all > mkdir -p ${DESTDIR}${PREFIX}/bin > diff --git a/config.def.h b/config.def.h > index 641de0d..659ad5b 100644 > --- a/config.def.h > +++ b/config.def.h > @@ -1,5 +1,5 @@ > -/* > - distancethreshold: Minimum cutoff for a gestures to take effect > +/* > + distancethreshold: Minimum cutoff for a gestures to take effect > degreesleniency: Offset degrees within which gesture is recognized (max=45) > timeoutms: Maximum duration for a gesture to take place in miliseconds > orientation: Number of 90 degree turns to shift gestures by > @@ -15,18 +15,20 @@ unsigned int degreesleniency = 15; > unsigned int timeoutms = 800; > unsigned int orientation = 0; > unsigned int verbose = 0; > +double edgesize_x = 50.0; > +double edgesize_y = 50.0; Let's keep with the style of no underscores. So edgesize{x,y} works here. > char *device = "/dev/input/event1"; > > Gesture gestures[] = { > /* nfingers gesturetype command */ > - { 1, SwipeLR, "xdotool key --clearmodifiers Alt+Shift+e" }, > - { 1, SwipeRL, "xdotool key --clearmodifiers Alt+Shift+r" }, > - { 1, SwipeDLUR, "sxmo_vol.sh up" }, > - { 1, SwipeURDL, "sxmo_vol.sh down" }, > - { 1, SwipeDRUL, "sxmo_brightness.sh up" }, > - { 1, SwipeULDR, "sxmo_brightness.sh down" }, > - { 2, SwipeLR, "xdotool key --clearmodifiers Alt+e" }, > - { 2, SwipeRL, "xdotool key --clearmodifiers Alt+r" }, > - { 2, SwipeDU, "pidof svkbd-sxmo || svkbd-sxmo &" }, > - { 2, SwipeUD, "pkill -9 svkbd-sxmo" }, > + { 1, SwipeLR, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+Shift+e" }, > + { 1, SwipeRL, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+Shift+r" }, > + { 1, SwipeDLUR, AnyEdge, AnyDistance, "sxmo_vol.sh up" }, > + { 1, SwipeURDL, AnyEdge, AnyDistance, "sxmo_vol.sh down" }, > + { 1, SwipeDRUL, AnyEdge, AnyDistance, "sxmo_brightness.sh up" }, > + { 1, SwipeULDR, AnyEdge, AnyDistance, "sxmo_brightness.sh down" }, > + { 2, SwipeLR, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+e" }, > + { 2, SwipeRL, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+r" }, > + { 2, SwipeDU, AnyEdge, AnyDistance, "pidof svkbd-sxmo || svkbd-sxmo &" }, > + { 2, SwipeUD, AnyEdge, AnyDistance, "pkill -9 svkbd-sxmo" }, > }; > diff --git a/lisgd.c b/lisgd.c > index 5adfbfa..bf83143 100644 > --- a/lisgd.c > +++ b/lisgd.c > @@ -10,6 +10,7 @@ > #include <sys/select.h> > #include <time.h> > #include <unistd.h> > +#include <X11/Xlib.h> See note above on X11. > > /* Defines */ > #define MAXSLOTS 20 > @@ -26,11 +27,35 @@ enum { > SwipeURDL, > SwipeULDR > }; > - > typedef int Swipe; > + > +enum { > + AnyEdge, > + NoEdge, > + LeftEdge, > + RightEdge, > + TopEdge, > + BottomEdge, > + TopLeftCorner, > + TopRightCorner, > + BottomLeftCorner, > + BottomRightCorner, > +}; > +typedef int Edge; Similar to Swipe<Identifier>; for consistency we should use Edge<Identifier>. So instead of TopEdge, we should use EdgeTop. > + > +enum { > + AnyDistance, > + ShortDistance, > + MediumDistance, > + LongDistance, Same feeback here - should be DistanceShort not ShortDistance. > +}; > +typedef int Distance; > + > typedef struct { > int nfswipe; > Swipe swipe; > + Edge edge; > + Distance distance; > char *command; > } Gesture; > > @@ -41,9 +66,14 @@ typedef struct { > Gesture *gestsarr; > int gestsarrlen; > Swipe pendingswipe; > +Edge pendingedge; > +Distance pendingdistance; > double xstart[MAXSLOTS], xend[MAXSLOTS], ystart[MAXSLOTS], yend[MAXSLOTS]; > unsigned nfdown = 0, nfpendingswipe = 0; > struct timespec timedown; > +static Display *dpy; > +static int screen; > +static int screenwidth, screenheight; > > void > die(char * msg) > @@ -91,31 +121,119 @@ gesturecalculateswipe(double x0, double y0, double x1, double y1) { > return -1; > } > > +Distance > +gesturecalculatedistance(double x0, double y0, double x1, double y1, Swipe swipe) { > + double dist = sqrt(pow(x1 - x0, 2) + pow(y1 - y0, 2)); > + double diag = sqrt(pow(screenwidth,2) + pow(screenheight,2)); > + switch (swipe) { > + case SwipeDU: > + case SwipeUD: > + if (dist >= screenheight * 0.66) { > + return LongDistance; > + } else if (dist >= screenheight * 0.33) { > + return MediumDistance; > + } else { > + return ShortDistance; > + } > + break; > + case SwipeLR: > + case SwipeRL: > + if (dist >= screenwidth * 0.66) { > + return LongDistance; > + } else if (dist >= screenwidth * 0.33) { > + return MediumDistance; > + } else { > + return ShortDistance; > + } > + break; > + case SwipeULDR: > + case SwipeDRUL: > + case SwipeDLUR: > + case SwipeURDL: > + if (dist >= diag * 0.66) { > + return LongDistance; > + } else if (dist >= diag * 0.33) { > + return MediumDistance; > + } else { > + return ShortDistance; > + } > + break; > + } > + > + return 0; //shouldn't happen > +} > + > +Edge > +gesturecalculateedge(double x0, double y0, double x1, double y1) { > + Edge horizontal = NoEdge; > + Edge vertical = NoEdge; > + if (x0 <= edgesize_x) { > + horizontal = LeftEdge; Does the ordering matter here - if not it would be nice to combine theses conditions to be less verbose like: if (x0 <= edgesize_x || x1 <= edgesize_x) horizontal = LeftEdge; else if (x0 >= screenwidth - edgesize_x || x1 >= screenwidth - edgesize_x) horizontal = RightEdge; > + } else if (x0 >= screenwidth - edgesize_x) { > + horizontal = RightEdge; > + } else if (x1 <= edgesize_x) { > + horizontal = LeftEdge; > + } else if (x1 >= screenwidth - edgesize_x) { > + horizontal = RightEdge; > + } > + if (y0 <= edgesize_y) { > + vertical = TopEdge; > + } else if (y0 >= screenheight - edgesize_y) { > + vertical = BottomEdge; > + } else if (y1 <= edgesize_y) { > + vertical = TopEdge; > + } else if (y1 >= screenheight - edgesize_y) { > + vertical = BottomEdge; > + } > + if (horizontal == LeftEdge && vertical == TopEdge) { > + return TopLeftCorner; > + } else if (horizontal == RightEdge && vertical == TopEdge) { > + return TopRightCorner; > + } else if (horizontal == LeftEdge && vertical == BottomEdge) { > + return BottomLeftCorner; > + } else if (horizontal == RightEdge && vertical == BottomEdge) { > + return BottomRightCorner; > + } else if (horizontal != NoEdge) { > + return horizontal; > + } else { > + return vertical; > + } > +} > + > void > -gestureexecute(Swipe swipe, int nfingers) { > +gestureexecute(Swipe swipe, int nfingers, Edge edge, Distance distance) { > int i; > > for (i = 0; i < gestsarrlen; i++) { > if (verbose) { > - fprintf(stderr, > - "[Nfswipe/SwipeId]: Cfg (%d/%d) <=> Evt (%d/%d)\n", > - gestsarr[i].nfswipe, gestsarr[i].swipe, nfingers, swipe > + fprintf(stderr, > + "[swipe]: Cfg(f=%d/s=%d/e=%d/d=%d) <=> Evt(f=%d/s=%d/e=%d/d=%d)\n", > + gestsarr[i].nfswipe, gestsarr[i].swipe, gestsarr[i].edge, gestsarr[i].distance, nfingers, swipe, edge, distance > ); > } > - if (gestsarr[i].nfswipe == nfingers && gestsarr[i].swipe == swipe) { > + if (gestsarr[i].nfswipe == nfingers && gestsarr[i].swipe == swipe > + && gestsarr[i].distance <= distance > + && (gestsarr[i].edge == AnyEdge || gestsarr[i].edge == edge || > + ((edge == TopLeftCorner || edge == TopRightCorner) && gestsarr[i].edge == TopEdge) || > + ((edge == BottomLeftCorner || edge == BottomRightCorner) && gestsarr[i].edge == BottomEdge) || > + ((edge == TopLeftCorner || edge == BottomLeftCorner) && gestsarr[i].edge == LeftEdge) || > + ((edge == TopRightCorner || edge == BottomRightCorner) && gestsarr[i].edge == RightEdge) > + ) > + ) { > if (verbose) fprintf(stderr, "Execute %s\n", gestsarr[i].command); > execcommand(gestsarr[i].command); > + break; //execute first match only > } > } > } > > -static int > +static int > libinputopenrestricted(const char *path, int flags, void *user_data) > { > int fd = open(path, flags); > return fd < 0 ? -errno : fd; > } > - > + > static void > libinputcloserestricted(int fd, void *user_data) > { > @@ -141,6 +259,25 @@ swipereorient(Swipe swipe, int orientation) { > return swipe; > } > > +Edge > +edgereorient(Edge edge, int orientation) { > + while (orientation > 0) { > + switch(edge) { > + // 90deg per turn > + case LeftEdge: edge = TopEdge; break; > + case RightEdge: edge = BottomEdge; break; > + case TopEdge: edge = RightEdge; break; > + case BottomEdge: edge = LeftEdge; break; > + case TopLeftCorner: edge = TopRightCorner; break; > + case TopRightCorner: edge = BottomRightCorner; break; > + case BottomLeftCorner: edge = TopLeftCorner; break; > + case BottomRightCorner: edge = BottomLeftCorner; break; > + } > + orientation--; > + } > + return edge; > +} > + > void > touchdown(struct libinput_event *e) > { > @@ -197,17 +334,27 @@ touchup(struct libinput_event *e) > Swipe swipe = gesturecalculateswipe( > xstart[slot], ystart[slot], xend[slot], yend[slot] > ); > - if (nfpendingswipe == 0) pendingswipe = swipe; > + Edge edge = gesturecalculateedge( > + xstart[slot], ystart[slot], xend[slot], yend[slot] > + ); > + Distance distance = gesturecalculatedistance( > + xstart[slot], ystart[slot], xend[slot], yend[slot], swipe > + ); > + if (nfpendingswipe == 0) { > + pendingswipe = swipe; > + pendingedge = edge; > + pendingdistance = distance; > + } > if (pendingswipe == swipe) nfpendingswipe++; > resetslot(slot); > > // All fingers up - check if within milisecond limit, exec, & reset > if (nfdown == 0) { > if ( > - timeoutms > > + timeoutms > > ((now.tv_sec - timedown.tv_sec) * 1000000 + (now.tv_nsec - timedown.tv_nsec) / 1000) / 1000 > - ) gestureexecute(swipe, nfpendingswipe); > - > + ) gestureexecute(swipe, nfpendingswipe, edge, distance); > + > nfpendingswipe = 0; > } > } > @@ -238,7 +385,7 @@ run() > die("Couldn't set mode to capture events"); > } > > - // E.g. initially invalidate every slot > + // E.g. initially invalidate every slot > for (i = 0; i < MAXSLOTS; i++) { > xend[i] = NOMOTION; > yend[i] = NOMOTION; > @@ -266,7 +413,7 @@ run() > } > libinput_unref(li); > } > - > + > int > main(int argc, char *argv[]) > { > @@ -300,10 +447,10 @@ main(int argc, char *argv[]) > exit(EXIT_FAILURE); > } > gestpt = strtok(argv[++i], ","); > - for (j = 0; gestpt != NULL && j < 3; gestpt = strtok(NULL, ","), j++) { > + for (j = 0; gestpt != NULL && j < 5; gestpt = strtok(NULL, ","), j++) { > switch(j) { > case 0: gestsarr[gestsarrlen - 1].nfswipe = atoi(gestpt); break; > - case 1: > + case 1: > if (!strcmp(gestpt, "LR")) gestsarr[gestsarrlen-1].swipe = SwipeLR; > if (!strcmp(gestpt, "RL")) gestsarr[gestsarrlen-1].swipe = SwipeRL; > if (!strcmp(gestpt, "DU")) gestsarr[gestsarrlen-1].swipe = SwipeDU; > @@ -313,15 +460,40 @@ main(int argc, char *argv[]) > if (!strcmp(gestpt, "ULDR")) gestsarr[gestsarrlen-1].swipe = SwipeULDR; > if (!strcmp(gestpt, "DRUL")) gestsarr[gestsarrlen-1].swipe = SwipeDRUL; > break; > - case 2: gestsarr[gestsarrlen - 1].command = gestpt; break; > + case 2: > + if (!strcmp(gestpt, "L")) gestsarr[gestsarrlen-1].edge = LeftEdge; > + if (!strcmp(gestpt, "R")) gestsarr[gestsarrlen-1].edge = RightEdge; > + if (!strcmp(gestpt, "T")) gestsarr[gestsarrlen-1].edge = TopEdge; > + if (!strcmp(gestpt, "B")) gestsarr[gestsarrlen-1].edge = BottomEdge; > + if (!strcmp(gestpt, "TL")) gestsarr[gestsarrlen-1].edge = TopLeftCorner; > + if (!strcmp(gestpt, "TR")) gestsarr[gestsarrlen-1].edge = TopRightCorner; > + if (!strcmp(gestpt, "BL")) gestsarr[gestsarrlen-1].edge = BottomLeftCorner; > + if (!strcmp(gestpt, "BR")) gestsarr[gestsarrlen-1].edge = BottomRightCorner; > + if (!strcmp(gestpt, "N")) gestsarr[gestsarrlen-1].edge = NoEdge; > + if (!strcmp(gestpt, "*")) gestsarr[gestsarrlen-1].edge = AnyEdge; > + break; > + case 3: > + if (!strcmp(gestpt, "L")) gestsarr[gestsarrlen-1].distance = LongDistance; > + if (!strcmp(gestpt, "M")) gestsarr[gestsarrlen-1].distance = MediumDistance; > + if (!strcmp(gestpt, "S")) gestsarr[gestsarrlen-1].distance = ShortDistance; > + if (!strcmp(gestpt, "*")) gestsarr[gestsarrlen-1].distance = AnyDistance; > + break; > + case 4: gestsarr[gestsarrlen - 1].command = gestpt; break; > } > } > } else { > - fprintf(stderr, "lisgd [-v] [-d /dev/input/0] [-o 0] [-t 200] [-r 20] [-m 400] [-g '1,LR,notify-send swiped left to right']\n"); > + fprintf(stderr, "lisgd [-v] [-d /dev/input/0] [-o 0] [-t 200] [-r 20] [-m 400] [-g '1,LR,L,notify-send swiped left to right from left edge']\n"); > exit(1); > } > } > > + //get display size > + if (!(dpy = XOpenDisplay(0))) > + die("cannot open display"); > + screen = DefaultScreen(dpy); > + screenwidth = DisplayWidth(dpy, screen); > + screenheight = DisplayHeight(dpy, screen); See note above on not depending on X11. > + > // E.g. no gestures passed on CLI - used gestures defined in config.def.h > if (gestsarrlen == 0) { > gestsarr = malloc(sizeof(gestures)); > @@ -329,9 +501,11 @@ main(int argc, char *argv[]) > memcpy(gestsarr, gestures, sizeof(gestures)); > } > > - // Modify gestures swipes based on orientation provided > - for (i = 0; i < gestsarrlen; i++) > + // Modify gestures swipes based on orientation provided > + for (i = 0; i < gestsarrlen; i++) { > gestsarr[i].swipe = swipereorient(gestsarr[i].swipe, orientation); > + gestsarr[i].edge = edgereorient(gestsarr[i].edge, orientation); > + } > > run(); > return 0; > -- > 2.28.0
Thanks for working on this and sending - this is a pretty great improvement and resolves alot of the issues with gestures currently triggering by the user unintentionally. And it also looks like this is backwards compatible if you don't want to use the edge/corner-based model. I should have detailed feedback on the lisgd side of things in the next few days - I just want to test things out and book some time to have a closer look at the diff. Miles Maarten van Gompel <proycon@anaproy.nl> wrote: > This is a big patch that allows for more fine-tuned gestures in lisgd. > I implemented edge and distance as extra features. This patch is the > required companion to a patch in sxmo-utils that reworks the entire > gesture system. > > --- > Makefile | 5 +- > config.def.h | 26 ++++--- > lisgd.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++----- > 3 files changed, 212 insertions(+), 33 deletions(-) > > diff --git a/Makefile b/Makefile > index b2ab358..4c86c8f 100644 > --- a/Makefile > +++ b/Makefile > @@ -2,6 +2,9 @@ SRC = lisgd.c > OBJ = ${SRC:.c=.o} > LDFLAGS = -linput -lm > > +X11INC = /usr/X11R6/include > +X11LIB = /usr/X11R6/lib > + > all: options lisgd > > options: > @@ -19,7 +22,7 @@ config.h: > cp config.def.h $@ > > lisgd: ${OBJ} > - ${CC} -g -o $@ ${OBJ} ${LDFLAGS} > + ${CC} -g -o $@ ${OBJ} -I${X11INC} -lX11 ${LDFLAGS} > > install: all > mkdir -p ${DESTDIR}${PREFIX}/bin > diff --git a/config.def.h b/config.def.h > index 641de0d..659ad5b 100644 > --- a/config.def.h > +++ b/config.def.h > @@ -1,5 +1,5 @@ > -/* > - distancethreshold: Minimum cutoff for a gestures to take effect > +/* > + distancethreshold: Minimum cutoff for a gestures to take effect > degreesleniency: Offset degrees within which gesture is recognized (max=45) > timeoutms: Maximum duration for a gesture to take place in miliseconds > orientation: Number of 90 degree turns to shift gestures by > @@ -15,18 +15,20 @@ unsigned int degreesleniency = 15; > unsigned int timeoutms = 800; > unsigned int orientation = 0; > unsigned int verbose = 0; > +double edgesize_x = 50.0; > +double edgesize_y = 50.0; > char *device = "/dev/input/event1"; > > Gesture gestures[] = { > /* nfingers gesturetype command */ > - { 1, SwipeLR, "xdotool key --clearmodifiers Alt+Shift+e" }, > - { 1, SwipeRL, "xdotool key --clearmodifiers Alt+Shift+r" }, > - { 1, SwipeDLUR, "sxmo_vol.sh up" }, > - { 1, SwipeURDL, "sxmo_vol.sh down" }, > - { 1, SwipeDRUL, "sxmo_brightness.sh up" }, > - { 1, SwipeULDR, "sxmo_brightness.sh down" }, > - { 2, SwipeLR, "xdotool key --clearmodifiers Alt+e" }, > - { 2, SwipeRL, "xdotool key --clearmodifiers Alt+r" }, > - { 2, SwipeDU, "pidof svkbd-sxmo || svkbd-sxmo &" }, > - { 2, SwipeUD, "pkill -9 svkbd-sxmo" }, > + { 1, SwipeLR, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+Shift+e" }, > + { 1, SwipeRL, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+Shift+r" }, > + { 1, SwipeDLUR, AnyEdge, AnyDistance, "sxmo_vol.sh up" }, > + { 1, SwipeURDL, AnyEdge, AnyDistance, "sxmo_vol.sh down" }, > + { 1, SwipeDRUL, AnyEdge, AnyDistance, "sxmo_brightness.sh up" }, > + { 1, SwipeULDR, AnyEdge, AnyDistance, "sxmo_brightness.sh down" }, > + { 2, SwipeLR, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+e" }, > + { 2, SwipeRL, AnyEdge, AnyDistance, "xdotool key --clearmodifiers Alt+r" }, > + { 2, SwipeDU, AnyEdge, AnyDistance, "pidof svkbd-sxmo || svkbd-sxmo &" }, > + { 2, SwipeUD, AnyEdge, AnyDistance, "pkill -9 svkbd-sxmo" }, > }; > diff --git a/lisgd.c b/lisgd.c > index 5adfbfa..bf83143 100644 > --- a/lisgd.c > +++ b/lisgd.c > @@ -10,6 +10,7 @@ > #include <sys/select.h> > #include <time.h> > #include <unistd.h> > +#include <X11/Xlib.h> > > /* Defines */ > #define MAXSLOTS 20 > @@ -26,11 +27,35 @@ enum { > SwipeURDL, > SwipeULDR > }; > - > typedef int Swipe; > + > +enum { > + AnyEdge, > + NoEdge, > + LeftEdge, > + RightEdge, > + TopEdge, > + BottomEdge, > + TopLeftCorner, > + TopRightCorner, > + BottomLeftCorner, > + BottomRightCorner, > +}; > +typedef int Edge; > + > +enum { > + AnyDistance, > + ShortDistance, > + MediumDistance, > + LongDistance, > +}; > +typedef int Distance; > + > typedef struct { > int nfswipe; > Swipe swipe; > + Edge edge; > + Distance distance; > char *command; > } Gesture; > > @@ -41,9 +66,14 @@ typedef struct { > Gesture *gestsarr; > int gestsarrlen; > Swipe pendingswipe; > +Edge pendingedge; > +Distance pendingdistance; > double xstart[MAXSLOTS], xend[MAXSLOTS], ystart[MAXSLOTS], yend[MAXSLOTS]; > unsigned nfdown = 0, nfpendingswipe = 0; > struct timespec timedown; > +static Display *dpy; > +static int screen; > +static int screenwidth, screenheight; > > void > die(char * msg) > @@ -91,31 +121,119 @@ gesturecalculateswipe(double x0, double y0, double x1, double y1) { > return -1; > } > > +Distance > +gesturecalculatedistance(double x0, double y0, double x1, double y1, Swipe swipe) { > + double dist = sqrt(pow(x1 - x0, 2) + pow(y1 - y0, 2)); > + double diag = sqrt(pow(screenwidth,2) + pow(screenheight,2)); > + switch (swipe) { > + case SwipeDU: > + case SwipeUD: > + if (dist >= screenheight * 0.66) { > + return LongDistance; > + } else if (dist >= screenheight * 0.33) { > + return MediumDistance; > + } else { > + return ShortDistance; > + } > + break; > + case SwipeLR: > + case SwipeRL: > + if (dist >= screenwidth * 0.66) { > + return LongDistance; > + } else if (dist >= screenwidth * 0.33) { > + return MediumDistance; > + } else { > + return ShortDistance; > + } > + break; > + case SwipeULDR: > + case SwipeDRUL: > + case SwipeDLUR: > + case SwipeURDL: > + if (dist >= diag * 0.66) { > + return LongDistance; > + } else if (dist >= diag * 0.33) { > + return MediumDistance; > + } else { > + return ShortDistance; > + } > + break; > + } > + > + return 0; //shouldn't happen > +} > + > +Edge > +gesturecalculateedge(double x0, double y0, double x1, double y1) { > + Edge horizontal = NoEdge; > + Edge vertical = NoEdge; > + if (x0 <= edgesize_x) { > + horizontal = LeftEdge; > + } else if (x0 >= screenwidth - edgesize_x) { > + horizontal = RightEdge; > + } else if (x1 <= edgesize_x) { > + horizontal = LeftEdge; > + } else if (x1 >= screenwidth - edgesize_x) { > + horizontal = RightEdge; > + } > + if (y0 <= edgesize_y) { > + vertical = TopEdge; > + } else if (y0 >= screenheight - edgesize_y) { > + vertical = BottomEdge; > + } else if (y1 <= edgesize_y) { > + vertical = TopEdge; > + } else if (y1 >= screenheight - edgesize_y) { > + vertical = BottomEdge; > + } > + if (horizontal == LeftEdge && vertical == TopEdge) { > + return TopLeftCorner; > + } else if (horizontal == RightEdge && vertical == TopEdge) { > + return TopRightCorner; > + } else if (horizontal == LeftEdge && vertical == BottomEdge) { > + return BottomLeftCorner; > + } else if (horizontal == RightEdge && vertical == BottomEdge) { > + return BottomRightCorner; > + } else if (horizontal != NoEdge) { > + return horizontal; > + } else { > + return vertical; > + } > +} > + > void > -gestureexecute(Swipe swipe, int nfingers) { > +gestureexecute(Swipe swipe, int nfingers, Edge edge, Distance distance) { > int i; > > for (i = 0; i < gestsarrlen; i++) { > if (verbose) { > - fprintf(stderr, > - "[Nfswipe/SwipeId]: Cfg (%d/%d) <=> Evt (%d/%d)\n", > - gestsarr[i].nfswipe, gestsarr[i].swipe, nfingers, swipe > + fprintf(stderr, > + "[swipe]: Cfg(f=%d/s=%d/e=%d/d=%d) <=> Evt(f=%d/s=%d/e=%d/d=%d)\n", > + gestsarr[i].nfswipe, gestsarr[i].swipe, gestsarr[i].edge, gestsarr[i].distance, nfingers, swipe, edge, distance > ); > } > - if (gestsarr[i].nfswipe == nfingers && gestsarr[i].swipe == swipe) { > + if (gestsarr[i].nfswipe == nfingers && gestsarr[i].swipe == swipe > + && gestsarr[i].distance <= distance > + && (gestsarr[i].edge == AnyEdge || gestsarr[i].edge == edge || > + ((edge == TopLeftCorner || edge == TopRightCorner) && gestsarr[i].edge == TopEdge) || > + ((edge == BottomLeftCorner || edge == BottomRightCorner) && gestsarr[i].edge == BottomEdge) || > + ((edge == TopLeftCorner || edge == BottomLeftCorner) && gestsarr[i].edge == LeftEdge) || > + ((edge == TopRightCorner || edge == BottomRightCorner) && gestsarr[i].edge == RightEdge) > + ) > + ) { > if (verbose) fprintf(stderr, "Execute %s\n", gestsarr[i].command); > execcommand(gestsarr[i].command); > + break; //execute first match only > } > } > } > > -static int > +static int > libinputopenrestricted(const char *path, int flags, void *user_data) > { > int fd = open(path, flags); > return fd < 0 ? -errno : fd; > } > - > + > static void > libinputcloserestricted(int fd, void *user_data) > { > @@ -141,6 +259,25 @@ swipereorient(Swipe swipe, int orientation) { > return swipe; > } > > +Edge > +edgereorient(Edge edge, int orientation) { > + while (orientation > 0) { > + switch(edge) { > + // 90deg per turn > + case LeftEdge: edge = TopEdge; break; > + case RightEdge: edge = BottomEdge; break; > + case TopEdge: edge = RightEdge; break; > + case BottomEdge: edge = LeftEdge; break; > + case TopLeftCorner: edge = TopRightCorner; break; > + case TopRightCorner: edge = BottomRightCorner; break; > + case BottomLeftCorner: edge = TopLeftCorner; break; > + case BottomRightCorner: edge = BottomLeftCorner; break; > + } > + orientation--; > + } > + return edge; > +} > + > void > touchdown(struct libinput_event *e) > { > @@ -197,17 +334,27 @@ touchup(struct libinput_event *e) > Swipe swipe = gesturecalculateswipe( > xstart[slot], ystart[slot], xend[slot], yend[slot] > ); > - if (nfpendingswipe == 0) pendingswipe = swipe; > + Edge edge = gesturecalculateedge( > + xstart[slot], ystart[slot], xend[slot], yend[slot] > + ); > + Distance distance = gesturecalculatedistance( > + xstart[slot], ystart[slot], xend[slot], yend[slot], swipe > + ); > + if (nfpendingswipe == 0) { > + pendingswipe = swipe; > + pendingedge = edge; > + pendingdistance = distance; > + } > if (pendingswipe == swipe) nfpendingswipe++; > resetslot(slot); > > // All fingers up - check if within milisecond limit, exec, & reset > if (nfdown == 0) { > if ( > - timeoutms > > + timeoutms > > ((now.tv_sec - timedown.tv_sec) * 1000000 + (now.tv_nsec - timedown.tv_nsec) / 1000) / 1000 > - ) gestureexecute(swipe, nfpendingswipe); > - > + ) gestureexecute(swipe, nfpendingswipe, edge, distance); > + > nfpendingswipe = 0; > } > } > @@ -238,7 +385,7 @@ run() > die("Couldn't set mode to capture events"); > } > > - // E.g. initially invalidate every slot > + // E.g. initially invalidate every slot > for (i = 0; i < MAXSLOTS; i++) { > xend[i] = NOMOTION; > yend[i] = NOMOTION; > @@ -266,7 +413,7 @@ run() > } > libinput_unref(li); > } > - > + > int > main(int argc, char *argv[]) > { > @@ -300,10 +447,10 @@ main(int argc, char *argv[]) > exit(EXIT_FAILURE); > } > gestpt = strtok(argv[++i], ","); > - for (j = 0; gestpt != NULL && j < 3; gestpt = strtok(NULL, ","), j++) { > + for (j = 0; gestpt != NULL && j < 5; gestpt = strtok(NULL, ","), j++) { > switch(j) { > case 0: gestsarr[gestsarrlen - 1].nfswipe = atoi(gestpt); break; > - case 1: > + case 1: > if (!strcmp(gestpt, "LR")) gestsarr[gestsarrlen-1].swipe = SwipeLR; > if (!strcmp(gestpt, "RL")) gestsarr[gestsarrlen-1].swipe = SwipeRL; > if (!strcmp(gestpt, "DU")) gestsarr[gestsarrlen-1].swipe = SwipeDU; > @@ -313,15 +460,40 @@ main(int argc, char *argv[]) > if (!strcmp(gestpt, "ULDR")) gestsarr[gestsarrlen-1].swipe = SwipeULDR; > if (!strcmp(gestpt, "DRUL")) gestsarr[gestsarrlen-1].swipe = SwipeDRUL; > break; > - case 2: gestsarr[gestsarrlen - 1].command = gestpt; break; > + case 2: > + if (!strcmp(gestpt, "L")) gestsarr[gestsarrlen-1].edge = LeftEdge; > + if (!strcmp(gestpt, "R")) gestsarr[gestsarrlen-1].edge = RightEdge; > + if (!strcmp(gestpt, "T")) gestsarr[gestsarrlen-1].edge = TopEdge; > + if (!strcmp(gestpt, "B")) gestsarr[gestsarrlen-1].edge = BottomEdge; > + if (!strcmp(gestpt, "TL")) gestsarr[gestsarrlen-1].edge = TopLeftCorner; > + if (!strcmp(gestpt, "TR")) gestsarr[gestsarrlen-1].edge = TopRightCorner; > + if (!strcmp(gestpt, "BL")) gestsarr[gestsarrlen-1].edge = BottomLeftCorner; > + if (!strcmp(gestpt, "BR")) gestsarr[gestsarrlen-1].edge = BottomRightCorner; > + if (!strcmp(gestpt, "N")) gestsarr[gestsarrlen-1].edge = NoEdge; > + if (!strcmp(gestpt, "*")) gestsarr[gestsarrlen-1].edge = AnyEdge; > + break; > + case 3: > + if (!strcmp(gestpt, "L")) gestsarr[gestsarrlen-1].distance = LongDistance; > + if (!strcmp(gestpt, "M")) gestsarr[gestsarrlen-1].distance = MediumDistance; > + if (!strcmp(gestpt, "S")) gestsarr[gestsarrlen-1].distance = ShortDistance; > + if (!strcmp(gestpt, "*")) gestsarr[gestsarrlen-1].distance = AnyDistance; > + break; > + case 4: gestsarr[gestsarrlen - 1].command = gestpt; break; > } > } > } else { > - fprintf(stderr, "lisgd [-v] [-d /dev/input/0] [-o 0] [-t 200] [-r 20] [-m 400] [-g '1,LR,notify-send swiped left to right']\n"); > + fprintf(stderr, "lisgd [-v] [-d /dev/input/0] [-o 0] [-t 200] [-r 20] [-m 400] [-g '1,LR,L,notify-send swiped left to right from left edge']\n"); > exit(1); > } > } > > + //get display size > + if (!(dpy = XOpenDisplay(0))) > + die("cannot open display"); > + screen = DefaultScreen(dpy); > + screenwidth = DisplayWidth(dpy, screen); > + screenheight = DisplayHeight(dpy, screen); > + > // E.g. no gestures passed on CLI - used gestures defined in config.def.h > if (gestsarrlen == 0) { > gestsarr = malloc(sizeof(gestures)); > @@ -329,9 +501,11 @@ main(int argc, char *argv[]) > memcpy(gestsarr, gestures, sizeof(gestures)); > } > > - // Modify gestures swipes based on orientation provided > - for (i = 0; i < gestsarrlen; i++) > + // Modify gestures swipes based on orientation provided > + for (i = 0; i < gestsarrlen; i++) { > gestsarr[i].swipe = swipereorient(gestsarr[i].swipe, orientation); > + gestsarr[i].edge = edgereorient(gestsarr[i].edge, orientation); > + } > > run(); > return 0; > -- > 2.28.0