3 * xserver-xorg-input-evdev-multitouch
5 * Contact: Sung-Jin Park <sj76.park@samsung.com>
6 * Sangjin LEE <lsj119@samsung.com>
8 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
10 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
11 * Copyright 1993 by David Dawes <dawes@xfree86.org>
12 * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
13 * Copyright 1994-2002 by The XFree86 Project, Inc.
14 * Copyright 2002 by Paul Elliott
15 * (Ported from xf86-input-mouse, above copyrights taken from there)
16 * Copyright © 2008 University of South Australia
17 * Copyright 2008 by Chris Salch
18 * Copyright 2008 Red Hat, Inc.
20 * Permission to use, copy, modify, distribute, and sell this software
21 * and its documentation for any purpose is hereby granted without
22 * fee, provided that the above copyright notice appear in all copies
23 * and that both that copyright notice and this permission notice
24 * appear in supporting documentation, and that the name of the authors
25 * not be used in advertising or publicity pertaining to distribution of the
26 * software without specific, written prior permission. The authors make no
27 * representations about the suitability of this software for any
28 * purpose. It is provided "as is" without express or implied
31 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
32 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
33 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
34 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
35 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
36 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
37 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48 #include <xf86Xinput.h>
49 #include <X11/Xatom.h>
52 #include <evdevmultitouch-properties.h>
53 #include "evdevmultitouch.h"
55 #ifdef HAVE_PROPERTIES
56 static Atom prop_dlock = 0; /* Drag lock buttons. */
59 void EvdevMultitouchDragLockLockButton(InputInfoPtr pInfo, unsigned int button);
62 /* Setup and configuration code */
64 EvdevMultitouchDragLockPreInit(InputInfoPtr pInfo)
66 EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
67 char *option_string = NULL;
70 char *next_num = NULL;
74 option_string = xf86CheckStrOption(pInfo->options, "DragLockButtons",NULL);
79 next_num = option_string;
81 /* Loop until we hit the end of our option string */
82 while (next_num != NULL) {
84 meta_button = strtol(next_num, &end_str, 10);
86 /* check to see if we found anything */
87 if (next_num != end_str) {
88 /* setup for the next number */
91 /* we have nothing more to parse, drop out of the loop */
95 /* Check for a button to lock if we have a meta button */
96 if (meta_button != 0 && next_num != NULL ) {
97 lock_button = strtol(next_num, &end_str, 10);
99 /* check to see if we found anything */
100 if (next_num != end_str) {
101 /* setup for the next number */
104 /* we have nothing more to parse, drop out of the loop */
109 /* Ok, let the user know what we found on this look */
110 if (meta_button != 0) {
111 if (lock_button == 0) {
113 /* We only have a meta button */
114 pEvdevMultitouch->dragLock.meta = meta_button;
116 xf86Msg(X_CONFIG, "%s: DragLockButtons : "
118 pInfo->name, meta_button);
120 xf86Msg(X_ERROR, "%s: DragLockButtons : "
121 "Incomplete pair specifying button pairs %s\n",
122 pInfo->name, option_string);
126 /* Do bounds checking to make sure we don't crash */
127 if ((meta_button <= EVDEVMULTITOUCH_MAXBUTTONS) && (meta_button > 0 ) &&
128 (lock_button <= EVDEVMULTITOUCH_MAXBUTTONS) && (lock_button >= 0)) {
130 xf86Msg(X_CONFIG, "%s: DragLockButtons : %i -> %i\n",
131 pInfo->name, meta_button, lock_button);
133 pEvdevMultitouch->dragLock.lock_pair[meta_button - 1] = lock_button;
136 /* Let the user know something was wrong
137 with this pair of buttons */
138 xf86Msg(X_CONFIG, "%s: DragLockButtons : "
139 "Invalid button pair %i -> %i\n",
140 pInfo->name, meta_button, lock_button);
144 xf86Msg(X_ERROR, "%s: Found DragLockButtons "
145 "with invalid lock button string : '%s'\n",
146 pInfo->name, option_string);
148 /* This should be the case anyhow, just make sure */
152 /* Check for end of string, to avoid annoying error */
153 if (next_num != NULL && *next_num == '\0')
158 /* Updates DragLock button state and fires button event messges */
160 EvdevMultitouchDragLockLockButton(InputInfoPtr pInfo, unsigned int button)
162 EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
165 /* update button state */
166 state = pEvdevMultitouch->dragLock.lock_state[button - 1] ? FALSE : TRUE;
167 pEvdevMultitouch->dragLock.lock_state[button - 1] = state;
169 EvdevMultitouchQueueButtonEvent(pInfo, button, state);
172 /* Filter button presses looking for either a meta button or the
173 * control of a button pair.
175 * @param button button number (1 for left, 3 for right)
176 * @param value TRUE if button press, FALSE if release
178 * @return TRUE if the event was swallowed here, FALSE otherwise.
181 EvdevMultitouchDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value)
183 EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
188 /* Do we have a single meta key or
189 several button pairings? */
190 if (pEvdevMultitouch->dragLock.meta != 0) {
192 if (pEvdevMultitouch->dragLock.meta == button) {
194 /* setup up for button lock */
196 pEvdevMultitouch->dragLock.meta_state = TRUE;
199 } else if (pEvdevMultitouch->dragLock.meta_state) { /* waiting to lock */
201 pEvdevMultitouch->dragLock.meta_state = FALSE;
203 EvdevMultitouchDragLockLockButton(pInfo, button);
207 } else if (pEvdevMultitouch->dragLock.lock_pair[button - 1] && value) {
208 /* A meta button in a meta/lock pair was pressed */
209 EvdevMultitouchDragLockLockButton(pInfo, pEvdevMultitouch->dragLock.lock_pair[button - 1]);
213 /* Eat events for buttons that are locked */
214 if (pEvdevMultitouch->dragLock.lock_state[button - 1])
220 #ifdef HAVE_PROPERTIES
222 * Set the drag lock property.
223 * If only one value is supplied, then this is used as the meta button.
224 * If more than one value is supplied, then each value is the drag lock button
225 * for the pair. 0 disables a pair.
226 * i.e. to set bt 3 to draglock button 1, supply 0,0,1
229 EvdevMultitouchDragLockSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
232 InputInfoPtr pInfo = dev->public.devicePrivate;
233 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
235 if (atom == prop_dlock)
239 if (val->format != 8 || val->type != XA_INTEGER)
242 /* Don't allow changes while a lock is active */
243 if (pEvdevMultitouch->dragLock.meta)
245 if (pEvdevMultitouch->dragLock.meta_state)
249 for (i = 0; i < EVDEVMULTITOUCH_MAXBUTTONS; i++)
250 if (pEvdevMultitouch->dragLock.lock_state[i])
256 else if (val->size == 1)
258 int meta = *((CARD8*)val->data);
259 if (meta > EVDEVMULTITOUCH_MAXBUTTONS)
264 pEvdevMultitouch->dragLock.meta = meta;
265 memset(pEvdevMultitouch->dragLock.lock_pair, 0, sizeof(pEvdevMultitouch->dragLock.lock_pair));
267 } else if ((val->size % 2) == 0)
269 CARD8* vals = (CARD8*)val->data;
271 for (i = 0; i < val->size && i < EVDEVMULTITOUCH_MAXBUTTONS; i++)
272 if (vals[i] > EVDEVMULTITOUCH_MAXBUTTONS)
277 pEvdevMultitouch->dragLock.meta = 0;
278 memset(pEvdevMultitouch->dragLock.lock_pair, 0, sizeof(pEvdevMultitouch->dragLock.lock_pair));
280 for (i = 0; i < val->size && i < EVDEVMULTITOUCH_MAXBUTTONS; i += 2)
281 pEvdevMultitouch->dragLock.lock_pair[vals[i] - 1] = vals[i + 1];
291 * Initialise property for drag lock buttons setting.
294 EvdevMultitouchDragLockInitProperty(DeviceIntPtr dev)
296 InputInfoPtr pInfo = dev->public.devicePrivate;
297 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
299 if (!dev->button) /* don't init prop for keyboards */
302 prop_dlock = MakeAtom(EVDEVMULTITOUCH_PROP_DRAGLOCK, strlen(EVDEVMULTITOUCH_PROP_DRAGLOCK), TRUE);
303 if (pEvdevMultitouch->dragLock.meta)
305 XIChangeDeviceProperty(dev, prop_dlock, XA_INTEGER, 8,
306 PropModeReplace, 1, &pEvdevMultitouch->dragLock.meta,
311 CARD8 pair[EVDEVMULTITOUCH_MAXBUTTONS] = {0};
313 for (i = 0; i < EVDEVMULTITOUCH_MAXBUTTONS; i++)
315 if (pEvdevMultitouch->dragLock.lock_pair[i])
317 pair[i] = pEvdevMultitouch->dragLock.lock_pair[i];
320 XIChangeDeviceProperty(dev, prop_dlock, XA_INTEGER, 8, PropModeReplace,
321 highest + 1, pair, FALSE);
324 XISetDevicePropertyDeletable(dev, prop_dlock, FALSE);
326 XIRegisterPropertyHandler(dev, EvdevMultitouchDragLockSetProperty, NULL, NULL);