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

Reply via email to