From e17c4cde1d008ce28cf343c67263d47218885e26 Mon Sep 17 00:00:00 2001 From: Chris Salch Date: Mon, 4 Aug 2008 22:28:38 -0500 Subject: [PATCH] Adding in DragLock functionality. --- man/evdev.man | 13 +++- src/Makefile.am | 4 +- src/draglock.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/evdev.c | 51 +++++++++++++ src/evdev.h | 12 +++ 5 files changed, 287 insertions(+), 2 deletions(-) create mode 100644 src/draglock.c diff --git a/man/evdev.man b/man/evdev.man index 0a4b71a..d853f51 100644 --- a/man/evdev.man +++ b/man/evdev.man @@ -77,7 +77,18 @@ 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 \*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. +.TP 7 +.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. .SH AUTHORS Kristian Høgsberg. .SH "SEE ALSO" diff --git a/src/Makefile.am b/src/Makefile.am index d0b9b63..2207d7f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,4 +30,6 @@ @DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \ @DRIVER_NAME@.h \ - emuMB.c + emuMB.c \ + draglock.c + diff --git a/src/draglock.c b/src/draglock.c new file mode 100644 index 0000000..ae5c677 --- /dev/null +++ b/src/draglock.c @@ -0,0 +1,209 @@ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * Copyright 1993 by David Dawes + * 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 + * + * 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 +#include +#include +#include + +#include "evdev.h" + +void EvdevDragLockLockButton(InputInfoPtr pInfo, unsigned char button); + + +/* Setup and configuration code */ +void +EvdevDragLockInit(InputInfoPtr pInfo) +{ + EvdevPtr pEvdev = (EvdevPtr)pInfo->private; + char *option_string = 0; + + option_string = xf86CheckStrOption(pInfo->options, "DragLockButtons",NULL); + + if (option_string) { + int meta_button = 0; + int lock_button = 0; + char *next_num = option_string; + char *end_str = 0; + BOOL pairs = FALSE; + + /* Loop until we hit the end of our option string */ + while (next_num != 0) { + 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 = 0; + } + + /* Check for a button to lock if we have a meta button */ + if (meta_button != 0 && next_num != 0 ) { + 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 = 0; + } + } + + /* 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 <= 32) && (meta_button >= 0 ) && + (lock_button <= 32) && (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 no 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 = 0; + } + + /* Check for end of string, to avoid annoying error */ + if (next_num != 0 && *next_num == '\0') + next_num = 0; + } + } +} + +/* Clean up after ourselves */ +void +EvdevDragLockUnInit(InputInfoPtr pInfo) +{ + +} + +/* Updates DragLock button state and firest button event messges */ +void +EvdevDragLockLockButton(InputInfoPtr pInfo, unsigned char button) +{ + EvdevPtr pEvdev = (EvdevPtr)pInfo->private; + BOOL state=0; + + /* update button state */ + state = TRUE - pEvdev->dragLock.lock_state[button - 1]; + pEvdev->dragLock.lock_state[button - 1] = state; + + xf86PostButtonEvent(pInfo->dev, 0, button, state, 0, 0); +} + +BOOL +EvdevDragLockFilterEvent(InputInfoPtr pInfo, struct input_event *pEv) +{ + EvdevPtr pEvdev = (EvdevPtr)pInfo->private; + unsigned char button=0; + + /* Is this an event we care about? */ + if (pEv->type != EV_KEY) + return FALSE; + + button = EvdevUtilButtonEventToButtonNumber(pEv->code); + + 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 (pEv->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] && pEv->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; +} + diff --git a/src/evdev.c b/src/evdev.c index 670cbb2..52bb524 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -206,6 +206,7 @@ EvdevReadInput(InputInfoPtr pInfo) break; } + /* Get the signed value, earlier kernels had this as unsigned */ value = ev.value; @@ -256,6 +257,10 @@ EvdevReadInput(InputInfoPtr pInfo) if (value == 2) break; + /* Handle drage lock */ + if (EvdevDragLockFilterEvent(pInfo, &ev)) + break; + switch (ev.code) { /* swap here, pretend we're an X-conformant device. */ case BTN_LEFT: @@ -957,7 +962,10 @@ EvdevProc(DeviceIntPtr device, int what) { xf86AddEnabledDevice(pInfo); if (pEvdev->flags & EVDEV_BUTTON_EVENTS) + { EvdevMBEmuPreInit(pInfo); + EvdevDragLockInit(pInfo); + } device->public.on = TRUE; } break; @@ -968,6 +976,7 @@ EvdevProc(DeviceIntPtr device, int what) strerror(errno)); xf86RemoveEnabledDevice(pInfo); EvdevMBEmuFinalize(pInfo); + EvdevDragLockUnInit(pInfo); device->public.on = FALSE; break; @@ -1216,3 +1225,45 @@ _X_EXPORT XF86ModuleData evdevModuleData = EvdevPlug, EvdevUnplug }; + + +/* Return an index value for a given button event code + * returns -1 on invalid value. + */ +unsigned char +EvdevUtilButtonEventToButtonNumber(int code) +{ + unsigned char button = 0; + switch(code) { + case BTN_LEFT: + button = 1; + break; + + case BTN_RIGHT: + button = 3; + break; + + case BTN_MIDDLE: + button = 2; + break; + + case BTN_SIDE: + case BTN_EXTRA: + case BTN_FORWARD: + case BTN_BACK: + case BTN_TASK: + button = (code - BTN_LEFT + 5); + break; + + default: + if ((code > BTN_TASK) && (code < KEY_OK)) { + if (code < BTN_JOYSTICK) + button = (code - BTN_LEFT + 5); + } + } + + if (button > 32) + return 0; + + return button; +} diff --git a/src/evdev.h b/src/evdev.h index bc79287..38e072a 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -68,6 +68,12 @@ typedef struct { Time expires; /* time of expiry */ Time timeout; } emulateMB; + struct { + int meta; /* meta key to lock any button */ + BOOL meta_state; /* meta_button state */ + unsigned char lock_pair[32]; /* specify a meta/lock pair */ + BOOL lock_state[32]; /* state of any locked buttons */ + } dragLock; unsigned char btnmap[32]; /* config-file specified button mapping */ } EvdevRec, *EvdevPtr; @@ -86,4 +92,10 @@ Atom EvdevMBEmuInitPropertyTimeout(DeviceIntPtr, char*); BOOL EvdevMBEmuSetProperty(DeviceIntPtr, Atom, XIPropertyValuePtr); #endif +/* Draglock code */ +void EvdevDragLockInit(InputInfoPtr pInfo); +void EvdevDragLockUnInit(InputInfoPtr pInfo); /* may not need this after all */ +BOOL EvdevDragLockFilterEvent(InputInfoPtr pInfo, struct input_event *pEv); + +unsigned char EvdevUtilButtonEventToButtonNumber(int code); #endif -- 1.5.6.3