Oops, forgot to pass "-2" to git-format-patch. This patch depends on the "Pass current WacomDeviceState through to sendAction" patch which has just been sent separately.
Jason --- Now instead of four in the eights place / you’ve got three, ‘Cause you added one / (That is to say, eight) to the two, / But you can’t take seven from three, / So you look at the sixty-fours.... On Mon, Dec 18, 2017 at 11:46 AM, Jason Gerecke <killert...@gmail.com> wrote: > When enabled through `xsetwacom set <id> button <n> pan`, this causes the > driver > to appear to "drag" scrollable window contents by emitting appropriate scroll > events as the pen is dragged around. > > Signed-off-by: Jason Gerecke <jason.gere...@wacom.com> > --- > include/Xwacom.h | 1 + > include/wacom-properties.h | 3 ++ > man/wacom.man | 7 ++++ > man/xsetwacom.man | 14 ++++++++ > src/wcmCommon.c | 90 > ++++++++++++++++++++++++++++++++++++++++++---- > src/wcmValidateDevice.c | 3 ++ > src/wcmXCommand.c | 21 +++++++++++ > src/xf86WacomDefs.h | 3 ++ > tools/xsetwacom.c | 24 +++++++++++++ > 9 files changed, 160 insertions(+), 6 deletions(-) > > diff --git a/include/Xwacom.h b/include/Xwacom.h > index 49489ff..c2af381 100644 > --- a/include/Xwacom.h > +++ b/include/Xwacom.h > @@ -60,6 +60,7 @@ > #define AC_MODETOGGLE 0x00020000 /* Toggle absolute/relative mode */ > #define AC_DBLCLICK 0x00030000 /* DEPRECATED: use two button events > instead */ > #define AC_DISPLAYTOGGLE 0x00040000 /* DEPRECATED: has no effect (used > to toggle among screens) */ > +#define AC_PANSCROLL 0x00050000 /* Enter/exit panscroll mode */ > #define AC_BUTTON 0x00080000 /* Emit button events */ > #define AC_TYPE 0x000f0000 /* The mask to isolate event type > bits */ > #define AC_KEYBTNPRESS 0x00100000 /* bit set for key/button presses */ > diff --git a/include/wacom-properties.h b/include/wacom-properties.h > index b845083..0796ab0 100644 > --- a/include/wacom-properties.h > +++ b/include/wacom-properties.h > @@ -111,6 +111,9 @@ > */ > #define WACOM_PROP_PRESSURE_RECAL "Wacom Pressure Recalibration" > > +/* 32 bit, 1 values */ > +#define WACOM_PROP_PANSCROLL_THRESHOLD "Wacom Panscroll Threshold" > + > /* The following are tool types used by the driver in WACOM_PROP_TOOL_TYPE > * or in the 'type' field for XI1 clients. Clients may check for one of > * these types to identify tool types. > diff --git a/man/wacom.man b/man/wacom.man > index 3693c94..3e9c7bd 100644 > --- a/man/wacom.man > +++ b/man/wacom.man > @@ -277,6 +277,13 @@ initial pressure reading may be unequal to zero even for > a perfectly > good pen. If the consecutive pressure readings are not higher than > the initial pressure by a threshold no button event will be generated. > This option allows to disable the recalibration. > +.TP 4 > +.B Option \fI"PanScrollThreshold"\fP \fI"number"\fP > +Specifies the distance the pen must move (in tablet units) before a > +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) > diff --git a/man/xsetwacom.man b/man/xsetwacom.man > index 234e9ba..6e82301 100644 > --- a/man/xsetwacom.man > +++ b/man/xsetwacom.man > @@ -134,6 +134,13 @@ numbers. > The "modetoggle" keyword is also recognized; it takes no arguments, > and toggles the device mode between relative and absolute pointer tracking. > > +The "pan" keyword causes the driver to send scroll events while the pen > +is dragged. This makes it easy to scroll through lists and documents, > +pan around 2D canvases, and zoom in/out of 3D scenes (exact behavior > +depends on application interpretation of scrollwheel events). Dragging > +the pen up/down will send scrollwheel down/up events; dragging it left/right > +will send scrollwheel right/left events. > + > The events in the action mapping are sent when the physical button is > pressed. > If the action mapping leaves any buttons or keys pressed (such as a modifier > key), they will be released when the physical button is released. > @@ -273,6 +280,13 @@ initial pressure reading may be unequal to zero even for > a perfectly > good pen. If the consecutive pressure readings are not higher than > the initial pressure by a threshold no button event will be generated. > This option allows to disable the recalibration. Default: on > +.TP > +\fBPanScrollThreshold\fR distance > +This specifies the distance the pen must move (in tablet units) before > +a 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). > > > .SH "AUTHORS" > diff --git a/src/wcmCommon.c b/src/wcmCommon.c > index b816cdd..f7620af 100644 > --- a/src/wcmCommon.c > +++ b/src/wcmCommon.c > @@ -89,6 +89,50 @@ void set_absolute(InputInfoPtr pInfo, Bool absolute) > priv->flags &= ~ABSOLUTE_FLAG; > } > > +static int wcmButtonPerNotch(WacomDevicePtr priv, int value, int threshold, > int btn_positive, int btn_negative) > +{ > + int mode = is_absolute(priv->pInfo); > + int notches = value / threshold; > + int button = (notches > 0) ? btn_positive : btn_negative; > + int i; > + > + for (i = 0; i < abs(notches); i++) { > + xf86PostButtonEventP(priv->pInfo->dev, mode, button, 1, 0, 0, > 0); > + xf86PostButtonEventP(priv->pInfo->dev, mode, button, 0, 0, 0, > 0); > + } > + > + return value % threshold; > +} > + > +static void wcmPanscroll(WacomDevicePtr priv, const WacomDeviceState *ds) > +{ > + WacomCommonPtr common = priv->common; > + int threshold = common->wcmPanscrollThreshold; > + int *accumulated_x, *accumulated_y; > + > + if (!(priv->flags & SCROLLMODE_FLAG) || !(ds->buttons & 1)) > + return; > + > + /* Tip has gone down down; store state for dragging */ > + if (!(priv->oldState.buttons & 1)) { > + priv->wcmPanscrollState = *ds; > + priv->wcmPanscrollState.x = 0; > + priv->wcmPanscrollState.y = 0; > + return; > + } > + > + accumulated_x = &priv->wcmPanscrollState.x; > + accumulated_y = &priv->wcmPanscrollState.y; > + > + *accumulated_x += (ds->x - priv->oldState.x); > + *accumulated_y += (ds->y - priv->oldState.y); > + > + DBG(6, priv, "pan x = %d, pan y = %d\n", *accumulated_x, > *accumulated_y); > + > + *accumulated_x = wcmButtonPerNotch(priv, *accumulated_x, threshold, > 6, 7); > + *accumulated_y = wcmButtonPerNotch(priv, *accumulated_y, threshold, > 4, 5); > +} > + > > /***************************************************************************** > * wcmSendButtons -- > * Send button events by comparing the current button mask with the > @@ -170,6 +214,7 @@ static void sendAction(InputInfoPtr pInfo, const > WacomDeviceState* ds, > int press, unsigned int *keys, int nkeys, > int first_val, int num_val, int *valuators) > { > + WacomDevicePtr priv = (WacomDevicePtr) pInfo->private; > int i; > > /* Actions only trigger on press, not release */ > @@ -186,10 +231,15 @@ static void sendAction(InputInfoPtr pInfo, const > WacomDeviceState* ds, > { > int btn_no = (action & AC_CODE); > int is_press = (action & > AC_KEYBTNPRESS); > - xf86PostButtonEventP(pInfo->dev, > - > is_absolute(pInfo), btn_no, > - is_press, > first_val, num_val, > - VCOPY(valuators, > num_val)); > + if (btn_no == 1 && (priv->flags & > SCROLLMODE_FLAG)) { > + /* Don't send clicks in > scroll mode */ > + } > + else { > + > xf86PostButtonEventP(pInfo->dev, > + > is_absolute(pInfo), btn_no, > + is_press, > first_val, num_val, > + > VCOPY(valuators, num_val)); > + } > } > break; > case AC_KEY: > @@ -204,6 +254,12 @@ static void sendAction(InputInfoPtr pInfo, const > WacomDeviceState* ds, > wcmDevSwitchModeCall(pInfo, > (is_absolute(pInfo)) > ? Relative : Absolute); /* not a typo! */ > break; > + case AC_PANSCROLL: > + priv->flags |= SCROLLMODE_FLAG; > + priv->wcmPanscrollState = *ds; > + priv->wcmPanscrollState.x = 0; > + priv->wcmPanscrollState.y = 0; > + break; > } > } > > @@ -240,8 +296,11 @@ static void sendAction(InputInfoPtr pInfo, const > WacomDeviceState* ds, > if (countPresses(key_code, &keys[i], > nkeys - i)) > wcmEmitKeycode(pInfo->dev, > key_code, 0); > } > + break; > + case AC_PANSCROLL: > + priv->flags &= ~SCROLLMODE_FLAG; > + break; > } > - > } > } > > @@ -428,6 +487,9 @@ static void sendCommonEvents(InputInfoPtr pInfo, const > WacomDeviceState* ds, > WacomDevicePtr priv = (WacomDevicePtr) pInfo->private; > int buttons = ds->buttons; > > + /* send scrolling events if necessary */ > + wcmPanscroll(priv, ds); > + > /* send button events when state changed or first time in prox and > button unpresses */ > if (priv->oldState.buttons != buttons || (!priv->oldState.proximity > && !buttons)) > wcmSendButtons(pInfo, ds, buttons, first_val, num_vals, > valuators); > @@ -568,7 +630,8 @@ wcmSendNonPadEvents(InputInfoPtr pInfo, const > WacomDeviceState *ds, > VCOPY(valuators, num_vals)); > > /* Move the cursor to where it should be before sending > button events */ > - if(!(priv->flags & BUTTONS_ONLY_FLAG)) > + if(!(priv->flags & BUTTONS_ONLY_FLAG) && > + !(priv->flags & SCROLLMODE_FLAG && priv->oldState.buttons > & 1)) > { > xf86PostMotionEventP(pInfo->dev, is_absolute(pInfo), > first_val, num_vals, > @@ -650,6 +713,10 @@ void wcmSendEvents(InputInfoPtr pInfo, const > WacomDeviceState* ds) > ty = ds->stripy; > } > > + /* cancel panscroll */ > + if (!ds->proximity) > + priv->flags &= ~SCROLLMODE_FLAG; > + > DBG(7, priv, "[%s] o_prox=%s x=%d y=%d z=%d " > "b=%s b=%d tx=%d ty=%d wl=%d wl2=%d rot=%d th=%d\n", > pInfo->type_name, > @@ -1356,6 +1423,16 @@ int wcmInitTablet(InputInfoPtr pInfo, const char* id, > float version) > pInfo->name, common->wcmThreshold); > } > > + /* Calculate default panscroll threshold if not set */ > + xf86Msg(X_CONFIG, "%s: panscroll is %d\n", pInfo->name, > common->wcmPanscrollThreshold); > + if (common->wcmPanscrollThreshold < 1) { > + common->wcmPanscrollThreshold = common->wcmResolY * 13 / > 1000; /* 13mm */ > + } > + if (common->wcmPanscrollThreshold < 1) { > + common->wcmPanscrollThreshold = 1000; > + } > + xf86Msg(X_CONFIG, "%s: panscroll modified to %d\n", pInfo->name, > common->wcmPanscrollThreshold); > + > /* output tablet state as probed */ > if (IsPen(priv)) > xf86Msg(X_PROBED, "%s: maxX=%d maxY=%d maxZ=%d " > @@ -1468,6 +1545,7 @@ WacomCommonPtr wcmNewCommon(void) > /* transmit position if increment is superior */ > common->wcmRawSample = DEFAULT_SAMPLES; > /* number of raw data to be used to for filtering */ > + common->wcmPanscrollThreshold = 0; > common->wcmPressureRecalibration = 1; > return common; > } > diff --git a/src/wcmValidateDevice.c b/src/wcmValidateDevice.c > index 21ccd5f..486235b 100644 > --- a/src/wcmValidateDevice.c > +++ b/src/wcmValidateDevice.c > @@ -912,6 +912,9 @@ Bool wcmPreInitParseOptions(InputInfoPtr pInfo, Bool > is_primary, > tool = priv->tool; > tool->serial = priv->serial; > > + common->wcmPanscrollThreshold = xf86SetIntOption(pInfo->options, > "PanScrollThreshold", > + common->wcmPanscrollThreshold); > + > /* The first device doesn't need to add any tools/areas as it > * will be the first anyway. So if different, add tool > * and/or area to the existing lists > diff --git a/src/wcmXCommand.c b/src/wcmXCommand.c > index e18fb8f..63d1b3d 100644 > --- a/src/wcmXCommand.c > +++ b/src/wcmXCommand.c > @@ -99,6 +99,7 @@ static Atom prop_tooltype; > static Atom prop_btnactions; > static Atom prop_product_id; > static Atom prop_pressure_recal; > +static Atom prop_panscroll_threshold; > #ifdef DEBUG > static Atom prop_debuglevels; > #endif > @@ -336,6 +337,9 @@ void InitWcmDeviceProperties(InputInfoPtr pInfo) > XA_INTEGER, 8, 1, values); > } > > + values[0] = common->wcmPanscrollThreshold; > + prop_panscroll_threshold = InitWcmAtom(pInfo->dev, > WACOM_PROP_PANSCROLL_THRESHOLD, XA_INTEGER, 32, 1, values); > + > values[0] = common->vendor_id; > values[1] = common->tablet_id; > prop_product_id = InitWcmAtom(pInfo->dev, XI_PROP_PRODUCT_ID, > XA_INTEGER, 32, 2, values); > @@ -455,6 +459,8 @@ static int wcmCheckActionProperty(WacomDevicePtr priv, > Atom property, XIProperty > break; > case AC_MODETOGGLE: > break; > + case AC_PANSCROLL: > + break; > default: > DBG(3, priv, "ERROR: Unknown command\n"); > return BadValue; > @@ -972,6 +978,21 @@ int wcmSetProperty(DeviceIntPtr dev, Atom property, > XIPropertyValuePtr prop, > > if (!checkonly) > common->wcmPressureRecalibration = values[0]; > + } else if (property == prop_panscroll_threshold) > + { > + CARD32 *values = (CARD32*)prop->data; > + > + if (prop->size != 1 || prop->format != 32) > + return BadValue; > + > + if (values[0] <= 0) > + return BadValue; > + > + if (IsTouch(priv)) > + return BadMatch; > + > + if (!checkonly) > + common->wcmPanscrollThreshold = values[0]; > } else > { > Atom *handler = NULL; > diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h > index a772597..a2053a8 100644 > --- a/src/xf86WacomDefs.h > +++ b/src/xf86WacomDefs.h > @@ -175,6 +175,7 @@ struct _WacomModel > #define ABSOLUTE_FLAG 0x00000100 > #define BAUD_19200_FLAG 0x00000400 > #define BUTTONS_ONLY_FLAG 0x00000800 > +#define SCROLLMODE_FLAG 0x00001000 > > #define IsCursor(priv) (DEVICE_ID((priv)->flags) == CURSOR_ID) > #define IsStylus(priv) (DEVICE_ID((priv)->flags) == STYLUS_ID) > @@ -288,6 +289,7 @@ struct _WacomDeviceRec > WacomCommonPtr common; /* common info pointer */ > > /* state fields in device coordinates */ > + struct _WacomDeviceState wcmPanscrollState; /* panscroll state > tracking */ > struct _WacomDeviceState oldState; /* previous state information */ > int oldCursorHwProx; /* previous cursor hardware proximity */ > > @@ -467,6 +469,7 @@ struct _WacomCommonRec > int wcmRawSample; /* Number of raw data used to filter an > event */ > int wcmPressureRecalibration; /* Determine if pressure recalibration > of > worn pens should be performed */ > + int wcmPanscrollThreshold; /* distance pen must move to send a > panscroll event */ > > int bufpos; /* position with buffer */ > unsigned char buffer[BUFFER_SIZE]; /* data read from device */ > diff --git a/tools/xsetwacom.c b/tools/xsetwacom.c > index 1051868..5615836 100644 > --- a/tools/xsetwacom.c > +++ b/tools/xsetwacom.c > @@ -471,6 +471,15 @@ static param_t parameters[] = > .arg_count = 1, > .prop_flags = PROP_FLAG_BOOLEAN > }, > + { > + .name = "PanScrollThreshold", > + .x11name = "PanScrollThreshold", > + .desc = "Adjusts distance required for pan actions to > generate a scroll event", > + .prop_name = WACOM_PROP_PANSCROLL_THRESHOLD, > + .prop_format = 32, > + .prop_offset = 0, > + .arg_count = 1, > + }, > { > .name = "MapToOutput", > .desc = "Map the device to the given output. ", > @@ -1012,6 +1021,7 @@ static int special_map_button(Display *dpy, int argc, > char **argv, unsigned long > static int special_map_core(Display *dpy, int argc, char **argv, unsigned > long *ndata, unsigned long *data, const size_t size); > static int special_map_modetoggle(Display *dpy, int argc, char **argv, > unsigned long *ndata, unsigned long *data, const size_t size); > static int special_map_displaytoggle(Display *dpy, int argc, char **argv, > unsigned long *ndata, unsigned long *data, const size_t size); > +static int special_map_panscroll(Display *dpy, int argc, char **argv, > unsigned long *ndata, unsigned long *data, const size_t size); > > /* Valid keywords for the --set ButtonX options */ > static struct keywords { > @@ -1023,6 +1033,7 @@ static struct keywords { > {"core", special_map_core}, > {"modetoggle", special_map_modetoggle}, > {"displaytoggle", special_map_displaytoggle}, > + {"pan", special_map_panscroll}, > { NULL, NULL } > }; > > @@ -1067,6 +1078,19 @@ static int special_map_displaytoggle(Display *dpy, int > argc, char **argv, unsign > return 0; > } > > +static int special_map_panscroll(Display *dpy, int argc, char **argv, > unsigned long *ndata, unsigned long *data, const size_t size) > +{ > + if (*ndata + 1 > size) { > + fprintf(stderr, "Insufficient space to store all > commands.\n"); > + return 0; > + } > + data[*ndata] = AC_PANSCROLL; > + > + *ndata += 1; > + > + return 0; > +} > + > static inline int is_valid_keyword(const char *keyword) > { > struct keywords *kw = keywords; > -- > 2.15.1 > ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel