lisgd + wvkbd
This commit is contained in:
parent
adbe4541cb
commit
6d345f43d4
36 changed files with 31637 additions and 0 deletions
2
packages/lisgd/.gitignore
vendored
Normal file
2
packages/lisgd/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
lisgd
|
||||
lisgd.o
|
||||
21
packages/lisgd/LICENSE
Normal file
21
packages/lisgd/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT/X Consortium License
|
||||
|
||||
© 2020 Miles Alan <m@milesalan.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
56
packages/lisgd/Makefile
Normal file
56
packages/lisgd/Makefile
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
PREFIX = /usr
|
||||
SRC = lisgd.c
|
||||
OBJ = ${SRC:.c=.o}
|
||||
LDFLAGS = -g
|
||||
LIBS = -linput -lm
|
||||
|
||||
X11INC = /usr/X11R6/include
|
||||
X11LIB = /usr/X11R6/lib
|
||||
|
||||
ifndef WITHOUT_X11
|
||||
CPPFLAGS += -I${X11INC} -DWITH_X11
|
||||
LIBS += -L${X11LIB} -lX11
|
||||
endif
|
||||
|
||||
ifndef WITHOUT_WAYLAND
|
||||
CPPFLAGS += -DWITH_WAYLAND
|
||||
LIBS += -lwayland-client
|
||||
endif
|
||||
|
||||
all: options lisgd
|
||||
|
||||
options:
|
||||
@echo lisgd build options:
|
||||
@echo "CFLAGS = ${CFLAGS}"
|
||||
@echo "CPPFLAGS = ${CPPFLAGS}"
|
||||
@echo "LDFLAGS = ${LDFLAGS}"
|
||||
@echo "LIBS = ${LIBS}"
|
||||
@echo "CC = ${CC}"
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} ${CPPFLAGS} $<
|
||||
|
||||
${OBJ}: config.h
|
||||
|
||||
config.h:
|
||||
cp config.def.h $@
|
||||
|
||||
lisgd: ${OBJ}
|
||||
${CC} -o $@ ${OBJ} ${LDFLAGS} ${LIBS}
|
||||
|
||||
install: all
|
||||
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||
cp -f lisgd ${DESTDIR}${PREFIX}/bin
|
||||
chmod 755 ${DESTDIR}${PREFIX}/bin/lisgd
|
||||
|
||||
mkdir -p ${DESTDIR}${PREFIX}/share/man/man1
|
||||
cp lisgd.1 ${DESTDIR}${PREFIX}/share/man/man1
|
||||
chmod 755 ${DESTDIR}${PREFIX}/share/man/man1
|
||||
|
||||
uninstall:
|
||||
rm -f ${DESTDIR}${PREFIX}/bin/lisgd ${DESTDIR}${PREFIX}/share/man/man1/lisgd.1
|
||||
|
||||
clean:
|
||||
rm -f lisgd.o lisgd
|
||||
|
||||
.PHONY: all options install clean
|
||||
72
packages/lisgd/README.md
Normal file
72
packages/lisgd/README.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# lisgd
|
||||
|
||||
Lisgd (libinput **synthetic** gesture daemon) lets you bind gestures based on
|
||||
libinput touch events to run specific commands to execute. For example,
|
||||
dragging left to right with one finger could execute a particular command
|
||||
like launching a terminal. Directional L-R, R-L, U-D, and D-U gestures and
|
||||
diagnol LD-RU, RD-LU, UR-DL, UL-DR gestures are supported with 1 through
|
||||
n fingers.
|
||||
|
||||
Unlike other libinput gesture daemons, lisgd uses touch events to
|
||||
recognize **synthetic swipe gestures** rather than using the *libinput*'s
|
||||
gesture events. The advantage of this is that the synthetic gestures
|
||||
you define via lisgd can be used on touchscreens, which normal libinput
|
||||
gestures don't support.
|
||||
|
||||
This program was built for use on the [Pinephone](https://www.pine64.org/pinephone/);
|
||||
however it could be used in general for any device that supports touch events,
|
||||
like laptop touchscreens or similar. You may want to adjust the threshold
|
||||
depending on the device you're using.
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration can be done in two ways:
|
||||
|
||||
1. Through a suckless style `config.h`; see the `config.def.h`
|
||||
2. Through commandline flags which override the default config.h values
|
||||
|
||||
### Suckless-style config.h based configuration
|
||||
|
||||
Copy the example `config.def.h` configuration to `config.h`.
|
||||
|
||||
### Commandline flags based configuration
|
||||
|
||||
Flags:
|
||||
|
||||
- **-d [devicenodepath]**: Defines the dev filesystem device to monitor
|
||||
- Example: `lisgd -d /dev/input/input1`
|
||||
- **-g [nfingers,gesture,edge,distance,actmode,command]**: Allows you to bind a gesture wherein nfingers is an integer, gesture is
|
||||
one of {LR,RL,DU,UD,DLUR,URDL,ULDR,DLUR}, edge is one of * (any), N (none), L (left), R (right), T (top), B (bottom), TL (top left), TR (top right), BL (bottom left), BR (bottom right) and distance is one of * (any), S (short), M (medium), L (large). actmode is R (release) for normal mode and P (pressed) for pressed mode (but this field may be omitted entirely for backward
|
||||
compatibility), command is the shell command to be executed. The -g option can be used
|
||||
multiple times to bind multiple gestures.
|
||||
- Single Gesture Example: `lisgd -g "1,LR,*,*,R,notify-send swiped lr"`
|
||||
- Multiple Gestures Example: `lisgd -g "1,LR,*,*,R,notify-send swiped lr" -g "1,RL,R,*,R,notify-send swiped rl from right edge"`
|
||||
- **-m [timeoutms]**: Number of milliseconds gestures must be performed within
|
||||
to be registered. After the timeoutms value; the gesture won't be registered.
|
||||
- Example: `lisgd -m 1200`
|
||||
- **-o [orientation]**: Number of 90-degree rotations to translate gestures by.
|
||||
Can be set to 0-3. For example using 1; a L-R gesture would become a U-D
|
||||
gesture. Meant to be used for screen-rotation.
|
||||
- Example `lisgd -o 1`
|
||||
- **-r [degrees]**: Number of degrees offset each 45-degree interval may still
|
||||
be recognized within. Maximum value is 45. Default value is 15. E.g. U-D
|
||||
is a 180 degree gesture but with 15 degrees of leniency will be recognized
|
||||
between 165-195 degrees.
|
||||
- Example: `lisgd -r 20`
|
||||
- **-t [threshold_units]**: Threshold in libinput units (pixels) after which a
|
||||
gesture registers. Defaults to 125.
|
||||
- Example: `lisgd -t 125`
|
||||
- **-T [threshold_units]**: Threshold in libinput units (pixels) after which a
|
||||
gesture registers for 'pressed' gestures where fingers are not lifted.
|
||||
Defaults to 60.
|
||||
- Example: `lisgd -t 60`
|
||||
- **-w [screenwidth]**: Width of screen used for edge-based gestures. Use in
|
||||
conjunction with -h. If unset dynamic X/Wayland screen geometry detection is
|
||||
used.
|
||||
- Example: `lisgd -w 600`
|
||||
- **-h [screenheight]**: Height of screen used for edge-based gestures. Use in
|
||||
conjunction with -w. If unset dynamic X/Wayland screen geometry detection is
|
||||
used.
|
||||
- Example: `lisgd -h 500`
|
||||
- **-v**: Verbose mode, useful for debugging
|
||||
- Example: `lisgd -v`
|
||||
39
packages/lisgd/config.def.h
Normal file
39
packages/lisgd/config.def.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
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
|
||||
verbose: 1=enabled, 0=disabled; helpful for debugging
|
||||
device: Path to the /dev/ filesystem device events should be read from
|
||||
gestures: Array of gestures; binds num of fingers / gesturetypes to commands
|
||||
Supported gestures: SwipeLR, SwipeRL, SwipeDU, SwipeUD,
|
||||
SwipeDLUR, SwipeURDL, SwipeDRUL, SwipeULDR
|
||||
*/
|
||||
|
||||
unsigned int distancethreshold = 125;
|
||||
unsigned int distancethreshold_pressed = 60;
|
||||
unsigned int degreesleniency = 15;
|
||||
unsigned int timeoutms = 800;
|
||||
unsigned int orientation = 0;
|
||||
unsigned int verbose = 0;
|
||||
double edgesizeleft = 50.0;
|
||||
double edgesizetop = 50.0;
|
||||
double edgesizeright = 50.0;
|
||||
double edgesizebottom = 50.0;
|
||||
double edgessizecaling = 1.0;
|
||||
char *device = "/dev/input/touchscreen";
|
||||
|
||||
//Gestures can also be specified interactively from the command line using -g
|
||||
Gesture gestures[] = {
|
||||
/* nfingers gesturetype command */
|
||||
{ 1, SwipeLR, EdgeAny, DistanceAny, ActModeReleased, "xdotool key --clearmodifiers Alt+Shift+e" },
|
||||
{ 1, SwipeRL, EdgeAny, DistanceAny, ActModeReleased, "xdotool key --clearmodifiers Alt+Shift+r" },
|
||||
{ 1, SwipeDLUR, EdgeAny, DistanceAny, ActModeReleased, "sxmo_vol.sh up" },
|
||||
{ 1, SwipeURDL, EdgeAny, DistanceAny, ActModeReleased, "sxmo_vol.sh down" },
|
||||
{ 1, SwipeDRUL, EdgeAny, DistanceAny, ActModeReleased, "sxmo_brightness.sh up" },
|
||||
{ 1, SwipeULDR, EdgeAny, DistanceAny, ActModeReleased, "sxmo_brightness.sh down" },
|
||||
{ 2, SwipeLR, EdgeAny, DistanceAny, ActModeReleased, "xdotool key --clearmodifiers Alt+e" },
|
||||
{ 2, SwipeRL, EdgeAny, DistanceAny, ActModeReleased, "xdotool key --clearmodifiers Alt+r" },
|
||||
{ 2, SwipeDU, EdgeAny, DistanceAny, ActModeReleased, "pidof $KEYBOARD || $KEYBOARD &" },
|
||||
{ 2, SwipeUD, EdgeAny, DistanceAny, ActModeReleased, "pkill -9 -f $KEYBOARD" },
|
||||
};
|
||||
60
packages/lisgd/config.h
Normal file
60
packages/lisgd/config.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
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
|
||||
verbose: 1=enabled, 0=disabled; helpful for debugging
|
||||
device: Path to the /dev/ filesystem device events should be read from
|
||||
gestures: Array of gestures; binds num of fingers / gesturetypes to commands
|
||||
Supported gestures: SwipeLR, SwipeRL, SwipeDU, SwipeUD,
|
||||
SwipeDLUR, SwipeURDL, SwipeDRUL, SwipeULDR
|
||||
*/
|
||||
|
||||
unsigned int distancethreshold = 125;
|
||||
unsigned int distancethreshold_pressed = 60;
|
||||
unsigned int degreesleniency = 15;
|
||||
unsigned int timeoutms = 800;
|
||||
unsigned int orientation = 0;
|
||||
unsigned int verbose = 1;
|
||||
double edgesizeleft = 50.0;
|
||||
double edgesizetop = 50.0;
|
||||
double edgesizeright = 50.0;
|
||||
double edgesizebottom = 50.0;
|
||||
double edgessizecaling = 2.0;
|
||||
char *device = "/dev/touchscreen";
|
||||
|
||||
// Gestures can also be specified interactively from the command line using -g
|
||||
Gesture gestures[] = {
|
||||
{1, SwipeRL, EdgeRight, DistanceAny, ActModeReleased,
|
||||
"niri msg action focus-column-right"},
|
||||
{1, SwipeLR, EdgeLeft, DistanceAny, ActModeReleased,
|
||||
"niri msg action focus-column-left"},
|
||||
{1, SwipeDU, CornerBottomRight, DistanceMedium, ActModeReleased,
|
||||
"niri msg action focus-workspace-down"},
|
||||
{1, SwipeUD, CornerTopRight, DistanceMedium, ActModeReleased,
|
||||
"niri msg action focus-workspace-up"},
|
||||
{1, SwipeDU, CornerBottomLeft, DistanceShort, ActModeReleased,
|
||||
"niri msg action switch-preset-column-width"},
|
||||
//{1, SwipeUD, EdgeTop, DistanceAny, ActModeReleased, "nwggrid -o 0.98"},
|
||||
//"pkill -SIGRTMIN -f wvkbd"},
|
||||
//{2, SwipeUD, EdgeAny, DistanceAny, ActModeReleased,
|
||||
//"sway-interactive-screenshot -s focused-output"},
|
||||
//{3, SwipeLR, EdgeAny, DistanceAny, ActModeReleased,
|
||||
//"swaymsg layout tabbed"},
|
||||
//{3, SwipeRL, EdgeAny, DistanceAny, ActModeReleased,
|
||||
//"swaymsg layout toggle split"},
|
||||
{2, SwipeUD, EdgeLeft, DistanceShort, ActModePressed,
|
||||
"niri msg action fullscreen-window"},
|
||||
{2, SwipeUD, EdgeRight, DistanceMedium, ActModeReleased,
|
||||
"niri msg action close-window"},
|
||||
{2, SwipeDU, EdgeBottom, DistanceAny, ActModeReleased,
|
||||
"pkill -34 -f wvkbd"},
|
||||
//{3, SwipeUD, EdgeTop, DistanceLong, ActModeReleased,
|
||||
// "systemctl --user restart desktop-shell.service"},
|
||||
{2, SwipeUD, EdgeTop, DistanceLong, ActModeReleased,
|
||||
"grim -g \"$(slurp -w 0)\" -t ppm - | satty --early-exit --copy-command 'wl-copy' --filename='-' -o '~/Pictures/Screenshots/Screenshot-%Y-%m-%d_%H:%M:%S.png' --initial-tool brush"},
|
||||
//{2, SwipeUD, EdgeBottom, DistanceAny, ActModeReleased,
|
||||
//"pkill -9 -f wvkbd-mobintl"},
|
||||
{3, SwipeDU, EdgeAny, DistanceAny, ActModeReleased,
|
||||
"niri msg action toggle-overview"},
|
||||
};
|
||||
118
packages/lisgd/lisgd.1
Normal file
118
packages/lisgd/lisgd.1
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
.TH LISGD 1
|
||||
|
||||
.SH NAME
|
||||
lisgd \- libinput synthetic gesture daemon
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B lisgd
|
||||
[\fB\-d\fR \fIdevicepath\fR]
|
||||
[\fB\-g\fR \fIgesturespec\fR]...
|
||||
[\fB\-t\fR \fIthreshold\fR]
|
||||
[\fB\-m\fR \fItimeoutms\fR]
|
||||
[\fB\-o\fR \fIorientation\fR]
|
||||
[\fB\-w\fR \fIwidth\fR]
|
||||
[\fB\-h\fR \fIheight\fR]
|
||||
[\fB\-r\fR \fIdegreesofleniency\fR]
|
||||
[\fB\-v]
|
||||
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B lisgd
|
||||
(or libinput synthetic gesture daemon) lets you bind gestures based on
|
||||
libinput touch events to run specific commands to execute. For example,
|
||||
dragging left to right with one finger could execute a particular command
|
||||
like launching a terminal. Directional L-R, R-L, U-D, and D-U gestures and
|
||||
diagnol LD-RU, RD-LU, UR-DL, UL-DR gestures are supported with 1 through
|
||||
n fingers and can be bound to the screen's edges and/or made sensitive to
|
||||
the distance of the gesture.
|
||||
|
||||
Unlike other libinput gesture daemons, lisgd uses touch events to
|
||||
recognize synthetic swipe gestures rather than using the libinput's
|
||||
gesture events. The advantage of this is that the synthetic gestures
|
||||
you define via lisgd can be used on touchscreens, which normal libinput
|
||||
gestures don't support.
|
||||
|
||||
This program was built for use on the Pinephone however it could be used in
|
||||
general for any device that supports touch events, like laptop touchscreens
|
||||
or similar. You may want to adjust the threshold depending on the device
|
||||
you're using.
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR \-d ", " \-d\ devicepath\fR
|
||||
Path of the dev filesystem device to monitor (like /dev/input/event1).
|
||||
|
||||
.TP
|
||||
.BR \-g ", " \-g\ nfingers,gesture,edge,distance,actmode,command\fR
|
||||
Allows you to bind a gesture wherein nfingers is an integer, gesture is
|
||||
one of {LR,RL,DU,UD,DLUR,DRUL,URDL,ULDR}, edge is one of * (any), N (none), L
|
||||
(left), R (right), T (top), B (bottom), TL (top left), TR (top right), BL
|
||||
(bottom left), BR (bottom right) and distance is one of * (any), S (short), M
|
||||
(medium), L (large), actmode is R (release) for normal mode and P (pressed) for
|
||||
pressed mode (but this field may be omitted entirely for backward
|
||||
compatibility), command is the shell command to be executed.
|
||||
|
||||
The -g option can be used multiple times to bind multiple gestures.
|
||||
|
||||
.TP
|
||||
.BR \-m ", " \-m\ timeoutms\fR
|
||||
Number of milliseconds gestures must be performed within to be registered. After
|
||||
the timeoutms value; the gesture won't be registered.
|
||||
|
||||
.TP
|
||||
.BR \-o ", " \-o\ orientation\fR
|
||||
Number of 90-degree rotations to translate gestures by. Can be set to 0-3. For
|
||||
example using 1; a L-R gesture would become a U-D gesture. Meant to be used
|
||||
for screen-rotation.
|
||||
|
||||
.TP
|
||||
.BR \-r ", " \-r\ degreesofleniency\fR
|
||||
Number of degrees offset each 45-degree interval may still be recognized within.
|
||||
Maximum value is 45. Default value is 15. E.g. U-D is a 180 degree gesture
|
||||
but with 15 degrees of leniency will be recognized between 165-195 degrees.
|
||||
|
||||
.TP
|
||||
.BR \-t ", " \-t\ distancethreshold\fR
|
||||
Threshold in libinput units (pixels) after which a gesture registers. Defaults
|
||||
to 125.
|
||||
|
||||
.TP
|
||||
.BR \-T ", " \-T\ distancethreshold_pressed\fR
|
||||
Threshold in libinput units (pixels) after which a gesture registers when fingers
|
||||
are not lifted. Defaults to 60.
|
||||
|
||||
.TP
|
||||
.BR \-w ", " \-w\ screnwidth\fR
|
||||
Allows you to specify the width of the screen area to be used for
|
||||
edge-based gestures. Should be used in conjunction with -h. If unset,
|
||||
and either the DISPLAY or WAYLAND_DISPLAY env var is set, X/Wayland
|
||||
dynamic screen geometry detection will be used instead.
|
||||
|
||||
.TP
|
||||
.BR \-h ", " \-h\ screenheight\fR
|
||||
Allows you to specify the height of the screen area to be used for
|
||||
edge-based gestures. Should be used in conjunction with -w. If unset,
|
||||
and either the DISPLAY or WAYLAND_DISPLAY env var is set, X/Wayland
|
||||
dynamic screen geometry detection will be used instead.
|
||||
|
||||
.TP
|
||||
.BR \-s ", " \-s\ edgessizecaling\fR
|
||||
Scale the edge sizes with this value. It is very usefull with very hidpi screens,
|
||||
to help detecting edge gestures.
|
||||
|
||||
.TP
|
||||
.BR \-v \fR
|
||||
Enables verbose mode which prints debugging messages.
|
||||
|
||||
|
||||
.SH SEE ALSO
|
||||
lisgd was built as part of Sxmo; an project to create a Pinephone UI out of
|
||||
simple and suckless programs. See: http://sr.ht/mil/Sxmo
|
||||
|
||||
.SH AUTHOR
|
||||
.BR lisgd
|
||||
is written by Miles Alan <m@milesalan.com>
|
||||
|
||||
.SH CONTRIBUTING
|
||||
Bugs and feature dicussions can be sent to ~mil/sxmo-devel@lists.sr.ht
|
||||
674
packages/lisgd/lisgd.c
Normal file
674
packages/lisgd/lisgd.c
Normal file
|
|
@ -0,0 +1,674 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libinput.h>
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#ifdef WITH_X11
|
||||
# include <X11/Xlib.h>
|
||||
#endif
|
||||
#ifdef WITH_WAYLAND
|
||||
# include <wayland-client.h>
|
||||
#endif
|
||||
|
||||
/* Defines */
|
||||
#define MAXSLOTS 20
|
||||
#define NOMOTION -999999
|
||||
|
||||
/* Types */
|
||||
enum {
|
||||
SwipeDU,
|
||||
SwipeUD,
|
||||
SwipeLR,
|
||||
SwipeRL,
|
||||
SwipeDLUR,
|
||||
SwipeDRUL,
|
||||
SwipeURDL,
|
||||
SwipeULDR
|
||||
};
|
||||
typedef int Swipe;
|
||||
|
||||
enum {
|
||||
EdgeAny,
|
||||
EdgeNone,
|
||||
EdgeLeft,
|
||||
EdgeRight,
|
||||
EdgeTop,
|
||||
EdgeBottom,
|
||||
CornerTopLeft,
|
||||
CornerTopRight,
|
||||
CornerBottomLeft,
|
||||
CornerBottomRight,
|
||||
};
|
||||
typedef int Edge;
|
||||
|
||||
enum {
|
||||
DistanceAny,
|
||||
DistanceShort,
|
||||
DistanceMedium,
|
||||
DistanceLong,
|
||||
};
|
||||
typedef int Distance;
|
||||
|
||||
enum {
|
||||
ActModeReleased, //action triggers when fingers are released
|
||||
ActModePressed, //action triggers while finger is not lifted yet (as soon as a swipe is completed)
|
||||
};
|
||||
typedef int ActMode;
|
||||
|
||||
typedef struct {
|
||||
int nfswipe;
|
||||
Swipe swipe;
|
||||
Edge edge;
|
||||
Distance distance;
|
||||
ActMode actmode;
|
||||
char *command;
|
||||
} Gesture;
|
||||
|
||||
/* Config */
|
||||
#include "config.h"
|
||||
|
||||
/* Globals */
|
||||
Gesture *gestsarr;
|
||||
int gestsarrlen;
|
||||
int have_actmode_pressed = 0; //do we have gestures using actmode pressed?
|
||||
Swipe pendingswipe;
|
||||
Edge pendingedge;
|
||||
Distance pendingdistance;
|
||||
double xstart[MAXSLOTS], xend[MAXSLOTS], ystart[MAXSLOTS], yend[MAXSLOTS];
|
||||
unsigned nfdown = 0, nfpendingswipe = 0;
|
||||
struct timespec timedown;
|
||||
static int screen;
|
||||
#ifdef WITH_WAYLAND
|
||||
struct wl_display *wl_display;
|
||||
struct wl_registry *wl_registry;
|
||||
struct wl_output *wl_output;
|
||||
#endif
|
||||
static int screenwidth = 0, screenheight = 0;
|
||||
|
||||
void
|
||||
die(char * msg)
|
||||
{
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
gesturecalculateswipewithindegrees(double gestdegrees, double wantdegrees) {
|
||||
return (
|
||||
gestdegrees >= wantdegrees - degreesleniency &&
|
||||
gestdegrees <= wantdegrees + degreesleniency
|
||||
);
|
||||
}
|
||||
|
||||
Swipe
|
||||
gesturecalculateswipe(double x0, double y0, double x1, double y1, int mindistance) {
|
||||
double t, degrees, dist;
|
||||
|
||||
t = atan2(x1 - x0, y0 - y1);
|
||||
degrees = 57.2957795130823209 * (t < 0 ? t + 6.2831853071795865 : t);
|
||||
dist = sqrt(pow(x1 - x0, 2) + pow(y1 - y0, 2));
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "Swipe distance=[%.2f]; degrees=[%.2f]\n", dist, degrees);
|
||||
|
||||
if (dist < mindistance) return -1;
|
||||
else if (gesturecalculateswipewithindegrees(degrees, 0)) return SwipeDU;
|
||||
else if (gesturecalculateswipewithindegrees(degrees, 45)) return SwipeDLUR;
|
||||
else if (gesturecalculateswipewithindegrees(degrees, 90)) return SwipeLR;
|
||||
else if (gesturecalculateswipewithindegrees(degrees, 135)) return SwipeULDR;
|
||||
else if (gesturecalculateswipewithindegrees(degrees, 180)) return SwipeUD;
|
||||
else if (gesturecalculateswipewithindegrees(degrees, 225)) return SwipeURDL;
|
||||
else if (gesturecalculateswipewithindegrees(degrees, 270)) return SwipeRL;
|
||||
else if (gesturecalculateswipewithindegrees(degrees, 315)) return SwipeDRUL;
|
||||
else if (gesturecalculateswipewithindegrees(degrees, 360)) return SwipeDU;
|
||||
|
||||
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 DistanceLong;
|
||||
} else if (dist >= screenheight * 0.33) {
|
||||
return DistanceMedium;
|
||||
} else {
|
||||
return DistanceShort;
|
||||
}
|
||||
break;
|
||||
case SwipeLR:
|
||||
case SwipeRL:
|
||||
if (dist >= screenwidth * 0.66) {
|
||||
return DistanceLong;
|
||||
} else if (dist >= screenwidth * 0.33) {
|
||||
return DistanceMedium;
|
||||
} else {
|
||||
return DistanceShort;
|
||||
}
|
||||
break;
|
||||
case SwipeULDR:
|
||||
case SwipeDRUL:
|
||||
case SwipeDLUR:
|
||||
case SwipeURDL:
|
||||
if (dist >= diag * 0.66) {
|
||||
return DistanceLong;
|
||||
} else if (dist >= diag * 0.33) {
|
||||
return DistanceMedium;
|
||||
} else {
|
||||
return DistanceShort;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0; //shouldn't happen
|
||||
}
|
||||
|
||||
Edge
|
||||
gesturecalculateedge(double x0, double y0, double x1, double y1) {
|
||||
Edge horizontal = EdgeNone;
|
||||
Edge vertical = EdgeNone;
|
||||
if (x0 <= edgesizeleft * edgessizecaling) {
|
||||
horizontal = EdgeLeft;
|
||||
} else if (x0 >= screenwidth - edgesizeright * edgessizecaling) {
|
||||
horizontal = EdgeRight;
|
||||
} else if (x1 <= edgesizeleft * edgessizecaling) {
|
||||
horizontal = EdgeLeft;
|
||||
} else if (x1 >= screenwidth - edgesizeright * edgessizecaling) {
|
||||
horizontal = EdgeRight;
|
||||
}
|
||||
if (y0 <= edgesizetop * edgessizecaling) {
|
||||
vertical = EdgeTop;
|
||||
} else if (y0 >= screenheight - edgesizebottom * edgessizecaling) {
|
||||
vertical = EdgeBottom;
|
||||
} else if (y1 <= edgesizetop * edgessizecaling) {
|
||||
vertical = EdgeTop;
|
||||
} else if (y1 >= screenheight - edgesizebottom * edgessizecaling) {
|
||||
vertical = EdgeBottom;
|
||||
}
|
||||
if (horizontal == EdgeLeft && vertical == EdgeTop) {
|
||||
return CornerTopLeft;
|
||||
} else if (horizontal == EdgeRight && vertical == EdgeTop) {
|
||||
return CornerTopRight;
|
||||
} else if (horizontal == EdgeLeft && vertical == EdgeBottom) {
|
||||
return CornerBottomLeft;
|
||||
} else if (horizontal == EdgeRight && vertical == EdgeBottom) {
|
||||
return CornerBottomRight;
|
||||
} else if (horizontal != EdgeNone) {
|
||||
return horizontal;
|
||||
} else {
|
||||
return vertical;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
gestureexecute(Swipe swipe, int nfingers, Edge edge, Distance distance, ActMode actmode) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < gestsarrlen; i++) {
|
||||
if (verbose) {
|
||||
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
|
||||
&& gestsarr[i].distance <= distance
|
||||
&& (gestsarr[i].edge == EdgeAny || gestsarr[i].edge == edge ||
|
||||
((edge == CornerTopLeft || edge == CornerTopRight) && gestsarr[i].edge == EdgeTop) ||
|
||||
((edge == CornerBottomLeft || edge == CornerBottomRight) && gestsarr[i].edge == EdgeBottom) ||
|
||||
((edge == CornerTopLeft || edge == CornerBottomLeft) && gestsarr[i].edge == EdgeLeft) ||
|
||||
((edge == CornerTopRight || edge == CornerBottomRight) && gestsarr[i].edge == EdgeRight)
|
||||
)
|
||||
&& (actmode == ActModeReleased || gestsarr[i].actmode == actmode)
|
||||
) {
|
||||
if (verbose) fprintf(stderr, "Execute %s\n", gestsarr[i].command);
|
||||
system(gestsarr[i].command);
|
||||
return 1; //execute first match only
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
Swipe
|
||||
swipereorient(Swipe swipe, int orientation) {
|
||||
while (orientation > 0) {
|
||||
switch(swipe) {
|
||||
// 90deg per turn so: L->U, R->D, U->R, D->L
|
||||
case SwipeDU: swipe = SwipeLR; break;
|
||||
case SwipeDLUR: swipe = SwipeULDR; break;
|
||||
case SwipeLR: swipe = SwipeUD; break;
|
||||
case SwipeULDR: swipe = SwipeURDL; break;
|
||||
case SwipeUD: swipe = SwipeRL; break;
|
||||
case SwipeURDL: swipe = SwipeDRUL; break;
|
||||
case SwipeRL: swipe = SwipeDU; break;
|
||||
case SwipeDRUL: swipe = SwipeDLUR; break;
|
||||
}
|
||||
orientation--;
|
||||
}
|
||||
return swipe;
|
||||
}
|
||||
|
||||
Edge
|
||||
edgereorient(Edge edge, int orientation) {
|
||||
while (orientation > 0) {
|
||||
switch(edge) {
|
||||
// 90deg per turn
|
||||
case EdgeLeft: edge = EdgeTop; break;
|
||||
case EdgeRight: edge = EdgeBottom; break;
|
||||
case EdgeTop: edge = EdgeRight; break;
|
||||
case EdgeBottom: edge = EdgeLeft; break;
|
||||
case CornerTopLeft: edge = CornerTopRight; break;
|
||||
case CornerTopRight: edge = CornerBottomRight; break;
|
||||
case CornerBottomLeft: edge = CornerTopLeft; break;
|
||||
case CornerBottomRight: edge = CornerBottomLeft; break;
|
||||
}
|
||||
orientation--;
|
||||
}
|
||||
return edge;
|
||||
}
|
||||
|
||||
void
|
||||
touchdown(struct libinput_event *e)
|
||||
{
|
||||
struct libinput_event_touch *tevent;
|
||||
int slot;
|
||||
|
||||
tevent = libinput_event_get_touch_event(e);
|
||||
slot = libinput_event_touch_get_slot(tevent);
|
||||
xstart[slot] = libinput_event_touch_get_x_transformed(tevent, screenwidth);
|
||||
ystart[slot] = libinput_event_touch_get_y_transformed(tevent, screenheight);
|
||||
if (nfdown == 0) clock_gettime(CLOCK_MONOTONIC_RAW, &timedown);
|
||||
nfdown++;
|
||||
}
|
||||
|
||||
void
|
||||
resetslot(int slot) {
|
||||
xend[slot] = NOMOTION;
|
||||
yend[slot] = NOMOTION;
|
||||
xstart[slot] = NOMOTION;
|
||||
ystart[slot] = NOMOTION;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
touchmotion(struct libinput_event *e)
|
||||
{
|
||||
struct libinput_event_touch *tevent;
|
||||
struct timespec now;
|
||||
int slot;
|
||||
|
||||
tevent = libinput_event_get_touch_event(e);
|
||||
slot = libinput_event_touch_get_slot(tevent);
|
||||
xend[slot] = libinput_event_touch_get_x_transformed(tevent, screenwidth);
|
||||
yend[slot] = libinput_event_touch_get_y_transformed(tevent, screenheight);
|
||||
|
||||
if (have_actmode_pressed) {
|
||||
Swipe swipe = gesturecalculateswipe(
|
||||
xstart[slot], ystart[slot], xend[slot], yend[slot], distancethreshold_pressed
|
||||
);
|
||||
if (swipe != -1) {
|
||||
Edge edge = gesturecalculateedge(
|
||||
xstart[slot], ystart[slot], xend[slot], yend[slot]
|
||||
);
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &now);
|
||||
if (
|
||||
timeoutms >
|
||||
((now.tv_sec - timedown.tv_sec) * 1000000 + (now.tv_nsec - timedown.tv_nsec) / 1000) / 1000
|
||||
) {
|
||||
if (verbose) fprintf(stderr, "(Attempting to find matching pressed gesture)\n");
|
||||
if (gestureexecute(swipe, nfdown, edge, DistanceAny, ActModePressed)) {
|
||||
//we found and executed a matching gesture, reset the slot
|
||||
if (verbose) fprintf(stderr, "(Pressed gestured Executed)\n");
|
||||
xstart[slot] = xend[slot];
|
||||
ystart[slot] = yend[slot];
|
||||
timedown = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
touchup(struct libinput_event *e)
|
||||
{
|
||||
int slot;
|
||||
struct libinput_event_touch *tevent;
|
||||
struct timespec now;
|
||||
|
||||
tevent = libinput_event_get_touch_event(e);
|
||||
slot = libinput_event_touch_get_slot(tevent);
|
||||
nfdown--;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &now);
|
||||
|
||||
// E.g. invalid motion, it didn't begin/end from anywhere
|
||||
if (
|
||||
xstart[slot] == NOMOTION || ystart[slot] == NOMOTION ||
|
||||
xend[slot] == NOMOTION || yend[slot] == NOMOTION
|
||||
) return;
|
||||
|
||||
Swipe swipe = gesturecalculateswipe(
|
||||
xstart[slot], ystart[slot], xend[slot], yend[slot], distancethreshold
|
||||
);
|
||||
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 millisecond limit, exec, & reset
|
||||
if (nfdown == 0) {
|
||||
if (
|
||||
timeoutms >
|
||||
((now.tv_sec - timedown.tv_sec) * 1000000 + (now.tv_nsec - timedown.tv_nsec) / 1000) / 1000
|
||||
) gestureexecute(swipe, nfpendingswipe, edge, distance, ActModeReleased);
|
||||
|
||||
nfpendingswipe = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run(void)
|
||||
{
|
||||
int i;
|
||||
struct libinput *li;
|
||||
struct libinput_event *event;
|
||||
struct libinput_device *d;
|
||||
int selectresult;
|
||||
fd_set fdset;
|
||||
|
||||
const static struct libinput_interface interface = {
|
||||
.open_restricted = libinputopenrestricted,
|
||||
.close_restricted = libinputcloserestricted,
|
||||
};
|
||||
|
||||
if ((li = libinput_path_create_context(&interface, NULL)) == NULL)
|
||||
die("Failed to initialize context");
|
||||
|
||||
if ((d = libinput_path_add_device(li, device)) == NULL) {
|
||||
die("Couldn't bind event from dev filesystem");
|
||||
} else if (LIBINPUT_CONFIG_STATUS_SUCCESS != libinput_device_config_send_events_set_mode(
|
||||
d, LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
|
||||
)) {
|
||||
die("Couldn't set mode to capture events");
|
||||
}
|
||||
|
||||
// E.g. initially invalidate every slot
|
||||
for (i = 0; i < MAXSLOTS; i++) {
|
||||
xend[i] = NOMOTION;
|
||||
yend[i] = NOMOTION;
|
||||
xstart[i] = NOMOTION;
|
||||
ystart[i] = NOMOTION;
|
||||
}
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(libinput_get_fd(li), &fdset);
|
||||
for (;;) {
|
||||
selectresult = select(FD_SETSIZE, &fdset, NULL, NULL, NULL);
|
||||
if (selectresult == -1) {
|
||||
die("Can't select on device node?");
|
||||
} else {
|
||||
libinput_dispatch(li);
|
||||
while ((event = libinput_get_event(li)) != NULL) {
|
||||
switch(libinput_event_get_type(event)) {
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN: touchdown(event); break;
|
||||
case LIBINPUT_EVENT_TOUCH_UP: touchup(event); break;
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION: touchmotion(event); break;
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
libinput_unref(li);
|
||||
}
|
||||
|
||||
#ifdef WITH_WAYLAND
|
||||
static void
|
||||
display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, int physical_width, int physical_height, int subpixel, const char *make, const char *model, int transform)
|
||||
{
|
||||
orientation = transform;
|
||||
if (orientation == 1) {
|
||||
orientation = 3;
|
||||
} else if (orientation == 3) {
|
||||
orientation = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_handle_done(void *data, struct wl_output *wl_output)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
display_handle_scale(void *data, struct wl_output *wl_output, int32_t scale)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
display_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, int width, int height, int refresh)
|
||||
{
|
||||
screenwidth = width;
|
||||
screenheight = height;
|
||||
}
|
||||
|
||||
static const struct wl_output_listener output_listener = {
|
||||
.geometry = display_handle_geometry,
|
||||
.mode = display_handle_mode,
|
||||
.done = display_handle_done,
|
||||
.scale = display_handle_scale
|
||||
};
|
||||
|
||||
static void
|
||||
registry_global(void *data, struct wl_registry *wl_registry,
|
||||
uint32_t name, const char *interface, uint32_t version)
|
||||
{
|
||||
if (strcmp(interface, "wl_output") == 0) {
|
||||
if (!wl_output) {
|
||||
wl_output = wl_registry_bind(wl_registry, name, &wl_output_interface, 3);
|
||||
wl_output_add_listener(wl_output, &output_listener, NULL);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static void
|
||||
registry_global_remove(void *data,
|
||||
struct wl_registry *wl_registry, uint32_t name)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct
|
||||
wl_registry_listener wl_registry_listener = {
|
||||
.global = registry_global,
|
||||
.global_remove = registry_global_remove,
|
||||
};
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, j;
|
||||
char *gestpt;
|
||||
|
||||
gestsarr = NULL;
|
||||
gestsarrlen = 0;
|
||||
|
||||
prctl(PR_SET_PDEATHSIG, SIGTERM);
|
||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-v")) {
|
||||
verbose = 1;
|
||||
} else if (!strcmp(argv[i], "-d")) {
|
||||
if (i == argc - 1) die("option -d expects a value");
|
||||
device = argv[++i];
|
||||
} else if (!strcmp(argv[i], "-t")) {
|
||||
if (i == argc - 1) die("option -t expects a value");
|
||||
distancethreshold = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-T")) {
|
||||
if (i == argc - 1) die("option -T expects a value");
|
||||
distancethreshold_pressed = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-r")) {
|
||||
if (i == argc - 1) die("option -r expects a value");
|
||||
degreesleniency = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-m")) {
|
||||
if (i == argc - 1) die("option -m expects a value");
|
||||
timeoutms = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-o")) {
|
||||
if (i == argc - 1) die("option -o expects a value");
|
||||
orientation = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-h")) {
|
||||
if (i == argc - 1) die("option -h expects a value");
|
||||
screenheight = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-w")) {
|
||||
if (i == argc - 1) die("option -w expects a value");
|
||||
screenwidth = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-s")) {
|
||||
if (i == argc - 1) die("option -s expects a value");
|
||||
edgessizecaling = atof(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-g")) {
|
||||
if (i == argc - 1) die("option -g expects a value");
|
||||
gestsarrlen++;
|
||||
gestsarr = realloc(gestsarr, (gestsarrlen * sizeof(Gesture)));
|
||||
if (gestsarr == NULL) {
|
||||
perror("Could not allocate memory");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
gestpt = strtok(argv[++i], ",");
|
||||
for (j = 0; gestpt != NULL && j < 6; gestpt = strtok(NULL, ","), j++) {
|
||||
switch(j) {
|
||||
case 0: gestsarr[gestsarrlen - 1].nfswipe = atoi(gestpt); break;
|
||||
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;
|
||||
if (!strcmp(gestpt, "UD")) gestsarr[gestsarrlen-1].swipe = SwipeUD;
|
||||
if (!strcmp(gestpt, "DLUR")) gestsarr[gestsarrlen-1].swipe = SwipeDLUR;
|
||||
if (!strcmp(gestpt, "URDL")) gestsarr[gestsarrlen-1].swipe = SwipeURDL;
|
||||
if (!strcmp(gestpt, "ULDR")) gestsarr[gestsarrlen-1].swipe = SwipeULDR;
|
||||
if (!strcmp(gestpt, "DRUL")) gestsarr[gestsarrlen-1].swipe = SwipeDRUL;
|
||||
break;
|
||||
case 2:
|
||||
if (!strcmp(gestpt, "L")) gestsarr[gestsarrlen-1].edge = EdgeLeft;
|
||||
if (!strcmp(gestpt, "R")) gestsarr[gestsarrlen-1].edge = EdgeRight;
|
||||
if (!strcmp(gestpt, "T")) gestsarr[gestsarrlen-1].edge = EdgeTop;
|
||||
if (!strcmp(gestpt, "B")) gestsarr[gestsarrlen-1].edge = EdgeBottom;
|
||||
if (!strcmp(gestpt, "TL")) gestsarr[gestsarrlen-1].edge = CornerTopLeft;
|
||||
if (!strcmp(gestpt, "TR")) gestsarr[gestsarrlen-1].edge = CornerTopRight;
|
||||
if (!strcmp(gestpt, "BL")) gestsarr[gestsarrlen-1].edge = CornerBottomLeft;
|
||||
if (!strcmp(gestpt, "BR")) gestsarr[gestsarrlen-1].edge = CornerBottomRight;
|
||||
if (!strcmp(gestpt, "N")) gestsarr[gestsarrlen-1].edge = EdgeNone;
|
||||
if (!strcmp(gestpt, "*")) gestsarr[gestsarrlen-1].edge = EdgeAny;
|
||||
break;
|
||||
case 3:
|
||||
if (!strcmp(gestpt, "L")) gestsarr[gestsarrlen-1].distance = DistanceLong;
|
||||
if (!strcmp(gestpt, "M")) gestsarr[gestsarrlen-1].distance = DistanceMedium;
|
||||
if (!strcmp(gestpt, "S")) gestsarr[gestsarrlen-1].distance = DistanceShort;
|
||||
if (!strcmp(gestpt, "*")) gestsarr[gestsarrlen-1].distance = DistanceAny;
|
||||
break;
|
||||
case 4:
|
||||
if (!strcmp(gestpt, "P")) {
|
||||
gestsarr[gestsarrlen-1].actmode = ActModePressed;
|
||||
} else {
|
||||
gestsarr[gestsarrlen-1].actmode = ActModeReleased;
|
||||
if (strcmp(gestpt, "R") != 0) {
|
||||
//for backward compatibility, allow fourth field to hold command
|
||||
gestsarr[gestsarrlen - 1].command = gestpt;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5: 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,L,*,R,notify-send swiped left to right from left edge']\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Get display size (if not set with -w/-h)
|
||||
if (screenwidth == 0 && screenheight == 0) {
|
||||
if (getenv("WAYLAND_DISPLAY")) {
|
||||
#ifdef WITH_WAYLAND
|
||||
wl_display = wl_display_connect(NULL);
|
||||
wl_registry = wl_display_get_registry(wl_display);
|
||||
wl_registry_add_listener(wl_registry, &wl_registry_listener, NULL);
|
||||
wl_display_roundtrip(wl_display);
|
||||
wl_display_dispatch(wl_display);
|
||||
#else
|
||||
die("Wayland environment detected but support for it is not enabled");
|
||||
#endif
|
||||
} else if (getenv("DISPLAY")) {
|
||||
#ifdef WITH_X11
|
||||
Display *dpy;
|
||||
if (!(dpy = XOpenDisplay(0))) {
|
||||
die("Cannot open X display");
|
||||
}
|
||||
screen = DefaultScreen(dpy);
|
||||
if (0 == orientation % 2) {
|
||||
screenwidth = DisplayWidth(dpy, screen);
|
||||
screenheight = DisplayHeight(dpy, screen);
|
||||
} else {
|
||||
screenwidth = DisplayHeight(dpy, screen);
|
||||
screenheight = DisplayWidth(dpy, screen);
|
||||
}
|
||||
#else
|
||||
die("X11 environment detected but support for it is not enabled");
|
||||
#endif
|
||||
} else {
|
||||
die("Cannot detect display environment ($DISPLAY and $WAYLAND_DISPLAY unset); and no -w / -h screen geometry parameter options set");
|
||||
}
|
||||
}
|
||||
|
||||
// E.g. no gestures passed on CLI - used gestures defined in config.def.h
|
||||
if (gestsarrlen == 0) {
|
||||
gestsarr = malloc(sizeof(gestures));
|
||||
if (gestsarr == NULL) {
|
||||
perror("Could not allocate memory");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
gestsarrlen = sizeof(gestures) / sizeof(Gesture);
|
||||
memcpy(gestsarr, gestures, sizeof(gestures));
|
||||
}
|
||||
|
||||
// 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);
|
||||
//Detect whether ActMode pressed is used
|
||||
if (gestsarr[i].actmode == ActModePressed) have_actmode_pressed++;
|
||||
}
|
||||
|
||||
run();
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue