Skip to content

Commit

Permalink
Implement support for devices with two relative wheels / dials
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
jigpu authored and Pinglinux committed Aug 8, 2024
1 parent a418ede commit b43c259
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 17 deletions.
10 changes: 4 additions & 6 deletions include/wacom-properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
12 changes: 12 additions & 0 deletions man/xsetwacom.man
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 20 additions & 4 deletions src/wcmCommon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -1137,15 +1147,15 @@ 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,
ds.device_type,
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);

Expand Down Expand Up @@ -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 */
Expand Down
4 changes: 3 additions & 1 deletion src/wcmConfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/wcmUSB.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/x11/xf86WacomProperties.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
9 changes: 6 additions & 3 deletions src/xf86WacomDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -207,6 +209,7 @@ struct _WacomDeviceState
int abswheel;
int abswheel2;
int relwheel;
int relwheel2;
int distance;
int throttle;
int proximity;
Expand Down Expand Up @@ -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 */
Expand Down
62 changes: 61 additions & 1 deletion tools/xsetwacom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. ",
Expand All @@ -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. ",
Expand Down Expand Up @@ -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. ",
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit b43c259

Please sign in to comment.