From e1a7f4bb5333b0271d29f785eb55f1c3273e626a Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 5 May 2015 14:18:54 +1000
Subject: [PATCH] dix: Add unaccelerated valuators to the ValuatorMask

Allows a mask to carry both accelerated and unaccelerated motion at the same
time.

This is required for xf86-input-libinput where the pointer acceleration
happens in libinput already, but parts of the server, specifically raw events
and DGA rely on device-specific unaccelerated data.

To ease integration add this as a second set to the ValuatorMask rather than
extending all APIs to carry a second, possibly NULL set of valuators.

Note that a valuator mask should only be used in either accel/unaccel or
standard mode at any time. Switching requires either a valuator_mask_zero()
call or unsetting all valuators one-by-one. Trying to mix the two will produce
a warning.

The server has a shortcut for changing a mask with the
valuator_mask_drop_unaccelerated() call. This saves us from having to loop
through all valuators on every event, we can just drop the bits we know we
don't want.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
 dix/inpututils.c               | 82 +++++++++++++++++++++++++++++++++++++++---
 hw/xfree86/common/xf86Module.h |  2 +-
 include/input.h                | 15 ++++++++
 include/inpututils.h           |  2 ++
 4 files changed, 95 insertions(+), 6 deletions(-)

diff --git a/dix/inpututils.c b/dix/inpututils.c
index 5c2a32d..1363988 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -505,11 +505,8 @@ valuator_mask_isset(const ValuatorMask *mask, int valuator)
     return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator);
 }
 
-/**
- * Set the valuator to the given floating-point data.
- */
-void
-valuator_mask_set_double(ValuatorMask *mask, int valuator, double data)
+static inline void
+_valuator_mask_set_double(ValuatorMask *mask, int valuator, double data)
 {
     mask->last_bit = max(valuator, mask->last_bit);
     SetBit(mask->mask, valuator);
@@ -517,6 +514,17 @@ valuator_mask_set_double(ValuatorMask *mask, int valuator, double data)
 }
 
 /**
+ * Set the valuator to the given floating-point data.
+ */
+void
+valuator_mask_set_double(ValuatorMask *mask, int valuator, double data)
+{
+    BUG_WARN_MSG(mask->has_unaccelerated,
+                 "Do not mix valuator types, zero mask first\n");
+    _valuator_mask_set_double(mask, valuator, data);
+}
+
+/**
  * Set the valuator to the given integer data.
  */
 void
@@ -594,11 +602,15 @@ valuator_mask_unset(ValuatorMask *mask, int valuator)
 
         ClearBit(mask->mask, valuator);
         mask->valuators[valuator] = 0.0;
+        mask->unaccelerated[valuator] = 0.0;
 
         for (i = 0; i <= mask->last_bit; i++)
             if (valuator_mask_isset(mask, i))
                 lastbit = max(lastbit, i);
         mask->last_bit = lastbit;
+
+        if (mask->last_bit == -1)
+            mask->has_unaccelerated = FALSE;
     }
 }
 
@@ -611,6 +623,66 @@ valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src)
         valuator_mask_zero(dest);
 }
 
+Bool
+valuator_mask_has_unaccelerated(const ValuatorMask *mask)
+{
+    return mask->has_unaccelerated;
+}
+
+void
+valuator_mask_drop_unaccelerated(ValuatorMask *mask)
+{
+    memset(mask->unaccelerated, 0, sizeof(mask->unaccelerated));
+    mask->has_unaccelerated = FALSE;
+}
+
+/**
+ * Set both accelerated and unaccelerated value for this mask.
+ */
+void
+valuator_mask_set_unaccelerated(ValuatorMask *mask,
+                                int valuator,
+                                double accel,
+                                double unaccel)
+{
+    BUG_WARN_MSG(mask->last_bit != -1 && !mask->has_unaccelerated,
+                 "Do not mix valuator types, zero mask first\n");
+    _valuator_mask_set_double(mask, valuator, accel);
+    mask->has_unaccelerated = TRUE;
+    mask->unaccelerated[valuator] = unaccel;
+}
+
+double
+valuator_mask_get_accelerated(const ValuatorMask *mask,
+                              int valuator)
+{
+    return valuator_mask_get_double(mask, valuator);
+}
+
+double
+valuator_mask_get_unaccelerated(const ValuatorMask *mask,
+                                int valuator)
+{
+    return mask->unaccelerated[valuator];
+}
+
+Bool
+valuator_mask_fetch_unaccelerated(const ValuatorMask *mask,
+                                  int valuator,
+                                  double *accel,
+                                  double *unaccel)
+{
+    if (valuator_mask_isset(mask, valuator)) {
+        if (accel)
+            *accel = valuator_mask_get_accelerated(mask, valuator);
+        if (unaccel)
+            *unaccel = valuator_mask_get_unaccelerated(mask, valuator);
+        return TRUE;
+    }
+    else
+        return FALSE;
+}
+
 int
 CountBits(const uint8_t * mask, int len)
 {
diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index e68fe9c..6133641 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -81,7 +81,7 @@ typedef enum {
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 4)
 #define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(19, 0)
-#define ABI_XINPUT_VERSION	SET_ABI_VERSION(21, 0)
+#define ABI_XINPUT_VERSION	SET_ABI_VERSION(21, 1)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(9, 0)
 #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 6)
 
diff --git a/include/input.h b/include/input.h
index bf22dc7..0a4c4f7 100644
--- a/include/input.h
+++ b/include/input.h
@@ -674,6 +674,21 @@ extern _X_EXPORT Bool valuator_mask_fetch(const ValuatorMask *mask,
 extern _X_EXPORT Bool valuator_mask_fetch_double(const ValuatorMask *mask,
                                                  int valnum, double *val);
 
+extern _X_EXPORT Bool valuator_mask_has_unaccelerated(const ValuatorMask *mask);
+extern _X_EXPORT void valuator_mask_set_unaccelerated(ValuatorMask *mask,
+                                                      int valuator,
+                                                      double accel,
+                                                      double unaccel);
+extern _X_EXPORT double valuator_mask_get_accelerated(const ValuatorMask *mask,
+                                                      int valuator);
+extern _X_EXPORT double valuator_mask_get_unaccelerated(const ValuatorMask *mask,
+                                                        int valuator);
+extern _X_EXPORT Bool valuator_mask_fetch_unaccelerated(const ValuatorMask *mask,
+                                                        int valuator,
+                                                        double *accel,
+                                                        double *unaccel);
+extern _X_HIDDEN void valuator_mask_drop_unaccelerated(ValuatorMask *mask);
+
 /* InputOption handling interface */
 extern _X_EXPORT InputOption *input_option_new(InputOption *list,
                                                const char *key,
diff --git a/include/inpututils.h b/include/inpututils.h
index 53c96ba..4e90815 100644
--- a/include/inpututils.h
+++ b/include/inpututils.h
@@ -36,8 +36,10 @@ extern Mask event_filters[MAXDEVICES][MAXEVENTS];
 
 struct _ValuatorMask {
     int8_t last_bit;            /* highest bit set in mask */
+    int8_t has_unaccelerated;
     uint8_t mask[(MAX_VALUATORS + 7) / 8];
     double valuators[MAX_VALUATORS];    /* valuator data */
+    double unaccelerated[MAX_VALUATORS];    /* valuator data */
 };
 
 extern void verify_internal_event(const InternalEvent *ev);
-- 
2.4.1

