Adding wheel emulation, ported from evdev(4)
ok matthieu@
This commit is contained in:
parent
2d087d2918
commit
86e4fbccae
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 $@ $<; \
|
||||
|
380
driver/xf86-input-ws/src/emuwheel.c
Normal file
380
driver/xf86-input-ws/src/emuwheel.c
Normal file
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user