2 * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * Rickard E. (Rik) Faith <faith@redhat.com>
35 * Provide support and helper functions for enqueing events received by
36 * the low-level input drivers. */
38 #ifdef HAVE_DMX_CONFIG_H
39 #include <dmx-config.h>
42 #define DMX_EVENTS_DEBUG 0
44 #include "dmxinputinit.h"
45 #include "dmxevents.h"
47 #include "dmxcommon.h"
48 #include "dmxcursor.h"
49 #include "dmxmotion.h"
54 #include <X11/keysym.h>
57 #include "mipointer.h"
64 static int dmxGlobalX
, dmxGlobalY
; /* Global cursor position */
65 static int dmxGlobalInvalid
; /* Flag indicating dmxCoreMotion
66 * should move the mouse anyway. */
69 #define DMXDBG0(f) dmxLog(dmxDebug,f)
70 #define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
71 #define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
72 #define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
73 #define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
74 #define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
75 #define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
76 #define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
80 #define DMXDBG2(f,a,b)
81 #define DMXDBG3(f,a,b,c)
82 #define DMXDBG4(f,a,b,c,d)
83 #define DMXDBG5(f,a,b,c,d,e)
84 #define DMXDBG6(f,a,b,c,d,e,g)
85 #define DMXDBG7(f,a,b,c,d,e,g,h)
88 static int dmxApplyFunctions(DMXInputInfo
*dmxInput
, DMXFunctionType f
)
93 for (i
= 0; i
< dmxInput
->numDevs
; i
+= dmxInput
->devs
[i
]->binding
)
94 if (dmxInput
->devs
[i
]->functions
)
95 rc
+= dmxInput
->devs
[i
]->functions(dmxInput
->devs
[i
]->private, f
);
99 static int dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal
,
103 DMXInputInfo
*dmxInput
= &dmxInputs
[dmxLocal
->inputIdx
];
104 unsigned short state
= 0;
106 #if 1 /* hack to detect ctrl-alt-q, etc */
107 static int ctrl
= 0, alt
= 0;
108 /* keep track of ctrl/alt key status */
109 if (type
== KeyPress
&& keySym
== 0xffe3) {
112 else if (type
== KeyRelease
&& keySym
== 0xffe3) {
115 else if (type
== KeyPress
&& keySym
== 0xffe9) {
118 else if (type
== KeyRelease
&& keySym
== 0xffe9) {
124 if (dmxLocal
->sendsCore
)
125 state
= dmxLocalCoreKeyboard
->pDevice
->key
->state
;
126 else if (dmxLocal
->pDevice
->key
)
127 state
= dmxLocal
->pDevice
->key
->state
;
129 DMXDBG3("dmxCheckFunctionKeys: keySym=0x%04x %s state=0x%04x\n",
130 keySym
, type
== KeyPress
? "press" : "release", state
);
132 if ((state
& (ControlMask
|Mod1Mask
)) != (ControlMask
|Mod1Mask
))
138 if (type
== KeyPress
)
139 dmxApplyFunctions(dmxInput
, DMX_FUNCTION_GRAB
);
142 if (type
== KeyPress
)
143 dmxApplyFunctions(dmxInput
, DMX_FUNCTION_FINE
);
146 if (type
== KeyPress
&& dmxLocal
->sendsCore
)
147 if (dmxApplyFunctions(dmxInput
, DMX_FUNCTION_TERMINATE
)) {
148 dmxLog(dmxInfo
, "User request for termination\n");
149 dispatchException
|= DE_TERMINATE
;
158 static void dmxEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal
, xEvent
*e
,
162 deviceKeyButtonPointer
*xev
= (deviceKeyButtonPointer
*)xE
;
163 deviceValuator
*xv
= (deviceValuator
*)xev
+1;
164 DeviceIntPtr pDevice
= dmxLocal
->pDevice
;
165 DMXInputInfo
*dmxInput
= &dmxInputs
[dmxLocal
->inputIdx
];
166 int type
= e
->u
.u
.type
;
168 switch (e
->u
.u
.type
) {
170 type
= DeviceKeyPress
;
173 type
= DeviceKeyRelease
;
176 type
= DeviceButtonPress
;
179 type
= DeviceButtonRelease
;
183 "dmxEnqueueExtEvent: MotionNotify not allowed here\n");
186 if (e
->u
.u
.type
== ProximityIn
|| e
->u
.u
.type
== ProximityOut
)
188 dmxLogInput(dmxInput
,
189 "dmxEnqueueExtEvent: Unhandled %s event (%d)\n",
190 e
->u
.u
.type
>= LASTEvent
? "extension" : "non-extension",
196 xev
->detail
= e
->u
.u
.detail
;
197 xev
->deviceid
= pDevice
->id
| MORE_EVENTS
;
198 xev
->time
= e
->u
.keyButtonPointer
.time
;
200 xv
->type
= DeviceValuator
;
201 xv
->deviceid
= pDevice
->id
;
202 xv
->num_valuators
= 0;
203 xv
->first_valuator
= 0;
213 DMXScreenInfo
*dmxFindFirstScreen(int x
, int y
)
217 for (i
= 0; i
< dmxNumScreens
; i
++) {
218 DMXScreenInfo
*dmxScreen
= &dmxScreens
[i
];
219 if (dmxOnScreen(x
, y
, dmxScreen
))
227 * Enqueue a motion event.
229 static void enqueueMotion(DevicePtr pDev
, int x
, int y
)
232 DeviceIntPtr p
= dmxLocal
->pDevice
;
233 int i
, nevents
, valuators
[3];
234 xEvent
*events
= Xcalloc(sizeof(xEvent
), GetMaximumEventsNum());
235 int detail
= 0; /* XXX should this be mask of pressed buttons? */
238 nevents
= GetPointerEvents(events
, p
, MotionNotify
, detail
,
239 POINTER_ABSOLUTE
, 0, 2, valuators
);
240 for (i
= 0; i
< nevents
; i
++)
241 mieqEnqueue(p
, events
+ i
);
248 dmxCoreMotion(DevicePtr pDev
, int x
, int y
, int delta
, DMXBlockType block
)
250 DMXScreenInfo
*dmxScreen
;
251 DMXInputInfo
*dmxInput
;
257 if (!dmxGlobalInvalid
&& dmxGlobalX
== x
&& dmxGlobalY
== y
)
260 DMXDBG5("dmxCoreMotion(%d,%d,%d) dmxGlobalX=%d dmxGlobalY=%d\n",
261 x
, y
, delta
, dmxGlobalX
, dmxGlobalY
);
263 dmxGlobalInvalid
= 0;
271 if (dmxGlobalX
>= dmxGlobalWidth
)
272 dmxGlobalX
= dmxGlobalWidth
+ delta
-1;
273 if (dmxGlobalY
>= dmxGlobalHeight
)
274 dmxGlobalY
= dmxGlobalHeight
+ delta
-1;
276 if ((dmxScreen
= dmxFindFirstScreen(dmxGlobalX
, dmxGlobalY
))) {
277 localX
= dmxGlobalX
- dmxScreen
->rootXOrigin
;
278 localY
= dmxGlobalY
- dmxScreen
->rootYOrigin
;
279 if ((pScreen
= miPointerGetScreen(inputInfo
.pointer
))
280 && pScreen
->myNum
== dmxScreen
->index
) {
281 /* Screen is old screen */
285 enqueueMotion(pDev
, localX
, localY
);
290 DMXDBG4(" New screen: old=%d new=%d localX=%d localY=%d\n",
291 pScreen
->myNum
, dmxScreen
->index
, localX
, localY
);
294 dmxeqProcessInputEvents();
295 miPointerSetScreen(inputInfo
.pointer
, dmxScreen
->index
,
298 enqueueMotion(pDev
, localX
, localY
);
303 miPointerGetPosition(inputInfo
.pointer
, &localX
, &localY
);
305 if ((pScreen
= miPointerGetScreen(inputInfo
.pointer
))) {
306 dmxGlobalX
= localX
+ dmxScreens
[pScreen
->myNum
].rootXOrigin
;
307 dmxGlobalY
= localY
+ dmxScreens
[pScreen
->myNum
].rootYOrigin
;
308 ErrorF("Global is now %d, %d %d, %d\n", dmxGlobalX
, dmxGlobalY
,
310 DMXDBG6(" Moved to dmxGlobalX=%d dmxGlobalY=%d"
311 " on screen index=%d/%d localX=%d localY=%d\n",
312 dmxGlobalX
, dmxGlobalY
,
313 dmxScreen
? dmxScreen
->index
: -1, pScreen
->myNum
,
318 /* Send updates down to all core input
320 for (i
= 0, dmxInput
= &dmxInputs
[0]; i
< dmxNumInputs
; i
++, dmxInput
++) {
322 for (j
= 0; j
< dmxInput
->numDevs
; j
+= dmxInput
->devs
[j
]->binding
)
323 if (!dmxInput
->detached
324 && dmxInput
->devs
[j
]->sendsCore
325 && dmxInput
->devs
[j
]->update_position
)
326 dmxInput
->devs
[j
]->update_position(dmxInput
->devs
[j
]->private,
327 dmxGlobalX
, dmxGlobalY
);
329 if (!dmxScreen
) ProcessInputEvents();
335 #define DMX_MAX_AXES 32 /* Max axes reported by this routine */
336 static void dmxExtMotion(DMXLocalInputInfoPtr dmxLocal
,
337 int *v
, int firstAxis
, int axesCount
,
338 DMXMotionType type
, DMXBlockType block
)
340 DeviceIntPtr pDevice
= dmxLocal
->pDevice
;
341 xEvent xE
[2 * DMX_MAX_AXES
/6];
342 deviceKeyButtonPointer
*xev
= (deviceKeyButtonPointer
*)xE
;
343 deviceValuator
*xv
= (deviceValuator
*)xev
+1;
349 memset(xE
, 0, sizeof(xE
));
351 if (axesCount
> DMX_MAX_AXES
) axesCount
= DMX_MAX_AXES
;
353 if (!pDevice
->valuator
->mode
&& axesCount
== 2) {
354 /* The dmx console is a relative mode
355 * device that sometimes reports
356 * absolute motion. It only has two
358 if (type
== DMX_RELATIVE
) {
361 dmxLocal
->lastX
+= thisX
;
362 dmxLocal
->lastY
+= thisY
;
363 if (dmxLocal
->update_position
)
364 dmxLocal
->update_position(dmxLocal
->private,
365 dmxLocal
->lastX
, dmxLocal
->lastY
);
366 } else { /* Convert to relative */
367 if (dmxLocal
->lastX
|| dmxLocal
->lastY
) {
368 thisX
= v
[0] - dmxLocal
->lastX
;
369 thisY
= v
[1] - dmxLocal
->lastY
;
371 dmxLocal
->lastX
= v
[0];
372 dmxLocal
->lastY
= v
[1];
378 if (axesCount
<= 6) {
379 /* Optimize for the common case when
380 * only 1 or 2 axes change. */
381 xev
->time
= GetTimeInMillis();
382 xev
->type
= DeviceMotionNotify
;
384 xev
->deviceid
= pDevice
->id
| MORE_EVENTS
;
386 xv
->type
= DeviceValuator
;
387 xv
->deviceid
= pDevice
->id
;
388 xv
->num_valuators
= axesCount
;
389 xv
->first_valuator
= firstAxis
;
390 switch (xv
->num_valuators
) {
391 case 6: xv
->valuator5
= v
[5];
392 case 5: xv
->valuator4
= v
[4];
393 case 4: xv
->valuator3
= v
[3];
394 case 3: xv
->valuator2
= v
[2];
395 case 2: xv
->valuator1
= v
[1];
396 case 1: xv
->valuator0
= v
[0];
400 for (i
= 0, count
= 0; i
< axesCount
; i
+= 6) {
401 xev
->time
= GetTimeInMillis();
402 xev
->type
= DeviceMotionNotify
;
404 xev
->deviceid
= pDevice
->id
| MORE_EVENTS
;
407 xv
->type
= DeviceValuator
;
408 xv
->deviceid
= pDevice
->id
;
409 xv
->num_valuators
= (i
+6 >= axesCount
? axesCount
- i
: 6);
410 xv
->first_valuator
= firstAxis
+ i
;
411 switch (xv
->num_valuators
) {
412 case 6: xv
->valuator5
= v
[i
+5];
413 case 5: xv
->valuator4
= v
[i
+4];
414 case 4: xv
->valuator3
= v
[i
+3];
415 case 3: xv
->valuator2
= v
[i
+2];
416 case 2: xv
->valuator1
= v
[i
+1];
417 case 1: xv
->valuator0
= v
[i
+0];
426 dmxPointerPutMotionEvent(pDevice
, firstAxis
, axesCount
, v
, xev
->time
);
432 static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal
,
433 XEvent
*e
, DMXBlockType block
)
436 deviceKeyButtonPointer
*xev
= (deviceKeyButtonPointer
*)xE
;
437 deviceValuator
*xv
= (deviceValuator
*)xev
+1;
440 XDeviceKeyEvent
*ke
= (XDeviceKeyEvent
*)e
;
441 XDeviceMotionEvent
*me
= (XDeviceMotionEvent
*)e
;
444 return -1; /* No extended event passed, cannot handle */
446 if ((XID
)dmxLocal
->deviceId
!= ke
->deviceid
) {
447 /* Search for the correct dmxLocal,
448 * since backend and console events are
449 * picked up for the first device on
452 DMXInputInfo
*dmxInput
= &dmxInputs
[dmxLocal
->inputIdx
];
453 for (i
= 0; i
< dmxInput
->numDevs
; i
++) {
454 dmxLocal
= dmxInput
->devs
[i
];
455 if ((XID
)dmxLocal
->deviceId
== ke
->deviceid
)
460 if ((XID
)dmxLocal
->deviceId
!= ke
->deviceid
461 || (type
= dmxMapLookup(dmxLocal
, e
->type
)) < 0)
462 return -1; /* No mapping, so this event is unhandled */
465 case XI_DeviceValuator
: event
= DeviceValuator
; break;
466 case XI_DeviceKeyPress
: event
= DeviceKeyPress
; break;
467 case XI_DeviceKeyRelease
: event
= DeviceKeyRelease
; break;
468 case XI_DeviceButtonPress
: event
= DeviceButtonPress
; break;
469 case XI_DeviceButtonRelease
: event
= DeviceButtonRelease
; break;
470 case XI_DeviceMotionNotify
: event
= DeviceMotionNotify
; break;
471 case XI_DeviceFocusIn
: event
= DeviceFocusIn
; break;
472 case XI_DeviceFocusOut
: event
= DeviceFocusOut
; break;
473 case XI_ProximityIn
: event
= ProximityIn
; break;
474 case XI_ProximityOut
: event
= ProximityOut
; break;
475 case XI_DeviceStateNotify
: event
= DeviceStateNotify
; break;
476 case XI_DeviceMappingNotify
: event
= DeviceMappingNotify
; break;
477 case XI_ChangeDeviceNotify
: event
= ChangeDeviceNotify
; break;
478 case XI_DeviceKeystateNotify
: event
= DeviceStateNotify
; break;
479 case XI_DeviceButtonstateNotify
: event
= DeviceStateNotify
; break;
483 case XI_DeviceKeyPress
:
484 case XI_DeviceKeyRelease
:
485 case XI_DeviceButtonPress
:
486 case XI_DeviceButtonRelease
:
488 case XI_ProximityOut
:
490 xev
->detail
= ke
->keycode
; /* same as ->button */
491 xev
->deviceid
= dmxLocal
->pDevice
->id
| MORE_EVENTS
;
492 xev
->time
= GetTimeInMillis();
494 xv
->type
= DeviceValuator
;
495 xv
->deviceid
= dmxLocal
->pDevice
->id
;
496 xv
->num_valuators
= ke
->axes_count
;
497 xv
->first_valuator
= ke
->first_axis
;
498 xv
->valuator0
= ke
->axis_data
[0];
499 xv
->valuator1
= ke
->axis_data
[1];
500 xv
->valuator2
= ke
->axis_data
[2];
501 xv
->valuator3
= ke
->axis_data
[3];
502 xv
->valuator4
= ke
->axis_data
[4];
503 xv
->valuator5
= ke
->axis_data
[5];
512 case XI_DeviceMotionNotify
:
513 dmxExtMotion(dmxLocal
, me
->axis_data
, me
->first_axis
, me
->axes_count
,
514 DMX_ABSOLUTE
, block
);
516 case XI_DeviceFocusIn
:
517 case XI_DeviceFocusOut
:
518 case XI_DeviceStateNotify
:
519 case XI_DeviceMappingNotify
:
520 case XI_ChangeDeviceNotify
:
521 case XI_DeviceKeystateNotify
:
522 case XI_DeviceButtonstateNotify
:
523 /* These are ignored, since DMX will
524 * generate its own events of these
525 * types, as necessary.
527 * Perhaps ChangeDeviceNotify should
528 * generate an error, because it is
531 case XI_DeviceValuator
:
534 "XInput extension event (remote=%d -> zero-based=%d)"
535 " not supported yet\n", e
->type
, type
);
542 static int dmxGetButtonMapping(DMXLocalInputInfoPtr dmxLocal
, int button
)
544 ButtonClassPtr b
= dmxLocal
->pDevice
->button
;
546 if (button
> b
->numButtons
) { /* This shouldn't happen. */
547 dmxLog(dmxWarning
, "Button %d pressed, but only %d buttons?!?\n",
548 button
, b
->numButtons
);
551 return b
->map
[button
];
554 /** Return DMX's notion of the pointer position in the global coordinate
556 void dmxGetGlobalPosition(int *x
, int *y
)
562 /** Invalidate the global position for #dmxCoreMotion. */
563 void dmxInvalidateGlobalPosition(void)
565 dmxGlobalInvalid
= 1;
568 /** Enqueue a motion event for \a pDev. The \a v vector has length \a
569 * axesCount, and contains values for each of the axes, starting at \a
572 * The \a type of the motion may be \a DMX_RELATIVE, \a DMX_ABSOLUTE, or
573 * \a DMX_ABSOLUTE_CONFINED (in the latter case, the pointer will not be
574 * allowed to move outside the global boundaires).
576 * If \a block is set to \a DMX_BLOCK, then the SIGIO handler will be
577 * blocked around calls to #dmxeqEnqueue(). */
578 void dmxMotion(DevicePtr pDev
, int *v
, int firstAxes
, int axesCount
,
579 DMXMotionType type
, DMXBlockType block
)
584 if (!dmxLocal
->sendsCore
) {
585 dmxExtMotion(dmxLocal
, v
, firstAxes
, axesCount
, type
, block
);
589 if (axesCount
== 2) {
592 dmxCoreMotion(pDev
, dmxGlobalX
- v
[0], dmxGlobalY
- v
[1], 0, block
);
595 dmxCoreMotion(pDev
, v
[0], v
[1], 0, block
);
597 case DMX_ABSOLUTE_CONFINED
:
598 dmxCoreMotion(pDev
, v
[0], v
[1], -1, block
);
604 static KeySym
dmxKeyCodeToKeySym(DMXLocalInputInfoPtr dmxLocal
,
607 KeySymsPtr pKeySyms
= NULL
;
609 if (!dmxLocal
|| !dmxLocal
->pDevice
|| !dmxLocal
->pDevice
->key
)
611 pKeySyms
= &dmxLocal
->pDevice
->key
->curKeySyms
;
615 if (keyCode
> pKeySyms
->minKeyCode
&& keyCode
<= pKeySyms
->maxKeyCode
) {
616 DMXDBG2("dmxKeyCodeToKeySym: Translated keyCode=%d to keySym=0x%04x\n",
618 pKeySyms
->map
[(keyCode
- pKeySyms
->minKeyCode
)
619 * pKeySyms
->mapWidth
]);
621 return pKeySyms
->map
[(keyCode
- pKeySyms
->minKeyCode
)
622 * pKeySyms
->mapWidth
];
627 static KeyCode
dmxKeySymToKeyCode(DMXLocalInputInfoPtr dmxLocal
, KeySym keySym
,
630 KeySymsPtr pKeySyms
= &dmxLocal
->pDevice
->key
->curKeySyms
;
633 /* Optimize for similar maps */
634 if (tryFirst
>= pKeySyms
->minKeyCode
635 && tryFirst
<= pKeySyms
->maxKeyCode
636 && pKeySyms
->map
[(tryFirst
- pKeySyms
->minKeyCode
)
637 * pKeySyms
->mapWidth
] == keySym
)
640 for (i
= pKeySyms
->minKeyCode
; i
<= pKeySyms
->maxKeyCode
; i
++) {
641 if (pKeySyms
->map
[(i
- pKeySyms
->minKeyCode
)
642 * pKeySyms
->mapWidth
] == keySym
) {
643 DMXDBG3("dmxKeySymToKeyCode: Translated keySym=0x%04x to"
644 " keyCode=%d (reverses to core keySym=0x%04x)\n",
645 keySym
, i
, dmxKeyCodeToKeySym(dmxLocalCoreKeyboard
,i
));
652 static int dmxFixup(DevicePtr pDev
, int detail
, KeySym keySym
)
657 if (!dmxLocal
->pDevice
->key
) {
658 dmxLog(dmxWarning
, "dmxFixup: not a keyboard device (%s)\n",
659 dmxLocal
->pDevice
->name
);
663 keySym
= dmxKeyCodeToKeySym(dmxLocal
, detail
);
664 if (keySym
== NoSymbol
)
666 keyCode
= dmxKeySymToKeyCode(dmxLocalCoreKeyboard
, keySym
, detail
);
668 return keyCode
? keyCode
: detail
;
671 /** Enqueue an event from the \a pDev device with the
672 * specified \a type and \a detail. If the event is a KeyPress or
673 * KeyRelease event, then the \a keySym is also specified.
675 * If \a block is set to \a DMX_BLOCK, then the SIGIO handler will be
676 * blocked around calls to #dmxeqEnqueue(). */
678 void dmxEnqueue(DevicePtr pDev
, int type
, int detail
, KeySym keySym
,
679 XEvent
*e
, DMXBlockType block
)
683 DeviceIntPtr p
= dmxLocal
->pDevice
;
684 int i
, nevents
, valuators
[3];
687 DMXDBG2("dmxEnqueue: Enqueuing type=%d detail=0x%0x\n", type
, detail
);
693 keySym
= dmxKeyCodeToKeySym(dmxLocal
, detail
);
694 if (dmxCheckFunctionKeys(dmxLocal
, type
, keySym
))
696 if (dmxLocal
->sendsCore
&& dmxLocal
!= dmxLocalCoreKeyboard
)
697 xE
.u
.u
.detail
= dmxFixup(pDev
, detail
, keySym
);
699 events
= Xcalloc(sizeof(xEvent
), GetMaximumEventsNum());
700 /*ErrorF("KEY %d sym %d\n", detail, (int) keySym);*/
701 nevents
= GetKeyboardEvents(events
, p
, type
, detail
);
702 for (i
= 0; i
< nevents
; i
++)
703 mieqEnqueue(p
, events
+ i
);
709 detail
= dmxGetButtonMapping(dmxLocal
, detail
);
710 events
= Xcalloc(sizeof(xEvent
), GetMaximumEventsNum());
711 nevents
= GetPointerEvents(events
, p
, type
, detail
,
713 0, /* first_valuator = 0 */
714 0, /* num_valuators = 0 */
716 for (i
= 0; i
< nevents
; i
++)
717 mieqEnqueue(p
, events
+ i
);
722 events
= Xcalloc(sizeof(xEvent
), GetMaximumEventsNum());
723 valuators
[0] = e
->xmotion
.x
;
724 valuators
[1] = e
->xmotion
.y
;
725 valuators
[2] = e
->xmotion
.state
;
726 nevents
= GetPointerEvents(events
, p
, type
, detail
,
727 POINTER_ABSOLUTE
, 0, 3, valuators
);
728 for (i
= 0; i
< nevents
; i
++)
729 mieqEnqueue(p
, events
+ i
);
736 case MappingNotify
: /* This is sent because we change the
737 * modifier map on the backend/console
738 * input device so that we have complete
739 * control of the input device LEDs. */
743 if (type
== ProximityIn
|| type
== ProximityOut
) {
744 if (dmxLocal
->sendsCore
)
745 return; /* Not a core event */
749 if (type
>= LASTEvent
) {
751 if (dmxTranslateAndEnqueueExtEvent(dmxLocal
, e
, block
))
753 dmxLogInput(dmxInput
, "Unhandled extension event: %d\n", type
);
755 dmxLogInput(dmxInput
, "Unhandled event: %d (%s)\n",
756 type
, dmxEventName(type
));
761 #if 00 /* dead code? */
762 memset(&xE
, 0, sizeof(xE
));
764 xE
.u
.u
.detail
= detail
;
765 xE
.u
.keyButtonPointer
.time
= GetTimeInMillis();
768 if (!dmxLocal
->sendsCore
)
769 dmxEnqueueExtEvent(dmxLocal
, &xE
, block
);
776 /** A pointer to this routine is passed to low-level input drivers so
777 * that all special keychecking is unified to this file. This function
778 * returns 0 if no special keys have been pressed. If the user has
779 * requested termination of the DMX server, -1 is returned. If the user
780 * has requested a switch to a VT, then the (1-based) number of that VT
782 int dmxCheckSpecialKeys(DevicePtr pDev
, KeySym keySym
)
786 unsigned short state
= 0;
788 if (dmxLocal
->sendsCore
)
789 state
= dmxLocalCoreKeyboard
->pDevice
->key
->state
;
790 else if (dmxLocal
->pDevice
->key
)
791 state
= dmxLocal
->pDevice
->key
->state
;
793 if (!dmxLocal
->sendsCore
) return 0; /* Only for core devices */
795 DMXDBG2("dmxCheckSpecialKeys: keySym=0x%04x state=0x%04x\n", keySym
,state
);
797 if ((state
& (ControlMask
|Mod1Mask
)) != (ControlMask
|Mod1Mask
)) return 0;
810 vt
= keySym
- XK_F1
+ 1;
815 vt
= keySym
- XK_F11
+ 11;
818 case XK_q
: /* To avoid confusion */
822 dmxLog(dmxInfo
, "User request for termination\n");
823 dispatchException
|= DE_TERMINATE
;
824 return -1; /* Terminate */
828 dmxLog(dmxInfo
, "Request to switch to VT %d\n", vt
);
829 dmxInput
->vt_switch_pending
= vt
;
833 return 0; /* Do nothing */