mirror of
https://github.com/X11Libre/xf86-input-synaptics.git
synced 2026-04-14 11:54:16 +00:00
Added support for circular scrolling. From Alexei Gilchrist
<alexei@physics.uq.edu.au>, with some cosmetic changes by me.
This commit is contained in:
14
README
14
README
@@ -107,6 +107,12 @@ TapButton2 Int Which mouse button is reported on a non-corner two-finger tap
|
||||
0=No action, 1=Left Button, 2=Middle Button, 3=Right Button
|
||||
TapButton3 Int Which mouse button is reported on a non-corner three-finger tap
|
||||
0=No action, 1=Left Button, 2=Middle Button, 3=Right Button
|
||||
CircularScrolling Bool If on, circular scrolling is used (see below)
|
||||
CircScrollDelta Float Move angle (radians) of finger to generate a scroll event
|
||||
CircScrollTrigger Int Trigger region on the touchpad to start circular scrolling
|
||||
0=All Edges, 1=Top Edge, 2=Top Right Corner, 3=Right Edge,
|
||||
4=Bottom Right Corner, 5=Bottom Edge, 6=Bottom Left Corner,
|
||||
7=Left Edge, 8=Top Left Corner
|
||||
|
||||
A tap event happens when the finger is touched and released in a time
|
||||
interval shorter than MaxTapTime, and the touch and release
|
||||
@@ -133,6 +139,14 @@ events. If you press both the left and right mouse buttons at almost
|
||||
the same time (no more than EmulateMidButtonTime milliseconds apart)
|
||||
the driver generates a middle mouse button event.
|
||||
|
||||
Circular scrolling acts like a scrolling wheel on the trackpad.
|
||||
Scrolling is engaged when a drag starts in the given CircScrollTrigger
|
||||
region, which can be all edges, a particular side, or a particular
|
||||
corner. Once scrolling is engaged, moving your finger in clockwise
|
||||
circles around the trackpad will generate scroll down events and
|
||||
counter clockwise scroll up events. Lifting your finger will disengage
|
||||
circular scrolling. Use tight circles near the center of the pad for
|
||||
fast scrolling and large circles for better control.
|
||||
|
||||
FAQ
|
||||
---
|
||||
|
||||
99
synaptics.c
99
synaptics.c
@@ -1,4 +1,7 @@
|
||||
/*
|
||||
* Copyright 2004 Alexei Gilchrist <alexei@physics.uq.edu.au>
|
||||
* patch for circular scrolling
|
||||
*
|
||||
* Copyright 2003 Jörg Bösner <ich@joerg-boesner.de>
|
||||
* patch for switching the touchpad off (for example, when a
|
||||
* USB mouse is connected)
|
||||
@@ -110,6 +113,10 @@ typedef enum {
|
||||
#define TIME_DIFF(a, b) ((long)((a)-(b)))
|
||||
#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/* for auto-dev: */
|
||||
#define DEV_INPUT_EVENT "/dev/input"
|
||||
#define EVENT_DEV_NAME "event"
|
||||
@@ -336,6 +343,8 @@ SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
|
||||
priv->synpara->tap_action[F1_TAP] = xf86SetIntOption(local->options, "TapButton1", 1);
|
||||
priv->synpara->tap_action[F2_TAP] = xf86SetIntOption(local->options, "TapButton2", 2);
|
||||
priv->synpara->tap_action[F3_TAP] = xf86SetIntOption(local->options, "TapButton3", 3);
|
||||
priv->synpara->circular_scrolling = xf86SetBoolOption(local->options, "CircularScrolling", FALSE);
|
||||
priv->synpara->circular_trigger = xf86SetIntOption(local->options, "CircScrollTrigger", 0);
|
||||
|
||||
str_par = xf86FindOptionValue(local->options, "MinSpeed");
|
||||
if ((!str_par) || (xf86sscanf(str_par, "%lf", &priv->synpara->min_speed) != 1))
|
||||
@@ -346,6 +355,14 @@ SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
|
||||
str_par = xf86FindOptionValue(local->options, "AccelFactor");
|
||||
if ((!str_par) || (xf86sscanf(str_par, "%lf", &priv->synpara->accl) != 1))
|
||||
priv->synpara->accl=0.0015;
|
||||
str_par = xf86FindOptionValue(local->options, "CircScrollDelta");
|
||||
if ((!str_par) || (xf86sscanf(str_par, "%lf", &priv->synpara->scroll_dist_circ) != 1))
|
||||
priv->synpara->scroll_dist_circ = 0.1;
|
||||
|
||||
if (priv->synpara->circular_trigger < 0 || priv->synpara->circular_trigger > 8) {
|
||||
xf86Msg(X_WARNING, "Unknown circular scrolling trigger, using 0 (edges)");
|
||||
priv->synpara->circular_trigger = 0;
|
||||
}
|
||||
|
||||
/* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
|
||||
if (priv->synpara->top_edge > priv->synpara->bottom_edge) {
|
||||
@@ -573,6 +590,28 @@ move_distance(int dx, int dy)
|
||||
return xf86sqrt((dx * dx) + (dy * dy));
|
||||
}
|
||||
|
||||
/* return angle of point relative to center */
|
||||
static double
|
||||
angle(SynapticsPrivate *priv, int x, int y)
|
||||
{
|
||||
double xCenter = (priv->synpara->left_edge + priv->synpara->right_edge) / 2.0;
|
||||
double yCenter = (priv->synpara->top_edge + priv->synpara->bottom_edge) / 2.0;
|
||||
|
||||
return xf86atan2(-(y - yCenter), x - xCenter);
|
||||
}
|
||||
|
||||
/* return angle difference */
|
||||
static double
|
||||
diffa(double a1, double a2)
|
||||
{
|
||||
double da = xf86fmod(a2 - a1, 2 * M_PI);
|
||||
if (da < 0)
|
||||
da += 2 * M_PI;
|
||||
if (da > M_PI)
|
||||
da -= 2 * M_PI;
|
||||
return da;
|
||||
}
|
||||
|
||||
static edge_type
|
||||
edge_detection(SynapticsPrivate *priv, int x, int y)
|
||||
{
|
||||
@@ -1004,17 +1043,38 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw)
|
||||
|
||||
/* scroll detection */
|
||||
if (finger && !priv->finger_flag) {
|
||||
if (edge & RIGHT_EDGE) {
|
||||
priv->vert_scroll_on = TRUE;
|
||||
priv->scroll_y = hw->y;
|
||||
DBG(7, ErrorF("vert edge scroll detected on right edge\n"));
|
||||
}
|
||||
if (edge & BOTTOM_EDGE) {
|
||||
priv->horiz_scroll_on = TRUE;
|
||||
priv->scroll_x = hw->x;
|
||||
DBG(7, ErrorF("horiz edge scroll detected on bottom edge\n"));
|
||||
if (para->circular_scrolling) {
|
||||
if ((para->circular_trigger == 0 && edge) ||
|
||||
(para->circular_trigger == 1 && edge & TOP_EDGE) ||
|
||||
(para->circular_trigger == 2 && edge & TOP_EDGE && edge & RIGHT_EDGE) ||
|
||||
(para->circular_trigger == 3 && edge & RIGHT_EDGE) ||
|
||||
(para->circular_trigger == 4 && edge & RIGHT_EDGE && edge & BOTTOM_EDGE) ||
|
||||
(para->circular_trigger == 5 && edge & BOTTOM_EDGE) ||
|
||||
(para->circular_trigger == 6 && edge & BOTTOM_EDGE && edge & LEFT_EDGE) ||
|
||||
(para->circular_trigger == 7 && edge & LEFT_EDGE) ||
|
||||
(para->circular_trigger == 8 && edge & LEFT_EDGE && edge & TOP_EDGE)) {
|
||||
priv->circ_scroll_on = TRUE;
|
||||
priv->scroll_a = angle(priv, hw->x, hw->y);
|
||||
DBG(7, ErrorF("circular scroll detected on edge\n"));
|
||||
}
|
||||
} else {
|
||||
if (edge & RIGHT_EDGE) {
|
||||
priv->vert_scroll_on = TRUE;
|
||||
priv->scroll_y = hw->y;
|
||||
DBG(7, ErrorF("vert edge scroll detected on right edge\n"));
|
||||
}
|
||||
if (edge & BOTTOM_EDGE) {
|
||||
priv->horiz_scroll_on = TRUE;
|
||||
priv->scroll_x = hw->x;
|
||||
DBG(7, ErrorF("horiz edge scroll detected on bottom edge\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (priv->circ_scroll_on && (!finger || priv->palm)) {
|
||||
/* circular scroll locks in until finger is raised */
|
||||
DBG(7, ErrorF("cicular scroll off\n"));
|
||||
priv->circ_scroll_on = FALSE;
|
||||
}
|
||||
if (priv->vert_scroll_on && (!(edge & RIGHT_EDGE) || !finger || priv->palm)) {
|
||||
DBG(7, ErrorF("vert edge scroll off\n"));
|
||||
priv->vert_scroll_on = FALSE;
|
||||
@@ -1038,6 +1098,25 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw)
|
||||
priv->scroll_y -= para->scroll_dist_vert;
|
||||
}
|
||||
}
|
||||
if (priv->circ_scroll_on) {
|
||||
/* + = counter clockwise, - = clockwise */
|
||||
while (diffa(priv->scroll_a, angle(priv, hw->x, hw->y)) > para->scroll_dist_circ) {
|
||||
scroll_up++;
|
||||
if (scroll_up > 1000)
|
||||
break; /* safety */
|
||||
priv->scroll_a += para->scroll_dist_circ;
|
||||
if (priv->scroll_a > M_PI)
|
||||
priv->scroll_a -= 2 * M_PI;
|
||||
}
|
||||
while (diffa(priv->scroll_a, angle(priv, hw->x, hw->y)) < -para->scroll_dist_circ) {
|
||||
scroll_down++;
|
||||
if (scroll_down > 1000)
|
||||
break; /* safety */
|
||||
priv->scroll_a -= para->scroll_dist_circ;
|
||||
if (priv->scroll_a < -M_PI)
|
||||
priv->scroll_a += 2 * M_PI;
|
||||
}
|
||||
}
|
||||
scroll_left = 0;
|
||||
scroll_right = 0;
|
||||
if (priv->horiz_scroll_on) {
|
||||
@@ -1053,7 +1132,7 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw)
|
||||
}
|
||||
|
||||
/* movement */
|
||||
if (finger && !priv->vert_scroll_on && !priv->horiz_scroll_on &&
|
||||
if (finger && !priv->vert_scroll_on && !priv->horiz_scroll_on && !priv->circ_scroll_on &&
|
||||
!priv->finger_count && !priv->palm) {
|
||||
delay = MIN(delay, 13);
|
||||
if (priv->count_packet_finger > 3) { /* min. 3 packets */
|
||||
|
||||
@@ -54,6 +54,9 @@ typedef struct _SynapticsSHM
|
||||
Bool touchpad_off; /* Switches the Touchpad off*/
|
||||
Bool locked_drags; /* Enable locked drags */
|
||||
int tap_action[MAX_TAP]; /* Button to report on tap events */
|
||||
Bool circular_scrolling; /* Enable circular scrolling */
|
||||
double scroll_dist_circ; /* Scrolling angle radians */
|
||||
int circular_trigger; /* Trigger area for circular scrolling */
|
||||
} SynapticsSHM;
|
||||
|
||||
#ifdef SYNAPTICS_PRIVATE
|
||||
@@ -147,6 +150,7 @@ typedef struct _SynapticsPrivateRec
|
||||
int largest_valid_x; /* Largest valid X coordinate seen so far */
|
||||
int scroll_y; /* last y-scroll position */
|
||||
int scroll_x; /* last x-scroll position */
|
||||
double scroll_a; /* last angle-scroll position */
|
||||
unsigned long count_packet_finger; /* packet counter with finger on the touchpad */
|
||||
unsigned int tapping_millis; /* packet counter for tapping */
|
||||
unsigned int button_delay_millis; /* button delay for 3rd button emulation */
|
||||
@@ -157,6 +161,7 @@ typedef struct _SynapticsPrivateRec
|
||||
Bool tap_left, tap_mid, tap_right; /* tapping buttons */
|
||||
Bool vert_scroll_on; /* scrolling flag */
|
||||
Bool horiz_scroll_on; /* scrolling flag */
|
||||
Bool circ_scroll_on; /* scrolling flag */
|
||||
double frac_x, frac_y; /* absoulte -> relative fraction */
|
||||
enum MidButtonEmulation mid_emu_state; /* emulated 3rd button */
|
||||
int repeatButtons; /* buttons for repeat */
|
||||
|
||||
@@ -71,6 +71,9 @@ static struct Parameter params[] = {
|
||||
DEFINE_PAR("TapButton1", tap_action[F1_TAP], PT_INT, 0, 3),
|
||||
DEFINE_PAR("TapButton2", tap_action[F2_TAP], PT_INT, 0, 3),
|
||||
DEFINE_PAR("TapButton3", tap_action[F3_TAP], PT_INT, 0, 3),
|
||||
DEFINE_PAR("CircularScrolling", circular_scrolling, PT_BOOL, 0, 1),
|
||||
DEFINE_PAR("CircScrollDelta", scroll_dist_circ, PT_DOUBLE, .01, 3),
|
||||
DEFINE_PAR("CircScrollTrigger", circular_trigger, PT_INT, 0, 8),
|
||||
{ 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user