chiark / gitweb /
Sensitivity: Handle sensitivities < 1.0 without rounding errors
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 24 Apr 2016 01:36:01 +0000 (02:36 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 26 Apr 2016 20:06:50 +0000 (21:06 +0100)
Background: We tell the xf86 core that our x and y ranges are the
overall range of the trackpad.  The xf86 core scales the supplied
values in the same way for relative and absolute pointers.  The result
is that at sensitivity 1.0, the scale of the whole trackpad
corresponds to the scale of the whole screen (so for example moving
the pointer from the very LHS to the very RHS of the screen can be
achieved by moving a finger from the very LHS to the very RHS of the
trackpad).

On some modern machines the resolution of the screen is much higher
than the resolution of the trackpad.  When this occurs, due to
rounding error, it can be impossible to reach the bottom and right
edges of the screen.  This is because even a 1-unit movement on the
trackpad is multipled by a >1-pixel pointer movement, and pointer
movements which would take the pointer off the screen are ignored.
(Arguably this is some kind of bug.)  In any case the user will
probably want to be able to control the pointer position with 1-pixel
accuracy.

This requires mtrack to specify a higher resolution.  Otherwise, the
fact that the values provided by mtrack to xf86 are integers means
that attempts to set the sensitivity to values < 1.0 are not properly
effective - resulting in "lumpy" response.

Fix this as follows:

 * Split sensitivity_val into sensitivity_big and _smalldiv,
   both >= 1.0, such that sensitivity_big/sensitivity_smalldiv is the
   specified sensitivity.

 * Multiply the size we tell xf86 by sensitivity_smalldiv.

As a result, when sensitivity is < 1.0, instead of scaling down
motions (resulting in unwanted rounding), we scale up the nominal size
(resulting in a lower scaling factor being applied by xf86).

When the sensitivity is > 1.0, everything behaves as before.

There is no change to the visible configuration.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
driver/mtrack.c
include/mconfig.h
src/gestures.c
src/mconfig.c

index 6bf1821bf3a2ac1f6685e5eae7bf5cc966fbcb8b..abc83c92f0bb8e9b9abf12d97406d8138111f39a 100644 (file)
@@ -133,8 +133,8 @@ static int device_init(DeviceIntPtr dev, LocalDevicePtr local)
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
                                   axes_labels[0],
 #endif
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
                                   axes_labels[0],
 #endif
-                                  mt->caps.abs[MTDEV_POSITION_X].minimum,
-                                  mt->caps.abs[MTDEV_POSITION_X].maximum,
+                                  mt->caps.abs[MTDEV_POSITION_X].minimum * mt->cfg.sensitivity_smalldiv,
+                                  mt->caps.abs[MTDEV_POSITION_X].maximum * mt->cfg.sensitivity_smalldiv,
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
                                   1, 0, 1, Absolute);
 #else
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
                                   1, 0, 1, Absolute);
 #else
@@ -145,8 +145,8 @@ static int device_init(DeviceIntPtr dev, LocalDevicePtr local)
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
                                   axes_labels[1],
 #endif
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
                                   axes_labels[1],
 #endif
-                                  mt->caps.abs[MTDEV_POSITION_Y].minimum,
-                                  mt->caps.abs[MTDEV_POSITION_Y].maximum,
+                                  mt->caps.abs[MTDEV_POSITION_Y].minimum * mt->cfg.sensitivity_smalldiv,
+                                  mt->caps.abs[MTDEV_POSITION_Y].maximum * mt->cfg.sensitivity_smalldiv,
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
                                   1, 0, 1, Absolute);
 #else
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
                                   1, 0, 1, Absolute);
 #else
index fa446351e337468772e3f66cce176ca137b36e7d..9912f14fe9151a2f17376853cef569323343927b 100644 (file)
@@ -165,14 +165,15 @@ struct MConfig {
        int drag_timeout;               // How long to wait for a move after tapping? > 0
        int drag_wait;                  // How long to wait before triggering button down? >= 0
        int drag_dist;                  // How far is the finger allowed to move during wait time? >= 0
        int drag_timeout;               // How long to wait for a move after tapping? > 0
        int drag_wait;                  // How long to wait before triggering button down? >= 0
        int drag_dist;                  // How far is the finger allowed to move during wait time? >= 0
-       double sensitivity_val;         // Mouse movement multiplier. >= 0
+       double sensitivity_big;         // Mouse movement multiplier. >= 1.0        } real sensitivity is
+       double sensitivity_smalldiv;    // Mouse movement divisor.    >= 1.0        }   big * smalldiv
 };
 
 /* Load the MConfig struct with its defaults.
  */
 void mconfig_defaults(struct MConfig* cfg);
 
 };
 
 /* Load the MConfig struct with its defaults.
  */
 void mconfig_defaults(struct MConfig* cfg);
 
-/* Set and read ->sensitivity_val
+/* Set and read ->sensitivity_big and _small.
  *
  * Configuration code must always use these get/set functions.
  *
  *
  * Configuration code must always use these get/set functions.
  *
index af6d42cc97f89f225e62aa1a3d70b409ad6dae0f..5ee61181ff539e2d8b63f72454311b121b84c8e3 100644 (file)
@@ -414,8 +414,8 @@ static void trigger_move(struct Gestures* gs,
 {
        if ((gs->move_type == GS_MOVE || !timercmp(&gs->time, &gs->move_wait, <)) && (dx != 0 || dy != 0)) {
                if (trigger_drag_start(gs, cfg, dx, dy)) {
 {
        if ((gs->move_type == GS_MOVE || !timercmp(&gs->time, &gs->move_wait, <)) && (dx != 0 || dy != 0)) {
                if (trigger_drag_start(gs, cfg, dx, dy)) {
-                       gs->move_dx = (int)(dx*cfg->sensitivity_val);
-                       gs->move_dy = (int)(dy*cfg->sensitivity_val);
+                       gs->move_dx = (int)(dx*cfg->sensitivity_big);
+                       gs->move_dy = (int)(dy*cfg->sensitivity_big);
                        gs->move_type = GS_MOVE;
                        gs->move_dist = 0;
                        gs->move_dir = TR_NONE;
                        gs->move_type = GS_MOVE;
                        gs->move_dist = 0;
                        gs->move_dir = TR_NONE;
index ca2970130d0edde754922a63c17e63f417451e44..eeaae53854ecb4394cfad0e0272ef21b122fb130 100644 (file)
 
 void mconfig_set_sensitivity(struct MConfig *cfg, double sensitivity)
 {
 
 void mconfig_set_sensitivity(struct MConfig *cfg, double sensitivity)
 {
-       cfg->sensitivity_val = sensitivity;
+       if (sensitivity >= 1.0) {
+               cfg->sensitivity_big = sensitivity;
+               cfg->sensitivity_smalldiv = 1.0;
+       } else {
+               cfg->sensitivity_big = 1.0;
+               cfg->sensitivity_smalldiv = 1.0 / sensitivity;
+       }
 }
 
 double mconfig_get_sensitivity(const struct MConfig * cfg)
 {
 }
 
 double mconfig_get_sensitivity(const struct MConfig * cfg)
 {
-       return cfg->sensitivity_val;
+       return cfg->sensitivity_big / cfg->sensitivity_smalldiv;
 }
 
 void mconfig_defaults(struct MConfig* cfg)
 }
 
 void mconfig_defaults(struct MConfig* cfg)