summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--driver/xf86-input-ws/include/ws-properties.h12
-rw-r--r--driver/xf86-input-ws/man/ws.man82
-rw-r--r--driver/xf86-input-ws/src/Makefile.am3
-rw-r--r--driver/xf86-input-ws/src/Makefile.in7
-rw-r--r--driver/xf86-input-ws/src/emuwheel.c380
-rw-r--r--driver/xf86-input-ws/src/ws.c186
-rw-r--r--driver/xf86-input-ws/src/ws.h35
7 files changed, 604 insertions, 101 deletions
diff --git a/driver/xf86-input-ws/include/ws-properties.h b/driver/xf86-input-ws/include/ws-properties.h
index dd58eab99..f6d902859 100644
--- a/driver/xf86-input-ws/include/ws-properties.h
+++ b/driver/xf86-input-ws/include/ws-properties.h
@@ -23,6 +23,18 @@
/* CARD32 */
#define WS_PROP_MIDBUTTON_TIMEOUT "WS Pointer Middle Button Timeout"
+/* Mouse wheel emulation */
+/* BOOL */
+#define WS_PROP_WHEEL "WS Pointer Wheel Emulation"
+/* CARD8, 4 values [x up, x down, y up, y down], 0 to disable a value */
+#define WS_PROP_WHEEL_AXES "WS Pointer Wheel Emulation Axes"
+/* CARD16 */
+#define WS_PROP_WHEEL_INERTIA "WS Pointer Wheel Emulation Inertia"
+/* CARD32 */
+#define WS_PROP_WHEEL_TIMEOUT "WS Pointer Wheel Emulation Timeout"
+/* CARD8, value range 0-32, 0 to always scroll */
+#define WS_PROP_WHEEL_BUTTON "WS Pointer Wheel Emulation Button"
+
/* Run-time calibration */
/* CARD32, 4 values [minx, maxx, miny, maxy], or no values for unset */
#define WS_PROP_CALIBRATION "WS Pointer Axis Calibration"
diff --git a/driver/xf86-input-ws/man/ws.man b/driver/xf86-input-ws/man/ws.man
index 2e4acea20..09c23c15e 100644
--- a/driver/xf86-input-ws/man/ws.man
+++ b/driver/xf86-input-ws/man/ws.man
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ws.man,v 1.11 2011/11/19 12:28:10 shadchin Exp $
+.\" $OpenBSD: ws.man,v 1.12 2011/11/28 23:49:59 shadchin Exp $
.\"
.\" Copyright (c) 2005,2009,2011 Matthieu Herrb
.\"
@@ -69,6 +69,51 @@ Sets the timeout (in milliseconds) that the driver waits before deciding
if two buttons where pressed "simultaneously" when 3 button emulation is
enabled. Default: 50.
.TP 4
+.BI "Option \*qEmulateWheel\*q \*q" boolean \*q
+Enable/disable "wheel" emulation.
+Wheel emulation means emulating button press/release events when the mouse
+is moved while a specific real button is pressed.
+Wheel button events (typically buttons 4 and 5) are usually used for scrolling.
+Wheel emulation is useful for getting wheel-like behaviour with trackballs.
+It can also be useful for mice with 4 or more buttons but no wheel.
+See the description of the
+.BR EmulateWheelButton ,
+.BR EmulateWheelInertia ,
+.BR EmulateWheelTimeout ,
+.BR XAxisMapping ,
+and
+.B YAxisMapping
+options.
+Default: off.
+.TP 4
+.BI "Option \*qEmulateWheelButton\*q \*q" integer \*q
+Specifies which button must be held down to enable wheel emulation mode.
+While this button is down, X and/or Y pointer movement will generate button
+press/release events as specified for the
+.B XAxisMapping
+and
+.B YAxisMapping
+settings.
+If the button is 0 and
+.BR EmulateWheel
+is on, any motion of the device is converted into wheel events.
+Default:\ 4.
+.TP 4
+.BI "Option \*qEmulateWheelInertia\*q \*q" integer \*q
+Specifies how far (in pixels) the pointer must move to generate button
+press/release events in wheel emulation mode.
+Default:\ 10.
+.TP 4
+.BI "Option \*qEmulateWheelTimeout\*q \*q" integer \*q
+Specifies the time in milliseconds the
+.BR EmulateWheelButton
+must be pressed before wheel emulation is started.
+If the
+.BR EmulateWheelButton
+is released before this timeout, the original button press/release event
+is sent.
+Default:\ 200.
+.TP 4
.BI "Option \*qDebugLevel\*q \*q" integer \*q
This option sets the verbosity level of the driver.
It defaults to 0, which means no extra debug output.
@@ -107,6 +152,26 @@ clockwise, counter-clockwise, or upside-down respectively.
.BI "Option \*qSwapXY\*q \*q" boolean \*q
swaps the X and Y axis of the input device if set. Default: false.
.TP 4
+.BI "Option \*qXAxisMapping\*q \*q" "N1 N2" \*q
+Specifies which buttons are mapped to motion in the X direction in wheel
+emulation mode.
+Button number
+.I N1
+is mapped to the negative X axis motion and button number
+.I N2
+is mapped to the positive X axis motion.
+Default: no mapping.
+.TP 4
+.BI "Option \*qYAxisMapping\*q \*q" "N1 N2" \*q
+Specifies which buttons are mapped to motion in the Y direction in wheel
+emulation mode.
+Button number
+.I N1
+is mapped to the negative Y axis motion and button number
+.I N2
+is mapped to the positive Y axis motion.
+Default:\ "4\ 5".
+.TP 4
.BI "Option \*qZAxisMapping\*q \*q" "N1 N2" \*q
Set the mapping for the Z axis (wheel) motion to buttons. Button
number
@@ -135,6 +200,21 @@ driver.
.BI "WS Pointer Middle Button Timeout"
1 32-bit positive value (unit: milliseconds)
.TP 7
+.BI "WS Pointer Wheel Emulation"
+1 boolean value (8 bit, 0 or 1).
+.TP 7
+.BI "WS Pointer Wheel Emulation Axes"
+4 8-bit values, order X up, X down, Y up, Y down. 0 disables a value.
+.TP 7
+.BI "WS Pointer Wheel Emulation Button"
+1 8-bit value, allowed range 0-32, 0 to always scroll.
+.TP 7
+.BI "WS Pointer Wheel Emulation Inertia"
+1 16-bit positive value.
+.TP 7
+.BI "WS Pointer Wheel Emulation Timeout"
+1 32-bit positive value (unit: milliseconds).
+.TP 7
.BI "WS Pointer Axis Calibration"
4 32 bits values, in the order min-x, max-x, min-y, max-y.
This property is present only for devices with absolute coordinates (ie
diff --git a/driver/xf86-input-ws/src/Makefile.am b/driver/xf86-input-ws/src/Makefile.am
index 989f2457c..a400d3f40 100644
--- a/driver/xf86-input-ws/src/Makefile.am
+++ b/driver/xf86-input-ws/src/Makefile.am
@@ -24,4 +24,5 @@ INCLUDES=-I$(top_srcdir)/include/
@DRIVER_NAME@_drv_la_SOURCES = \
@DRIVER_NAME@.c \
@DRIVER_NAME@.h \
- emumb.c
+ emumb.c \
+ emuwheel.c
diff --git a/driver/xf86-input-ws/src/Makefile.in b/driver/xf86-input-ws/src/Makefile.in
index 562c9698f..c9e098b27 100644
--- a/driver/xf86-input-ws/src/Makefile.in
+++ b/driver/xf86-input-ws/src/Makefile.in
@@ -55,7 +55,8 @@ am__installdirs = "$(DESTDIR)$(@DRIVER_NAME@_drv_ladir)"
@DRIVER_NAME@_drv_laLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(@DRIVER_NAME@_drv_la_LTLIBRARIES)
@DRIVER_NAME@_drv_la_LIBADD =
-am_@DRIVER_NAME@_drv_la_OBJECTS = @DRIVER_NAME@.lo emumb.lo
+am_@DRIVER_NAME@_drv_la_OBJECTS = @DRIVER_NAME@.lo emumb.lo \
+ emuwheel.lo
@DRIVER_NAME@_drv_la_OBJECTS = $(am_@DRIVER_NAME@_drv_la_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -230,7 +231,8 @@ INCLUDES = -I$(top_srcdir)/include/
@DRIVER_NAME@_drv_la_SOURCES = \
@DRIVER_NAME@.c \
@DRIVER_NAME@.h \
- emumb.c
+ emumb.c \
+ emuwheel.c
all: all-am
@@ -303,6 +305,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/@DRIVER_NAME@.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emumb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emuwheel.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
diff --git a/driver/xf86-input-ws/src/emuwheel.c b/driver/xf86-input-ws/src/emuwheel.c
new file mode 100644
index 000000000..0be81a576
--- /dev/null
+++ b/driver/xf86-input-ws/src/emuwheel.c
@@ -0,0 +1,380 @@
+/* $OpenBSD: emuwheel.c,v 1.1 2011/11/28 23:49:59 shadchin Exp $ */
+/*
+* Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+* Copyright 1993 by David Dawes <dawes@xfree86.org>
+* Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
+* Copyright 1994-2002 by The XFree86 Project, Inc.
+* Copyright 2002 by Paul Elliott
+* (Ported from xf86-input-mouse, above copyrights taken from there)
+* Copyright 2008 by Chris Salch
+* Copyright © 2008 Red Hat, Inc.
+*
+* Permission to use, copy, modify, distribute, and sell this software
+* and its documentation for any purpose is hereby granted without
+* fee, provided that the above copyright notice appear in all copies
+* and that both that copyright notice and this permission notice
+* appear in supporting documentation, and that the name of the authors
+* not be used in advertising or publicity pertaining to distribution of the
+* software without specific, written prior permission. The authors make no
+* representations about the suitability of this software for any
+* purpose. It is provided "as is" without express or implied
+* warranty.
+*
+* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+* NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*
+*/
+
+/* Mouse wheel emulation code. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xorg-server.h>
+#include <X11/Xatom.h>
+#include <xf86.h>
+#include <xf86_OSproc.h>
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include <xf86Xinput.h>
+#include <exevents.h>
+
+#include <ws-properties.h>
+
+#include "ws.h"
+
+static Atom prop_wheel_emu;
+static Atom prop_wheel_axismap;
+static Atom prop_wheel_inertia;
+static Atom prop_wheel_timeout;
+static Atom prop_wheel_button;
+
+static int wsWheelEmuInertia(InputInfoPtr, WheelAxisPtr, int);
+static int wsWheelEmuSetProperty(DeviceIntPtr, Atom, XIPropertyValuePtr, BOOL);
+
+BOOL
+wsWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int press)
+{
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+ int ms;
+
+ if (!priv->emulateWheel.enabled)
+ return FALSE;
+
+ if (priv->emulateWheel.button == button) {
+ priv->emulateWheel.button_state = press;
+
+ if (press) {
+ priv->emulateWheel.expires = GetTimeInMillis() +
+ priv->emulateWheel.timeout;
+ } else {
+ ms = priv->emulateWheel.expires - GetTimeInMillis();
+
+ if (ms > 0) {
+ /*
+ * If the button is released early enough emit
+ * the button press/release events
+ */
+ wsButtonClicks(pInfo, button, 1);
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL
+wsWheelEmuFilterMotion(InputInfoPtr pInfo, int dx, int dy)
+{
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+ WheelAxisPtr pAxis = NULL, pOtherAxis = NULL;
+ int value;
+
+ if (!priv->emulateWheel.enabled)
+ return FALSE;
+
+ /*
+ * Handle our motion events if the emuWheel button is pressed.
+ * Wheel button of 0 means always emulate wheel.
+ */
+ if (priv->emulateWheel.button_state || priv->emulateWheel.button == 0) {
+ if (priv->emulateWheel.button) {
+ int ms = priv->emulateWheel.expires - GetTimeInMillis();
+
+ if (ms > 0)
+ return TRUE;
+ }
+
+ if (dx) {
+ pAxis = &(priv->emulateWheel.X);
+ pOtherAxis = &(priv->emulateWheel.Y);
+ value = dx;
+ } else if (dy) {
+ pAxis = &(priv->emulateWheel.Y);
+ pOtherAxis = &(priv->emulateWheel.X);
+ value = dy;
+ } else
+ return FALSE;
+
+ /*
+ * Reset the inertia of the other axis when a scroll event
+ * was sent to avoid the buildup of erroneous scroll events if the
+ * user doesn't move in a perfectly straight line.
+ */
+ if (pAxis) {
+ if (wsWheelEmuInertia(pInfo, pAxis, value))
+ pOtherAxis->traveled_distance = 0;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int
+wsWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value)
+{
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+ int button, inertia;
+ int rc = 0;
+
+ if (axis->negative == WS_NOMAP)
+ return rc;
+
+ axis->traveled_distance += value;
+
+ if (axis->traveled_distance < 0) {
+ button = axis->negative;
+ inertia = -priv->emulateWheel.inertia;
+ } else {
+ button = axis->positive;
+ inertia = priv->emulateWheel.inertia;
+ }
+
+ while (abs(axis->traveled_distance) > priv->emulateWheel.inertia) {
+ axis->traveled_distance -= inertia;
+ wsButtonClicks(pInfo, button, 1);
+ rc++;
+ }
+
+ return rc;
+}
+
+void
+wsWheelEmuPreInit(InputInfoPtr pInfo)
+{
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+ int button, inertia, timeout;
+
+ priv->emulateWheel.enabled = xf86SetBoolOption(pInfo->options,
+ "EmulateWheel", FALSE);
+
+ button = xf86SetIntOption(pInfo->options, "EmulateWheelButton", 4);
+ if (button < 0 || button > NBUTTONS) {
+ xf86IDrvMsg(pInfo, X_WARNING,
+ "Invalid EmulateWheelButton value: %d\n", button);
+ xf86IDrvMsg(pInfo, X_WARNING, "Wheel emulation disabled\n");
+ priv->emulateWheel.enabled = FALSE;
+ button = 4;
+ }
+ priv->emulateWheel.button = button;
+
+ inertia = xf86SetIntOption(pInfo->options, "EmulateWheelInertia", 10);
+ if (inertia <= 0) {
+ xf86IDrvMsg(pInfo, X_WARNING,
+ "Invalid EmulateWheelInertia value: %d\n", inertia);
+ xf86IDrvMsg(pInfo, X_WARNING, "Using built-in inertia value\n");
+ inertia = 10;
+ }
+ priv->emulateWheel.inertia = inertia;
+
+ timeout = xf86SetIntOption(pInfo->options, "EmulateWheelTimeout", 200);
+ if (timeout < 0) {
+ xf86IDrvMsg(pInfo, X_WARNING,
+ "Invalid EmulateWheelTimeout value: %d\n", timeout);
+ xf86IDrvMsg(pInfo, X_WARNING, "Using built-in timeout value\n");
+ timeout = 200;
+ }
+ priv->emulateWheel.timeout = timeout;
+
+ wsWheelHandleButtonMap(pInfo, &(priv->emulateWheel.Y),
+ "YAxisMapping", "4 5");
+ wsWheelHandleButtonMap(pInfo, &(priv->emulateWheel.X),
+ "XAxisMapping", NULL);
+}
+
+static int
+wsWheelEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+ BOOL checkonly)
+{
+ InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+
+ if (atom == prop_wheel_emu) {
+ if (val->format != 8 || val->size != 1 ||
+ val->type != XA_INTEGER)
+ return BadMatch;
+
+ if (!checkonly)
+ priv->emulateWheel.enabled = *((BOOL*)val->data) != 0;
+ } else if (atom == prop_wheel_button) {
+ int button;
+
+ if (val->format != 8 || val->size != 1 ||
+ val->type != XA_INTEGER)
+ return BadMatch;
+
+ button = *((CARD8*)val->data);
+
+ if (button < 0 || button > NBUTTONS)
+ return BadValue;
+
+ if (!checkonly)
+ priv->emulateWheel.button = button;
+ } else if (atom == prop_wheel_axismap) {
+ int x_negative, x_positive;
+ int y_negative, y_positive;
+
+ if (val->format != 8 || val->size != 4 ||
+ val->type != XA_INTEGER)
+ return BadMatch;
+
+ x_negative = *((CARD8*)val->data);
+ x_positive = *(((CARD8*)val->data) + 1);
+ y_negative = *(((CARD8*)val->data) + 2);
+ y_positive = *(((CARD8*)val->data) + 3);
+
+ if (x_negative < 0 || x_negative > NBUTTONS ||
+ x_positive < 0 || x_positive > NBUTTONS ||
+ y_negative < 0 || y_negative > NBUTTONS ||
+ y_positive < 0 || y_positive > NBUTTONS)
+ return BadValue;
+
+ if ((x_negative == WS_NOMAP && x_positive != WS_NOMAP) ||
+ (x_negative != WS_NOMAP && x_positive == WS_NOMAP) ||
+ (y_negative == WS_NOMAP && y_positive != WS_NOMAP) ||
+ (y_negative != WS_NOMAP && y_positive == WS_NOMAP))
+ return BadValue;
+
+ if (!checkonly) {
+ priv->emulateWheel.X.negative = x_negative;
+ priv->emulateWheel.X.positive = x_positive;
+ priv->emulateWheel.Y.negative = y_negative;
+ priv->emulateWheel.Y.positive = y_positive;
+ }
+ } else if (atom == prop_wheel_inertia) {
+ int inertia;
+
+ if (val->format != 16 || val->size != 1 ||
+ val->type != XA_INTEGER)
+ return BadMatch;
+
+ inertia = *((CARD16*)val->data);
+
+ if (inertia <= 0)
+ return BadValue;
+
+ if (!checkonly)
+ priv->emulateWheel.inertia = inertia;
+ } else if (atom == prop_wheel_timeout) {
+ int timeout;
+
+ if (val->format != 32 || val->size != 1 ||
+ val->type != XA_INTEGER)
+ return BadMatch;
+
+ timeout = *((CARD32*)val->data);
+
+ if (timeout < 0)
+ return BadValue;
+
+ if (!checkonly)
+ priv->emulateWheel.timeout = timeout;
+ }
+
+ return Success;
+}
+
+void
+wsWheelEmuInitProperty(DeviceIntPtr dev)
+{
+ InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+ char vals[4];
+ int rc;
+
+ prop_wheel_emu = MakeAtom(WS_PROP_WHEEL, strlen(WS_PROP_WHEEL), TRUE);
+ rc = XIChangeDeviceProperty(dev, prop_wheel_emu, XA_INTEGER, 8,
+ PropModeReplace, 1, &priv->emulateWheel.enabled, FALSE);
+ if (rc != Success) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "cannot create device property %s: %d\n",
+ WS_PROP_WHEEL, rc);
+ return;
+ }
+ XISetDevicePropertyDeletable(dev, prop_wheel_emu, FALSE);
+
+ vals[0] = priv->emulateWheel.X.negative;
+ vals[1] = priv->emulateWheel.X.positive;
+ vals[2] = priv->emulateWheel.Y.negative;
+ vals[3] = priv->emulateWheel.Y.positive;
+
+ prop_wheel_axismap = MakeAtom(WS_PROP_WHEEL_AXES,
+ strlen(WS_PROP_WHEEL_AXES), TRUE);
+ rc = XIChangeDeviceProperty(dev, prop_wheel_axismap, XA_INTEGER, 8,
+ PropModeReplace, 4, vals, FALSE);
+ if (rc != Success) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "cannot create device property %s: %d\n",
+ WS_PROP_WHEEL_AXES, rc);
+ return;
+ }
+ XISetDevicePropertyDeletable(dev, prop_wheel_axismap, FALSE);
+
+ prop_wheel_inertia = MakeAtom(WS_PROP_WHEEL_INERTIA,
+ strlen(WS_PROP_WHEEL_INERTIA), TRUE);
+ rc = XIChangeDeviceProperty(dev, prop_wheel_inertia, XA_INTEGER, 16,
+ PropModeReplace, 1, &priv->emulateWheel.inertia, FALSE);
+ if (rc != Success) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "cannot create device property %s: %d\n",
+ WS_PROP_WHEEL_INERTIA, rc);
+ return;
+ }
+ XISetDevicePropertyDeletable(dev, prop_wheel_inertia, FALSE);
+
+ prop_wheel_timeout = MakeAtom(WS_PROP_WHEEL_TIMEOUT,
+ strlen(WS_PROP_WHEEL_TIMEOUT), TRUE);
+ rc = XIChangeDeviceProperty(dev, prop_wheel_timeout, XA_INTEGER, 32,
+ PropModeReplace, 1, &priv->emulateWheel.timeout, FALSE);
+ if (rc != Success) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "cannot create device property %s: %d\n",
+ WS_PROP_WHEEL_TIMEOUT, rc);
+ return;
+ }
+ XISetDevicePropertyDeletable(dev, prop_wheel_timeout, FALSE);
+
+ prop_wheel_button = MakeAtom(WS_PROP_WHEEL_BUTTON,
+ strlen(WS_PROP_WHEEL_BUTTON), TRUE);
+ rc = XIChangeDeviceProperty(dev, prop_wheel_button, XA_INTEGER, 8,
+ PropModeReplace, 1, &priv->emulateWheel.button, FALSE);
+ if (rc != Success) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "cannot create device property %s: %d\n",
+ WS_PROP_WHEEL_BUTTON, rc);
+ return;
+ }
+ XISetDevicePropertyDeletable(dev, prop_wheel_button, FALSE);
+
+ XIRegisterPropertyHandler(dev, wsWheelEmuSetProperty, NULL, NULL);
+}
diff --git a/driver/xf86-input-ws/src/ws.c b/driver/xf86-input-ws/src/ws.c
index dae88fbe1..301f316a0 100644
--- a/driver/xf86-input-ws/src/ws.c
+++ b/driver/xf86-input-ws/src/ws.c
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $OpenBSD: ws.c,v 1.49 2011/11/19 13:12:49 shadchin Exp $ */
+/* $OpenBSD: ws.c,v 1.50 2011/11/28 23:49:59 shadchin Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -144,52 +144,9 @@ wsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
priv->buttons = DFLTBUTTONS;
buttons_from = X_DEFAULT;
}
- priv->negativeZ = priv->positiveZ = WS_NOMAP;
- s = xf86SetStrOption(pInfo->options, "ZAxisMapping", "4 5");
- if (s) {
- int b1, b2;
- if (sscanf(s, "%d %d", &b1, &b2) == 2 &&
- b1 > 0 && b1 <= NBUTTONS &&
- b2 > 0 && b2 <= NBUTTONS) {
- priv->negativeZ = 1 << (b1 - 1);
- priv->positiveZ = 1 << (b2 - 1);
- xf86IDrvMsg(pInfo, X_CONFIG,
- "ZAxisMapping: buttons %d and %d\n",
- b1, b2);
- if (max(b1, b2) > priv->buttons) {
- priv->buttons = max(b1, b2);
- buttons_from = X_CONFIG;
- }
- } else {
- xf86IDrvMsg(pInfo, X_WARNING,
- "invalid ZAxisMapping value: \"%s\"\n", s);
- }
- free(s);
- }
- priv->negativeW = priv->positiveW = WS_NOMAP;
- s = xf86SetStrOption(pInfo->options, "WAxisMapping", "6 7");
- if (s) {
- int b1, b2;
-
- if (sscanf(s, "%d %d", &b1, &b2) == 2 &&
- b1 > 0 && b1 <= NBUTTONS &&
- b2 > 0 && b2 <= NBUTTONS) {
- priv->negativeW = 1 << (b1 - 1);
- priv->positiveW = 1 << (b2 - 1);
- xf86IDrvMsg(pInfo, X_CONFIG,
- "WAxisMapping: buttons %d and %d\n",
- b1, b2);
- if (max(b1, b2) > priv->buttons) {
- priv->buttons = max(b1, b2);
- buttons_from = X_CONFIG;
- }
- } else {
- xf86IDrvMsg(pInfo, X_WARNING,
- "invalid WAxisMapping value: \"%s\"\n", s);
- }
- free(s);
- }
+ wsWheelHandleButtonMap(pInfo, &(priv->Z), "ZAxisMapping", "4 5");
+ wsWheelHandleButtonMap(pInfo, &(priv->W), "WAxisMapping", "6 7");
priv->screen_no = xf86SetIntOption(pInfo->options, "ScreenNo", 0);
xf86IDrvMsg(pInfo, X_CONFIG, "associated screen: %d\n",
@@ -280,6 +237,7 @@ wsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
wsClose(pInfo);
wsmbEmuPreInit(pInfo);
+ wsWheelEmuPreInit(pInfo);
return Success;
fail:
@@ -413,6 +371,7 @@ wsDeviceInit(DeviceIntPtr pWS)
if (priv->type == WSMOUSE_TYPE_TPANEL)
wsInitCalibProperty(pWS);
wsmbEmuInitProperty(pWS);
+ wsWheelEmuInitProperty(pWS);
return Success;
}
@@ -498,7 +457,6 @@ wsReadInput(InputInfoPtr pInfo)
int n, c;
struct wscons_event *event = eventList;
unsigned char *pBuf;
- int ax, ay;
priv = pInfo->private;
@@ -515,10 +473,9 @@ wsReadInput(InputInfoPtr pInfo)
n /= sizeof(struct wscons_event);
while( n-- ) {
int buttons = priv->lastButtons;
- int dx = 0, dy = 0, dz = 0, dw = 0;
+ int dx = 0, dy = 0, dz = 0, dw = 0, ax = 0, ay = 0;
int zbutton = 0, wbutton = 0;
- ax = 0; ay = 0;
switch (event->type) {
case WSCONS_EVENT_MOUSE_UP:
@@ -572,53 +529,35 @@ wsReadInput(InputInfoPtr pInfo)
++event;
continue;
} /* case */
+ ++event;
if (dx || dy) {
+ if (wsWheelEmuFilterMotion(pInfo, dx, dy))
+ continue;
+
/* relative motion event */
DBG(3, ErrorF("postMotionEvent dX %d dY %d\n",
- dx, dy));
- xf86PostMotionEvent(pInfo->dev, 0, 0, 2,
- dx, dy);
+ dx, dy));
+ xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
}
- if (dz && priv->negativeZ != WS_NOMAP
- && priv->positiveZ != WS_NOMAP) {
- buttons &= ~(priv->negativeZ | priv->positiveZ);
- if (dz < 0) {
- DBG(4, ErrorF("Z -> button %d\n",
- ffs(priv->negativeZ)));
- zbutton = priv->negativeZ;
- } else {
- DBG(4, ErrorF("Z -> button %d\n",
- ffs(priv->positiveZ)));
- zbutton = priv->positiveZ;
- }
- buttons |= zbutton;
- dz = 0;
+ if (dz && priv->Z.negative != WS_NOMAP
+ && priv->Z.positive != WS_NOMAP) {
+ zbutton = (dz < 0) ? priv->Z.negative :
+ priv->Z.positive;
+ DBG(4, ErrorF("Z -> button %d\n", zbutton));
+ wsButtonClicks(pInfo, zbutton, abs(dz));
}
- if (dw && priv->negativeW != WS_NOMAP
- && priv->positiveW != WS_NOMAP) {
- buttons &= ~(priv->negativeW | priv->positiveW);
- if (dw < 0) {
- DBG(4, ErrorF("W -> button %d\n",
- ffs(priv->negativeW)));
- wbutton = priv->negativeW;
- } else {
- DBG(4, ErrorF("W -> button %d\n",
- ffs(priv->positiveW)));
- wbutton = priv->positiveW;
- }
- buttons |= wbutton;
- dw = 0;
+ if (dw && priv->W.negative != WS_NOMAP
+ && priv->W.positive != WS_NOMAP) {
+ wbutton = (dw < 0) ? priv->W.negative :
+ priv->W.positive;
+ DBG(4, ErrorF("W -> button %d\n", wbutton));
+ wsButtonClicks(pInfo, wbutton, abs(dw));
}
if (priv->lastButtons != buttons) {
/* button event */
wsSendButtons(pInfo, buttons);
}
- if (zbutton != 0) {
- /* generate a button up event */
- buttons &= ~zbutton;
- wsSendButtons(pInfo, buttons);
- }
if (priv->swap_axes) {
int tmp;
@@ -627,16 +566,25 @@ wsReadInput(InputInfoPtr pInfo)
ay = tmp;
}
if (ax) {
+ dx = ax - priv->old_ax;
+ priv->old_ax = ax;
+ if (wsWheelEmuFilterMotion(pInfo, dx, 0))
+ continue;
+
/* absolute position event */
DBG(3, ErrorF("postMotionEvent X %d\n", ax));
xf86PostMotionEvent(pInfo->dev, 1, 0, 1, ax);
}
if (ay) {
+ dy = ay - priv->old_ay;
+ priv->old_ay = ay;
+ if (wsWheelEmuFilterMotion(pInfo, 0, dy))
+ continue;
+
/* absolute position event */
DBG(3, ErrorF("postMotionEvent y %d\n", ay));
xf86PostMotionEvent(pInfo->dev, 1, 1, 1, ay);
}
- ++event;
}
return;
} /* wsReadInput */
@@ -645,19 +593,22 @@ static void
wsSendButtons(InputInfoPtr pInfo, int buttons)
{
WSDevicePtr priv = (WSDevicePtr)pInfo->private;
- int change, button, mask;
+ int change, button, press;
change = buttons ^ priv->lastButtons;
while (change) {
button = ffs(change);
- mask = 1 << (button - 1);
- change &= ~mask;
- if (!wsmbEmuFilterEvent(pInfo, button, (buttons & mask) != 0)) {
- xf86PostButtonEvent(pInfo->dev, TRUE,
- button, (buttons & mask) != 0, 0, 0);
- DBG(3, ErrorF("post button event %d %d\n",
- button, (buttons & mask) != 0))
- }
+ press = buttons & (1 << (button - 1));
+ change &= ~(1 << (button - 1));
+
+ if (wsWheelEmuFilterButton(pInfo, button, press))
+ continue;
+
+ if (wsmbEmuFilterEvent(pInfo, button, press))
+ continue;
+
+ xf86PostButtonEvent(pInfo->dev, TRUE, button, press, 0, 0);
+ DBG(3, ErrorF("post button event %d %d\n", button, press));
}
priv->lastButtons = buttons;
} /* wsSendButtons */
@@ -818,3 +769,48 @@ wsSetCalibProperty(DeviceIntPtr device, Atom atom, XIPropertyValuePtr val,
}
return Success;
}
+
+void
+wsWheelHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis,
+ char* axis_name, char* default_value)
+{
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+ char *option_string;
+ int b1, b2;
+
+ pAxis->negative = pAxis->positive = WS_NOMAP;
+ pAxis->traveled_distance = 0;
+
+ option_string = xf86SetStrOption(pInfo->options, axis_name,
+ default_value);
+ if (option_string) {
+ if (sscanf(option_string, "%d %d", &b1, &b2) == 2 &&
+ b1 > 0 && b1 <= NBUTTONS &&
+ b2 > 0 && b2 <= NBUTTONS) {
+ xf86IDrvMsg(pInfo, X_CONFIG, "%s: buttons %d and %d\n",
+ axis_name, b1, b2);
+
+ pAxis->negative = b1;
+ pAxis->positive = b2;
+
+ if (max(b1, b2) > priv->buttons)
+ priv->buttons = max(b1, b2);
+ } else {
+ xf86IDrvMsg(pInfo, X_WARNING,
+ "Invalid %s value: \"%s\"\n",
+ axis_name, option_string);
+ }
+ free(option_string);
+ }
+}
+
+void
+wsButtonClicks(InputInfoPtr pInfo, int button, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ xf86PostButtonEvent(pInfo->dev, TRUE, button, 1, 0, 0);
+ xf86PostButtonEvent(pInfo->dev, TRUE, button, 0, 0, 0);
+ }
+}
diff --git a/driver/xf86-input-ws/src/ws.h b/driver/xf86-input-ws/src/ws.h
index 6aaee9061..512648c2a 100644
--- a/driver/xf86-input-ws/src/ws.h
+++ b/driver/xf86-input-ws/src/ws.h
@@ -33,20 +33,29 @@ extern int ws_debug_level;
#define WS_NOMAP 0
+/* axis specific data for wheel */
+typedef struct {
+ int negative;
+ int positive;
+ int traveled_distance;
+} WheelAxis, *WheelAxisPtr;
+
typedef struct WSDevice {
char *devName; /* device name */
int type; /* ws device type */
unsigned int buttons; /* # of buttons */
unsigned int lastButtons; /* last state of buttons */
+ int old_ax, old_ay;
int min_x, max_x, min_y, max_y; /* coord space */
int swap_axes;
int raw;
int inv_x, inv_y;
int screen_no;
pointer buffer;
- int negativeZ, positiveZ; /* mappings for Z axis */
- int negativeW, positiveW; /* mappings for W axis */
+ WheelAxis Z;
+ WheelAxis W;
struct wsmouse_calibcoords coords; /* mirror of the kernel values */
+
/* Middle mouse button emulation */
struct {
BOOL enabled;
@@ -56,8 +65,21 @@ typedef struct WSDevice {
Time expires; /* time of expiry */
Time timeout;
} emulateMB;
+
+ /* Mouse wheel emulation */
+ struct {
+ BOOL enabled;
+ int button;
+ int button_state;
+ int inertia;
+ WheelAxis X;
+ WheelAxis Y;
+ Time expires; /* time of expiry */
+ Time timeout;
+ } emulateWheel;
} WSDeviceRec, *WSDevicePtr;
+/* Middle mouse button emulation */
extern int wsmbEmuTimer(InputInfoPtr);
extern BOOL wsmbEmuFilterEvent(InputInfoPtr, int, BOOL);
extern void wsmbEmuWakeupHandler(pointer, int, pointer);
@@ -66,3 +88,12 @@ extern void wsmbEmuPreInit(InputInfoPtr);
extern void wsmbEmuOn(InputInfoPtr);
extern void wsmbEmuFinalize(InputInfoPtr);
extern void wsmbEmuInitProperty(DeviceIntPtr);
+
+/* Mouse wheel emulation */
+extern void wsWheelEmuPreInit(InputInfoPtr);
+extern BOOL wsWheelEmuFilterButton(InputInfoPtr, unsigned int, int);
+extern BOOL wsWheelEmuFilterMotion(InputInfoPtr, int, int);
+extern void wsWheelEmuInitProperty(DeviceIntPtr);
+
+extern void wsWheelHandleButtonMap(InputInfoPtr, WheelAxisPtr, char *, char *);
+extern void wsButtonClicks(InputInfoPtr, int, int);