From: Ian Jackson Date: Sat, 23 Apr 2016 19:18:53 +0000 (+0100) Subject: Button zones: Provide BottomEdgeZonesEnable X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=xf86-input-mtrack.git;a=commitdiff_plain;h=898a7d315ac511bbdc3c1d424cb7ae23e71bc191 Button zones: Provide BottomEdgeZonesEnable Many modern laptops have a clickpad, with some faint legend on the surface suggesting that the bottom portion is a pair (usually) of buttons. Some users who are used to laptops which had separate physical buttons below the trackpad have developed the habit of putting one finger on the physical button, and using another finger to mouse. This user behaviour can be supported if we: - ignore touches in the "button" area for all purposes, except - decide which button was pressed, if the user clicks the clickpad, by looking at which touch(es) are present in the button area This is a novel combination of the behaviours of the BottomEdge and ButtonZones options. Provide a new BottomEdgeZonesEnable option, (including documentation and static configuration). The current code does not support users who have a habit of generating and using chorded button events on mice with physical buttons. (That is, users who have configured application(s) to process simultaneous clicks of different buttons meaningfully differently to single-button clicks.) I think this should be regarded as a bug in the implementation I am introducing in this patch. Fixing this would be feasible without new config options or changes to other semantics but would involve more rework of the zone processing in gestures.c than I currently have time for. Signed-off-by: Ian Jackson --- diff --git a/README.md b/README.md index 5063eae..c65eef1 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,15 @@ those ClickFinger values that are enabled. So setting ClickFinger1 to 0 and enabling the other two will create two zones, one for ClickFinger2 and one for ClickFinger3. Boolean value. Defaults to false. +**BottomEdgeZonesEnable** - +Whether to enable button zones in the bottom edge. If this feature is +enabled then touches in the BottomEdge region determine which button +is sent. The vertical division of the zones is as for +ButtonZonesEnable. If there is no touch in the bottom edge, then +button 0 will be sent (or the button according to ButtonZonesEnable, +if that is enabled). This is particularly useful for clickpads with +integrated buttons. Defaults to false. + **ButtonTouchExpire** - How long (in ms) to consider a touching finger as part of button emulation. A value of 0 will not expire touches. Integer value. Defaults to 100. diff --git a/include/mconfig.h b/include/mconfig.h index 6cead2a..2c3c86f 100644 --- a/include/mconfig.h +++ b/include/mconfig.h @@ -38,6 +38,7 @@ #define DEFAULT_BUTTON_ENABLE 1 #define DEFAULT_BUTTON_INTEGRATED 1 #define DEFAULT_BUTTON_ZONES 0 +#define DEFAULT_BOTTOM_EDGE_ZONES 0 #define DEFAULT_BUTTON_1TOUCH 3 #define DEFAULT_BUTTON_2TOUCH 2 #define DEFAULT_BUTTON_3TOUCH 0 @@ -119,6 +120,7 @@ struct MConfig { int button_integrated; // Is the button under the touchpad? 0 or 1 int button_expire; // How long to consider a touch for button emulation. >= 0 int button_zones; // Use button zones for emulation? + int bottom_edge_zones; // Use bottom edge zones for emulation? int button_1touch; // What button to emulate when one finger is on the // pad or the first zone is clicked? 0 to 32 int button_2touch; // What button to emulate when two fingers are on the diff --git a/src/gestures.c b/src/gestures.c index 5922c00..22a94ac 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -215,6 +215,21 @@ static void buttons_update(struct Gestures* gs, if (cfg->button_zones && earliest >= 0) { pos = ms->touch[earliest].x; } + if (cfg->bottom_edge_zones) { + int latest_bottom = -1; + foreach_bit(i, ms->touch_used) { + if (!GETBIT(ms->touch[i].state, MT_BOTTOM_EDGE)) + continue; + if (GETBIT(ms->touch[i].state, MT_PALM) && cfg->ignore_palm) + continue; + /* we deliberately don't ignore thumbs for bottom button zones */ + + if (latest_bottom == -1 || timercmp(&ms->touch[i].down, &ms->touch[latest_bottom].down, >)) + latest_bottom = i; + } + if (latest_bottom >= 0) + pos = ms->touch[latest_bottom].x; + } if (pos >= 0) { int zones, left, right; diff --git a/src/mconfig.c b/src/mconfig.c index 4ecbd87..761b9a1 100644 --- a/src/mconfig.c +++ b/src/mconfig.c @@ -41,6 +41,7 @@ void mconfig_defaults(struct MConfig* cfg) cfg->button_integrated = DEFAULT_BUTTON_INTEGRATED; cfg->button_expire = DEFAULT_BUTTON_EXPIRE; cfg->button_zones = DEFAULT_BUTTON_ZONES; + cfg->bottom_edge_zones = DEFAULT_BOTTOM_EDGE_ZONES; cfg->button_1touch = DEFAULT_BUTTON_1TOUCH; cfg->button_2touch = DEFAULT_BUTTON_2TOUCH; cfg->button_3touch = DEFAULT_BUTTON_3TOUCH; @@ -137,6 +138,7 @@ void mconfig_configure(struct MConfig* cfg, cfg->button_integrated = xf86SetBoolOption(opts, "ButtonIntegrated", DEFAULT_BUTTON_INTEGRATED); cfg->button_expire = MAXVAL(xf86SetIntOption(opts, "ButtonTouchExpire", DEFAULT_BUTTON_EXPIRE), 0); cfg->button_zones = xf86SetBoolOption(opts, "ButtonZonesEnable", DEFAULT_BUTTON_ZONES); + cfg->bottom_edge_zones = xf86SetBoolOption(opts, "BottomEdgeZonesEnable", DEFAULT_BOTTOM_EDGE_ZONES); cfg->button_1touch = CLAMPVAL(xf86SetIntOption(opts, "ClickFinger1", DEFAULT_BUTTON_1TOUCH), 0, 32); cfg->button_2touch = CLAMPVAL(xf86SetIntOption(opts, "ClickFinger2", DEFAULT_BUTTON_2TOUCH), 0, 32); cfg->button_3touch = CLAMPVAL(xf86SetIntOption(opts, "ClickFinger3", DEFAULT_BUTTON_3TOUCH), 0, 32);