3 * xserver-xorg-input-evdev
5 * Contact: Sung-Jin Park <sj76.park@samsung.com>
6 * Sangjin LEE <lsj119@samsung.com>
7 * Jeonghyun Kang <jhyuni.kang@samsung.com>
9 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
10 * Copyright © 2004-2008 Red Hat, Inc.
12 * Permission to use, copy, modify, distribute, and sell this software
13 * and its documentation for any purpose is hereby granted without
14 * fee, provided that the above copyright notice appear in all copies
15 * and that both that copyright notice and this permission notice
16 * appear in supporting documentation, and that the name of Red Hat
17 * not be used in advertising or publicity pertaining to distribution
18 * of the software without specific, written prior permission. Red
19 * Hat makes no representations about the suitability of this software
20 * for any purpose. It is provided "as is" without express or implied
23 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
25 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
27 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
28 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
29 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 * Kristian Høgsberg (krh@redhat.com)
33 * Adam Jackson (ajax@redhat.com)
34 * Peter Hutterer (peter.hutterer@redhat.com)
35 * Oliver McFadden (oliver.mcfadden@nokia.com)
38 #ifdef _F_PROXY_DEVICE_ENABLED_
44 #include <evdev-properties.h>
46 #include <sys/types.h>
53 #include <xf86Xinput.h>
54 #include <X11/Xatom.h>
55 #include <xorg/optionstr.h>
60 unsigned char header; /**< Always ET_Internal */
61 enum EventType type; /**< One of EventType */
62 int length; /**< Length in bytes */
63 Time time; /**< Time in ms */
64 int deviceid; /**< Device to post this event for */
65 int sourceid; /**< The physical source device */
67 uint32_t button; /**< Button number (also used in pointer emulating
69 uint32_t key; /**< Key code */
71 uint32_t touchid; /**< Touch ID (client_id) */
72 int16_t root_x; /**< Pos relative to root window in integral data */
73 float root_x_frac; /**< Pos relative to root window in frac part */
74 int16_t root_y; /**< Pos relative to root window in integral part */
75 float root_y_frac; /**< Pos relative to root window in frac part */
76 uint8_t buttons[(MAX_BUTTONS + 7) / 8]; /**< Button mask */
78 uint8_t mask[(MAX_VALUATORS + 7) / 8];/**< Valuator mask */
79 uint8_t mode[(MAX_VALUATORS + 7) / 8];/**< Valuator mode (Abs or Rel)*/
80 double data[MAX_VALUATORS]; /**< Valuator data */
83 uint32_t base; /**< XKB base modifiers */
84 uint32_t latched; /**< XKB latched modifiers */
85 uint32_t locked; /**< XKB locked modifiers */
86 uint32_t effective;/**< XKB effective modifiers */
89 uint8_t base; /**< XKB base group */
90 uint8_t latched; /**< XKB latched group */
91 uint8_t locked; /**< XKB locked group */
92 uint8_t effective;/**< XKB effective group */
94 Window root; /**< Root window of the event */
95 int corestate; /**< Core key/button state BEFORE the event */
96 int key_repeat; /**< Internally-generated key repeat event */
97 uint32_t flags; /**< Flags to be copied into the generated event */
98 uint32_t resource; /**< Touch event resource, only for TOUCH_REPLAYING */
101 typedef struct _barrierBoundary {
108 typedef enum _barrierState {
114 #define prop_MLS_Barrier_Boundary "MLS_Barrier_Boundary"
115 #define prop_MLS_Barrier_Hit "MLS_Barrier_Hit"
117 static void EvdevProxyBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead);
118 void EvdevProxySetBarrierBoundary(int num, unsigned int val[4], barrierBoundary *boundary);
119 barrierState EvdevProxyLocationManager(int x, int y, barrierBoundary boundary);
120 void EvdevProxyProcessMotion(int screen_num, InternalEvent *ev, DeviceIntPtr device);
121 void EvdevProxyProcessRawMotion(int screen_num, InternalEvent *ev, DeviceIntPtr device);
122 static int EvdevProxySetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, BOOL checkonly);
123 static int EvdevProxyDeleteProperty(DeviceIntPtr dev, Atom atom);
125 DeviceIntPtr proxyDev;
128 barrierBoundary BarrierBoundary;
129 barrierState BarrierState;
130 Atom atom_MLS_Barrier_Boundary;
131 Atom atom_MLS_Barrier_Hit;
134 static Atom prop_ungrab_device;
140 EvdevProxyBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
142 InputInfoPtr pInfo = (InputInfoPtr)data;
145 RemoveBlockAndWakeupHandlers(EvdevProxyBlockHandler,
146 (WakeupHandlerProcPtr)NoopDDA,
149 if (BarrierState != BARRIER_NONE)
150 rc = XIChangeDeviceProperty(pInfo->dev, atom_MLS_Barrier_Hit, XA_INTEGER, 32,
151 PropModeReplace, 1, &BarrierState, TRUE);
155 xf86IDrvMsg(pInfo, X_ERROR, "[%s:%d] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, __LINE__, pInfo->dev->id, atom_MLS_Barrier_Hit);
159 void EvdevProxySetBarrierBoundary(int num, unsigned int val[4], barrierBoundary *boundary)
162 if (BarrierState != BARRIER_NONE) ErrorF("[%s:%d] Unset MLS Barrier Boundary\n", __FUNCTION__, __LINE__);
167 BarrierState = BARRIER_NONE;
170 ErrorF("[%s:%d] Set MLS Barrier Boundary (%d, %d) (%d, %d)\n", __FUNCTION__, __LINE__, val[0], val[1], val[2], val[3]);
171 boundary->x1 = val[0];
172 boundary->x2 = val[2];
173 boundary->y1 = val[1];
174 boundary->y2 = val[3];
178 barrierState EvdevProxyLocationManager(int x, int y, barrierBoundary boundary)
180 if ((boundary.x1+boundary.y1+boundary.x2+boundary.y2) <= 0 ) {
183 else if ( (boundary.x1 <= x && x <=boundary.x2)
184 && (boundary.y1 <= y && y <=boundary.y2) ) {
185 return BARRIER_INSIDE;
187 return BARRIER_OUTSIDE;
190 void EvdevProxyProcessRawMotion(int screen_num, InternalEvent * ev,DeviceIntPtr device)
192 if (device->id != VCP_ID)
193 last_id = device->id;
194 device->public.processInputProc(ev, device);
197 void EvdevProxyProcessMotion(int screen_num, InternalEvent * ev,DeviceIntPtr device)
199 DeviceEvent *dev = &(ev->changed_event);
200 barrierState prevBarrierState = BarrierState;
202 ErrorF("[%s:%d] It is not a device event\n", __FUNCTION__, __LINE__);
205 if (last_id != device->id) {
210 BarrierState = EvdevProxyLocationManager(dev->root_x, dev->root_y, BarrierBoundary);
211 if (BarrierState == BARRIER_NONE)
213 else if (prevBarrierState == BarrierState)
215 else if (prevBarrierState == BARRIER_INSIDE) {
216 ErrorF("[%s:%d] Pointer in to barrier from outside\n", __FUNCTION__, __LINE__);
218 RegisterBlockAndWakeupHandlers(EvdevProxyBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, (InputInfoPtr)(proxyDev->public.devicePrivate));
221 else if (prevBarrierState == BARRIER_OUTSIDE) {
222 ErrorF("[%s:%d] Pointer out to barrier from inside\n", __FUNCTION__, __LINE__);
224 RegisterBlockAndWakeupHandlers(EvdevProxyBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, (InputInfoPtr)(proxyDev->public.devicePrivate));
227 else if (prevBarrierState == BARRIER_NONE && BarrierState == BARRIER_INSIDE) {
228 ErrorF("[%s:%d] Pointer move start from inside\n", __FUNCTION__, __LINE__);
230 RegisterBlockAndWakeupHandlers(EvdevProxyBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, (InputInfoPtr)(proxyDev->public.devicePrivate));
235 device->public.processInputProc(ev, device);
238 void EvdevProxyInit(DeviceIntPtr device)
240 InputInfoPtr pInfo = device->public.devicePrivate;;
241 EvdevPtr pEvdev = pInfo->private;
243 XIRegisterPropertyHandler(device, EvdevProxySetProperty, NULL, EvdevProxyDeleteProperty);
244 mieqSetHandler(ET_Motion, EvdevProxyProcessMotion);
245 mieqSetHandler(ET_RawMotion, EvdevProxyProcessRawMotion);
249 BarrierBoundary.x1 = 0;
250 BarrierBoundary.y1 = 0;
251 BarrierBoundary.x2 = 0;
252 BarrierBoundary.y2 = 0;
253 BarrierState = BARRIER_NONE;
257 atom_MLS_Barrier_Boundary = MakeAtom(prop_MLS_Barrier_Boundary, strlen(prop_MLS_Barrier_Boundary), TRUE);
258 atom_MLS_Barrier_Hit = MakeAtom(prop_MLS_Barrier_Hit, strlen(prop_MLS_Barrier_Hit), TRUE);
259 prop_ungrab_device = MakeAtom(XI_PROP_UNGRAB_DEVICE, strlen(XI_PROP_UNGRAB_DEVICE), TRUE);
263 EvdevProxySetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
266 if (atom == atom_MLS_Barrier_Boundary) {
267 if (val->format != 32 || val->type != XA_INTEGER)
269 if (val->size != 4 && val->size != 0)
273 EvdevProxySetBarrierBoundary(val->size, val->data, &BarrierBoundary);
277 else if (atom == prop_ungrab_device )
280 DeviceIntPtr master = inputInfo.pointer;
283 data = *((CARD8*)val->data);
284 if (data == 1 && master->deviceGrab.grab) {
285 ErrorF("[%s:%d] ungrab master pointer device(%d) in device (%d)\n", __FUNCTION__, __LINE__, master->id, dev->id);
286 (*master->deviceGrab.DeactivateGrab) (master);
295 EvdevProxyDeleteProperty(DeviceIntPtr dev, Atom atom)
297 if (atom == atom_MLS_Barrier_Boundary) {
298 EvdevProxySetBarrierBoundary(0, NULL, &BarrierBoundary);
303 #endif //_F_PROXY_DEVICE_ENABLED_