From 4bfca3b0e892106a0907312eac0b824b4f6ec260 Mon Sep 17 00:00:00 2001 From: Chris Salch Date: Sun, 17 Aug 2008 12:31:23 -0500 Subject: [PATCH] Adding in DragLockButtons functionality. --- man/evdev.man | 12 +++ src/Makefile.am | 3 +- src/draglock.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/evdev.c | 5 ++ src/evdev.h | 10 +++- 5 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 src/draglock.c diff --git a/man/evdev.man b/man/evdev.man index 3b0f3b1..3e87f26 100644 --- a/man/evdev.man +++ b/man/evdev.man @@ -78,6 +78,17 @@ 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. .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 @@ -120,6 +131,7 @@ emulation mode. Button number is mapped to the negative Y axis motion and button number .I N2 is mapped to the positive Y axis motion. Default: "4 5" +>>>>>>> master:man/evdev.man .SH AUTHORS Kristian Høgsberg. .SH "SEE ALSO" diff --git a/src/Makefile.am b/src/Makefile.am index e6bb64e..a3b256f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,5 +31,6 @@ @DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \ @DRIVER_NAME@.h \ emuMB.c \ - emuWheel.c + emuWheel.c \ + draglock.c diff --git a/src/draglock.c b/src/draglock.c new file mode 100644 index 0000000..8739697 --- /dev/null +++ b/src/draglock.c @@ -0,0 +1,203 @@ +/* + * 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 "evdev.h" + +void EvdevDragLockLockButton(InputInfoPtr pInfo, unsigned int button); + + +/* Setup and configuration code */ +void +EvdevDragLockInit(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; +} + diff --git a/src/evdev.c b/src/evdev.c index 806c228..7c20ba7 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -287,6 +287,10 @@ EvdevReadInput(InputInfoPtr pInfo) default: button = EvdevUtilButtonEventToButtonNumber(ev.code); + /* Handle drage lock */ + if (EvdevDragLockFilterEvent(pInfo, button, value)) + break; + if (EvdevWheelEmuFilterButton(pInfo, button, value)) break; @@ -952,6 +956,7 @@ EvdevProc(DeviceIntPtr device, int what) { EvdevMBEmuPreInit(pInfo); EvdevWheelEmuPreInit(pInfo); + EvdevDragLockInit(pInfo); } device->public.on = TRUE; } diff --git a/src/evdev.h b/src/evdev.h index a0a336a..667915a 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -78,6 +78,12 @@ typedef struct { Time timeout; } emulateMB; struct { + int meta; /* meta key to lock any button */ + BOOL meta_state; /* meta_button state */ + unsigned int lock_pair[32]; /* specify a meta/lock pair */ + BOOL lock_state[32]; /* state of any locked buttons */ + } dragLock; + struct { BOOL enabled; int button; int button_state; @@ -113,5 +119,7 @@ void EvdevWheelEmuPreInit(InputInfoPtr pInfo); BOOL EvdevWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int value); BOOL EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv); - +/* Draglock code */ +void EvdevDragLockInit(InputInfoPtr pInfo); +BOOL EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value); #endif -- 1.5.6.4