Compare commits

...

150 Commits

Author SHA1 Message Date
Peter Hutterer
11d506dce6 evdev 2.1.1 2009-01-13 11:36:14 +10:00
Michael Chapman
a34a2cd347 Disable middle mouse button emulation when a middle mouse button event is registered
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 0592d97fbb)
2009-01-13 11:36:14 +10:00
Matt Helsley
78c00bd77f Fix FOO_MAX off-by-one
In linux/input.h each section's (e.g. ABS) FOO_MAX is the maximum FOO
value. Recent kernels define FOO_CNT as the maximum number of FOO there
will ever be. Hence using FOO_MAX to size the bit vectors representing
the capabilities of an evdev device is off by one.

Define FOO_CNT values for use with Linux kernels which lack them. Use
FOO_CNT whenever we need to know the number of bits needed -- usually to
calculate the number of longs needed.

When iterating over the values FOO_MAX still seems appropriate however
the loop test should include FOO_MAX rather than skip it.

Signed-off-by: Matt Helsley <matt.helsley@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 4dfd86b220)

Conflicts:

	src/evdev.c
2009-01-13 11:36:13 +10:00
Matt Helsley
760f1c6bb1 rename NBITS to NLONGS to reflect its actual meaning
NBITS really convers the number of bits passed as its argument
into a number of longs. This is somewhat atypical of many
function-like-macro names. Rename it to NLONGS.

Signed-off-by: Matt Helsley <matt.helsley@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

(cherry-picked from commit d3fd42d864)
Not really required, but it makes cherry-picking
4dfd86b220 easier.
2009-01-13 11:36:13 +10:00
Alan Coopersmith
2db04ba3c3 Remove xorgconfig & xorgcfg from See Also list in man page
(cherry picked from commit 0f0a149067)
2009-01-13 11:36:13 +10:00
Yan Li
363d0bdb9f Fix XkbModel parsing error
Signed-off-by: Yan Li <yan.i.li@intel.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit d170cba0cd)
2009-01-13 11:36:13 +10:00
Peter Hutterer
16a26a1eca Finalize MB emu (and wakeup handlers) before closing the fd.
Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit 2bf6e29b40)
2009-01-13 11:36:13 +10:00
Peter Hutterer
b879ae7351 evdev 2.1 2008-11-18 15:21:01 +10:00
Peter Hutterer
53566b7d4d Store device file's minor/major to avoid duplicate devices.
Devices added that use the same min/maj as an already added device are ignored
by the driver. This way users can have an xorg.conf entry on
/dev/input/by-id/blahblah and not get the same device added by HAL.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit 63af314368)
2008-11-18 15:13:34 +10:00
Fernando Carrijo
29c2765fc3 Fix error message
(cherry picked from commit 4c5c9c111d)
2008-11-11 14:37:45 +10:00
Peter Hutterer
7ef4e2c5e1 evdev 2.1 RC 3
That's it, no more new features. Now it's down to bugfixing only.
2008-11-03 13:47:15 +10:30
Peter Hutterer
dd0eeacc24 Add support for axes swapping.
New option: SwapAxes (boolean)
New property: EVDEV_PROP_SWAP_AXES.

Actual swapping code written by Donnie Berkholz.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit 4826969f23)
2008-11-03 13:46:40 +10:30
Peter Hutterer
67c0ea6c94 Add support for run-time calibration.
Some devices require run-time axis calibration. We can't change the min/max
ranges once we've initialised the valuator structs though, so in-driver
run-time calibration is required.

If the property is set, the driver scales from the calibrated range to the
values reported to the X server (which then may scale to screen coordinates).
If the property is not set (i.e. zero items) no scaling is performed.
(cherry picked from commit 33eb36f266)
2008-11-03 13:46:39 +10:30
Peter Hutterer
6bcbbc0411 Treat BTN_[0-2] as LMR buttons if necessary.
Treat BTN_[0-2] as LMR buttons on devices that do not advertise BTN_LEFT,
BTN_MIDDLE, BTN_RIGHT (e.g. 3Dconnexion SpaceNavigator).

Otherwise, treat BTN_[0+n] as button 5+n. Note: This causes duplicate
mappings for BTN_0 + n and  BTN_SIDE + n.

This also fixes a bug where we could end up with negative button numbers after
trying to map BTN_0.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit 64554e4799)
2008-11-03 13:46:35 +10:30
Peter Hutterer
534a3734d0 Remove obsolete FIXME
xkeyboard-config's maps are perfectly able to cope with evdev now.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit b77f939857)
2008-11-03 13:46:35 +10:30
Peter Hutterer
215c230d5c Flush input after re-opening the fd.
Suggested by Julien Cristau.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
(cherry picked from commit a43ab4999b)
2008-11-03 13:46:33 +10:30
Peter Hutterer
8f96530449 emuMB: add EvdevMBEmuOn and call from EvdevOn to register wakeup handlers.
This got broken in b0737bdbd1, when the
EmuMBPreInit call was removed from EvdevOn. As a result, VT switching away and
back wouldn't restore the wakeup handlers and mouse button presses
disappeared.
(cherry picked from commit af096e8c5d)
2008-11-03 13:46:31 +10:30
Peter Hutterer
4fb97edcd4 Fix axis inversion for absolute coordinates.
If min_x/y was not equal to 0, the inverted calculated range was off and leads
to inaccessible or out-of-range areas.
(cherry picked from commit 12498042fc)
2008-11-03 13:46:25 +10:30
Peter Hutterer
4e86393bc0 emulate MB: fix confusing log message.
If we're forcing MB emulation behaviour as per config, then at least state
whether we're forcing it off or on.

Found by Michel Dänzer.
(cherry picked from commit 0f8fcfccb3)
2008-11-03 13:46:17 +10:30
Peter Hutterer
a64a78791f evdev 2.1 RC 2 2008-10-23 17:16:36 +10:30
Peter Hutterer
09b2a5e87b Silence compiler warning by memsetting the struct properly.
(cherry picked from commit 0ab4c09e50)
2008-10-23 17:15:32 +10:30
Peter Hutterer
fa18a4a38d MB emulation timeout is stored as Time, make the property 32-bit too.
(cherry picked from commit d348eb8ce7)
2008-10-23 17:15:30 +10:30
Peter Hutterer
172523d745 Init ioctl bitmasks to 0, shuts up valgrind too.
(cherry picked from commit 2c1698fa61)
2008-10-23 17:15:28 +10:30
Søren Hauberg
8fb820ffaf Add touchscreen support.
Touchscreens are devices that do not have buttons and only advertise
BTN_TOUCH. Add a new flag to note the device type.

If BTN_TOUCH is detected, change it to BTN_LEFT and process it normally.
(cherry picked from commit 8c39302594)
2008-10-23 17:15:25 +10:30
Julien Cristau
c7893b212d Fix TestBit() on 64bit
Reported by Albert Damen <albrt@gmx.net>
X.Org Bug#18150 <http://bugs.freedesktop.org/show_bug.cgi?id=18150>
(cherry picked from commit f57e8face9)
2008-10-23 17:14:52 +10:30
Peter Hutterer
e9dd721e2d Add option "GrabDevice", don't grab the device by default.
We now have the matching code in the server to set the console to RAW mode and
don't need to grab the devices anymore.

This is an updated version of e8534d47c8, which
was reverted in 6dc4199155.
(cherry picked from commit 4912e2aa7f)
2008-10-23 17:14:49 +10:30
Peter Hutterer
cab104fd9e Don't post keycodes > 255.
If we only have keys > 255 we don't set up a key class rec, so don't post
them. It makes the server unhappy.

Signed-off-by: Julien Cristau <jcristau@debian.org>
(cherry picked from commit 7243116f55)
2008-10-23 17:14:45 +10:30
Peter Hutterer
708eb34599 evdev 2.1 RC 1. 2008-10-14 17:19:58 +10:30
Peter Hutterer
36a687796f Fix "Device reopened after N attempts" message.
(cherry picked from commit 0089d931ac)
2008-10-14 17:18:08 +10:30
Peter Hutterer
26229df106 Don't init draglock, etc. if we don't have the required capabilities.
(cherry picked from commit 0f5a5ac09e)
2008-10-14 17:18:07 +10:30
Peter Hutterer
f4616d87fc 8-bit properties should use 8-bit storage types...
(cherry picked from commit 36d68b006d)
2008-10-14 17:18:07 +10:30
Peter Hutterer
2aa5ca8cdd Don't include the client-side header anymore. xkbstr.h is server SDK.
(cherry picked from commit bb1f421687)
2008-10-14 17:18:07 +10:30
Peter Hutterer
39263dc65d Tidy up evdev.h
This includes shuffling some functions around so we don't need the prototypes
in evdev.h.
(cherry picked from commit 0405f7b17f)
2008-10-14 17:18:07 +10:30
Peter Hutterer
57521e4e60 Rename DragLockInit to DragLockPreInit, remove superfluous "return".
(cherry picked from commit 088e0a175a)
2008-10-14 17:18:07 +10:30
Peter Hutterer
7da1522309 Register property handler from within the modules, not the main evdev file.
(cherry picked from commit cefedeb205)
2008-10-14 17:18:07 +10:30
Peter Hutterer
b4fcb825fc Clean up program flow - don't call PreInit for "modules" on DEVICE_INIT.
Call the PreInit functions for MB Emulation, wheel emu, and draglock during
PreInit, not on DEVICE_INIT. This way, we only parse the options once and
don't overwrite with defaults when coming back from a VT switch.
(cherry picked from commit b0737bdbd1)
2008-10-14 17:18:07 +10:30
Peter Hutterer
7c955ad050 Janitor: clean up xf86Msg use, might as well use X_CONFIG directly.
(cherry picked from commit 5f2c8a2dcd)
2008-10-14 17:18:07 +10:30
Peter Hutterer
4f80c0f2cb Add property support for ReopenAttempts option.
(cherry picked from commit ff783fce65)
2008-10-14 17:18:07 +10:30
Peter Hutterer
5070d64aa8 Document properties in man page.
(cherry picked from commit c638aa4a88)
2008-10-14 17:18:07 +10:30
Peter Hutterer
caacacf057 Document InvertX/Y options.
(cherry picked from commit b46677e346)
2008-10-14 17:18:07 +10:30
Peter Hutterer
9065d0ccb2 Remove "Path" option.
Path was just an alias for Device anyway, so we might as well not parse it.
By now you should be using HAL anyway which fills in Device for you.
2008-10-11 12:24:54 +10:30
Peter Hutterer
a9fcce1833 Remove parsing of ScreenNumber option.
Was unused anyway, so we might as well not parse it.
2008-10-11 12:24:54 +10:30
Peter Hutterer
ab934d840d Janitor: purge unused headers, reshuffle for readability, fix whitespace errors. 2008-10-11 12:24:54 +10:30
Peter Hutterer
6f6ac98295 Add checkonly handling to property handlers.
If checkonly is TRUE, we can only check if applying the value would succeed.
The value is actually applied if checkonly is FALSE.
2008-10-11 12:24:54 +10:30
Peter Hutterer
a2633c8078 Fix up bad return code in draglock property handler. 2008-10-11 12:24:54 +10:30
Peter Hutterer
e6c699dedc Stricter value checking for property changes. 2008-10-11 12:24:54 +10:30
Julien Cristau
847eac8262 Set pInfo->fd to -1 on DEVICE_CLOSE
This allows the reopen logic to kick in later.
DEVICE_CLOSE gets called on regen, so without this we'd keep a stale
file descriptor in pInfo->fd in subsequent sessions.

Debian bug#496101 (http://bugs.debian.org/496101)
2008-10-11 02:16:25 +02:00
Peter Hutterer
a196672a6b Add property support for axis inversion. 2008-10-03 14:42:02 +09:30
Søren Hauberg
3985d42320 Add support for axis inversion. 2008-10-03 14:41:58 +09:30
Peter Hutterer
e138e4b79a Install xorg-evdev.pc for clients who need evdev-properties.h 2008-10-03 14:39:25 +09:30
Peter Hutterer
125e2b8ce2 Close fd on DEVICE_OFF. (LP #276887)
Leaving the fd open means we still get keyboard events after VT switching
away. Coming back, some of these events are replayed on the application that
has the current focus.

Reproduceable:
1. open terminal, focus.
2. VT switch away
3. type something, preferably a password
4. VT switch back, trigger a mouse event
5. Observe the X server guessing your password.

Closing the fd on DEVICE_OFF fixes this. Reopen is handled by the reopen
code introduced with

    commit 9930477cbe
    Author: Peter Hutterer <peter.hutterer@redhat.com>
    Date:   Tue Aug 26 14:33:40 2008 +0930

        Attempt to re-open devices on read errors.

Launchpad Bug 276887
<https://bugs.edge.launchpad.net/ubuntu/+source/xorg-server/+bug/276887>
2008-10-02 12:09:13 +09:30
Peter Hutterer
91bc0a0ba3 Remove useless initialization of rc. 2008-10-02 12:09:12 +09:30
Peter Hutterer
4c55186aed Change DragLock atom name - prepend with Evdev. 2008-10-02 12:09:10 +09:30
Peter Hutterer
62069b97d2 Move misplaced #endif 2008-09-30 12:24:07 +09:30
Peter Hutterer
2718a5c56b Register property handlers directly, instead of abstracting them.
This removes a left-over from the early device property code where we could
only have a single handler. Now it's easier to just register the handlers for
each subsystem (emulate wheel, draglock and MB emulation).
2008-09-30 12:24:07 +09:30
Peter Hutterer
90d1d494f8 Cleanup: "valid_vals" should be "vals" now. 2008-09-30 12:24:07 +09:30
Peter Hutterer
a77c2622cc Add evdev-properties.h file with #defines for all property names. 2008-09-30 12:24:03 +09:30
Peter Hutterer
84a0e39c0d Use new property API (no ConfigureDP, less args to ChangeDP)
Return appropriate status codes from property handlers.
Make properties non-deletable.
2008-09-26 13:23:35 +09:30
Peter Hutterer
7386937221 draglock: Shut up compiler warning. 2008-09-26 12:56:36 +09:30
Peter Hutterer
fcf8375f2b Don't require randrproto. 2008-09-26 12:56:33 +09:30
Peter Hutterer
9930477cbe Attempt to re-open devices on read errors.
Coming back from resume may leave us with a file descriptor that can be opened
but fails on the first read (ENODEV).
In this case, try to open the device until it becomes available or until the
predefined count expires. To be safe, we cache the information from the device
and compare against it when we re-open. This way we ensure that if the
topology changes under us, we don't open a completely different device. If a
device has changed, we disable it.

Adds option "ReopenAttempts" <int>
2008-09-04 18:33:39 +09:30
Peter Hutterer
4509ec1daf Use HAVE_PROPERTIES define instead of GET_ABI_MAJOR for property compilation. 2008-09-04 18:22:56 +09:30
Peter Hutterer
a205dfc091 Shut up "unused variable" compiler warnings.
Hide properties behind ifdefs, fake use of "val".
2008-09-04 18:14:48 +09:30
Peter Hutterer
184206e717 Wheel emulation: initial values must be char.
parsing int* to char* in XIChangeDeviceProperty means we lose values.
2008-08-25 17:24:15 +09:30
Peter Hutterer
79ff677c52 Init all emulateWheel values, even if EmulateWheel is disabled.
Even if we don't want EmulateWheel, we can at least init everything to usable
values. This way we only need to toggle "enabled", rather than initialising
the whole lot before usage.
2008-08-22 09:04:33 +09:30
Dan Nicholson
37e3addf89 Add wheel timeout property support
Copied from the wheel inertia property support.

Signed-off-by: Dan Nicholson <dbn.lists@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
2008-08-22 09:04:16 +09:30
Dan Nicholson
e237de0dea Add timeout support for mouse wheel emulation
Support the EmulateWheelTimeout option as the mouse driver does.

Signed-off-by: Dan Nicholson <dbn.lists@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
2008-08-22 08:41:14 +09:30
Peter Hutterer
92c6611b6f Add property support for drag lock. 2008-08-18 13:44:02 +09:30
Chris Salch
bd405ddc83 Adding in DragLockButtons functionality.
Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
2008-08-18 12:03:07 +09:30
Daniel Stone
36d702006d Force rules, not model, to be evdev
xkeyboard-config recently changed to a separate ruleset for the evdev
driver, so match that by only forcing the ruleset, not the model, to be
evdev.
2008-08-16 15:34:03 +03:00
Peter Hutterer
6dc4199155 Revert "Don't grab devices unless specified through the config options."
Not such a good idea, CTRL+C terminates the server and other issues. Reverting
for now until a better solution is found, at least this way the driver is
usable.

See also: http://lists.freedesktop.org/archives/xorg/2008-August/038032.html

This reverts commit e8534d47c8.
2008-08-15 11:54:53 +09:30
Peter Hutterer
e8534d47c8 Don't grab devices unless specified through the config options.
Grabbing event devices stops in-kernel event forwarding, most notably rfkill
and the "Macintosh mouse button emulation" device. Let's not do that.

Option "GrabDevice" forces grabbing the device.
2008-08-14 13:44:11 +09:30
Chris Salch
555f5a7cbf Filter wheel events before middle mouse button emulation.
The Emulate3Button needs to be the last filter function, otherwise the timeout
code causes it to hijack button presses for the first 3 buttons.

Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
2008-08-08 16:04:26 +09:30
Peter Hutterer
134829d911 Simplify the property handler registration.
Instead of having separate handlers for each property, just handle all of them
in one handler for emuMB, and one handler for emuWheel.
2008-08-08 16:04:23 +09:30
Peter Hutterer
4e121b297e Add EVDEV_MAXBUTTONS instead of checking against 32.
Numbers are so lame, defines are all the rage now I've heard.
2008-08-08 15:51:09 +09:30
Peter Hutterer
9793de8137 Expose wheel emulation through device properties.
Don't enable wheel emulation with 0 inertia - bad things happen.
2008-08-08 15:50:55 +09:30
Chris Salch
a9d72b40fb Adding mouse wheel emulation code.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2008-08-07 16:04:31 +09:30
Adam Jackson
c1f7f8c3d2 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>
2008-08-07 09:36:02 +09:30
Chris Salch
40e1474d84 Adding a function to map button events to button numbers.
Remove code duplication, let the mapping function hand us the actual button
event to be passed up to the server.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2008-08-06 16:36:51 +09:30
Julien Cristau
d9097df01b Actually close the fd on DEVICE_CLOSE (bug#16948)
Fixes file descriptor leak.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2008-08-04 09:17:37 +09:30
Julien Cristau
5c074af5a9 Print the device name when we get a read error 2008-07-30 10:42:05 +02:00
Michel Dänzer
72551662a0 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>
2008-07-30 11:26:23 +09:30
Peter Hutterer
53e7525744 Add support for ButtonMapping option. 2008-07-22 11:49:33 +09:30
Peter Hutterer
5d13259a5d Guard property changes against ABI_XINPUT < 3. 2008-07-21 13:10:11 +09:30
Julien Cristau
2b7edaa4ab Fill up the version info
Report correct versions instead of
"compiled for 0.0.0, module version = 1.0.0"
2008-07-20 11:33:37 +02:00
Peter Hutterer
bf0d81011e 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".
2008-07-14 13:10:34 +09:30
Peter Hutterer
ef4bb69c1a Add .gitignore file. 2008-07-10 19:32:22 +09:30
Peter Hutterer
d1818ef206 Add support for device properties, currently MB emulation and timeout. 2008-07-10 17:08:49 +09:30
Peter Hutterer
a9223edcd8 Clean out configure.ac
We're not building with or without XInput. Same with xkb.
2008-07-10 16:55:21 +09:30
Peter Hutterer
ec23c6b2f5 Remove static ChangeLog, autogenerate as part of make dist.
Hook taken from xserver's Makefile.am
2008-07-03 15:01:32 +09:30
Peter Hutterer
18d70d796f Update COPYING with the correct copyright info.
Fix up licence of emuMB.c, was using Red Hat instead of "The authors", but
this code wasn't contributed by RH anyway.
2008-07-03 14:59:27 +09:30
Peter Hutterer
37b854cb64 Remove stale comments.
Ctrl+Alt+Backspace works, I'm using it daily.
CapsLock doesn't repeat, otherwise we wouldn't have Bug 16318.
2008-07-03 14:45:41 +09:30
Peter Hutterer
8c06093191 Remove EvdevConvert, nobody calls it now anyway.
Conversion is now done in the DIX.
2008-07-03 14:44:52 +09:30
Ander Conselvan de Oliveira
0830676a0c 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>
2008-06-28 17:54:33 +09:30
Peter Hutterer
1cf7b8f7ee Count buttons at probe and print to log.
We don't really do anything with the number other than print it since I'm sure
that half the mice don't report the correct number anyway (especially with the
wheel button mapping). But having a bit more debug info is good.
2008-06-28 17:53:24 +09:30
Peter Hutterer
826e6e7dd4 Bump to 2.0.99. 2008-06-22 17:52:40 +09:30
Peter Hutterer
5a0ea39b79 No need to finalize MB emulation after EvdevProbe anymore.
Follow-up to 76800bfa75.
2008-06-22 10:56:44 +09:30
Simon Munton
373e13ae35 Close file descriptor if EvdevProbe fails.
Signed-off-by: Peter Hutterer <peter@cs.unisa.edu.au>
2008-06-22 10:56:00 +09:30
Keith Packard
76800bfa75 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>
2008-06-21 18:14:35 -07:00
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
Adam Jackson
d45f315845 evdev 1.99.2 2008-05-21 15:05:10 -04:00
Dan A. Dickey
a4a7003f7c Fix a trivial bug in testing for absolute axes.
Signed-off-by: Peter Hutterer <peter@cs.unisa.edu.au>
2008-05-20 10:57:06 +09:30
Peter Hutterer
3e0dc9945d Shut up two compiler warnings. 2008-05-19 08:36:20 +09:30
Peter Hutterer
ff6251a2bd Remove unused EvdevOpts and EvdevOptions.
In the mouse driver, these options are only used if XFree86LOADER is
undefined. configure.ac in the xserver forces said define to 1 if we're
building the xfree86 DDX, so I don't see the point of having them around.
Especially since they weren't used in evdev anyway.
2008-05-19 08:24:55 +09:30
Peter Hutterer
e9222a8285 man: Option "Path" is supported in the code, add it to man page. 2008-05-18 11:04:43 +09:30
Peter Hutterer
8b7738457f Don't allow relative and absolute axes on the same device.
This is a bit of a mess. The MS Optical Desktop 2000 registers both relative
and absolute axes on the same device (the mouse). The absolute axes have a
valid min/max range for x/y and thus overwrite the x/y relative axes in the
server (no, this is not a server bug). And I wouldn't be surprised if other
devices have similar issues.

Since the device only sends relative events after that, the mouse is
essentially restricted to the min..max range of 0..255. The server simply
doesn't do unrestricted relative axis and restricted absolute axis on the same
device (not for the same axis numbers anyway).
2008-05-02 11:17:57 +09:30
Sascha Hlusiak
1b9deb8e7e Add XK_Meta_L and XK_Meta_R to list of modifiers
Stopps meta/super key from autorepeating
2008-04-01 17:24:13 +02:00
Daniel Stone
0ec391f51c Keyboard: Don't allow arbitrary keymap settings
Pretty much dead code anyway.
2008-03-28 17:46:38 +02:00
Adam Jackson
f77410e1f9 Map REL_DIAL to REL_HWHEEL.
Some Microsoft mice have this wrong.  And it seems like a sensible thing
to do anyway.
2008-03-14 11:15:01 -04:00
Adam Jackson
d28c2e1efb Filter out repeat events for mouse buttons.
Not many mice do this, but some do, Apple Mighty Mouse in particular, and
it makes click-and-drag pretty much impossible to use.

Arguably we should filter _all_ repeat events from the kernel and handle
synthesizing them in the server.
2008-03-12 13:54:10 -04:00
Adam Jackson
697e850a63 Fix middle/right button munging.
Don't do this in the button map.  That's writeable by clients, which means
they have the chance to get it wrong.  Just swap right and middle around
in event dispatch before you get to the user's map.
2008-03-11 19:07:58 -04:00
Adam Jackson
87037b9953 Force xkb_model to be "evdev".
Or at least, refuse to recognise the config option.  It's nonsensical to
use a model of something other than evdev, and it'll just break if you try.
2008-03-10 17:16:38 -04:00
Dan Nicholson
71f4eaec77 Fix cut-and-paste errors in xkb alternate spellings code
Fixes 2b334d6b69.
2008-03-09 22:52:13 +01:00
Adam Jackson
7208397612 Fix cut-and-paste error in abs-to-rel translation. 2008-03-09 16:15:14 -04:00
Adam Jackson
c250f84383 Fix the default XKB rules to be "base" instead of "xfree86". 2008-03-09 15:54:27 -04:00
Adam Jackson
2b334d6b69 Handle the alternate spellings of the xkb options. 2008-03-09 15:53:40 -04:00
Adam Jackson
9773dac623 Merge branch 'evdev-2.0-branch'
This resets to before the ad-hoc input hotplug state, ports that to
current server ABI, adds input hotplug integration, and re-adds support
for absolute coordinate events and XKB.  Several other small fixes were
cherry-picked from the new 1.2 branch.
2008-03-08 20:27:02 -05:00
Adam Jackson
1a0bc8e64a Force maximum keycode to be 255
Even though we don't have keycodes for anything above 127, make sure our
map always covers up to 255.  This ensures that the keycode range never
changes.

Spiritually cherry-picked from a9e87f29cc
and 6db4a9fb84.
2008-03-08 20:06:24 -05:00
Adam Jackson
6271494faa Add absolute coordinate event support.
There are two major classes here, touchscreens and touchpads.  Touchpads
are logically more like relative devices, in that your initial touch
should not warp the cursor.  So attempt to detect touchpads (via the
existence of BTN_TOUCH) and translate absolute events from those devices
to relative motion.
2008-03-08 19:54:44 -05:00
Adam Jackson
f5bfc7ec3c Nuke the keyboard bell code.
It did nothing, and the core won't invoke it anymore anyway.
2008-03-08 16:52:17 -05:00
Adam Jackson
bf0848ec8e Re-add XKB support.
Almost entirely taken from a patch I did ages ago in bug #3912, with
slight cleanups, and with the KcCGST options removed as per evdev 1.x.
2008-03-08 16:50:20 -05:00
Adam Jackson
f1445feac7 Parse Option "Path" as well as Option "Device".
The hotplug core passes Path not Device.  With this change, hotplugging
works.
2008-03-08 16:09:47 -05:00
Adam Jackson
ad5bdcb50f Ignore button events above BTN_TASK for now. 2008-03-07 20:29:58 -05:00
Adam Jackson
bb36ca65c6 Support the new DIX motion history API
Spiritually cherry-picked from 036b457c1b
2008-03-07 19:43:07 -05:00
Daniel Stone
40a1e1439c remove XFree86LOADER usage
Build evdevModuleData, et al, unconditionally.
2008-03-07 19:38:33 -05:00
Adam Jackson
946beb16f8 Unlibcwrap. 2008-03-07 19:09:35 -05:00
Adam Jackson
305f90d37a Branch for evdev 2.0 2008-03-07 19:06:14 -05:00
Sascha Hlusiak
11cf9c92c0 Updated manpage to reflect current state
Large parts of the manpage were obsolete and confused users. Current state should reflect all available driver options. Some details are still missing.
2008-03-03 13:40:52 +02:00
Sascha Hlusiak
7f1e8146d4 More accurate error messages on device open fail.
The message "cannot open input pEvdev" resulted in a lot of bug reports of confused users that did not
supply a device path. Now we tell them when it is missing or print out a reason when device open fails.
2008-02-20 20:41:08 +01:00
Sascha Hlusiak
8ae4d17ca3 Let kernel autorepeat pass when set on default values
xorg-server won't generate soft autorepeat, when interval/delay are at default of 40/660 (see xkb/ddxCtrls.c:
XkbDDXUsesSoftRepeat). When we hit the defaults, we let the kernel autorepeat pass, if we differ, we swallow them all
and let the server figure out autorepeat in software.
2008-02-19 22:49:51 +01:00
Sascha Hlusiak
134ce2e493 Set repeat_delay and repeat_interval to default values
Set ctrls->repeat_delay and ctrls->repeat_interval so that keys will be automatically repeated in software.
2008-02-19 21:12:36 +01:00
Sascha Hlusiak
10e7c3fbdf Filter all incoming repeated key events
Not just filter modifiers but every repeated key, because the software implementation will take care of what key to
repeat and what not. Otherwise the kernel's autorepeated keys interfere with the software generated ones.
2008-02-19 21:09:13 +01:00
Sascha Hlusiak
f766404fd9 Don't inform kernel evdev driver about autorepeat change
We do autorepeat in software now. Informing the kernel would change the autorepeat speed on virtual terminals, which is
probably not wanted so we leave the settings untouched.
2008-02-19 21:05:49 +01:00
Vinay Bondhugula
d032d3c8b4 Clear EV_ABS_V_USE_TOUCH for devices without a touch button
VMware's absolute pointing device does not have a pressure/touch button.
Although evdev correctly recognizes this, it sets "use_touch" for X and Y axes
regardless of the touch button. This patch clears the USE_TOUCH flag for the X
and Y axes if the device does not have a touch button.
2008-01-29 22:15:22 -08:00
Peter Hutterer
5adbc6b98c Initialise b_map_data to correct size. Bug #13991
X.Org Bug 13991 <http://bugs.freedesktop.org/show_bug.cgi?id=13991>
2008-01-29 14:07:49 +10:30
Julien Cristau
eeb3727004 Don't flush buttons on init (bug#12630) 2007-12-07 17:02:11 +01:00
21 changed files with 3313 additions and 2930 deletions

19
.cvsignore Normal file
View File

@@ -0,0 +1,19 @@
Makefile
Makefile.in
*.la
*.lo
aclocal.m4
autom4te.cache
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
depcomp
install-sh
libtool
ltmain.sh
missing
stamp-h1

18
.gitignore vendored
View File

@@ -1,13 +1,9 @@
*.patch
ChangeLog
Makefile
Makefile.in
ChangeLog
xf86-input-evdev-*.tar.bz2
xf86-input-evdev-*.tar.gz
*.la
*.lo
aclocal.m4
autom4te.cache
compile
config.guess
config.h
config.h.in
@@ -19,7 +15,13 @@ depcomp
install-sh
libtool
ltmain.sh
man/evdev.4
missing
.deps
.libs
*.lo
*.la
stamp-h1
.*.swp
*~
*.bz2
*.gz
*.pc

99
COPYING
View File

@@ -1,12 +1,95 @@
This is a stub file. This package has not yet had its complete licensing
information compiled. Please see the individual source files for details on
your rights to use and modify this software.
Various copyright notices found in this driver:
Please submit updated COPYING files to the Xorg bugzilla:
Copyright © 2004-2008 Red Hat, Inc.
https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
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.
All licensing questions regarding this software should be directed at the
Xorg mailing list:
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.
Copyright 2005 Sun Microsystems, Inc. All rights reserved.
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.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the copyright holders shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the copyright holders.
Copyright © 2008 University of South Australia
copyrights taken from xf86-input-mouse, partly valid for this driver.
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
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.
Copyright 2005 Adam Jackson.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://lists.freedesktop.org/mailman/listinfo/xorg

View File

@@ -19,15 +19,19 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src man
SUBDIRS = src man include
EXTRA_DIST=ChangeLog
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = xorg-evdev.pc
CLEANFILES=ChangeLog
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)
(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_INIT([xf86-input-evdev],
1.2.0,
2.1.1,
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
xf86-input-evdev)
@@ -44,24 +44,6 @@ AC_PROG_CC
AH_TOP([#include "xorg-server.h"])
#AC_DEFINE(XFree86LOADER,1,[Stub define for loadable drivers])
#
#AC_ARG_ENABLE(XINPUT, AS_HELP_STRING([--enable-xinput],
# [Build XInput support (default: yes)]),
# [XINPUT=$enableval],[XINPUT=yes])
#AM_CONDITIONAL(XINPUT, test "x$XINPUT" = "xyes")
#if test "x$XINPUT" = "xyes" ; then
# AC_DEFINE(XINPUT,1,[Enable XInput support])
#fi
#
#AC_ARG_ENABLE(XKB, AS_HELP_STRING([--enable-xkb],
# [Build XKB support (default: yes)]),
# [XKB=$enableval],[XKB=yes])
#AM_CONDITIONAL(XKB, test "x$XKB" = "xyes")
#if test "x$XKB" = "xyes" ; then
# AC_DEFINE(XKB,1,[Enable XKB support])
#fi
AC_ARG_WITH(xorg-module-dir,
AC_HELP_STRING([--with-xorg-module-dir=DIR],
[Default xorg module directory [[default=$libdir/xorg/modules]]]),
@@ -71,13 +53,12 @@ inputdir=${moduledir}/input
AC_SUBST(inputdir)
# Checks for extensions
#XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
XORG_DRIVER_CHECK_EXT(XKB, kbproto)
XORG_DRIVER_CHECK_EXT(XINPUT, inputproto)
# Checks for pkg-config packages
PKG_CHECK_MODULES(XORG, xorg-server xproto $REQUIRED_MODULES)
sdkdir=$(pkg-config --variable=sdkdir xorg-server)
AC_SUBST(sdkdir)
CFLAGS="$CFLAGS $XORG_CFLAGS "' -I$(top_srcdir)/src'
AC_SUBST([CFLAGS])
@@ -90,4 +71,8 @@ AC_HEADER_STDC
XORG_MANPAGE_SECTIONS
XORG_RELEASE_VERSION
AC_OUTPUT([Makefile src/Makefile man/Makefile])
AC_OUTPUT([Makefile
src/Makefile
man/Makefile
include/Makefile
xorg-evdev.pc])

2
include/Makefile.am Normal file
View File

@@ -0,0 +1,2 @@
EXTRA_DIST = evdev-properties.h
sdk_HEADERS = evdev-properties.h

View File

@@ -0,0 +1,69 @@
/*
* 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 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:
* Peter Hutterer (peter.hutterer@redhat.com)
*/
#ifndef _EVDEV_PROPERTIES_H_
#define _EVDEV_PROPERTIES_H_
/* Middle mouse button emulation */
/* BOOL */
#define EVDEV_PROP_MIDBUTTON "Evdev Middle Button Emulation"
/* CARD32 */
#define EVDEV_PROP_MIDBUTTON_TIMEOUT "Evdev Middle Button Timeout"
/* Wheel emulation */
/* BOOL */
#define EVDEV_PROP_WHEEL "Evdev Wheel Emulation"
/* CARD8, 4 values [x up, x down, y up, y down], 0 to disable a value*/
#define EVDEV_PROP_WHEEL_AXES "Evdev Wheel Emulation Axes"
/* CARD16 */
#define EVDEV_PROP_WHEEL_INERTIA "Evdev Wheel Emulation Inertia"
/* CARD16 */
#define EVDEV_PROP_WHEEL_TIMEOUT "Evdev Wheel Emulation Timeout"
/* CARD8, value range 0-32, 0 to disable a value */
#define EVDEV_PROP_WHEEL_BUTTON "Evdev Wheel Emulation Button"
/* Drag lock */
/* CARD8, either 1 value or pairs, value range 0-32, 0 to disable a value*/
#define EVDEV_PROP_DRAGLOCK "Evdev Drag Lock Buttons"
/* Axis inversion */
/* BOOL, 2 values [x, y], 1 inverts axis */
#define EVDEV_PROP_INVERT_AXES "Evdev Axis Inversion"
/* Reopen attempts. */
/* CARD8 */
#define EVDEV_PROP_REOPEN "Evdev Reopen Attempts"
/* Run-time calibration */
/* CARD32, 4 values [minx, maxx, miny, maxy], or no values for unset */
#define EVDEV_PROP_CALIBRATION "Evdev Axis Calibration"
/* Swap x and y axis. */
/* BOOL */
#define EVDEV_PROP_SWAP_AXES "Evdev Axes Swap"
#endif

View File

@@ -1,3 +1,2 @@
Makefile
Makefile.in
evdev.4

View File

@@ -1,5 +1,3 @@
# $Id$
#
# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
#
# Permission to use, copy, modify, distribute, and sell this software and its

View File

@@ -9,12 +9,15 @@ evdev \- Generic Linux input driver
.BI " Identifier \*q" devname \*q
.B " Driver \*qevdev\*q"
.BI " Option \*qDevice\*q \*q" devpath \*q
.BI " Option \*qEmulate3Buttons\*q \*q" True \*q
.BI " Option \*qEmulate3Timeout\*q \*q" 50 \*q
.BI " Option \*qGrabDevice\*q \*q" False \*q
\ \ ...
.B EndSection
.fi
.SH DESCRIPTION
.B evdev
is an __xservername__ input driver for Linux's generic event devices. It
is an __xservername__ input driver for Linux\'s generic event devices. It
therefore supports all input devices that the kernel knows about, including
most mice and keyboards.
.PP
@@ -37,301 +40,166 @@ Please refer to __xconfigfile__(__filemansuffix__) for general configuration
details and for options that can be used with all input drivers. This
section only covers configuration details specific to this driver.
.PP
.SH BASIC CONFIGURATIONS
Most users of this driver will probably be quite happy with the following for
all QWERTY keyboards:
.PP
.nf
.B "Section \*qInputDevice\*q"
.BI " Identifier \*q" keyboard \*q
.B " Driver \*qevdev\*q"
.BI " Option \*qevBits\*q \*q" "+1" \*q
.BI " Option \*qkeyBits\*q \*q" "~1\-255 ~352\-511" \*q
.BI " Option \*qPass\*q \*q" "3" \*q
\ \ ...
.B EndSection
.fi
.PP
And the following for all mice:
.PP
.nf
.B "Section \*qInputDevice\*q"
.BI " Identifier \*q" mouse \*q
.B " Driver \*qevdev\*q"
.BI " Option \*qevBits\*q \*q" "+1\-2" \*q
.BI " Option \*qkeyBits\*q \*q" "~272\-287" \*q
.BI " Option \*qrelBits\*q \*q" "~0\-2 ~6 ~8" \*q
.BI " Option \*qPass\*q \*q" "3" \*q
\ \ ...
.B EndSection
.fi
.PP
To understand what those Bits options do, or for more complex
configurations, please see
.BR "ADVANCED OPTIONS"
below.
.PP
.SH ADVANCED OPTIONS
.SS DEVICE SPECIFICATION
For this section you'll want to have knowledge of
.B glob (7)
and our evil
.B "BIT MATCHING SPECIFICATION"
stuff.
.PP
The following driver
.B Options
control what devices are accepted:
are supported:
.TP 7
.BI "Option \*qDevice\*q \*q" string \*q
Specifies the device note through which the device can be accessed.
At this time ONLY
.RI /dev/input/event n ,
where
.I n
is an integer, are matched against this this field.
.fi
This option uses globbing.
.fi
Please note that use of this option is strongly discouraged.
Specifies the device through which the device can be accessed. This will
generally be of the form \*q/dev/input/eventX\*q, where X is some integer.
The mapping from device node to hardware is system-dependent.
.TP 7
.BI "Option \*qName\*q \*q" string \*q
Specifies the device name for the device you wish to use.
.fi
The device name is generally the only consistent identifier for devices
that are commonly unplugged and plugged back into different ports.
.fi
A list of currently plugged in devices and associated device names can be
obtained by typing \*qcat /proc/bus/input/devices\*q, the \*qName\*q field
is the value you want for this option.
.fi
This option uses globbing.
.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. Property: "Evdev Middle Button Emulation".
.TP 7
.BI "Option \*qPhys\*q \*q" string \*q
Specifies the device phys string for the device you wish to use.
.fi
The phys string is generally consistent to the USB port a device is plugged
into.
.fi
A list of currently plugged in devices and associated device names can be
obtained by typing \*qcat /proc/bus/input/devices\*q, the \*qPhys\*q field
is the value you want for this option.
.fi
This option uses globbing.
.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. Property: "Evdev Middle Button Timeout".
.TP 7
.BI "Option \*q" map "Bits\*q \*q" "bit specifier" \*q
Specifies device capability bits which must be set, possibly set, or unset.
.fi
.IR map "Bits: Where " map
is one of
.BR ev ", " key ", " rel ", " abs ,
.BR msc ", " led ", " snd ", or " ff .
.fi
The bit specifier format is a string consisting of
.RI + n ", \-" n ", and ~" n
space-separated specifiers, where
.I n
is a positive integer or integer range. (The latter given in the format of 2\-6.)
.fi
+ specifies bits which must be set.
.fi
\- specifies bits which must not be set.
.fi
~ is a little more complex, it specifies that at least one of the bits given
with ~ for the field in question must be set, but it doesn't matter how many
or which of the bits. (It is actually the most useful of the 3 specifiers.)
.fi
As an example, \*q+0 +3 \-1\-2 ~5\-10\*q requires bits 0 and 3 be set,
bits 1 and 2 to not be set, and at least one bit in the range of 5 to
10 be set.
.fi
An annoyingly formatted set of bitmasks for your devices can be obtained
by typing \*qcat /proc/bus/input/devices\*q, and
.B /usr/include/linux/input.h
should contain the defines which declare what bits are what for each field.
.BI "Option \*qButtonMapping\*q \*q" string \*q
Sets the button mapping for this device. The mapping is a space-separated list
of button mappings that correspond in order to the physical buttons on the
device (i.e. the first number is the mapping for button 1, etc.). The default
mapping is "1 2 3 ... 32". A mapping of 0 deactivates the button. Multiple
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 \*qbustype\*q \*q" n \*q
Specifies the bus ID for the device you wish to use.
.fi
This is either 0 (the default, matches anything), or the
.BI Bus= n
field in
.B /proc/bus/input/devices
for your device.
.fi
This value depends on what type of bus your device is connected to.
.BI "Option \*qDragLockButtons\*q \*q" "L1 B2 L3 B4" \*q
Sets \*qdrag lock buttons\*q that simulate holding a button down, so
that low dexterity people do not have to hold a button down at the
same time they move a mouse cursor. Button numbers occur in pairs,
with the lock button number occurring first, followed by the button
number that is the target of the lock button. Property: "Evdev
Drag Lock Buttons".
.TP 7
.BI "Option \*qvendor\*q \*q" n \*q
Specifies the vendor ID for the device you wish to use.
.fi
This is either 0 (the default, matches anything), or the
.BI Vendor= n
field in
.B /proc/bus/input/devices
for your device.
.fi
This value should remain constant barring perhaps firmware updates to the
device itself.
.BI "Option \*qDragLockButtons\*q \*q" "M1" \*q
Sets a \*qmaster drag lock button\*q that acts as a \*qMeta Key\*q
indicating that the next button pressed is to be
\*qdrag locked\*q. Property: "Evdev Drag Lock Buttons".
.TP 7
.BI "Option \*qversion\*q \*q" n \*q
Specifies the version for the device you wish to use.
.fi
This is either 0 (the default, matches anything), or the
.BI Version= n
field in
.B /proc/bus/input/devices
for your device.
.fi
This value should remain constant barring perhaps firmware updates to the
device itself.
.TP 7
.BI "Option \*qproduct\*q \*q" n \*q
Specifies the product ID for the device you wish to use.
.fi
This is either 0 (the default, matches anything), or the
.BI Product= n
field in
.B /proc/bus/input/devices
for your device.
.fi
This value should remain constant barring perhaps firmware updates to the
device itself.
.TP 7
.BI "Option \*qPass\*q \*q" n \*q
Specifies the order in which evdev will scan for devices.
.fi
This is in the range of 0 to 3, and is used for the case
where more then one evdev input section matches the same device.
.fi
An input section with a lower pass number will always beat out
one with a higher pass number. Order when both sections are
the same number is undefined.
.fi
The default is 0.
.PP
.SS RELATIVE AXIS CONFIGURATION
The relative axis portion of this driver handle all reported relative axes.
.fi
The axes are named X, Y, Z, RX, RY, RZ, HWHEEL, DIAL, WHEEL, MISC, 10, 11,
12, 13, 14, and 15.
.fi
The axes are reported to X as valuators, with the default mapping of axes
to valuators being the first axes found to the first valuator, the second
found to the second valuator, and so on, so that if you have axes X, Y,
HWHEEL, and WHEEL, you would have X=0, Y=1, HWHEEL=2, WHEEL=3.
.fi
If the driver is reporting core events, valuators 0 and 1 are always mapped
to x and y coordinates, respectively.
.fi
The following driver
.B Options
control the relative axis portion of the driver:
.TP 7
.BI "Option \*q" axis "RelativeAxisMap\*q \*q" n \*q
This remaps the axis specified to the specified valuator.
.TP 7
.BI "Option \*q" axis "RelativeAxisButtons\*q \*q" "n n" \*q
This remaps the axis specified to the specified buttons.
.fi
Note that the physical buttons are always remapped around \*qfake\*q buttons
created by this option, so that if you have physical buttons 1 2 3 4 5,
and map the Wheel axis to buttons 4 5, you get buttons 1 2 3
.B 4 5
6 7, with buttons 6 and 7 being physical buttons 4 and 5.
.PP
.SS ABSOLUTE AXIS CONFIGURATION
The relative axis portion of this driver handle all reported relative axes.
.fi
The axes are named X, Y, Z, RX, RY, RZ, THROTTLE, RUDDER, WHEEL, GAS, BRAKE,
<11\-15>, HAT0X, HAT0Y, HAT1X, HAT1Y, HAT2X, HAT2Y, HAT3X, HAT3Y, PRESSURE,
TILT_X, TILT_Y, TOOL_WIDTH, VOLUME, <29\-39>, MISC, <41\-62>.
.fi
The axes are reported to X as valuators, with the default mapping of axes
to valuators being the first axes found to the first valuator, the second
found to the second valuator, and so on, so that if you have axes X, Y,
TILT_X, and TILT_Y, you would have X=0, Y=1, TILT_X=2, TILT_Y=3.
.fi
If the driver is reporting core events, valuators 0 and 1 are always mapped
to x and y coordinates, respectively.
.fi
The following driver
.B Options
control the relative axis portion of the driver:
.TP 7
.BI "Option \*q" axis "AbsoluteAxisMap\*q \*q" n \*q
This remaps the axis specified to the specified valuator.
.TP 7
.BI "Option \*qAbsoluteScreen\*q \*q" n \*q
This binds the device to a specific screen, scaling it to
the coordinate space of that screen.
.fi
The number can either be \-1, or a valid screen number.
.fi
If \-1 or if in relative mode no scaling or screen fixing is done.
.fi
This is of most use for digitizers, where the screen and the input
device are the same surface.
.TP 7
.BI "Option \*qMode\*q \*q" mode \*q
This selects the default mode for the device.
.fi
Valid values are \*qabsolute\*q and \*qrelative\*q.
.fi
This can be set at run time per actual device with the xinput utility.
.PP
.SS BUTTON CONFIGURATION
At the moment, the button portion of this driver only handles buttons
reported as mouse buttons, that is from BTN_MOUSE to BTN_JOYSTICK \- 1.
.fi
At this time there are no configuration options for buttons.
.SS KEYBOARD CONFIGURATION
The keyboard portion of this driver handles all keys reported and requires
XKB support.
.fi
The following driver
.B Options
control the relative axis portion of the driver:
.TP 7
.BI "Option \*qXkbRules\*q \*q" rules \*q
specifies which XKB rules file to use for interpreting the
.BR XkbModel ,
.BR XkbLayout ,
.BR XkbVariant ,
.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 XkbOptions
settings. Default: \*qxorg\*q for most platforms, but \*qxfree98\*q for the
Japanese PC-98 platforms.
.B YAxisMapping
options below. Default: off. Property "Evdev Wheel Emulation".
.TP 7
.BI "Option \*qXkbModel\*q \*q" modelname \*q
specifies the XKB keyboard model name. Default: \*qevdev\*q.
.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. Property: "Evdev Wheel Emulation Button".
.TP 7
.BI "Option \*qXkbLayout\*q \*q" layoutname \*q
specifies the XKB keyboard layout name. This is usually the country or
language type of the keyboard. Default: \*qus\*q.
.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. Property: "Evdev
Wheel Emulation Inertia".
.TP 7
.BI "Option \*qXkbVariant\*q \*q" variants \*q
specifies the XKB keyboard variant components. These can be used to
enhance the keyboard layout details. Default: not set.
.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. Property: "Evdev Wheel Emulation Timeout".
.TP 7
.BI "Option \*qXkbOptions\*q \*q" options \*q
specifies the XKB keyboard option components. These can be used to
enhance the keyboard behaviour. Default: not set.
.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. Property:
"Evdev Wheel Emulation Axes".
.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". Property:
"Evdev Wheel Emulation Axes".
.TP 7
.BI "Option \*qReopenAttempts\*q \*q" integer \*q
Number of reopen attempts after a read error occurs on the device (e.g. after
waking up from suspend). In between each attempt is a 100ms wait. Default: 10.
.TP 7
.BI "Option \*qInvertX\*q \*q" Bool \*q
.TP 7
.BI "Option \*qInvertY\*q \*q" Bool \*q
Invert the given axis. Default: off. Property: "Evdev Axis Inversion".
.TP 7
.BI "Option \*qSwapAxes\*q \*q" Bool \*q
Swap x/y axes. Default: off. Property: "Evdev Axes Swap".
.TP 7
.BI "Option \*qGrabDevice\*q \*q" boolean \*q
Force a grab on the event device. Doing so will ensure that no other driver
can initialise the same device and it will also stop the device from sending
events to /dev/kbd or /dev/input/mice. Events from this device will not be
sent to virtual devices (e.g. rfkill or the Macintosh mouse button emulation).
Default disabled.
.SH SUPPORTED PROPERTIES
The following properties are provided by the
.B evdev
driver.
.TP 7
.BI "Evdev Middle Button Emulation"
1 boolean value (8 bit, 0 or 1).
.TP 7
.BI "Evdev Middle Button Timeout"
1 16-bit positive value.
.TP 7
.BI "Evdev Wheel Emulation"
1 boolean value (8 bit, 0 or 1).
.TP 7
.BI "Evdev Wheel Emulation Axes"
4 8-bit values, order X up, X down, Y up, Y down. 0 disables a value.
.TP 7
.BI "Evdev Wheel Emulation Inertia"
1 16-bit positive value.
.TP 7
.BI "Evdev Wheel Emulation Timeout"
1 16-bit positive value.
.TP 7
.BI "Evdev Wheel Emulation Button"
1 8-bit value, allowed range 0-32, 0 disables the button.
.TP 7
.BI "Evdev Drag Lock Buttons"
8-bit. Either 1 value or pairs of values. Value range 0-32, 0 disables a
value.
.TP 7
.BI "Evdev Axis Inversion"
2 boolean values (8 bit, 0 or 1), order X, Y. 1 inverts the axis.
.BI "Evdev Axis Calibration"
4 32-bit values, order min-x, max-x, min-y, max-y or 0 values to disable
run-time axis calibration. This feature is required for devices that need to
scale to a different coordinate system than originally reported to the X
server, such as touchscreens that require run-time calibration.
.TP 7
.BI "Evdev Axis Swap"
1 boolean values (8 bit, 0 or 1). 1 swaps x/y axes.
.PP
.SH AUTHORS
Zephaniah E. Hull.
.fi
Kristian H\(/ogsberg.
Kristian Høgsberg.
.SH "SEE ALSO"
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__).
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__),
README.mouse.

View File

@@ -26,7 +26,13 @@
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
@DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
@DRIVER_NAME@_drv_la_CFLAGS = -Wall
@DRIVER_NAME@_drv_ladir = @inputdir@
@DRIVER_NAME@_drv_la_SOURCES = evdev.c evdev.h evdev_axes.c evdev_btn.c evdev_key.c
INCLUDES=-I$(top_srcdir)/include/
@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
@DRIVER_NAME@.h \
emuMB.c \
emuWheel.c \
draglock.c

318
src/draglock.c Normal file
View File

@@ -0,0 +1,318 @@
/*
* 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
* 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.
*
*/
/* Draglock code */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <xf86.h>
#include <xf86Xinput.h>
#include <X11/Xatom.h>
#include <exevents.h>
#include <evdev-properties.h>
#include "evdev.h"
#ifdef HAVE_PROPERTIES
static Atom prop_dlock = 0; /* Drag lock buttons. */
#endif
void EvdevDragLockLockButton(InputInfoPtr pInfo, unsigned int button);
/* Setup and configuration code */
void
EvdevDragLockPreInit(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
char *option_string = NULL;
int meta_button = 0;
int lock_button = 0;
char *next_num = NULL;
char *end_str = NULL;
BOOL pairs = FALSE;
option_string = xf86CheckStrOption(pInfo->options, "DragLockButtons",NULL);
if (!option_string)
return;
next_num = option_string;
/* Loop until we hit the end of our option string */
while (next_num != NULL) {
lock_button = 0;
meta_button = strtol(next_num, &end_str, 10);
/* check to see if we found anything */
if (next_num != end_str) {
/* setup for the next number */
next_num = end_str;
} else {
/* we have nothing more to parse, drop out of the loop */
next_num = NULL;
}
/* Check for a button to lock if we have a meta button */
if (meta_button != 0 && next_num != NULL ) {
lock_button = strtol(next_num, &end_str, 10);
/* check to see if we found anything */
if (next_num != end_str) {
/* setup for the next number */
next_num = end_str;
} else {
/* we have nothing more to parse, drop out of the loop */
next_num = NULL;
}
}
/* Ok, let the user know what we found on this look */
if (meta_button != 0) {
if (lock_button == 0) {
if (!pairs) {
/* We only have a meta button */
pEvdev->dragLock.meta = meta_button;
xf86Msg(X_CONFIG, "%s: DragLockButtons : "
"%i as meta\n",
pInfo->name, meta_button);
} else {
xf86Msg(X_ERROR, "%s: DragLockButtons : "
"Incomplete pair specifying button pairs %s\n",
pInfo->name, option_string);
}
} else {
/* Do bounds checking to make sure we don't crash */
if ((meta_button <= EVDEV_MAXBUTTONS) && (meta_button >= 0 ) &&
(lock_button <= EVDEV_MAXBUTTONS) && (lock_button >= 0)) {
xf86Msg(X_CONFIG, "%s: DragLockButtons : %i -> %i\n",
pInfo->name, meta_button, lock_button);
pEvdev->dragLock.lock_pair[meta_button - 1] = lock_button;
pairs=TRUE;
} else {
/* Let the user know something was wrong
with this pair of buttons */
xf86Msg(X_CONFIG, "%s: DragLockButtons : "
"Invalid button pair %i -> %i\n",
pInfo->name, meta_button, lock_button);
}
}
} else {
xf86Msg(X_ERROR, "%s: Found DragLockButtons "
"with invalid lock button string : '%s'\n",
pInfo->name, option_string);
/* This should be the case anyhow, just make sure */
next_num = NULL;
}
/* Check for end of string, to avoid annoying error */
if (next_num != NULL && *next_num == '\0')
next_num = NULL;
}
}
/* Updates DragLock button state and firest button event messges */
void
EvdevDragLockLockButton(InputInfoPtr pInfo, unsigned int button)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
BOOL state=0;
/* update button state */
state = pEvdev->dragLock.lock_state[button - 1] ? FALSE : TRUE;
pEvdev->dragLock.lock_state[button - 1] = state;
xf86PostButtonEvent(pInfo->dev, 0, button, state, 0, 0);
}
/* Filter button presses looking for either a meta button or the
* control of a button pair.
*
* @param button button number (1 for left, 3 for right)
* @param value TRUE if button press, FALSE if release
*
* @return TRUE if the event was swallowed here, FALSE otherwise.
*/
BOOL
EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
if (button == 0)
return FALSE;
/* Do we have a single meta key or
several button pairings? */
if (pEvdev->dragLock.meta != 0) {
if (pEvdev->dragLock.meta == button) {
/* setup up for button lock */
if (value)
pEvdev->dragLock.meta_state = TRUE;
return TRUE;
} else if (pEvdev->dragLock.meta_state) { /* waiting to lock */
pEvdev->dragLock.meta_state = FALSE;
EvdevDragLockLockButton(pInfo, button);
return TRUE;
}
} else if (pEvdev->dragLock.lock_pair[button - 1] && value) {
/* A meta button in a meta/lock pair was pressed */
EvdevDragLockLockButton(pInfo, pEvdev->dragLock.lock_pair[button - 1]);
return TRUE;
}
/* Eat events for buttons that are locked */
if (pEvdev->dragLock.lock_state[button - 1])
return TRUE;
return FALSE;
}
#ifdef HAVE_PROPERTIES
/**
* Set the drag lock property.
* If only one value is supplied, then this is used as the meta button.
* If more than one value is supplied, then each value is the drag lock button
* for the pair. 0 disables a pair.
* i.e. to set bt 3 to draglock button 1, supply 0,0,1
*/
int
EvdevDragLockSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (atom == prop_dlock)
{
int i;
if (val->format != 8 || val->type != XA_INTEGER)
return BadMatch;
/* Don't allow changes while a lock is active */
if (pEvdev->dragLock.meta)
{
if (pEvdev->dragLock.meta_state)
return BadAccess;
} else
{
for (i = 0; i < EVDEV_MAXBUTTONS; i++)
if (pEvdev->dragLock.lock_state[i])
return BadValue;
}
if (val->size == 1)
{
int meta = *((CARD8*)val->data);
if (meta > EVDEV_MAXBUTTONS)
return BadValue;
if (!checkonly)
{
pEvdev->dragLock.meta = meta;
memset(pEvdev->dragLock.lock_pair, 0, sizeof(pEvdev->dragLock.lock_pair));
}
} else
{
CARD8* vals = (CARD8*)val->data;
for (i = 0; i < val->size && i < EVDEV_MAXBUTTONS; i++)
if (vals[i] > EVDEV_MAXBUTTONS)
return BadValue;
if (!checkonly)
{
pEvdev->dragLock.meta = 0;
memset(pEvdev->dragLock.lock_pair, 0, sizeof(pEvdev->dragLock.lock_pair));
for (i = 0; i < val->size && i < EVDEV_MAXBUTTONS; i++)
pEvdev->dragLock.lock_pair[i] = vals[i];
}
}
}
return Success;
}
/**
* Initialise property for drag lock buttons setting.
*/
void
EvdevDragLockInitProperty(DeviceIntPtr dev)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (!dev->button) /* don't init prop for keyboards */
return;
prop_dlock = MakeAtom(EVDEV_PROP_DRAGLOCK, strlen(EVDEV_PROP_DRAGLOCK), TRUE);
if (pEvdev->dragLock.meta)
{
XIChangeDeviceProperty(dev, prop_dlock, XA_INTEGER, 8,
PropModeReplace, 1, &pEvdev->dragLock.meta,
FALSE);
} else {
int highest = 0;
int i;
CARD8 pair[EVDEV_MAXBUTTONS] = {0};
for (i = 0; i < EVDEV_MAXBUTTONS; i++)
{
if (pEvdev->dragLock.lock_pair[i])
highest = i;
pair[i] = pEvdev->dragLock.lock_pair[i];
}
XIChangeDeviceProperty(dev, prop_dlock, XA_INTEGER, 8, PropModeReplace,
highest + 1, pair, FALSE);
}
XISetDevicePropertyDeletable(dev, prop_dlock, FALSE);
XIRegisterPropertyHandler(dev, EvdevDragLockSetProperty, NULL, NULL);
}
#endif

415
src/emuMB.c Normal file
View File

@@ -0,0 +1,415 @@
/*
* 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 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.
*
*/
/* Middle mouse button emulation code. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <X11/Xatom.h>
#include <xf86.h>
#include <xf86Xinput.h>
#include <exevents.h>
#include <evdev-properties.h>
#include "evdev.h"
enum {
MBEMU_DISABLED = 0,
MBEMU_ENABLED,
MBEMU_AUTO
};
#ifdef HAVE_PROPERTIES
static Atom prop_mbemu = 0; /* Middle button emulation on/off property */
static Atom prop_mbtimeout = 0; /* Middle button timeout property */
#endif
/*
* 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 button number (1 for left, 3 for 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 button, BOOL press)
{
EvdevPtr pEvdev = pInfo->private;
int id;
int *btstate;
int ret = FALSE;
if (!pEvdev->emulateMB.enabled)
return ret;
if (button == 2) {
EvdevMBEmuEnable(pInfo, FALSE);
return ret;
}
/* don't care about other buttons */
if (button != 1 && button != 3)
return ret;
btstate = &pEvdev->emulateMB.buttonstate;
if (press)
*btstate |= (button == 1) ? 0x1 : 0x2;
else
*btstate &= (button == 1) ? ~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 %s.\n",
pInfo->name, (pEvdev->emulateMB.enabled) ? "on" : "off");
}
pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options,
"Emulate3Timeout", 50);
}
void
EvdevMBEmuOn(InputInfoPtr pInfo)
{
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;
}
#ifdef HAVE_PROPERTIES
int
EvdevMBEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (atom == prop_mbemu)
{
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
pEvdev->emulateMB.enabled = *((BOOL*)val->data);
} else if (atom == prop_mbtimeout)
{
if (val->format != 32 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
pEvdev->emulateMB.timeout = *((CARD32*)val->data);
}
return Success;
}
/**
* Initialise property for MB emulation on/off.
*/
void
EvdevMBEmuInitProperty(DeviceIntPtr dev)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
int rc;
if (!dev->button) /* don't init prop for keyboards */
return;
prop_mbemu = MakeAtom(EVDEV_PROP_MIDBUTTON, strlen(EVDEV_PROP_MIDBUTTON), TRUE);
rc = XIChangeDeviceProperty(dev, prop_mbemu, XA_INTEGER, 8,
PropModeReplace, 1,
&pEvdev->emulateMB.enabled,
FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_mbemu, FALSE);
prop_mbtimeout = MakeAtom(EVDEV_PROP_MIDBUTTON_TIMEOUT,
strlen(EVDEV_PROP_MIDBUTTON_TIMEOUT),
TRUE);
rc = XIChangeDeviceProperty(dev, prop_mbtimeout, XA_INTEGER, 32, PropModeReplace, 1,
&pEvdev->emulateMB.timeout, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_mbtimeout, FALSE);
XIRegisterPropertyHandler(dev, EvdevMBEmuSetProperty, NULL, NULL);
}
#endif

466
src/emuWheel.c Normal file
View File

@@ -0,0 +1,466 @@
/*
* 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 <X11/Xatom.h>
#include <xf86.h>
#include <xf86Xinput.h>
#include <exevents.h>
#include <evdev-properties.h>
#include "evdev.h"
#define WHEEL_NOT_CONFIGURED 0
#ifdef HAVE_PROPERTIES
static Atom prop_wheel_emu = 0;
static Atom prop_wheel_axismap = 0;
static Atom prop_wheel_inertia = 0;
static Atom prop_wheel_timeout = 0;
static Atom prop_wheel_button = 0;
#endif
/* 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;
int ms;
/* 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;
if (value)
/* Start the timer when the button is pressed */
pEvdev->emulateWheel.expires = pEvdev->emulateWheel.timeout +
GetTimeInMillis();
else {
ms = pEvdev->emulateWheel.expires - GetTimeInMillis();
if (ms > 0) {
/*
* If the button is released early enough emit the button
* press/release events
*/
xf86PostButtonEvent(pInfo->dev, 0, button, 1, 0, 0);
xf86PostButtonEvent(pInfo->dev, 0, button, 0, 0, 0);
}
}
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;
int ms;
/* 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) {
/* Just return if the timeout hasn't expired yet */
ms = pEvdev->emulateWheel.expires - GetTimeInMillis();
if (ms > 0)
return TRUE;
/* 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 <= EVDEV_MAXBUTTONS)) &&
((down_button > 0) && (down_button <= EVDEV_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;
char val[4];
int wheelButton;
int inertia;
int timeout;
val[0] = 0;
val[1] = 0;
if (xf86SetBoolOption(pInfo->options, "EmulateWheel", FALSE)) {
pEvdev->emulateWheel.enabled = TRUE;
} else
pEvdev->emulateWheel.enabled = FALSE;
wheelButton = xf86SetIntOption(pInfo->options, "EmulateWheelButton", 4);
if ((wheelButton < 0) || (wheelButton > EVDEV_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;
}
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;
timeout = xf86SetIntOption(pInfo->options, "EmulateWheelTimeout", 200);
if (timeout < 0) {
xf86Msg(X_WARNING, "%s: Invalid EmulateWheelTimeout value: %d\n",
pInfo->name, timeout);
xf86Msg(X_WARNING, "%s: Using built-in timeout value.\n",
pInfo->name);
timeout = 200;
}
pEvdev->emulateWheel.timeout = timeout;
/* 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, "
"EmulateWheelTimeout: %d\n",
pInfo->name, pEvdev->emulateWheel.button, inertia, timeout);
}
#ifdef HAVE_PROPERTIES
int
EvdevWheelEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (atom == prop_wheel_emu)
{
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
{
pEvdev->emulateWheel.enabled = *((BOOL*)val->data);
/* Don't enable with zero inertia, otherwise we may get stuck in an
* infinite loop */
if (pEvdev->emulateWheel.inertia <= 0)
{
pEvdev->emulateWheel.inertia = 10;
/* We may get here before the property is actually enabled */
if (prop_wheel_inertia)
XIChangeDeviceProperty(dev, prop_wheel_inertia, XA_INTEGER,
16, PropModeReplace, 1,
&pEvdev->emulateWheel.inertia, TRUE);
}
/* Don't enable with negative timeout */
if (pEvdev->emulateWheel.timeout < 0)
{
pEvdev->emulateWheel.timeout = 200;
XIChangeDeviceProperty(dev, prop_wheel_timeout, XA_INTEGER, 16,
PropModeReplace, 1,
&pEvdev->emulateWheel.timeout, TRUE);
}
}
}
else if (atom == prop_wheel_button)
{
int bt = *((CARD8*)val->data);
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (bt < 0 || bt >= EVDEV_MAXBUTTONS)
return BadValue;
if (!checkonly)
pEvdev->emulateWheel.button = bt;
} else if (atom == prop_wheel_axismap)
{
if (val->format != 8 || val->size != 4 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
{
pEvdev->emulateWheel.X.up_button = *((CARD8*)val->data);
pEvdev->emulateWheel.X.down_button = *(((CARD8*)val->data) + 1);
pEvdev->emulateWheel.Y.up_button = *(((CARD8*)val->data) + 2);
pEvdev->emulateWheel.Y.down_button = *(((CARD8*)val->data) + 3);
}
} else if (atom == prop_wheel_inertia)
{
int inertia = *((CARD16*)val->data);
if (val->format != 16 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (inertia < 0)
return BadValue;
if (!checkonly)
pEvdev->emulateWheel.inertia = inertia;
} else if (atom == prop_wheel_timeout)
{
int timeout = *((CARD16*)val->data);
if (val->format != 16 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (timeout < 0)
return BadValue;
if (!checkonly)
pEvdev->emulateWheel.timeout = timeout;
}
return Success;
}
void
EvdevWheelEmuInitProperty(DeviceIntPtr dev)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
int rc = TRUE;
char vals[4];
if (!dev->button) /* don't init prop for keyboards */
return;
prop_wheel_emu = MakeAtom(EVDEV_PROP_WHEEL, strlen(EVDEV_PROP_WHEEL), TRUE);
rc = XIChangeDeviceProperty(dev, prop_wheel_emu, XA_INTEGER, 8,
PropModeReplace, 1,
&pEvdev->emulateWheel.enabled, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_wheel_emu, FALSE);
vals[0] = pEvdev->emulateWheel.X.up_button;
vals[1] = pEvdev->emulateWheel.X.down_button;
vals[2] = pEvdev->emulateWheel.Y.up_button;
vals[3] = pEvdev->emulateWheel.Y.down_button;
prop_wheel_axismap = MakeAtom(EVDEV_PROP_WHEEL_AXES, strlen(EVDEV_PROP_WHEEL_AXES), TRUE);
rc = XIChangeDeviceProperty(dev, prop_wheel_axismap, XA_INTEGER, 8,
PropModeReplace, 4, vals, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_wheel_axismap, FALSE);
prop_wheel_inertia = MakeAtom(EVDEV_PROP_WHEEL_INERTIA, strlen(EVDEV_PROP_WHEEL_INERTIA), TRUE);
rc = XIChangeDeviceProperty(dev, prop_wheel_inertia, XA_INTEGER, 16,
PropModeReplace, 1,
&pEvdev->emulateWheel.inertia, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_wheel_inertia, FALSE);
prop_wheel_timeout = MakeAtom(EVDEV_PROP_WHEEL_TIMEOUT, strlen(EVDEV_PROP_WHEEL_TIMEOUT), TRUE);
rc = XIChangeDeviceProperty(dev, prop_wheel_timeout, XA_INTEGER, 16,
PropModeReplace, 1,
&pEvdev->emulateWheel.timeout, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_wheel_timeout, FALSE);
prop_wheel_button = MakeAtom(EVDEV_PROP_WHEEL_BUTTON, strlen(EVDEV_PROP_WHEEL_BUTTON), TRUE);
rc = XIChangeDeviceProperty(dev, prop_wheel_button, XA_INTEGER, 8,
PropModeReplace, 1,
&pEvdev->emulateWheel.button, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_wheel_button, FALSE);
XIRegisterPropertyHandler(dev, EvdevWheelEmuSetProperty, NULL, NULL);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,272 +1,178 @@
/*
* Copyright © 2006-2007 Zephaniah E. Hull
* Copyright © 2004 Red Hat, Inc.
* Copyright © 2004-2008 Red Hat, Inc.
* Copyright © 2008 University of South Australia
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Soft-
* ware"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, provided that the above copyright
* notice(s) and this permission notice appear in all copies of the Soft-
* ware and that both the above copyright notice(s) and this permission
* notice appear in supporting documentation.
* 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
* QUENTIAL 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 PERFOR-
* MANCE OF THIS SOFTWARE.
*
* Except as contained in this notice, the name of a copyright holder shall
* not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization of
* the copyright holder.
* 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:
* Zephaniah E. Hull (warp@aehallh.com)
* Kristian Høgsberg (krh@redhat.com)
* Kristian Høgsberg (krh@redhat.com)
* Adam Jackson (ajax@redhat.com)
* Peter Hutterer (peter@cs.unisa.edu.au)
*/
#ifndef __EVDEV_H
#define __EVDEV_H
#define _XF86_ANSIC_H
#define XF86_LIBC_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef EVDEV_H
#define EVDEV_H
#include <linux/input.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <linux/types.h>
#include <xf86Xinput.h>
#include <xf86_OSproc.h>
#ifndef BITS_PER_LONG
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
#ifdef XKB
#include <xkbstr.h>
#endif
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
#define LONG(x) ((x)/BITS_PER_LONG)
#define MASK(x) (1UL << ((x) & (BITS_PER_LONG - 1)))
#ifndef test_bit
#define test_bit(bit, array) (!!(array[LONG(bit)] & MASK(bit)))
#ifndef EV_CNT /* linux 2.4 kernels and earlier lack _CNT defines */
#define EV_CNT (EV_MAX+1)
#endif
#ifndef set_bit
#define set_bit(bit, array) (array[LONG(bit)] |= MASK(bit))
#ifndef KEY_CNT
#define KEY_CNT (KEY_MAX+1)
#endif
#ifndef clear_bit
#define clear_bit(bit, array) (array[LONG(bit)] &= ~MASK(bit))
#ifndef REL_CNT
#define REL_CNT (REL_MAX+1)
#endif
#ifndef ABS_CNT
#define ABS_CNT (ABS_MAX+1)
#endif
#ifndef LED_CNT
#define LED_CNT (LED_MAX+1)
#endif
#define EVDEV_MAXBUTTONS 32
#include <X11/extensions/XKB.h>
#include <X11/extensions/XKBstr.h>
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
#define HAVE_PROPERTIES 1
#endif
/*
* At the moment, ABS_MAX is larger then REL_MAX.
* As they are the only two providors of axes, ABS_MAX is it.
*/
#define AXES_MAX ABS_MAX
#define LONG_BITS (sizeof(long) * 8)
/* Number of longs needed to hold the given number of bits */
#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
#define BTN_MAX 96
struct _evdevDevice;
/*
* FIXME: The mode option here is a kludge.
* It can be 0 (rel mode), 1 (abs mode), or -1 (input side has no clue).
*
* Worse, it arguably shouldn't even be the sender that decides here.
* And only the Axes targets and sources care at all right now.
*/
typedef void (*evdev_map_func_f)(InputInfoPtr pInfo, int value, int mode, void *map_data);
/* axis specific data for wheel emulation */
typedef struct {
int up_button;
int down_button;
int traveled_distance;
} WheelAxis, *WheelAxisPtr;
typedef struct {
unsigned long ev[NBITS(EV_MAX)];
unsigned long key[NBITS(KEY_MAX)];
unsigned long rel[NBITS(REL_MAX)];
unsigned long abs[NBITS(ABS_MAX)];
unsigned long msc[NBITS(MSC_MAX)];
unsigned long led[NBITS(LED_MAX)];
unsigned long snd[NBITS(SND_MAX)];
unsigned long ff[NBITS(FF_MAX)];
} evdevBitsRec, *evdevBitsPtr;
const char *device;
int grabDevice; /* grab the event device? */
int screen;
int min_x, min_y, max_x, max_y;
int abs_x, abs_y, old_x, old_y;
int flags;
int tool;
int buttons; /* number of buttons */
BOOL swap_axes;
BOOL invert_x;
BOOL invert_y;
#define EV_BTN_B_PRESENT (1<<0)
/* 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;
struct {
int meta; /* meta key to lock any button */
BOOL meta_state; /* meta_button state */
unsigned int lock_pair[EVDEV_MAXBUTTONS]; /* specify a meta/lock pair */
BOOL lock_state[EVDEV_MAXBUTTONS]; /* state of any locked buttons */
} dragLock;
struct {
BOOL enabled;
int button;
int button_state;
int inertia;
WheelAxis X;
WheelAxis Y;
Time expires; /* time of expiry */
Time timeout;
} emulateWheel;
/* run-time calibration */
struct {
int min_x;
int max_x;
int min_y;
int max_y;
} calibration;
typedef struct {
int real_buttons;
int buttons;
int b_flags[BTN_MAX];
void *b_map_data[ABS_MAX];
evdev_map_func_f b_map[BTN_MAX];
void (*callback[BTN_MAX])(InputInfoPtr pInfo, int button, int value);
} evdevBtnRec, *evdevBtnPtr;
unsigned char btnmap[32]; /* config-file specified button mapping */
#define EV_ABS_V_PRESENT (1<<0)
#define EV_ABS_V_M_AUTO (1<<1)
#define EV_ABS_V_M_REL (1<<2)
#define EV_ABS_V_INVERT (1<<3)
#define EV_ABS_V_RESET (1<<4)
#define EV_ABS_V_USE_TOUCH (1<<5)
int reopen_attempts; /* max attempts to re-open after read failure */
int reopen_left; /* number of attempts left to re-open the device */
OsTimerPtr reopen_timer;
#define EV_ABS_USE_TOUCH (1<<0)
#define EV_ABS_TOUCH (1<<1)
#define EV_ABS_UPDATED (1<<2)
/* Cached info from device. */
char name[1024];
long bitmask[NLONGS(EV_CNT)];
long key_bitmask[NLONGS(KEY_CNT)];
long rel_bitmask[NLONGS(REL_CNT)];
long abs_bitmask[NLONGS(ABS_CNT)];
long led_bitmask[NLONGS(LED_CNT)];
struct input_absinfo absinfo[ABS_CNT];
typedef struct {
int flags;
int axes;
int v[ABS_MAX];
int v_flags[ABS_MAX];
void *v_map_data[ABS_MAX];
evdev_map_func_f v_map[ABS_MAX];
} evdevAbsRec, *evdevAbsPtr;
/* minor/major number */
dev_t min_maj;
} EvdevRec, *EvdevPtr;
#define EV_REL_V_PRESENT (1<<0)
#define EV_REL_V_INVERT (1<<1)
#define EV_REL_UPDATED (1<<0)
unsigned int EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code);
typedef struct {
int flags;
int v_flags[REL_MAX];
int v[REL_MAX];
int axes;
void *v_map_data[REL_MAX];
evdev_map_func_f v_map[REL_MAX];
} evdevRelRec, *evdevRelPtr;
/* 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 EvdevMBEmuOn(InputInfoPtr);
void EvdevMBEmuFinalize(InputInfoPtr);
void EvdevMBEmuEnable(InputInfoPtr, BOOL);
#define EV_AXES_V_M_ABS (1<<0)
#define EV_AXES_V_M_REL (1<<1)
#define EV_AXES_V_PRESENT (1<<2)
#define EV_AXES_V_UPDATED (1<<3)
/* Mouse Wheel emulation */
void EvdevWheelEmuPreInit(InputInfoPtr pInfo);
BOOL EvdevWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int value);
BOOL EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv);
#define EV_AXES_V_M_MASK (EV_AXES_V_M_ABS | EV_AXES_V_M_REL)
/* Draglock code */
void EvdevDragLockPreInit(InputInfoPtr pInfo);
BOOL EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value);
#define EV_AXES_UPDATED (1<<0)
typedef struct {
int axes;
int flags;
int v_flags[AXES_MAX];
int v_min[AXES_MAX];
int v_max[AXES_MAX];
int v[AXES_MAX];
int rotation;
float rot_sin, rot_cos;
int x, y;
} evdevAxesRec, *evdevAxesPtr;
typedef struct {
char *xkb_rules;
char *xkb_model;
char *xkb_layout;
char *xkb_variant;
char *xkb_options;
XkbComponentNamesRec xkbnames;
} evdevKeyRec, *evdevKeyPtr;
typedef struct _evdevState {
Bool can_grab;
Bool sync;
evdevBtnPtr btn;
evdevAbsPtr abs;
evdevRelPtr rel;
evdevKeyPtr key;
evdevAxesPtr axes;
} evdevStateRec, *evdevStatePtr;
typedef struct _evdevDevice {
const char *device;
evdevBitsRec bits;
evdevStateRec state;
} evdevDeviceRec, *evdevDevicePtr;
int EvdevBtnInit (DeviceIntPtr device);
int EvdevBtnOn (DeviceIntPtr device);
int EvdevBtnOff (DeviceIntPtr device);
int EvdevBtnNew0(InputInfoPtr pInfo);
int EvdevBtnNew1(InputInfoPtr pInfo);
void EvdevBtnProcess (InputInfoPtr pInfo, struct input_event *ev);
void EvdevBtnPostFakeClicks(InputInfoPtr pInfo, int button, int count);
int EvdevBtnFind (InputInfoPtr pInfo, const char *button);
int EvdevBtnExists (InputInfoPtr pInfo, int button);
int EvdevAxesInit (DeviceIntPtr device);
int EvdevAxesOn (DeviceIntPtr device);
int EvdevAxesOff (DeviceIntPtr device);
int EvdevAxesNew0(InputInfoPtr pInfo);
int EvdevAxesNew1(InputInfoPtr pInfo);
void EvdevAxesAbsProcess (InputInfoPtr pInfo, struct input_event *ev);
void EvdevAxesRelProcess (InputInfoPtr pInfo, struct input_event *ev);
void EvdevAxesSynRep (InputInfoPtr pInfo);
void EvdevAxesSynCfg (InputInfoPtr pInfo);
int EvdevKeyInit (DeviceIntPtr device);
int EvdevKeyNew (InputInfoPtr pInfo);
int EvdevKeyOn (DeviceIntPtr device);
int EvdevKeyOff (DeviceIntPtr device);
void EvdevKeyProcess (InputInfoPtr pInfo, struct input_event *ev);
/*
* Option handling stuff.
*/
typedef struct evdev_option_token_s {
const char *str;
struct evdev_option_token_s *chain;
struct evdev_option_token_s *next;
} evdev_option_token_t;
typedef Bool (*evdev_parse_opt_func_f)(InputInfoPtr pInfo, const char *name, evdev_option_token_t *token, int *flags);
typedef Bool (*evdev_parse_map_func_f)(InputInfoPtr pInfo,
const char *name,
evdev_option_token_t *option,
void **map_data, evdev_map_func_f *map_func);
evdev_option_token_t *EvdevTokenize (const char *option, const char *tokens);
void EvdevFreeTokens (evdev_option_token_t *token);
Bool EvdevParseMapToRelAxis (InputInfoPtr pInfo,
const char *name,
evdev_option_token_t *option,
void **map_data, evdev_map_func_f *map_func);
Bool EvdevParseMapToAbsAxis (InputInfoPtr pInfo,
const char *name,
evdev_option_token_t *option,
void **map_data, evdev_map_func_f *map_func);
Bool
EvdevParseMapToButton (InputInfoRec *pInfo,
const char *name,
evdev_option_token_t *option,
void **map_data, evdev_map_func_f *map_func);
Bool
EvdevParseMapToButtons (InputInfoRec *pInfo,
const char *name,
evdev_option_token_t *option,
void **map_data, evdev_map_func_f *map_func);
typedef struct {
char *name;
evdev_parse_map_func_f func;
} evdev_map_parsers_t;
extern evdev_map_parsers_t evdev_map_parsers[];
Bool EvdevParseMapOption (InputInfoRec *pInfo, char *option, char *def, void **map_data, evdev_map_func_f *map_func);
#endif /* __EVDEV_H */
#ifdef HAVE_PROPERTIES
void EvdevMBEmuInitProperty(DeviceIntPtr);
void EvdevWheelEmuInitProperty(DeviceIntPtr);
void EvdevDragLockInitProperty(DeviceIntPtr);
#endif
#endif

View File

@@ -1,930 +0,0 @@
/*
* Copyright © 2006-2007 Zephaniah E. Hull
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Soft-
* ware"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, provided that the above copyright
* notice(s) and this permission notice appear in all copies of the Soft-
* ware and that both the above copyright notice(s) and this permission
* notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
* QUENTIAL 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 PERFOR-
* MANCE OF THIS SOFTWARE.
*
* Except as contained in this notice, the name of a copyright holder shall
* not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization of
* the copyright holder.
*
* Author: Zephaniah E. Hull (warp@aehallh.com)
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <X11/keysym.h>
#include <X11/XF86keysym.h>
#include <X11/extensions/XIproto.h>
#include <string.h>
#include "evdev.h"
#include <xf86.h>
#include <xf86Module.h>
#include <mipointer.h>
#include <xf86_OSproc.h>
#undef DEBUG
static char *rel_axis_names[] = {
"X",
"Y",
"Z",
"RX",
"RY",
"RZ",
"HWHEEL",
"DIAL",
"WHEEL",
"MISC",
"10",
"11",
"12",
"13",
"14",
"15",
NULL
};
static char *abs_axis_names[] = {
"X",
"Y",
"Z",
"RX",
"RY",
"RZ",
"THROTTLE",
"RUDDER",
"WHEEL",
"GAS",
"BRAKE",
"11",
"12",
"13",
"14",
"15",
"HAT0X",
"HAT0Y",
"HAT1X",
"HAT1Y",
"HAT2X",
"HAT2Y",
"HAT3X",
"HAT3Y",
"PRESSURE",
"TILT_X",
"TILT_Y",
"TOOL_WIDTH",
"VOLUME",
"29",
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"MISC",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"60",
"61",
"62",
NULL
};
static void EvdevAxesTouchCallback (InputInfoPtr pInfo, int button, int value);
void
EvdevAxesMapAxis (InputInfoPtr pInfo, int value, int mode, void *map_data)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
evdevAxesPtr axes = state->axes;
long map = (long) map_data;
if (map >= AXES_MAX || !axes || !(axes->v_flags[map] & (EV_AXES_V_M_ABS | EV_AXES_V_M_REL)))
return;
axes->v[map] = value;
if (mode == 0) {
axes->v_flags[map] &= ~EV_AXES_V_M_ABS;
axes->v_flags[map] |= EV_AXES_V_M_REL;
} else if (mode == 1) {
axes->v_flags[map] &= ~EV_AXES_V_M_REL;
axes->v_flags[map] |= EV_AXES_V_M_ABS;
}
axes->v_flags[map] |= EV_AXES_V_UPDATED;
axes->flags |= EV_AXES_UPDATED;
}
static Bool
EvdevParseRelOptions (InputInfoPtr pInfo, const char *name, evdev_option_token_t *option, int *flags)
{
if (!option)
return 0;
for (; option; option = option->next) {
if (!strcasecmp (option->str, "invert"))
*flags |= EV_REL_V_INVERT;
else
xf86Msg(X_ERROR, "%s: %s unknown relative option '%s'.\n", pInfo->name, name, option->str);
}
*flags |= EV_REL_V_PRESENT;
return 1;
}
static Bool
EvdevParseAbsOptions (InputInfoPtr pInfo, const char *name, evdev_option_token_t *option, int *flags)
{
if (!option)
return 0;
for (; option; option = option->next) {
if (!strcasecmp (option->str, "invert"))
*flags |= EV_ABS_V_INVERT;
else if (!strcasecmp (option->str, "use_touch"))
*flags |= EV_ABS_V_USE_TOUCH;
else if (!strcasecmp (option->str, "mode_auto"))
*flags |= EV_ABS_V_M_AUTO;
else if (!strcasecmp (option->str, "mode_rel"))
*flags |= EV_ABS_V_M_REL;
else
xf86Msg(X_ERROR, "%s: %s unknown absolute option '%s'.\n", pInfo->name, name, option->str);
}
*flags |= EV_ABS_V_PRESENT;
return 1;
}
Bool
EvdevParseMapToRelAxis (InputInfoPtr pInfo,
const char *name,
evdev_option_token_t *option,
void **map_data, evdev_map_func_f *map_func)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
evdevAxesPtr axes = state->axes;
long i;
errno = 0;
i = strtol (option->str, NULL, 0);
if (errno) {
for (i = 0; rel_axis_names[i]; i++) {
if (!strcmp (option->str, rel_axis_names[i]))
break;
}
if (!rel_axis_names[i])
return 0;
}
if ((i < 0) || (i > AXES_MAX))
return 0;
if (axes->v_flags[i] & EV_AXES_V_PRESENT)
return 0;
axes->v_flags[i] = EV_AXES_V_M_REL | EV_AXES_V_PRESENT;
*map_data = (void *) i;
*map_func = EvdevAxesMapAxis;
return 1;
}
Bool
EvdevParseMapToAbsAxis (InputInfoPtr pInfo,
const char *name,
evdev_option_token_t *option,
void **map_data, evdev_map_func_f *map_func)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
evdevAxesPtr axes = state->axes;
long i;
errno = 0;
i = strtol (option->str, NULL, 0);
if (errno) {
for (i = 0; abs_axis_names[i]; i++) {
if (!strcmp (option->str, abs_axis_names[i]))
break;
}
if (!abs_axis_names[i]) {
xf86Msg (X_ERROR, "%s: %s: No axis named '%s'.\n", pInfo->name, name, option->str);
return 0;
}
}
if ((i < 0) || (i > AXES_MAX)) {
xf86Msg (X_ERROR, "%s: %s: Axis %ld out of range.\n", pInfo->name, name, i);
return 0;
}
if (axes->v_flags[i] & EV_AXES_V_PRESENT) {
xf86Msg (X_ERROR, "%s: %s: Axis %ld already claimed.\n", pInfo->name, name, i);
return 0;
}
option = option->next;
if (!option) {
xf86Msg (X_ERROR, "%s: %s: No min.\n", pInfo->name, name);
return 0;
}
errno = 0;
axes->v_min[i] = strtol (option->str, NULL, 0);
if (errno) {
xf86Msg (X_ERROR, "%s: %s: Unable to parse '%s' as min. (%s)\n", pInfo->name, name, option->str, strerror(errno));
return 0;
}
option = option->next;
if (!option) {
xf86Msg (X_ERROR, "%s: %s: No max.\n", pInfo->name, name);
return 0;
}
errno = 0;
axes->v_max[i] = strtol (option->str, NULL, 0);
if (errno) {
xf86Msg (X_ERROR, "%s: %s: Unable to parse '%s' as max. (%s)\n", pInfo->name, name, option->str, strerror(errno));
return 0;
}
axes->v_flags[i] = EV_AXES_V_M_ABS | EV_AXES_V_PRESENT;
*map_data = (void *) i;
*map_func = EvdevAxesMapAxis;
return 1;
}
static Bool
EvdevConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
int v3, int v4, int v5, int *x, int *y)
{
if (first == 0) {
*x = v0;
*y = v1;
return TRUE;
} else
return FALSE;
}
/*
* Rotation and rep code, this is a mess and much of it needs to live in mi/
* after a cleanup.
*/
static void
EvdevAxesDoRotation (InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
evdevAxesPtr axes = state->axes;
DeviceIntPtr dev = pInfo->dev;
AbsoluteClassRec *dabs = dev->absolute;
/*
* Rotation.
* Cache the sine and cosine results so we're not doing it every time.
*/
if (dabs->rotation != axes->rotation || (axes->rot_cos == axes->rot_sin)) {
axes->rotation = dabs->rotation % 360;
axes->rot_cos = cos ( ((float) axes->rotation) * (M_PI/180));
axes->rot_sin = sin ( ((float) axes->rotation) * (M_PI/180));
}
if (axes->rotation) {
float x = axes->v[0], y = axes->v[1];
axes->v[0] = (x * axes->rot_cos) - (y * axes->rot_sin);
axes->v[1] = (y * axes->rot_cos) + (x * axes->rot_sin);
axes->v_flags[0] |= EV_AXES_V_UPDATED;
axes->v_flags[1] |= EV_AXES_V_UPDATED;
#if DEBUG
xf86Msg(X_ERROR, "%s %d (%s): rotation=%d, cos=%f, sin=%f, x=%f, y=%f, v[0]=%d, v[1]=%d\n", __FILE__, __LINE__, __FUNCTION__,
axes->rotation, axes->rot_cos, axes->rot_sin, x, y, axes->v[0], axes->v[1]);
#endif
}
}
/*
* Cx - raw data from touch screen
* Sxhigh - scaled highest dimension
* (remember, this is of rows - 1 because of 0 origin)
* Sxlow - scaled lowest dimension
* Rxhigh - highest raw value from touch screen calibration
* Rxlow - lowest raw value from touch screen calibration
*
* This function is the same for X or Y coordinates.
* You may have to reverse the high and low values to compensate for
* different orgins on the touch screen vs X.
*/
_X_EXPORT int
EvdevScaleAxis(int Cx,
int Sxlow,
int Sxhigh,
int Rxlow,
int Rxhigh)
{
int X;
int dSx = Sxhigh - Sxlow;
int dRx = Rxhigh - Rxlow;
/* This is +, because Cx is negitive, so we're really subtracting. */
if (Cx < 0)
Cx = Rxhigh + Cx;
dSx = Sxhigh - Sxlow;
if (dRx) {
X = ((dSx * (Cx - Rxlow)) / dRx) + Sxlow;
}
else {
X = 0;
ErrorF ("Divide by Zero in evdevScaleAxis");
}
if (X < Sxlow)
X = Sxlow;
if (X > Sxhigh)
X = Sxhigh;
return (X);
}
void
EvdevAxesSynRep (InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
evdevAxesPtr axes = state->axes;
DeviceIntPtr dev = pInfo->dev;
AbsoluteClassRec *dabs = dev->absolute;
int i, start, run, mode;
if (!axes || !(axes->flags & EV_AXES_UPDATED))
return;
start = 0;
mode = 0;
run = 0;
/*
* This handles most, but not all, of the ABS_CALIB and ABS_AREA
* additions to XInput 1.0.
*
* Note, we do this if both X and Y are set to absolute, or a more
* limited subset if both X and Y are relative, we don't do anything
* if we lack X or Y, or if they are not both set to both be ABS or REL.
*/
if (axes->axes >= 2 && dabs) {
if ((axes->v_flags[0] & EV_AXES_V_M_ABS) &&
(axes->v_flags[1] & EV_AXES_V_M_ABS) &&
((axes->v_flags[0] & EV_AXES_V_UPDATED) ||
(axes->v_flags[1] & EV_AXES_V_UPDATED))
) {
int width, height, min_x, max_x, min_y, max_y;
if (axes->v_flags[0] & EV_AXES_V_UPDATED) axes->x = axes->v[0];
else axes->v[0] = axes->x;
if (axes->v_flags[1] & EV_AXES_V_UPDATED) axes->y = axes->v[1];
else axes->v[1] = axes->y;
if (dabs->width > 0)
width = dabs->width;
else
width = screenInfo.screens[dabs->screen]->width;
if (dabs->height > 0)
height = dabs->height;
else
height = screenInfo.screens[dabs->screen]->height;
if (dabs->flip_x)
axes->v[0] = dabs->max_x - axes->v[0];
if (dabs->flip_y)
axes->v[1] = dabs->max_y - axes->v[1];
/*
* In some cases we need to swap width and height.
* This depends on the rotation.
*/
if ( (axes->rotation >= 45 && axes->rotation < 135) ||
(axes->rotation >= 225 && axes->rotation < 315)) {
min_x = dabs->min_y;
max_x = dabs->max_y;
min_y = dabs->min_x;
max_y = dabs->max_x;
} else {
min_x = dabs->min_x;
max_x = dabs->max_x;
min_y = dabs->min_y;
max_y = dabs->max_y;
}
EvdevAxesDoRotation (pInfo);
axes->v[0] = EvdevScaleAxis (axes->v[0], 0, width, min_x, max_x);
axes->v[1] = EvdevScaleAxis (axes->v[1], 0, height, min_y, max_y);
axes->v[0] += dabs->offset_x;
axes->v[1] += dabs->offset_y;
xf86XInputSetScreen (pInfo, dabs->screen, axes->v[0], axes->v[1]);
} else if ((axes->v_flags[0] & EV_AXES_V_M_REL) &&
(axes->v_flags[1] & EV_AXES_V_M_REL) &&
((axes->v_flags[0] & EV_AXES_V_UPDATED) ||
(axes->v_flags[1] & EV_AXES_V_UPDATED))
) {
if (axes->v_flags[0] & EV_AXES_V_UPDATED) axes->x = axes->v[0];
else axes->v[0] = axes->x;
if (axes->v_flags[1] & EV_AXES_V_UPDATED) axes->y = axes->v[1];
else axes->v[1] = axes->y;
if (dabs->flip_x)
axes->v[0] = -axes->v[0];
if (dabs->flip_y)
axes->v[1] = -axes->v[1];
EvdevAxesDoRotation (pInfo);
}
}
#if DEBUG
xf86Msg(X_ERROR, "%s %d (%s): v[0]=%d%s%s, v[1]=%d%s%s, v[2]=%d%s%s\n", __FILE__, __LINE__, __FUNCTION__,
axes->v[0],
axes->v_flags[0] & EV_AXES_V_M_ABS ? "!" : "",
axes->v_flags[0] & EV_AXES_V_UPDATED ? "*" : "",
axes->v[1],
axes->v_flags[1] & EV_AXES_V_M_ABS ? "!" : "",
axes->v_flags[1] & EV_AXES_V_UPDATED ? "*" : "",
axes->v[2],
axes->v_flags[2] & EV_AXES_V_M_ABS ? "!" : "",
axes->v_flags[2] & EV_AXES_V_UPDATED ? "*" : "");
#endif
for (i = 0; i < axes->axes; i++) {
if (axes->v_flags[i] & EV_AXES_V_UPDATED) {
if (run) {
if (mode != (axes->v_flags[i] & EV_AXES_V_M_MASK)) {
mode = (mode == EV_AXES_V_M_ABS);
#if DEBUG
xf86Msg(X_ERROR, "%s %d (%s): mode=%d, start=%d, i - start=%d\n", __FILE__, __LINE__, __FUNCTION__,
mode, start, i - start);
#endif
xf86PostMotionEventP (pInfo->dev, mode, start, i - start, axes->v + start);
start = i;
mode = axes->v_flags[i] & EV_AXES_V_M_MASK;
}
} else {
start = i;
mode = axes->v_flags[i] & EV_AXES_V_M_MASK;
}
run = 1;
axes->v_flags[i] &= ~EV_AXES_V_UPDATED;
} else if (run) {
mode = (mode == EV_AXES_V_M_ABS);
xf86PostMotionEventP (pInfo->dev, mode, start, i - start, axes->v + start);
run = 0;
}
}
if (run) {
mode = (mode == EV_AXES_V_M_ABS);
xf86PostMotionEventP (pInfo->dev, mode, start, i - start, axes->v + start);
}
}
/*
* End rotation and rep code, this is a mess and much of it needs to live in mi/
* after a cleanup.
*/
void
EvdevAxesSynCfg (InputInfoPtr pInfo)
{
/* EvdevAxesAbsSynCfg (pInfo);*/
/* EvdevAxesRelSynCfg (pInfo);*/
}
void
EvdevAxesAbsProcess (InputInfoPtr pInfo, struct input_event *ev)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
evdevAbsRec *abs = state->abs;
int value, v_flags, is_rel;
if (ev->code >= ABS_MAX || !abs->v_map[ev->code])
return;
value = ev->value;
v_flags = abs->v_flags[ev->code];
if ((v_flags & EV_ABS_V_USE_TOUCH) && !(state->abs->flags & EV_ABS_TOUCH))
return;
#if 0
if (v_flags & EV_ABS_V_INVERT)
value = -value;
#endif
if (v_flags & EV_ABS_V_M_REL)
is_rel = 1;
else if ((v_flags & EV_ABS_V_M_AUTO) && pInfo->dev->valuator->mode == Relative)
is_rel = 1;
else
is_rel = 0;
if (is_rel) {
if ((v_flags & EV_ABS_V_RESET) && value != abs->v[ev->code]) {
abs->v_flags[ev->code] &= ~EV_ABS_V_RESET;
} else
abs->v_map[ev->code](pInfo, value - abs->v[ev->code], 0, abs->v_map_data[ev->code]);
abs->v[ev->code] = value;
} else
abs->v_map[ev->code](pInfo, value, 1, abs->v_map_data[ev->code]);
}
void
EvdevAxesRelProcess (InputInfoPtr pInfo, struct input_event *ev)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
evdevRelRec *rel = state->rel;
int value, v_flags;
if (ev->code >= REL_MAX || !rel->v_map[ev->code])
return;
value = ev->value;
v_flags = rel->v_flags[ev->code];
if (v_flags & EV_REL_V_INVERT)
value = -value;
rel->v_map[ev->code](pInfo, value, 0, rel->v_map_data[ev->code]);
}
int
EvdevAxesOn (DeviceIntPtr device)
{
return Success;
}
int
EvdevAxesOff (DeviceIntPtr device)
{
return Success;
}
static int
EvdevAxisAbsNew(InputInfoPtr pInfo)
{
evdevDeviceRec *pEvdev = pInfo->private;
evdevStateRec *state = &pEvdev->state;
evdevAbsRec *abs;
struct input_absinfo absinfo;
char option[128], value[128];
const char *s;
int i, j, real_axes;
evdev_option_token_t *tokens;
real_axes = 0;
for (i = 0; i < ABS_MAX; i++)
if (test_bit (i, pEvdev->bits.abs))
real_axes++;
if (!real_axes)
return !Success;
state->abs = abs = Xcalloc (sizeof (evdevAbsRec));
xf86Msg(X_INFO, "%s: Found %d absolute axes.\n", pInfo->name, real_axes);
xf86Msg(X_INFO, "%s: Configuring as pointer.\n", pInfo->name);
pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
XI86_CONFIGURED;
pInfo->type_name = XI_MOUSE;
pInfo->conversion_proc = EvdevConvert;
for (i = 0, j = 0; i < ABS_MAX; i++) {
if (!test_bit (i, pEvdev->bits.abs))
continue;
if (ioctl (pInfo->fd, EVIOCGABS(i), &absinfo) < 0) {
xf86Msg(X_ERROR, "ioctl EVIOCGABS failed: %s\n", strerror(errno));
return !Success;
}
snprintf(option, sizeof(option), "Abs%sMapTo", abs_axis_names[i]);
snprintf(value, sizeof(value), "AbsAxis %d %d %d", j, absinfo.minimum, absinfo.maximum);
EvdevParseMapOption (pInfo, option, value, &abs->v_map_data[i], &abs->v_map[i]);
snprintf(option, sizeof(option), "Abs%sOptions", abs_axis_names[i]);
if (i == ABS_X || i == ABS_Y)
s = xf86SetStrOption(pInfo->options, option, "use_touch mode_auto");
else
s = xf86SetStrOption(pInfo->options, option, "");
if (s[0]) {
tokens = EvdevTokenize (s, " ");
if (!EvdevParseAbsOptions (pInfo, option, tokens, &abs->v_flags[i]))
xf86Msg (X_ERROR, "%s: Unable to parse '%s' as absolute options.\n", pInfo->name, s);
EvdevFreeTokens (tokens);
}
abs->v_flags[i] |= EV_ABS_V_PRESENT;
j++;
}
state->abs->axes = real_axes;
return Success;
}
static int
EvdevAxisAbsNew1(InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
char *s;
if (!state->abs)
return !Success;
xf86Msg(X_CONFIG, "%s: Configuring %d absolute axes.\n", pInfo->name,
state->abs->axes);
{
int btn;
s = xf86SetStrOption(pInfo->options, "AbsoluteTouch", "DIGI_Touch");
btn = EvdevBtnFind (pInfo, s);
if (btn != -1) {
if (EvdevBtnExists (pInfo, btn)) {
state->abs->flags |= EV_ABS_USE_TOUCH;
xf86Msg(X_ERROR, "%s: Button: %d.\n", pInfo->name, btn);
xf86Msg(X_ERROR, "%s: state->btn: %p.\n", pInfo->name, state->btn);
state->btn->callback[btn] = &EvdevAxesTouchCallback;
} else {
xf86Msg(X_ERROR, "%s: AbsoluteTouch: '%s' does not exist.\n", pInfo->name, s);
}
} else {
xf86Msg(X_ERROR, "%s: AbsoluteTouch: '%s' is not a valid button name.\n", pInfo->name, s);
}
}
return Success;
}
static int
EvdevAxisRelNew(InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
evdevRelPtr rel;
char *s, option[128], value[128];
int i, j, real_axes;
evdev_option_token_t *tokens;
real_axes = 0;
for (i = 0; i < REL_MAX; i++)
if (test_bit (i, pEvdev->bits.rel))
real_axes++;
if (!real_axes && (!state->abs || state->abs->axes < 2))
return !Success;
state->rel = rel = Xcalloc (sizeof (evdevRelRec));
xf86Msg(X_INFO, "%s: Found %d relative axes.\n", pInfo->name,
real_axes);
xf86Msg(X_INFO, "%s: Configuring as pointer.\n", pInfo->name);
pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
XI86_CONFIGURED;
pInfo->type_name = XI_MOUSE;
pInfo->conversion_proc = EvdevConvert;
for (i = 0, j = 0; i < REL_MAX; i++) {
if (!test_bit (i, pEvdev->bits.rel))
continue;
snprintf(option, sizeof(option), "Rel%sMapTo", rel_axis_names[i]);
if (i == REL_WHEEL || i == REL_Z)
snprintf(value, sizeof(value), "Buttons 4 5 1");
else if (i == REL_HWHEEL)
snprintf(value, sizeof(value), "Buttons 6 7 1");
else
snprintf(value, sizeof(value), "RelAxis %d", j);
EvdevParseMapOption (pInfo, option, value, &rel->v_map_data[i], &rel->v_map[i]);
snprintf(option, sizeof(option), "Rel%sOptions", rel_axis_names[i]);
s = xf86SetStrOption(pInfo->options, option, "");
if (s[0]) {
tokens = EvdevTokenize (s, " ");
if (!EvdevParseRelOptions (pInfo, option, tokens, &rel->v_flags[i]))
xf86Msg (X_ERROR, "%s: Unable to parse '%s' as relative options.\n", pInfo->name, s);
EvdevFreeTokens (tokens);
}
rel->v_flags[i] |= EV_REL_V_PRESENT;
j++;
}
return Success;
}
int
EvdevAxesNew0 (InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
int ret = Success;
state->axes = Xcalloc (sizeof (evdevAxesRec));
if (EvdevAxisAbsNew(pInfo) != Success)
ret = !Success;
if (EvdevAxisRelNew(pInfo) != Success)
ret = !Success;
if (!state->abs && !state->rel) {
Xfree (state->axes);
state->axes = NULL;
}
return ret;
}
int
EvdevAxesNew1 (InputInfoPtr pInfo)
{
evdevDeviceRec *pEvdev = pInfo->private;
evdevStateRec *state = &pEvdev->state;
evdevAxesRec *axes = state->axes;
int i, ret = Success;
if (!state->axes)
return ret;
for (i = 0; i < AXES_MAX; i++)
if (axes->v_flags[i] & EV_AXES_V_PRESENT)
axes->axes = i + 1;
if (EvdevAxisAbsNew1(pInfo) != Success)
ret = !Success;
if (!state->abs && !state->rel) {
Xfree (state->axes);
state->axes = NULL;
}
return ret;
}
static void
EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
{
/* Nothing to do, dix handles all settings */
}
int
EvdevAxesInit (DeviceIntPtr device)
{
InputInfoPtr pInfo = device->public.devicePrivate;
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
evdevAxesRec *axes = state->axes;
AbsoluteClassRec *dev_abs;
int i;
const char *s;
if (!axes || !axes->axes)
return Success;
xf86Msg(X_CONFIG, "%s: %d valuators.\n", pInfo->name,
axes->axes);
if (!InitValuatorClassDeviceStruct(device, axes->axes,
GetMotionHistory,
GetMotionHistorySize(),
0))
return !Success;
/*
* This has to go in Init, because until now there is no valuator struct
* allocated.
*/
s = xf86SetStrOption(pInfo->options, "Mode", "Absolute");
if (!strcasecmp(s, "Absolute")) {
pInfo->dev->valuator->mode = Absolute;
xf86Msg(X_CONFIG, "%s: Configuring in %s mode.\n", pInfo->name, s);
} else if (!strcasecmp(s, "Relative")) {
pInfo->dev->valuator->mode = Relative;
xf86Msg(X_CONFIG, "%s: Configuring in %s mode.\n", pInfo->name, s);
} else {
pInfo->dev->valuator->mode = Absolute;
xf86Msg(X_CONFIG, "%s: Unknown Mode: %s.\n", pInfo->name, s);
}
/*
* Yes, we want to do this for relative devices too.
* Some of the settings are useful for both.
*/
if ((axes->v_flags[0] & EV_AXES_V_PRESENT) &&
(axes->v_flags[1] & EV_AXES_V_PRESENT) &&
InitAbsoluteClassDeviceStruct (device)) {
dev_abs = device->absolute;
if (axes->v_min[0] != axes->v_max[1] && axes->v_min[1] != axes->v_max[1]) {
device->absolute->min_x = axes->v_min[0];
device->absolute->max_x = axes->v_max[0];
device->absolute->min_y = axes->v_min[1];
device->absolute->max_y = axes->v_max[1];
}
}
for (i = 0; i < axes->axes; i++) {
xf86InitValuatorAxisStruct(device, i, -1, -1, 1, 1, 1);
xf86InitValuatorDefaults(device, i);
}
if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc))
return !Success;
return Success;
}
static void
EvdevAxesTouchCallback (InputInfoPtr pInfo, int button, int value)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
int i;
#if DEBUG
xf86Msg(X_INFO, "%s: Touch callback; %d.\n", pInfo->name, value);
#endif
if (state->abs->flags & EV_ABS_USE_TOUCH) {
if (value) {
state->abs->flags |= EV_ABS_TOUCH;
for (i = 0; i < ABS_MAX; i++)
if (state->abs->v_flags[i] & EV_ABS_V_USE_TOUCH)
state->abs->v_flags[i] |= EV_ABS_V_RESET;
} else
state->abs->flags &= ~EV_ABS_TOUCH;
}
}

View File

@@ -1,477 +0,0 @@
/*
* Copyright © 2006-2007 Zephaniah E. Hull
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Soft-
* ware"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, provided that the above copyright
* notice(s) and this permission notice appear in all copies of the Soft-
* ware and that both the above copyright notice(s) and this permission
* notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
* QUENTIAL 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 PERFOR-
* MANCE OF THIS SOFTWARE.
*
* Except as contained in this notice, the name of a copyright holder shall
* not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization of
* the copyright holder.
*
* Author: Zephaniah E. Hull (warp@aehallh.com)
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "evdev.h"
#include <X11/keysym.h>
#include <X11/XF86keysym.h>
#include <X11/extensions/XIproto.h>
#include <linux/input.h>
#include <misc.h>
#include <xf86.h>
#include <xf86str.h>
#include <xf86_OSproc.h>
#include <xf86Xinput.h>
#include <exevents.h>
#include <mipointer.h>
#include <xf86Module.h>
static char *button_names[] = {
"MISC_0",
"MISC_1",
"MISC_2",
"MISC_3",
"MISC_4",
"MISC_5",
"MISC_6",
"MISC_7",
"MISC_8",
"MISC_9",
"MISC_10",
"MISC_11",
"MISC_12",
"MISC_13",
"MISC_14",
"MISC_15",
"MOUSE_LEFT",
"MOUSE_RIGHT",
"MOUSE_MIDDLE",
"MOUSE_SIDE",
"MOUSE_EXTRA",
"MOUSE_FORWARD",
"MOUSE_BACK",
"MOUSE_TASK",
"MOUSE_8",
"MOUSE_9",
"MOUSE_10",
"MOUSE_12",
"MOUSE_13",
"MOUSE_14",
"MOUSE_15",
"JOY_TRIGGER",
"JOY_THUMB",
"JOY_THUMB2",
"JOY_TOP",
"JOY_TOP2",
"JOY_PINKIE",
"JOY_BASE",
"JOY_BASE2",
"JOY_BASE3",
"JOY_BASE4",
"JOY_BASE5",
"JOY_BASE6",
"JOY_12",
"JOY_13",
"JOY_14",
"JOY_DEAD",
"GAME_A",
"GAME_B",
"GAME_C",
"GAME_X",
"GAME_Y",
"GAME_Z",
"GAME_TL",
"GAME_TR",
"GAME_TL2",
"GAME_TR2",
"GAME_SELECT",
"GAME_START",
"GAME_MODE",
"GAME_THUMBL",
"GAME_THUMBR",
"GAME_15",
"DIGI_TOOL_PEN",
"DIGI_TOOL_RUBBER",
"DIGI_TOOL_BRUSH",
"DIGI_TOOL_PENCIL",
"DIGI_TOOL_AIRBRUSH",
"DIGI_TOOL_FINGER",
"DIGI_TOOL_MOUSE",
"DIGI_TOOL_LENS",
"DIGI_8",
"DIGI_9",
"DIGI_TOUCH",
"DIGI_STYLUS",
"DIGI_STYLUS2",
"DIGI_TOOL_DOUBLETAP",
"DIGI_TOOL_TRIPLETAP",
"DIGI_15",
"WHEEL_GEAR_UP",
"WHEEL_GEAR_DOWN",
"WHEEL_2",
"WHEEL_3",
"WHEEL_4",
"WHEEL_5",
"WHEEL_6",
"WHEEL_7",
"WHEEL_8",
"WHEEL_9",
"WHEEL_10",
"WHEEL_11",
"WHEEL_12",
"WHEEL_13",
"WHEEL_14",
"WHEEL_15",
NULL
};
void
EvdevBtnPostFakeClicks(InputInfoRec *pInfo, int button, int count)
{
int i;
for (i = 0; i < count; i++) {
xf86PostButtonEvent(pInfo->dev, 0, button, 1, 0, 0);
xf86PostButtonEvent(pInfo->dev, 0, button, 0, 0, 0);
}
}
static void
EvdevMapButton (InputInfoRec *pInfo, int value, int mode, void *map_data)
{
long button = (long) map_data;
xf86PostButtonEvent (pInfo->dev, 0, button, value, 0, 0);
}
Bool
EvdevParseMapToButton (InputInfoRec *pInfo,
const char *name,
evdev_option_token_t *option,
void **map_data, evdev_map_func_f *map_func)
{
evdevDeviceRec *pEvdev = pInfo->private;
evdevStateRec *state = &pEvdev->state;
evdevBtnRec *btn = state->btn;
int button;
errno = 0;
button = strtol (option->str, NULL, 0);
if (errno)
button = EvdevBtnFind (pInfo, option->str);
if ((button < 0) || (button > BTN_MAX)) {
xf86Msg (X_ERROR, "%s: %s: Button %d out of range.\n", pInfo->name, name, button);
return 0;
}
if (btn->b_flags[button] & EV_BTN_B_PRESENT) {
xf86Msg (X_ERROR, "%s: %s: Button %d already claimed.\n", pInfo->name, name, button);
return 0;
}
btn->b_flags[button] = EV_BTN_B_PRESENT;
*map_data = (void *) button;
*map_func = EvdevMapButton;
return 1;
}
typedef struct {
int button_plus;
int button_minus;
int step;
int count;
} MapButtons_t;
static void
EvdevMapButtons (InputInfoRec *pInfo, int value, int mode, void *map_data)
{
MapButtons_t *map = map_data;
int i;
if (!map)
return;
map->count += value;
i = map->count / map->step;
if (i) {
map->count -= i * map->step;
if (i > 0)
EvdevBtnPostFakeClicks (pInfo, map->button_plus, i);
else
EvdevBtnPostFakeClicks (pInfo, map->button_minus, -i);
}
}
Bool
EvdevParseMapToButtons (InputInfoRec *pInfo,
const char *name,
evdev_option_token_t *option,
void **map_data, evdev_map_func_f *map_func)
{
evdevDeviceRec *pEvdev = pInfo->private;
evdevStateRec *state = &pEvdev->state;
evdevBtnRec *btn = state->btn;
int btn_plus, btn_minus;
MapButtons_t *map;
errno = 0;
btn_plus = strtol (option->str, NULL, 0);
if (errno)
btn_plus = EvdevBtnFind (pInfo, option->str);
if ((btn_plus < 0) || (btn_plus > BTN_MAX)) {
xf86Msg (X_ERROR, "%s: %s: Button %d out of range.\n", pInfo->name, name, btn_plus);
return 0;
}
if (btn->b_flags[btn_plus] & EV_BTN_B_PRESENT) {
xf86Msg (X_ERROR, "%s: %s: Button %d already claimed.\n", pInfo->name, name, btn_plus);
return 0;
}
option = option->next;
if (!option) {
xf86Msg (X_ERROR, "%s: %s: No button minus.\n", pInfo->name, name);
return 0;
}
errno = 0;
btn_minus = strtol (option->str, NULL, 0);
if (errno)
btn_minus = EvdevBtnFind (pInfo, option->str);
if ((btn_minus < 0) || (btn_minus > BTN_MAX)) {
xf86Msg (X_ERROR, "%s: %s: Button %d out of range.\n", pInfo->name, name, btn_minus);
return 0;
}
if (btn->b_flags[btn_minus] & EV_BTN_B_PRESENT) {
xf86Msg (X_ERROR, "%s: %s: Button %d already claimed.\n", pInfo->name, name, btn_minus);
return 0;
}
errno = 0;
btn->b_flags[btn_plus] = EV_BTN_B_PRESENT;
btn->b_flags[btn_minus] = EV_BTN_B_PRESENT;
map = calloc(1, sizeof (MapButtons_t));
map->button_plus = btn_plus;
map->button_minus = btn_minus;
map->step = 1;
*map_data = (void *) map;
*map_func = EvdevMapButtons;
return 1;
}
int
EvdevBtnInit (DeviceIntRec *device)
{
InputInfoRec *pInfo = device->public.devicePrivate;
evdevDeviceRec *pEvdev = pInfo->private;
CARD8 *map;
int i;
if (!pEvdev->state.btn)
return Success;
map = Xcalloc (sizeof (CARD8) * (pEvdev->state.btn->buttons + 1));
for (i = 0; i <= pEvdev->state.btn->buttons; i++)
map[i] = i;
xf86Msg(X_CONFIG, "%s: Registering %d buttons.\n", pInfo->name,
pEvdev->state.btn->buttons);
if (!InitButtonClassDeviceStruct (device, pEvdev->state.btn->buttons, map)) {
pEvdev->state.btn->buttons = 0;
return !Success;
}
Xfree (map);
return Success;
}
int
EvdevBtnOn (DeviceIntRec *device)
{
InputInfoRec *pInfo = device->public.devicePrivate;
evdevDeviceRec *pEvdev = pInfo->private;
int i, blocked;
if (!pEvdev->state.btn)
return Success;
blocked = xf86BlockSIGIO ();
for (i = 1; i <= pEvdev->state.btn->buttons; i++)
xf86PostButtonEvent (device, 0, i, 0, 0, 0);
xf86UnblockSIGIO (blocked);
return Success;
}
int
EvdevBtnOff (DeviceIntRec *device)
{
return Success;
}
int
EvdevBtnNew0(InputInfoRec *pInfo)
{
evdevDeviceRec *pEvdev = pInfo->private;
evdevStateRec *state = &pEvdev->state;
state->btn = Xcalloc (sizeof (evdevBtnRec));
return Success;
}
int
EvdevBtnNew1(InputInfoRec *pInfo)
{
evdevDeviceRec *pEvdev = pInfo->private;
evdevStateRec *state = &pEvdev->state;
evdevBtnRec *btn = state->btn;
char option[128], value[128];
int i, b, j, target;
if (!btn)
return !Success;
for (i = 0; i < BTN_MAX; i++) {
b = i + BTN_MISC;
if (!test_bit (b, pEvdev->bits.key))
continue;
btn->real_buttons++;
snprintf(option, sizeof(option), "Button%sMapTo", button_names[i]);
if (b >= BTN_DIGI && b < BTN_WHEEL)
target = -1;
else if (b == BTN_RIGHT)
target = 3;
else if (b == BTN_MIDDLE)
target = 2;
else if (b >= BTN_MOUSE && b < BTN_JOYSTICK)
target = 1 + i - (BTN_MOUSE - BTN_MISC);
else if (b >= BTN_MISC && b < BTN_MOUSE)
target = 1 + i + (BTN_MOUSE - BTN_MISC);
else
target = 1 + i;
if (btn->b_flags[target] & EV_BTN_B_PRESENT) {
for (j = target; j < BTN_MAX; j++)
if (!(btn->b_flags[j] & EV_BTN_B_PRESENT)) {
target = j;
break;
}
}
if (target > 0)
snprintf (value, sizeof (value), "Button %d", target);
else
snprintf (value, sizeof (value), "null");
EvdevParseMapOption (pInfo, option, value, &btn->b_map_data[i], &btn->b_map[i]);
}
if (state->btn->real_buttons)
xf86Msg(X_INFO, "%s: Found %d mouse buttons\n", pInfo->name, state->btn->real_buttons);
for (i = 0; i < BTN_MAX; i++)
if (btn->b_flags[i] & EV_BTN_B_PRESENT)
btn->buttons = i + 1;
if (state->btn->buttons)
xf86Msg(X_INFO, "%s: Configured %d mouse buttons.\n", pInfo->name, state->btn->buttons);
else {
Xfree (state->btn);
state->btn = NULL;
return !Success;
}
pInfo->flags |= XI86_SEND_DRAG_EVENTS | XI86_CONFIGURED;
/*
* FIXME: Mouse may not be accurate.
* Check buttons to see if we're actually a joystick or something.
*/
pInfo->type_name = XI_MOUSE;
return Success;
}
void
EvdevBtnProcess (InputInfoRec *pInfo, struct input_event *ev)
{
evdevDeviceRec *pEvdev = pInfo->private;
evdevStateRec *state = &pEvdev->state;
int button;
if (!state->btn)
return;
button = ev->code;
button -= BTN_MISC;
if (state->btn->callback[button])
state->btn->callback[button](pInfo, button, ev->value);
if (state->btn->b_map[button])
state->btn->b_map[button](pInfo, ev->value, -1, state->btn->b_map_data[button]);
}
int
EvdevBtnFind (InputInfoRec *pInfo, const char *button)
{
int i;
for (i = 0; button_names[i]; i++)
if (!strcasecmp(button, button_names[i]))
return i + 1;
return -1;
}
int
EvdevBtnExists (InputInfoRec *pInfo, int button)
{
evdevDeviceRec *pEvdev = pInfo->private;
xf86Msg(X_INFO, "%s: Checking button %s (%d)\n", pInfo->name, button_names[button], button);
button += BTN_MISC;
xf86Msg(X_INFO, "%s: Checking bit %d\n", pInfo->name, button);
return test_bit(button, pEvdev->bits.key);
}

View File

@@ -1,549 +0,0 @@
/*
* Copyright © 2006-2007 Zephaniah E. Hull
* Copyright © 2004 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Soft-
* ware"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, provided that the above copyright
* notice(s) and this permission notice appear in all copies of the Soft-
* ware and that both the above copyright notice(s) and this permission
* notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
* QUENTIAL 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 PERFOR-
* MANCE OF THIS SOFTWARE.
*
* Except as contained in this notice, the name of a copyright holder shall
* not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization of
* the copyright holder.
*
* Authors:
* Zephaniah E. Hull (warp@aehallh.com),
* Kristian Høgsberg (krh@redhat.com)
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "evdev.h"
#include <X11/keysym.h>
#include <X11/XF86keysym.h>
#include <X11/extensions/XIproto.h>
#include <linux/input.h>
#include <misc.h>
#include <xf86.h>
#include <xf86str.h>
#include <xf86_OSproc.h>
#include <xf86Xinput.h>
#include <exevents.h>
#include <mipointer.h>
#include <xf86Module.h>
#include <X11/extensions/XKB.h>
#include <X11/extensions/XKBstr.h>
#include <X11/extensions/XKBsrv.h>
#define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
#define MIN_KEYCODE 8
#define GLYPHS_PER_KEY 2
#define AltMask Mod1Mask
#define NumLockMask Mod2Mask
#define AltLangMask Mod3Mask
#define KanaMask Mod4Mask
#define ScrollLockMask Mod5Mask
#define CAPSFLAG 1
#define NUMFLAG 2
#define SCROLLFLAG 4
#define MODEFLAG 8
#define COMPOSEFLAG 16
/* FIXME: this map works with evdev keyboards, but all the xkb maps
* probably don't. The easiest is to remap the event keycodes. */
static KeySym map[] = {
/* 0x00 */ NoSymbol, NoSymbol,
/* 0x01 */ XK_Escape, NoSymbol,
/* 0x02 */ XK_1, XK_exclam,
/* 0x03 */ XK_2, XK_at,
/* 0x04 */ XK_3, XK_numbersign,
/* 0x05 */ XK_4, XK_dollar,
/* 0x06 */ XK_5, XK_percent,
/* 0x07 */ XK_6, XK_asciicircum,
/* 0x08 */ XK_7, XK_ampersand,
/* 0x09 */ XK_8, XK_asterisk,
/* 0x0a */ XK_9, XK_parenleft,
/* 0x0b */ XK_0, XK_parenright,
/* 0x0c */ XK_minus, XK_underscore,
/* 0x0d */ XK_equal, XK_plus,
/* 0x0e */ XK_BackSpace, NoSymbol,
/* 0x0f */ XK_Tab, XK_ISO_Left_Tab,
/* 0x10 */ XK_Q, NoSymbol,
/* 0x11 */ XK_W, NoSymbol,
/* 0x12 */ XK_E, NoSymbol,
/* 0x13 */ XK_R, NoSymbol,
/* 0x14 */ XK_T, NoSymbol,
/* 0x15 */ XK_Y, NoSymbol,
/* 0x16 */ XK_U, NoSymbol,
/* 0x17 */ XK_I, NoSymbol,
/* 0x18 */ XK_O, NoSymbol,
/* 0x19 */ XK_P, NoSymbol,
/* 0x1a */ XK_bracketleft, XK_braceleft,
/* 0x1b */ XK_bracketright,XK_braceright,
/* 0x1c */ XK_Return, NoSymbol,
/* 0x1d */ XK_Control_L, NoSymbol,
/* 0x1e */ XK_A, NoSymbol,
/* 0x1f */ XK_S, NoSymbol,
/* 0x20 */ XK_D, NoSymbol,
/* 0x21 */ XK_F, NoSymbol,
/* 0x22 */ XK_G, NoSymbol,
/* 0x23 */ XK_H, NoSymbol,
/* 0x24 */ XK_J, NoSymbol,
/* 0x25 */ XK_K, NoSymbol,
/* 0x26 */ XK_L, NoSymbol,
/* 0x27 */ XK_semicolon, XK_colon,
/* 0x28 */ XK_quoteright, XK_quotedbl,
/* 0x29 */ XK_quoteleft, XK_asciitilde,
/* 0x2a */ XK_Shift_L, NoSymbol,
/* 0x2b */ XK_backslash, XK_bar,
/* 0x2c */ XK_Z, NoSymbol,
/* 0x2d */ XK_X, NoSymbol,
/* 0x2e */ XK_C, NoSymbol,
/* 0x2f */ XK_V, NoSymbol,
/* 0x30 */ XK_B, NoSymbol,
/* 0x31 */ XK_N, NoSymbol,
/* 0x32 */ XK_M, NoSymbol,
/* 0x33 */ XK_comma, XK_less,
/* 0x34 */ XK_period, XK_greater,
/* 0x35 */ XK_slash, XK_question,
/* 0x36 */ XK_Shift_R, NoSymbol,
/* 0x37 */ XK_KP_Multiply, NoSymbol,
/* 0x38 */ XK_Alt_L, XK_Meta_L,
/* 0x39 */ XK_space, NoSymbol,
/* 0x3a */ XK_Caps_Lock, NoSymbol,
/* 0x3b */ XK_F1, NoSymbol,
/* 0x3c */ XK_F2, NoSymbol,
/* 0x3d */ XK_F3, NoSymbol,
/* 0x3e */ XK_F4, NoSymbol,
/* 0x3f */ XK_F5, NoSymbol,
/* 0x40 */ XK_F6, NoSymbol,
/* 0x41 */ XK_F7, NoSymbol,
/* 0x42 */ XK_F8, NoSymbol,
/* 0x43 */ XK_F9, NoSymbol,
/* 0x44 */ XK_F10, NoSymbol,
/* 0x45 */ XK_Num_Lock, NoSymbol,
/* 0x46 */ XK_Scroll_Lock, NoSymbol,
/* These KP keys should have the KP_7 keysyms in the numlock
* modifer... ? */
/* 0x47 */ XK_KP_Home, XK_KP_7,
/* 0x48 */ XK_KP_Up, XK_KP_8,
/* 0x49 */ XK_KP_Prior, XK_KP_9,
/* 0x4a */ XK_KP_Subtract, NoSymbol,
/* 0x4b */ XK_KP_Left, XK_KP_4,
/* 0x4c */ XK_KP_Begin, XK_KP_5,
/* 0x4d */ XK_KP_Right, XK_KP_6,
/* 0x4e */ XK_KP_Add, NoSymbol,
/* 0x4f */ XK_KP_End, XK_KP_1,
/* 0x50 */ XK_KP_Down, XK_KP_2,
/* 0x51 */ XK_KP_Next, XK_KP_3,
/* 0x52 */ XK_KP_Insert, XK_KP_0,
/* 0x53 */ XK_KP_Delete, XK_KP_Decimal,
/* 0x54 */ NoSymbol, NoSymbol,
/* 0x55 */ XK_F13, NoSymbol,
/* 0x56 */ XK_less, XK_greater,
/* 0x57 */ XK_F11, NoSymbol,
/* 0x58 */ XK_F12, NoSymbol,
/* 0x59 */ XK_F14, NoSymbol,
/* 0x5a */ XK_F15, NoSymbol,
/* 0x5b */ XK_F16, NoSymbol,
/* 0x5c */ XK_F17, NoSymbol,
/* 0x5d */ XK_F18, NoSymbol,
/* 0x5e */ XK_F19, NoSymbol,
/* 0x5f */ XK_F20, NoSymbol,
/* 0x60 */ XK_KP_Enter, NoSymbol,
/* 0x61 */ XK_Control_R, NoSymbol,
/* 0x62 */ XK_KP_Divide, NoSymbol,
/* 0x63 */ XK_Print, XK_Sys_Req,
/* 0x64 */ XK_Alt_R, XK_Meta_R,
/* 0x65 */ NoSymbol, NoSymbol, /* KEY_LINEFEED */
/* 0x66 */ XK_Home, NoSymbol,
/* 0x67 */ XK_Up, NoSymbol,
/* 0x68 */ XK_Prior, NoSymbol,
/* 0x69 */ XK_Left, NoSymbol,
/* 0x6a */ XK_Right, NoSymbol,
/* 0x6b */ XK_End, NoSymbol,
/* 0x6c */ XK_Down, NoSymbol,
/* 0x6d */ XK_Next, NoSymbol,
/* 0x6e */ XK_Insert, NoSymbol,
/* 0x6f */ XK_Delete, NoSymbol,
/* 0x70 */ NoSymbol, NoSymbol, /* KEY_MACRO */
/* 0x71 */ NoSymbol, NoSymbol,
/* 0x72 */ NoSymbol, NoSymbol,
/* 0x73 */ NoSymbol, NoSymbol,
/* 0x74 */ NoSymbol, NoSymbol,
/* 0x75 */ XK_KP_Equal, NoSymbol,
/* 0x76 */ NoSymbol, NoSymbol,
/* 0x77 */ NoSymbol, NoSymbol,
/* 0x78 */ XK_F21, NoSymbol,
/* 0x79 */ XK_F22, NoSymbol,
/* 0x7a */ XK_F23, NoSymbol,
/* 0x7b */ XK_F24, NoSymbol,
/* 0x7c */ XK_KP_Separator, NoSymbol,
/* 0x7d */ XK_Meta_L, NoSymbol,
/* 0x7e */ XK_Meta_R, NoSymbol,
/* 0x7f */ XK_Multi_key, NoSymbol,
/* 0x80 */ NoSymbol, NoSymbol,
/* 0x81 */ NoSymbol, NoSymbol,
/* 0x82 */ NoSymbol, NoSymbol,
/* 0x83 */ NoSymbol, NoSymbol,
/* 0x84 */ NoSymbol, NoSymbol,
/* 0x85 */ NoSymbol, NoSymbol,
/* 0x86 */ NoSymbol, NoSymbol,
/* 0x87 */ NoSymbol, NoSymbol,
/* 0x88 */ NoSymbol, NoSymbol,
/* 0x89 */ NoSymbol, NoSymbol,
/* 0x8a */ NoSymbol, NoSymbol,
/* 0x8b */ NoSymbol, NoSymbol,
/* 0x8c */ NoSymbol, NoSymbol,
/* 0x8d */ NoSymbol, NoSymbol,
/* 0x8e */ NoSymbol, NoSymbol,
/* 0x8f */ NoSymbol, NoSymbol,
/* 0x90 */ NoSymbol, NoSymbol,
/* 0x91 */ NoSymbol, NoSymbol,
/* 0x92 */ NoSymbol, NoSymbol,
/* 0x93 */ NoSymbol, NoSymbol,
/* 0x94 */ NoSymbol, NoSymbol,
/* 0x95 */ NoSymbol, NoSymbol,
/* 0x96 */ NoSymbol, NoSymbol,
/* 0x97 */ NoSymbol, NoSymbol,
/* 0x98 */ NoSymbol, NoSymbol,
/* 0x99 */ NoSymbol, NoSymbol,
/* 0x9a */ NoSymbol, NoSymbol,
/* 0x9b */ NoSymbol, NoSymbol,
/* 0x9c */ NoSymbol, NoSymbol,
/* 0x9d */ NoSymbol, NoSymbol,
/* 0x9e */ NoSymbol, NoSymbol,
/* 0x9f */ NoSymbol, NoSymbol,
/* 0xa0 */ NoSymbol, NoSymbol,
/* 0xa1 */ NoSymbol, NoSymbol,
/* 0xa2 */ NoSymbol, NoSymbol,
/* 0xa3 */ NoSymbol, NoSymbol,
/* 0xa4 */ NoSymbol, NoSymbol,
/* 0xa5 */ NoSymbol, NoSymbol,
/* 0xa6 */ NoSymbol, NoSymbol,
/* 0xa7 */ NoSymbol, NoSymbol,
/* 0xa8 */ NoSymbol, NoSymbol,
/* 0xa9 */ NoSymbol, NoSymbol,
/* 0xaa */ NoSymbol, NoSymbol,
/* 0xab */ NoSymbol, NoSymbol,
/* 0xac */ NoSymbol, NoSymbol,
/* 0xad */ NoSymbol, NoSymbol,
/* 0xae */ NoSymbol, NoSymbol,
/* 0xaf */ NoSymbol, NoSymbol,
/* 0xb0 */ NoSymbol, NoSymbol,
/* 0xb1 */ NoSymbol, NoSymbol,
/* 0xb2 */ NoSymbol, NoSymbol,
/* 0xb3 */ NoSymbol, NoSymbol,
/* 0xb4 */ NoSymbol, NoSymbol,
/* 0xb5 */ NoSymbol, NoSymbol,
/* 0xb6 */ NoSymbol, NoSymbol,
/* 0xb7 */ NoSymbol, NoSymbol,
/* 0xb8 */ NoSymbol, NoSymbol,
/* 0xb9 */ NoSymbol, NoSymbol,
/* 0xba */ NoSymbol, NoSymbol,
/* 0xbb */ NoSymbol, NoSymbol,
/* 0xbc */ NoSymbol, NoSymbol,
/* 0xbd */ NoSymbol, NoSymbol,
/* 0xbe */ NoSymbol, NoSymbol,
/* 0xbf */ NoSymbol, NoSymbol,
/* 0xc0 */ NoSymbol, NoSymbol,
/* 0xc1 */ NoSymbol, NoSymbol,
/* 0xc2 */ NoSymbol, NoSymbol,
/* 0xc3 */ NoSymbol, NoSymbol,
/* 0xc4 */ NoSymbol, NoSymbol,
/* 0xc5 */ NoSymbol, NoSymbol,
/* 0xc6 */ NoSymbol, NoSymbol,
/* 0xc7 */ NoSymbol, NoSymbol,
/* 0xc8 */ NoSymbol, NoSymbol,
/* 0xc9 */ NoSymbol, NoSymbol,
/* 0xca */ NoSymbol, NoSymbol,
/* 0xcb */ NoSymbol, NoSymbol,
/* 0xcc */ NoSymbol, NoSymbol,
/* 0xcd */ NoSymbol, NoSymbol,
/* 0xce */ NoSymbol, NoSymbol,
/* 0xcf */ NoSymbol, NoSymbol,
/* 0xd0 */ NoSymbol, NoSymbol,
/* 0xd1 */ NoSymbol, NoSymbol,
/* 0xd2 */ NoSymbol, NoSymbol,
/* 0xd3 */ NoSymbol, NoSymbol,
/* 0xd4 */ NoSymbol, NoSymbol,
/* 0xd5 */ NoSymbol, NoSymbol,
/* 0xd6 */ NoSymbol, NoSymbol,
/* 0xd7 */ NoSymbol, NoSymbol,
/* 0xd8 */ NoSymbol, NoSymbol,
/* 0xd9 */ NoSymbol, NoSymbol,
/* 0xda */ NoSymbol, NoSymbol,
/* 0xdb */ NoSymbol, NoSymbol,
/* 0xdc */ NoSymbol, NoSymbol,
/* 0xdd */ NoSymbol, NoSymbol,
/* 0xde */ NoSymbol, NoSymbol,
/* 0xdf */ NoSymbol, NoSymbol,
/* 0xe0 */ NoSymbol, NoSymbol,
/* 0xe1 */ NoSymbol, NoSymbol,
/* 0xe2 */ NoSymbol, NoSymbol,
/* 0xe3 */ NoSymbol, NoSymbol,
/* 0xe4 */ NoSymbol, NoSymbol,
/* 0xe5 */ NoSymbol, NoSymbol,
/* 0xe6 */ NoSymbol, NoSymbol,
/* 0xe7 */ NoSymbol, NoSymbol,
/* 0xe8 */ NoSymbol, NoSymbol,
/* 0xe9 */ NoSymbol, NoSymbol,
/* 0xea */ NoSymbol, NoSymbol,
/* 0xeb */ NoSymbol, NoSymbol,
/* 0xec */ NoSymbol, NoSymbol,
/* 0xed */ NoSymbol, NoSymbol,
/* 0xee */ NoSymbol, NoSymbol,
/* 0xef */ NoSymbol, NoSymbol,
/* 0xf0 */ NoSymbol, NoSymbol,
/* 0xf1 */ NoSymbol, NoSymbol,
/* 0xf2 */ NoSymbol, NoSymbol,
/* 0xf3 */ NoSymbol, NoSymbol,
/* 0xf4 */ NoSymbol, NoSymbol,
/* 0xf5 */ NoSymbol, NoSymbol,
/* 0xf6 */ NoSymbol, NoSymbol,
/* 0xf7 */ NoSymbol, NoSymbol,
};
static void
EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
{
static struct { int xbit, code; } bits[] = {
{ CAPSFLAG, LED_CAPSL },
{ NUMFLAG, LED_NUML },
{ SCROLLFLAG, LED_SCROLLL },
{ MODEFLAG, LED_KANA },
{ COMPOSEFLAG, LED_COMPOSE }
};
InputInfoPtr pInfo;
struct input_event ev[ArrayLength(bits)];
int i;
pInfo = device->public.devicePrivate;
for (i = 0; i < ArrayLength(bits); i++) {
ev[i].type = EV_LED;
ev[i].code = bits[i].code;
ev[i].value = (ctrl->leds & bits[i].xbit) > 0;
}
write(pInfo->fd, ev, sizeof(ev));
if (device->key && device->key->xkbInfo && device->key->xkbInfo->desc
&& device->key->xkbInfo->desc->ctrls) {
XkbControlsRec *ctrls = device->key->xkbInfo->desc->ctrls;
ev[0].type = EV_REP;
ev[0].code = REP_DELAY;
ev[0].value = ctrls->repeat_delay;
ev[1].type = EV_REP;
ev[1].code = REP_PERIOD;
ev[1].value = ctrls->repeat_interval;
write(pInfo->fd, ev, sizeof(ev[0]) * 2);
}
}
int
EvdevKeyInit (DeviceIntPtr device)
{
InputInfoPtr pInfo = device->public.devicePrivate;
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
KeySymsRec keySyms;
CARD8 modMap[MAP_LENGTH];
KeySym sym;
int i, j;
static struct { KeySym keysym; CARD8 mask; } modifiers[] = {
{ XK_Shift_L, ShiftMask },
{ XK_Shift_R, ShiftMask },
{ XK_Control_L, ControlMask },
{ XK_Control_R, ControlMask },
{ XK_Caps_Lock, LockMask },
{ XK_Alt_L, AltMask },
{ XK_Alt_R, AltMask },
{ XK_Num_Lock, NumLockMask },
{ XK_Scroll_Lock, ScrollLockMask },
{ XK_Mode_switch, AltLangMask }
};
/* TODO:
* Ctrl-Alt-Backspace and other Ctrl-Alt-stuff should work
* XKB, let's try without the #ifdef nightmare
* Get keyboard repeat under control (right now caps lock repeats!)
*/
pInfo = device->public.devicePrivate;
/* Compute the modifier map */
memset(modMap, 0, sizeof modMap);
for (i = 0; i < ArrayLength(map) / GLYPHS_PER_KEY; i++) {
sym = map[i * GLYPHS_PER_KEY];
for (j = 0; j < ArrayLength(modifiers); j++) {
if (modifiers[j].keysym == sym)
modMap[i + MIN_KEYCODE] = modifiers[j].mask;
}
}
keySyms.map = map;
keySyms.mapWidth = GLYPHS_PER_KEY;
keySyms.minKeyCode = MIN_KEYCODE;
keySyms.maxKeyCode = MIN_KEYCODE + ArrayLength(map) / GLYPHS_PER_KEY - 1;
XkbSetRulesDflts (state->key->xkb_rules, state->key->xkb_model,
state->key->xkb_layout, state->key->xkb_variant,
state->key->xkb_options);
XkbInitKeyboardDeviceStruct (device, &state->key->xkbnames, &keySyms, modMap,
NULL, EvdevKbdCtrl);
return Success;
}
static void
SetXkbOption(InputInfoPtr pInfo, char *name, char *value, char **option)
{
char *s;
if ((s = xf86SetStrOption(pInfo->options, name, value))) {
if (!s[0]) {
xfree(s);
*option = NULL;
} else {
*option = s;
}
}
}
int
EvdevKeyNew (InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
int i, keys = 0;
for (i = 0; i <= 0xF7; i++)
if (test_bit (i, pEvdev->bits.key)) {
keys = 1;
break;
}
if (!keys)
return !Success;
state->key = Xcalloc (sizeof (evdevKeyRec));
pInfo->type_name = XI_KEYBOARD;
pInfo->flags |= XI86_KEYBOARD_CAPABLE | XI86_CONFIGURED;
SetXkbOption (pInfo, "xkb_rules", NULL, &state->key->xkb_rules);
if (!state->key->xkb_rules)
SetXkbOption (pInfo, "XkbRules", __XKBDEFRULES__,
&state->key->xkb_rules);
SetXkbOption (pInfo, "xkb_model", NULL, &state->key->xkb_model);
if (!state->key->xkb_model)
SetXkbOption (pInfo, "XkbModel", "evdev", &state->key->xkb_model);
SetXkbOption (pInfo, "xkb_layout", NULL, &state->key->xkb_layout);
if (!state->key->xkb_layout)
SetXkbOption (pInfo, "XkbLayout", "us", &state->key->xkb_layout);
SetXkbOption (pInfo, "xkb_variant", NULL, &state->key->xkb_variant);
if (!state->key->xkb_variant)
SetXkbOption (pInfo, "XkbVariant", NULL, &state->key->xkb_variant);
SetXkbOption (pInfo, "xkb_options", NULL, &state->key->xkb_options);
if (!state->key->xkb_options)
SetXkbOption (pInfo, "XkbOptions", NULL, &state->key->xkb_options);
return Success;
}
int
EvdevKeyOn (DeviceIntPtr device)
{
return Success;
}
int
EvdevKeyOff (DeviceIntPtr device)
{
unsigned int i;
KeyClassRec *keyc = device->key;
KeySym *map = keyc->curKeySyms.map;
/*
* A bit of a hack, vaguely stolen from xf86-input-keyboard.
*
* Don't leave any keys in the down state if we are getting turned
* off, as they are likely to be released before we are turned back
* on.
* (For example, if the user switches VTs, or if we are unplugged.)
*/
for (i = keyc->curKeySyms.minKeyCode, map = keyc->curKeySyms.map;
i < keyc->curKeySyms.maxKeyCode;
i++, map += keyc->curKeySyms.mapWidth)
if ((keyc->down[i >> 3] & (1 << (i & 7))))
{
switch (*map) {
/* Don't release the lock keys */
case XK_Caps_Lock:
case XK_Shift_Lock:
case XK_Num_Lock:
case XK_Scroll_Lock:
case XK_Kana_Lock:
break;
default:
xf86PostKeyboardEvent(device, i, 0);
}
}
return Success;
}
void
EvdevKeyProcess (InputInfoPtr pInfo, struct input_event *ev)
{
int keycode = ev->code + MIN_KEYCODE;
/* filter repeat events for chording keys */
if (ev->value == 2) {
DeviceIntPtr device = pInfo->dev;
KeyClassRec *keyc = device->key;
KbdFeedbackClassRec *kbdfeed = device->kbdfeed;
int num = keycode >> 3;
int bit = 1 << (keycode & 7);
if (keyc->modifierMap[keycode] ||
!(kbdfeed->ctrl.autoRepeats[num] & bit))
return;
}
xf86PostKeyboardEvent(pInfo->dev, keycode, ev->value);
}

6
xorg-evdev.pc.in Normal file
View File

@@ -0,0 +1,6 @@
sdkdir=@sdkdir@
Name: xorg-evdev
Description: X.Org evdev input driver.
Version: @PACKAGE_VERSION@
Cflags: -I${sdkdir}