Input: update input_mt_report_pointer_emulation to support hovering
authorKT Liao <kt.liao@emc.com.tw>
Fri, 20 May 2016 00:38:07 +0000 (17:38 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Wed, 1 Jun 2016 21:21:10 +0000 (14:21 -0700)
For devices that are incapable of reporting per-contact distance and can
only report ABS_DISTANCE, just distance is not enough for upper layers of
OS to determine whether contact is leaving the area or if it is continuing
hovering, we need BTN_TOOL_FINGER for that:

                                   Contact State
                    Inactive          Hovering            Active
                   (far away)    (inside hover area)  (touching surface)
BTN_TOUCH              0                 0                   1
BTN_TOOL_FINGER        0                 1                   1
ABS_DISTANCE          N/A                1                   0

Signed-off-by: KT Liao <kt.liao@emc.com.tw>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/input-mt.c

index 54fce56c80236808d5a6eb02fa6c8d17ebb76415..a1bbec9cda8d45e66274b4e287d068d1dcd9ca1c 100644 (file)
@@ -218,8 +218,23 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
        }
 
        input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
-       if (use_count)
+
+       if (use_count) {
+               if (count == 0 &&
+                   !test_bit(ABS_MT_DISTANCE, dev->absbit) &&
+                   test_bit(ABS_DISTANCE, dev->absbit) &&
+                   input_abs_get_val(dev, ABS_DISTANCE) != 0) {
+                       /*
+                        * Force reporting BTN_TOOL_FINGER for devices that
+                        * only report general hover (and not per-contact
+                        * distance) when contact is in proximity but not
+                        * on the surface.
+                        */
+                       count = 1;
+               }
+
                input_mt_report_finger_count(dev, count);
+       }
 
        if (oldest) {
                int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);