xref: /OK3568_Linux_fs/external/xserver/hw/dmx/input/dmxevents.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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