Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DeJitter functionality to Wacom driver and update documentation #361

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions include/wacom-properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,13 @@
#define WACOM_PROP_XI_TYPE_PAD "PAD"
#define WACOM_PROP_XI_TYPE_TOUCH "TOUCH"

/* BOOL, 1 value */
#define WACOM_PROP_DEJITTER_ENABLED "Wacom DeJitter Enabled"

/* 32 bit, 1 value */
#define WACOM_PROP_DEJITTER_THRESHOLD "Wacom DeJitter Threshold"

/* 32 bit, 1 value */
#define WACOM_PROP_DEJITTER_TIME_THRESHOLD "Wacom DeJitter Time Threshold"

#endif
15 changes: 15 additions & 0 deletions man/xsetwacom.man
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,21 @@ 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
\fBDeJitterEnable\fR on|off
Enable or disable the de-jittering feature. When enabled, the device will
attempt to suppress small, erratic movements based on the thresholds defined
below. Default: off.
.TP
\fBDeJitterThreshold\fR distance
Set the spatial threshold for de-jittering in device units. Movements below
this distance will be suppressed if de-jittering is enabled. Default: 150,
range: 0 to 1000.
.TP
\fBDeJitterTimeThreshold\fR milliseconds
Set the time threshold for de-jittering in milliseconds. Movements that occur
within this time and below the spatial threshold will be suppressed. Default:
100 ms, range: 0 to 10000 ms.
.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
Expand Down
95 changes: 75 additions & 20 deletions src/wcmCommon.c
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,58 @@ void wcmSendEvents(WacomDevicePtr priv, const WacomDeviceState* ds)
wcmAxisSet(&axes, WACOM_AXIS_PRESSURE, ds->pressure);
}

bool supressing = false;
if (priv->wcmDejitterEnabled)
{
CARD32 now = GetTimeInMillis();
const int Thresh = priv->wcmDejitterThreshold == 0 ? 150 : priv->wcmDejitterThreshold;
const int TimeThresh = priv->wcmDejitterTimeThreshold == 0 ? 100 : priv->wcmDejitterTimeThreshold;
if (ds->buttons > 0)
{
if (priv->dejitterState.is_suppresed)
{
int dx = priv->dejitterState.x - x;
int dy = priv->dejitterState.y - y;
if (now < priv->dejitterState.suppress_start + TimeThresh &&
dx * dx + dy * dy < Thresh * Thresh)
{
DBG(10, priv, "suppressing\n");
x = priv->dejitterState.x;
y = priv->dejitterState.y;
wcmAxisSet(&axes, WACOM_AXIS_X, x);
wcmAxisSet(&axes, WACOM_AXIS_Y, y);
supressing = true;
}
}
else
{
DBG(10, priv, "start suppressing\n");
priv->dejitterState.is_suppresed = true;
priv->dejitterState.x = x;
priv->dejitterState.y = y;
priv->dejitterState.suppress_start = now;
}
}
else
{
if (priv->dejitterState.is_suppresed)
{
DBG(10, priv, "stop suppressing\n");
priv->dejitterState.is_suppresed = false;
int dx = priv->dejitterState.x - x;
int dy = priv->dejitterState.y - y;
if (now < priv->dejitterState.suppress_start + TimeThresh &&
dx * dx + dy * dy < Thresh * Thresh)
{
x = priv->dejitterState.x;
y = priv->dejitterState.y;
wcmAxisSet(&axes, WACOM_AXIS_X, x);
wcmAxisSet(&axes, WACOM_AXIS_Y, y);
}
}
}
}

if (type == PAD_ID)
{
wcmAxisSet(&axes, WACOM_AXIS_STRIP_X, ds->stripx);
Expand Down Expand Up @@ -925,28 +977,31 @@ void wcmSendEvents(WacomDevicePtr priv, const WacomDeviceState* ds)
ds->proximity, dump, id, serial, is_button ? "true" : "false",
ds->buttons);

/* when entering prox, replace the zeroed-out oldState with a copy of
* the current state to prevent jumps. reset the prox and button state
* to zero to properly detect changes.
*/
if(!priv->oldState.proximity)
if (!supressing)
{
int old_key_state = priv->oldState.keys;

wcmUpdateOldState(priv, ds, x, y);
priv->oldState.proximity = 0;
priv->oldState.buttons = 0;

/* keys can happen without proximity */
priv->oldState.keys = old_key_state;
}

if (type == PAD_ID)
wcmSendPadEvents(priv, ds, &axes);
else {
/* don't move the cursor if in gesture mode (except drag mode) */
if ((type != TOUCH_ID) || wcmTouchNeedSendEvents(priv->common))
/* when entering prox, replace the zeroed-out oldState with a copy of
* the current state to prevent jumps. reset the prox and button state
* to zero to properly detect changes.
*/
if (!priv->oldState.proximity)
{
int old_key_state = priv->oldState.keys;

wcmUpdateOldState(priv, ds, x, y);
priv->oldState.proximity = 0;
priv->oldState.buttons = 0;

/* keys can happen without proximity */
priv->oldState.keys = old_key_state;
}

if (type == PAD_ID)
wcmSendPadEvents(priv, ds, &axes);
else {
/* don't move the cursor if in gesture mode (except drag mode) */
if ((type != TOUCH_ID) || wcmTouchNeedSendEvents(priv->common))
wcmSendNonPadEvents(priv, ds, &axes);
}
}

if (ds->proximity)
Expand Down
48 changes: 48 additions & 0 deletions src/x11/xf86WacomProperties.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ static Atom prop_panscroll_threshold;
#ifdef DEBUG
static Atom prop_debuglevels;
#endif
static Atom prop_dejitter_enabled;
static Atom prop_dejitter_threshold;
static Atom prop_dejitter_time_threshold;

/**
* Calculate a user-visible pressure level from a driver-internal pressure
Expand Down Expand Up @@ -295,6 +298,15 @@ void InitWcmDeviceProperties(WacomDevicePtr priv)
prop_debuglevels = InitWcmAtom(pInfo->dev, WACOM_PROP_DEBUGLEVELS, XA_INTEGER, 8, 2, values);
#endif

values[0] = priv->wcmDejitterEnabled;
prop_dejitter_enabled = InitWcmAtom(pInfo->dev, WACOM_PROP_DEJITTER_ENABLED, XA_INTEGER, 8, 1, values);

values[0] = priv->wcmDejitterThreshold;
prop_dejitter_threshold = InitWcmAtom(pInfo->dev, WACOM_PROP_DEJITTER_THRESHOLD, XA_INTEGER, 32, 1, values);

values[0] = priv->wcmDejitterTimeThreshold;
prop_dejitter_time_threshold = InitWcmAtom(pInfo->dev, WACOM_PROP_DEJITTER_TIME_THRESHOLD, XA_INTEGER, 32, 1, values);

XIRegisterPropertyHandler(pInfo->dev, wcmSetProperty, wcmGetProperty, wcmDeleteProperty);
}

Expand Down Expand Up @@ -945,6 +957,42 @@ static int wcmSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr pr

if (!checkonly)
common->wcmPanscrollThreshold = values[0];
} else if (property == prop_dejitter_enabled)
{
CARD8 *values = (CARD8*)prop->data;

if (prop->size != 1 || prop->format != 8)
return BadValue;

if ((values[0] != 0) && (values[0] != 1))
return BadValue;

if (!checkonly && priv->wcmDejitterEnabled != values[0])
priv->wcmDejitterEnabled = values[0];
} else if (property == prop_dejitter_threshold)
{
INT32 *values = (INT32*)prop->data;

if (prop->size != 1 || prop->format != 32)
return BadValue;

if (values[0] > 1000)
return BadValue;

if (!checkonly && priv->wcmDejitterThreshold != values[0])
priv->wcmDejitterThreshold = values[0];
} else if (property == prop_dejitter_time_threshold)
{
INT32 *values = (INT32*)prop->data;

if (prop->size != 1 || prop->format != 32)
return BadValue;

if (values[0] > 10000)
return BadValue;

if (!checkonly && priv->wcmDejitterTimeThreshold != values[0])
priv->wcmDejitterTimeThreshold = values[0];
} else
{
Atom *handler = NULL;
Expand Down
12 changes: 12 additions & 0 deletions src/xf86WacomDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@ struct _WacomDeviceState
unsigned int keys; /* bitmask for IDX_KEY_CONTROLPANEL, etc. */
};

struct _WacomDejitterState
{
int x;
int y;
bool is_suppresed;
CARD32 suppress_start;
};

static const struct _WacomDeviceState OUTPROX_STATE = {
.abswheel = INT_MAX,
.abswheel2 = INT_MAX
Expand Down Expand Up @@ -310,6 +318,10 @@ 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 */
struct _WacomDejitterState dejitterState;
int wcmDejitterEnabled;
int wcmDejitterThreshold;
int wcmDejitterTimeThreshold;

ValuatorMask *valuator_mask; /* reusable valuator mask for sending events without reallocation */
};
Expand Down
25 changes: 25 additions & 0 deletions tools/xsetwacom.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,31 @@ static param_t parameters[] =
.arg_count = 1,
.prop_flags = PROP_FLAG_WRITEONLY | PROP_FLAG_OUTPUT,
},
{
.name = "DeJitterEnable",
.desc = "Enable or disable de-jittering (default is off).",
.prop_name = WACOM_PROP_DEJITTER_ENABLED,
.prop_format = 8,
.prop_offset = 0,
.arg_count = 1,
.prop_flags = PROP_FLAG_BOOLEAN,
},
{
.name = "DeJitterThreshold",
.desc = "Set the spatial threshold for de-jittering (default is 150).",
.prop_name = WACOM_PROP_DEJITTER_THRESHOLD,
.prop_format = 32,
.prop_offset = 0,
.arg_count = 1,
},
{
.name = "DeJitterTimeThreshold",
.desc = "Set the time threshold (in ms) for de-jittering (default is 100).",
.prop_name = WACOM_PROP_DEJITTER_TIME_THRESHOLD,
.prop_format = 32,
.prop_offset = 0,
.arg_count = 1,
},
{
.name = "all",
.desc = "Get value for all parameters. ",
Expand Down