summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreenscreener <honzikcernoh@gmail.com>2022-07-24 15:02:46 +0200
committerPeter Hutterer <peter.hutterer@who-t.net>2022-11-24 08:52:12 +1000
commitfe923e927a8ddf4d2e82ef4757c885b06d47fa03 (patch)
tree2ba9d5bdfe49550448fa902b08bbaed8c1553d99
parent2a9e5953f89a7085786326e07edcb53ad821aace (diff)
downloadxf86-input-wacom-fe923e927a8ddf4d2e82ef4757c885b06d47fa03.tar.gz
Implement smooth panscrolling
-rw-r--r--src/WacomInterface.h11
-rw-r--r--src/gwacom/wacom-device.h5
-rw-r--r--src/wcmCommon.c35
-rw-r--r--src/wcmConfig.c15
-rw-r--r--src/x11/xf86Wacom.c25
-rw-r--r--src/xf86WacomDefs.h5
-rw-r--r--test/test_wacom.py56
-rw-r--r--tools/wacom-record.c2
8 files changed, 117 insertions, 37 deletions
diff --git a/src/WacomInterface.h b/src/WacomInterface.h
index 55cde08..a0110a4 100644
--- a/src/WacomInterface.h
+++ b/src/WacomInterface.h
@@ -63,8 +63,10 @@ enum WacomAxisType {
WACOM_AXIS_WHEEL = (1 << 9), /* Artpen rotation or airbrush wheel */
WACOM_AXIS_RING = (1 << 10),
WACOM_AXIS_RING2 = (1 << 11),
+ WACOM_AXIS_SCROLL_X = (1 << 12),
+ WACOM_AXIS_SCROLL_Y = (1 << 13),
- _WACOM_AXIS_LAST = WACOM_AXIS_RING2,
+ _WACOM_AXIS_LAST = WACOM_AXIS_SCROLL_Y,
};
typedef struct {
@@ -77,6 +79,7 @@ typedef struct {
int throttle;
int wheel;
int ring, ring2;
+ int scroll_x, scroll_y;
} WacomAxisData;
@@ -163,6 +166,8 @@ static inline void wcmAxisSet(WacomAxisData *data,
case WACOM_AXIS_WHEEL: data->wheel = value; break;
case WACOM_AXIS_RING: data->ring = value; break;
case WACOM_AXIS_RING2: data->ring2 = value; break;
+ case WACOM_AXIS_SCROLL_X: data->scroll_x = value; break;
+ case WACOM_AXIS_SCROLL_Y: data->scroll_y = value; break;
default:
abort();
}
@@ -187,6 +192,8 @@ static inline bool wcmAxisGet(const WacomAxisData *data,
case WACOM_AXIS_WHEEL: *value_out = data->wheel; break;
case WACOM_AXIS_RING: *value_out = data->ring; break;
case WACOM_AXIS_RING2: *value_out = data->ring2; break;
+ case WACOM_AXIS_SCROLL_X: *value_out = data->scroll_x; break;
+ case WACOM_AXIS_SCROLL_Y: *value_out = data->scroll_y; break;
default:
abort();
}
@@ -224,6 +231,8 @@ static inline const char* wcmAxisName(enum WacomAxisType which)
case WACOM_AXIS_WHEEL: return "wheel";
case WACOM_AXIS_RING: return "ring";
case WACOM_AXIS_RING2: return "ring2";
+ case WACOM_AXIS_SCROLL_X: return "scroll-x";
+ case WACOM_AXIS_SCROLL_Y: return "scroll-y";
default:
abort();
}
diff --git a/src/gwacom/wacom-device.h b/src/gwacom/wacom-device.h
index 546fd9f..659ed5e 100644
--- a/src/gwacom/wacom-device.h
+++ b/src/gwacom/wacom-device.h
@@ -108,8 +108,10 @@ typedef enum {
WAXIS_WHEEL = (1 << 9),
WAXIS_RING = (1 << 10),
WAXIS_RING2 = (1 << 11),
+ WAXIS_SCROLL_X = (1 << 12),
+ WAXIS_SCROLL_Y = (1 << 13),
- _WAXIS_LAST = WAXIS_RING2,
+ _WAXIS_LAST = WAXIS_SCROLL_Y,
} WacomEventAxis;
/* The pointer argument to all the event signals. If the mask is set for
@@ -124,6 +126,7 @@ typedef struct {
int throttle;
int wheel;
int ring, ring2;
+ int scroll_x, scroll_y;
} WacomEventData;
#define WACOM_TYPE_EVENT_DATA (wacom_event_data_get_type())
diff --git a/src/wcmCommon.c b/src/wcmCommon.c
index 44bffb5..20cfaac 100644
--- a/src/wcmCommon.c
+++ b/src/wcmCommon.c
@@ -95,38 +95,17 @@ Bool wcmDevSwitchModeCall(WacomDevicePtr priv, Bool absolute)
return TRUE;
}
-
-static int wcmButtonPerNotch(WacomDevicePtr priv, int value, int threshold, int btn_positive, int btn_negative)
-{
- int mode = is_absolute(priv);
- int notches = value / threshold;
- int button = (notches > 0) ? btn_positive : btn_negative;
- int i;
- WacomAxisData axes = {0};
-
- for (i = 0; i < abs(notches); i++) {
- wcmEmitButton(priv, mode, button, 1, &axes);
- wcmEmitButton(priv, mode, button, 0, &axes);
- }
-
- return value % threshold;
-}
-
static void wcmPanscroll(WacomDevicePtr priv, const WacomDeviceState *ds, int x, int y)
{
WacomCommonPtr common = priv->common;
int threshold = common->wcmPanscrollThreshold;
- int *accumulated_x, *accumulated_y;
int delta_x, delta_y;
if (!(priv->flags & SCROLLMODE_FLAG) || !(ds->buttons & 1))
return;
- /* Tip has gone down down; store state for dragging */
+ /* Tip has gone down down; don't send pan event yet */
if (!(priv->oldState.buttons & 1)) {
- priv->wcmPanscrollState = *ds;
- priv->wcmPanscrollState.x = 0;
- priv->wcmPanscrollState.y = 0;
return;
}
@@ -139,15 +118,13 @@ static void wcmPanscroll(WacomDevicePtr priv, const WacomDeviceState *ds, int x,
delta_y = (y - priv->oldState.y);
}
- accumulated_x = &priv->wcmPanscrollState.x;
- accumulated_y = &priv->wcmPanscrollState.y;
- *accumulated_x += delta_x;
- *accumulated_y += delta_y;
- DBG(6, priv, "pan x = %d, pan y = %d\n", *accumulated_x, *accumulated_y);
+ DBG(6, priv, "pan x = %d, pan y = %d\n", delta_x, delta_y);
- *accumulated_x = wcmButtonPerNotch(priv, *accumulated_x, threshold, 6, 7);
- *accumulated_y = wcmButtonPerNotch(priv, *accumulated_y, threshold, 4, 5);
+ WacomAxisData axes = {0};
+ wcmAxisSet(&axes, WACOM_AXIS_SCROLL_X, -delta_x * PANSCROLL_INCREMENT/threshold);
+ wcmAxisSet(&axes, WACOM_AXIS_SCROLL_Y, -delta_y * PANSCROLL_INCREMENT/threshold);
+ wcmEmitMotion(priv, FALSE, &axes);
}
void wcmResetButtonAction(WacomDevicePtr priv, int button)
diff --git a/src/wcmConfig.c b/src/wcmConfig.c
index 757492d..7c0483f 100644
--- a/src/wcmConfig.c
+++ b/src/wcmConfig.c
@@ -99,7 +99,7 @@ WacomDevicePtr wcmAllocate(void *frontend, const char *name)
priv->touch_timer = wcmTimerNew();
/* reusable valuator mask */
- priv->valuator_mask = valuator_mask_new(7);
+ priv->valuator_mask = valuator_mask_new(8);
return priv;
@@ -1220,6 +1220,14 @@ static int wcmInitAxes(WacomDevicePtr priv)
wcmInitAxis(priv, WACOM_AXIS_RING2, min, max, res);
}
+ if (IsPen(priv)) {
+ /* seventh valuator: scroll_x */
+ wcmInitAxis(priv, WACOM_AXIS_SCROLL_X, -1, -1, 0);
+
+ /* eighth valuator: scroll_y */
+ wcmInitAxis(priv, WACOM_AXIS_SCROLL_Y, -1, -1, 0);
+ }
+
return TRUE;
}
@@ -1232,7 +1240,7 @@ Bool wcmDevInit(WacomDevicePtr priv)
if (priv->common->wcmModel->DetectConfig)
priv->common->wcmModel->DetectConfig (priv);
- nbaxes = priv->naxes; /* X, Y, Pressure, Tilt-X, Tilt-Y, Wheel */
+ nbaxes = priv->naxes; /* X, Y, Pressure, Tilt-X, Tilt-Y, Wheel, Scroll-X, Scroll-Y */
if (!nbaxes || nbaxes > 6)
nbaxes = priv->naxes = 6;
nbbuttons = priv->nbuttons; /* Use actual number of buttons, if possible */
@@ -1240,6 +1248,9 @@ Bool wcmDevInit(WacomDevicePtr priv)
if (IsPad(priv) && TabletHasFeature(priv->common, WCM_DUALRING))
nbaxes = priv->naxes = nbaxes + 1; /* ABS wheel 2 */
+ if (IsPen(priv))
+ nbaxes = priv->naxes = nbaxes + 2; /* Scroll X and Y */
+
/* if more than 3 buttons, offset by the four scroll buttons,
* otherwise, alloc 7 buttons for scroll wheel. */
nbbuttons = min(max(nbbuttons + 4, 7), WCM_MAX_BUTTONS);
diff --git a/src/x11/xf86Wacom.c b/src/x11/xf86Wacom.c
index 4cabe36..9c71897 100644
--- a/src/x11/xf86Wacom.c
+++ b/src/x11/xf86Wacom.c
@@ -388,6 +388,8 @@ valuatorNumber(enum WacomAxisType which)
case WACOM_AXIS_WHEEL: pos = 5; break;
case WACOM_AXIS_RING: pos = 5; break;
case WACOM_AXIS_RING2: pos = 6; break;
+ case WACOM_AXIS_SCROLL_X: pos = 6; break;
+ case WACOM_AXIS_SCROLL_Y: pos = 7; break;
break;
default:
abort();
@@ -518,15 +520,28 @@ void wcmInitAxis(WacomDevicePtr priv, enum WacomAxisType type,
break;
case WACOM_AXIS_RING2:
break;
+ case WACOM_AXIS_SCROLL_X:
+ label = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
+ break;
+ case WACOM_AXIS_SCROLL_Y:
+ label = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
+ break;
+
default:
abort();
}
index = valuatorNumber(type);
InitValuatorAxisStruct(pInfo->dev, index,
- label,
- min, max, res, min_res, max_res,
- Absolute);
+ label,
+ min, max, res, min_res, max_res,
+ Absolute);
+
+ if (type == WACOM_AXIS_SCROLL_X)
+ SetScrollValuator(pInfo->dev, index, SCROLL_TYPE_HORIZONTAL, PANSCROLL_INCREMENT, 0);
+ else if (type == WACOM_AXIS_SCROLL_Y)
+ SetScrollValuator(pInfo->dev, index, SCROLL_TYPE_VERTICAL, PANSCROLL_INCREMENT, 0);
+
}
bool wcmInitButtons(WacomDevicePtr priv, unsigned int nbuttons)
@@ -1119,7 +1134,7 @@ valuator_mask_get(const ValuatorMask *mask, int valuator)
TEST_CASE(test_convert_axes)
{
WacomAxisData axes = {0};
- ValuatorMask *mask = valuator_mask_new(7);
+ ValuatorMask *mask = valuator_mask_new(8);
convertAxes(&axes, mask);
assert(valuator_mask_num_valuators(mask) == 0);
@@ -1165,6 +1180,7 @@ TEST_CASE(test_convert_axes)
assert(valuator_mask_isset(mask, 5));
assert(valuator_mask_get(mask, 5) == 2);
assert(!valuator_mask_isset(mask, 6));
+ assert(!valuator_mask_isset(mask, 7));
memset(&axes, 0, sizeof(axes));
valuator_mask_zero(mask);
@@ -1195,6 +1211,7 @@ TEST_CASE(test_convert_axes)
assert(valuator_mask_get(mask, 5) == 2);
assert(!valuator_mask_isset(mask, 6));
assert(!valuator_mask_isset(mask, 7));
+ assert(!valuator_mask_isset(mask, 8));
free(mask);
}
diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h
index df21856..92c4d91 100644
--- a/src/xf86WacomDefs.h
+++ b/src/xf86WacomDefs.h
@@ -68,6 +68,11 @@
#define BTN_STYLUS3 0x149
#endif
+/* This value is arbitrary, but low enough values can cause integer division to round
+ * non-zero numbers to zero. See https://github.com/linuxwacom/xf86-input-wacom/pull/222#discussion_r927920625.
+ */
+#define PANSCROLL_INCREMENT 0xffff
+
/******************************************************************************
* Forward Declarations
*****************************************************************************/
diff --git a/test/test_wacom.py b/test/test_wacom.py
index 26a01aa..19999ac 100644
--- a/test/test_wacom.py
+++ b/test/test_wacom.py
@@ -327,4 +327,60 @@ def test_axis_updates_wheel(mainloop, opts, stylus_type):
assert first_wheel == current_wheel
+def test_scroll(mainloop, opts):
+ """
+ Check panscrolling works correctly
+ """
+ dev = Device.from_name("PTH660", "Pen")
+ opts["PanScrollThreshold"] = "150"
+
+ prox_in = [
+ Sev("ABS_X", 50),
+ Sev("ABS_Y", 50),
+ Sev("BTN_TOOL_PEN", 1),
+ Sev("SYN_REPORT", 0),
+ ]
+
+ prox_out = [
+ Sev("BTN_TOOL_PEN", 0),
+ Sev("SYN_REPORT", 0),
+ ]
+
+ press_button2 = [
+ Sev("BTN_STYLUS", 1),
+ Sev("SYN_REPORT", 0),
+ ]
+
+ touchdown_pen = [
+ Sev("BTN_TOUCH", 1),
+ Sev("ABS_PRESSURE", 20),
+ Sev("SYN_REPORT", 0),
+ ]
+
+ move_pen_x = [Sev("ABS_X", 75), Sev("SYN_REPORT", 0)]
+
+ up_pen = [Sev("BTN_TOUCH", 0), Sev("ABS_PRESSURE", 0), Sev("SYN_REPORT", 0)]
+
+ depress_button2 = [Sev("BTN_STYLUS", 0), Sev("SYN_REPORT", 0)]
+
+ monitor = Monitor.new_from_device(dev, opts)
+ monitor.wacom_device.set_runtime_option("PanButton", "2")
+
+ monitor.write_events(prox_in)
+ monitor.write_events(press_button2)
+ monitor.write_events(touchdown_pen) # Pen touchdown
+ monitor.write_events(move_pen_x) # Move pen 25% towards positive x
+ monitor.write_events(up_pen) # Pen up
+ monitor.write_events(depress_button2) # Depress button2
+ monitor.write_events(prox_out)
+
+ mainloop.run()
+ have_we_scrolled = False
+ for event in monitor.events:
+ if event.axes.scroll_x != 0:
+ assert event.axes.scroll_x == -1223320
+ have_we_scrolled = True
+ assert have_we_scrolled
+
+
# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/tools/wacom-record.c b/tools/wacom-record.c
index 395282b..8b1cf77 100644
--- a/tools/wacom-record.c
+++ b/tools/wacom-record.c
@@ -233,6 +233,8 @@ static void device_added(WacomDriver *driver, WacomDevice *device)
case WAXIS_WHEEL: typestr = "wheel"; break;
case WAXIS_RING: typestr = "ring"; break;
case WAXIS_RING2: typestr = "ring2"; break;
+ case WAXIS_SCROLL_X: typestr = "scroll_x"; break;
+ case WAXIS_SCROLL_Y: typestr = "scroll_y"; break;
}
printf(" - {type: %-12s, range: [%5d, %5d], resolution: %5d}\n",