From b43c2597e0604980ba66dda46270be40d3da2086 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 28 May 2024 13:49:36 -0700 Subject: [PATCH] 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); }