From ad11a9da15d4cbef62f4ec1c19a6279ef21710f3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 25 Jul 2022 12:30:14 +1000 Subject: [PATCH 01/53] Remove a comment referring to the wrong function The function moved away in e4ea35d56aec59a5de0ef3d9282fdd796d89e6ad, let's drop this comment. Signed-off-by: Peter Hutterer --- src/x11/xf86WacomProperties.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/x11/xf86WacomProperties.c b/src/x11/xf86WacomProperties.c index a27ce1f7..6401a3b5 100644 --- a/src/x11/xf86WacomProperties.c +++ b/src/x11/xf86WacomProperties.c @@ -37,10 +37,6 @@ static int wcmSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr pr static int wcmGetProperty(DeviceIntPtr dev, Atom property); static int wcmDeleteProperty(DeviceIntPtr dev, Atom property); -/***************************************************************************** -* wcmDevSwitchMode -- -*****************************************************************************/ - static Atom prop_devnode; static Atom prop_rotation; static Atom prop_tablet_area; From 18ed7697e3049943e3bfef46af6c647b2d93ed8f Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Tue, 19 Jul 2022 14:01:35 -0700 Subject: [PATCH 02/53] Don't report error when waiting for serial number For some devices, such as AES pens, serial number is 0 when tool comes into proximity. That means serial number was not ready. It is a known state. All we needed is to wait for the non-zero serial number. Don't report it through W_ERROR. Signed-off-by: Ping Cheng --- src/wcmUSB.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/wcmUSB.c b/src/wcmUSB.c index 99c199b8..b7b3d060 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -1020,11 +1020,18 @@ static void usbParseMscEvent(WacomDevicePtr priv, } else { - /* we don't report serial numbers for some tools but we never report - * a serial number with a value of 0 - if that happens drop the - * whole frame */ - wcmLogSafe(priv, W_ERROR, "%s: usbParse: Ignoring event from invalid serial 0\n", - priv->name); + /* If this is the first time to set wcmLastToolSerial and serial + * number is 0, it means the value is not ready. Just wait for a + * non-zero one. However, if we are in the middle of an established + * established reporting process, serial number should never be 0. + * Report the error and show the serial number that we expect. + * + * In both cases, we drop the whole frame. + */ + if (private->wcmLastToolSerial) + wcmLogSafe(priv, W_ERROR, + "%s: usbParse: Ignoring packet for serial=0. It should be %ud \n", + priv->name, private->wcmLastToolSerial); usbResetEventCounter(private); } } From 23c46706f12982c3baaa03b3b8f53ea72679a136 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 26 Aug 2022 15:02:16 -0700 Subject: [PATCH 03/53] Bring two finger right-click function back Patch 65b7c37 fixed spurious right-clicks by setting wcmGestureMode back to GESTURE_CANCEL_MODE immediately when there is less than two fingers on the tablet, if the wcmGestureMode was in SCROLL_MODE or ZOOM_MODE. However, it narrowed wcmFingerTapToClick() rotine to LAG_MODE, which removed the opportunity for the routine to executed. Revert that. Fixes: https://github.com/linuxwacom/xf86-input-wacom/commit/65b7c37f0fac5cdd03ff7f977124148d0bdf4be8 (Prevent spurious right-clicks at the end of very short scroll and zoom gestures) Signed-off-by: Ping Cheng --- src/wcmTouchFilter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wcmTouchFilter.c b/src/wcmTouchFilter.c index 23123e31..08b8b0d5 100644 --- a/src/wcmTouchFilter.c +++ b/src/wcmTouchFilter.c @@ -542,7 +542,7 @@ void wcmGestureFilter(WacomDevicePtr priv, unsigned int touch_id) goto ret; } - if ((common->wcmGestureMode & GESTURE_LAG_MODE) && touch_id == 1) + if (!(common->wcmGestureMode & (GESTURE_SCROLL_MODE | GESTURE_ZOOM_MODE)) && touch_id == 1) wcmFingerTapToClick(priv); /* Change mode happens only when both fingers are out */ From 1aaa36753c1008733b62cea5f60088ddbddff1e8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 31 Aug 2022 11:35:53 +1000 Subject: [PATCH 04/53] Remove useless Wacom action name setting Copy/paste error from when this as lifted from the properties code to the core driver code, in the commits leading up to 5326fd126042684338dfb662f48ba2e27be7fa5a. Signed-off-by: Peter Hutterer --- src/wcmCommon.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/wcmCommon.c b/src/wcmCommon.c index b39a43a2..44bffb5c 100644 --- a/src/wcmCommon.c +++ b/src/wcmCommon.c @@ -154,9 +154,7 @@ void wcmResetButtonAction(WacomDevicePtr priv, int button) { WacomAction new_action = {}; int x11_button = priv->button_default[button]; - char name[64]; - sprintf(name, "Wacom button action %d", button); wcmActionSet(&new_action, 0, AC_BUTTON | AC_KEYBTNPRESS | x11_button); wcmActionCopy(&priv->key_actions[button], &new_action); } @@ -164,9 +162,7 @@ void wcmResetButtonAction(WacomDevicePtr priv, int button) void wcmResetStripAction(WacomDevicePtr priv, int index) { WacomAction new_action = {}; - char name[64]; - sprintf(name, "Wacom strip action %d", index); wcmActionSet(&new_action, 0, AC_BUTTON | AC_KEYBTNPRESS | (priv->strip_default[index])); wcmActionSet(&new_action, 1, AC_BUTTON | (priv->strip_default[index])); wcmActionCopy(&priv->strip_actions[index], &new_action); @@ -175,9 +171,7 @@ void wcmResetStripAction(WacomDevicePtr priv, int index) void wcmResetWheelAction(WacomDevicePtr priv, int index) { WacomAction new_action = {}; - char name[64]; - sprintf(name, "Wacom wheel action %d", index); wcmActionSet(&new_action, 0, AC_BUTTON | AC_KEYBTNPRESS | (priv->wheel_default[index])); wcmActionSet(&new_action, 1, AC_BUTTON | (priv->wheel_default[index])); wcmActionCopy(&priv->wheel_actions[index], &new_action); From 8e4a77bc28970d23da80838c195550cad4ef8e05 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 1 Sep 2022 15:31:47 +1000 Subject: [PATCH 05/53] x11: de-duplicate the valuator number assignment Let's add a helper function for this so we can't mess this up. Signed-off-by: Peter Hutterer --- src/x11/xf86Wacom.c | 58 ++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/x11/xf86Wacom.c b/src/x11/xf86Wacom.c index fca6fc86..aebf27a6 100644 --- a/src/x11/xf86Wacom.c +++ b/src/x11/xf86Wacom.c @@ -370,6 +370,32 @@ void wcmEmitKeycode(WacomDevicePtr priv, int keycode, int state) xf86PostKeyboardEvent (keydev, keycode, state); } +static inline int +valuatorNumber(enum WacomAxisType which) +{ + int pos; + + switch (which){ + case WACOM_AXIS_X: pos = 0; break; + case WACOM_AXIS_Y: pos = 1; break; + case WACOM_AXIS_PRESSURE: pos = 2; break; + case WACOM_AXIS_TILT_X: pos = 3; break; + case WACOM_AXIS_TILT_Y: pos = 4; break; + case WACOM_AXIS_STRIP_X: pos = 3; break; + case WACOM_AXIS_STRIP_Y: pos = 4; break; + case WACOM_AXIS_ROTATION: pos = 3; break; + case WACOM_AXIS_THROTTLE: pos = 4; break; + case WACOM_AXIS_WHEEL: pos = 5; break; + case WACOM_AXIS_RING: pos = 5; break; + case WACOM_AXIS_RING2: pos = 6; break; + break; + default: + abort(); + } + + return pos; +} + static inline void convertAxes(const WacomAxisData *axes, int *first_out, int *num_out, int valuators_out[7]) { @@ -387,24 +413,7 @@ convertAxes(const WacomAxisData *axes, int *first_out, int *num_out, int valuato continue; /* Positions need to match wcmInitAxis */ - switch (which){ - case WACOM_AXIS_X: pos = 0; break; - case WACOM_AXIS_Y: pos = 1; break; - case WACOM_AXIS_PRESSURE: pos = 2; break; - case WACOM_AXIS_TILT_X: pos = 3; break; - case WACOM_AXIS_TILT_Y: pos = 4; break; - case WACOM_AXIS_STRIP_X: pos = 3; break; - case WACOM_AXIS_STRIP_Y: pos = 4; break; - case WACOM_AXIS_ROTATION: pos = 3; break; - case WACOM_AXIS_THROTTLE: pos = 4; break; - case WACOM_AXIS_WHEEL: pos = 5; break; - case WACOM_AXIS_RING: pos = 5; break; - case WACOM_AXIS_RING2: pos = 6; break; - break; - default: - abort(); - } - + pos = valuatorNumber(which); first = min(first, pos); last = max(last, pos); valuators[pos] = value; @@ -490,51 +499,40 @@ void wcmInitAxis(WacomDevicePtr priv, enum WacomAxisType type, switch (type) { case WACOM_AXIS_X: - index = 0; label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); break; case WACOM_AXIS_Y: - index = 1; label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); break; case WACOM_AXIS_PRESSURE: - index = 2; label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE); break; case WACOM_AXIS_TILT_X: - index = 3; label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X); break; case WACOM_AXIS_TILT_Y: - index = 4; label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y); break; case WACOM_AXIS_STRIP_X: - index = 3; - break; case WACOM_AXIS_STRIP_Y: - index = 4; break; case WACOM_AXIS_ROTATION: - index = 3; label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_RZ); break; case WACOM_AXIS_THROTTLE: - index = 4; label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_THROTTLE); break; case WACOM_AXIS_WHEEL: case WACOM_AXIS_RING: - index = 5; label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_WHEEL); break; case WACOM_AXIS_RING2: - index = 6; break; default: abort(); } + index = valuatorNumber(type); InitValuatorAxisStruct(pInfo->dev, index, label, min, max, res, min_res, max_res, From 829a2d996f1a8d8a735c0eb7340797959de03ca8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 31 Aug 2022 11:56:16 +1000 Subject: [PATCH 06/53] gwacom: add support for special runtime options This is a hack to make it possible to test options that cannot be set through the xorg.conf, e.g button actions that are set through the X-specific properties interface. Expose a new function for "runtime options", though the actual option implementation needs to be handled in the gwacom wrapper code - i.e. only options explicitly supported can work. The currently supported option is "PanButton" which maps the given button to the PanScroll action. --- src/gwacom/wacom-device.c | 15 +++++++++++++++ src/gwacom/wacom-device.h | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/gwacom/wacom-device.c b/src/gwacom/wacom-device.c index 29fb9aef..87ac433a 100644 --- a/src/gwacom/wacom-device.c +++ b/src/gwacom/wacom-device.c @@ -296,6 +296,21 @@ WacomOptions *wacom_device_get_options(WacomDevice *device) return device->options; } +void wacom_device_set_runtime_option(WacomDevice *device, const char *name, const char *value) +{ + WacomDevicePtr priv = device->priv; + + wcmLog(priv, W_ERROR, "Setting special option %s=%s\n", name, value); + + if (g_str_equal(name, "PanButton")) { + guint btn = atoi(value) - 1; /* array is zero-indexed, config options use 1-indexed ones */ + assert(btn < sizeof(priv->key_actions)); + wcmActionSet(&priv->key_actions[btn], 0, AC_PANSCROLL); + } else { + wcmLog(priv, W_ERROR, ":::::::::::::::: Unsupported runtime option %s ::::::::::::::::\n", name); + } +} + /****************** Driver layer *****************/ int diff --git a/src/gwacom/wacom-device.h b/src/gwacom/wacom-device.h index 3ada1dd8..546fd9fc 100644 --- a/src/gwacom/wacom-device.h +++ b/src/gwacom/wacom-device.h @@ -197,6 +197,16 @@ WacomToolType wacom_device_get_tool_type(WacomDevice *device); */ WacomOptions *wacom_device_get_options(WacomDevice *device); +/** + * wacom_device_set_runtime_option: + * + * Some options like button actions are runtime-only and cannot be set through. + * WacomOptionx (which maps to the xorg.conf support of the driver). + * This is a hack to set some of those options, however the options + * and values supported are very specific to the implementation. + */ +void wacom_device_set_runtime_option(WacomDevice *device, const char *name, const char *value); + /* The following getters are only available after wacom_device_setup() */ int wacom_device_get_num_buttons(WacomDevice *device); From 61b7d9061b53f79b5a37a463269bb9c8d45dbe14 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 2 Nov 2022 21:55:21 -0700 Subject: [PATCH 07/53] Move wcmDeviceTypeKeys to wcmConfig.c There is only one file that needs wcmDeviceTypeKeys. Move it and make it into a static routine to simply the logic. Also, there is no value to return from this routine. It sets the types and keys to the common structure. Signed-off-by: Ping Cheng --- src/wcmConfig.c | 214 +++++++++++++++++++++++++++++++++++++++ src/wcmValidateDevice.c | 217 ---------------------------------------- src/xf86Wacom.h | 1 - 3 files changed, 214 insertions(+), 218 deletions(-) diff --git a/src/wcmConfig.c b/src/wcmConfig.c index f1d058bf..6276bbde 100644 --- a/src/wcmConfig.c +++ b/src/wcmConfig.c @@ -710,6 +710,220 @@ static inline Bool filter_test_suite(WacomDevicePtr priv) return TRUE; } +/* Choose valid types according to device ID. */ +static void wcmDeviceTypeKeys(WacomDevicePtr priv) +{ + WacomCommonPtr common = priv->common; + + priv->common->tablet_id = common->wcmDevCls->ProbeKeys(priv); + + switch (priv->common->tablet_id) + { + case 0xF8: /* Cintiq 24HDT */ + case 0xF4: /* Cintiq 24HD */ + TabletSetFeature(priv->common, WCM_DUALRING); + _fallthrough_; + case 0x34D: /* MobileStudio Pro 13 */ + case 0x34E: /* MobileStudio Pro 16 */ + case 0x398: /* MobileStudio Pro 13 */ + case 0x399: /* MobileStudio Pro 16 */ + case 0x3AA: /* MobileStudio Pro 16 */ + TabletSetFeature(priv->common, WCM_LCD); + _fallthrough_; + case 0x357: /* Intuos Pro 2 M */ + case 0x358: /* Intuos Pro 2 L */ + case 0x360: /* Intuos Pro 2 M (Bluetooth) */ + case 0x36a: /* Intuos Pro 2 L (Bluetooth) */ + case 0x392: /* Intuos Pro 2 S */ + case 0x393: /* Intuos Pro 2 S (Bluetooth) */ + case 0x314: /* Intuos Pro S */ + case 0x315: /* Intuos Pro M */ + case 0x317: /* Intuos Pro L */ + case 0x26: /* I5 */ + case 0x27: /* I5 */ + case 0x28: /* I5 */ + case 0x29: /* I5 */ + case 0x2A: /* I5 */ + case 0xB8: /* I4 */ + case 0xB9: /* I4 */ + case 0xBA: /* I4 */ + case 0xBB: /* I4 */ + case 0xBC: /* I4 */ + case 0xBD: /* I4 */ + TabletSetFeature(priv->common, WCM_ROTATION); + _fallthrough_; + /* tablets with touch ring */ + case 0x17: /* BambooFun */ + case 0x18: /* BambooFun */ + TabletSetFeature(priv->common, WCM_RING); + break; + + /* tablets support dual input */ + case 0x20: /* I1 */ + case 0x21: /* I1 */ + case 0x22: /* I1 */ + case 0x23: /* I1 */ + case 0x24: /* I1 */ + case 0x41: /* I2 */ + case 0x42: /* I2 */ + case 0x43: /* I2 */ + case 0x44: /* I2 */ + case 0x45: /* I2 */ + case 0x47: /* I2 */ + TabletSetFeature(priv->common, WCM_DUALINPUT); + break; + + /* P4 display tablets */ + case 0x30: /* PL400 */ + case 0x31: /* PL500 */ + case 0x32: /* PL600 */ + case 0x33: /* PL600SX */ + case 0x34: /* PL550 */ + case 0x35: /* PL800 */ + case 0x37: /* PL700 */ + case 0x38: /* PL510 */ + case 0x39: /* PL710 */ + case 0x3A: /* DTI520 */ + case 0xC0: /* DTF720 */ + case 0xC2: /* DTF720a */ + case 0xC4: /* DTF521 */ + case 0xC7: /* DTU1931 */ + case 0xCE: /* DTU2231 */ + case 0xF0: /* DTU1631 */ + + /* Wacom One display tablet */ + case 0x3A6: /* DTC133 */ + TabletSetFeature(priv->common, WCM_LCD); + break; + + /* tablets support menu strips */ + case 0x3F: /* CintiqV5 */ + case 0xC5: /* CintiqV5 */ + case 0xC6: /* CintiqV5 */ + case 0xCC: /* CinitqV5 */ + case 0xFA: /* Cintiq 22HD */ + case 0x5B: /* Cintiq 22HDT Pen */ + TabletSetFeature(priv->common, WCM_LCD); + _fallthrough_; + case 0xB0: /* I3 */ + case 0xB1: /* I3 */ + case 0xB2: /* I3 */ + case 0xB3: /* I3 */ + case 0xB4: /* I3 */ + case 0xB5: /* I3 */ + case 0xB7: /* I3 */ + TabletSetFeature(priv->common, WCM_STRIP | WCM_ROTATION); + break; + + case 0x100: /* TPC with MT */ + case 0x101: /* TPC with MT */ + case 0x10D: /* TPC with MT */ + case 0x116: /* TPC with 1FGT */ + case 0x12C: /* TPC */ + case 0x4001: /* TPC with MT */ + case 0x4004: /* TPC with MT (no pen on Motion) */ + case 0x5000: /* TPC with MT */ + case 0x5002: /* TPC with MT */ + case 0xE2: /* TPC with 2FGT */ + case 0xE3: /* TPC with 2FGT */ + case 0xE5: /* TPC with MT */ + case 0xE6: /* TPC with 2FGT */ + case 0x93: /* TPC with 1FGT */ + case 0x9A: /* TPC with 1FGT */ + case 0xEC: /* TPC with 1FGT */ + case 0xED: /* TPC with 1FGT */ + case 0x90: /* TPC */ + case 0x97: /* TPC */ + case 0x9F: /* TPC */ + case 0xEF: /* TPC */ + TabletSetFeature(priv->common, WCM_TPC); + break; + + case 0x304:/* Cintiq 13HD */ + case 0x307:/* Cintiq Companion Hybrid */ + case 0x30A:/* Cintiq Companion */ + case 0x325:/* Cintiq Companion 2 */ + case 0x32A:/* Cintiq 27QHD */ + case 0x32B:/* Cintiq 27QHDT Pen */ + case 0x333:/* Cintiq 13HDT Pen */ + case 0x34F:/* Cintiq Pro 13 FHD */ + case 0x350:/* Cintiq Pro 16 UHD */ + case 0x351:/* Cintiq Pro 24 */ + case 0x352:/* Cintiq Pro 32 */ + case 0x37C:/* Cintiq Pro 24 Pen-Only */ + case 0x390:/* Cintiq 16 */ + case 0x391:/* Cintiq 22 */ + case 0x396:/* DTK-1660E */ + case 0x3AE:/* Cintiq 16 */ + case 0x3B0:/* DTK-1660E */ + TabletSetFeature(priv->common, WCM_ROTATION); + _fallthrough_; + case 0xF6: /* Cintiq 24HDT Touch */ + case 0x57: /* DTK2241 */ + case 0x59: /* DTH2242 Pen */ + case 0x5D: /* DTH2242 Touch */ + case 0x5E: /* Cintiq 22HDT Touch */ + case 0x309:/* Cintiq Companion Hybrid Touch */ + case 0x30C:/* Cintiq Companion Touch */ + case 0x326:/* Cintiq Companion 2 Touch */ + case 0x32C:/* Cintiq 27QHDT Touch */ + case 0x32F:/* DTU-1031X */ + case 0x335:/* Cintiq 13HDT Touch */ + case 0x336:/* DTU-1141 */ + case 0x343:/* DTK-1651 */ + case 0x34A:/* MobileStudio Pro 13 Touch */ + case 0x34B:/* MobileStudio Pro 16 Touch */ + case 0x353:/* Cintiq Pro 13 FHD Touch */ + case 0x354:/* Cintiq Pro 13 UHD Touch */ + case 0x355:/* Cintiq Pro 24 Touch */ + case 0x356:/* Cintiq Pro 32 Touch */ + case 0x359:/* DTU-1141B */ + case 0x35A:/* DTH-1152*/ + case 0x368:/* DTH-1152 Touch */ + case 0x382:/* DTK-2451 */ + case 0x37D:/* DTH-2452 */ + case 0x37E:/* DTH-2452 Touch */ + case 0x39A:/* MobileStudio Pro 13 Touch */ + case 0x39B:/* MobileStudio Pro 16 Touch */ + case 0x3AC:/* MobileStudio Pro 16 Touch */ + TabletSetFeature(priv->common, WCM_LCD); + break; + } + + if (ISBITSET(common->wcmInputProps, INPUT_PROP_DIRECT)) + TabletSetFeature(priv->common, WCM_LCD); + + if (ISBITSET(common->wcmKeys, BTN_TOOL_PEN)) + TabletSetFeature(priv->common, WCM_PEN); + + if (ISBITSET (common->wcmKeys, BTN_0) || + ISBITSET (common->wcmKeys, BTN_FORWARD)) + { + TabletSetFeature(priv->common, WCM_PAD); + } + + /* This handles both protocol 4 and 5 meanings of wcmKeys */ + if (common->wcmProtocolLevel == WCM_PROTOCOL_4) + { + /* TRIPLETAP means 2 finger touch */ + /* DOUBLETAP without TRIPLETAP means 1 finger touch */ + if (ISBITSET(common->wcmKeys, BTN_TOOL_TRIPLETAP)) + TabletSetFeature(priv->common, WCM_2FGT); + else if (ISBITSET(common->wcmKeys, BTN_TOOL_DOUBLETAP)) + TabletSetFeature(priv->common, WCM_1FGT); + } + + if (common->wcmProtocolLevel == WCM_PROTOCOL_GENERIC) + { + /* DOUBLETAP means 2 finger touch */ + /* FINGER without DOUBLETAP means 1 finger touch */ + if (ISBITSET(common->wcmKeys, BTN_TOOL_DOUBLETAP)) + TabletSetFeature(priv->common, WCM_2FGT); + else if (ISBITSET(common->wcmKeys, BTN_TOOL_FINGER)) + TabletSetFeature(priv->common, WCM_1FGT); + } +} + /* wcmPreInit - called for each input devices with the driver set to * "wacom" */ int wcmPreInit(WacomDevicePtr priv) diff --git a/src/wcmValidateDevice.c b/src/wcmValidateDevice.c index d5a7b2b8..d1a17b14 100644 --- a/src/wcmValidateDevice.c +++ b/src/wcmValidateDevice.c @@ -212,223 +212,6 @@ Bool wcmIsAValidType(WacomDevicePtr priv, const char* type) return FALSE; } -/* Choose valid types according to device ID. */ -int wcmDeviceTypeKeys(WacomDevicePtr priv) -{ - int ret = 1; - WacomCommonPtr common = priv->common; - - priv->common->tablet_id = common->wcmDevCls->ProbeKeys(priv); - - switch (priv->common->tablet_id) - { - case 0xF8: /* Cintiq 24HDT */ - case 0xF4: /* Cintiq 24HD */ - TabletSetFeature(priv->common, WCM_DUALRING); - _fallthrough_; - case 0x34D: /* MobileStudio Pro 13 */ - case 0x34E: /* MobileStudio Pro 16 */ - case 0x398: /* MobileStudio Pro 13 */ - case 0x399: /* MobileStudio Pro 16 */ - case 0x3AA: /* MobileStudio Pro 16 */ - TabletSetFeature(priv->common, WCM_LCD); - _fallthrough_; - case 0x357: /* Intuos Pro 2 M */ - case 0x358: /* Intuos Pro 2 L */ - case 0x360: /* Intuos Pro 2 M (Bluetooth) */ - case 0x36a: /* Intuos Pro 2 L (Bluetooth) */ - case 0x392: /* Intuos Pro 2 S */ - case 0x393: /* Intuos Pro 2 S (Bluetooth) */ - case 0x314: /* Intuos Pro S */ - case 0x315: /* Intuos Pro M */ - case 0x317: /* Intuos Pro L */ - case 0x26: /* I5 */ - case 0x27: /* I5 */ - case 0x28: /* I5 */ - case 0x29: /* I5 */ - case 0x2A: /* I5 */ - case 0xB8: /* I4 */ - case 0xB9: /* I4 */ - case 0xBA: /* I4 */ - case 0xBB: /* I4 */ - case 0xBC: /* I4 */ - case 0xBD: /* I4 */ - TabletSetFeature(priv->common, WCM_ROTATION); - _fallthrough_; - /* tablets with touch ring */ - case 0x17: /* BambooFun */ - case 0x18: /* BambooFun */ - TabletSetFeature(priv->common, WCM_RING); - break; - - /* tablets support dual input */ - case 0x20: /* I1 */ - case 0x21: /* I1 */ - case 0x22: /* I1 */ - case 0x23: /* I1 */ - case 0x24: /* I1 */ - case 0x41: /* I2 */ - case 0x42: /* I2 */ - case 0x43: /* I2 */ - case 0x44: /* I2 */ - case 0x45: /* I2 */ - case 0x47: /* I2 */ - TabletSetFeature(priv->common, WCM_DUALINPUT); - break; - - /* P4 display tablets */ - case 0x30: /* PL400 */ - case 0x31: /* PL500 */ - case 0x32: /* PL600 */ - case 0x33: /* PL600SX */ - case 0x34: /* PL550 */ - case 0x35: /* PL800 */ - case 0x37: /* PL700 */ - case 0x38: /* PL510 */ - case 0x39: /* PL710 */ - case 0x3A: /* DTI520 */ - case 0xC0: /* DTF720 */ - case 0xC2: /* DTF720a */ - case 0xC4: /* DTF521 */ - case 0xC7: /* DTU1931 */ - case 0xCE: /* DTU2231 */ - case 0xF0: /* DTU1631 */ - - /* Wacom One display tablet */ - case 0x3A6: /* DTC133 */ - TabletSetFeature(priv->common, WCM_LCD); - break; - - /* tablets support menu strips */ - case 0x3F: /* CintiqV5 */ - case 0xC5: /* CintiqV5 */ - case 0xC6: /* CintiqV5 */ - case 0xCC: /* CinitqV5 */ - case 0xFA: /* Cintiq 22HD */ - case 0x5B: /* Cintiq 22HDT Pen */ - TabletSetFeature(priv->common, WCM_LCD); - _fallthrough_; - case 0xB0: /* I3 */ - case 0xB1: /* I3 */ - case 0xB2: /* I3 */ - case 0xB3: /* I3 */ - case 0xB4: /* I3 */ - case 0xB5: /* I3 */ - case 0xB7: /* I3 */ - TabletSetFeature(priv->common, WCM_STRIP | WCM_ROTATION); - break; - - case 0x100: /* TPC with MT */ - case 0x101: /* TPC with MT */ - case 0x10D: /* TPC with MT */ - case 0x116: /* TPC with 1FGT */ - case 0x12C: /* TPC */ - case 0x4001: /* TPC with MT */ - case 0x4004: /* TPC with MT (no pen on Motion) */ - case 0x5000: /* TPC with MT */ - case 0x5002: /* TPC with MT */ - case 0xE2: /* TPC with 2FGT */ - case 0xE3: /* TPC with 2FGT */ - case 0xE5: /* TPC with MT */ - case 0xE6: /* TPC with 2FGT */ - case 0x93: /* TPC with 1FGT */ - case 0x9A: /* TPC with 1FGT */ - case 0xEC: /* TPC with 1FGT */ - case 0xED: /* TPC with 1FGT */ - case 0x90: /* TPC */ - case 0x97: /* TPC */ - case 0x9F: /* TPC */ - case 0xEF: /* TPC */ - TabletSetFeature(priv->common, WCM_TPC); - break; - - case 0x304:/* Cintiq 13HD */ - case 0x307:/* Cintiq Companion Hybrid */ - case 0x30A:/* Cintiq Companion */ - case 0x325:/* Cintiq Companion 2 */ - case 0x32A:/* Cintiq 27QHD */ - case 0x32B:/* Cintiq 27QHDT Pen */ - case 0x333:/* Cintiq 13HDT Pen */ - case 0x34F:/* Cintiq Pro 13 FHD */ - case 0x350:/* Cintiq Pro 16 UHD */ - case 0x351:/* Cintiq Pro 24 */ - case 0x352:/* Cintiq Pro 32 */ - case 0x37C:/* Cintiq Pro 24 Pen-Only */ - case 0x390:/* Cintiq 16 */ - case 0x391:/* Cintiq 22 */ - case 0x396:/* DTK-1660E */ - case 0x3AE:/* Cintiq 16 */ - case 0x3B0:/* DTK-1660E */ - TabletSetFeature(priv->common, WCM_ROTATION); - _fallthrough_; - case 0xF6: /* Cintiq 24HDT Touch */ - case 0x57: /* DTK2241 */ - case 0x59: /* DTH2242 Pen */ - case 0x5D: /* DTH2242 Touch */ - case 0x5E: /* Cintiq 22HDT Touch */ - case 0x309:/* Cintiq Companion Hybrid Touch */ - case 0x30C:/* Cintiq Companion Touch */ - case 0x326:/* Cintiq Companion 2 Touch */ - case 0x32C:/* Cintiq 27QHDT Touch */ - case 0x32F:/* DTU-1031X */ - case 0x335:/* Cintiq 13HDT Touch */ - case 0x336:/* DTU-1141 */ - case 0x343:/* DTK-1651 */ - case 0x34A:/* MobileStudio Pro 13 Touch */ - case 0x34B:/* MobileStudio Pro 16 Touch */ - case 0x353:/* Cintiq Pro 13 FHD Touch */ - case 0x354:/* Cintiq Pro 13 UHD Touch */ - case 0x355:/* Cintiq Pro 24 Touch */ - case 0x356:/* Cintiq Pro 32 Touch */ - case 0x359:/* DTU-1141B */ - case 0x35A:/* DTH-1152*/ - case 0x368:/* DTH-1152 Touch */ - case 0x382:/* DTK-2451 */ - case 0x37D:/* DTH-2452 */ - case 0x37E:/* DTH-2452 Touch */ - case 0x39A:/* MobileStudio Pro 13 Touch */ - case 0x39B:/* MobileStudio Pro 16 Touch */ - case 0x3AC:/* MobileStudio Pro 16 Touch */ - TabletSetFeature(priv->common, WCM_LCD); - break; - } - - if (ISBITSET(common->wcmInputProps, INPUT_PROP_DIRECT)) - TabletSetFeature(priv->common, WCM_LCD); - - if (ISBITSET(common->wcmKeys, BTN_TOOL_PEN)) - TabletSetFeature(priv->common, WCM_PEN); - - if (ISBITSET (common->wcmKeys, BTN_0) || - ISBITSET (common->wcmKeys, BTN_FORWARD)) - { - TabletSetFeature(priv->common, WCM_PAD); - } - - /* This handles both protocol 4 and 5 meanings of wcmKeys */ - if (common->wcmProtocolLevel == WCM_PROTOCOL_4) - { - /* TRIPLETAP means 2 finger touch */ - /* DOUBLETAP without TRIPLETAP means 1 finger touch */ - if (ISBITSET(common->wcmKeys, BTN_TOOL_TRIPLETAP)) - TabletSetFeature(priv->common, WCM_2FGT); - else if (ISBITSET(common->wcmKeys, BTN_TOOL_DOUBLETAP)) - TabletSetFeature(priv->common, WCM_1FGT); - } - - if (common->wcmProtocolLevel == WCM_PROTOCOL_GENERIC) - { - /* DOUBLETAP means 2 finger touch */ - /* FINGER without DOUBLETAP means 1 finger touch */ - if (ISBITSET(common->wcmKeys, BTN_TOOL_DOUBLETAP)) - TabletSetFeature(priv->common, WCM_2FGT); - else if (ISBITSET(common->wcmKeys, BTN_TOOL_FINGER)) - TabletSetFeature(priv->common, WCM_1FGT); - } - - return ret; -} - static void wcmAddHotpluggedDevice(WacomDevicePtr priv, const char *basename, const char *type, WacomToolPtr ser) diff --git a/src/xf86Wacom.h b/src/xf86Wacom.h index 9d65f8d3..90a6cf91 100644 --- a/src/xf86Wacom.h +++ b/src/xf86Wacom.h @@ -117,7 +117,6 @@ void wcmSendEvents(WacomDevicePtr priv, const WacomDeviceState* ds); /* validation */ extern Bool wcmIsAValidType(WacomDevicePtr priv, const char* type); extern int wcmIsDuplicate(const char* device, WacomDevicePtr priv); -extern int wcmDeviceTypeKeys(WacomDevicePtr priv); /* hotplug */ extern int wcmNeedAutoHotplug(WacomDevicePtr priv, char **type); From 66f41d6225b34ca02a4a70d2a101e82c561c51d7 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 2 Nov 2022 22:09:36 -0700 Subject: [PATCH 08/53] Assign Wacom specific keys only to Wacom devices Most extra features are only for Wacom 0x56a devices. Make them specific so we don't abuse other devices ;). Signed-off-by: Ping Cheng --- src/wcmConfig.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/wcmConfig.c b/src/wcmConfig.c index 6276bbde..da6a0300 100644 --- a/src/wcmConfig.c +++ b/src/wcmConfig.c @@ -710,25 +710,21 @@ static inline Bool filter_test_suite(WacomDevicePtr priv) return TRUE; } -/* Choose valid types according to device ID. */ -static void wcmDeviceTypeKeys(WacomDevicePtr priv) +/* Wacom 0x056a specific types */ +static void wcmSpecialTypeKeys(WacomCommonPtr common) { - WacomCommonPtr common = priv->common; - - priv->common->tablet_id = common->wcmDevCls->ProbeKeys(priv); - - switch (priv->common->tablet_id) + switch (common->tablet_id) { case 0xF8: /* Cintiq 24HDT */ case 0xF4: /* Cintiq 24HD */ - TabletSetFeature(priv->common, WCM_DUALRING); + TabletSetFeature(common, WCM_DUALRING); _fallthrough_; case 0x34D: /* MobileStudio Pro 13 */ case 0x34E: /* MobileStudio Pro 16 */ case 0x398: /* MobileStudio Pro 13 */ case 0x399: /* MobileStudio Pro 16 */ case 0x3AA: /* MobileStudio Pro 16 */ - TabletSetFeature(priv->common, WCM_LCD); + TabletSetFeature(common, WCM_LCD); _fallthrough_; case 0x357: /* Intuos Pro 2 M */ case 0x358: /* Intuos Pro 2 L */ @@ -750,12 +746,12 @@ static void wcmDeviceTypeKeys(WacomDevicePtr priv) case 0xBB: /* I4 */ case 0xBC: /* I4 */ case 0xBD: /* I4 */ - TabletSetFeature(priv->common, WCM_ROTATION); + TabletSetFeature(common, WCM_ROTATION); _fallthrough_; /* tablets with touch ring */ case 0x17: /* BambooFun */ case 0x18: /* BambooFun */ - TabletSetFeature(priv->common, WCM_RING); + TabletSetFeature(common, WCM_RING); break; /* tablets support dual input */ @@ -770,7 +766,7 @@ static void wcmDeviceTypeKeys(WacomDevicePtr priv) case 0x44: /* I2 */ case 0x45: /* I2 */ case 0x47: /* I2 */ - TabletSetFeature(priv->common, WCM_DUALINPUT); + TabletSetFeature(common, WCM_DUALINPUT); break; /* P4 display tablets */ @@ -793,7 +789,7 @@ static void wcmDeviceTypeKeys(WacomDevicePtr priv) /* Wacom One display tablet */ case 0x3A6: /* DTC133 */ - TabletSetFeature(priv->common, WCM_LCD); + TabletSetFeature(common, WCM_LCD); break; /* tablets support menu strips */ @@ -803,7 +799,7 @@ static void wcmDeviceTypeKeys(WacomDevicePtr priv) case 0xCC: /* CinitqV5 */ case 0xFA: /* Cintiq 22HD */ case 0x5B: /* Cintiq 22HDT Pen */ - TabletSetFeature(priv->common, WCM_LCD); + TabletSetFeature(common, WCM_LCD); _fallthrough_; case 0xB0: /* I3 */ case 0xB1: /* I3 */ @@ -812,7 +808,7 @@ static void wcmDeviceTypeKeys(WacomDevicePtr priv) case 0xB4: /* I3 */ case 0xB5: /* I3 */ case 0xB7: /* I3 */ - TabletSetFeature(priv->common, WCM_STRIP | WCM_ROTATION); + TabletSetFeature(common, WCM_STRIP | WCM_ROTATION); break; case 0x100: /* TPC with MT */ @@ -836,7 +832,7 @@ static void wcmDeviceTypeKeys(WacomDevicePtr priv) case 0x97: /* TPC */ case 0x9F: /* TPC */ case 0xEF: /* TPC */ - TabletSetFeature(priv->common, WCM_TPC); + TabletSetFeature(common, WCM_TPC); break; case 0x304:/* Cintiq 13HD */ @@ -856,7 +852,7 @@ static void wcmDeviceTypeKeys(WacomDevicePtr priv) case 0x396:/* DTK-1660E */ case 0x3AE:/* Cintiq 16 */ case 0x3B0:/* DTK-1660E */ - TabletSetFeature(priv->common, WCM_ROTATION); + TabletSetFeature(common, WCM_ROTATION); _fallthrough_; case 0xF6: /* Cintiq 24HDT Touch */ case 0x57: /* DTK2241 */ @@ -886,9 +882,20 @@ static void wcmDeviceTypeKeys(WacomDevicePtr priv) case 0x39A:/* MobileStudio Pro 13 Touch */ case 0x39B:/* MobileStudio Pro 16 Touch */ case 0x3AC:/* MobileStudio Pro 16 Touch */ - TabletSetFeature(priv->common, WCM_LCD); + TabletSetFeature(common, WCM_LCD); break; } +} + +/* Choose valid types according to vendor ID and device ID. */ +static void wcmDeviceTypeKeys(WacomDevicePtr priv) +{ + WacomCommonPtr common = priv->common; + + priv->common->tablet_id = common->wcmDevCls->ProbeKeys(priv); + + if (priv->common->vendor_id == WACOM_VENDOR_ID) + wcmSpecialTypeKeys(common); if (ISBITSET(common->wcmInputProps, INPUT_PROP_DIRECT)) TabletSetFeature(priv->common, WCM_LCD); From 6eefde01f04454c8b0df1dedd2bbf77086206c09 Mon Sep 17 00:00:00 2001 From: Greenscreener Date: Sun, 24 Jul 2022 14:41:50 +0200 Subject: [PATCH 09/53] Fixing discrepancy in naxes See https://github.com/linuxwacom/xf86-input-wacom/pull/222#discussion_r897908702 --- src/wcmConfig.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wcmConfig.c b/src/wcmConfig.c index da6a0300..014fc70d 100644 --- a/src/wcmConfig.c +++ b/src/wcmConfig.c @@ -1230,8 +1230,8 @@ Bool wcmDevInit(WacomDevicePtr priv) priv->common->wcmModel->DetectConfig (priv); nbaxes = priv->naxes; /* X, Y, Pressure, Tilt-X, Tilt-Y, Wheel */ - if (!nbaxes || nbaxes > 7) - nbaxes = priv->naxes = 7; + if (!nbaxes || nbaxes > 6) + nbaxes = priv->naxes = 6; nbbuttons = priv->nbuttons; /* Use actual number of buttons, if possible */ if (IsPad(priv) && TabletHasFeature(priv->common, WCM_DUALRING)) From 2a9e5953f89a7085786326e07edcb53ad821aace Mon Sep 17 00:00:00 2001 From: Greenscreener Date: Sun, 24 Jul 2022 14:48:29 +0200 Subject: [PATCH 10/53] Replace valuator array with valuator mask in convertAxes ValuatorMask has been around since xserver 1.10, released in 2011. --- src/gwacom/wacom-device.c | 6 + src/wcmConfig.c | 3 + src/x11/xf86Wacom.c | 277 +++++++++++++++++++++++++++----------- src/xf86WacomDefs.h | 2 + 4 files changed, 213 insertions(+), 75 deletions(-) diff --git a/src/gwacom/wacom-device.c b/src/gwacom/wacom-device.c index 87ac433a..2a9c915a 100644 --- a/src/gwacom/wacom-device.c +++ b/src/gwacom/wacom-device.c @@ -196,6 +196,12 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; +ValuatorMask * +valuator_mask_new(int num_valuators) +{ + return NULL; +} + WacomDevice* wacom_device_new(WacomDriver *driver, const char *name, diff --git a/src/wcmConfig.c b/src/wcmConfig.c index 014fc70d..757492d3 100644 --- a/src/wcmConfig.c +++ b/src/wcmConfig.c @@ -98,6 +98,9 @@ WacomDevicePtr wcmAllocate(void *frontend, const char *name) priv->tap_timer = wcmTimerNew(); priv->touch_timer = wcmTimerNew(); + /* reusable valuator mask */ + priv->valuator_mask = valuator_mask_new(7); + return priv; error: diff --git a/src/x11/xf86Wacom.c b/src/x11/xf86Wacom.c index aebf27a6..4cabe36f 100644 --- a/src/x11/xf86Wacom.c +++ b/src/x11/xf86Wacom.c @@ -397,11 +397,9 @@ valuatorNumber(enum WacomAxisType which) } static inline void -convertAxes(const WacomAxisData *axes, int *first_out, int *num_out, int valuators_out[7]) +convertAxes(const WacomAxisData *axes, ValuatorMask *mask) { - int first = 7; - int last = -1; - int valuators[7] = {0}; + for (enum WacomAxisType which = _WACOM_AXIS_LAST; which > 0; which >>= 1) { @@ -414,51 +412,43 @@ convertAxes(const WacomAxisData *axes, int *first_out, int *num_out, int valuato /* Positions need to match wcmInitAxis */ pos = valuatorNumber(which); - first = min(first, pos); - last = max(last, pos); - valuators[pos] = value; + valuator_mask_set(mask, pos, value); } - - if (last < 0) - first = 0; - *first_out = first; - *num_out = last - first + 1; - - memcpy(valuators_out, &valuators[first], *num_out * sizeof(valuators[0])); } void wcmEmitProximity(WacomDevicePtr priv, bool is_proximity_in, const WacomAxisData *axes) { InputInfoPtr pInfo = priv->frontend; - int valuators[7] = {0}; - int first_val, num_vals; - convertAxes(axes, &first_val, &num_vals, valuators); + ValuatorMask *mask = priv->valuator_mask; + valuator_mask_zero(mask); + convertAxes(axes, mask); - xf86PostProximityEventP(pInfo->dev, is_proximity_in, first_val, num_vals, valuators); + xf86PostProximityEventM(pInfo->dev, is_proximity_in, mask); } void wcmEmitMotion(WacomDevicePtr priv, bool is_absolute, const WacomAxisData *axes) { InputInfoPtr pInfo = priv->frontend; - int valuators[7] = {0}; - int first_val, num_vals; - convertAxes(axes, &first_val, &num_vals, valuators); + ValuatorMask *mask = priv->valuator_mask; + valuator_mask_zero(mask); + convertAxes(axes, mask); - xf86PostMotionEventP(pInfo->dev, is_absolute, first_val, num_vals, valuators); + xf86PostMotionEventM(pInfo->dev, is_absolute, mask); } void wcmEmitButton(WacomDevicePtr priv, bool is_absolute, int button, bool is_press, const WacomAxisData *axes) { InputInfoPtr pInfo = priv->frontend; - int valuators[7] = {0}; - int first_val, num_vals; - convertAxes(axes, &first_val, &num_vals, valuators); + ValuatorMask *mask = priv->valuator_mask; + valuator_mask_zero(mask); + convertAxes(axes, mask); - xf86PostButtonEventP(pInfo->dev, is_absolute, button, is_press, first_val, num_vals, valuators); + + xf86PostButtonEventM(pInfo->dev, is_absolute, button, is_press, mask); } void wcmEmitTouch(WacomDevicePtr priv, int type, unsigned int touchid, int x, int y) @@ -993,60 +983,191 @@ _X_EXPORT XF86ModuleData wacomModuleData = #ifdef ENABLE_TESTS #include "wacom-test-suite.h" -TEST_CASE(test_convert_axes) +#define MAX_VALUATORS 36 + +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 */ +}; + +// The following functions are copied from https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/dix/inpututils.c + +int +CountBits(const uint8_t * mask, int len) { - WacomAxisData axes = {0}; - int first, num; - int valuators[7]; + int i; + int ret = 0; + + for (i = 0; i < len; i++) + if (BitIsOn(mask, i)) + ret++; + + return ret; +} + + +/** + * Alloc a valuator mask large enough for num_valuators. + */ +ValuatorMask * +valuator_mask_new(int num_valuators) +{ + /* alloc a fixed size mask for now and ignore num_valuators. in the + * flying-car future, when we can dynamically alloc the masks and are + * not constrained by signals, we can start using num_valuators */ + ValuatorMask *mask = calloc(1, sizeof(ValuatorMask)); + + if (mask == NULL) + return NULL; -#define reset(v) \ - for (size_t _i = 0; _i < ARRAY_SIZE(v); _i++) \ - v[_i] = 0xab; + mask->last_bit = -1; + return mask; +} - reset(valuators); +/** + * Reset mask to zero. + */ +void +valuator_mask_zero(ValuatorMask *mask) +{ + memset(mask, 0, sizeof(*mask)); + mask->last_bit = -1; +} - convertAxes(&axes, &first, &num, valuators); - assert(first == 0); - assert(num == 0); - for (size_t i = 0; i< ARRAY_SIZE(valuators); i++) - assert(valuators[i] == 0xab); +/** + * Returns the current size of the mask (i.e. the highest number of + * valuators currently set + 1). + */ +int +valuator_mask_size(const ValuatorMask *mask) +{ + return mask->last_bit + 1; +} + +/** + * Returns the number of valuators set in the given mask. + */ +int +valuator_mask_num_valuators(const ValuatorMask *mask) +{ + return CountBits(mask->mask, min(mask->last_bit + 1, MAX_VALUATORS)); +} + +/** + * Return true if the valuator is set in the mask, or false otherwise. + */ +int +valuator_mask_isset(const ValuatorMask *mask, int valuator) +{ + return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator); +} + +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); + mask->valuators[valuator] = data; +} + +/** + * Set the valuator to the given floating-point data. + */ +void +valuator_mask_set_double(ValuatorMask *mask, int valuator, double data) +{ + if (mask->has_unaccelerated) { + wcmLog(null, 0, "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 +valuator_mask_set(ValuatorMask *mask, int valuator, int data) +{ + valuator_mask_set_double(mask, valuator, data); +} + +/** + * Return the requested valuator value as a double. If the mask bit is not + * set for the given valuator, the returned value is undefined. + */ + double +valuator_mask_get_double(const ValuatorMask *mask, int valuator) +{ + return mask->valuators[valuator]; +} + +/** + * Return the requested valuator value as an integer, rounding towards zero. + * If the mask bit is not set for the given valuator, the returned value is + * undefined. + */ +int +valuator_mask_get(const ValuatorMask *mask, int valuator) +{ + return trunc(valuator_mask_get_double(mask, valuator)); +} + + +TEST_CASE(test_convert_axes) +{ + WacomAxisData axes = {0}; + ValuatorMask *mask = valuator_mask_new(7); + + convertAxes(&axes, mask); + assert(valuator_mask_num_valuators(mask) == 0); + assert(valuator_mask_size(mask) == 0); + for (size_t i = 0; i< 9; i++) + assert(!valuator_mask_isset(mask, i)); - reset(valuators); memset(&axes, 0, sizeof(axes)); + valuator_mask_zero(mask); /* Check conversion for single value with first_valuator != 0 */ wcmAxisSet(&axes, WACOM_AXIS_PRESSURE, 1); /* pos 2 */ - convertAxes(&axes, &first, &num, valuators); - assert(first == 2); - assert(num == 1); - assert(valuators[0] == 1); - assert(valuators[1] == 0xab); - assert(valuators[2] == 0xab); - assert(valuators[3] == 0xab); - assert(valuators[4] == 0xab); - assert(valuators[5] == 0xab); - assert(valuators[6] == 0xab); - - reset(valuators); + convertAxes(&axes, mask); + assert(valuator_mask_num_valuators(mask) == 1); + assert(valuator_mask_size(mask) == 3); + assert(!valuator_mask_isset(mask, 0)); + assert(!valuator_mask_isset(mask, 1)); + assert(valuator_mask_isset(mask, 2)); + assert(valuator_mask_get(mask, 2) == 1); + assert(!valuator_mask_isset(mask, 3)); + assert(!valuator_mask_isset(mask, 4)); + assert(!valuator_mask_isset(mask, 5)); + assert(!valuator_mask_isset(mask, 6)); + assert(!valuator_mask_isset(mask, 7)); + assert(!valuator_mask_isset(mask, 8)); + memset(&axes, 0, sizeof(axes)); + valuator_mask_zero(mask); /* Check conversion for gaps with first_valuator != 0 */ wcmAxisSet(&axes, WACOM_AXIS_PRESSURE, 1); /* pos 2 */ wcmAxisSet(&axes, WACOM_AXIS_WHEEL, 2); /* pos 5 */ - convertAxes(&axes, &first, &num, valuators); - assert(first == 2); - assert(num == 4); - assert(valuators[0] == 1); - assert(valuators[1] == 0); - assert(valuators[2] == 0); - assert(valuators[3] == 2); - assert(valuators[4] == 0xab); - assert(valuators[5] == 0xab); - assert(valuators[6] == 0xab); - - reset(valuators); + convertAxes(&axes, mask); + assert(valuator_mask_num_valuators(mask) == 2); + assert(valuator_mask_size(mask) == 6); + assert(!valuator_mask_isset(mask, 0)); + assert(!valuator_mask_isset(mask, 1)); + assert(valuator_mask_isset(mask, 2)); + assert(valuator_mask_get(mask, 2) == 1); + assert(!valuator_mask_isset(mask, 3)); + assert(!valuator_mask_isset(mask, 4)); + assert(valuator_mask_isset(mask, 5)); + assert(valuator_mask_get(mask, 5) == 2); + assert(!valuator_mask_isset(mask, 6)); + memset(&axes, 0, sizeof(axes)); + valuator_mask_zero(mask); /* Check conversion for valuators with duplicate uses. Note that this * test is implementation-dependent: the loop in convertAxes decides @@ -1059,17 +1180,23 @@ TEST_CASE(test_convert_axes) wcmAxisSet(&axes, WACOM_AXIS_RING, 3); /* pos 5 */ wcmAxisSet(&axes, WACOM_AXIS_WHEEL, 2); /* also pos 5 */ - convertAxes(&axes, &first, &num, valuators); - assert(first == 2); - assert(num == 4); - assert(valuators[0] == 1); - assert(valuators[1] == 10); - assert(valuators[2] == 11); - assert(valuators[3] == 2); - assert(valuators[4] == 0xab); - assert(valuators[5] == 0xab); - assert(valuators[6] == 0xab); - + convertAxes(&axes, mask); + assert(valuator_mask_num_valuators(mask) == 4); + assert(valuator_mask_size(mask) == 6); + assert(!valuator_mask_isset(mask, 0)); + assert(!valuator_mask_isset(mask, 1)); + assert(valuator_mask_isset(mask, 2)); + assert(valuator_mask_get(mask, 2) == 1); + assert(valuator_mask_isset(mask, 3)); + assert(valuator_mask_get(mask, 3) == 10); + assert(valuator_mask_isset(mask, 4)); + assert(valuator_mask_get(mask, 4) == 11); + 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)); + + free(mask); } #endif diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h index 886bf77e..df218563 100644 --- a/src/xf86WacomDefs.h +++ b/src/xf86WacomDefs.h @@ -302,6 +302,8 @@ struct _WacomDeviceRec WacomTimerPtr serial_timer; /* timer used for serial number property update */ WacomTimerPtr tap_timer; /* timer used for tap timing */ WacomTimerPtr touch_timer; /* timer used for touch switch property update */ + + ValuatorMask *valuator_mask; /* reusable valuator mask for sending events without reallocation */ }; #define MAX_SAMPLES 20 From fe923e927a8ddf4d2e82ef4757c885b06d47fa03 Mon Sep 17 00:00:00 2001 From: Greenscreener Date: Sun, 24 Jul 2022 15:02:46 +0200 Subject: [PATCH 11/53] Implement smooth panscrolling --- src/WacomInterface.h | 11 +++++++- src/gwacom/wacom-device.h | 5 +++- src/wcmCommon.c | 35 +++++------------------- src/wcmConfig.c | 15 +++++++++-- src/x11/xf86Wacom.c | 25 ++++++++++++++--- src/xf86WacomDefs.h | 5 ++++ test/test_wacom.py | 56 +++++++++++++++++++++++++++++++++++++++ tools/wacom-record.c | 2 ++ 8 files changed, 117 insertions(+), 37 deletions(-) diff --git a/src/WacomInterface.h b/src/WacomInterface.h index 55cde081..a0110a49 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 546fd9fc..659ed5e0 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 44bffb5c..20cfaac9 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 757492d3..7c0483f8 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 4cabe36f..9c718974 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 df218563..92c4d913 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 26a01aab..19999ac0 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 395282b0..8b1cf771 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", From 0bf20b63f35385893f58bcbacbc3d78dc9dcf207 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 7 Dec 2022 08:46:32 +1000 Subject: [PATCH 12/53] CI: update some actions to v3 Node 12 is deprecated so let's switch to the newer version https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/ Signed-off-by: Peter Hutterer --- .github/workflows/black.yml | 4 ++-- .github/workflows/build.yml | 22 +++++++++++----------- .github/workflows/coverity.yml | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index 6ca60ffa..ff250367 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -5,8 +5,8 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout the repo - uses: actions/checkout@v2 - - uses: actions/setup-python@v1 + uses: actions/checkout@v3 + - uses: actions/setup-python@v4 with: python-version: '3.x' - run: pip install black diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a88d8b77..8c664f79 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: compiler: [ gcc, clang ] steps: - name: Checkout the repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - uses: linuxwacom/libwacom/.github/actions/pkginstall@master with: apt: $UBUNTU_PACKAGES @@ -50,7 +50,7 @@ jobs: - name: move tarball to top level run: | mv _build/xf86-input-wacom-*tar.bz2 . - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: tarball path: xf86-input-wacom-*tar.bz2 @@ -69,7 +69,7 @@ jobs: # https://github.com/mesonbuild/meson/issues/764 - '-Db_sanitize=address,undefined -Db_lundef=false' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: linuxwacom/libwacom/.github/actions/pkginstall@master with: apt: $UBUNTU_PACKAGES @@ -81,7 +81,7 @@ jobs: env: CC: ${{matrix.compiler}} # Capture all the meson logs, even if we failed - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: ${{ always() }} # even if we fail with: name: meson-test-logs-${{github.job}}-${{matrix.compiler}}-${{matrix.meson_options}} @@ -92,7 +92,7 @@ jobs: compile-with-meson-exact-version: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: linuxwacom/libwacom/.github/actions/pkginstall@master with: apt: $UBUNTU_PACKAGES @@ -104,7 +104,7 @@ jobs: with: meson_args: -Dauto_features=enabled # Capture all the meson logs, even if we failed - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: ${{ always() }} # even if we fail with: name: meson-test-logs-${{github.job}} @@ -127,7 +127,7 @@ jobs: with: apt: $UBUNTU_PACKAGES - name: fetch tarball from previous job(s) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: tarball - name: extract tarball @@ -157,7 +157,7 @@ jobs: apt: $UBUNTU_PACKAGES pip: $PIP_PACKAGES - name: fetch tarball from previous job(s) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: tarball - name: extract tarball @@ -172,7 +172,7 @@ jobs: meson_args: -Dauto_features=enabled --prefix="$INSTALLDIR" ninja_args: test # Capture all the meson logs, even if we failed - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: ${{ always() }} # even if we fail with: name: tarball-build-meson-test-logs @@ -187,9 +187,9 @@ jobs: TARBALLDIR: '_tarball_dir' steps: - name: Checkout the repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: fetch tarball from previous job(s) - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: tarball - name: list git files diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index f9d82f7b..cda14052 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -19,7 +19,7 @@ jobs: if: ${{ github.repository == '$COVERITY_SCAN_PROJECT_NAME' }} steps: - name: Checkout the repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up build environment / dependencies run: | From 8f655fe3faabc4a44a32504d0ef14fc961f803fb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 6 Apr 2023 11:17:09 +1000 Subject: [PATCH 13/53] wacom 1.2.0 Signed-off-by: Peter Hutterer --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c50035e2..354dfb4e 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ AC_PREREQ([2.60]) # bump version in meson.build AC_INIT([xf86-input-wacom], - [1.1.0], + [1.2.0], [https://github.com/linuxwacom/xf86-input-wacom/issues/], [xf86-input-wacom]) AC_CONFIG_MACRO_DIR([m4]) From 991660b38caf40aeaa8dd6e59c6b554b12c761da Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 29 May 2023 09:38:14 +1000 Subject: [PATCH 14/53] man: remove some unnecessary indent All our options were indented by an extra 4 units, unnecessary since we use TP for all of those anyway and get a highlight. Signed-off-by: Peter Hutterer --- man/wacom.man | 2 -- 1 file changed, 2 deletions(-) diff --git a/man/wacom.man b/man/wacom.man index a93ea285..71ffb50f 100644 --- a/man/wacom.man +++ b/man/wacom.man @@ -65,7 +65,6 @@ section only covers configuration details specific to this driver. .PP Multiple instances of the Wacom devices can cohabit. Each device supports the following entries: -.RS 8 .TP 4 .B Option \fI"Type"\fP \fI"stylus"|"eraser"|"cursor"|"pad"|"touch"\fP sets the type of tool the device represents. This option is mandatory. @@ -289,7 +288,6 @@ scroll event is generated when using the "pan" action. Smaller values will require less distance and be more sensitive. Larger values will require more distance and be less sensitive. Default: 1300 or 2600 depending on tablet resolution (corresponds to 13 mm of distance). -.RE .SH "TOUCH GESTURES" .SS Single finger (1FG) .LP From 3bde61c986ca7c1c373edd5ba4844ca6550fdbb8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 6 Jun 2023 14:30:09 +1000 Subject: [PATCH 15/53] release.sh: drop support for modfiles and module sets Leftover from the xorg release.sh script, no longer needed here since we only ever release one module at a time. Signed-off-by: Peter Hutterer --- release.sh | 93 ------------------------------------------------------ 1 file changed, 93 deletions(-) diff --git a/release.sh b/release.sh index 9eb949e9..9d50ab80 100755 --- a/release.sh +++ b/release.sh @@ -44,56 +44,17 @@ check_local_changes() { return 0 } -#------------------------------------------------------------------------------ -# Function: check_option_args -#------------------------------------------------------------------------------ -# -# perform sanity checks on cmdline args which require arguments -# arguments: -# $1 - the option being examined -# $2 - the argument to the option -# returns: -# if it returns, everything is good -# otherwise it exit's -check_option_args() { - option=$1 - arg=$2 - - # check for an argument - if [ x"$arg" = x ]; then - echo "" - echo "Error: the '$option' option is missing its required argument." - echo "" - usage - exit 1 - fi - - # does the argument look like an option? - echo $arg | $GREP "^-" > /dev/null - if [ $? -eq 0 ]; then - echo "" - echo "Error: the argument '$arg' of option '$option' looks like an option itself." - echo "" - usage - exit 1 - fi -} - #------------------------------------------------------------------------------ # Function: check_modules_specification #------------------------------------------------------------------------------ # check_modules_specification() { - -if [ x"$MODFILE" = x ]; then if [ x"${INPUT_MODULES}" = x ]; then echo "" echo "Error: no modules specified (blank command line)." usage exit 1 fi -fi - } #------------------------------------------------------------------------------ @@ -201,37 +162,6 @@ ${BT3} RELEASE } -#------------------------------------------------------------------------------ -# Function: read_modfile -#------------------------------------------------------------------------------ -# -# Read the module names from the file and set a variable to hold them -# This will be the same interface as cmd line supplied modules -# -read_modfile() { - - if [ x"$MODFILE" != x ]; then - # Make sure the file is sane - if [ ! -r "$MODFILE" ]; then - echo "Error: module file '$MODFILE' is not readable or does not exist." - exit 1 - fi - # read from input file, skipping blank and comment lines - while read line; do - # skip blank lines - if [ x"$line" = x ]; then - continue - fi - # skip comment lines - if echo "$line" | $GREP -q "^#" ; then - continue; - fi - INPUT_MODULES="$INPUT_MODULES $line" - done <"$MODFILE" - fi - return 0 -} - #------------------------------------------------------------------------------ # Function: print_epilog #------------------------------------------------------------------------------ @@ -658,7 +588,6 @@ Options: --dry-run Does everything except tagging and uploading tarballs --force Force overwriting an existing release --help Display this help and exit successfully - --modfile Release the git modules specified in --moduleset The jhbuild moduleset full pathname to be updated --no-quit Do not quit after error; just print error message --github Release project to Github with username / token @@ -730,18 +659,6 @@ do usage exit 0 ;; - # Release the git modules specified in - --modfile) - check_option_args $1 $2 - shift - MODFILE=$1 - ;; - # The jhbuild moduleset to update with relase info - --moduleset) - check_option_args $1 $2 - shift - JH_MODULESET=$1 - ;; # Do not quit after error; just print error message --no-quit) NO_QUIT=yes @@ -768,13 +685,6 @@ do exit 1 ;; *) - if [ x"${MODFILE}" != x ]; then - echo "" - echo "Error: specifying both modules and --modfile is not permitted" - echo "" - usage - exit 1 - fi INPUT_MODULES="${INPUT_MODULES} $1" ;; esac @@ -790,9 +700,6 @@ fi # If no modules specified (blank cmd line) display help check_modules_specification -# Read the module file and normalize input in INPUT_MODULES -read_modfile - # Loop through each module to release # Exit on error if --no-quit no specified process_modules From ca34daadc486217cfe5463237b42035146339cff Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 29 May 2023 11:10:43 +1000 Subject: [PATCH 16/53] Remove a confusing comment We clip to 6 axis here, so having a comment that lists 8 axes is not overly useful. Signed-off-by: Peter Hutterer --- src/wcmConfig.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wcmConfig.c b/src/wcmConfig.c index 7c0483f8..eedfb663 100644 --- a/src/wcmConfig.c +++ b/src/wcmConfig.c @@ -1240,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, Scroll-X, Scroll-Y */ + nbaxes = priv->naxes; /* X, Y, Pressure, Tilt-X, Tilt-Y, Wheel */ if (!nbaxes || nbaxes > 6) nbaxes = priv->naxes = 6; nbbuttons = priv->nbuttons; /* Use actual number of buttons, if possible */ @@ -1248,6 +1248,7 @@ Bool wcmDevInit(WacomDevicePtr priv) if (IsPad(priv) && TabletHasFeature(priv->common, WCM_DUALRING)) nbaxes = priv->naxes = nbaxes + 1; /* ABS wheel 2 */ + /* For smooth scrolling we set up two additional axes */ if (IsPen(priv)) nbaxes = priv->naxes = nbaxes + 2; /* Scroll X and Y */ From d0e1fee6bbdadfd8aa76a46e87a29fb689817fc3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 29 May 2023 11:15:51 +1000 Subject: [PATCH 17/53] Remove some unnecessary empty lines Signed-off-by: Peter Hutterer --- src/wcmCommon.c | 1 - src/x11/xf86Wacom.c | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/wcmCommon.c b/src/wcmCommon.c index 20cfaac9..0c08daae 100644 --- a/src/wcmCommon.c +++ b/src/wcmCommon.c @@ -118,7 +118,6 @@ static void wcmPanscroll(WacomDevicePtr priv, const WacomDeviceState *ds, int x, delta_y = (y - priv->oldState.y); } - DBG(6, priv, "pan x = %d, pan y = %d\n", delta_x, delta_y); WacomAxisData axes = {0}; diff --git a/src/x11/xf86Wacom.c b/src/x11/xf86Wacom.c index 9c718974..a9d57491 100644 --- a/src/x11/xf86Wacom.c +++ b/src/x11/xf86Wacom.c @@ -401,8 +401,6 @@ valuatorNumber(enum WacomAxisType which) static inline void convertAxes(const WacomAxisData *axes, ValuatorMask *mask) { - - for (enum WacomAxisType which = _WACOM_AXIS_LAST; which > 0; which >>= 1) { int value; @@ -449,7 +447,6 @@ void wcmEmitButton(WacomDevicePtr priv, bool is_absolute, int button, bool is_pr valuator_mask_zero(mask); convertAxes(axes, mask); - xf86PostButtonEventM(pInfo->dev, is_absolute, button, is_press, mask); } @@ -470,7 +467,6 @@ void wcmNotifyEvdev(WacomDevicePtr priv, const struct input_event *event) /* NOOP */ } - void wcmInitAxis(WacomDevicePtr priv, enum WacomAxisType type, int min, int max, int res) { From 692aa3b04916af3aad7b84131e1475d141f6d899 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 29 May 2023 11:21:23 +1000 Subject: [PATCH 18/53] x11: don't post motion/proximity events with an empty valuator mask After converting from our internal axis types to the x11 valuators we may (theoretically) be left with an empty valuator mask. Let's not post events in that case. This is a theoretical issue for now. Signed-off-by: Peter Hutterer --- src/x11/xf86Wacom.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/x11/xf86Wacom.c b/src/x11/xf86Wacom.c index a9d57491..adb16436 100644 --- a/src/x11/xf86Wacom.c +++ b/src/x11/xf86Wacom.c @@ -425,7 +425,8 @@ void wcmEmitProximity(WacomDevicePtr priv, bool is_proximity_in, valuator_mask_zero(mask); convertAxes(axes, mask); - xf86PostProximityEventM(pInfo->dev, is_proximity_in, mask); + if (valuator_mask_num_valuators(mask)) + xf86PostProximityEventM(pInfo->dev, is_proximity_in, mask); } void wcmEmitMotion(WacomDevicePtr priv, bool is_absolute, const WacomAxisData *axes) @@ -436,7 +437,8 @@ void wcmEmitMotion(WacomDevicePtr priv, bool is_absolute, const WacomAxisData *a valuator_mask_zero(mask); convertAxes(axes, mask); - xf86PostMotionEventM(pInfo->dev, is_absolute, mask); + if (valuator_mask_num_valuators(mask)) + xf86PostMotionEventM(pInfo->dev, is_absolute, mask); } void wcmEmitButton(WacomDevicePtr priv, bool is_absolute, int button, bool is_press, const WacomAxisData *axes) From 815edf68875193d254f12dbf7e0f944dccbbd6c1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 15 Jun 2023 13:10:06 +1000 Subject: [PATCH 19/53] test: parametrize the scroll test for vert + horiz scrolling Signed-off-by: Peter Hutterer --- test/test_wacom.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/test/test_wacom.py b/test/test_wacom.py index 19999ac0..3f7364a8 100644 --- a/test/test_wacom.py +++ b/test/test_wacom.py @@ -327,7 +327,8 @@ def test_axis_updates_wheel(mainloop, opts, stylus_type): assert first_wheel == current_wheel -def test_scroll(mainloop, opts): +@pytest.mark.parametrize("vertical", (True, False)) +def test_scroll(mainloop, opts, vertical): """ Check panscrolling works correctly """ @@ -357,7 +358,10 @@ def test_scroll(mainloop, opts): Sev("SYN_REPORT", 0), ] - move_pen_x = [Sev("ABS_X", 75), Sev("SYN_REPORT", 0)] + if vertical: + move_pen = [Sev("ABS_Y", 75), Sev("SYN_REPORT", 0)] + else: + move_pen = [Sev("ABS_X", 75), Sev("SYN_REPORT", 0)] up_pen = [Sev("BTN_TOUCH", 0), Sev("ABS_PRESSURE", 0), Sev("SYN_REPORT", 0)] @@ -369,7 +373,7 @@ def test_scroll(mainloop, opts): 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(move_pen) # Move pen 25% towards positive x or y monitor.write_events(up_pen) # Pen up monitor.write_events(depress_button2) # Depress button2 monitor.write_events(prox_out) @@ -377,9 +381,14 @@ def test_scroll(mainloop, opts): 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 + if vertical: + if event.axes.scroll_y != 0: + assert event.axes.scroll_y == -808265 + have_we_scrolled = True + else: + if event.axes.scroll_x != 0: + assert event.axes.scroll_x == -1223320 + have_we_scrolled = True assert have_we_scrolled From 55a10e392f7337da0dfcc19a60f816aa7645f2df Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 29 May 2023 11:15:45 +1000 Subject: [PATCH 20/53] Add option SmoothPanscrollingEnabled This is a backwards-compatibility option similar to the Pressure2K option. GDK2 applications are effectively limited to 7 axes (value of GDK_AXES_LAST in GDK2) and adding smooth panscrolling gives our device 8 axes total. This can cause issues when the driver, GDK and the application don't agree on the number of axes in the device. This is an application/GDK bug but as for the Pressure2K option we expect there to be applications that cannot be updated easily. To work around this, provide a driver option to disable this new feature altogether and effectively return to 6 axes for the pen device. This is a partial revert of fe923e927a "Implement smooth panscrolling" for the implementation. Minor changes though, the implementation now relies more on local variables than pointers. Signed-off-by: Peter Hutterer --- man/wacom.man | 22 +++++++++++++++++++++ src/wcmCommon.c | 42 ++++++++++++++++++++++++++++++++++++----- src/wcmConfig.c | 9 +++++---- src/wcmValidateDevice.c | 4 ++++ src/xf86WacomDefs.h | 1 + test/test_wacom.py | 41 +++++++++++++++++++++++++++------------- 6 files changed, 97 insertions(+), 22 deletions(-) diff --git a/man/wacom.man b/man/wacom.man index 71ffb50f..6d17c49c 100644 --- a/man/wacom.man +++ b/man/wacom.man @@ -288,6 +288,17 @@ scroll event is generated when using the "pan" action. Smaller values will require less distance and be more sensitive. Larger values will require more distance and be less sensitive. Default: 1300 or 2600 depending on tablet resolution (corresponds to 13 mm of distance). +.TP 4 +.B Option \fI"SmoothPanscrollingEnabled"\fP \fI"bool"\fP +Allows to disable smooth panscrolling. Default: true. +If disabled, panscrolling sends legacy button events instead. +This option exists for backwards compatibility with +applications that have the number of axes on a device limited to 6. +See section +.B BUGS +for more details. This option should not be used unless the user runs one or +more applications that do not support more than six axes. + .SH "TOUCH GESTURES" .SS Single finger (1FG) .LP @@ -334,6 +345,17 @@ option to reduce the range to 2048 steps. Note that this setting applies to the device. Once applied, all applications will see the reduced pressure range. It is not possible to provide this setting on a per-application basis. +.SS "Smooth panscrolling exceeds the axis limits" +In version 1.2.0, the driver's support for smooth panscrolling added two axes +to the stylus device, bringing the total axis count to eight. The number of +axes is advertised through the X Input Protocol but some applications (notably +GIMP 2.xx) cannot handle more than six axes. This is an application bug but for +backwards-compatibility with such applications, this driver provides the +.B SmoothPanscrollingEnabled +option to disable this feature and thus limit the axis count to six. Note that +this setting applies to the device. Once applied, the driver will not send +smooth panscroll events at all. It is not possible to provide this setting on a +per-application basis. .SH "SEE ALSO" __xservername__(1), xorg.conf(5), xorg.conf.d(5), X(7) diff --git a/src/wcmCommon.c b/src/wcmCommon.c index 0c08daae..b33446d7 100644 --- a/src/wcmCommon.c +++ b/src/wcmCommon.c @@ -95,14 +95,35 @@ 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 delta_x, delta_y; + bool smooth_scrolling = priv->common->wcmPanscrollIsSmooth; - if (!(priv->flags & SCROLLMODE_FLAG) || !(ds->buttons & 1)) + if (!(priv->flags & SCROLLMODE_FLAG) || !(ds->buttons & 1)) { + priv->wcmPanscrollState = *ds; + priv->wcmPanscrollState.x = 0; + priv->wcmPanscrollState.y = 0; return; + } /* Tip has gone down down; don't send pan event yet */ if (!(priv->oldState.buttons & 1)) { @@ -120,10 +141,21 @@ static void wcmPanscroll(WacomDevicePtr priv, const WacomDeviceState *ds, int x, DBG(6, priv, "pan x = %d, pan y = %d\n", delta_x, delta_y); - 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); + if (smooth_scrolling) { + 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); + } else { + int accumulated_x = priv->wcmPanscrollState.x + delta_x; + int accumulated_y = priv->wcmPanscrollState.y + delta_y; + + int remainder_x = wcmButtonPerNotch(priv, accumulated_x, threshold, 6, 7); + int remainder_y = wcmButtonPerNotch(priv, accumulated_y, threshold, 4, 5); + + priv->wcmPanscrollState.x = remainder_x; + priv->wcmPanscrollState.y = remainder_y; + } } void wcmResetButtonAction(WacomDevicePtr priv, int button) diff --git a/src/wcmConfig.c b/src/wcmConfig.c index eedfb663..5dab9cd5 100644 --- a/src/wcmConfig.c +++ b/src/wcmConfig.c @@ -1115,7 +1115,7 @@ int wcmDevOpen(WacomDevicePtr priv) * Any de-facto defined axis index left unused is initialized with default * attributes. */ -static int wcmInitAxes(WacomDevicePtr priv) +static int wcmInitAxes(WacomDevicePtr priv, Bool use_smooth_panscrolling) { WacomCommonPtr common = priv->common; int min, max, res; @@ -1220,7 +1220,7 @@ static int wcmInitAxes(WacomDevicePtr priv) wcmInitAxis(priv, WACOM_AXIS_RING2, min, max, res); } - if (IsPen(priv)) { + if (use_smooth_panscrolling && IsPen(priv)) { /* seventh valuator: scroll_x */ wcmInitAxis(priv, WACOM_AXIS_SCROLL_X, -1, -1, 0); @@ -1235,6 +1235,7 @@ Bool wcmDevInit(WacomDevicePtr priv) { WacomCommonPtr common = priv->common; int nbaxes, nbbuttons; + Bool use_smooth_panscrolling = priv->common->wcmPanscrollIsSmooth; /* Detect tablet configuration, if possible */ if (priv->common->wcmModel->DetectConfig) @@ -1249,7 +1250,7 @@ Bool wcmDevInit(WacomDevicePtr priv) nbaxes = priv->naxes = nbaxes + 1; /* ABS wheel 2 */ /* For smooth scrolling we set up two additional axes */ - if (IsPen(priv)) + if (use_smooth_panscrolling && IsPen(priv)) nbaxes = priv->naxes = nbaxes + 2; /* Scroll X and Y */ /* if more than 3 buttons, offset by the four scroll buttons, @@ -1287,7 +1288,7 @@ Bool wcmDevInit(WacomDevicePtr priv) } } - if (!wcmInitAxes(priv)) + if (!wcmInitAxes(priv, use_smooth_panscrolling)) return FALSE; return TRUE; diff --git a/src/wcmValidateDevice.c b/src/wcmValidateDevice.c index d1a17b14..282097c5 100644 --- a/src/wcmValidateDevice.c +++ b/src/wcmValidateDevice.c @@ -589,6 +589,10 @@ Bool wcmPreInitParseOptions(WacomDevicePtr priv, Bool is_primary, common->wcmPanscrollThreshold = wcmOptGetInt(priv, "PanScrollThreshold", common->wcmPanscrollThreshold); + common->wcmPanscrollIsSmooth = wcmOptGetBool(priv, "SmoothPanscrollingEnabled", + TRUE); + wcmLog(priv, W_CONFIG, "Smooth panscrolling is %s\n", + common->wcmPanscrollIsSmooth ? "enabled" : "disabled"); /* The first device doesn't need to add any tools/areas as it * will be the first anyway. So if different, add tool diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h index 92c4d913..1ee84abf 100644 --- a/src/xf86WacomDefs.h +++ b/src/xf86WacomDefs.h @@ -465,6 +465,7 @@ struct _WacomCommonRec int wcmPressureRecalibration; /* Determine if pressure recalibration of worn pens should be performed */ int wcmPanscrollThreshold; /* distance pen must move to send a panscroll event */ + int wcmPanscrollIsSmooth; /* nonzero if smooth panscrolling is enabled */ int bufpos; /* position with buffer */ unsigned char buffer[BUFFER_SIZE]; /* data read from device */ diff --git a/test/test_wacom.py b/test/test_wacom.py index 3f7364a8..203aac78 100644 --- a/test/test_wacom.py +++ b/test/test_wacom.py @@ -16,7 +16,7 @@ from typing import Dict -from . import Device, Monitor, Ev, Sev, Proximity, PenId +from . import Button, Device, Monitor, Ev, Sev, Proximity, PenId import pytest import logging @@ -327,13 +327,15 @@ def test_axis_updates_wheel(mainloop, opts, stylus_type): assert first_wheel == current_wheel +@pytest.mark.parametrize("smooth", (True, False)) @pytest.mark.parametrize("vertical", (True, False)) -def test_scroll(mainloop, opts, vertical): +def test_scroll(mainloop, opts, vertical, smooth): """ Check panscrolling works correctly """ dev = Device.from_name("PTH660", "Pen") opts["PanScrollThreshold"] = "150" + opts["SmoothPanscrollingEnabled"] = "true" if smooth else "false" prox_in = [ Sev("ABS_X", 50), @@ -379,17 +381,30 @@ def test_scroll(mainloop, opts, vertical): monitor.write_events(prox_out) mainloop.run() - have_we_scrolled = False - for event in monitor.events: - if vertical: - if event.axes.scroll_y != 0: - assert event.axes.scroll_y == -808265 - have_we_scrolled = True - else: - if event.axes.scroll_x != 0: - assert event.axes.scroll_x == -1223320 - have_we_scrolled = True - assert have_we_scrolled + if smooth: + have_we_scrolled = False + for event in monitor.events: + if vertical: + if event.axes.scroll_y != 0: + assert event.axes.scroll_y == -808265 + have_we_scrolled = True + else: + if event.axes.scroll_x != 0: + assert event.axes.scroll_x == -1223320 + have_we_scrolled = True + assert have_we_scrolled + else: + have_button_events = False + for event in monitor.events: + if isinstance(event, Button): + print(event.button) + if vertical: + if event.button == 4: # we're moving bottom-to-top + have_button_events = True + else: + if event.button == 6: # we're moving right-to-left + have_button_events = True + assert have_button_events # vim: set expandtab tabstop=4 shiftwidth=4: From 2612afb19e37fed69f3aca534d213a0d7e71b595 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 14 Nov 2023 12:31:50 +1000 Subject: [PATCH 21/53] Move the pressurecurve calculation into a separate file There's nothing driver-specific about this and it allows us to test it separately or write tools to test it. --- meson.build | 1 + src/common.mk | 2 + src/wcmFilter.c | 134 +---------------------------------- src/wcmPressureCurve.c | 156 +++++++++++++++++++++++++++++++++++++++++ src/wcmPressureCurve.h | 24 +++++++ 5 files changed, 184 insertions(+), 133 deletions(-) create mode 100644 src/wcmPressureCurve.c create mode 100644 src/wcmPressureCurve.h diff --git a/meson.build b/meson.build index 2166b208..092eff6e 100644 --- a/meson.build +++ b/meson.build @@ -130,6 +130,7 @@ src_wacom_core = [ 'src/wcmConfig.c', 'src/wcmFilter.c', 'src/wcmFilter.h', + 'src/wcmPressureCurve.c', 'src/wcmTouchFilter.c', 'src/wcmTouchFilter.h', 'src/wcmUSB.c', diff --git a/src/common.mk b/src/common.mk index 745c7101..19bd89dc 100644 --- a/src/common.mk +++ b/src/common.mk @@ -9,6 +9,8 @@ DRIVER_SOURCES= \ $(top_srcdir)/src/wcmConfig.c \ $(top_srcdir)/src/wcmFilter.c \ $(top_srcdir)/src/wcmFilter.h \ + $(top_srcdir)/src/wcmPressureCurve.c \ + $(top_srcdir)/src/wcmPressureCurve.h \ $(top_srcdir)/src/xf86WacomDefs.h \ $(top_srcdir)/src/wcmUSB.c \ $(top_srcdir)/src/wcmValidateDevice.c \ diff --git a/src/wcmFilter.c b/src/wcmFilter.c index 6c9839b1..7f4af3ac 100644 --- a/src/wcmFilter.c +++ b/src/wcmFilter.c @@ -22,17 +22,7 @@ #include #include "xf86Wacom.h" #include "wcmFilter.h" - -/***************************************************************************** - * Static functions - ****************************************************************************/ - -static void filterCurveToLine(int* pCurve, int nMax, double x0, double y0, - double x1, double y1, double x2, double y2, - double x3, double y3); -static int filterOnLine(double x0, double y0, double x1, double y1, - double a, double b); -static void filterLine(int* pCurve, int nMax, int x0, int y0, int x1, int y1); +#include "wcmPressureCurve.h" /***************************************************************************** @@ -101,128 +91,6 @@ void wcmResetSampleCounter(const WacomChannelPtr pChannel) } -static void filterNearestPoint(double x0, double y0, double x1, double y1, - double a, double b, double* x, double* y) -{ - double vx, vy, wx, wy, d1, d2, c; - - wx = a - x0; wy = b - y0; - vx = x1 - x0; vy = y1 - y0; - - d1 = vx * wx + vy * wy; - if (d1 <= 0) - { - *x = x0; - *y = y0; - } - else - { - d2 = vx * vx + vy * vy; - if (d1 >= d2) - { - *x = x1; - *y = y1; - } - else - { - c = d1 / d2; - *x = x0 + c * vx; - *y = y0 + c * vy; - } - } -} - -static int filterOnLine(double x0, double y0, double x1, double y1, - double a, double b) -{ - double x, y, d; - filterNearestPoint(x0,y0,x1,y1,a,b,&x,&y); - d = (x-a)*(x-a) + (y-b)*(y-b); - return d < 0.00001; /* within 100th of a point (1E-2 squared) */ -} - -static void filterCurveToLine(int* pCurve, int nMax, double x0, double y0, - double x1, double y1, double x2, double y2, - double x3, double y3) -{ - double x01,y01,x32,y32,xm,ym; - double c1,d1,c2,d2,e,f; - - /* check if control points are on line */ - if (filterOnLine(x0,y0,x3,y3,x1,y1) && filterOnLine(x0,y0,x3,y3,x2,y2)) - { - filterLine(pCurve,nMax, - (int)(x0*nMax),(int)(y0*nMax), - (int)(x3*nMax),(int)(y3*nMax)); - return; - } - - /* calculate midpoints */ - x01 = (x0 + x1) / 2; y01 = (y0 + y1) / 2; - x32 = (x3 + x2) / 2; y32 = (y3 + y2) / 2; - - /* calc split point */ - xm = (x1 + x2) / 2; ym = (y1 + y2) / 2; - - /* calc control points and midpoint */ - c1 = (x01 + xm) / 2; d1 = (y01 + ym) / 2; - c2 = (x32 + xm) / 2; d2 = (y32 + ym) / 2; - e = (c1 + c2) / 2; f = (d1 + d2) / 2; - - /* do each side */ - filterCurveToLine(pCurve,nMax,x0,y0,x01,y01,c1,d1,e,f); - filterCurveToLine(pCurve,nMax,e,f,c2,d2,x32,y32,x3,y3); -} - -static void filterLine(int* pCurve, int nMax, int x0, int y0, int x1, int y1) -{ - int dx, dy, ax, ay, sx, sy, x, y, d; - - /* sanity check */ - if ((x0 < 0) || (y0 < 0) || (x1 < 0) || (y1 < 0) || - (x0 > nMax) || (y0 > nMax) || (x1 > nMax) || (y1 > nMax)) - return; - - dx = x1 - x0; ax = abs(dx) * 2; sx = (dx>0) ? 1 : -1; - dy = y1 - y0; ay = abs(dy) * 2; sy = (dy>0) ? 1 : -1; - x = x0; y = y0; - - /* x dominant */ - if (ax > ay) - { - d = ay - ax / 2; - while (1) - { - pCurve[x] = y; - if (x == x1) break; - if (d >= 0) - { - y += sy; - d -= ax; - } - x += sx; - d += ay; - } - } - - /* y dominant */ - else - { - d = ax - ay / 2; - while (1) - { - pCurve[x] = y; - if (y == y1) break; - if (d >= 0) - { - x += sx; - d -= ay; - } - y += sy; - d += ax; - } - } -} static void storeRawSample(WacomCommonPtr common, WacomChannelPtr pChannel, WacomDeviceStatePtr ds) { diff --git a/src/wcmPressureCurve.c b/src/wcmPressureCurve.c new file mode 100644 index 00000000..2145d69f --- /dev/null +++ b/src/wcmPressureCurve.c @@ -0,0 +1,156 @@ +/* + * Copyright 1995-2002 by Frederic Lepied, France. + * Copyright 2002-2008 by Ping Cheng, Wacom. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include "wcmPressureCurve.h" + +#include +#include + +static int filterOnLine(double x0, double y0, double x1, double y1, + double a, double b); +static void filterLine(int* pCurve, int nMax, int x0, int y0, int x1, int y1); + + +static void filterNearestPoint(double x0, double y0, double x1, double y1, + double a, double b, double* x, double* y) +{ + double vx, vy, wx, wy, d1, d2, c; + + wx = a - x0; wy = b - y0; + vx = x1 - x0; vy = y1 - y0; + + d1 = vx * wx + vy * wy; + if (d1 <= 0) + { + *x = x0; + *y = y0; + } + else + { + d2 = vx * vx + vy * vy; + if (d1 >= d2) + { + *x = x1; + *y = y1; + } + else + { + c = d1 / d2; + *x = x0 + c * vx; + *y = y0 + c * vy; + } + } +} + +static int filterOnLine(double x0, double y0, double x1, double y1, + double a, double b) +{ + double x, y, d; + filterNearestPoint(x0,y0,x1,y1,a,b,&x,&y); + d = (x-a)*(x-a) + (y-b)*(y-b); + return d < 0.00001; /* within 100th of a point (1E-2 squared) */ +} + +void filterCurveToLine(int* pCurve, int nMax, double x0, double y0, + double x1, double y1, double x2, double y2, + double x3, double y3) +{ + double x01,y01,x32,y32,xm,ym; + double c1,d1,c2,d2,e,f; + + /* check if control points are on line */ + if (filterOnLine(x0,y0,x3,y3,x1,y1) && filterOnLine(x0,y0,x3,y3,x2,y2)) + { + filterLine(pCurve,nMax, + (int)(x0*nMax),(int)(y0*nMax), + (int)(x3*nMax),(int)(y3*nMax)); + return; + } + + /* calculate midpoints */ + x01 = (x0 + x1) / 2; y01 = (y0 + y1) / 2; + x32 = (x3 + x2) / 2; y32 = (y3 + y2) / 2; + + /* calc split point */ + xm = (x1 + x2) / 2; ym = (y1 + y2) / 2; + + /* calc control points and midpoint */ + c1 = (x01 + xm) / 2; d1 = (y01 + ym) / 2; + c2 = (x32 + xm) / 2; d2 = (y32 + ym) / 2; + e = (c1 + c2) / 2; f = (d1 + d2) / 2; + + /* do each side */ + filterCurveToLine(pCurve,nMax,x0,y0,x01,y01,c1,d1,e,f); + filterCurveToLine(pCurve,nMax,e,f,c2,d2,x32,y32,x3,y3); +} + +static void filterLine(int* pCurve, int nMax, int x0, int y0, int x1, int y1) +{ + int dx, dy, ax, ay, sx, sy, x, y, d; + + /* sanity check */ + if ((x0 < 0) || (y0 < 0) || (x1 < 0) || (y1 < 0) || + (x0 > nMax) || (y0 > nMax) || (x1 > nMax) || (y1 > nMax)) + return; + + dx = x1 - x0; ax = abs(dx) * 2; sx = (dx>0) ? 1 : -1; + dy = y1 - y0; ay = abs(dy) * 2; sy = (dy>0) ? 1 : -1; + x = x0; y = y0; + + /* x dominant */ + if (ax > ay) + { + d = ay - ax / 2; + while (1) + { + pCurve[x] = y; + if (x == x1) break; + if (d >= 0) + { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } + } + + /* y dominant */ + else + { + d = ax - ay / 2; + while (1) + { + pCurve[x] = y; + if (y == y1) break; + if (d >= 0) + { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } +} + +/* vim: set noexpandtab tabstop=8 shiftwidth=8: */ + diff --git a/src/wcmPressureCurve.h b/src/wcmPressureCurve.h new file mode 100644 index 00000000..496d734d --- /dev/null +++ b/src/wcmPressureCurve.h @@ -0,0 +1,24 @@ +/* + * Copyright 1995-2002 by Frederic Lepied, France. + * Copyright 2002-2008 by Ping Cheng, Wacom. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +void filterCurveToLine(int* pCurve, int nMax, double x0, double y0, + double x1, double y1, double x2, double y2, + double x3, double y3); From 3d3b474a750106f8db7c47d0088209f8ec3ae1c4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 14 Nov 2023 14:02:48 +1000 Subject: [PATCH 22/53] Add a pressurecurve debugging tool This tool takes (one or multiple) sets of 4 coordinate that represent the second and third point for our pressure curve (first and fourth points are hardcoded to 0/0 and 1/1 like the driver does) It spits out gnuplot-compatible lines that can be printed for visual debugging. Usage to print the GNOME default curves: ./build/pressurecurve \ 0 .75 .25 1 \ 0 .5 .5 1 \ 0 .25 .75 1 \ 0 0 1 1 \ .25 0 1 .75 \ .5 0 1 .5 \ .75 0 1 .25 > gnuplot.data And that gnuplot data can then be printed with: #!/usr/bin/gnuplot set terminal qt persist set style data lines set xrange [0:1] set yrange [0:1] plot \ "gnuplot.data" using 1:2 title " 0, .75, .25, 1", \ "gnuplot.data" using 1:3 title " 0, .50, .50, 1", \ "gnuplot.data" using 1:4 title " 0, .25, .75, 1", \ "gnuplot.data" using 1:5 title " 0, 0, 1, 1", \ "gnuplot.data" using 1:6 title ".25, 0, 1, .75", \ "gnuplot.data" using 1:7 title ".50, 0, 1, .50", \ "gnuplot.data" using 1:8 title ".75, 0, 1, .25" --- meson.build | 7 +++ tools/Makefile.am | 2 +- tools/pressurecurve.c | 114 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 tools/pressurecurve.c diff --git a/meson.build b/meson.build index 092eff6e..506fb014 100644 --- a/meson.build +++ b/meson.build @@ -295,6 +295,13 @@ executable( install: true, ) +executable( + 'pressurecurve', + ['tools/pressurecurve.c', + 'src/wcmPressureCurve.c'], + include_directories: [dir_src], + install: false) + # Man pages config_man = configuration_data() config_man.set('VERSION', '@0@ @1@'.format(meson.project_name(), meson.project_version())) diff --git a/tools/Makefile.am b/tools/Makefile.am index d54ab713..ecd9e832 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -46,4 +46,4 @@ xsetwacom_test_LDADD = $(X11_LIBS) TESTS=$(check_PROGRAMS) endif -EXTRA_DIST = wacom-record.c +EXTRA_DIST = wacom-record.c pressurecurve.c diff --git a/tools/pressurecurve.c b/tools/pressurecurve.c new file mode 100644 index 00000000..b96bec21 --- /dev/null +++ b/tools/pressurecurve.c @@ -0,0 +1,114 @@ +/* + * Copyright 2023 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include +#include +#include +#include + +#include "wcmPressureCurve.h" + +static void +usage(void) { + printf("Usage: pressurecurve [OPTIONS] x1 y1 x2 y2 ...\n"); + printf("\n"); + printf("This tool takes four coordinates in the range [0.0, 1.0] representing \n" + "the driver's pressure curve configuration.\n" + "The output contains one line with input pressure and output pressure for\n" + "each normalized [0.0, 1.0] input pressure value\n" + "\n" + "Multiple sets of 4 coordinates may be given \n"); +} + +int main(int argc, char **argv) +{ + /* The driver pre-calculates the pressurecurve for each possible + * pressure value. Typically this is 2k or 8k for newer pens, here + * we use 1000 points to get smooth gnuplot output. + * + * The value in filterCurveToLine() is normalized into this range so + * the curve will have values in the range [0, 1000]. + */ + const size_t npoints = 1000; + + /* These two are hardcoded by the driver */ + const double x0 = 0.0, y0 = 0.0; + const double x3 = 1.0, y3 = 1.0; + + enum { + OPT_HELP, + }; + + static struct option long_options[] = { + {"help", no_argument, 0, OPT_HELP}, + {0, 0, 0, 0}, + }; + + int c; + while (1) + { + int option_index = 0; + + c = getopt_long(argc, argv, "", long_options, &option_index); + if (c == -1) + break; + switch (c) { + case OPT_HELP: + usage(); + return 0; + default: + break; + } + } + + if (optind + 4 > argc || (argc - optind) % 4 != 0) { + usage(); + return 1; + + } + + size_t ncurves = (argc - optind) / 4; + int curve[ncurves][npoints]; + int idx = 0; + + printf("# column 0: input pressure value [0,1]\n"); + while (optind < argc) + { + double x1 = atof(argv[optind++]); + double y1 = atof(argv[optind++]); + double x2 = atof(argv[optind++]); + double y2 = atof(argv[optind++]); + + filterCurveToLine(curve[idx], npoints, x0, y0, x1, y1, x2, y2, x3, y3); + + printf("# column %d: %f/%f %f/%f %f/%f %f/%f\n", idx, x0, y0, x1, y1, x2, y2, x3, y3); + idx++; + } + + for (size_t i = 0; i < npoints; i++) + { + printf("%f", i/(double)npoints); + for (size_t j = 0; j < ncurves; j++) + printf(" %f", curve[j][i]/(double)npoints); + printf("\n"); + } + + return 0; +} From dbb8ddce94b7bfe416dd88b6ea286538940d9d38 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Thu, 30 Nov 2023 07:47:43 -0800 Subject: [PATCH 23/53] github: Minimize permissions granted to automated workflows / jobs Jobs that use the GITHUB_TOKEN to perform sensitive actions on behalf of a real user may be granted a range of permissions. Instead of granting blanket permissions to read and write "all" APIs, we should really limit the permissions what any individual workflow or job can do. This commit sets the default permissions for each workflow to "contents: read", which allows jobs to only read from the repository. Link: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idpermissions Signed-off-by: Jason Gerecke --- .github/workflows/black.yml | 3 +++ .github/workflows/build.yml | 3 +++ .github/workflows/coverity.yml | 3 +++ 3 files changed, 9 insertions(+) diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index ff250367..62941bb0 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -1,5 +1,8 @@ on: [ push, pull_request ] +permissions: + contents: read + jobs: python-black: runs-on: ubuntu-20.04 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8c664f79..db43c6da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,5 +1,8 @@ on: [ push, pull_request ] +permissions: + contents: read + env: CFLAGS: -Werror UBUNTU_PACKAGES: | diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index cda14052..3720800f 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -3,6 +3,9 @@ on: - cron: '0 0 1,15 * *' workflow_dispatch: +permissions: + contents: read + env: COVERITY_SCAN_PROJECT_NAME: linuxwacom/xf86-input-wacom COVERITY_SCAN_NOTIFICATION_EMAIL: killertofu@gmail.com From bf61b3e22b2bb25dc9aed76103488eb7ebc47bb5 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Thu, 30 Nov 2023 08:02:08 -0800 Subject: [PATCH 24/53] wcmUSB: Correct bounds check of maximum button number Automated test runs have detected the following issue while running UBSan checks: ~~~ ../src/wcmUSB.c:1372:11: runtime error: left shift of 1 by 31 places cannot be represented in type 'int' #0 0x7f0444bcbd8c in mod_buttons ../src/wcmUSB.c:1372 #1 0x7f0444bd7f26 in test_mod_buttons ../src/wcmUSB.c:2090 #2 0x7f0444bfcea7 in wcm_run_tests ../test/wacom-test-suite.c:46 #3 0x56204d77b405 in main ../test/wacom-tests.c:44 #4 0x7f0448625082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) #5 0x56204d77b1cd in _start (/home/runner/work/xf86-input-wacom/xf86-input-wacom/builddir/wacom-tests+0x11cd) SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../src/wcmUSB.c:1372:11 in ~~~ While the faulty line has some protection against an excessively-large value of 'btn', the bounds are incorrect. A button number of 32 would be allowed by the existing check but would also lead to undefined behavior. This commit modifies the bounds to properly fit the condition. Link: https://github.com/linuxwacom/xf86-input-wacom/actions/runs/7049012015/job/19186502078 Signed-off-by: Jason Gerecke --- src/wcmUSB.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wcmUSB.c b/src/wcmUSB.c index b7b3d060..40649776 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -1361,7 +1361,7 @@ mod_buttons(WacomCommonPtr common, unsigned int buttons, unsigned int btn, Bool { unsigned int mask; - if (btn >= sizeof(int) * 8) + if (btn >= sizeof(int) * 8 - 1) { wcmLogCommonSafe(common, W_ERROR, "%s: Invalid button number %u. Insufficient storage\n", @@ -2085,7 +2085,7 @@ static int usbProbeKeys(WacomDevicePtr priv) TEST_CASE(test_mod_buttons) { WacomCommonRec common = {0}; - for (size_t i = 0; i < sizeof(int) * 8; i++) + for (size_t i = 0; i < sizeof(int) * 8 - 1; i++) { unsigned int buttons = mod_buttons(&common, 0, i, 1); assert(buttons == (1u << i)); @@ -2093,6 +2093,7 @@ TEST_CASE(test_mod_buttons) assert(buttons == 0); } + assert(mod_buttons(&common, 0, sizeof(int) * 8 - 1, 1) == 0); assert(mod_buttons(&common, 0, sizeof(int) * 8, 1) == 0); } From 73f66d42d72c2c758c09acab84b13dab065886d3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 1 Dec 2023 09:14:11 +1000 Subject: [PATCH 25/53] Revert "wcmUSB: Correct bounds check of maximum button number" This fixed the wrong issue, the undefined behavior was caused by (1 << btn) defaulting to int rather than unsigned int. See the follow-up commit for a fix. This reverts commit bf61b3e22b2bb25dc9aed76103488eb7ebc47bb5. --- src/wcmUSB.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/wcmUSB.c b/src/wcmUSB.c index 40649776..b7b3d060 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -1361,7 +1361,7 @@ mod_buttons(WacomCommonPtr common, unsigned int buttons, unsigned int btn, Bool { unsigned int mask; - if (btn >= sizeof(int) * 8 - 1) + if (btn >= sizeof(int) * 8) { wcmLogCommonSafe(common, W_ERROR, "%s: Invalid button number %u. Insufficient storage\n", @@ -2085,7 +2085,7 @@ static int usbProbeKeys(WacomDevicePtr priv) TEST_CASE(test_mod_buttons) { WacomCommonRec common = {0}; - for (size_t i = 0; i < sizeof(int) * 8 - 1; i++) + for (size_t i = 0; i < sizeof(int) * 8; i++) { unsigned int buttons = mod_buttons(&common, 0, i, 1); assert(buttons == (1u << i)); @@ -2093,7 +2093,6 @@ TEST_CASE(test_mod_buttons) assert(buttons == 0); } - assert(mod_buttons(&common, 0, sizeof(int) * 8 - 1, 1) == 0); assert(mod_buttons(&common, 0, sizeof(int) * 8, 1) == 0); } From f963825e9a2ff531ca16e36408a42c8e2b9e48c3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 1 Dec 2023 09:16:21 +1000 Subject: [PATCH 26/53] wcmUSB: fix undefined behavior for bit-shifting Automated test runs have detected the following issue while running UBSan checks: ~~~ ../src/wcmUSB.c:1372:11: runtime error: left shift of 1 by 31 places cannot be represented in type 'int' #0 0x7f0444bcbd8c in mod_buttons ../src/wcmUSB.c:1372 #1 0x7f0444bd7f26 in test_mod_buttons ../src/wcmUSB.c:2090 #2 0x7f0444bfcea7 in wcm_run_tests ../test/wacom-test-suite.c:46 #3 0x56204d77b405 in main ../test/wacom-tests.c:44 #4 0x7f0448625082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) #5 0x56204d77b1cd in _start (/home/runner/work/xf86-input-wacom/xf86-input-wacom/builddir/wacom-tests+0x11cd) SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../src/wcmUSB.c:1372:11 in The default type of a literal `1` is `int` and thus a leftshift of 31 is not permitted. Switch it to `1u` and thus `unsigned int` for Button 31 which is the max button we support (if zero-indexed). Link: https://github.com/linuxwacom/xf86-input-wacom/actions/runs/7049012015/job/19186502078 Signed-off-by: Peter Hutterer --- src/wcmUSB.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wcmUSB.c b/src/wcmUSB.c index b7b3d060..33f8b67a 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -1369,7 +1369,7 @@ mod_buttons(WacomCommonPtr common, unsigned int buttons, unsigned int btn, Bool return buttons; } - mask = 1 << btn; + mask = 1u << btn; if (state) buttons |= mask; From 6f8ed055c655fdd3a0f91870817864ecd81c4d8a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 29 Feb 2024 15:04:18 +1000 Subject: [PATCH 27/53] CI: bump our containers to use Ubuntu 22.04 --- .github/workflows/black.yml | 2 +- .github/workflows/build.yml | 12 ++++++------ .github/workflows/coverity.yml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index 62941bb0..a1d43144 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -5,7 +5,7 @@ permissions: jobs: python-black: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout the repo uses: actions/checkout@v3 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index db43c6da..18eb56dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ env: jobs: compile-with-autotools: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: matrix: compiler: [ gcc, clang ] @@ -59,7 +59,7 @@ jobs: path: xf86-input-wacom-*tar.bz2 compile-with-meson: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: matrix: compiler: @@ -93,7 +93,7 @@ jobs: builddir/meson-logs/meson-log.txt compile-with-meson-exact-version: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 - uses: linuxwacom/libwacom/.github/actions/pkginstall@master @@ -121,7 +121,7 @@ jobs: # build-from-tarball-autotools: needs: compile-with-autotools - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: TARBALLDIR: '_tarball_dir' INSTALLDIR: '/tmp/_inst' @@ -150,7 +150,7 @@ jobs: build-from-tarball-meson: needs: compile-with-autotools - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: TARBALLDIR: '_tarball_dir' INSTALLDIR: '/tmp/_inst' @@ -185,7 +185,7 @@ jobs: check-tarball-files: needs: compile-with-autotools - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: TARBALLDIR: '_tarball_dir' steps: diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 3720800f..fcd08611 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -17,7 +17,7 @@ env: jobs: coverity: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 environment: coverity if: ${{ github.repository == '$COVERITY_SCAN_PROJECT_NAME' }} steps: From 3ce73a61a17ca1cbb222c67c0c803a7e40d0b993 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 20 Feb 2024 10:52:25 +1000 Subject: [PATCH 28/53] meson.build: allow disabling the xsetwacom build xsetwacom pulls in the xorgproto and Xlib dependencies, so let's make this optional for the (niche) case of where we really only want the driver built. Since this is a rather niche case let's make it a boolean true/false option instead of a feature with "auto". --- meson.build | 68 ++++++++++++++++++++++++++--------------------- meson_options.txt | 5 ++++ 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/meson.build b/meson.build index 506fb014..d5db3e94 100644 --- a/meson.build +++ b/meson.build @@ -47,20 +47,24 @@ cflags = [ add_project_arguments(cc.get_supported_arguments(cflags), language : 'c') add_project_arguments('-D_GNU_SOURCE', language : 'c') +build_xsetwacom = get_option('xsetwacom') # Dependencies pkgconfig = import('pkgconfig') -dep_protos = [] -protos = ['xproto', 'xext', 'kbproto', 'inputproto', 'randrproto'] -foreach proto : protos - dep_protos += [dependency(proto)] -endforeach dep_xserver = dependency('xorg-server', version: '>= 1.13.0') -xlibs = ['x11', 'xi', 'xrandr', 'xinerama'] -dep_xlibs = [] -foreach xlib : xlibs - dep_xlibs += [dependency(xlib)] -endforeach +if build_xsetwacom + dep_protos = [] + protos = ['xproto', 'xext', 'kbproto', 'inputproto', 'randrproto'] + foreach proto : protos + dep_protos += [dependency(proto)] + endforeach + + xlibs = ['x11', 'xi', 'xrandr', 'xinerama'] + dep_xlibs = [] + foreach xlib : xlibs + dep_xlibs += [dependency(xlib)] + endforeach +endif dep_libudev = dependency('libudev') dep_m = cc.find_library('m') @@ -282,18 +286,20 @@ if get_option('serial-device-support') ) endif -xsetwacom_deps = [dep_xlibs, dep_protos, dep_m] -src_xsetwacom = [ - config_ver_h, - 'tools/xsetwacom.c', -] -executable( - 'xsetwacom', - src_xsetwacom, - dependencies: xsetwacom_deps, - include_directories: [dir_include], - install: true, -) +if build_xsetwacom + xsetwacom_deps = [dep_xlibs, dep_protos, dep_m] + src_xsetwacom = [ + config_ver_h, + 'tools/xsetwacom.c', + ] + executable( + 'xsetwacom', + src_xsetwacom, + dependencies: xsetwacom_deps, + include_directories: [dir_include], + install: true, + ) +endif executable( 'pressurecurve', @@ -337,14 +343,16 @@ endif build_unittests = not get_option('unittests').disabled() if build_unittests - xsetwacom_test = executable( - 'xsetwacom-test', - src_xsetwacom + ['test/wacom-test-suite.c', 'test/wacom-test-suite.h'], - c_args: ['-DENABLE_TESTS', '-Wno-unused-function'], - dependencies: xsetwacom_deps, - include_directories: [dir_include, dir_src, dir_src_test], - ) - test('xsetwacom-tests', xsetwacom_test) + if build_xsetwacom + xsetwacom_test = executable( + 'xsetwacom-test', + src_xsetwacom + ['test/wacom-test-suite.c', 'test/wacom-test-suite.h'], + c_args: ['-DENABLE_TESTS', '-Wno-unused-function'], + dependencies: xsetwacom_deps, + include_directories: [dir_include, dir_src, dir_src_test], + ) + test('xsetwacom-tests', xsetwacom_test) + endif # Rebuild the driver with -DENABLE_TESTS to enable all the various # local tests in the files. This is built as a module (like the diff --git a/meson_options.txt b/meson_options.txt index f58af9d3..17b32d33 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -48,3 +48,8 @@ option('wacom-gobject', value: 'auto', description: 'Build the Wacom GObject library and associated tools [default: auto]' ) +option('xsetwacom', + type: 'boolean', + value: 'true', + description: 'Build the xsetwacom tool [default: true]' +) From d73eb2ee78670cc2b1d7cc3861f466867ccba479 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 4 Mar 2024 09:33:07 +1000 Subject: [PATCH 29/53] wacom 1.2.1 Signed-off-by: Peter Hutterer --- configure.ac | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 354dfb4e..35f4b0b2 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ AC_PREREQ([2.60]) # bump version in meson.build AC_INIT([xf86-input-wacom], - [1.2.0], + [1.2.1], [https://github.com/linuxwacom/xf86-input-wacom/issues/], [xf86-input-wacom]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/meson.build b/meson.build index d5db3e94..cd04e053 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('xf86-input-wacom', 'c', - version : '1.1.0', # bump version in configure.ac + version : '1.2.1', # bump version in configure.ac license : 'MIT/Expat', default_options : [ 'c_std=gnu99', 'warning_level=2' ], meson_version : '>= 0.51.0') From 564e034166141976ba9e88de098043bf6bc73046 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 11 Mar 2024 10:33:17 +1000 Subject: [PATCH 30/53] release.sh: update to take a --token value (#340) Apparently the old way no longer works, so let's update with a copy/paste from the examples. Intentional switch to use --token because that's how you should be doing releases anyway - with a temporary token that can be revoked after the release is complete (and that also encodes the username). https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#create-a-release --- release.sh | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/release.sh b/release.sh index 9d50ab80..f5cd9c30 100755 --- a/release.sh +++ b/release.sh @@ -96,25 +96,32 @@ release_to_github() { "body": %s, "draft": false, "prerelease": false}' "$tar_name" "$tar_name" "$release_descr") - create_result=`curl -s --data "$api_json" -u $GH_USERNAME https://api.github.com/repos/$GH_REPO/$PROJECT/releases` + create_result=$(curl -s --data "$api_json" \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $TOKEN" \ + https://api.github.com/repos/$GH_REPO/$PROJECT/releases) GH_RELEASE_ID=`echo $create_result | jq '.id'` check_json_message "$create_result" # Upload the tar to the release - upload_result=`curl -s -u $GH_USERNAME \ + upload_result=$(curl -s \ -H "Content-Type: application/x-bzip" \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $TOKEN" \ --data-binary @$tarball \ - "https://uploads.github.com/repos/$GH_REPO/$PROJECT/releases/$GH_RELEASE_ID/assets?name=$tarball"` + "https://uploads.github.com/repos/$GH_REPO/$PROJECT/releases/$GH_RELEASE_ID/assets?name=$tarball") DL_URL=`echo $upload_result | jq -r '.browser_download_url'` check_json_message "$upload_result" # Upload the sig to the release - sig_result=`curl -s -u $GH_USERNAME \ + sig_result=$(curl -s \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/pgp-signature" \ --data-binary @$tarball.sig \ - "https://uploads.github.com/repos/$GH_REPO/$PROJECT/releases/$GH_RELEASE_ID/assets?name=$tarball.sig"` + "https://uploads.github.com/repos/$GH_REPO/$PROJECT/releases/$GH_RELEASE_ID/assets?name=$tarball.sig") PGP_URL=`echo $sig_result | jq -r '.browser_download_url'` check_json_message "$sig_result" @@ -557,7 +564,10 @@ process_module() { "body": %s, "draft": false, "prerelease": false}' "$tar_name" "$tar_name" "$release_descr") - create_result=`curl -s -X PATCH --data "$api_json" -u $GH_USERNAME https://api.github.com/repos/$GH_REPO/$PROJECT/releases/$GH_RELEASE_ID` + create_result=$(curl -s -X PATCH --data "$api_json" \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $TOKEN" \ + https://api.github.com/repos/$GH_REPO/$PROJECT/releases/$GH_RELEASE_ID) check_json_message "$create_result" echo "Git shortlog posted to the release at Github, please edit the release to add a description of what's interesting." @@ -590,7 +600,7 @@ Options: --help Display this help and exit successfully --moduleset The jhbuild moduleset full pathname to be updated --no-quit Do not quit after error; just print error message - --github Release project to Github with username / token + --token GitHub personal access token value Environment variables defined by the "make" program and used by release.sh: MAKE The name of the make command [make] @@ -663,11 +673,9 @@ do --no-quit) NO_QUIT=yes ;; - # Github username. Optional. Append colon and Personal - # Access Token to username if 2FA is enabled on the user - # account doing the release - --github) - GH_USERNAME=$2 + # Personal GitHub Access Token to create the release + --token) + TOKEN=$2 shift ;; --*) @@ -692,11 +700,6 @@ do shift done -if [[ x$GH_USERNAME = "x" ]] ; then - GH_USERNAME=`whoami` - echo "--github missing, using local username as github username" -fi - # If no modules specified (blank cmd line) display help check_modules_specification From 29e27f27401fc2a18f8feabc09959cae38cc11ab Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 11 Mar 2024 10:36:34 +1000 Subject: [PATCH 31/53] release.sh: default to '.' if no module was given Might as well since we only ever release one module at a time with this script. --- release.sh | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/release.sh b/release.sh index f5cd9c30..daf80ef3 100755 --- a/release.sh +++ b/release.sh @@ -44,19 +44,6 @@ check_local_changes() { return 0 } -#------------------------------------------------------------------------------ -# Function: check_modules_specification -#------------------------------------------------------------------------------ -# -check_modules_specification() { - if [ x"${INPUT_MODULES}" = x ]; then - echo "" - echo "Error: no modules specified (blank command line)." - usage - exit 1 - fi -} - #------------------------------------------------------------------------------ # Function: check_json_message #------------------------------------------------------------------------------ @@ -588,9 +575,9 @@ usage() { basename="`expr "//$0" : '.*/\([^/]*\)'`" cat < Date: Mon, 11 Mar 2024 10:37:35 +1000 Subject: [PATCH 32/53] release.sh: drop --force and --moduleset No longer hooked into anything so let's not pretend we have it. --- release.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/release.sh b/release.sh index daf80ef3..559e7f4a 100755 --- a/release.sh +++ b/release.sh @@ -583,9 +583,7 @@ Options: --dist make 'dist' instead of 'distcheck'; use with caution --distcheck Default, ignored for compatibility --dry-run Does everything except tagging and uploading tarballs - --force Force overwriting an existing release --help Display this help and exit successfully - --moduleset The jhbuild moduleset full pathname to be updated --no-quit Do not quit after error; just print error message --token GitHub personal access token value @@ -646,11 +644,6 @@ do --dry-run) DRY_RUN=yes ;; - # Force overwriting an existing release - # Use only if nothing changed in the git repo - --force) - FORCE=yes - ;; # Display this help and exit successfully --help) usage From f4241514b725377e03ad55b4dbe8750cd3e4e5f4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 11 Mar 2024 10:43:17 +1000 Subject: [PATCH 33/53] release.sh: Drop the ancient x"foo" != x comparisons These haven't been needed in decades. Where a string may be empty use quotes, otherwise let's switch string comparisons to just that. And where we check for empty/nonempty use -z/-n. --- release.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/release.sh b/release.sh index 559e7f4a..82f49277 100755 --- a/release.sh +++ b/release.sh @@ -163,11 +163,11 @@ RELEASE print_epilog() { epilog="======== Successful Completion" - if [ x"$NO_QUIT" != x ]; then - if [ x"$failed_modules" != x ]; then + if [ -n "$NO_QUIT" ]; then + if [ -n "$failed_modules" ]; then epilog="======== Partial Completion" fi - elif [ x"$failed_modules" != x ]; then + elif [ -n "$failed_modules" ]; then epilog="======== Stopped on Error" fi @@ -175,7 +175,7 @@ print_epilog() { echo "$epilog `date`" # Report about modules that failed for one reason or another - if [ x"$failed_modules" != x ]; then + if [ -n "$failed_modules" ]; then echo " List of failed modules:" for mod in $failed_modules; do echo " $mod" @@ -197,7 +197,7 @@ process_modules() { if ! process_module ; then echo "Error: processing module \"$MODULE_RPATH\" failed." failed_modules="$failed_modules $MODULE_RPATH" - if [ x"$NO_QUIT" = x ]; then + if [ -z "$NO_QUIT" ]; then print_epilog exit 1 fi @@ -248,7 +248,7 @@ get_section() { return 1 fi - if [ x"$section" = xlinuxwacom ]; then + if [ "$section" = "linuxwacom" ]; then section=`echo $module_url | cut -d'/' -f2` if [ $? -ne 0 ]; then echo "Error: unable to extract section from $module_url second field." @@ -337,7 +337,7 @@ process_module() { echo "Error: failed to locate $buildfile." echo "Has the module been configured?" return 1 - elif [ x"$configNum" != x1 ]; then + elif [ "$configNum" != "1" ]; then echo "Error: more than one $buildfile file was found," echo " clean-up previously failed attempts at distcheck" return 1 @@ -453,7 +453,7 @@ process_module() { cd $top_src return 1 fi - if [ x"$remote_top_commit_sha" != x"$local_top_commit_sha" ]; then + if [ "$remote_top_commit_sha" != "$local_top_commit_sha" ]; then echo "Error: the local top commit has not been pushed to the remote." local_top_commit_descr=`git log --oneline --max-count=1 $local_top_commit_sha` echo " the local top commit is: \"$local_top_commit_descr\"" @@ -466,7 +466,7 @@ process_module() { tagged_commit_sha=`git rev-list --max-count=1 $tag_name 2>/dev/null` if [ $? -eq 0 ]; then # Check if the tag is pointing to the top commit - if [ x"$tagged_commit_sha" != x"$remote_top_commit_sha" ]; then + if [ "$tagged_commit_sha" != "$remote_top_commit_sha" ]; then echo "Error: the \"$tag_name\" already exists." echo " this tag is not tagging the top commit." remote_top_commit_descr=`git log --oneline --max-count=1 $remote_top_commit_sha` @@ -480,7 +480,7 @@ process_module() { fi else # Tag the top commit with the tar name - if [ x"$DRY_RUN" = x ]; then + if [ -z "$DRY_RUN" ]; then git tag -s -m $tag_name $tag_name if [ $? -ne 0 ]; then echo "Error: unable to tag module with \"$tag_name\"." @@ -528,7 +528,7 @@ process_module() { echo " Please check the commit history in the announce." fi fi - if [ x"$tag_previous" != x ]; then + if [ -n "$tag_previous" ]; then # The top commit may not have been tagged in dry-run mode. Use commit. tag_range=$tag_previous..$local_top_commit_sha else @@ -606,7 +606,7 @@ MAKE=${MAKE:="make"} check_for_jq # Choose which grep program to use (on Solaris, must be gnu grep) -if [ "x$GREP" = "x" ] ; then +if [ -z "$GREP" ] ; then if [ -x /usr/gnu/bin/grep ] ; then GREP=/usr/gnu/bin/grep else @@ -615,7 +615,7 @@ if [ "x$GREP" = "x" ] ; then fi # Find path for GnuPG v2 -if [ "x$GPG" = "x" ] ; then +if [ -z "$GPG" ] ; then if [ -x /usr/bin/gpg2 ] ; then GPG=/usr/bin/gpg2 else From d55788137c84594754f1d46e4828fa3b8d773368 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 10 Apr 2024 11:46:10 +1000 Subject: [PATCH 34/53] Fix wcmForeachDevice check in wcmMatchDevice wcmForeachDevice returns 0 for no matches, a negative errno or the greater-than-zero number of matches. In wcmMatchDevice we return either 0 or 1 as matchDevice() stops the foreach once the first match is encountered. Fixes: d5ca999f35c7 ("Add a helper function to iterate over local devices to the driver layer") Closes #342 --- src/wcmConfig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wcmConfig.c b/src/wcmConfig.c index 5dab9cd5..36a06d3d 100644 --- a/src/wcmConfig.c +++ b/src/wcmConfig.c @@ -413,7 +413,7 @@ static Bool wcmMatchDevice(WacomDevicePtr priv, WacomCommonPtr *common_return) return 0; /* If a match is found, priv->common has been replaced */ - if (wcmForeachDevice(priv, matchDevice, priv) == 0) + if (wcmForeachDevice(priv, matchDevice, priv) > 0) *common_return = priv->common; return 0; } From 418e38f5b5abd823dcc4d68f1009ea48fb936324 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 15 Apr 2024 14:56:16 +1000 Subject: [PATCH 35/53] xf86-input-wacom 1.2.2 Signed-off-by: Peter Hutterer --- configure.ac | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 35f4b0b2..d833c7e9 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ AC_PREREQ([2.60]) # bump version in meson.build AC_INIT([xf86-input-wacom], - [1.2.1], + [1.2.2], [https://github.com/linuxwacom/xf86-input-wacom/issues/], [xf86-input-wacom]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/meson.build b/meson.build index cd04e053..36f56aac 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('xf86-input-wacom', 'c', - version : '1.2.1', # bump version in configure.ac + version : '1.2.2', # bump version in configure.ac license : 'MIT/Expat', default_options : [ 'c_std=gnu99', 'warning_level=2' ], meson_version : '>= 0.51.0') From bc795e97a7c145704bad7e34cc3948d00dd60574 Mon Sep 17 00:00:00 2001 From: Tatsunosuke Tobita Date: Wed, 12 Jun 2024 12:31:26 +0900 Subject: [PATCH 36/53] man: remove texts related to InputDevice (#345) Since xorg fully started to rely on hotplugging over decade, modern tablet devices can be automatically detected. This commit removes "Section InputDevice" related texts, which is used when hotplugging is disabled. Also, it replaces all "5X' to "5" to describe the proper references while we're here. Signed-off-by: Tatsunosuke Tobita --- man/wacom.man | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/man/wacom.man b/man/wacom.man index 6d17c49c..5be0e2ca 100644 --- a/man/wacom.man +++ b/man/wacom.man @@ -4,10 +4,12 @@ wacom \- Wacom input driver .SH SYNOPSIS .nf -.B "Section \*qInputDevice\*q" +.B "Section \*qInputClass\*q" .BI " Identifier \*q" idevname \*q +.B " MatchIsTablet \*qon\*q" +.BI " MatchDevicePath \*q" devpath \*q .B " Driver \*qwacom\*q" -.BI " Option \*qDevice\*q \*q" devpath \*q +.B " Option \*q...\*q \*q ...\*q" \ \ ... .B EndSection .fi @@ -26,11 +28,9 @@ and requires the wacom kernel driver being loaded before this driver starts. Please check https://github.com/linuxwacom for latest updates of Wacom X and kernel drivers. .SH DRIVER-INTERNAL DEVICE HOTPLUGGING -When input device hotplugging in the X server is enabled and no -.B InputDevice -section exists for a compatible tablet device and an +The .B InputClass -section (see xorg.conf.d(5x)) assigns this driver for the device, the +section (see xorg.conf.d(5)) assigns this driver for the device, the .B wacom driver creates multiple X devices for each a physical device, one X device for each available tool. The list of tools is hardware-dependent. See @@ -59,7 +59,7 @@ possible to use a .B MatchProduct directive to match against this appended type name. .SH CONFIGURATION DETAILS -Please refer to xorg.conf(5x) or xorg.conf.d(5x) for general configuration +Please refer to xorg.conf(5) or xorg.conf.d(5) for general configuration details and for options that can be used with all input drivers. This section only covers configuration details specific to this driver. .PP From f70c7dee7cef4b703801597fc49cd701d82d37ac Mon Sep 17 00:00:00 2001 From: Tatsunosuke Tobita Date: Mon, 24 Jun 2024 14:04:42 +0900 Subject: [PATCH 37/53] man: add the description for ResetArea option (#346) ResetArea is an option already available in xf86-input-wacom. And it is the reciprocal option to Area option. Signed-off-by: Tatsunosuke Tobita --- man/xsetwacom.man | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/man/xsetwacom.man b/man/xsetwacom.man index 968d4797..ad63179a 100644 --- a/man/xsetwacom.man +++ b/man/xsetwacom.man @@ -97,6 +97,11 @@ device's native orientation, regardless of the actual rotation currently applied. Input outside of these coordinates will be clipped to the edges of the area defined. Default: 0 0 x2 y2; with x2 and y2 tablet specific. .TP +\fBResetArea +Set the tablet input area to the default set. +The set is defined device's native orientation, regardless of the actual rotation currently +applied. +.TP \fBButton\fR button-number [mapping] Set a mapping for the specified button-number. Mappings take the form of either a single numeric button or an 'action' to be performed. If no mapping From 4e1d6d61bef5154d66ef0116ef70a817ce21857e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 31 Jul 2024 11:35:29 +1000 Subject: [PATCH 38/53] conf: add huion and xp-pen to our default snippet These tablets are supported provided the right kernel driver is loaded, so let's add them by default instead of requiring every user to write a config snippet . --- conf/70-wacom.conf | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/conf/70-wacom.conf b/conf/70-wacom.conf index 9576587e..b572bcbd 100644 --- a/conf/70-wacom.conf +++ b/conf/70-wacom.conf @@ -93,6 +93,24 @@ Section "InputClass" Driver "wacom" EndSection +# Huion tablets +Section "InputClass" + Identifier "Huion class" + MatchUSBID "256c:*" + MatchIsTablet "on" + MatchDevicePath "/dev/input/event*" + Driver "wacom" +EndSection + +# XP-Pen tablets +Section "InputClass" + Identifier "XP-Pen class" + MatchUSBID "28bd:*" + MatchIsTablet "on" + MatchDevicePath "/dev/input/event*" + Driver "wacom" +EndSection + # N-Trig Duosense Electromagnetic Digitizer Section "InputClass" Identifier "Wacom N-Trig class" From f77696e392e7dff4e5ad6bc989a9fda2fe4fa7db Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 31 Jul 2024 15:36:31 -0700 Subject: [PATCH 39/53] Avoid out-of-bounds array read in usbInitToolType and fix its fallback The usbInitToolType function uses `deriveDeviceTypeFromButtonEvent` as a fallback when it cannot otherwise discover the type of tool being reported in a packet of kernel events. This fallback was intended to be called for each event in the packet by iterating over the `event_ptr` array. The loop is incorrectly implemented, however. Before we get to this point, the value of `event_ptr` would have already been incremented to the end of the list by the deviceTypeFromEvent loop. This means our calls to deriveDeviceTypeFromButtonEvent are accessing data beyond the valid list of events and possibly even beyond the end of the array. To fix this, we can replace the pointer arithmetic in both loops with array index notation instead. Fixes: 3eacea1058ef ("Attempt to derive the tool type from a known button/key event") Signed-off-by: Jason Gerecke --- src/wcmUSB.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wcmUSB.c b/src/wcmUSB.c index 33f8b67a..182b425f 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -1787,9 +1787,9 @@ static int usbInitToolType(WacomDevicePtr priv, int fd, { int i, device_type = 0; - for (i = 0; (i < nevents) && !device_type; ++i, event_ptr++) + for (i = 0; (i < nevents) && !device_type; ++i) { - device_type = deviceTypeFromEvent(priv, event_ptr->type, event_ptr->code, event_ptr->value); + device_type = deviceTypeFromEvent(priv, event_ptr[i].type, event_ptr[i].code, event_ptr[i].value); } if (!device_type) @@ -1799,8 +1799,8 @@ static int usbInitToolType(WacomDevicePtr priv, int fd, device_type = refreshDeviceType(priv, fd); if (!device_type) /* expresskey pressed at startup or missing type */ - for (i = 0; (i < nevents) && !device_type; ++i, event_ptr++) - device_type = deriveDeviceTypeFromButtonEvent(priv, event_ptr); + for (i = 0; (i < nevents) && !device_type; ++i) + device_type = deriveDeviceTypeFromButtonEvent(priv, &event_ptr[i]); return device_type; } From 8be74a345eeaa6440d1f315b6836eda58e495ebb Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Thu, 1 Aug 2024 10:44:42 -0700 Subject: [PATCH 40/53] Do not log errors due to REL_WHEEL_HI_RES events from kernel High-res events are "expected" from the kernel going forward. We may not support doing anything with them, but we also shouldn't clutter the logs with error messages. Signed-off-by: Jason Gerecke --- src/wcmUSB.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/wcmUSB.c b/src/wcmUSB.c index 182b425f..4f40a3db 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -1917,17 +1917,21 @@ static void usbDispatchEvents(WacomDevicePtr priv) } else if (event->type == EV_REL) { - if (event->code == REL_WHEEL) - { + switch (event->code) { + case REL_WHEEL: ds->relwheel = -event->value; ds->time = wcmTimeInMillis(); common->wcmChannel[channel].dirty |= TRUE; - } - else + break; + case REL_WHEEL_HI_RES: + /* unsupported */ + break; + default: wcmLogSafe(priv, W_ERROR, "%s: rel event recv'd (%d)!\n", priv->name, event->code); + } } else if (event->type == EV_KEY) { From 388cbf8263fe50c79d2e7ff0291f21d1b16861e5 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 31 Jul 2024 10:42:46 -0700 Subject: [PATCH 41/53] Fix log output of pointer arbitration Misplaced newline causes logs some logs to get intermingled. Whichever log follows this one becomes part of the same entry. Signed-off-by: Jason Gerecke --- src/wcmCommon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wcmCommon.c b/src/wcmCommon.c index b33446d7..02fcd2a8 100644 --- a/src/wcmCommon.c +++ b/src/wcmCommon.c @@ -1077,7 +1077,7 @@ static Bool check_arbitrated_control(WacomDevicePtr priv, WacomDeviceStatePtr ds if (IsPad(priv)) { /* Pad may never be the "active" pointer controller */ - DBG(6, priv, "Event from pad; not yielding pointer control\n."); + DBG(6, priv, "Event from pad; not yielding pointer control.\n"); return FALSE; } From 77adee9c6ef3f2c6c141d16df099c3c996397f81 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 29 May 2024 13:37:26 -0700 Subject: [PATCH 42/53] Clean up function documentation Remove documentation for parameters that are no longer present. Signed-off-by: Jason Gerecke --- src/wcmCommon.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/wcmCommon.c b/src/wcmCommon.c index 02fcd2a8..14ba53ac 100644 --- a/src/wcmCommon.c +++ b/src/wcmCommon.c @@ -531,9 +531,7 @@ static int getWheelButton(int delta, int action_up, int action_dn) /** * Send button or actions for a scrolling axis. * - * @param button X button number to send if no action is defined * @param action Action to send - * @param nactions Length of action array */ static void sendWheelStripEvent(WacomDevicePtr priv, const WacomAction *action, const WacomDeviceState* ds, const WacomAxisData *axes) From 7722f2ea1d6e50b26ec273becc8ded901f14590f Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 28 May 2024 13:41:34 -0700 Subject: [PATCH 43/53] Update xsetwacom documentation Updates documentation for some of the button-like parameters. The man page for xsetwacom now lists all button-like parameters and the help page now describes the 2nd absolute wheel properly. Signed-off-by: Jason Gerecke --- man/xsetwacom.man | 18 +++++++++++++++--- tools/xsetwacom.c | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/man/xsetwacom.man b/man/xsetwacom.man index ad63179a..46040145 100644 --- a/man/xsetwacom.man +++ b/man/xsetwacom.man @@ -103,10 +103,22 @@ The set is defined device's native orientation, regardless of the actual rotatio applied. .TP \fBButton\fR button-number [mapping] -Set a mapping for the specified button-number. Mappings take the form of +.TQ +\fBAbsWheelUp\fR [mapping] +.TQ +\fBAbsWheelDown\fR [mapping] +.TQ +\fBAbsWheel2Up\fR [mapping] +.TQ +\fBAbsWheel2Down\fR [mapping] +.TQ +\fBRelWheelUp\fR [mapping] +.TQ +\fBRelWheelDown\fR [mapping] +Set a mapping for the specified control. Mappings take the form of either a single numeric button or an 'action' to be performed. If no mapping -is provided, the default mapping is restored. If button-number is mapped -to 0, the Button event is ignored. +is provided, the default mapping is restored. If a control is mapped +to 0, the event is ignored. Numeric button mappings indicate what X11 button number the given button-number should correspond to. For example, a mapping of "3" means a press of the given diff --git a/tools/xsetwacom.c b/tools/xsetwacom.c index 9394b960..a4a6d3a0 100644 --- a/tools/xsetwacom.c +++ b/tools/xsetwacom.c @@ -332,7 +332,7 @@ static param_t parameters[] = }, { .name = "AbsWheel2Up", - .desc = "X11 event to which absolute wheel up should be mapped. ", + .desc = "X11 event to which 2nd absolute wheel up should be mapped. ", .prop_name = WACOM_PROP_WHEELBUTTONS, .prop_format = 8, .prop_offset = 4, @@ -342,7 +342,7 @@ static param_t parameters[] = }, { .name = "AbsWheel2Down", - .desc = "X11 event to which absolute wheel down should be mapped. ", + .desc = "X11 event to which 2nd absolute wheel down should be mapped. ", .prop_name = WACOM_PROP_WHEELBUTTONS, .prop_format = 8, .prop_offset = 5, From a91168c7c257e7727e9c70cef48d6d6d3d1d926f Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 31 Jul 2024 15:37:19 -0700 Subject: [PATCH 44/53] Recognize the pad in more situations Allow dial and ring events to be recognized as coming from the pad when there are no other better sources of information (for example, BTN_TOOL_* events earlier in the event packet, an ABS_MISC with the information, or a previously-known tool type). This fixes an issue where the pad is not recognized (and events are not generated) if your first interaction is with a relative wheel rather than a button or touchring. The events types matched by this function have an ambiguous source on their own, but other earlier tests would be able to determine the type from other context. If all other context-sensitive tests fail to find a tool type, it is reasonably safe to assume we're looking at a pad. Signed-off-by: Jason Gerecke --- src/wcmUSB.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/wcmUSB.c b/src/wcmUSB.c index 4f40a3db..913e5923 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -1735,8 +1735,8 @@ static int refreshDeviceType(WacomDevicePtr priv, int fd) return 0; } -static int deriveDeviceTypeFromButtonEvent(WacomDevicePtr priv, - const struct input_event *event_ptr) +static Bool eventCouldBeFromPad(WacomDevicePtr priv, + const struct input_event *event_ptr) { WacomCommonPtr common = priv->common; wcmUSBData *usbdata = common->private; @@ -1752,18 +1752,33 @@ static int deriveDeviceTypeFromButtonEvent(WacomDevicePtr priv, case BTN_BACK: case BTN_EXTRA: case BTN_FORWARD: - return PAD_ID; + return TRUE; default: for (nkeys = 0; nkeys < usbdata->npadkeys; nkeys++) { if (event_ptr->code == usbdata->padkey_code[nkeys]) { - return PAD_ID; + return TRUE; } } break; } } - return 0; + if (event_ptr->type == EV_REL) { + switch (event_ptr->code) { + case REL_WHEEL: + case REL_WHEEL_HI_RES: + return TRUE; + } + } + if (event_ptr->type == EV_ABS) { + switch (event_ptr->code) { + case ABS_WHEEL: + case ABS_THROTTLE: + return TRUE; + } + } + + return FALSE; } /*** @@ -1800,7 +1815,8 @@ static int usbInitToolType(WacomDevicePtr priv, int fd, if (!device_type) /* expresskey pressed at startup or missing type */ for (i = 0; (i < nevents) && !device_type; ++i) - device_type = deriveDeviceTypeFromButtonEvent(priv, &event_ptr[i]); + if (eventCouldBeFromPad(priv, &event_ptr[i])) + device_type = PAD_ID; return device_type; } From a418ede89488ecbd2785860ff7ac112e37c6857b Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 30 Jul 2024 14:43:09 -0700 Subject: [PATCH 45/53] Swap the relwheel actions triggered and defaults for vertical scrolling Relative wheel actions are backwards from how the user thinks about them. If you want to get/set the action that occurs when scrolling up, you currently need to work with the REL_WHEEL_DOWN action. This is difficult to explain to users and is also makes the code more difficult to follow. This commit changes the behavior so that programming the REL_WHEEL_UP action actually affects what happens when you physically scroll the wheel up. The behavior is now: physical scroll wheel up -> positive delta from kernel -> REL_WHEEL_UP action -> X11 mouse button 4 -> window scrolls up. Note that this commit will break any xsetwacom scripts that users may have which change the relative wheel actions from their defaults. It would also affect control panels that rely on xsetwacom or configuring the driver directly. We don't expect this to cause significant problems in reality since Wacom has not produced tools with relative wheels in many years and so there are few scripts/control panels to break. Signed-off-by: Jason Gerecke --- src/wcmCommon.c | 17 +++++++++-------- src/wcmConfig.c | 4 ++-- src/wcmUSB.c | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/wcmCommon.c b/src/wcmCommon.c index 14ba53ac..7bd74853 100644 --- a/src/wcmCommon.c +++ b/src/wcmCommon.c @@ -513,17 +513,17 @@ static int getScrollDelta(int current, int old, int wrap, int flags) * the scrolling axis and the possible events that can be * sent. * - * @param delta Amount of change in the scrolling axis - * @param action_up Array index of action to send on scroll up - * @param action_dn Array index of action to send on scroll down - * @return Array index of action that should be performed, or -1 if none. + * @param delta Amount of change in the scrolling axis + * @param action_positive Array index of action to send on a positive delta + * @param action_negative Array index of action to send on negative delta + * @return Array index of action that should be performed, or -1 if none. */ -static int getWheelButton(int delta, int action_up, int action_dn) +static int getWheelButton(int delta, int action_positive, int action_negative) { if (delta > 0) - return action_up; + return action_positive; else if (delta < 0) - return action_dn; + return action_negative; else return -1; } @@ -571,7 +571,8 @@ static void sendWheelStripEvents(WacomDevicePtr priv, const WacomDeviceState* ds sendWheelStripEvent(priv, &priv->strip_actions[idx], ds, axes); } - /* emulate events for relative wheel */ + /* emulate events for relative wheel: + * positive delta = scroll up */ delta = getScrollDelta(ds->relwheel, 0, 0, 0); idx = getWheelButton(delta, WHEEL_REL_UP, WHEEL_REL_DN); if (idx >= 0 && (IsCursor(priv) || IsPad(priv)) && priv->oldState.proximity == ds->proximity) diff --git a/src/wcmConfig.c b/src/wcmConfig.c index 36a06d3d..5b6e84e2 100644 --- a/src/wcmConfig.c +++ b/src/wcmConfig.c @@ -70,8 +70,8 @@ WacomDevicePtr wcmAllocate(void *frontend, const char *name) priv->button_default[i] = (i < 3) ? i + 1 : i + 5; priv->nbuttons = WCM_MAX_BUTTONS; /* Default number of buttons */ - priv->wheel_default[WHEEL_REL_UP] = 5; - priv->wheel_default[WHEEL_REL_DN] = 4; + priv->wheel_default[WHEEL_REL_UP] = 4; /* scroll up */ + priv->wheel_default[WHEEL_REL_DN] = 5; /* scroll down */ /* wheel events are set to 0, but the pad overwrites this default * later in wcmParseOptions, when we have IsPad() available */ priv->wheel_default[WHEEL_ABS_UP] = 0; diff --git a/src/wcmUSB.c b/src/wcmUSB.c index 913e5923..2240a4a0 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -1935,7 +1935,7 @@ static void usbDispatchEvents(WacomDevicePtr priv) { switch (event->code) { case REL_WHEEL: - ds->relwheel = -event->value; + ds->relwheel = event->value; ds->time = wcmTimeInMillis(); common->wcmChannel[channel].dirty |= TRUE; break; From b43c2597e0604980ba66dda46270be40d3da2086 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 28 May 2024 13:49:36 -0700 Subject: [PATCH 46/53] Implement support for devices with two relative wheels / dials Just like how tablets may have two absolute wheels, it also is possible for them to have two relative wheels. This commit extends the WACOM_PROP_WHEELBUTTONS property to reference two new actions: RelWheel2Up and RelWheel2Down. These actions will be triggered in response to horizontal scrolling events from the kernel (positive and negative REL_HWHEEL events, respecitively). The default action for these wheels is sending horizontal mouse scroll events (X11 mouse buttons 7 and 6, respectively). Signed-off-by: Jason Gerecke --- include/wacom-properties.h | 10 +++--- man/xsetwacom.man | 12 +++++++ src/wcmCommon.c | 24 +++++++++++--- src/wcmConfig.c | 4 ++- src/wcmUSB.c | 12 +++++++ src/x11/xf86WacomProperties.c | 4 +-- src/xf86WacomDefs.h | 9 +++-- tools/xsetwacom.c | 62 ++++++++++++++++++++++++++++++++++- 8 files changed, 120 insertions(+), 17 deletions(-) diff --git a/include/wacom-properties.h b/include/wacom-properties.h index 0796ab03..9cec2114 100644 --- a/include/wacom-properties.h +++ b/include/wacom-properties.h @@ -42,15 +42,13 @@ /* CARD32, 1 value */ #define WACOM_PROP_SERIAL_BIND "Wacom Serial ID binding" -/* 8 bit, 4 values, left up, left down, right up, right down - OR - Atom, 4 values , left up, left down, right up, right down +/* 8 bit OR Atom, 4 values: + left up, left down, right up, right down */ #define WACOM_PROP_STRIPBUTTONS "Wacom Strip Buttons" -/* 8 bit, 6 values, rel wheel up, rel wheel down, abs wheel up, abs wheel down, abs wheel 2 up, abs wheel 2 down - OR - Atom, 6 values , rel wheel up, rel wheel down, abs wheel up, abs wheel down, abs wheel 2 up, abs wheel 2 down +/* 8 bit OR Atom, 8 values: + rel wheel up, rel wheel down, abs wheel up, abs wheel down, abs wheel 2 up, abs wheel 2 down, rel wheel 2 up, rel wheel 2 down */ #define WACOM_PROP_WHEELBUTTONS "Wacom Wheel Buttons" diff --git a/man/xsetwacom.man b/man/xsetwacom.man index 46040145..fe6807b3 100644 --- a/man/xsetwacom.man +++ b/man/xsetwacom.man @@ -112,9 +112,21 @@ applied. .TQ \fBAbsWheel2Down\fR [mapping] .TQ +\fBDialCW\fR [mapping] +.TQ +\fBDialCCW\fR [mapping] +.TQ +\fBDial2CW\fR [mapping] +.TQ +\fBDial2CCW\fR [mapping] +.TQ \fBRelWheelUp\fR [mapping] .TQ \fBRelWheelDown\fR [mapping] +.TQ +\fBRelWheel2Up\fR [mapping] +.TQ +\fBRelWheel2Down\fR [mapping] Set a mapping for the specified control. Mappings take the form of either a single numeric button or an 'action' to be performed. If no mapping is provided, the default mapping is restored. If a control is mapped diff --git a/src/wcmCommon.c b/src/wcmCommon.c index 7bd74853..06669e8a 100644 --- a/src/wcmCommon.c +++ b/src/wcmCommon.c @@ -581,6 +581,15 @@ static void sendWheelStripEvents(WacomDevicePtr priv, const WacomDeviceState* ds sendWheelStripEvent(priv, &priv->wheel_actions[idx], ds, axes); } + /* emulate events for 2nd relative wheel */ + delta = getScrollDelta(ds->relwheel2, 0, 0, 0); + idx = getWheelButton(delta, WHEEL2_REL_UP, WHEEL2_REL_DN); + if (idx >= 0 && (IsCursor(priv) || IsPad(priv)) && priv->oldState.proximity == ds->proximity) + { + DBG(10, priv, "Relative wheel 2 scroll delta = %d\n", delta); + sendWheelStripEvent(priv, &priv->wheel_actions[idx], ds, axes); + } + /* emulate events for left touch ring */ delta = getScrollDelta(ds->abswheel, priv->oldState.abswheel, common->wcmMaxRing, AXIS_INVERT); idx = getWheelButton(delta, WHEEL_ABS_UP, WHEEL_ABS_DN); @@ -622,7 +631,7 @@ static void sendCommonEvents(WacomDevicePtr priv, const WacomDeviceState* ds, wcmSendButtons(priv, ds, buttons, axes); /* emulate wheel/strip events when defined */ - if ( ds->relwheel || (ds->abswheel != priv->oldState.abswheel) || (ds->abswheel2 != priv->oldState.abswheel2) || + if ( ds->relwheel || ds->relwheel2 || (ds->abswheel != priv->oldState.abswheel) || (ds->abswheel2 != priv->oldState.abswheel2) || ( (ds->stripx - priv->oldState.stripx) && ds->stripx && priv->oldState.stripx) || ((ds->stripy - priv->oldState.stripy) && ds->stripy && priv->oldState.stripy) ) sendWheelStripEvents(priv, ds, axes); @@ -711,7 +720,7 @@ wcmSendPadEvents(WacomDevicePtr priv, const WacomDeviceState* ds, const WacomAxi if (!priv->oldState.proximity && ds->proximity) wcmEmitProximity(priv, TRUE, axes); - if (axes->mask || ds->buttons || ds->relwheel || + if (axes->mask || ds->buttons || ds->relwheel || ds->relwheel2 || (ds->abswheel != priv->oldState.abswheel) || (ds->abswheel2 != priv->oldState.abswheel2)) { sendCommonEvents(priv, ds, axes); @@ -1001,6 +1010,7 @@ wcmCheckSuppress(WacomCommonPtr common, if (abs(dsOrig->abswheel - dsNew->abswheel) > suppress) goto out; if (abs(dsOrig->abswheel2 - dsNew->abswheel2) > suppress) goto out; if (dsNew->relwheel != 0) goto out; + if (dsNew->relwheel2 != 0) goto out; returnV = SUPPRESS_ALL; @@ -1137,7 +1147,7 @@ void wcmEvent(WacomCommonPtr common, unsigned int channel, DBG(10, common, "c=%u i=%d t=%d s=0x%x x=%d y=%d b=%u " - "p=%d rz=%d tx=%d ty=%d aw=%d aw2=%d rw=%d " + "p=%d rz=%d tx=%d ty=%d aw=%d aw2=%d rw=%d rw2=%d " "t=%d px=%d st=%u cs=%d \n", channel, ds.device_id, @@ -1145,7 +1155,7 @@ void wcmEvent(WacomCommonPtr common, unsigned int channel, ds.serial_num, ds.x, ds.y, ds.buttons, ds.pressure, ds.rotation, ds.tiltx, - ds.tilty, ds.abswheel, ds.abswheel2, ds.relwheel, ds.throttle, + ds.tilty, ds.abswheel, ds.abswheel2, ds.relwheel, ds.relwheel2, ds.throttle, ds.proximity, ds.sample, pChannel->nSamples); @@ -1995,6 +2005,12 @@ TEST_CASE(test_suppress) assert(rc == SUPPRESS_NONE); new.relwheel = 0; + /* any movement on relwheel2 counts */ + new.relwheel2 = 1; + rc = wcmCheckSuppress(&common, &old, &new); + assert(rc == SUPPRESS_NONE); + new.relwheel2 = 0; + /* x axis movement */ /* not enough movement */ diff --git a/src/wcmConfig.c b/src/wcmConfig.c index 5b6e84e2..c5492831 100644 --- a/src/wcmConfig.c +++ b/src/wcmConfig.c @@ -72,6 +72,8 @@ WacomDevicePtr wcmAllocate(void *frontend, const char *name) priv->nbuttons = WCM_MAX_BUTTONS; /* Default number of buttons */ priv->wheel_default[WHEEL_REL_UP] = 4; /* scroll up */ priv->wheel_default[WHEEL_REL_DN] = 5; /* scroll down */ + priv->wheel_default[WHEEL2_REL_UP] = 7; /* scroll right */ + priv->wheel_default[WHEEL2_REL_DN] = 6; /* scroll left */ /* wheel events are set to 0, but the pad overwrites this default * later in wcmParseOptions, when we have IsPad() available */ priv->wheel_default[WHEEL_ABS_UP] = 0; @@ -674,7 +676,7 @@ static void wcmInitActions(WacomDevicePtr priv) if (IsPad(priv) || IsCursor(priv)) { - for (i = 0; i < 6; i++) + for (i = 0; i < 8; i++) wcmResetWheelAction(priv, i); } } diff --git a/src/wcmUSB.c b/src/wcmUSB.c index 2240a4a0..a7949292 100644 --- a/src/wcmUSB.c +++ b/src/wcmUSB.c @@ -1766,7 +1766,9 @@ static Bool eventCouldBeFromPad(WacomDevicePtr priv, if (event_ptr->type == EV_REL) { switch (event_ptr->code) { case REL_WHEEL: + case REL_HWHEEL: case REL_WHEEL_HI_RES: + case REL_HWHEEL_HI_RES: return TRUE; } } @@ -1895,6 +1897,7 @@ static void usbDispatchEvents(WacomDevicePtr priv) /* all USB data operates from previous context except relative values*/ ds->relwheel = 0; + ds->relwheel2 = 0; ds->serial_num = private->wcmLastToolSerial; /* loop through all events in group */ @@ -1942,11 +1945,20 @@ static void usbDispatchEvents(WacomDevicePtr priv) case REL_WHEEL_HI_RES: /* unsupported */ break; + case REL_HWHEEL: + ds->relwheel2 = event->value; + ds->time = wcmTimeInMillis(); + common->wcmChannel[channel].dirty |= TRUE; + break; + case REL_HWHEEL_HI_RES: + /* unsupported */ + break; default: wcmLogSafe(priv, W_ERROR, "%s: rel event recv'd (%d)!\n", priv->name, event->code); + break; } } else if (event->type == EV_KEY) diff --git a/src/x11/xf86WacomProperties.c b/src/x11/xf86WacomProperties.c index 6401a3b5..66802b55 100644 --- a/src/x11/xf86WacomProperties.c +++ b/src/x11/xf86WacomProperties.c @@ -269,10 +269,10 @@ void InitWcmDeviceProperties(WacomDevicePtr priv) if (IsPad(priv) || IsCursor(priv)) { - for (i = 0; i < 6; i++) + for (i = 0; i < 8; i++) wcmInitWheelActionProp(priv, i); prop_wheel_buttons = InitWcmAtom(pInfo->dev, WACOM_PROP_WHEELBUTTONS, XA_ATOM, 32, - 6, (int*)priv->wheel_action_props); + 8, (int*)priv->wheel_action_props); } if (IsStylus(priv) || IsEraser(priv)) { diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h index 1ee84abf..370ea81f 100644 --- a/src/xf86WacomDefs.h +++ b/src/xf86WacomDefs.h @@ -177,6 +177,8 @@ struct _WacomModel #define WHEEL_ABS_DN 3 #define WHEEL2_ABS_UP 4 #define WHEEL2_ABS_DN 5 +#define WHEEL2_REL_UP 6 +#define WHEEL2_REL_DN 7 #define STRIP_LEFT_UP 0 #define STRIP_LEFT_DN 1 #define STRIP_RIGHT_UP 2 @@ -207,6 +209,7 @@ struct _WacomDeviceState int abswheel; int abswheel2; int relwheel; + int relwheel2; int distance; int throttle; int proximity; @@ -272,13 +275,13 @@ struct _WacomDeviceRec */ int button_default[WCM_MAX_BUTTONS]; /* Default mappings set by ourselves (possibly overridden by xorg.conf) */ int strip_default[4]; - int wheel_default[6]; + int wheel_default[8]; WacomAction key_actions[WCM_MAX_BUTTONS]; /* Action codes to perform when the associated event occurs */ WacomAction strip_actions[4]; - WacomAction wheel_actions[6]; + WacomAction wheel_actions[8]; Atom btn_action_props[WCM_MAX_BUTTONS]; /* Action references so we can update the action codes when a client makes a change */ Atom strip_action_props[4]; - Atom wheel_action_props[6]; + Atom wheel_action_props[8]; int nbuttons; /* number of buttons for this subdevice */ int naxes; /* number of axes */ diff --git a/tools/xsetwacom.c b/tools/xsetwacom.c index a4a6d3a0..c8f7a21b 100644 --- a/tools/xsetwacom.c +++ b/tools/xsetwacom.c @@ -300,6 +300,16 @@ static param_t parameters[] = .set_func = map_actions, .get_func = get_map, }, + { + .name = "DialCCW", + .desc = "X11 event to which counter-clockwise motion of the dial should be mapped." , + .prop_name = WACOM_PROP_WHEELBUTTONS, + .prop_format = 8, + .prop_offset = 0, + .arg_count = 0, + .set_func = map_actions, + .get_func = get_map, + }, { .name = "RelWheelDown", .desc = "X11 event to which relative wheel down should be mapped. ", @@ -310,6 +320,16 @@ static param_t parameters[] = .set_func = map_actions, .get_func = get_map, }, + { + .name = "DialCW", + .desc = "X11 event to which clockwise motion of the dial should be mapped." , + .prop_name = WACOM_PROP_WHEELBUTTONS, + .prop_format = 8, + .prop_offset = 1, + .arg_count = 0, + .set_func = map_actions, + .get_func = get_map, + }, { .name = "AbsWheelUp", .desc = "X11 event to which absolute wheel up should be mapped. ", @@ -350,6 +370,46 @@ static param_t parameters[] = .set_func = map_actions, .get_func = get_map, }, + { + .name = "RelWheel2Up", + .desc = "X11 event to which 2nd relative wheel up should be mapped. ", + .prop_name = WACOM_PROP_WHEELBUTTONS, + .prop_format = 8, + .prop_offset = 6, + .arg_count = 0, + .set_func = map_actions, + .get_func = get_map, + }, + { + .name = "Dial2CW", + .desc = "X11 event to which clockwise motion of the 2nd dial should be mapped. ", + .prop_name = WACOM_PROP_WHEELBUTTONS, + .prop_format = 8, + .prop_offset = 6, + .arg_count = 0, + .set_func = map_actions, + .get_func = get_map, + }, + { + .name = "RelWheel2Down", + .desc = "X11 event to which 2nd relative wheel down should be mapped. ", + .prop_name = WACOM_PROP_WHEELBUTTONS, + .prop_format = 8, + .prop_offset = 7, + .arg_count = 0, + .set_func = map_actions, + .get_func = get_map, + }, + { + .name = "Dial2CCW", + .desc = "X11 event to which counter-clockwise motion of the 2nd dial should be mapped. ", + .prop_name = WACOM_PROP_WHEELBUTTONS, + .prop_format = 8, + .prop_offset = 7, + .arg_count = 0, + .set_func = map_actions, + .get_func = get_map, + }, { .name = "StripLeftUp", .desc = "X11 event to which left strip up should be mapped. ", @@ -3079,7 +3139,7 @@ TEST_CASE(test_parameter_number) * deprecated them. * Numbers include trailing NULL entry. */ - assert(ARRAY_SIZE(parameters) == 40); + assert(ARRAY_SIZE(parameters) == 46); assert(ARRAY_SIZE(deprecated_parameters) == 17); } From 94c2d331d3cc57d21b61f38985843403e91191a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 22:42:05 +0000 Subject: [PATCH 47/53] CI: bump actions/download-artifact to v4 Originally suggested by github's dependabot this bumps to download-artifact@v4 for a security issue. That requires bumping to upload-artifact@v4 too. And that in turn requires that we only have one tarball with any given name so we no only generate the tarball from the gcc job. --- .github/workflows/build.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 18eb56dd..bf2ee199 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,7 +53,8 @@ jobs: - name: move tarball to top level run: | mv _build/xf86-input-wacom-*tar.bz2 . - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 + if: ${{ matrix.compiler == 'gcc' }} with: name: tarball path: xf86-input-wacom-*tar.bz2 @@ -84,7 +85,7 @@ jobs: env: CC: ${{matrix.compiler}} # Capture all the meson logs, even if we failed - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: ${{ always() }} # even if we fail with: name: meson-test-logs-${{github.job}}-${{matrix.compiler}}-${{matrix.meson_options}} @@ -107,7 +108,7 @@ jobs: with: meson_args: -Dauto_features=enabled # Capture all the meson logs, even if we failed - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: ${{ always() }} # even if we fail with: name: meson-test-logs-${{github.job}} @@ -130,7 +131,7 @@ jobs: with: apt: $UBUNTU_PACKAGES - name: fetch tarball from previous job(s) - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: tarball - name: extract tarball @@ -160,7 +161,7 @@ jobs: apt: $UBUNTU_PACKAGES pip: $PIP_PACKAGES - name: fetch tarball from previous job(s) - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: tarball - name: extract tarball @@ -175,7 +176,7 @@ jobs: meson_args: -Dauto_features=enabled --prefix="$INSTALLDIR" ninja_args: test # Capture all the meson logs, even if we failed - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: ${{ always() }} # even if we fail with: name: tarball-build-meson-test-logs @@ -192,7 +193,7 @@ jobs: - name: Checkout the repo uses: actions/checkout@v3 - name: fetch tarball from previous job(s) - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: tarball - name: list git files From fdf6d5a73597bb6962ca7dc89aae6aed5eaf505e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 4 Sep 2024 09:14:57 +1000 Subject: [PATCH 48/53] CI: bump to actions/checkout@v4 and actions/setup-python@v5 --- .github/workflows/black.yml | 4 ++-- .github/workflows/build.yml | 8 ++++---- .github/workflows/coverity.yml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index a1d43144..62258a07 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -8,8 +8,8 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout the repo - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: '3.x' - run: pip install black diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bf2ee199..7054664d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: compiler: [ gcc, clang ] steps: - name: Checkout the repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: linuxwacom/libwacom/.github/actions/pkginstall@master with: apt: $UBUNTU_PACKAGES @@ -73,7 +73,7 @@ jobs: # https://github.com/mesonbuild/meson/issues/764 - '-Db_sanitize=address,undefined -Db_lundef=false' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: linuxwacom/libwacom/.github/actions/pkginstall@master with: apt: $UBUNTU_PACKAGES @@ -96,7 +96,7 @@ jobs: compile-with-meson-exact-version: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: linuxwacom/libwacom/.github/actions/pkginstall@master with: apt: $UBUNTU_PACKAGES @@ -191,7 +191,7 @@ jobs: TARBALLDIR: '_tarball_dir' steps: - name: Checkout the repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: fetch tarball from previous job(s) uses: actions/download-artifact@v4 with: diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index fcd08611..74b1c772 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -22,7 +22,7 @@ jobs: if: ${{ github.repository == '$COVERITY_SCAN_PROJECT_NAME' }} steps: - name: Checkout the repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up build environment / dependencies run: | From 659fee33a1e3600e86a959e60d969754fa1370b9 Mon Sep 17 00:00:00 2001 From: TheSnowfield <17957399+TheSnowfield@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:52:57 +0900 Subject: [PATCH 49/53] conf: add support for Surface IPTS device --- conf/70-wacom.conf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/conf/70-wacom.conf b/conf/70-wacom.conf index b572bcbd..91e55d01 100644 --- a/conf/70-wacom.conf +++ b/conf/70-wacom.conf @@ -145,4 +145,11 @@ Section "InputClass" Driver "wacom" EndSection +# Surface IPTS (Intel Precise Touch and Stylus) +Section "InputClass" + Identifier "Surface IPTS Device" + MatchProduct "IPTS" + MatchDevicePath "/dev/input/event*" + Driver "wacom" +EndSection From 47552e13e714ab6b8c2dcbce0d7e0bca6d8a8bf0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 12 Sep 2024 10:56:59 +1000 Subject: [PATCH 50/53] conf: bind this driver to all tablets by default Historically we've only bound to Wacom devices and a select few other tablets that were handled by this driver. This required adding those tablets which we forgot for years for e.g. Huion/XP-Pen devices (see commit 4e1d6d61). At this point we should support pretty much anything that is a tablet so let's bind to those by default. Exceptions for Wacom touchpad/touchscreens stay in the file and so do some other ones that are too hard to test whether they're handled by them generic MatchIsTablet condition. Closes #353 --- conf/70-wacom.conf | 69 ---------------------------------------------- 1 file changed, 69 deletions(-) diff --git a/conf/70-wacom.conf b/conf/70-wacom.conf index 91e55d01..9c96a707 100644 --- a/conf/70-wacom.conf +++ b/conf/70-wacom.conf @@ -8,7 +8,6 @@ Section "InputClass" Identifier "Wacom USB tablet class" - MatchUSBID "056a:*" MatchDevicePath "/dev/input/event*" MatchIsTablet "true" Driver "wacom" @@ -30,14 +29,6 @@ Section "InputClass" Driver "wacom" EndSection -Section "InputClass" - Identifier "Wacom tablet class" - MatchProduct "Wacom|WACOM|PTK-540WL|ISD-V4" - MatchDevicePath "/dev/input/event*" - MatchIsTablet "true" - Driver "wacom" -EndSection - Section "InputClass" Identifier "Wacom touchscreen class" MatchProduct "Wacom|WACOM|PTK-540WL|ISD-V4" @@ -76,41 +67,6 @@ Section "InputClass" Driver "wacom" EndSection -# Hanwang tablets -Section "InputClass" - Identifier "Hanwang class" - MatchProduct "Hanwang" - MatchDevicePath "/dev/input/event*" - Driver "wacom" -EndSection - -# Waltop tablets -Section "InputClass" - Identifier "Waltop class" - MatchProduct "WALTOP" - MatchIsTablet "on" - MatchDevicePath "/dev/input/event*" - Driver "wacom" -EndSection - -# Huion tablets -Section "InputClass" - Identifier "Huion class" - MatchUSBID "256c:*" - MatchIsTablet "on" - MatchDevicePath "/dev/input/event*" - Driver "wacom" -EndSection - -# XP-Pen tablets -Section "InputClass" - Identifier "XP-Pen class" - MatchUSBID "28bd:*" - MatchIsTablet "on" - MatchDevicePath "/dev/input/event*" - Driver "wacom" -EndSection - # N-Trig Duosense Electromagnetic Digitizer Section "InputClass" Identifier "Wacom N-Trig class" @@ -128,28 +84,3 @@ Section "InputClass" MatchIsTouchscreen "true" Driver "wacom" EndSection - -# Surface Go -Section "InputClass" - Identifier "SurfaceGo Touch" - MatchProduct "ELAN9038:00 04F3:261A" - MatchDevicePath "/dev/input/event*" - Driver "wacom" -EndSection - -# Nuvision Solo 10 Draw (Supports Surface Pens) -Section "InputClass" - Identifier "Nuvision Solo 10 Draw" - MatchProduct "04F3200A:00 04F3:22F7" - MatchDevicePath "/dev/input/event*" - Driver "wacom" -EndSection - -# Surface IPTS (Intel Precise Touch and Stylus) -Section "InputClass" - Identifier "Surface IPTS Device" - MatchProduct "IPTS" - MatchDevicePath "/dev/input/event*" - Driver "wacom" -EndSection - From 948d0ba8a918646154d3bd73c7483639d4a79d55 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 21 Oct 2024 19:12:14 +1000 Subject: [PATCH 51/53] man: discourage use of Section InputDevice Closes #339 --- man/wacom.man | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/man/wacom.man b/man/wacom.man index 5be0e2ca..1ed65629 100644 --- a/man/wacom.man +++ b/man/wacom.man @@ -21,18 +21,22 @@ The .B wacom driver functions as a pointer input device. .SH SUPPORTED HARDWARE -This driver supports the Wacom IV and Wacom V protocols. Serial tablets only -need this driver. USB tablet support is available on some Linux platforms -and requires the wacom kernel driver being loaded before this driver starts. +This driver supports virtually all tablet devices that are supported +by the Linux kernel. .PP Please check https://github.com/linuxwacom for latest updates of Wacom X and kernel drivers. .SH DRIVER-INTERNAL DEVICE HOTPLUGGING -The +Configuration via +.B "Section \*qInputDevice\*q" +is discouraged as such devices cannot be hotplugged at runtime. Instead +users should use +.B "Section \*qInputClass\*q" +as in the example above. The .B InputClass section (see xorg.conf.d(5)) assigns this driver for the device, the .B wacom -driver creates multiple X devices for each a physical device, one X device +driver creates multiple X devices for each physical device, one X device for each available tool. The list of tools is hardware-dependent. See .B Option "Type" as outlined in the @@ -81,7 +85,8 @@ Right now only a few Tablet PCs have this feature. sets the path to the special file which represents serial line where the tablet is plugged. You have to specify it for each subsection with the same value if you want to have multiple devices with the same tablet. -This option is mandatory. +This option is mandatory only if using +.B "Section \*qInputDevice\*q" for static configuration. .TP 4 .B Option \fI"Suppress"\fP \fI"number"\fP sets the position increment under which not to transmit coordinates. From 4aab05f10e44b2c990f603b5ecbaff49c65871e8 Mon Sep 17 00:00:00 2001 From: Joshua Dickens Date: Tue, 29 Oct 2024 14:55:35 -0700 Subject: [PATCH 52/53] wacom 1.2.3 Signed-off-by: Joshua Dickens --- configure.ac | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index d833c7e9..f54d2c8d 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ AC_PREREQ([2.60]) # bump version in meson.build AC_INIT([xf86-input-wacom], - [1.2.2], + [1.2.3], [https://github.com/linuxwacom/xf86-input-wacom/issues/], [xf86-input-wacom]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/meson.build b/meson.build index 36f56aac..139dc3f4 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('xf86-input-wacom', 'c', - version : '1.2.2', # bump version in configure.ac + version : '1.2.3', # bump version in configure.ac license : 'MIT/Expat', default_options : [ 'c_std=gnu99', 'warning_level=2' ], meson_version : '>= 0.51.0') From 31d3b745d630ed87ed25d1f44a6596c9968ffc0c Mon Sep 17 00:00:00 2001 From: Funda Wang Date: Sun, 17 Nov 2024 19:04:07 +0800 Subject: [PATCH 53/53] meson.build: fix variable name when dealing with systemd-unit-dir --- meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 139dc3f4..d2efe084 100644 --- a/meson.build +++ b/meson.build @@ -89,8 +89,8 @@ if dir_udev_rules == '' endif dir_systemd_unit = get_option('systemd-unit-dir') -if dir_udev_rules == '' - dir_systemd_unit = dir_systemd / 'systemd' +if dir_systemd_unit == '' + dir_systemd_unit = dir_systemd / 'system' endif