1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * All Rights Reserved.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining
7*4882a593Smuzhiyun * a copy of this software and associated documentation files (the
8*4882a593Smuzhiyun * "Software"), to deal in the Software without restriction, including
9*4882a593Smuzhiyun * without limitation on the rights to use, copy, modify, merge,
10*4882a593Smuzhiyun * publish, distribute, sublicense, and/or sell copies of the Software,
11*4882a593Smuzhiyun * and to permit persons to whom the Software is furnished to do so,
12*4882a593Smuzhiyun * subject to the following conditions:
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the
15*4882a593Smuzhiyun * next paragraph) shall be included in all copies or substantial
16*4882a593Smuzhiyun * portions of the Software.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*4882a593Smuzhiyun * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22*4882a593Smuzhiyun * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23*4882a593Smuzhiyun * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24*4882a593Smuzhiyun * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25*4882a593Smuzhiyun * SOFTWARE.
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun * Authors:
30*4882a593Smuzhiyun * Rickard E. (Rik) Faith <faith@redhat.com>
31*4882a593Smuzhiyun *
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun /** \file
35*4882a593Smuzhiyun * Provide support and helper functions for enqueing events received by
36*4882a593Smuzhiyun * the low-level input drivers. */
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #ifdef HAVE_DMX_CONFIG_H
39*4882a593Smuzhiyun #include <dmx-config.h>
40*4882a593Smuzhiyun #endif
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #define DMX_EVENTS_DEBUG 0
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #include "dmxinputinit.h"
45*4882a593Smuzhiyun #include "dmxevents.h"
46*4882a593Smuzhiyun #include "dmxcb.h"
47*4882a593Smuzhiyun #include "dmxcommon.h"
48*4882a593Smuzhiyun #include "dmxcursor.h"
49*4882a593Smuzhiyun #include "dmxmotion.h"
50*4882a593Smuzhiyun #include "dmxmap.h"
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun #include <X11/keysym.h>
53*4882a593Smuzhiyun #include "opaque.h"
54*4882a593Smuzhiyun #include "inputstr.h"
55*4882a593Smuzhiyun #include "inpututils.h"
56*4882a593Smuzhiyun #include "mipointer.h"
57*4882a593Smuzhiyun #include "mi.h"
58*4882a593Smuzhiyun #include "exglobals.h"
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun #include "xkbsrv.h"
61*4882a593Smuzhiyun #include "XIstubs.h"
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static int dmxGlobalX, dmxGlobalY; /* Global cursor position */
64*4882a593Smuzhiyun static int dmxGlobalInvalid; /* Flag indicating dmxCoreMotion
65*4882a593Smuzhiyun * should move the mouse anyway. */
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun #if DMX_EVENTS_DEBUG
68*4882a593Smuzhiyun #define DMXDBG0(f) dmxLog(dmxDebug,f)
69*4882a593Smuzhiyun #define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
70*4882a593Smuzhiyun #define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
71*4882a593Smuzhiyun #define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
72*4882a593Smuzhiyun #define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
73*4882a593Smuzhiyun #define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
74*4882a593Smuzhiyun #define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
75*4882a593Smuzhiyun #define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
76*4882a593Smuzhiyun #else
77*4882a593Smuzhiyun #define DMXDBG0(f)
78*4882a593Smuzhiyun #define DMXDBG1(f,a)
79*4882a593Smuzhiyun #define DMXDBG2(f,a,b)
80*4882a593Smuzhiyun #define DMXDBG3(f,a,b,c)
81*4882a593Smuzhiyun #define DMXDBG4(f,a,b,c,d)
82*4882a593Smuzhiyun #define DMXDBG5(f,a,b,c,d,e)
83*4882a593Smuzhiyun #define DMXDBG6(f,a,b,c,d,e,g)
84*4882a593Smuzhiyun #define DMXDBG7(f,a,b,c,d,e,g,h)
85*4882a593Smuzhiyun #endif
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun static int
dmxApplyFunctions(DMXInputInfo * dmxInput,DMXFunctionType f)88*4882a593Smuzhiyun dmxApplyFunctions(DMXInputInfo * dmxInput, DMXFunctionType f)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun int i;
91*4882a593Smuzhiyun int rc = 0;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
94*4882a593Smuzhiyun if (dmxInput->devs[i]->functions)
95*4882a593Smuzhiyun rc += dmxInput->devs[i]->functions(dmxInput->devs[i]->private, f);
96*4882a593Smuzhiyun return rc;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun static int
dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal,int type,KeySym keySym)100*4882a593Smuzhiyun dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal, int type, KeySym keySym)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun #if 1 /* hack to detect ctrl-alt-q, etc */
105*4882a593Smuzhiyun static int ctrl = 0, alt = 0;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* keep track of ctrl/alt key status */
108*4882a593Smuzhiyun if (type == KeyPress && keySym == 0xffe3) {
109*4882a593Smuzhiyun ctrl = 1;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun else if (type == KeyRelease && keySym == 0xffe3) {
112*4882a593Smuzhiyun ctrl = 0;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun else if (type == KeyPress && keySym == 0xffe9) {
115*4882a593Smuzhiyun alt = 1;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun else if (type == KeyRelease && keySym == 0xffe9) {
118*4882a593Smuzhiyun alt = 0;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun if (!ctrl || !alt)
121*4882a593Smuzhiyun return 0;
122*4882a593Smuzhiyun #else
123*4882a593Smuzhiyun unsigned short state = 0;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun if (dmxLocal->sendsCore)
126*4882a593Smuzhiyun state = dmxLocalCoreKeyboard->pDevice->key->state;
127*4882a593Smuzhiyun else if (dmxLocal->pDevice->key)
128*4882a593Smuzhiyun state = dmxLocal->pDevice->key->state;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun DMXDBG3("dmxCheckFunctionKeys: keySym=0x%04x %s state=0x%04x\n",
131*4882a593Smuzhiyun keySym, type == KeyPress ? "press" : "release", state);
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun if ((state & (ControlMask | Mod1Mask)) != (ControlMask | Mod1Mask))
134*4882a593Smuzhiyun return 0;
135*4882a593Smuzhiyun #endif
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun switch (keySym) {
138*4882a593Smuzhiyun case XK_g:
139*4882a593Smuzhiyun if (type == KeyPress)
140*4882a593Smuzhiyun dmxApplyFunctions(dmxInput, DMX_FUNCTION_GRAB);
141*4882a593Smuzhiyun return 1;
142*4882a593Smuzhiyun case XK_f:
143*4882a593Smuzhiyun if (type == KeyPress)
144*4882a593Smuzhiyun dmxApplyFunctions(dmxInput, DMX_FUNCTION_FINE);
145*4882a593Smuzhiyun return 1;
146*4882a593Smuzhiyun case XK_q:
147*4882a593Smuzhiyun if (type == KeyPress && dmxLocal->sendsCore)
148*4882a593Smuzhiyun if (dmxApplyFunctions(dmxInput, DMX_FUNCTION_TERMINATE)) {
149*4882a593Smuzhiyun dmxLog(dmxInfo, "User request for termination\n");
150*4882a593Smuzhiyun dispatchException |= DE_TERMINATE;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun return 1;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun DMXScreenInfo *
dmxFindFirstScreen(int x,int y)159*4882a593Smuzhiyun dmxFindFirstScreen(int x, int y)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun int i;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun for (i = 0; i < dmxNumScreens; i++) {
164*4882a593Smuzhiyun DMXScreenInfo *dmxScreen = &dmxScreens[i];
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun if (dmxOnScreen(x, y, dmxScreen))
167*4882a593Smuzhiyun return dmxScreen;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun return NULL;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun /**
173*4882a593Smuzhiyun * Enqueue a motion event.
174*4882a593Smuzhiyun */
175*4882a593Smuzhiyun static void
enqueueMotion(DevicePtr pDev,int x,int y)176*4882a593Smuzhiyun enqueueMotion(DevicePtr pDev, int x, int y)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun GETDMXLOCALFROMPDEV;
179*4882a593Smuzhiyun DeviceIntPtr p = dmxLocal->pDevice;
180*4882a593Smuzhiyun int valuators[3];
181*4882a593Smuzhiyun int detail = 0; /* XXX should this be mask of pressed buttons? */
182*4882a593Smuzhiyun ValuatorMask mask;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun valuators[0] = x;
185*4882a593Smuzhiyun valuators[1] = y;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun valuator_mask_set_range(&mask, 0, 2, valuators);
188*4882a593Smuzhiyun QueuePointerEvents(p, MotionNotify, detail,
189*4882a593Smuzhiyun POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
190*4882a593Smuzhiyun return;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun void
dmxCoreMotion(DevicePtr pDev,int x,int y,int delta,DMXBlockType block)194*4882a593Smuzhiyun dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun DMXScreenInfo *dmxScreen;
197*4882a593Smuzhiyun DMXInputInfo *dmxInput;
198*4882a593Smuzhiyun ScreenPtr pScreen;
199*4882a593Smuzhiyun int localX;
200*4882a593Smuzhiyun int localY;
201*4882a593Smuzhiyun int i;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun if (!dmxGlobalInvalid && dmxGlobalX == x && dmxGlobalY == y)
204*4882a593Smuzhiyun return;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun DMXDBG5("dmxCoreMotion(%d,%d,%d) dmxGlobalX=%d dmxGlobalY=%d\n",
207*4882a593Smuzhiyun x, y, delta, dmxGlobalX, dmxGlobalY);
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun dmxGlobalInvalid = 0;
210*4882a593Smuzhiyun dmxGlobalX = x;
211*4882a593Smuzhiyun dmxGlobalY = y;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (dmxGlobalX < 0)
214*4882a593Smuzhiyun dmxGlobalX = 0;
215*4882a593Smuzhiyun if (dmxGlobalY < 0)
216*4882a593Smuzhiyun dmxGlobalY = 0;
217*4882a593Smuzhiyun if (dmxGlobalX >= dmxGlobalWidth)
218*4882a593Smuzhiyun dmxGlobalX = dmxGlobalWidth + delta - 1;
219*4882a593Smuzhiyun if (dmxGlobalY >= dmxGlobalHeight)
220*4882a593Smuzhiyun dmxGlobalY = dmxGlobalHeight + delta - 1;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if ((dmxScreen = dmxFindFirstScreen(dmxGlobalX, dmxGlobalY))) {
223*4882a593Smuzhiyun localX = dmxGlobalX - dmxScreen->rootXOrigin;
224*4882a593Smuzhiyun localY = dmxGlobalY - dmxScreen->rootYOrigin;
225*4882a593Smuzhiyun if ((pScreen = miPointerGetScreen(inputInfo.pointer))
226*4882a593Smuzhiyun && pScreen->myNum == dmxScreen->index) {
227*4882a593Smuzhiyun /* Screen is old screen */
228*4882a593Smuzhiyun if (block)
229*4882a593Smuzhiyun input_lock();
230*4882a593Smuzhiyun if (pDev)
231*4882a593Smuzhiyun enqueueMotion(pDev, localX, localY);
232*4882a593Smuzhiyun if (block)
233*4882a593Smuzhiyun input_unlock();
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun else {
236*4882a593Smuzhiyun /* Screen is new */
237*4882a593Smuzhiyun DMXDBG4(" New screen: old=%d new=%d localX=%d localY=%d\n",
238*4882a593Smuzhiyun pScreen->myNum, dmxScreen->index, localX, localY);
239*4882a593Smuzhiyun if (block)
240*4882a593Smuzhiyun input_lock();
241*4882a593Smuzhiyun mieqProcessInputEvents();
242*4882a593Smuzhiyun miPointerSetScreen(inputInfo.pointer, dmxScreen->index,
243*4882a593Smuzhiyun localX, localY);
244*4882a593Smuzhiyun if (pDev)
245*4882a593Smuzhiyun enqueueMotion(pDev, localX, localY);
246*4882a593Smuzhiyun if (block)
247*4882a593Smuzhiyun input_unlock();
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun #if 00
250*4882a593Smuzhiyun miPointerGetPosition(inputInfo.pointer, &localX, &localY);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun if ((pScreen = miPointerGetScreen(inputInfo.pointer))) {
253*4882a593Smuzhiyun dmxGlobalX = localX + dmxScreens[pScreen->myNum].rootXOrigin;
254*4882a593Smuzhiyun dmxGlobalY = localY + dmxScreens[pScreen->myNum].rootYOrigin;
255*4882a593Smuzhiyun ErrorF("Global is now %d, %d %d, %d\n", dmxGlobalX, dmxGlobalY,
256*4882a593Smuzhiyun localX, localY);
257*4882a593Smuzhiyun DMXDBG6(" Moved to dmxGlobalX=%d dmxGlobalY=%d"
258*4882a593Smuzhiyun " on screen index=%d/%d localX=%d localY=%d\n",
259*4882a593Smuzhiyun dmxGlobalX, dmxGlobalY,
260*4882a593Smuzhiyun dmxScreen ? dmxScreen->index : -1, pScreen->myNum,
261*4882a593Smuzhiyun localX, localY);
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun #endif
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun /* Send updates down to all core input
266*4882a593Smuzhiyun * drivers */
267*4882a593Smuzhiyun for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) {
268*4882a593Smuzhiyun int j;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun for (j = 0; j < dmxInput->numDevs; j += dmxInput->devs[j]->binding)
271*4882a593Smuzhiyun if (!dmxInput->detached
272*4882a593Smuzhiyun && dmxInput->devs[j]->sendsCore
273*4882a593Smuzhiyun && dmxInput->devs[j]->update_position)
274*4882a593Smuzhiyun dmxInput->devs[j]->update_position(dmxInput->devs[j]->private,
275*4882a593Smuzhiyun dmxGlobalX, dmxGlobalY);
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun if (!dmxScreen)
278*4882a593Smuzhiyun ProcessInputEvents();
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun #define DMX_MAX_AXES 32 /* Max axes reported by this routine */
282*4882a593Smuzhiyun static void
dmxExtMotion(DMXLocalInputInfoPtr dmxLocal,int * v,int firstAxis,int axesCount,DMXMotionType type,DMXBlockType block)283*4882a593Smuzhiyun dmxExtMotion(DMXLocalInputInfoPtr dmxLocal,
284*4882a593Smuzhiyun int *v, int firstAxis, int axesCount,
285*4882a593Smuzhiyun DMXMotionType type, DMXBlockType block)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun DeviceIntPtr pDevice = dmxLocal->pDevice;
288*4882a593Smuzhiyun xEvent xE[2 * DMX_MAX_AXES / 6];
289*4882a593Smuzhiyun deviceKeyButtonPointer *xev = (deviceKeyButtonPointer *) xE;
290*4882a593Smuzhiyun deviceValuator *xv = (deviceValuator *) xev + 1;
291*4882a593Smuzhiyun int thisX = 0;
292*4882a593Smuzhiyun int thisY = 0;
293*4882a593Smuzhiyun int count;
294*4882a593Smuzhiyun ValuatorMask mask;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun memset(xE, 0, sizeof(xE));
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun if (axesCount > DMX_MAX_AXES)
299*4882a593Smuzhiyun axesCount = DMX_MAX_AXES;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun if ((valuator_get_mode(pDevice, 0) == Relative) && axesCount == 2) {
302*4882a593Smuzhiyun /* The dmx console is a relative mode
303*4882a593Smuzhiyun * device that sometimes reports
304*4882a593Smuzhiyun * absolute motion. It only has two
305*4882a593Smuzhiyun * axes. */
306*4882a593Smuzhiyun if (type == DMX_RELATIVE) {
307*4882a593Smuzhiyun thisX = -v[0];
308*4882a593Smuzhiyun thisY = -v[1];
309*4882a593Smuzhiyun dmxLocal->lastX += thisX;
310*4882a593Smuzhiyun dmxLocal->lastY += thisY;
311*4882a593Smuzhiyun if (dmxLocal->update_position)
312*4882a593Smuzhiyun dmxLocal->update_position(dmxLocal->private,
313*4882a593Smuzhiyun dmxLocal->lastX, dmxLocal->lastY);
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun else { /* Convert to relative */
316*4882a593Smuzhiyun if (dmxLocal->lastX || dmxLocal->lastY) {
317*4882a593Smuzhiyun thisX = v[0] - dmxLocal->lastX;
318*4882a593Smuzhiyun thisY = v[1] - dmxLocal->lastY;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun dmxLocal->lastX = v[0];
321*4882a593Smuzhiyun dmxLocal->lastY = v[1];
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun v[0] = thisX;
324*4882a593Smuzhiyun v[1] = thisY;
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun if (axesCount <= 6) {
328*4882a593Smuzhiyun /* Optimize for the common case when
329*4882a593Smuzhiyun * only 1 or 2 axes change. */
330*4882a593Smuzhiyun xev->time = GetTimeInMillis();
331*4882a593Smuzhiyun xev->type = DeviceMotionNotify;
332*4882a593Smuzhiyun xev->detail = 0;
333*4882a593Smuzhiyun xev->deviceid = pDevice->id | MORE_EVENTS;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun xv->type = DeviceValuator;
336*4882a593Smuzhiyun xv->deviceid = pDevice->id;
337*4882a593Smuzhiyun xv->num_valuators = axesCount;
338*4882a593Smuzhiyun xv->first_valuator = firstAxis;
339*4882a593Smuzhiyun switch (xv->num_valuators) {
340*4882a593Smuzhiyun case 6:
341*4882a593Smuzhiyun xv->valuator5 = v[5];
342*4882a593Smuzhiyun case 5:
343*4882a593Smuzhiyun xv->valuator4 = v[4];
344*4882a593Smuzhiyun case 4:
345*4882a593Smuzhiyun xv->valuator3 = v[3];
346*4882a593Smuzhiyun case 3:
347*4882a593Smuzhiyun xv->valuator2 = v[2];
348*4882a593Smuzhiyun case 2:
349*4882a593Smuzhiyun xv->valuator1 = v[1];
350*4882a593Smuzhiyun case 1:
351*4882a593Smuzhiyun xv->valuator0 = v[0];
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun count = 2;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun else {
356*4882a593Smuzhiyun int i;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun for (i = 0, count = 0; i < axesCount; i += 6) {
359*4882a593Smuzhiyun xev->time = GetTimeInMillis();
360*4882a593Smuzhiyun xev->type = DeviceMotionNotify;
361*4882a593Smuzhiyun xev->detail = 0;
362*4882a593Smuzhiyun xev->deviceid = pDevice->id | MORE_EVENTS;
363*4882a593Smuzhiyun xev += 2;
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun xv->type = DeviceValuator;
366*4882a593Smuzhiyun xv->deviceid = pDevice->id;
367*4882a593Smuzhiyun xv->num_valuators = (i + 6 >= axesCount ? axesCount - i : 6);
368*4882a593Smuzhiyun xv->first_valuator = firstAxis + i;
369*4882a593Smuzhiyun switch (xv->num_valuators) {
370*4882a593Smuzhiyun case 6:
371*4882a593Smuzhiyun xv->valuator5 = v[i + 5];
372*4882a593Smuzhiyun case 5:
373*4882a593Smuzhiyun xv->valuator4 = v[i + 4];
374*4882a593Smuzhiyun case 4:
375*4882a593Smuzhiyun xv->valuator3 = v[i + 3];
376*4882a593Smuzhiyun case 3:
377*4882a593Smuzhiyun xv->valuator2 = v[i + 2];
378*4882a593Smuzhiyun case 2:
379*4882a593Smuzhiyun xv->valuator1 = v[i + 1];
380*4882a593Smuzhiyun case 1:
381*4882a593Smuzhiyun xv->valuator0 = v[i + 0];
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun xv += 2;
384*4882a593Smuzhiyun count += 2;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun if (block)
389*4882a593Smuzhiyun input_lock();
390*4882a593Smuzhiyun valuator_mask_set_range(&mask, firstAxis, axesCount, v);
391*4882a593Smuzhiyun QueuePointerEvents(pDevice, MotionNotify, 0, POINTER_ABSOLUTE, &mask);
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun if (block)
394*4882a593Smuzhiyun input_unlock();
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun static int
dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,XEvent * e,DMXBlockType block)398*4882a593Smuzhiyun dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
399*4882a593Smuzhiyun XEvent * e, DMXBlockType block)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun int type;
402*4882a593Smuzhiyun int event = -1;
403*4882a593Smuzhiyun XDeviceKeyEvent *ke = (XDeviceKeyEvent *) e;
404*4882a593Smuzhiyun XDeviceMotionEvent *me = (XDeviceMotionEvent *) e;
405*4882a593Smuzhiyun DeviceIntPtr pDevice = dmxLocal->pDevice;
406*4882a593Smuzhiyun int valuators[MAX_VALUATORS];
407*4882a593Smuzhiyun ValuatorMask mask;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun if (!e)
410*4882a593Smuzhiyun return -1; /* No extended event passed, cannot handle */
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun if ((XID) dmxLocal->deviceId != ke->deviceid) {
413*4882a593Smuzhiyun /* Search for the correct dmxLocal,
414*4882a593Smuzhiyun * since backend and console events are
415*4882a593Smuzhiyun * picked up for the first device on
416*4882a593Smuzhiyun * that X server. */
417*4882a593Smuzhiyun int i;
418*4882a593Smuzhiyun DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++) {
421*4882a593Smuzhiyun dmxLocal = dmxInput->devs[i];
422*4882a593Smuzhiyun if ((XID) dmxLocal->deviceId == ke->deviceid)
423*4882a593Smuzhiyun break;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun if ((XID) dmxLocal->deviceId != ke->deviceid
428*4882a593Smuzhiyun || (type = dmxMapLookup(dmxLocal, e->type)) < 0)
429*4882a593Smuzhiyun return -1; /* No mapping, so this event is unhandled */
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun switch (type) {
432*4882a593Smuzhiyun case XI_DeviceValuator:
433*4882a593Smuzhiyun event = DeviceValuator;
434*4882a593Smuzhiyun break;
435*4882a593Smuzhiyun case XI_DeviceKeyPress:
436*4882a593Smuzhiyun event = KeyPress;
437*4882a593Smuzhiyun break;
438*4882a593Smuzhiyun case XI_DeviceKeyRelease:
439*4882a593Smuzhiyun event = KeyRelease;
440*4882a593Smuzhiyun break;
441*4882a593Smuzhiyun case XI_DeviceButtonPress:
442*4882a593Smuzhiyun event = ButtonPress;
443*4882a593Smuzhiyun break;
444*4882a593Smuzhiyun case XI_DeviceButtonRelease:
445*4882a593Smuzhiyun event = ButtonRelease;
446*4882a593Smuzhiyun break;
447*4882a593Smuzhiyun case XI_DeviceMotionNotify:
448*4882a593Smuzhiyun event = MotionNotify;
449*4882a593Smuzhiyun break;
450*4882a593Smuzhiyun case XI_DeviceFocusIn:
451*4882a593Smuzhiyun event = DeviceFocusIn;
452*4882a593Smuzhiyun break;
453*4882a593Smuzhiyun case XI_DeviceFocusOut:
454*4882a593Smuzhiyun event = DeviceFocusOut;
455*4882a593Smuzhiyun break;
456*4882a593Smuzhiyun case XI_ProximityIn:
457*4882a593Smuzhiyun event = ProximityIn;
458*4882a593Smuzhiyun break;
459*4882a593Smuzhiyun case XI_ProximityOut:
460*4882a593Smuzhiyun event = ProximityOut;
461*4882a593Smuzhiyun break;
462*4882a593Smuzhiyun case XI_DeviceStateNotify:
463*4882a593Smuzhiyun event = DeviceStateNotify;
464*4882a593Smuzhiyun break;
465*4882a593Smuzhiyun case XI_DeviceMappingNotify:
466*4882a593Smuzhiyun event = DeviceMappingNotify;
467*4882a593Smuzhiyun break;
468*4882a593Smuzhiyun case XI_ChangeDeviceNotify:
469*4882a593Smuzhiyun event = ChangeDeviceNotify;
470*4882a593Smuzhiyun break;
471*4882a593Smuzhiyun case XI_DeviceKeystateNotify:
472*4882a593Smuzhiyun event = DeviceStateNotify;
473*4882a593Smuzhiyun break;
474*4882a593Smuzhiyun case XI_DeviceButtonstateNotify:
475*4882a593Smuzhiyun event = DeviceStateNotify;
476*4882a593Smuzhiyun break;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun #define EXTRACT_VALUATORS(ke, valuators) \
480*4882a593Smuzhiyun valuators[0] = ke->axis_data[0]; \
481*4882a593Smuzhiyun valuators[1] = ke->axis_data[1]; \
482*4882a593Smuzhiyun valuators[2] = ke->axis_data[2]; \
483*4882a593Smuzhiyun valuators[3] = ke->axis_data[3]; \
484*4882a593Smuzhiyun valuators[4] = ke->axis_data[4]; \
485*4882a593Smuzhiyun valuators[5] = ke->axis_data[5]; \
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun switch (type) {
488*4882a593Smuzhiyun case XI_DeviceKeyPress:
489*4882a593Smuzhiyun case XI_DeviceKeyRelease:
490*4882a593Smuzhiyun if (block)
491*4882a593Smuzhiyun input_lock();
492*4882a593Smuzhiyun QueueKeyboardEvents(pDevice, event, ke->keycode);
493*4882a593Smuzhiyun if (block)
494*4882a593Smuzhiyun input_unlock();
495*4882a593Smuzhiyun break;
496*4882a593Smuzhiyun case XI_DeviceButtonPress:
497*4882a593Smuzhiyun case XI_DeviceButtonRelease:
498*4882a593Smuzhiyun EXTRACT_VALUATORS(ke, valuators);
499*4882a593Smuzhiyun valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count,
500*4882a593Smuzhiyun valuators);
501*4882a593Smuzhiyun if (block)
502*4882a593Smuzhiyun input_lock();
503*4882a593Smuzhiyun QueuePointerEvents(pDevice, event, ke->keycode,
504*4882a593Smuzhiyun POINTER_ABSOLUTE, &mask);
505*4882a593Smuzhiyun if (block)
506*4882a593Smuzhiyun input_unlock();
507*4882a593Smuzhiyun break;
508*4882a593Smuzhiyun case XI_ProximityIn:
509*4882a593Smuzhiyun case XI_ProximityOut:
510*4882a593Smuzhiyun EXTRACT_VALUATORS(ke, valuators);
511*4882a593Smuzhiyun valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count,
512*4882a593Smuzhiyun valuators);
513*4882a593Smuzhiyun if (block)
514*4882a593Smuzhiyun input_lock();
515*4882a593Smuzhiyun QueueProximityEvents(pDevice, event, &mask);
516*4882a593Smuzhiyun if (block)
517*4882a593Smuzhiyun input_unlock();
518*4882a593Smuzhiyun break;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun break;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun case XI_DeviceMotionNotify:
523*4882a593Smuzhiyun dmxExtMotion(dmxLocal, me->axis_data, me->first_axis, me->axes_count,
524*4882a593Smuzhiyun DMX_ABSOLUTE, block);
525*4882a593Smuzhiyun break;
526*4882a593Smuzhiyun case XI_DeviceFocusIn:
527*4882a593Smuzhiyun case XI_DeviceFocusOut:
528*4882a593Smuzhiyun case XI_DeviceStateNotify:
529*4882a593Smuzhiyun case XI_DeviceMappingNotify:
530*4882a593Smuzhiyun case XI_ChangeDeviceNotify:
531*4882a593Smuzhiyun case XI_DeviceKeystateNotify:
532*4882a593Smuzhiyun case XI_DeviceButtonstateNotify:
533*4882a593Smuzhiyun /* These are ignored, since DMX will
534*4882a593Smuzhiyun * generate its own events of these
535*4882a593Smuzhiyun * types, as necessary.
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun * Perhaps ChangeDeviceNotify should
538*4882a593Smuzhiyun * generate an error, because it is
539*4882a593Smuzhiyun * unexpected? */
540*4882a593Smuzhiyun break;
541*4882a593Smuzhiyun case XI_DeviceValuator:
542*4882a593Smuzhiyun default:
543*4882a593Smuzhiyun dmxLog(dmxWarning,
544*4882a593Smuzhiyun "XInput extension event (remote=%d -> zero-based=%d)"
545*4882a593Smuzhiyun " not supported yet\n", e->type, type);
546*4882a593Smuzhiyun return -1;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun return 0;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun static int
dmxGetButtonMapping(DMXLocalInputInfoPtr dmxLocal,int button)552*4882a593Smuzhiyun dmxGetButtonMapping(DMXLocalInputInfoPtr dmxLocal, int button)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun ButtonClassPtr b = dmxLocal->pDevice->button;
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun if (button > b->numButtons) { /* This shouldn't happen. */
557*4882a593Smuzhiyun dmxLog(dmxWarning, "Button %d pressed, but only %d buttons?!?\n",
558*4882a593Smuzhiyun button, b->numButtons);
559*4882a593Smuzhiyun return button;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun return b->map[button];
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /** Return DMX's notion of the pointer position in the global coordinate
565*4882a593Smuzhiyun * space. */
566*4882a593Smuzhiyun void
dmxGetGlobalPosition(int * x,int * y)567*4882a593Smuzhiyun dmxGetGlobalPosition(int *x, int *y)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun *x = dmxGlobalX;
570*4882a593Smuzhiyun *y = dmxGlobalY;
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /** Invalidate the global position for #dmxCoreMotion. */
574*4882a593Smuzhiyun void
dmxInvalidateGlobalPosition(void)575*4882a593Smuzhiyun dmxInvalidateGlobalPosition(void)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun dmxGlobalInvalid = 1;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun /** Enqueue a motion event for \a pDev. The \a v vector has length \a
581*4882a593Smuzhiyun * axesCount, and contains values for each of the axes, starting at \a
582*4882a593Smuzhiyun * firstAxes.
583*4882a593Smuzhiyun *
584*4882a593Smuzhiyun * The \a type of the motion may be \a DMX_RELATIVE, \a DMX_ABSOLUTE, or
585*4882a593Smuzhiyun * \a DMX_ABSOLUTE_CONFINED (in the latter case, the pointer will not be
586*4882a593Smuzhiyun * allowed to move outside the global boundaires).
587*4882a593Smuzhiyun *
588*4882a593Smuzhiyun * If \a block is set to \a DMX_BLOCK, then the input thread will be
589*4882a593Smuzhiyun * blocked around calls to \a enqueueMotion(). */
590*4882a593Smuzhiyun void
dmxMotion(DevicePtr pDev,int * v,int firstAxes,int axesCount,DMXMotionType type,DMXBlockType block)591*4882a593Smuzhiyun dmxMotion(DevicePtr pDev, int *v, int firstAxes, int axesCount,
592*4882a593Smuzhiyun DMXMotionType type, DMXBlockType block)
593*4882a593Smuzhiyun {
594*4882a593Smuzhiyun GETDMXLOCALFROMPDEV;
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun if (!dmxLocal->sendsCore) {
597*4882a593Smuzhiyun dmxExtMotion(dmxLocal, v, firstAxes, axesCount, type, block);
598*4882a593Smuzhiyun return;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun if (axesCount == 2) {
601*4882a593Smuzhiyun switch (type) {
602*4882a593Smuzhiyun case DMX_RELATIVE:
603*4882a593Smuzhiyun dmxCoreMotion(pDev, dmxGlobalX - v[0], dmxGlobalY - v[1], 0, block);
604*4882a593Smuzhiyun break;
605*4882a593Smuzhiyun case DMX_ABSOLUTE:
606*4882a593Smuzhiyun dmxCoreMotion(pDev, v[0], v[1], 0, block);
607*4882a593Smuzhiyun break;
608*4882a593Smuzhiyun case DMX_ABSOLUTE_CONFINED:
609*4882a593Smuzhiyun dmxCoreMotion(pDev, v[0], v[1], -1, block);
610*4882a593Smuzhiyun break;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun static KeySym
dmxKeyCodeToKeySym(DMXLocalInputInfoPtr dmxLocal,KeyCode keyCode)616*4882a593Smuzhiyun dmxKeyCodeToKeySym(DMXLocalInputInfoPtr dmxLocal, KeyCode keyCode)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun KeySym keysym = NoSymbol;
619*4882a593Smuzhiyun int effectiveGroup;
620*4882a593Smuzhiyun XkbSrvInfoPtr xkbi;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun if (!dmxLocal || !dmxLocal->pDevice || !dmxLocal->pDevice->key)
623*4882a593Smuzhiyun goto out;
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun xkbi = dmxLocal->pDevice->key->xkbInfo;
626*4882a593Smuzhiyun effectiveGroup = XkbGetEffectiveGroup(xkbi, &xkbi->state, keyCode);
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun if (effectiveGroup == -1)
629*4882a593Smuzhiyun goto out;
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun keysym = XkbKeySym(xkbi->desc, keyCode, effectiveGroup);
632*4882a593Smuzhiyun DMXDBG2("dmxKeyCodeToKeySym: Translated keyCode=%d to keySym=0x%04x\n",
633*4882a593Smuzhiyun keyCode, keysym);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun out:
636*4882a593Smuzhiyun return keysym;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun static KeyCode
dmxKeySymToKeyCode(DMXLocalInputInfoPtr dmxLocal,KeySym keySym,int tryFirst)640*4882a593Smuzhiyun dmxKeySymToKeyCode(DMXLocalInputInfoPtr dmxLocal, KeySym keySym, int tryFirst)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun /* FIXME: this is quite ineffective, converting to a core map first and
643*4882a593Smuzhiyun * then extracting the info from there. It'd be better to run the actual
644*4882a593Smuzhiyun * xkb map */
645*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = dmxLocal->pDevice->key->xkbInfo;
646*4882a593Smuzhiyun KeySymsPtr pKeySyms = XkbGetCoreMap(dmxLocal->pDevice);
647*4882a593Smuzhiyun int i;
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun /* Optimize for similar maps */
650*4882a593Smuzhiyun if (XkbKeycodeInRange(xkbi->desc, tryFirst)
651*4882a593Smuzhiyun && pKeySyms->map[(tryFirst - xkbi->desc->min_key_code)
652*4882a593Smuzhiyun * pKeySyms->mapWidth] == keySym)
653*4882a593Smuzhiyun return tryFirst;
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun for (i = pKeySyms->minKeyCode; i <= pKeySyms->maxKeyCode; i++) {
656*4882a593Smuzhiyun if (pKeySyms->map[(i - pKeySyms->minKeyCode)
657*4882a593Smuzhiyun * pKeySyms->mapWidth] == keySym) {
658*4882a593Smuzhiyun DMXDBG3("dmxKeySymToKeyCode: Translated keySym=0x%04x to"
659*4882a593Smuzhiyun " keyCode=%d (reverses to core keySym=0x%04x)\n",
660*4882a593Smuzhiyun keySym, i, dmxKeyCodeToKeySym(dmxLocalCoreKeyboard, i));
661*4882a593Smuzhiyun return i;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun return 0;
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun static int
dmxFixup(DevicePtr pDev,int detail,KeySym keySym)668*4882a593Smuzhiyun dmxFixup(DevicePtr pDev, int detail, KeySym keySym)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun GETDMXLOCALFROMPDEV;
671*4882a593Smuzhiyun int keyCode;
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun if (!dmxLocal->pDevice->key) {
674*4882a593Smuzhiyun dmxLog(dmxWarning, "dmxFixup: not a keyboard device (%s)\n",
675*4882a593Smuzhiyun dmxLocal->pDevice->name);
676*4882a593Smuzhiyun return NoSymbol;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun if (!keySym)
679*4882a593Smuzhiyun keySym = dmxKeyCodeToKeySym(dmxLocal, detail);
680*4882a593Smuzhiyun if (keySym == NoSymbol)
681*4882a593Smuzhiyun return detail;
682*4882a593Smuzhiyun keyCode = dmxKeySymToKeyCode(dmxLocalCoreKeyboard, keySym, detail);
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun return keyCode ? keyCode : detail;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun /** Enqueue an event from the \a pDev device with the
688*4882a593Smuzhiyun * specified \a type and \a detail. If the event is a KeyPress or
689*4882a593Smuzhiyun * KeyRelease event, then the \a keySym is also specified.
690*4882a593Smuzhiyun *
691*4882a593Smuzhiyun * FIXME: make the code do what the comment says, or remove this comment.
692*4882a593Smuzhiyun * If \a block is set to \a DMX_BLOCK, then the input thread will be
693*4882a593Smuzhiyun * blocked around calls to dmxeqEnqueue(). */
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun void
dmxEnqueue(DevicePtr pDev,int type,int detail,KeySym keySym,XEvent * e,DMXBlockType block)696*4882a593Smuzhiyun dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
697*4882a593Smuzhiyun XEvent * e, DMXBlockType block)
698*4882a593Smuzhiyun {
699*4882a593Smuzhiyun GETDMXINPUTFROMPDEV;
700*4882a593Smuzhiyun DeviceIntPtr p = dmxLocal->pDevice;
701*4882a593Smuzhiyun int valuators[3];
702*4882a593Smuzhiyun ValuatorMask mask;
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun DMXDBG2("dmxEnqueue: Enqueuing type=%d detail=0x%0x\n", type, detail);
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun switch (type) {
707*4882a593Smuzhiyun case KeyPress:
708*4882a593Smuzhiyun case KeyRelease:
709*4882a593Smuzhiyun if (!keySym)
710*4882a593Smuzhiyun keySym = dmxKeyCodeToKeySym(dmxLocal, detail);
711*4882a593Smuzhiyun if (dmxCheckFunctionKeys(dmxLocal, type, keySym))
712*4882a593Smuzhiyun return;
713*4882a593Smuzhiyun if (dmxLocal->sendsCore && dmxLocal != dmxLocalCoreKeyboard)
714*4882a593Smuzhiyun detail = dmxFixup(pDev, detail, keySym);
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun /*ErrorF("KEY %d sym %d\n", detail, (int) keySym); */
717*4882a593Smuzhiyun QueueKeyboardEvents(p, type, detail);
718*4882a593Smuzhiyun return;
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun case ButtonPress:
721*4882a593Smuzhiyun case ButtonRelease:
722*4882a593Smuzhiyun detail = dmxGetButtonMapping(dmxLocal, detail);
723*4882a593Smuzhiyun valuator_mask_zero(&mask);
724*4882a593Smuzhiyun QueuePointerEvents(p, type, detail, 0, &mask);
725*4882a593Smuzhiyun return;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun case MotionNotify:
728*4882a593Smuzhiyun valuators[0] = e->xmotion.x;
729*4882a593Smuzhiyun valuators[1] = e->xmotion.y;
730*4882a593Smuzhiyun valuators[2] = e->xmotion.state; /* FIXME: WTF?? */
731*4882a593Smuzhiyun valuator_mask_set_range(&mask, 0, 3, valuators);
732*4882a593Smuzhiyun QueuePointerEvents(p, type, detail,
733*4882a593Smuzhiyun POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
734*4882a593Smuzhiyun return;
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun case EnterNotify:
737*4882a593Smuzhiyun case LeaveNotify:
738*4882a593Smuzhiyun case KeymapNotify:
739*4882a593Smuzhiyun case MappingNotify: /* This is sent because we change the
740*4882a593Smuzhiyun * modifier map on the backend/console
741*4882a593Smuzhiyun * input device so that we have complete
742*4882a593Smuzhiyun * control of the input device LEDs. */
743*4882a593Smuzhiyun return;
744*4882a593Smuzhiyun default:
745*4882a593Smuzhiyun if (type == ProximityIn || type == ProximityOut) {
746*4882a593Smuzhiyun if (dmxLocal->sendsCore)
747*4882a593Smuzhiyun return; /* Not a core event */
748*4882a593Smuzhiyun break;
749*4882a593Smuzhiyun }
750*4882a593Smuzhiyun if (type >= LASTEvent) {
751*4882a593Smuzhiyun if (dmxTranslateAndEnqueueExtEvent(dmxLocal, e, block))
752*4882a593Smuzhiyun dmxLogInput(dmxInput, "Unhandled extension event: %d\n", type);
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun else {
755*4882a593Smuzhiyun dmxLogInput(dmxInput, "Unhandled event: %d (%s)\n",
756*4882a593Smuzhiyun type, dmxEventName(type));
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun return;
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun }
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun /** A pointer to this routine is passed to low-level input drivers so
764*4882a593Smuzhiyun * that all special keychecking is unified to this file. This function
765*4882a593Smuzhiyun * returns 0 if no special keys have been pressed. If the user has
766*4882a593Smuzhiyun * requested termination of the DMX server, -1 is returned. If the user
767*4882a593Smuzhiyun * has requested a switch to a VT, then the (1-based) number of that VT
768*4882a593Smuzhiyun * is returned. */
769*4882a593Smuzhiyun int
dmxCheckSpecialKeys(DevicePtr pDev,KeySym keySym)770*4882a593Smuzhiyun dmxCheckSpecialKeys(DevicePtr pDev, KeySym keySym)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun GETDMXINPUTFROMPDEV;
773*4882a593Smuzhiyun int vt = 0;
774*4882a593Smuzhiyun unsigned short state = 0;
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun if (dmxLocal->sendsCore)
777*4882a593Smuzhiyun state =
778*4882a593Smuzhiyun XkbStateFieldFromRec(&dmxLocalCoreKeyboard->pDevice->key->xkbInfo->
779*4882a593Smuzhiyun state);
780*4882a593Smuzhiyun else if (dmxLocal->pDevice->key)
781*4882a593Smuzhiyun state = XkbStateFieldFromRec(&dmxLocal->pDevice->key->xkbInfo->state);
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun if (!dmxLocal->sendsCore)
784*4882a593Smuzhiyun return 0; /* Only for core devices */
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun DMXDBG2("dmxCheckSpecialKeys: keySym=0x%04x state=0x%04x\n", keySym, state);
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun if ((state & (ControlMask | Mod1Mask)) != (ControlMask | Mod1Mask))
789*4882a593Smuzhiyun return 0;
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun switch (keySym) {
792*4882a593Smuzhiyun case XK_F1:
793*4882a593Smuzhiyun case XK_F2:
794*4882a593Smuzhiyun case XK_F3:
795*4882a593Smuzhiyun case XK_F4:
796*4882a593Smuzhiyun case XK_F5:
797*4882a593Smuzhiyun case XK_F6:
798*4882a593Smuzhiyun case XK_F7:
799*4882a593Smuzhiyun case XK_F8:
800*4882a593Smuzhiyun case XK_F9:
801*4882a593Smuzhiyun case XK_F10:
802*4882a593Smuzhiyun vt = keySym - XK_F1 + 1;
803*4882a593Smuzhiyun break;
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun case XK_F11:
806*4882a593Smuzhiyun case XK_F12:
807*4882a593Smuzhiyun vt = keySym - XK_F11 + 11;
808*4882a593Smuzhiyun break;
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun case XK_q: /* To avoid confusion */
811*4882a593Smuzhiyun case XK_BackSpace:
812*4882a593Smuzhiyun case XK_Delete:
813*4882a593Smuzhiyun case XK_KP_Delete:
814*4882a593Smuzhiyun dmxLog(dmxInfo, "User request for termination\n");
815*4882a593Smuzhiyun dispatchException |= DE_TERMINATE;
816*4882a593Smuzhiyun return -1; /* Terminate */
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun if (vt) {
820*4882a593Smuzhiyun dmxLog(dmxInfo, "Request to switch to VT %d\n", vt);
821*4882a593Smuzhiyun dmxInput->vt_switch_pending = vt;
822*4882a593Smuzhiyun return vt;
823*4882a593Smuzhiyun }
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun return 0; /* Do nothing */
826*4882a593Smuzhiyun }
827