mirror of
https://github.com/X11Libre/xf86-input-evdev.git
synced 2026-03-24 09:44:28 +00:00
Adding mouse wheel emulation code.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
committed by
Peter Hutterer
parent
c1f7f8c3d2
commit
a9d72b40fb
@@ -77,7 +77,49 @@ buttons can have the same mapping.
|
||||
For example, a left-handed mouse with deactivated scroll-wheel would use a
|
||||
mapping of "3 2 1 0 0". Invalid mappings are ignored and the default mapping
|
||||
is used. Buttons not specified in the user's mapping use the default mapping.
|
||||
|
||||
.TP 7
|
||||
.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 XAxisMapping ,
|
||||
and
|
||||
.B YAxisMapping
|
||||
options below. Default: off.
|
||||
.TP 7
|
||||
.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. Default: 4.
|
||||
.TP 7
|
||||
.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 7
|
||||
.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 7
|
||||
.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"
|
||||
.SH AUTHORS
|
||||
Kristian Høgsberg.
|
||||
.SH "SEE ALSO"
|
||||
|
||||
@@ -30,4 +30,6 @@
|
||||
|
||||
@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
|
||||
@DRIVER_NAME@.h \
|
||||
emuMB.c
|
||||
emuMB.c \
|
||||
emuWheel.c
|
||||
|
||||
|
||||
257
src/emuWheel.c
Normal file
257
src/emuWheel.c
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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 "evdev.h"
|
||||
|
||||
#define MSE_MAXBUTTONS 32
|
||||
#define WHEEL_NOT_CONFIGURED 0
|
||||
|
||||
/* Local Funciton Prototypes */
|
||||
static BOOL EvdevWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, char *axis_name);
|
||||
static void EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value);
|
||||
|
||||
/* Filter mouse button events */
|
||||
BOOL
|
||||
EvdevWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int value)
|
||||
{
|
||||
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
|
||||
|
||||
/* Has wheel emulation been configured to be enabled? */
|
||||
if (!pEvdev->emulateWheel.enabled)
|
||||
return FALSE;
|
||||
|
||||
/* Check for EmulateWheelButton */
|
||||
if (pEvdev->emulateWheel.button == button) {
|
||||
pEvdev->emulateWheel.button_state = value;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Don't care about this event */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Filter mouse wheel events */
|
||||
BOOL
|
||||
EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv)
|
||||
{
|
||||
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
|
||||
WheelAxisPtr pAxis = NULL;
|
||||
int value = pEv->value;
|
||||
|
||||
/* Has wheel emulation been configured to be enabled? */
|
||||
if (!pEvdev->emulateWheel.enabled)
|
||||
return FALSE;
|
||||
|
||||
/* Handle our motion events if the emuWheel button is pressed*/
|
||||
if (pEvdev->emulateWheel.button_state) {
|
||||
/* We don't want to intercept real mouse wheel events */
|
||||
switch(pEv->code) {
|
||||
case REL_X:
|
||||
pAxis = &(pEvdev->emulateWheel.X);
|
||||
break;
|
||||
|
||||
case REL_Y:
|
||||
pAxis = &(pEvdev->emulateWheel.Y);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we found REL_X or REL_Y, emulate a mouse wheel */
|
||||
if (pAxis)
|
||||
EvdevWheelEmuInertia(pInfo, pAxis, value);
|
||||
|
||||
/* Eat motion events while emulateWheel button pressed. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Simulate inertia for our emulated mouse wheel */
|
||||
static void
|
||||
EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value)
|
||||
{
|
||||
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
|
||||
int button;
|
||||
int inertia;
|
||||
|
||||
/* if this axis has not been configured, just eat the motion */
|
||||
if (!axis->up_button)
|
||||
return;
|
||||
|
||||
axis->traveled_distance += value;
|
||||
|
||||
if (axis->traveled_distance < 0) {
|
||||
button = axis->up_button;
|
||||
inertia = -pEvdev->emulateWheel.inertia;
|
||||
} else {
|
||||
button = axis->down_button;
|
||||
inertia = pEvdev->emulateWheel.inertia;
|
||||
}
|
||||
|
||||
/* Produce button press events for wheel motion */
|
||||
while(abs(axis->traveled_distance) > pEvdev->emulateWheel.inertia) {
|
||||
|
||||
axis->traveled_distance -= inertia;
|
||||
xf86PostButtonEvent(pInfo->dev, 0, button, 1, 0, 0);
|
||||
xf86PostButtonEvent(pInfo->dev, 0, button, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle button mapping here to avoid code duplication,
|
||||
returns true if a button mapping was found. */
|
||||
static BOOL
|
||||
EvdevWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, char* axis_name)
|
||||
{
|
||||
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
|
||||
char *option_string;
|
||||
|
||||
pAxis->up_button = WHEEL_NOT_CONFIGURED;
|
||||
|
||||
/* Check to see if there is configuration for this axis */
|
||||
option_string = xf86SetStrOption(pInfo->options, axis_name, NULL);
|
||||
if (option_string) {
|
||||
int up_button = 0;
|
||||
int down_button = 0;
|
||||
char *msg = NULL;
|
||||
|
||||
if ((sscanf(option_string, "%d %d", &up_button, &down_button) == 2) &&
|
||||
((up_button > 0) && (up_button <= MSE_MAXBUTTONS)) &&
|
||||
((down_button > 0) && (down_button <= MSE_MAXBUTTONS))) {
|
||||
|
||||
/* Use xstrdup to allocate a string for us */
|
||||
msg = xstrdup("buttons XX and YY");
|
||||
|
||||
if (msg)
|
||||
sprintf(msg, "buttons %d and %d", up_button, down_button);
|
||||
|
||||
pAxis->up_button = up_button;
|
||||
pAxis->down_button = down_button;
|
||||
|
||||
/* Update the number of buttons if needed */
|
||||
if (up_button > pEvdev->buttons) pEvdev->buttons = up_button;
|
||||
if (down_button > pEvdev->buttons) pEvdev->buttons = down_button;
|
||||
|
||||
} else {
|
||||
xf86Msg(X_WARNING, "%s: Invalid %s value:\"%s\"\n",
|
||||
pInfo->name, axis_name, option_string);
|
||||
|
||||
}
|
||||
|
||||
/* Clean up and log what happened */
|
||||
if (msg) {
|
||||
xf86Msg(X_CONFIG, "%s: %s: %s\n",pInfo->name, axis_name, msg);
|
||||
xfree(msg);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Setup the basic configuration options used by mouse wheel emulation */
|
||||
void
|
||||
EvdevWheelEmuPreInit(InputInfoPtr pInfo)
|
||||
{
|
||||
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
|
||||
pEvdev->emulateWheel.enabled = FALSE;
|
||||
|
||||
if (xf86SetBoolOption(pInfo->options, "EmulateWheel", FALSE)) {
|
||||
int wheelButton;
|
||||
int inertia;
|
||||
|
||||
pEvdev->emulateWheel.enabled = TRUE;
|
||||
wheelButton = xf86SetIntOption(pInfo->options,
|
||||
"EmulateWheelButton", 4);
|
||||
|
||||
if ((wheelButton < 0) || (wheelButton > MSE_MAXBUTTONS)) {
|
||||
xf86Msg(X_WARNING, "%s: Invalid EmulateWheelButton value: %d\n",
|
||||
pInfo->name, wheelButton);
|
||||
xf86Msg(X_WARNING, "%s: Wheel emulation disabled.\n", pInfo->name);
|
||||
|
||||
pEvdev->emulateWheel.enabled = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
pEvdev->emulateWheel.button = wheelButton;
|
||||
|
||||
inertia = xf86SetIntOption(pInfo->options, "EmulateWheelInertia", 10);
|
||||
|
||||
if (inertia <= 0) {
|
||||
xf86Msg(X_WARNING, "%s: Invalid EmulateWheelInertia value: %d\n",
|
||||
pInfo->name, inertia);
|
||||
xf86Msg(X_WARNING, "%s: Using built-in inertia value.\n",
|
||||
pInfo->name);
|
||||
|
||||
inertia = 10;
|
||||
}
|
||||
|
||||
pEvdev->emulateWheel.inertia = inertia;
|
||||
|
||||
/* Configure the Y axis or default it */
|
||||
if (!EvdevWheelEmuHandleButtonMap(pInfo, &(pEvdev->emulateWheel.Y),
|
||||
"YAxisMapping")) {
|
||||
/* Default the Y axis to sane values */
|
||||
pEvdev->emulateWheel.Y.up_button = 4;
|
||||
pEvdev->emulateWheel.Y.down_button = 5;
|
||||
|
||||
/* Simpler to check just the largest value in this case */
|
||||
/* XXX: we should post this to the server */
|
||||
if (5 > pEvdev->buttons)
|
||||
pEvdev->buttons = 5;
|
||||
|
||||
/* Display default Configuration */
|
||||
xf86Msg(X_CONFIG, "%s: YAxisMapping: buttons %d and %d\n",
|
||||
pInfo->name, pEvdev->emulateWheel.Y.up_button,
|
||||
pEvdev->emulateWheel.Y.down_button);
|
||||
}
|
||||
|
||||
|
||||
/* This axis should default to an unconfigured state as most people
|
||||
are not going to expect a Horizontal wheel. */
|
||||
EvdevWheelEmuHandleButtonMap(pInfo, &(pEvdev->emulateWheel.X),
|
||||
"XAxisMapping");
|
||||
|
||||
/* Used by the inertia code */
|
||||
pEvdev->emulateWheel.X.traveled_distance = 0;
|
||||
pEvdev->emulateWheel.Y.traveled_distance = 0;
|
||||
|
||||
xf86Msg(X_CONFIG, "%s: EmulateWheelButton: %d, EmulateWheelInertia: %d\n",
|
||||
pInfo->name, pEvdev->emulateWheel.button, inertia);
|
||||
}
|
||||
}
|
||||
|
||||
11
src/evdev.c
11
src/evdev.c
@@ -217,11 +217,16 @@ EvdevReadInput(InputInfoPtr pInfo)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Get the signed value, earlier kernels had this as unsigned */
|
||||
value = ev.value;
|
||||
|
||||
switch (ev.type) {
|
||||
case EV_REL:
|
||||
/* Handle mouse wheel emulation */
|
||||
if (EvdevWheelEmuFilterMotion(pInfo, &ev))
|
||||
break;
|
||||
|
||||
switch (ev.code) {
|
||||
case REL_X:
|
||||
dx += value;
|
||||
@@ -286,6 +291,9 @@ EvdevReadInput(InputInfoPtr pInfo)
|
||||
if (EvdevMBEmuFilterEvent(pInfo, button, value))
|
||||
break;
|
||||
|
||||
if (EvdevWheelEmuFilterButton(pInfo, button, value))
|
||||
break;
|
||||
|
||||
if (button)
|
||||
xf86PostButtonEvent(pInfo->dev, 0, button, value, 0, 0);
|
||||
else
|
||||
@@ -943,7 +951,10 @@ EvdevProc(DeviceIntPtr device, int what)
|
||||
{
|
||||
xf86AddEnabledDevice(pInfo);
|
||||
if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
|
||||
{
|
||||
EvdevMBEmuPreInit(pInfo);
|
||||
EvdevWheelEmuPreInit(pInfo);
|
||||
}
|
||||
device->public.on = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
20
src/evdev.h
20
src/evdev.h
@@ -40,6 +40,13 @@
|
||||
#include <X11/extensions/XKBstr.h>
|
||||
#endif
|
||||
|
||||
/* axis specific data for wheel emulation */
|
||||
typedef struct {
|
||||
int up_button;
|
||||
int down_button;
|
||||
int traveled_distance;
|
||||
} WheelAxis, *WheelAxisPtr;
|
||||
|
||||
typedef struct {
|
||||
int kernel24;
|
||||
int screen;
|
||||
@@ -68,6 +75,14 @@ typedef struct {
|
||||
Time expires; /* time of expiry */
|
||||
Time timeout;
|
||||
} emulateMB;
|
||||
struct {
|
||||
BOOL enabled;
|
||||
int button;
|
||||
int button_state;
|
||||
int inertia;
|
||||
WheelAxis X;
|
||||
WheelAxis Y;
|
||||
} emulateWheel;
|
||||
|
||||
unsigned char btnmap[32]; /* config-file specified button mapping */
|
||||
} EvdevRec, *EvdevPtr;
|
||||
@@ -89,4 +104,9 @@ Atom EvdevMBEmuInitPropertyTimeout(DeviceIntPtr, char*);
|
||||
BOOL EvdevMBEmuSetProperty(DeviceIntPtr, Atom, XIPropertyValuePtr);
|
||||
#endif
|
||||
|
||||
/* Mouse Wheel emulation */
|
||||
void EvdevWheelEmuPreInit(InputInfoPtr pInfo);
|
||||
BOOL EvdevWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int value);
|
||||
BOOL EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user