diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h index 0b8975c..8bd1365 100644 --- a/include/synaptics-properties.h +++ b/include/synaptics-properties.h @@ -81,6 +81,15 @@ /* 8 bit (BOOL) */ #define SYNAPTICS_PROP_EDGEMOTION "Synaptics Edge Motion Always" +/* 8 bit (BOOL), 2 values [x, y], 1 inverts axis */ +#define SYNAPTICS_PROP_INVERT_AXES "Synaptics Axis Inversion" + +/* 8 bit (BOOL) */ +#define SYNAPTICS_PROP_SWAP_AXES "Synaptics Axes Swap" + +/* 8 bit, valid values (0, 1, 2, 3) for normal, inverted, left, right */ +#define SYNAPTICS_PROP_ROTATE_TOUCHPAD "Synaptics Rotate Touchpad" + /* 8 bit (BOOL), 2 values, updown, leftright */ #define SYNAPTICS_PROP_BUTTONSCROLLING "Synaptics Button Scrolling" diff --git a/include/synaptics.h b/include/synaptics.h index 28031d5..3b9bc7a 100644 --- a/include/synaptics.h +++ b/include/synaptics.h @@ -105,6 +105,16 @@ typedef struct _SynapticsSHM int edge_motion_max_speed; /* fastest setting for edge motion speed */ Bool edge_motion_use_always; /* If false, egde motion is used only when dragging */ + Bool swap_axes; /* If true, swap horizontal (x) with vertical motion (y) */ + Bool invert_x; /* If true, revert x-coordinate motion */ + Bool invert_y; /* If true, revert y-coordinate motion */ + int rotate_touchpad; /* Performs adjustments on motion and scrolling as if rotated + * 0 : normal + * 1 : inverted + * 2 : left + * 3 : right + */ + Bool updown_button_scrolling; /* Up/Down-Button scrolling or middle/double-click */ Bool leftright_button_scrolling; /* Left/right-button scrolling, or two lots of middle button */ Bool updown_button_repeat; /* If up/down button being used to scroll, auto-repeat?*/ diff --git a/man/synaptics.man b/man/synaptics.man index b18fb8d..ec04d92 100644 --- a/man/synaptics.man +++ b/man/synaptics.man @@ -196,6 +196,20 @@ If on, edge motion is also used for normal movements. If off, egde motion is used only when dragging. Property: "Synaptics Edge Motion Always" .TP +.BI "Option \*qInvertX\*q \*q" boolean \*q +.TP +.BI "Option \*qInvertY\*q \*q" boolean \*q +Invert the given axis. Default: off. +.TP +.BI "Option \*qSwapAxes\*q \*q" boolean \*q +Swap x/y axes. Default: off. +.TP +.BI "Option \*qRotateTouchpad\*q \*q" string \*q +Use this option together with the RANDR extension. It makes adjustments +so that motion and scroll be dependent on rotation. The values may be one of +"normal", "inverted", "left" and "right". It interferes with the previous +three options only as regards motion, not scrolling. Default: "left". +.TP .BI "Option \*qMinSpeed\*q \*q" float \*q Minimum speed factor. Property: "Synaptics Move Speed" .TP diff --git a/src/properties.c b/src/properties.c index 0861ae0..cde1440 100644 --- a/src/properties.c +++ b/src/properties.c @@ -61,6 +61,9 @@ Atom prop_speed = 0; Atom prop_edgemotion_pressure = 0; Atom prop_edgemotion_speed = 0; Atom prop_edgemotion_always = 0; +Atom prop_invert_axes = 0; +Atom prop_swap_axes = 0; +Atom prop_rotate_touchpad = 0; Atom prop_buttonscroll = 0; Atom prop_buttonscroll_repeat = 0; Atom prop_buttonscroll_time = 0; @@ -204,6 +207,12 @@ InitDeviceProperties(LocalDevicePtr local) prop_edgemotion_speed = InitAtom(local->dev, SYNAPTICS_PROP_EDGEMOTION_SPEED, 32, 2, values); prop_edgemotion_always = InitAtom(local->dev, SYNAPTICS_PROP_EDGEMOTION, 8, 1, ¶->edge_motion_use_always); + values[0] = para->invert_x; + values[1] = para->invert_y; + prop_invert_axes = InitAtom(local->dev, SYNAPTICS_PROP_INVERT_AXES, 8, 2, values); + prop_swap_axes = InitAtom(local->dev, SYNAPTICS_PROP_SWAP_AXES, 8, 1, ¶->swap_axes); + prop_rotate_touchpad = InitAtom(local->dev, SYNAPTICS_PROP_ROTATE_TOUCHPAD, 8, 1, ¶->rotate_touchpad); + values[0] = para->updown_button_scrolling; values[1] = para->leftright_button_scrolling; prop_buttonscroll = InitAtom(local->dev, SYNAPTICS_PROP_BUTTONSCROLLING, 8, 2, values); @@ -427,6 +436,38 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, para->edge_motion_use_always = *(BOOL*)prop->data; + } else if (property == prop_invert_axes) + { + BOOL *invert; + + if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER) + return BadMatch; + + invert = (BOOL*)prop->data; + para->invert_x = invert[0]; + para->invert_y = invert[1]; + + } else if (property == prop_swap_axes) + { + BOOL swap; + if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER) + return BadMatch; + + para->swap_axes = *(BOOL*)prop->data; + + } else if (property == prop_rotate_touchpad) + { + CARD8 rotate; + if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER) + return BadMatch; + + rotate = *(CARD8*)prop->data; + + if (rotate > 3) + return BadValue; + + para->rotate_touchpad = rotate; + } else if (property == prop_buttonscroll) { BOOL *scroll; diff --git a/src/synaptics.c b/src/synaptics.c index ddefecf..1e8cccf 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -290,6 +290,13 @@ free_param_data(SynapticsPrivate *priv) priv->synpara = NULL; } +static char *tchpad_rotation[4] = { + "normal", + "inverted", + "left", + "right" +}; + static void set_default_parameters(LocalDevicePtr local) { SynapticsPrivate *priv = local->private; /* read-only */ @@ -311,6 +318,8 @@ static void set_default_parameters(LocalDevicePtr local) int clickFinger1, clickFinger2, clickFinger3; Bool vertEdgeScroll, horizEdgeScroll; Bool vertTwoFingerScroll, horizTwoFingerScroll; + char *rotateTouchpad; + int i; /* read the parameters */ pars->version = (PACKAGE_VERSION_MAJOR*10000+PACKAGE_VERSION_MINOR*100+PACKAGE_VERSION_PATCHLEVEL); @@ -448,6 +457,18 @@ static void set_default_parameters(LocalDevicePtr local) pars->edge_motion_min_speed = xf86SetIntOption(opts, "EdgeMotionMinSpeed", edgeMotionMinSpeed); pars->edge_motion_max_speed = xf86SetIntOption(opts, "EdgeMotionMaxSpeed", edgeMotionMaxSpeed); pars->edge_motion_use_always = xf86SetBoolOption(opts, "EdgeMotionUseAlways", FALSE); + pars->invert_x = xf86SetBoolOption(opts, "InvertX", FALSE); + pars->invert_y = xf86SetBoolOption(opts, "InvertY", FALSE); + pars->swap_axes = xf86SetBoolOption(opts, "SwapAxes", FALSE); + rotateTouchpad = xf86SetStrOption(opts, "RotateTouchpad", "normal"); + for (i = 0; i < 4; i++) + if (!xf86NameCmp(tchpad_rotation[i], rotateTouchpad)) + break; + if (i == 4) + xf86Msg(X_WARNING, "%s: RotateTouchpad has an unrecognized value. " + "Resolving to \"normal\".\n", + local->name); + pars->rotate_touchpad = i % 4; pars->updown_button_scrolling = xf86SetBoolOption(opts, "UpDownScrolling", TRUE); pars->leftright_button_scrolling = xf86SetBoolOption(opts, "LeftRightScrolling", TRUE); pars->updown_button_repeat = xf86SetBoolOption(opts, "UpDownScrollRepeat", TRUE); @@ -1884,7 +1905,7 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) SynapticsPrivate *priv = (SynapticsPrivate *) (local->private); SynapticsSHM *para = priv->synpara; int finger; - int dx, dy, buttons, rep_buttons, id; + int dx, dy, tmp, map[4], buttons, rep_buttons, id; edge_type edge; int change; struct ScrollData scroll; @@ -2025,8 +2046,26 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) } /* Post events */ - if (dx || dy) + if (dx || dy) { + if (para->rotate_touchpad > 1) { /* left or right */ + tmp = (para->rotate_touchpad % 2) ? -dx : dx; + dx = (para->rotate_touchpad % 2) ? dy : -dy; + dy = tmp; + } else if (para->rotate_touchpad % 2) { /* inverted */ + dx = -dx; + dy = -dy; + } + if (para->swap_axes) { + tmp = dx; + dx = dy; + dy = tmp; + } + if (para->invert_x) + dx *= -1; + if (para->invert_y) + dy *= -1; xf86PostMotionEvent(local->dev, 0, 0, 2, dx, dy); + } if (priv->mid_emu_state == MBE_LEFT_CLICK) { @@ -2047,21 +2086,40 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) xf86PostButtonEvent(local->dev, FALSE, id, (buttons & (1 << (id - 1))), 0, 0); } - while (scroll.up-- > 0) { - xf86PostButtonEvent(local->dev, FALSE, 4, !hw->up, 0, 0); - xf86PostButtonEvent(local->dev, FALSE, 4, hw->up, 0, 0); - } - while (scroll.down-- > 0) { - xf86PostButtonEvent(local->dev, FALSE, 5, !hw->down, 0, 0); - xf86PostButtonEvent(local->dev, FALSE, 5, hw->down, 0, 0); - } - while (scroll.left-- > 0) { - xf86PostButtonEvent(local->dev, FALSE, 6, TRUE, 0, 0); - xf86PostButtonEvent(local->dev, FALSE, 6, FALSE, 0, 0); - } - while (scroll.right-- > 0) { - xf86PostButtonEvent(local->dev, FALSE, 7, TRUE, 0, 0); - xf86PostButtonEvent(local->dev, FALSE, 7, FALSE, 0, 0); + map[0] = 4; map[1] = 5; map[2] = 6; map[3] = 7; + if (para->rotate_touchpad % 3) { /* inverted or left */ + tmp = map[2]; + map[2] = map[3]; + map[3] = tmp; + } + if (para->rotate_touchpad % 2) { /* inverted or right */ + tmp = map[0]; + map[0] = map[1]; + map[1] = tmp; + } + if (para->rotate_touchpad > 1) { /* left or right */ + tmp = map[0]; + map[0] = map[2]; + map[2] = tmp; + tmp = map[1]; + map[1] = map[3]; + map[3] = tmp; + } + while (scroll.up-- > 0) { /* normal:4 */ + xf86PostButtonEvent(local->dev, FALSE, map[0], !hw->up, 0, 0); + xf86PostButtonEvent(local->dev, FALSE, map[0], hw->up, 0, 0); + } + while (scroll.down-- > 0) { /* normal:5 */ + xf86PostButtonEvent(local->dev, FALSE, map[1], !hw->down, 0, 0); + xf86PostButtonEvent(local->dev, FALSE, map[1], hw->down, 0, 0); + } + while (scroll.left-- > 0) { /* normal:6 */ + xf86PostButtonEvent(local->dev, FALSE, map[2], TRUE, 0, 0); + xf86PostButtonEvent(local->dev, FALSE, map[2], FALSE, 0, 0); + } + while (scroll.right-- > 0) { /* normal:7 */ + xf86PostButtonEvent(local->dev, FALSE, map[3], TRUE, 0, 0); + xf86PostButtonEvent(local->dev, FALSE, map[3], FALSE, 0, 0); } if (double_click) { int i;