diff --git a/README.md b/README.md index b218f3e..28644e8 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,15 @@ This is a standard autoconf package. So: make && make install It is likely that you will need to change system-dependent paths such as the -xorg module directory. See `configure --help` for options. +xorg module directory. Otherwise mtrack may be not installed in xserver search +path. +See `configure --help` for options. + +To build deb package and install in system wide you will usually have to change +installation prefix to /usr like so: + + ./configure --prefix=/usr + dpkg-buildpackage Configuration ------------- @@ -153,10 +161,13 @@ disables three-finger tapping. Defaults to 0. **ClickTime** - When tapping, how much time to hold down the emulated button. Integer value -representing milliseconds. Defaults to 50. +representing milliseconds. Not very usable because button release event will be +sent immediately after releasing any of fingers (touches). +Integer value representing miliseconds. Defaults to 50. **MaxTapTime** - -The amount of time to wait for a tap to release before counting it as a move. +The amount of time to wait for incoming touches after first one before counting +it as emulated button click. Integer value representing milliseconds. Defaults to 120. **MaxTapMove** - @@ -194,6 +205,10 @@ Integer value. A value of 0 disables scrolling left. Defaults to 6. For two finger scrolling. The button that is triggered by scrolling right. Integer value. A value of 0 disables scrolling right. Defaults to 7. +**ScrollClickTime** - +For two finger scrolling. How long button triggered by scrolling +will be hold down. Integer value representing milliseconds. Defaults to 20. + **SwipeDistance** - For three finger swiping. How far you must move your fingers before a button click is triggered. Integer value. Defaults to 700. @@ -214,6 +229,10 @@ value. A value of 0 disables swiping left. Defaults to 10. For three finger swiping. The button that is triggered by swiping right. Integer value. A value of 0 disables swiping right. Defaults to 11. +**SwipeClickTime** - +For three finger swiping. How long button triggered by swiping +will be hold down. Integer value representing milliseconds. Defaults to 300. + **Swipe4Distance** - For four finger swiping. How far you must move your fingers before a button click is triggered. Integer value. Defaults to 700. @@ -234,6 +253,10 @@ value. A value of 0 disables swiping left. Defaults to 10. For four finger swiping. The button that is triggered by swiping right. Integer value. A value of 0 disables swiping right. Defaults to 11. +**Swipe4ClickTime** - +For four finger swiping. How long button triggered by swiping +will be hold down. Integer value representing milliseconds. Defaults to 300. + **ScaleDistance** - For pinch scaling. How far you must move your fingers before a button click is triggered. Integer value. Defaults to 150. diff --git a/driver/mprops.c b/driver/mprops.c index 3ded861..6e2b414 100644 --- a/driver/mprops.c +++ b/driver/mprops.c @@ -75,6 +75,21 @@ Atom atom_init_float(DeviceIntPtr dev, char* name, int nvalues, float* values, A return atom; } +static void init_swipe_props(DeviceIntPtr dev, struct MPropsSwipe* props_swipe, + struct MConfigSwipe* cfg_swipe, char const* settings_prop_name, + char const* buttons_prop_name){ + int ivals[MAX_INT_VALUES]; + ivals[0] = cfg_swipe->dist; + ivals[1] = cfg_swipe->hold; + props_swipe->settings = atom_init_integer(dev, (char*)settings_prop_name, 2, ivals, 32); + + ivals[0] = cfg_swipe->up_btn; + ivals[1] = cfg_swipe->dn_btn; + ivals[2] = cfg_swipe->lt_btn; + ivals[3] = cfg_swipe->rt_btn; + props_swipe->buttons = atom_init_integer(dev, (char*)buttons_prop_name, 4, ivals, 8); +} + void mprops_init(struct MConfig* cfg, InputInfoPtr local) { int ivals[MAX_INT_VALUES]; float fvals[MAX_FLOAT_VALUES]; @@ -142,32 +157,11 @@ void mprops_init(struct MConfig* cfg, InputInfoPtr local) { ivals[1] = cfg->gesture_wait; mprops.gesture_settings = atom_init_integer(local->dev, MTRACK_PROP_GESTURE_SETTINGS, 2, ivals, 16); - ivals[0] = cfg->scroll_dist; - mprops.scroll_dist = atom_init_integer(local->dev, MTRACK_PROP_SCROLL_DIST, 1, ivals, 32); - - ivals[0] = cfg->scroll_up_btn; - ivals[1] = cfg->scroll_dn_btn; - ivals[2] = cfg->scroll_lt_btn; - ivals[3] = cfg->scroll_rt_btn; - mprops.scroll_buttons = atom_init_integer(local->dev, MTRACK_PROP_SCROLL_BUTTONS, 4, ivals, 8); + init_swipe_props(local->dev, &mprops.scroll, &cfg->scroll, MTRACK_PROP_SCROLL_SETTINGS, MTRACK_PROP_SCROLL_BUTTONS); - ivals[0] = cfg->swipe_dist; - mprops.swipe_dist = atom_init_integer(local->dev, MTRACK_PROP_SWIPE_DIST, 1, ivals, 32); + init_swipe_props(local->dev, &mprops.swipe3, &cfg->swipe3, MTRACK_PROP_SWIPE_SETTINGS, MTRACK_PROP_SWIPE_BUTTONS); - ivals[0] = cfg->swipe_up_btn; - ivals[1] = cfg->swipe_dn_btn; - ivals[2] = cfg->swipe_lt_btn; - ivals[3] = cfg->swipe_rt_btn; - mprops.swipe_buttons = atom_init_integer(local->dev, MTRACK_PROP_SWIPE_BUTTONS, 4, ivals, 8); - - ivals[0] = cfg->swipe4_dist; - mprops.swipe4_dist = atom_init_integer(local->dev, MTRACK_PROP_SWIPE4_DIST, 1, ivals, 32); - - ivals[0] = cfg->swipe4_up_btn; - ivals[1] = cfg->swipe4_dn_btn; - ivals[2] = cfg->swipe4_lt_btn; - ivals[3] = cfg->swipe4_rt_btn; - mprops.swipe4_buttons = atom_init_integer(local->dev, MTRACK_PROP_SWIPE4_BUTTONS, 4, ivals, 8); + init_swipe_props(local->dev, &mprops.swipe4, &cfg->swipe4, MTRACK_PROP_SWIPE4_SETTINGS, MTRACK_PROP_SWIPE4_BUTTONS); ivals[0] = cfg->scale_dist; mprops.scale_dist = atom_init_integer(local->dev, MTRACK_PROP_SCALE_DIST, 1, ivals, 32); @@ -194,6 +188,62 @@ void mprops_init(struct MConfig* cfg, InputInfoPtr local) { mprops.axis_invert = atom_init_integer(local->dev, MTRACK_PROP_AXIS_INVERT, 2, ivals, 8); } +/* Return: + * 1 - property was recognized and handled with or without error, check error code for details + * 0 - property not recognized, don't trust returned error code - it's invalid + */ +static int set_swipe_properties(Atom property, BOOL checkonly, XIPropertyValuePtr prop, + struct MPropsSwipe* props_swipe, + struct MConfigSwipe* cfg_swipe, int* error_code){ + + uint8_t* ivals8; + uint16_t* ivals16; + uint32_t* ivals32; + + *error_code = Success; + + if (property == props_swipe->settings) { + if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER) + return *error_code = BadMatch, 1; + + ivals32 = (uint32_t*)prop->data; + if (ivals32[0] < 1) + return *error_code = BadMatch, 1; + + if (!checkonly) { + cfg_swipe->dist = ivals32[0]; + cfg_swipe->hold = ivals32[1]; +#ifdef DEBUG_PROPS + xf86Msg(X_INFO, "mtrack: set swipe settings: dist: %d hold: %d\n", + cfg_swipe->dist, cfg_swipe->hold); +#endif + } + } + else if (property == props_swipe->buttons) { + if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER) + return *error_code = BadMatch, 1; + + ivals8 = (uint8_t*)prop->data; + if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3])) + return *error_code = BadMatch, 1; + + if (!checkonly) { + cfg_swipe->up_btn = ivals8[0]; + cfg_swipe->dn_btn = ivals8[1]; + cfg_swipe->lt_btn = ivals8[2]; + cfg_swipe->rt_btn = ivals8[3]; +#ifdef DEBUG_PROPS + xf86Msg(X_INFO, "mtrack: set swipe buttons to %d %d %d %d\n", + cfg_swipe->up_btn, cfg_swipe->dn_btn, cfg_swipe->lt_btn, cfg_swipe->rt_btn); +#endif + } + } + else{ + return 0; + } + return 1; +} + int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, BOOL checkonly) { InputInfoPtr local = dev->public.devicePrivate; struct MConfig* cfg = &((struct MTouch*)local->private)->cfg; @@ -203,6 +253,8 @@ int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop uint32_t* ivals32; float* fvals; + int error_code; + if (property == mprops.trackpad_disable) { if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER) return BadMatch; @@ -237,7 +289,7 @@ int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop } } else if (property == mprops.pressure) { - if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER) + if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER) return BadMatch; ivals8 = (uint8_t*)prop->data; @@ -254,7 +306,7 @@ int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop } } else if (property == mprops.button_settings) { - if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER) + if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER) return BadMatch; ivals8 = (uint8_t*)prop->data; @@ -332,7 +384,7 @@ int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3])) return BadMatch; - if (!checkonly) { + if (!checkonly) { cfg->tap_1touch = ivals8[0]; cfg->tap_2touch = ivals8[1]; cfg->tap_3touch = ivals8[2]; @@ -427,110 +479,14 @@ int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop #endif } } - else if (property == mprops.scroll_dist) { - if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER) - return BadMatch; - - ivals32 = (uint32_t*)prop->data; - if (ivals32[0] < 1) - return BadMatch; - - if (!checkonly) { - cfg->scroll_dist = ivals32[0]; -#ifdef DEBUG_PROPS - xf86Msg(X_INFO, "mtrack: set scroll distance to %d\n", - cfg->scroll_dist); -#endif - } - } - else if (property == mprops.scroll_buttons) { - if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER) - return BadMatch; - - ivals8 = (uint8_t*)prop->data; - if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3])) - return BadMatch; - - if (!checkonly) { - cfg->scroll_up_btn = ivals8[0]; - cfg->scroll_dn_btn = ivals8[1]; - cfg->scroll_lt_btn = ivals8[2]; - cfg->scroll_rt_btn = ivals8[3]; -#ifdef DEBUG_PROPS - xf86Msg(X_INFO, "mtrack: set scroll buttons to %d %d %d %d\n", - cfg->scroll_up_btn, cfg->scroll_dn_btn, cfg->scroll_lt_btn, cfg->scroll_rt_btn); -#endif - } - } - else if (property == mprops.swipe_dist) { - if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER) - return BadMatch; - - ivals32 = (uint32_t*)prop->data; - if (ivals32[0] < 1) - return BadMatch; - - if (!checkonly) { - cfg->swipe_dist = ivals32[0]; -#ifdef DEBUG_PROPS - xf86Msg(X_INFO, "mtrack: set swipe distance to %d\n", - cfg->swipe_dist); -#endif - } + else if (set_swipe_properties(property, checkonly, prop, &mprops.scroll, &cfg->scroll, &error_code)) { + return error_code; } - else if (property == mprops.swipe_buttons) { - if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER) - return BadMatch; - - ivals8 = (uint8_t*)prop->data; - if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3])) - return BadMatch; - - if (!checkonly) { - cfg->swipe_up_btn = ivals8[0]; - cfg->swipe_dn_btn = ivals8[1]; - cfg->swipe_lt_btn = ivals8[2]; - cfg->swipe_rt_btn = ivals8[3]; -#ifdef DEBUG_PROPS - xf86Msg(X_INFO, "mtrack: set swipe buttons to %d %d %d %d\n", - cfg->swipe_up_btn, cfg->swipe_dn_btn, cfg->swipe_lt_btn, cfg->swipe_rt_btn); -#endif - } + else if (set_swipe_properties(property, checkonly, prop, &mprops.swipe3, &cfg->swipe3, &error_code)) { + return error_code; } - else if (property == mprops.swipe4_dist) { - if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER) - return BadMatch; - - ivals32 = (uint32_t*)prop->data; - if (ivals32[0] < 1) - return BadMatch; - - if (!checkonly) { - cfg->swipe4_dist = ivals32[0]; -#ifdef DEBUG_PROPS - xf86Msg(X_INFO, "mtrack: set swipe4 distance to %d\n", - cfg->swipe4_dist); -#endif - } - } - else if (property == mprops.swipe4_buttons) { - if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER) - return BadMatch; - - ivals8 = (uint8_t*)prop->data; - if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3])) - return BadMatch; - - if (!checkonly) { - cfg->swipe4_up_btn = ivals8[0]; - cfg->swipe4_dn_btn = ivals8[1]; - cfg->swipe4_lt_btn = ivals8[2]; - cfg->swipe4_rt_btn = ivals8[3]; -#ifdef DEBUG_PROPS - xf86Msg(X_INFO, "mtrack: set swipe4 buttons to %d %d %d %d\n", - cfg->swipe4_up_btn, cfg->swipe4_dn_btn, cfg->swipe4_lt_btn, cfg->swipe4_rt_btn); -#endif - } + else if (set_swipe_properties(property, checkonly, prop, &mprops.swipe4, &cfg->swipe4, &error_code)) { + return error_code; } else if (property == mprops.scale_dist) { if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER) diff --git a/driver/mtrack.c b/driver/mtrack.c index 6bf1821..d13aeba 100644 --- a/driver/mtrack.c +++ b/driver/mtrack.c @@ -22,6 +22,7 @@ #include "mtouch.h" #include "mprops.h" +#include "os.h" /* xorg/os.h for timers */ #include #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 @@ -156,6 +157,8 @@ static int device_init(DeviceIntPtr dev, LocalDevicePtr local) mprops_init(&mt->cfg, local); XIRegisterPropertyHandler(dev, mprops_set_property, NULL, NULL); + TimerInit(); + mt->timer = NULL; /* allocated later in device_on */ return Success; } @@ -218,14 +221,56 @@ static void handle_gestures(LocalDevicePtr local, xf86PostMotionEvent(local->dev, 0, 0, 2, gs->move_dx, gs->move_dy); } -/* called for each full received packet from the touchpad */ +/* + * Timers documentation: + * http://www.x.org/releases/X11R7.7/doc/xorg-server/Xserver-spec.html#id2536042 + * + * This function indirectly may call itself recursively using timer to guarantee correct + * event delivery time. Ususally recursion ends after first recursive call. + */ +static CARD32 check_resolve_delayed(OsTimerPtr timer, CARD32 time, void *arg){ + LocalDevicePtr local = arg; + struct MTouch *mt = local->private; + // If it was to early to trigger delayed button, next timer will be set, + // but when called by timer such situation shouldn't take place. + switch (mtouch_delayed(mt)){ + case 1: + mt->timer = TimerSet(mt->timer, 0, timertoms(&mt->gs.button_delayed_delta), + check_resolve_delayed, local); + break; + case 2: + TimerCancel(mt->timer); + handle_gestures(local, &mt->gs); + break; + case 0: + default: break; + } + return 0; +} + +/* + * Called for each full received packet from the touchpad. + * Any xf86 input event generated by int this callback function fill be queued by + * xorg server, and fired when control return from this function. + * So to fire event as early as possible this function should return quickly. + * For delayed events we can't simply wait in this function, because it will delay + * all events generated by 'handle_gestures'. + * Moreover we don't know when next input event will occur, so to guarantee proper + * timing I have to use timer. + * + * If mtouch_delayed() retured 1 this means it was to early to trigger delayed button, + * and new timer have to be installed. Otherwise events generated inside can be handled + * as usual. + * + * More on input event processing: + * http://www.x.org/wiki/Development/Documentation/InputEventProcessing/ + */ static void read_input(LocalDevicePtr local) { struct MTouch *mt = local->private; while (mtouch_read(mt) > 0) handle_gestures(local, &mt->gs); - if (mtouch_delayed(mt)) - handle_gestures(local, &mt->gs); + check_resolve_delayed(mt->timer, 0, local); } static Bool device_control(DeviceIntPtr dev, int mode) @@ -266,10 +311,10 @@ static int preinit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) pInfo->read_input = read_input; pInfo->switch_mode = 0; - xf86CollectInputOptions(pInfo, NULL); - xf86OptionListReport(pInfo->options); - xf86ProcessCommonOptions(pInfo, pInfo->options); - mconfig_configure(&mt->cfg, pInfo->options); + xf86CollectInputOptions(pInfo, NULL); + xf86OptionListReport(pInfo->options); + xf86ProcessCommonOptions(pInfo, pInfo->options); + mconfig_configure(&mt->cfg, pInfo->options); return Success; } @@ -310,6 +355,9 @@ static void uninit(InputDriverPtr drv, InputInfoPtr local, int flags) xf86DeleteInput(local, 0); } +/* About xorg drivers, modules: + * http://www.x.org/wiki/Development/Documentation/XorgInputHOWTO/ + */ static InputDriverRec MTRACK = { 1, "mtrack", diff --git a/include/common.h b/include/common.h index 1021067..d80302a 100644 --- a/include/common.h +++ b/include/common.h @@ -53,7 +53,7 @@ typedef unsigned int bitmask_t; #define MODBIT(m, x, b) ((b) ? SETBIT(m, x) : CLEARBIT(m, x)) #define ABSVAL(x) ((x) < 0 ? -1*(x) : (x)) -#define MINVAL(x, y) ((x) < (y) ? (x) : (y)) +#define MINVAL(x, y) ((x) < (y) ? (x) : (y)) #define MAXVAL(x, y) ((x) > (y) ? (x) : (y)) #define MODVAL(x, y) ((x) - ((int)((x) / (y))) * (y)) #define SQRVAL(x) ((x) * (x)) @@ -105,6 +105,16 @@ static inline void timeraddms(const struct timeval* a, const mstime_t b, struct timeradd(a, &tv, dest); } +/* Check if given timeval a is set to epoch time. + */ +static inline int isepochtime(const struct timeval* a) +{ + struct timeval epoch; + timerclear(&epoch); + + return timercmp(a, &epoch, ==); +} + /* Clamp value to 15 bits. */ static inline int clamp15(int x) diff --git a/include/gestures.h b/include/gestures.h index dc5784b..68893dc 100644 --- a/include/gestures.h +++ b/include/gestures.h @@ -36,12 +36,14 @@ struct MTouch; #define GS_NONE 0 #define GS_MOVE 1 #define GS_SCROLL 2 -#define GS_SWIPE 3 -#define GS_SCALE 4 -#define GS_ROTATE 5 -#define GS_DRAG_READY 6 -#define GS_DRAG_WAIT 7 -#define GS_DRAG_ACTIVE 8 +#define GS_SWIPE2 GS_SCROLL +#define GS_SWIPE3 3 +#define GS_SWIPE4 4 +#define GS_SCALE 5 +#define GS_ROTATE 6 +#define GS_DRAG_READY 7 +#define GS_DRAG_WAIT 8 +#define GS_DRAG_ACTIVE 9 struct Gestures { /* Taps, physical buttons, and gestures will trigger diff --git a/include/mconfig.h b/include/mconfig.h index 6cead2a..2d9061e 100644 --- a/include/mconfig.h +++ b/include/mconfig.h @@ -57,11 +57,13 @@ #define DEFAULT_SCROLL_DN_BTN 5 #define DEFAULT_SCROLL_LT_BTN 6 #define DEFAULT_SCROLL_RT_BTN 7 +#define DEFAULT_SCROLL_HOLD 20 #define DEFAULT_SWIPE_DIST 700 #define DEFAULT_SWIPE_UP_BTN 8 #define DEFAULT_SWIPE_DN_BTN 9 #define DEFAULT_SWIPE_LT_BTN 10 #define DEFAULT_SWIPE_RT_BTN 11 +#define DEFAULT_SWIPE_HOLD 300 #define DEFAULT_SWIPE4_DIST 700 #define DEFAULT_SWIPE4_UP_BTN 0 #define DEFAULT_SWIPE4_DN_BTN 0 @@ -131,26 +133,20 @@ struct MConfig { int tap_2touch; // What button to emulate for two touch taps? 0 to 32 int tap_3touch; // What button to emulate for three touch taps? 0 to 32 int tap_4touch; // What button to emulate for four touch taps? 0 to 32 - int tap_timeout; // Window for touches when counting for the button. > 0 + int tap_timeout; // Window for touches when counting for the button. + // How long to wait for incoming touches after first one. > 0 int tap_hold; // How long to "hold down" the emulated button on tap. > 0 int tap_dist; // How far to allow a touch to move before it's a moving touch. > 0 int gesture_hold; // How long to "hold down" the emulated button for gestures. > 0 int gesture_wait; // How long after a gesture to wait before movement is allowed. >= 0 - int scroll_dist; // Distance needed to trigger a button. >= 0, 0 disables - int scroll_up_btn; // Button to use for scroll up. >= 0, 0 is none - int scroll_dn_btn; // Button to use for scroll down. >= 0, 0 is none - int scroll_lt_btn; // Button to use for scroll left. >= 0, 0 is none - int scroll_rt_btn; // Button to use for scroll right. >= 0, 0 is none - int swipe_dist; // Distance needed to trigger a button. >= 0, 0 disables - int swipe_up_btn; // Button to use for swipe up. >= 0, 0 is none - int swipe_dn_btn; // Button to use for swipe down. >= 0, 0 is none - int swipe_lt_btn; // Button to use for swipe left. >= 0, 0 is none - int swipe_rt_btn; // Button to use for swipe right. >= 0, 0 is none - int swipe4_dist; // Distance needed to trigger a button. >= 0, 0 disables - int swipe4_up_btn; // Button to use for four finger swipe up. >= 0, 0 is none - int swipe4_dn_btn; // Button to use for four finger swipe down. >= 0, 0 is none - int swipe4_lt_btn; // Button to use for four finger swipe left. >= 0, 0 is none - int swipe4_rt_btn; // Button to use for four finger swipe right. >= 0, 0 is none + struct MConfigSwipe{ + int dist; // Distance needed to trigger a button. >= 0, 0 disables + int up_btn; // Button to use for swipe up. >= 0, 0 is none + int dn_btn; // Button to use for swipe down. >= 0, 0 is none + int lt_btn; // Button to use for swipe left. >= 0, 0 is none + int rt_btn; // Button to use for swipe right. >= 0, 0 is none + int hold; // How long to "hold down" the emulated button for swipe up gesture. > 0 + } scroll, swipe3, swipe4/*, swipe5*/; int scale_dist; // Distance needed to trigger a button. >= 0, 0 disables int scale_up_btn; // Button to use for scale up. >= 0, 0 is none int scale_dn_btn; // Button to use for scale down. >= 0, 0 is none diff --git a/include/mprops.h b/include/mprops.h index 6672741..9ca5162 100644 --- a/include/mprops.h +++ b/include/mprops.h @@ -62,16 +62,22 @@ #define MTRACK_PROP_PALM_SIZE "Trackpad Palm Size" // int, 2 value - button hold, wait time #define MTRACK_PROP_GESTURE_SETTINGS "Trackpad Gesture Settings" -// int, 1 value - distance before a scroll event is triggered -#define MTRACK_PROP_SCROLL_DIST "Trackpad Scroll Distance" +// int, 2 values +// first: distance before a scroll event (two finger swipe) is triggered +// second: how much milliseconds button will be hold after {up,down,left,right} scroll +#define MTRACK_PROP_SCROLL_SETTINGS "Trackpad Scroll Settings" // int, 4 values - up button, down button, left button, right button #define MTRACK_PROP_SCROLL_BUTTONS "Trackpad Scroll Buttons" -// int, 1 value - distance before a swipe event is triggered -#define MTRACK_PROP_SWIPE_DIST "Trackpad Swipe Distance" +// int, 2 values +// first: distance before a three finger swipe event is triggered +// second: how much milliseconds button will be hold after {up,down,left,right} swipe +#define MTRACK_PROP_SWIPE_SETTINGS "Trackpad Swipe Settings" // int, 4 values - up button, down button, left button, right button #define MTRACK_PROP_SWIPE_BUTTONS "Trackpad Swipe Buttons" -// int, 1 value - distance before a swipe event is triggered -#define MTRACK_PROP_SWIPE4_DIST "Trackpad Swipe4 Distance" +// int, 2 values +// first: distance before a four finger swipe event is triggered +// second: how much milliseconds button will be hold after {up,down,left,right} swipe4 +#define MTRACK_PROP_SWIPE4_SETTINGS "Trackpad Swipe4 Settings" // int, 4 values - up button, down button, left button, right button #define MTRACK_PROP_SWIPE4_BUTTONS "Trackpad Swipe4 Buttons" // int, 1 value - distance before a scale event is triggered @@ -106,12 +112,10 @@ struct MProps { Atom palm_detect; Atom palm_size; Atom gesture_settings; - Atom scroll_dist; - Atom scroll_buttons; - Atom swipe_dist; - Atom swipe_buttons; - Atom swipe4_dist; - Atom swipe4_buttons; + struct MPropsSwipe{ + Atom settings; + Atom buttons; + } scroll, swipe3, swipe4/*, swipe5*/; Atom scale_dist; Atom scale_buttons; Atom rotate_dist; diff --git a/include/mtouch.h b/include/mtouch.h index 91fc41c..b6ad51c 100644 --- a/include/mtouch.h +++ b/include/mtouch.h @@ -29,6 +29,7 @@ #include "mtstate.h" #include "mconfig.h" #include "gestures.h" +#include "os.h" /* xorg/os.h for timers */ struct MTouch { int fd; @@ -38,6 +39,7 @@ struct MTouch { struct MTState state; struct MConfig cfg; struct Gestures gs; + OsTimerPtr timer; }; int mtouch_configure(struct MTouch* mt, int fd); diff --git a/required_packages.txt b/required_packages.txt new file mode 100644 index 0000000..f849d6a --- /dev/null +++ b/required_packages.txt @@ -0,0 +1 @@ +xserver-xorg-dev mtdev-dev xutils-dev diff --git a/src/gestures.c b/src/gestures.c index 5262fbd..a1ed9f4 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -77,20 +77,23 @@ static void trigger_button_emulation(struct Gestures* gs, int button) static void trigger_button_click(struct Gestures* gs, int button, struct timeval* trigger_up_time) { - struct timeval epoch; - timerclear(&epoch); - - if (IS_VALID_BUTTON(button) && timercmp(&gs->button_delayed_time, &epoch, ==)) { + if (!IS_VALID_BUTTON(button)) + return; + if (isepochtime(&gs->button_delayed_time)) { trigger_button_down(gs, button); gs->button_delayed = button; - timercp(&gs->button_delayed_time, trigger_up_time); - timerclear(&gs->button_delayed_delta); -#ifdef DEBUG_GESTRUES - xf86Msg(X_INFO, "trigger_button_click: %d placed in delayed mode\n"); + if(trigger_up_time == NULL || isepochtime(trigger_up_time)) + timercp(&gs->button_delayed_time, &gs->time); + else + timercp(&gs->button_delayed_time, trigger_up_time); + + timersub(&gs->button_delayed_time, &gs->time, &gs->button_delayed_delta); +#ifdef DEBUG_GESTURES + xf86Msg(X_INFO, "trigger_button_click: %d placed in delayed mode; delta: %d ms\n", button, timertoms(&gs->button_delayed_delta)); #endif } #ifdef DEBUG_GESTURES - else if (IS_VALID_BUTTON(button)) + else xf86Msg(X_INFO, "trigger_button_click: %d ignored, in delayed mode\n", button); #endif } @@ -164,7 +167,7 @@ static void trigger_drag_stop(struct Gestures* gs, int force) #ifdef DEBUG_GESTURES xf86Msg(X_INFO, "trigger_drag_stop: drag stopped\n"); #endif - } + } } static void buttons_update(struct Gestures* gs, @@ -300,6 +303,7 @@ static void tapping_update(struct Gestures* gs, timerclear(&epoch); timeraddms(&gs->tap_time_down, cfg->tap_timeout, &tv_tmp); if (!timercmp(&gs->tap_time_down, &epoch, ==) && !timercmp(&gs->time, &tv_tmp, <)) { + // too much time passed by from first touch, stop waiting for incoming touches gs->tap_touching = 0; gs->tap_released = 0; timerclear(&gs->tap_time_down); @@ -355,11 +359,13 @@ static void tapping_update(struct Gestures* gs, } if ((gs->tap_touching == 0 && gs->tap_released > 0) || gs->tap_released >= released_max) { + // in this branch tap was recognized as button click + // clear tap flags from touches foreach_bit(i, ms->touch_used) { if (GETBIT(ms->touch[i].flags, GS_TAP)) CLEARBIT(ms->touch[i].flags, GS_TAP); } - + // determinate which button was "tapped" by counting touches if (gs->tap_released == 1) n = cfg->tap_1touch - 1; else if (gs->tap_released == 2) @@ -369,6 +375,8 @@ static void tapping_update(struct Gestures* gs, else n = cfg->tap_4touch - 1; + // how long button should be hold down + timeraddms(&gs->time, cfg->tap_hold, &tv_tmp); trigger_button_click(gs, n, &tv_tmp); if (cfg->drag_enable && n == 0) trigger_drag_ready(gs, cfg); @@ -403,92 +411,50 @@ static void trigger_move(struct Gestures* gs, } } -static void trigger_scroll(struct Gestures* gs, - const struct MConfig* cfg, - double dist, int dir) -{ - if (gs->move_type == GS_SCROLL || !timercmp(&gs->time, &gs->move_wait, <)) { - struct timeval tv_tmp; - trigger_drag_stop(gs, 1); - if (gs->move_type != GS_SCROLL || gs->move_dir != dir) - gs->move_dist = 0; - gs->move_dx = 0; - gs->move_dy = 0; - gs->move_type = GS_SCROLL; - gs->move_dist += (int)ABSVAL(dist); - gs->move_dir = dir; - gs->move_speed = dist/timertomicro(&gs->dt); - timeraddms(&gs->time, cfg->gesture_wait, &gs->move_wait); - - if (gs->move_dist >= cfg->scroll_dist) { - gs->move_dist = MODVAL(gs->move_dist, cfg->scroll_dist); - timeraddms(&gs->time, cfg->gesture_hold, &tv_tmp); - if (dir == TR_DIR_UP) - trigger_button_click(gs, cfg->scroll_up_btn - 1, &tv_tmp); - else if (dir == TR_DIR_DN) - trigger_button_click(gs, cfg->scroll_dn_btn - 1, &tv_tmp); - else if (dir == TR_DIR_LT) - trigger_button_click(gs, cfg->scroll_lt_btn - 1, &tv_tmp); - else if (dir == TR_DIR_RT) - trigger_button_click(gs, cfg->scroll_rt_btn - 1, &tv_tmp); - } +static void trigger_swipe_button(struct Gestures* gs, const struct MConfigSwipe* swipeCfg, + int dir, double dist){ + struct timeval tv_tmp; + if (swipeCfg->dist > 0 && gs->move_dist >= swipeCfg->dist) { + timeraddms(&gs->time, swipeCfg->hold, &tv_tmp); + gs->move_dist = MODVAL(gs->move_dist, swipeCfg->dist); + if (dir == TR_DIR_UP) + trigger_button_click(gs, swipeCfg->up_btn - 1, &tv_tmp); + else if (dir == TR_DIR_DN) + trigger_button_click(gs, swipeCfg->dn_btn - 1, &tv_tmp); + else if (dir == TR_DIR_LT) + trigger_button_click(gs, swipeCfg->lt_btn - 1, &tv_tmp); + else if (dir == TR_DIR_RT) + trigger_button_click(gs, swipeCfg->rt_btn - 1, &tv_tmp); + } #ifdef DEBUG_GESTURES - xf86Msg(X_INFO, "trigger_scroll: scrolling %+f in direction %d (at %d of %d) (speed %f)\n", - dist, dir, gs->move_dist, cfg->scroll_dist, gs->move_speed); + xf86Msg(X_INFO, "trigger_swipe_button: swiping %+f in direction %d (at %d of %d) (speed %f)\n", + dist, dir, gs->move_dist, swipeCfg->dist, gs->move_speed); #endif - } } static void trigger_swipe(struct Gestures* gs, const struct MConfig* cfg, - double dist, int dir, int isfour) + double dist, int dir, int move_type_to_trigger) { - if (gs->move_type == GS_SWIPE || !timercmp(&gs->time, &gs->move_wait, <)) { - struct timeval tv_tmp; + if (gs->move_type == move_type_to_trigger || !timercmp(&gs->time, &gs->move_wait, <)) { trigger_drag_stop(gs, 1); - if (gs->move_type != GS_SWIPE || gs->move_dir != dir) + if (gs->move_type != move_type_to_trigger || gs->move_dir != dir) gs->move_dist = 0; gs->move_dx = 0; gs->move_dy = 0; - gs->move_type = GS_SWIPE; + gs->move_type = move_type_to_trigger; gs->move_dist += (int)ABSVAL(dist); gs->move_dir = dir; gs->move_speed = dist/timertomicro(&gs->dt); timeraddms(&gs->time, cfg->gesture_wait, &gs->move_wait); - timeraddms(&gs->time, cfg->gesture_hold, &tv_tmp); - - if (isfour) { - if (cfg->swipe4_dist > 0 && gs->move_dist >= cfg->swipe4_dist) { - gs->move_dist = MODVAL(gs->move_dist, cfg->swipe4_dist); - if (dir == TR_DIR_UP) - trigger_button_click(gs, cfg->swipe4_up_btn - 1, &tv_tmp); - else if (dir == TR_DIR_DN) - trigger_button_click(gs, cfg->swipe4_dn_btn - 1, &tv_tmp); - else if (dir == TR_DIR_LT) - trigger_button_click(gs, cfg->swipe4_lt_btn - 1, &tv_tmp); - else if (dir == TR_DIR_RT) - trigger_button_click(gs, cfg->swipe4_rt_btn - 1, &tv_tmp); - } -#ifdef DEBUG_GESTURES - xf86Msg(X_INFO, "trigger_swipe4: swiping %+f in direction %d (at %d of %d) (speed %f)\n", - dist, dir, gs->move_dist, cfg->swipe_dist, gs->move_speed); -#endif - } - else { - if (cfg->swipe_dist > 0 && gs->move_dist >= cfg->swipe_dist) { - gs->move_dist = MODVAL(gs->move_dist, cfg->swipe_dist); - if (dir == TR_DIR_UP) - trigger_button_click(gs, cfg->swipe_up_btn - 1, &tv_tmp); - else if (dir == TR_DIR_DN) - trigger_button_click(gs, cfg->swipe_dn_btn - 1, &tv_tmp); - else if (dir == TR_DIR_LT) - trigger_button_click(gs, cfg->swipe_lt_btn - 1, &tv_tmp); - else if (dir == TR_DIR_RT) - trigger_button_click(gs, cfg->swipe_rt_btn - 1, &tv_tmp); - } -#ifdef DEBUG_GESTURES - xf86Msg(X_INFO, "trigger_swipe: swiping %+f in direction %d (at %d of %d)\n", dist, dir, gs->move_dist, cfg->swipe_dist); -#endif + + switch(move_type_to_trigger){ + case GS_SWIPE2: + return trigger_swipe_button(gs, &cfg->scroll, dir, dist); + case GS_SWIPE3: + return trigger_swipe_button(gs, &cfg->swipe3, dir, dist); + case GS_SWIPE4: + return trigger_swipe_button(gs, &cfg->swipe4, dir, dist); } } } @@ -678,7 +644,7 @@ static void moving_update(struct Gestures* gs, dist = hypot( touches[0]->dx + touches[1]->dx, touches[0]->dy + touches[1]->dy); - trigger_scroll(gs, cfg, dist/2, dir); + trigger_swipe(gs, cfg, dist/2.0, dir, GS_SCROLL); } else if ((dir = get_rotate_dir(touches[0], touches[1])) != TR_NONE) { dist = ABSVAL(hypot(touches[0]->dx, touches[0]->dy)) + @@ -696,7 +662,7 @@ static void moving_update(struct Gestures* gs, dist = hypot( touches[0]->dx + touches[1]->dx + touches[2]->dx, touches[0]->dy + touches[1]->dy + touches[2]->dy); - trigger_swipe(gs, cfg, dist/3, dir, 0); + trigger_swipe(gs, cfg, dist/3.0, dir, GS_SWIPE3); } } else if (count == 4 && cfg->trackpad_disable < 1) { @@ -704,7 +670,7 @@ static void moving_update(struct Gestures* gs, dist = hypot( touches[0]->dx + touches[1]->dx + touches[2]->dx + touches[3]->dx, touches[0]->dy + touches[1]->dy + touches[2]->dy + touches[3]->dy); - trigger_swipe(gs, cfg, dist/4, dir, 1); + trigger_swipe(gs, cfg, dist/4.0, dir, GS_SWIPE4); } } } @@ -721,13 +687,11 @@ static void dragging_update(struct Gestures* gs) static void delayed_update(struct Gestures* gs) { - struct timeval epoch; - timerclear(&epoch); - - if (timercmp(&gs->button_delayed_time, &epoch, ==)) + // if there's no delayed button - return + if(isepochtime(&gs->button_delayed_time)) return; - if (!timercmp(&gs->time, &gs->button_delayed_time, <)) { + if (timercmp(&gs->time, &gs->button_delayed_time, >=)) { #ifdef DEBUG_GESTURES xf86Msg(X_INFO, "delayed_update: %d delay expired, triggering up\n", gs->button_delayed); #endif @@ -738,6 +702,9 @@ static void delayed_update(struct Gestures* gs) } else { timersub(&gs->button_delayed_time, &gs->time, &gs->button_delayed_delta); +#ifdef DEBUG_GESTURES + xf86Msg(X_INFO, "delayed_update: %d still waiting, new delta %d ms\n", gs->button_delayed, timertoms(&gs->button_delayed_delta)); +#endif } } @@ -758,39 +725,70 @@ void gestures_extract(struct MTouch* mt) delayed_update(&mt->gs); } -static int gestures_sleep(struct MTouch* mt, const struct timeval* sleep) -{ - if (mtdev_empty(&mt->dev)) { - struct timeval now; - mtdev_idle(&mt->dev, mt->fd, timertoms(sleep)); - microtime(&now); - timersub(&now, &mt->gs.time, &mt->gs.dt); - timercp(&mt->gs.time, &now); - return 1; - } - return 0; -} - +/* + * Executed every input time frame, at least once. First time from 'read_input' to check if + * timer is needed. + * Return value 1 means that next timer should be installed with this function as a + * callabck and gs->button_delayed_delta as delay time. + * + * Return vale meaning: + * - 0 - no delay to handle, don't install timer, do nothing + * - 1 - only install timer + * - 2 - state was changed, so caller have to cancel timer and handle state change + */ int gestures_delayed(struct MTouch* mt) { struct Gestures* gs = &mt->gs; - struct timeval epoch; + struct MTState* ms = &mt->state; + struct timeval now, epoch; + int i, taps_released; + timerclear(&epoch); + taps_released = 0; - if (timercmp(&gs->button_delayed_time, &epoch, >)) { - if (gestures_sleep(mt, &gs->button_delayed_delta)) { -#ifdef DEBUG_GESTURES - xf86Msg(X_INFO, "gestures_delayed: %d up, timer expired\n", gs->button_delayed); -#endif - trigger_button_up(gs, gs->button_delayed); - gs->move_dx = 0; - gs->move_dy = 0; - gs->button_delayed = 0; - timerclear(&gs->button_delayed_time); - timerclear(&gs->button_delayed_delta); - return 1; + // if there's no delayed button - return + if(timercmp(&gs->button_delayed_time, &epoch, ==)) + return 0; + + // count released fingers + foreach_bit(i, ms->touch_used) { + if (GETBIT(ms->touch[i].state, MT_RELEASED)) + ++taps_released; + } + + // if one of fingers were released it means that gesture was ended so + // send "button up" event immediately without checking for delivery time + if(taps_released == 0){ + microtime(&now); + timersub(&now, &mt->gs.time, &mt->gs.dt); + timercp(&mt->gs.time, &now); + + if(timercmp(&gs->button_delayed_time, &now, >)){ + // update delta time + timersub(&gs->button_delayed_time, &now, &gs->button_delayed_delta); + // That second check may seem unnecessary, but it is not. + // Even if button delayed time is > than now time, timertoms may still return 0 + // because it truncates time to miliseconds. It's important because truncated time + // is used to setup timer. + if(timertoms(&gs->button_delayed_delta) > 1){ + #ifdef DEBUG_GESTURES + xf86Msg(X_INFO, "gestures_delayed: %d delayed, new delta: %d ms\n", gs->button_delayed, timertoms(&gs->button_delayed_delta)); + #endif + return 1; // install timer + } + // else execute now } } - return 0; + timerclear(&gs->button_delayed_time); + timerclear(&gs->button_delayed_delta); +#ifdef DEBUG_GESTURES + xf86Msg(X_INFO, "gestures_delayed: %d up, timer expired\n", gs->button_delayed); +#endif + trigger_button_up(gs, gs->button_delayed); + gs->move_dx = 0; + gs->move_dy = 0; + gs->button_delayed = 0; + + return 2; // caller scholud call TimerCancel() and handle_gestures() } diff --git a/src/mconfig.c b/src/mconfig.c index 4ecbd87..faca504 100644 --- a/src/mconfig.c +++ b/src/mconfig.c @@ -53,21 +53,24 @@ void mconfig_defaults(struct MConfig* cfg) cfg->tap_dist = DEFAULT_TAP_DIST; cfg->gesture_hold = DEFAULT_GESTURE_HOLD; cfg->gesture_wait = DEFAULT_GESTURE_WAIT; - cfg->scroll_dist = DEFAULT_SCROLL_DIST; - cfg->scroll_up_btn = DEFAULT_SCROLL_UP_BTN; - cfg->scroll_dn_btn = DEFAULT_SCROLL_DN_BTN; - cfg->scroll_lt_btn = DEFAULT_SCROLL_LT_BTN; - cfg->scroll_rt_btn = DEFAULT_SCROLL_RT_BTN; - cfg->swipe_dist = DEFAULT_SWIPE_DIST; - cfg->swipe_up_btn = DEFAULT_SWIPE_UP_BTN; - cfg->swipe_dn_btn = DEFAULT_SWIPE_DN_BTN; - cfg->swipe_lt_btn = DEFAULT_SWIPE_LT_BTN; - cfg->swipe_rt_btn = DEFAULT_SWIPE_RT_BTN; - cfg->swipe4_dist = DEFAULT_SWIPE4_DIST; - cfg->swipe4_up_btn = DEFAULT_SWIPE4_UP_BTN; - cfg->swipe4_dn_btn = DEFAULT_SWIPE4_DN_BTN; - cfg->swipe4_lt_btn = DEFAULT_SWIPE4_LT_BTN; - cfg->swipe4_rt_btn = DEFAULT_SWIPE4_RT_BTN; + cfg->scroll.dist = DEFAULT_SCROLL_DIST; + cfg->scroll.up_btn = DEFAULT_SCROLL_UP_BTN; + cfg->scroll.dn_btn = DEFAULT_SCROLL_DN_BTN; + cfg->scroll.lt_btn = DEFAULT_SCROLL_LT_BTN; + cfg->scroll.rt_btn = DEFAULT_SCROLL_RT_BTN; + cfg->scroll.hold = DEFAULT_SCROLL_HOLD; + cfg->swipe3.dist = DEFAULT_SWIPE_DIST; + cfg->swipe3.up_btn = DEFAULT_SWIPE_UP_BTN; + cfg->swipe3.dn_btn = DEFAULT_SWIPE_DN_BTN; + cfg->swipe3.lt_btn = DEFAULT_SWIPE_LT_BTN; + cfg->swipe3.rt_btn = DEFAULT_SWIPE_RT_BTN; + cfg->swipe3.hold = DEFAULT_SWIPE_HOLD; + cfg->swipe4.dist = DEFAULT_SWIPE4_DIST; + cfg->swipe4.up_btn = DEFAULT_SWIPE4_UP_BTN; + cfg->swipe4.dn_btn = DEFAULT_SWIPE4_DN_BTN; + cfg->swipe4.lt_btn = DEFAULT_SWIPE4_LT_BTN; + cfg->swipe4.rt_btn = DEFAULT_SWIPE4_RT_BTN; + cfg->swipe4.hold = DEFAULT_SWIPE_HOLD; cfg->scale_dist = DEFAULT_SCALE_DIST; cfg->scale_up_btn = DEFAULT_SCALE_UP_BTN; cfg->scale_dn_btn = DEFAULT_SCALE_DN_BTN; @@ -85,7 +88,7 @@ void mconfig_init(struct MConfig* cfg, cfg->touch_minor = caps->has_abs[MTDEV_TOUCH_MINOR]; cfg->pad_width = get_cap_xsize(caps); cfg->pad_height = get_cap_ysize(caps); - + if (caps->has_abs[MTDEV_TOUCH_MAJOR] && caps->has_abs[MTDEV_WIDTH_MAJOR]) { cfg->touch_type = MCFG_SCALE; cfg->touch_min = caps->abs[MTDEV_TOUCH_MAJOR].minimum; @@ -150,21 +153,24 @@ void mconfig_configure(struct MConfig* cfg, cfg->tap_dist = MAXVAL(xf86SetIntOption(opts, "MaxTapMove", DEFAULT_TAP_DIST), 1); cfg->gesture_hold = MAXVAL(xf86SetIntOption(opts, "GestureClickTime", DEFAULT_GESTURE_HOLD), 1); cfg->gesture_wait = MAXVAL(xf86SetIntOption(opts, "GestureWaitTime", DEFAULT_GESTURE_WAIT), 0); - cfg->scroll_dist = MAXVAL(xf86SetIntOption(opts, "ScrollDistance", DEFAULT_SCROLL_DIST), 1); - cfg->scroll_up_btn = CLAMPVAL(xf86SetIntOption(opts, "ScrollUpButton", DEFAULT_SCROLL_UP_BTN), 0, 32); - cfg->scroll_dn_btn = CLAMPVAL(xf86SetIntOption(opts, "ScrollDownButton", DEFAULT_SCROLL_DN_BTN), 0, 32); - cfg->scroll_lt_btn = CLAMPVAL(xf86SetIntOption(opts, "ScrollLeftButton", DEFAULT_SCROLL_LT_BTN), 0, 32); - cfg->scroll_rt_btn = CLAMPVAL(xf86SetIntOption(opts, "ScrollRightButton", DEFAULT_SCROLL_RT_BTN), 0, 32); - cfg->swipe_dist = MAXVAL(xf86SetIntOption(opts, "SwipeDistance", DEFAULT_SWIPE_DIST), 1); - cfg->swipe_up_btn = CLAMPVAL(xf86SetIntOption(opts, "SwipeUpButton", DEFAULT_SWIPE_UP_BTN), 0, 32); - cfg->swipe_dn_btn = CLAMPVAL(xf86SetIntOption(opts, "SwipeDownButton", DEFAULT_SWIPE_DN_BTN), 0, 32); - cfg->swipe_lt_btn = CLAMPVAL(xf86SetIntOption(opts, "SwipeLeftButton", DEFAULT_SWIPE_LT_BTN), 0, 32); - cfg->swipe_rt_btn = CLAMPVAL(xf86SetIntOption(opts, "SwipeRightButton", DEFAULT_SWIPE_RT_BTN), 0, 32); - cfg->swipe4_dist = MAXVAL(xf86SetIntOption(opts, "Swipe4Distance", DEFAULT_SWIPE4_DIST), 1); - cfg->swipe4_up_btn = CLAMPVAL(xf86SetIntOption(opts, "Swipe4UpButton", DEFAULT_SWIPE4_UP_BTN), 0, 32); - cfg->swipe4_dn_btn = CLAMPVAL(xf86SetIntOption(opts, "Swipe4DownButton", DEFAULT_SWIPE4_DN_BTN), 0, 32); - cfg->swipe4_lt_btn = CLAMPVAL(xf86SetIntOption(opts, "Swipe4LeftButton", DEFAULT_SWIPE4_LT_BTN), 0, 32); - cfg->swipe4_rt_btn = CLAMPVAL(xf86SetIntOption(opts, "Swipe4RightButton", DEFAULT_SWIPE4_RT_BTN), 0, 32); + cfg->scroll.dist = MAXVAL(xf86SetIntOption(opts, "ScrollDistance", DEFAULT_SCROLL_DIST), 1); + cfg->scroll.hold = MAXVAL(xf86SetIntOption(opts, "ScrollClickTime", DEFAULT_SCROLL_HOLD), 0); + cfg->scroll.up_btn = CLAMPVAL(xf86SetIntOption(opts, "ScrollUpButton", DEFAULT_SCROLL_UP_BTN), 0, 32); + cfg->scroll.dn_btn = CLAMPVAL(xf86SetIntOption(opts, "ScrollDownButton", DEFAULT_SCROLL_DN_BTN), 0, 32); + cfg->scroll.lt_btn = CLAMPVAL(xf86SetIntOption(opts, "ScrollLeftButton", DEFAULT_SCROLL_LT_BTN), 0, 32); + cfg->scroll.rt_btn = CLAMPVAL(xf86SetIntOption(opts, "ScrollRightButton", DEFAULT_SCROLL_RT_BTN), 0, 32); + cfg->swipe3.dist = MAXVAL(xf86SetIntOption(opts, "SwipeDistance", DEFAULT_SWIPE_DIST), 1); + cfg->swipe3.hold = MAXVAL(xf86SetIntOption(opts, "SwipeClickTime", DEFAULT_SWIPE_HOLD), 0); + cfg->swipe3.up_btn = CLAMPVAL(xf86SetIntOption(opts, "SwipeUpButton", DEFAULT_SWIPE_UP_BTN), 0, 32); + cfg->swipe3.dn_btn = CLAMPVAL(xf86SetIntOption(opts, "SwipeDownButton", DEFAULT_SWIPE_DN_BTN), 0, 32); + cfg->swipe3.lt_btn = CLAMPVAL(xf86SetIntOption(opts, "SwipeLeftButton", DEFAULT_SWIPE_LT_BTN), 0, 32); + cfg->swipe3.rt_btn = CLAMPVAL(xf86SetIntOption(opts, "SwipeRightButton", DEFAULT_SWIPE_RT_BTN), 0, 32); + cfg->swipe4.dist = MAXVAL(xf86SetIntOption(opts, "Swipe4Distance", DEFAULT_SWIPE4_DIST), 1); + cfg->swipe4.hold = MAXVAL(xf86SetIntOption(opts, "Swipe4ClickTime", DEFAULT_SWIPE_HOLD), 0); + cfg->swipe4.up_btn = CLAMPVAL(xf86SetIntOption(opts, "Swipe4UpButton", DEFAULT_SWIPE4_UP_BTN), 0, 32); + cfg->swipe4.dn_btn = CLAMPVAL(xf86SetIntOption(opts, "Swipe4DownButton", DEFAULT_SWIPE4_DN_BTN), 0, 32); + cfg->swipe4.lt_btn = CLAMPVAL(xf86SetIntOption(opts, "Swipe4LeftButton", DEFAULT_SWIPE4_LT_BTN), 0, 32); + cfg->swipe4.rt_btn = CLAMPVAL(xf86SetIntOption(opts, "Swipe4RightButton", DEFAULT_SWIPE4_RT_BTN), 0, 32); cfg->scale_dist = MAXVAL(xf86SetIntOption(opts, "ScaleDistance", DEFAULT_SCALE_DIST), 1); cfg->scale_up_btn = CLAMPVAL(xf86SetIntOption(opts, "ScaleUpButton", DEFAULT_SCALE_UP_BTN), 0, 32); cfg->scale_dn_btn = CLAMPVAL(xf86SetIntOption(opts, "ScaleDownButton", DEFAULT_SCALE_DN_BTN), 0, 32); diff --git a/src/mtstate.c b/src/mtstate.c index 2cc0c32..6b30c0f 100644 --- a/src/mtstate.c +++ b/src/mtstate.c @@ -41,7 +41,7 @@ static int is_touch(const struct MConfig* cfg, if (cfg->touch_type == MCFG_SCALE) return percentage(hw->touch_major, hw->width_major) > cfg->touch_down; else if (cfg->touch_type == MCFG_SIZE) - return touch_range_ratio(cfg, hw->touch_major) > cfg->touch_down; + return touch_range_ratio(cfg, hw->touch_major) >= cfg->touch_down; else if (cfg->touch_type == MCFG_PRESSURE) return touch_range_ratio(cfg, hw->pressure) > cfg->touch_down; else @@ -231,24 +231,24 @@ static void touches_update(struct MTState* ms, SETBIT(ms->touch[n].state, MT_THUMB); else CLEARBIT(ms->touch[n].state, MT_THUMB); - + if (is_palm(cfg, &hs->data[i])) SETBIT(ms->touch[n].state, MT_PALM); else CLEARBIT(ms->touch[n].state, MT_PALM); - + if (ms->touch[n].y > (100 - cfg->bottom_edge)*cfg->pad_height/100) { if (GETBIT(ms->touch[n].state, MT_NEW)) SETBIT(ms->touch[n].state, MT_BOTTOM_EDGE); } else CLEARBIT(ms->touch[n].state, MT_BOTTOM_EDGE); - + MODBIT(ms->touch[n].state, MT_INVALID, GETBIT(ms->touch[n].state, MT_THUMB) && cfg->ignore_thumb || GETBIT(ms->touch[n].state, MT_PALM) && cfg->ignore_palm || GETBIT(ms->touch[n].state, MT_BOTTOM_EDGE)); - + disable |= cfg->disable_on_thumb && GETBIT(ms->touch[n].state, MT_THUMB); disable |= cfg->disable_on_palm && GETBIT(ms->touch[n].state, MT_PALM); }