Compare commits

...

31 Commits

Author SHA1 Message Date
Peter Hutterer
ed1382866c evdev 2.0.4 2008-08-14 23:17:16 +09:30
Adam Jackson
8fe38b2287 Print a warning if a keycode exceeds the range accepted by the server.
Keycodes over 255 are silently ignored in the server. The least we can do is
put a warning in the logs.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit c1f7f8c3d2)
2008-08-07 10:40:14 +09:30
Julien Cristau
ef607b6cce Actually close the fd on DEVICE_CLOSE (bug#16948)
Fixes file descriptor leak.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit d9097df01b)
2008-08-04 09:25:27 +09:30
Julien Cristau
906a5d6add Print the device name when we get a read error
(cherry picked from commit 5c074af5a9)
2008-08-04 09:25:14 +09:30
Peter Hutterer
5152d616ca evdev 2.0.3 2008-08-01 17:29:24 +09:30
Michel Dänzer
2e9a71df5f xf86-input-evdev: Fix EVIOCGBIT ioctl usage on big endian platforms.
With this fix, on my PowerBook HAL hotplugging correctly detects my USB mouse,
and no longer thinks keyboards have random numbers of mouse buttons. :)

The LONG_BITS and NBITS macro definitions are stolen from xf86-input-synaptics.

Signed-off-by: Michel Dänzer <michel@tungstengraphics.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
[cherry-picked from master and fixed the trivial conflict -- jcristau]
2008-07-30 10:45:31 +02:00
Julien Cristau
49de32e70f Fill up the version info
Report correct versions instead of
"compiled for 0.0.0, module version = 1.0.0"
(cherry picked from commit 2b7edaa4ab)
2008-07-20 11:45:30 +02:00
Peter Hutterer
f135e07462 evdev 2.0.2 2008-07-14 13:34:36 +09:30
Peter Hutterer
e926356eb0 Don't enable the device if the grab failed with ENODEV.
After suspend/resume, sometimes the device doesn't come back up on the same
node. Since we do not call PreInit for the device (which would detect this
situation), we continue to try to read a nonexisting file, spamming the log
file with "Read Error".
(cherry picked from commit bf0d81011e)
2008-07-14 13:17:39 +09:30
Peter Hutterer
bd56ab3d72 Add .gitignore file.
(cherry picked from commit ef4bb69c1a)
2008-07-10 19:34:05 +09:30
Peter Hutterer
2b30413598 Remove static ChangeLog, autogenerate as part of make dist.
Hook taken from xserver's Makefile.am
(cherry picked from commit ec23c6b2f5)
2008-07-10 19:29:57 +09:30
Ander Conselvan de Oliveira
52fc8ee846 Mice with a lot of buttons (e.g. Logitech MX1000) generate button events greater than BTN_TASK.
Signed-off-by: Peter Hutterer <peter@cs.unisa.edu.au>
(cherry picked from commit 0830676a0c)
2008-07-10 19:29:45 +09:30
Peter Hutterer
b125b834f4 evdev 2.0.1 2008-06-22 17:52:58 +09:30
Peter Hutterer
05b20db8db No need to finalize MB emulation after EvdevProbe anymore.
Follow-up to 76800bfa75.
(cherry picked from commit 5a0ea39b79)
2008-06-22 16:26:10 +09:30
Simon Munton
43768d59da Close file descriptor if EvdevProbe fails.
Signed-off-by: Peter Hutterer <peter@cs.unisa.edu.au>
(cherry picked from commit 373e13ae35)
2008-06-22 16:25:48 +09:30
Keith Packard
9c524f6963 Enable middle button emulation at DEVICE_ON instead of DEVICE_INIT.
This ensures that the middle button emulation is re-enabled after VT switch,
otherwise the block handler that deals with the timeouts would not get
re-registered.

Signed-off-by: Keith Packard <keithp@keithp.com>
(cherry picked from commit 76800bfa75)
2008-06-22 16:24:57 +09:30
Peter Hutterer
04003a98a9 evdev 2.0.0 2008-06-17 14:01:49 +09:30
Peter Hutterer
0443fb430f Shut up compiler warning "implicit declaration of function 'xf86Msg'" 2008-06-17 13:59:15 +09:30
Peter Hutterer
998f52010f Finalize MB emulation if EvdevProbe fails.
This avoids segfaults when HAL is restarted behind our backs. Also, only init
MB emulation when the device actually has a button.
2008-06-12 11:24:04 +09:30
Peter Hutterer
de07c04f5c evdev 1.99.4
1.99.3 had a nasty bug, so here's a quick update.
2008-06-11 11:55:12 +09:30
Peter Hutterer
01355b9d4b If Emulate3Buttons is specified in the config, don't auto-deactivate it.
Default setting is still "on" until middle button is pressed.  If the options
is however explicitly stated in the config file, it takes the value from the
config file, no matter if a middle button is present.
2008-06-11 11:23:53 +09:30
Peter Hutterer
9591dc1f6c Remove wakeup handlers when device is closed.
Less SIGABRTs are less exciting, but sometimes boredom is what we want.
2008-06-11 11:23:38 +09:30
Adam Jackson
08ba40b253 evdev 1.99.3 2008-06-10 17:35:33 -04:00
Peter Hutterer
39dc453691 Disable middle mouse button emulation when a real middle MB event is detected.
Devices may report middle mouse buttons even if they don't have one (PS/2
devices just don't know any better), so we can't be sure until we see the
event.
2008-06-10 22:48:01 +09:30
Peter Hutterer
e8887435ac Enable middle-mouse button emulation.
Ported from xf86-input-mouse, with a few cleanups.
2008-06-10 22:46:20 +09:30
Peter Hutterer
b0f6987ee6 Plug a memory leak, we allocated pEvdev twice, dropping the first memory area. 2008-06-10 22:43:37 +09:30
Sven Wegener
fec73e1418 evdev: Port b4a5a204 "Fix pointer crossing screen bug." to current master branch
The commit b4a5a204 fixed an issue, where we can't move the pointer to
other screens and this happens in current master branch again. This commit
ports the old commit to the current master branch.

Signed-off-by: Sven Wegener <swegener@gentoo.org>
Signed-off-by: Peter Hutterer <peter@cs.unisa.edu.au>
2008-06-08 21:44:57 +09:30
Peter Hutterer
da112737eb Check for XINPUT ABI < 3 (corrected version)
Thanks to Sven Wegener for pointing out the incorrect previous version.
2008-06-08 00:15:26 +09:30
Peter Hutterer
d40125ea8c Revert "Check for XINPUT ABI, parameters of InitValuatorClassRec have changed."
GetMotionEvents() doesn't exist, led to compile errors with servers pre-MPX
merge. Thanks to Sven Wegener for pointing this out.

This reverts commit 42422d8f69.
2008-06-08 00:13:35 +09:30
Peter Hutterer
42422d8f69 Check for XINPUT ABI, parameters of InitValuatorClassRec have changed. 2008-05-26 19:29:32 +09:30
Peter Hutterer
15e0091f0b Fail if the device cannot be grabbed during the probe.
If the grab fails, this is most likely a sign that the device has been grabbed
already (probably by a device specified in xorg.conf). So let's not add the
device to the server's input device list, since it won't generate events
anyway.

Exception: keyboards and kernel 2.4 are not affected.
2008-05-23 09:52:46 +09:30
9 changed files with 535 additions and 99 deletions

26
.gitignore vendored Normal file
View File

@@ -0,0 +1,26 @@
*.patch
ChangeLog
Makefile
Makefile.in
aclocal.m4
autom4te.cache
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
depcomp
install-sh
libtool
ltmain.sh
man/evdev.4
missing
.deps
.libs
*.lo
*.la
stamp-h1
*.bz2
*.gz

View File

@@ -1,47 +0,0 @@
2006-01-09 David Nusinow,,, <set EMAIL_ADDRESS environment variable>
* man/Makefile.am:
* man/evdev.man:
Bugzilla #968 <https://bugs.freedesktop.org/show_bug.cgi?id=968>
Patch #4301 <https://bugs.freedesktop.org/attachment.cgi?id=4301>
Add evdev manpage
2005-12-20 Kevin E. Martin <kem-at-freedesktop-dot-org>
* configure.ac:
Update package version for X11R7 release.
2005-12-14 Kevin E. Martin <kem-at-freedesktop-dot-org>
* configure.ac:
Update package version number for final X11R7 release candidate.
2005-12-06 Kevin E. Martin <kem-at-freedesktop-dot-org>
* man/Makefile.am:
Change *man_SOURCES ==> *man_PRE to fix autotools warnings.
2005-12-03 Kevin E. Martin <kem-at-freedesktop-dot-org>
* configure.ac:
Update package version number for X11R7 RC3 release.
2005-12-01 Kevin E. Martin <kem-at-freedesktop-dot-org>
* configure.ac:
Remove extraneous AC_MSG_RESULT.
2005-11-29 Adam Jackson <ajax@freedesktop.org>
* configure.ac:
Only build dlloader modules by default.
2005-11-09 Kevin E. Martin <kem-at-freedesktop-dot-org>
* configure.ac:
Update package version number for X11R7 RC2 release.
2005-11-01 Kevin E. Martin <kem-at-freedesktop-dot-org>
* configure.ac:
Update pkgcheck dependencies to work with separate build roots.

View File

@@ -20,3 +20,15 @@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
SUBDIRS = src man SUBDIRS = src man
EXTRA_DIST = ChangeLog autogen.sh
MAINTAINERCLEANFILES=ChangeLog
.PHONY: ChangeLog
ChangeLog:
(GIT_DIR=$(top_srcdir)/.git git-log > .changelog.tmp && mv .changelog.tmp ChangeLog; rm -f .changelog.tmp) || \
(touch ChangeLog; echo 'git directory not found: installing possibly empty changelog.' >&2)
dist-hook: ChangeLog

View File

@@ -22,7 +22,7 @@
AC_PREREQ(2.57) AC_PREREQ(2.57)
AC_INIT([xf86-input-evdev], AC_INIT([xf86-input-evdev],
1.99.2, 2.0.4,
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
xf86-input-evdev) xf86-input-evdev)

View File

@@ -10,6 +10,8 @@ evdev \- Generic Linux input driver
.B " Driver \*qevdev\*q" .B " Driver \*qevdev\*q"
.BI " Option \*qDevice\*q \*q" devpath \*q .BI " Option \*qDevice\*q \*q" devpath \*q
.BI " Option \*qPath\*q \*q" path \*q .BI " Option \*qPath\*q \*q" path \*q
.BI " Option \*qEmulate3Buttons\*q \*q" True \*q
.BI " Option \*qEmulate3Timeout\*q \*q" 50 \*q
\ \ ... \ \ ...
.B EndSection .B EndSection
.fi .fi
@@ -54,6 +56,17 @@ generally be of the form \*q/dev/input/by-path/xyz\*q, where xyz includes the
name of the device. The mapping from device node to hardware is name of the device. The mapping from device node to hardware is
system-dependent. This option has precedence over the \*qDevice\*q option but system-dependent. This option has precedence over the \*qDevice\*q option but
one of \*qPath\*q or \*qDevice\*q must be given. one of \*qPath\*q or \*qDevice\*q must be given.
.TP 7
.BI "Option \*qEmulate3Buttons\*q \*q" boolean \*q
Enable/disable the emulation of the third (middle) mouse button for mice
which only have two physical buttons. The third button is emulated by
pressing both buttons simultaneously. Default: on, until a middle mouse
button event is registered.
.TP 7
.BI "Option \*qEmulate3Timeout\*q \*q" integer \*q
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.
.SH AUTHORS .SH AUTHORS
Kristian Høgsberg. Kristian Høgsberg.
.SH "SEE ALSO" .SH "SEE ALSO"

View File

@@ -28,4 +28,6 @@
@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version @DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
@DRIVER_NAME@_drv_ladir = @inputdir@ @DRIVER_NAME@_drv_ladir = @inputdir@
@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c @DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
@DRIVER_NAME@.h \
emuMB.c

334
src/emuMB.c Normal file
View File

@@ -0,0 +1,334 @@
/*
* 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 University of South Australia
*
* 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 Red Hat
* not be used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission. Red
* Hat makes 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.
*
*/
/* Middle mouse button emulation code. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <xf86.h>
#include "evdev.h"
enum {
MBEMU_DISABLED = 0,
MBEMU_ENABLED,
MBEMU_AUTO
};
/*
* Lets create a simple finite-state machine for 3 button emulation:
*
* We track buttons 1 and 3 (left and right). There are 11 states:
* 0 ground - initial state
* 1 delayed left - left pressed, waiting for right
* 2 delayed right - right pressed, waiting for left
* 3 pressed middle - right and left pressed, emulated middle sent
* 4 pressed left - left pressed and sent
* 5 pressed right - right pressed and sent
* 6 released left - left released after emulated middle
* 7 released right - right released after emulated middle
* 8 repressed left - left pressed after released left
* 9 repressed right - right pressed after released right
* 10 pressed both - both pressed, not emulating middle
*
* At each state, we need handlers for the following events
* 0: no buttons down
* 1: left button down
* 2: right button down
* 3: both buttons down
* 4: emulate3Timeout passed without a button change
* Note that button events are not deltas, they are the set of buttons being
* pressed now. It's possible (ie, mouse hardware does it) to go from (eg)
* left down to right down without anything in between, so all cases must be
* handled.
*
* a handler consists of three values:
* 0: action1
* 1: action2
* 2: new emulation state
*
* action > 0: ButtonPress
* action = 0: nothing
* action < 0: ButtonRelease
*
* The comment preceeding each section is the current emulation state.
* The comments to the right are of the form
* <button state> (<events>) -> <new emulation state>
* which should be read as
* If the buttons are in <button state>, generate <events> then go to
* <new emulation state>.
*/
static signed char stateTab[11][5][3] = {
/* 0 ground */
{
{ 0, 0, 0 }, /* nothing -> ground (no change) */
{ 0, 0, 1 }, /* left -> delayed left */
{ 0, 0, 2 }, /* right -> delayed right */
{ 2, 0, 3 }, /* left & right (middle press) -> pressed middle */
{ 0, 0, -1 } /* timeout N/A */
},
/* 1 delayed left */
{
{ 1, -1, 0 }, /* nothing (left event) -> ground */
{ 0, 0, 1 }, /* left -> delayed left (no change) */
{ 1, -1, 2 }, /* right (left event) -> delayed right */
{ 2, 0, 3 }, /* left & right (middle press) -> pressed middle */
{ 1, 0, 4 }, /* timeout (left press) -> pressed left */
},
/* 2 delayed right */
{
{ 3, -3, 0 }, /* nothing (right event) -> ground */
{ 3, -3, 1 }, /* left (right event) -> delayed left (no change) */
{ 0, 0, 2 }, /* right -> delayed right (no change) */
{ 2, 0, 3 }, /* left & right (middle press) -> pressed middle */
{ 3, 0, 5 }, /* timeout (right press) -> pressed right */
},
/* 3 pressed middle */
{
{ -2, 0, 0 }, /* nothing (middle release) -> ground */
{ 0, 0, 7 }, /* left -> released right */
{ 0, 0, 6 }, /* right -> released left */
{ 0, 0, 3 }, /* left & right -> pressed middle (no change) */
{ 0, 0, -1 }, /* timeout N/A */
},
/* 4 pressed left */
{
{ -1, 0, 0 }, /* nothing (left release) -> ground */
{ 0, 0, 4 }, /* left -> pressed left (no change) */
{ -1, 0, 2 }, /* right (left release) -> delayed right */
{ 3, 0, 10 }, /* left & right (right press) -> pressed both */
{ 0, 0, -1 }, /* timeout N/A */
},
/* 5 pressed right */
{
{ -3, 0, 0 }, /* nothing (right release) -> ground */
{ -3, 0, 1 }, /* left (right release) -> delayed left */
{ 0, 0, 5 }, /* right -> pressed right (no change) */
{ 1, 0, 10 }, /* left & right (left press) -> pressed both */
{ 0, 0, -1 }, /* timeout N/A */
},
/* 6 released left */
{
{ -2, 0, 0 }, /* nothing (middle release) -> ground */
{ -2, 0, 1 }, /* left (middle release) -> delayed left */
{ 0, 0, 6 }, /* right -> released left (no change) */
{ 1, 0, 8 }, /* left & right (left press) -> repressed left */
{ 0, 0, -1 }, /* timeout N/A */
},
/* 7 released right */
{
{ -2, 0, 0 }, /* nothing (middle release) -> ground */
{ 0, 0, 7 }, /* left -> released right (no change) */
{ -2, 0, 2 }, /* right (middle release) -> delayed right */
{ 3, 0, 9 }, /* left & right (right press) -> repressed right */
{ 0, 0, -1 }, /* timeout N/A */
},
/* 8 repressed left */
{
{ -2, -1, 0 }, /* nothing (middle release, left release) -> ground */
{ -2, 0, 4 }, /* left (middle release) -> pressed left */
{ -1, 0, 6 }, /* right (left release) -> released left */
{ 0, 0, 8 }, /* left & right -> repressed left (no change) */
{ 0, 0, -1 }, /* timeout N/A */
},
/* 9 repressed right */
{
{ -2, -3, 0 }, /* nothing (middle release, right release) -> ground */
{ -3, 0, 7 }, /* left (right release) -> released right */
{ -2, 0, 5 }, /* right (middle release) -> pressed right */
{ 0, 0, 9 }, /* left & right -> repressed right (no change) */
{ 0, 0, -1 }, /* timeout N/A */
},
/* 10 pressed both */
{
{ -1, -3, 0 }, /* nothing (left release, right release) -> ground */
{ -3, 0, 4 }, /* left (right release) -> pressed left */
{ -1, 0, 5 }, /* right (left release) -> pressed right */
{ 0, 0, 10 }, /* left & right -> pressed both (no change) */
{ 0, 0, -1 }, /* timeout N/A */
},
};
int
EvdevMBEmuTimer(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = pInfo->private;
int sigstate;
int id;
sigstate = xf86BlockSIGIO ();
pEvdev->emulateMB.pending = FALSE;
if ((id = stateTab[pEvdev->emulateMB.state][4][0]) != 0) {
xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
pEvdev->emulateMB.state =
stateTab[pEvdev->emulateMB.state][4][2];
} else {
ErrorF("Got unexpected buttonTimer in state %d\n",
pEvdev->emulateMB.state);
}
xf86UnblockSIGIO (sigstate);
return 0;
}
/**
* Emulate a middle button on button press.
*
* @param code Evdev event code (BTN_LEFT or BTN_RIGHT)
* @param press TRUE if press, FALSE if release.
*
* @return TRUE if event was swallowed by middle mouse button emulation, FALSE
* otherwise.
*/
BOOL
EvdevMBEmuFilterEvent(InputInfoPtr pInfo, int code, BOOL press)
{
EvdevPtr pEvdev = pInfo->private;
int id;
int *btstate;
int ret = FALSE;
if (!pEvdev->emulateMB.enabled)
return ret;
/* don't care about other buttons */
if (code != BTN_LEFT && code != BTN_RIGHT)
return ret;
btstate = &pEvdev->emulateMB.buttonstate;
if (press)
*btstate |= (code == BTN_LEFT) ? 0x1 : 0x2;
else
*btstate &= (code == BTN_LEFT) ? ~0x1 : ~0x2;
if ((id = stateTab[pEvdev->emulateMB.state][*btstate][0]) != 0)
{
xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
ret = TRUE;
}
if ((id = stateTab[pEvdev->emulateMB.state][*btstate][1]) != 0)
{
xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
ret = TRUE;
}
pEvdev->emulateMB.state =
stateTab[pEvdev->emulateMB.state][*btstate][2];
if (stateTab[pEvdev->emulateMB.state][4][0] != 0) {
pEvdev->emulateMB.expires = GetTimeInMillis () + pEvdev->emulateMB.timeout;
pEvdev->emulateMB.pending = TRUE;
ret = TRUE;
} else {
pEvdev->emulateMB.pending = FALSE;
}
return ret;
}
void EvdevMBEmuWakeupHandler(pointer data,
int i,
pointer LastSelectMask)
{
InputInfoPtr pInfo = (InputInfoPtr)data;
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
int ms;
if (pEvdev->emulateMB.pending)
{
ms = pEvdev->emulateMB.expires - GetTimeInMillis();
if (ms <= 0)
EvdevMBEmuTimer(pInfo);
}
}
void EvdevMBEmuBlockHandler(pointer data,
struct timeval **waitTime,
pointer LastSelectMask)
{
InputInfoPtr pInfo = (InputInfoPtr) data;
EvdevPtr pEvdev= (EvdevPtr) pInfo->private;
int ms;
if (pEvdev->emulateMB.pending)
{
ms = pEvdev->emulateMB.expires - GetTimeInMillis ();
if (ms <= 0)
ms = 0;
AdjustWaitForDelay (waitTime, ms);
}
}
void
EvdevMBEmuPreInit(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
pEvdev->emulateMB.enabled = MBEMU_AUTO;
if (xf86FindOption(pInfo->options, "Emulate3Buttons"))
{
pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
"Emulate3Buttons",
MBEMU_ENABLED);
xf86Msg(X_INFO, "%s: Forcing middle mouse button emulation.\n",
pInfo->name);
}
pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options,
"Emulate3Timeout", 50);
RegisterBlockAndWakeupHandlers (EvdevMBEmuBlockHandler,
EvdevMBEmuWakeupHandler,
(pointer)pInfo);
}
void
EvdevMBEmuFinalize(InputInfoPtr pInfo)
{
RemoveBlockAndWakeupHandlers (EvdevMBEmuBlockHandler,
EvdevMBEmuWakeupHandler,
(pointer)pInfo);
}
/* Enable/disable middle mouse button emulation. */
void
EvdevMBEmuEnable(InputInfoPtr pInfo, BOOL enable)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
if (pEvdev->emulateMB.enabled == MBEMU_AUTO)
pEvdev->emulateMB.enabled = enable;
}

View File

@@ -33,7 +33,6 @@
#include <X11/XF86keysym.h> #include <X11/XF86keysym.h>
#include <X11/extensions/XIproto.h> #include <X11/extensions/XIproto.h>
#include <linux/input.h>
#include <unistd.h> #include <unistd.h>
#include <misc.h> #include <misc.h>
@@ -43,11 +42,9 @@
#include <xf86Xinput.h> #include <xf86Xinput.h>
#include <exevents.h> #include <exevents.h>
#include <mipointer.h> #include <mipointer.h>
#include <xorgVersion.h>
#if defined(XKB) #include "evdev.h"
/* XXX VERY WRONG. this is a client side header. */
#include <X11/extensions/XKBstr.h>
#endif
#include <xf86Module.h> #include <xf86Module.h>
@@ -91,25 +88,6 @@
#define MODEFLAG 8 #define MODEFLAG 8
#define COMPOSEFLAG 16 #define COMPOSEFLAG 16
typedef struct {
int kernel24;
int screen;
int min_x, min_y, max_x, max_y;
int abs_x, abs_y, old_x, old_y;
int flags;
int tool;
/* XKB stuff has to be per-device rather than per-driver */
int noXkb;
#ifdef XKB
char *xkb_rules;
char *xkb_model;
char *xkb_layout;
char *xkb_variant;
char *xkb_options;
XkbComponentNamesRec xkbnames;
#endif
} EvdevRec, *EvdevPtr;
static const char *evdevDefaults[] = { static const char *evdevDefaults[] = {
"XkbRules", "base", "XkbRules", "base",
@@ -153,6 +131,9 @@ PostButtonClicks(InputInfoPtr pInfo, int button, int count)
static void static void
PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
{ {
int code = ev->code + MIN_KEYCODE;
static char warned[KEY_MAX];
/* filter repeat events for chording keys */ /* filter repeat events for chording keys */
if (value == 2 && if (value == 2 &&
(ev->code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL || (ev->code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL ||
@@ -163,7 +144,14 @@ PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
ev->code == KEY_SCROLLLOCK)) /* XXX windows keys? */ ev->code == KEY_SCROLLLOCK)) /* XXX windows keys? */
return; return;
xf86PostKeyboardEvent(pInfo->dev, ev->code + MIN_KEYCODE, value); if (code > 255 && ev->code < KEY_MAX) {
if (!warned[ev->code])
xf86Msg(X_WARNING, "%s: unable to handle keycode %d\n",
pInfo->name, ev->code);
warned[ev->code] = 1;
}
xf86PostKeyboardEvent(pInfo->dev, code, value);
} }
static void static void
@@ -184,7 +172,7 @@ EvdevReadInput(InputInfoPtr pInfo)
if (len != sizeof ev) { if (len != sizeof ev) {
/* The kernel promises that we always only read a complete /* The kernel promises that we always only read a complete
* event, so len != sizeof ev is an error. */ * event, so len != sizeof ev is an error. */
xf86Msg(X_ERROR, "Read error: %s\n", strerror(errno)); xf86Msg(X_ERROR, "%s: Read error: %s\n", pInfo->name, strerror(errno));
break; break;
} }
@@ -241,12 +229,15 @@ EvdevReadInput(InputInfoPtr pInfo)
switch (ev.code) { switch (ev.code) {
/* swap here, pretend we're an X-conformant device. */ /* swap here, pretend we're an X-conformant device. */
case BTN_LEFT: case BTN_LEFT:
xf86PostButtonEvent(pInfo->dev, 0, 1, value, 0, 0); if (!EvdevMBEmuFilterEvent(pInfo, ev.code, value))
xf86PostButtonEvent(pInfo->dev, 0, 1, value, 0, 0);
break; break;
case BTN_RIGHT: case BTN_RIGHT:
xf86PostButtonEvent(pInfo->dev, 0, 3, value, 0, 0); if (!EvdevMBEmuFilterEvent(pInfo, ev.code, value))
xf86PostButtonEvent(pInfo->dev, 0, 3, value, 0, 0);
break; break;
case BTN_MIDDLE: case BTN_MIDDLE:
EvdevMBEmuEnable(pInfo, FALSE);
xf86PostButtonEvent(pInfo->dev, 0, 2, value, 0, 0); xf86PostButtonEvent(pInfo->dev, 0, 2, value, 0, 0);
break; break;
@@ -272,8 +263,15 @@ EvdevReadInput(InputInfoPtr pInfo)
break; break;
default: default:
if (ev.code > BTN_TASK && ev.code < KEY_OK) if (ev.code > BTN_TASK && ev.code < KEY_OK) {
/* Some fancy mice with a lot of buttons generate
* button events between BTN_TASK and BTN_JOYSTICK */
if (ev.code < BTN_JOYSTICK)
xf86PostButtonEvent(pInfo->dev, 0,
ev.code - BTN_LEFT + 5,
value, 0, 0);
break; break;
}
PostKbdEvent(pInfo, &ev, value); PostKbdEvent(pInfo, &ev, value);
break; break;
@@ -318,7 +316,9 @@ EvdevReadInput(InputInfoPtr pInfo)
} }
} }
#define TestBit(bit, array) (array[(bit) / 8] & (1 << ((bit) % 8))) #define LONG_BITS (sizeof(long) * 8)
#define NBITS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
#define TestBit(bit, array) (array[(bit) / LONG_BITS]) & (1 << ((bit) % LONG_BITS))
static void static void
EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl) EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
@@ -726,7 +726,10 @@ EvdevAddAbsClass(DeviceIntPtr device)
pEvdev->min_y = absinfo_y.minimum; pEvdev->min_y = absinfo_y.minimum;
pEvdev->max_y = absinfo_y.maximum; pEvdev->max_y = absinfo_y.maximum;
if (!InitValuatorClassDeviceStruct(device, 2, GetMotionHistory, if (!InitValuatorClassDeviceStruct(device, 2,
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
GetMotionHistory,
#endif
GetMotionHistorySize(), Absolute)) GetMotionHistorySize(), Absolute))
return !Success; return !Success;
@@ -756,16 +759,19 @@ EvdevAddRelClass(DeviceIntPtr device)
pInfo = device->public.devicePrivate; pInfo = device->public.devicePrivate;
if (!InitValuatorClassDeviceStruct(device, 2, GetMotionHistory, if (!InitValuatorClassDeviceStruct(device, 2,
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
GetMotionHistory,
#endif
GetMotionHistorySize(), Relative)) GetMotionHistorySize(), Relative))
return !Success; return !Success;
/* X valuator */ /* X valuator */
xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1); xf86InitValuatorAxisStruct(device, 0, -1, -1, 1, 0, 1);
xf86InitValuatorDefaults(device, 0); xf86InitValuatorDefaults(device, 0);
/* Y valuator */ /* Y valuator */
xf86InitValuatorAxisStruct(device, 1, 0, -1, 1, 0, 1); xf86InitValuatorAxisStruct(device, 1, -1, -1, 1, 0, 1);
xf86InitValuatorDefaults(device, 1); xf86InitValuatorDefaults(device, 1);
xf86MotionHistoryAllocate(pInfo); xf86MotionHistoryAllocate(pInfo);
@@ -848,20 +854,27 @@ EvdevProc(DeviceIntPtr device, int what)
if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)1))
xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name, xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
strerror(errno)); strerror(errno));
xf86AddEnabledDevice(pInfo); if (errno != ENODEV)
device->public.on = TRUE; {
xf86AddEnabledDevice(pInfo);
if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
EvdevMBEmuPreInit(pInfo);
device->public.on = TRUE;
}
break; break;
case DEVICE_OFF: case DEVICE_OFF:
if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)0)) if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name, xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
strerror(errno)); strerror(errno));
xf86RemoveEnabledDevice(pInfo); xf86RemoveEnabledDevice(pInfo);
EvdevMBEmuFinalize(pInfo);
device->public.on = FALSE; device->public.on = FALSE;
break; break;
case DEVICE_CLOSE: case DEVICE_CLOSE:
xf86Msg(X_INFO, "%s: Close\n", pInfo->name); xf86Msg(X_INFO, "%s: Close\n", pInfo->name);
close(pInfo->fd);
break; break;
} }
@@ -895,15 +908,20 @@ EvdevConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
static int static int
EvdevProbe(InputInfoPtr pInfo) EvdevProbe(InputInfoPtr pInfo)
{ {
char key_bitmask[(KEY_MAX + 7) / 8]; long key_bitmask[NBITS(KEY_MAX)];
char rel_bitmask[(REL_MAX + 7) / 8]; long rel_bitmask[NBITS(REL_MAX)];
char abs_bitmask[(ABS_MAX + 7) / 8]; long abs_bitmask[NBITS(ABS_MAX)];
int i, has_axes, has_buttons, has_keys; int i, has_axes, has_buttons, has_keys;
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1) && errno == EINVAL) { if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
/* keyboards are unsafe in 2.4 */ if (errno == EINVAL) {
pEvdev->kernel24 = 1; /* keyboards are unsafe in 2.4 */
pEvdev->kernel24 = 1;
} else {
xf86Msg(X_ERROR, "Grab failed. Device already configured?\n");
return 1;
}
} else { } else {
ioctl(pInfo->fd, EVIOCGRAB, (void *)0); ioctl(pInfo->fd, EVIOCGRAB, (void *)0);
} }
@@ -1018,10 +1036,6 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
pInfo->always_core_feedback = 0; pInfo->always_core_feedback = 0;
pInfo->conf_idev = dev; pInfo->conf_idev = dev;
if (!(pEvdev = xcalloc(sizeof(*pEvdev), 1)))
return pInfo;
pInfo->private = pEvdev;
if (!(pEvdev = xcalloc(sizeof(EvdevRec), 1))) if (!(pEvdev = xcalloc(sizeof(EvdevRec), 1)))
return pInfo; return pInfo;
@@ -1045,7 +1059,7 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
xf86DeleteInput(pInfo, 0); xf86DeleteInput(pInfo, 0);
return NULL; return NULL;
} }
xf86Msg(deviceFrom, "%s: Device: \"%s\"\n", pInfo->name, device); xf86Msg(deviceFrom, "%s: Device: \"%s\"\n", pInfo->name, device);
do { do {
pInfo->fd = open(device, O_RDWR, 0); pInfo->fd = open(device, O_RDWR, 0);
@@ -1062,6 +1076,7 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
/* parse the XKB options during kbd setup */ /* parse the XKB options during kbd setup */
if (EvdevProbe(pInfo)) { if (EvdevProbe(pInfo)) {
close(pInfo->fd);
xf86DeleteInput(pInfo, 0); xf86DeleteInput(pInfo, 0);
return NULL; return NULL;
} }
@@ -1100,8 +1115,8 @@ static XF86ModuleVersionInfo EvdevVersionRec =
MODULEVENDORSTRING, MODULEVENDORSTRING,
MODINFOSTRING1, MODINFOSTRING1,
MODINFOSTRING2, MODINFOSTRING2,
0, /* Missing from SDK: XORG_VERSION_CURRENT, */ XORG_VERSION_CURRENT,
1, 0, 0, PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
ABI_CLASS_XINPUT, ABI_CLASS_XINPUT,
ABI_XINPUT_VERSION, ABI_XINPUT_VERSION,
MOD_CLASS_XINPUT, MOD_CLASS_XINPUT,

81
src/evdev.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* Copyright © 2004-2008 Red Hat, Inc.
* Copyright © 2008 University of South Australia
*
* 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 Red Hat
* not be used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission. Red
* Hat makes 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.
*
* Authors:
* Kristian Høgsberg (krh@redhat.com)
* Adam Jackson (ajax@redhat.com)
* Peter Hutterer (peter@cs.unisa.edu.au)
*/
#ifndef EVDEV_H
#define EVDEV_H
#include <linux/input.h>
#include <xf86Xinput.h>
#include <xf86_OSproc.h>
#if defined(XKB)
/* XXX VERY WRONG. this is a client side header. */
#include <X11/extensions/XKBstr.h>
#endif
typedef struct {
int kernel24;
int screen;
int min_x, min_y, max_x, max_y;
int abs_x, abs_y, old_x, old_y;
int flags;
int tool;
/* XKB stuff has to be per-device rather than per-driver */
int noXkb;
#ifdef XKB
char *xkb_rules;
char *xkb_model;
char *xkb_layout;
char *xkb_variant;
char *xkb_options;
XkbComponentNamesRec xkbnames;
#endif
/* Middle mouse button emulation */
struct {
BOOL enabled;
BOOL pending; /* timer waiting? */
int buttonstate; /* phys. button state */
int state; /* state machine (see bt3emu.c) */
Time expires; /* time of expiry */
Time timeout;
} emulateMB;
} EvdevRec, *EvdevPtr;
/* Middle Button emulation */
int EvdevMBEmuTimer(InputInfoPtr);
BOOL EvdevMBEmuFilterEvent(InputInfoPtr, int, BOOL);
void EvdevMBEmuWakeupHandler(pointer, int, pointer);
void EvdevMBEmuBlockHandler(pointer, struct timeval**, pointer);
void EvdevMBEmuPreInit(InputInfoPtr);
void EvdevMBEmuFinalize(InputInfoPtr);
void EvdevMBEmuEnable(InputInfoPtr, BOOL);
#endif