First import
[xorg_rtime.git] / xorg-server-1.4 / dix / getevents.c
blobf92a0211ad44900bd16d8ae632104a19a859ee55
1 /*
2 * Copyright © 2006 Nokia Corporation
3 * Copyright © 2006-2007 Daniel Stone
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
24 * Author: Daniel Stone <daniel@fooishbar.org>
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
29 #endif
31 #include <X11/X.h>
32 #include <X11/keysym.h>
33 #define NEED_EVENTS
34 #define NEED_REPLIES
35 #include <X11/Xproto.h>
37 #include "misc.h"
38 #include "resource.h"
39 #include "inputstr.h"
40 #include "scrnintstr.h"
41 #include "cursorstr.h"
42 #include "dixstruct.h"
43 #include "globals.h"
44 #include "dixevents.h"
45 #include "mipointer.h"
47 #ifdef XKB
48 #include <X11/extensions/XKBproto.h>
49 #include <xkbsrv.h>
50 extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
51 #endif
53 #ifdef PANORAMIX
54 #include "panoramiX.h"
55 #include "panoramiXsrv.h"
56 #endif
58 #include <X11/extensions/XI.h>
59 #include <X11/extensions/XIproto.h>
60 #include "exglobals.h"
61 #include "exevents.h"
62 #include "exglobals.h"
63 #include "extnsionst.h"
66 /* Maximum number of valuators, divided by six, rounded up, to get number
67 * of events. */
68 #define MAX_VALUATOR_EVENTS 6
70 /* Number of motion history events to store. */
71 #define MOTION_HISTORY_SIZE 256
74 /**
75 * Pick some arbitrary size for Xi motion history.
77 _X_EXPORT int
78 GetMotionHistorySize(void)
80 return MOTION_HISTORY_SIZE;
83 static void
84 set_key_down(DeviceIntPtr pDev, int key_code)
86 pDev->key->postdown[key_code >> 3] |= (1 << (key_code & 7));
89 static void
90 set_key_up(DeviceIntPtr pDev, int key_code)
92 pDev->key->postdown[key_code >> 3] &= ~(1 << (key_code & 7));
95 static Bool
96 key_is_down(DeviceIntPtr pDev, int key_code)
98 return pDev->key->postdown[key_code >> 3] >> (key_code & 7);
102 * Allocate the motion history buffer.
104 _X_EXPORT void
105 AllocateMotionHistory(DeviceIntPtr pDev)
107 if (pDev->valuator->motion)
108 xfree(pDev->valuator->motion);
110 if (pDev->valuator->numMotionEvents < 1)
111 return;
113 pDev->valuator->motion = xalloc(((sizeof(INT32) * pDev->valuator->numAxes) +
114 sizeof(Time)) *
115 pDev->valuator->numMotionEvents);
116 pDev->valuator->first_motion = 0;
117 pDev->valuator->last_motion = 0;
122 * Dump the motion history between start and stop into the supplied buffer.
123 * Only records the event for a given screen in theory, but in practice, we
124 * sort of ignore this.
126 _X_EXPORT int
127 GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start,
128 unsigned long stop, ScreenPtr pScreen)
130 char *ibuff = NULL, *obuff = (char *) buff;
131 int i = 0, ret = 0;
132 Time current;
133 /* The size of a single motion event. */
134 int size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
136 if (!pDev->valuator || !pDev->valuator->numMotionEvents)
137 return 0;
139 for (i = pDev->valuator->first_motion;
140 i != pDev->valuator->last_motion;
141 i = (i + 1) % pDev->valuator->numMotionEvents) {
142 /* We index the input buffer by which element we're accessing, which
143 * is not monotonic, and the output buffer by how many events we've
144 * written so far. */
145 ibuff = (char *) pDev->valuator->motion + (i * size);
146 memcpy(&current, ibuff, sizeof(Time));
148 if (current > stop) {
149 return ret;
151 else if (current >= start) {
152 memcpy(obuff, ibuff, size);
153 obuff += size;
154 ret++;
158 return ret;
163 * Update the motion history for a specific device, with the list of
164 * valuators.
166 static void
167 updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
168 int num_valuators, int *valuators)
170 char *buff = (char *) pDev->valuator->motion;
172 if (!pDev->valuator->numMotionEvents)
173 return;
175 buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
176 pDev->valuator->last_motion;
177 memcpy(buff, &ms, sizeof(Time));
179 buff += sizeof(Time);
180 bzero(buff, sizeof(INT32) * pDev->valuator->numAxes);
182 buff += sizeof(INT32) * first_valuator;
183 memcpy(buff, valuators, sizeof(INT32) * num_valuators);
185 pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
186 pDev->valuator->numMotionEvents;
188 /* If we're wrapping around, just keep the circular buffer going. */
189 if (pDev->valuator->first_motion == pDev->valuator->last_motion)
190 pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
191 pDev->valuator->numMotionEvents;
193 return;
198 * Returns the maximum number of events GetKeyboardEvents,
199 * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
201 * Should be used in DIX as:
202 * xEvent *events = xcalloc(sizeof(xEvent), GetMaximumEventsNum());
204 _X_EXPORT int
205 GetMaximumEventsNum(void) {
206 /* Two base events -- core and device, plus valuator events. Multiply
207 * by two if we're doing key repeats. */
208 int ret = 2 + MAX_VALUATOR_EVENTS;
210 #ifdef XKB
211 if (noXkbExtension)
212 #endif
213 ret *= 2;
215 return ret;
219 /* Originally a part of xf86PostMotionEvent; modifies valuators
220 * in-place. */
221 static void
222 acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators,
223 int *valuators)
225 float mult = 0.0;
226 int dx = 0, dy = 0;
227 int *px = NULL, *py = NULL;
229 if (!num_valuators || !valuators)
230 return;
232 if (first_valuator == 0) {
233 dx = valuators[0];
234 px = &valuators[0];
236 if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
237 dy = valuators[1 - first_valuator];
238 py = &valuators[1 - first_valuator];
241 if (!dx && !dy)
242 return;
244 if (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) {
245 /* modeled from xf86Events.c */
246 if (pDev->ptrfeed->ctrl.threshold) {
247 if ((abs(dx) + abs(dy)) >= pDev->ptrfeed->ctrl.threshold) {
248 pDev->valuator->dxremaind = ((float)dx *
249 (float)(pDev->ptrfeed->ctrl.num)) /
250 (float)(pDev->ptrfeed->ctrl.den) +
251 pDev->valuator->dxremaind;
252 if (px) {
253 *px = (int)pDev->valuator->dxremaind;
254 pDev->valuator->dxremaind = pDev->valuator->dxremaind -
255 (float)(*px);
258 pDev->valuator->dyremaind = ((float)dy *
259 (float)(pDev->ptrfeed->ctrl.num)) /
260 (float)(pDev->ptrfeed->ctrl.den) +
261 pDev->valuator->dyremaind;
262 if (py) {
263 *py = (int)pDev->valuator->dyremaind;
264 pDev->valuator->dyremaind = pDev->valuator->dyremaind -
265 (float)(*py);
269 else {
270 mult = pow((float)dx * (float)dx + (float)dy * (float)dy,
271 ((float)(pDev->ptrfeed->ctrl.num) /
272 (float)(pDev->ptrfeed->ctrl.den) - 1.0) /
273 2.0) / 2.0;
274 if (dx) {
275 pDev->valuator->dxremaind = mult * (float)dx +
276 pDev->valuator->dxremaind;
277 *px = (int)pDev->valuator->dxremaind;
278 pDev->valuator->dxremaind = pDev->valuator->dxremaind -
279 (float)(*px);
281 if (dy) {
282 pDev->valuator->dyremaind = mult * (float)dy +
283 pDev->valuator->dyremaind;
284 *py = (int)pDev->valuator->dyremaind;
285 pDev->valuator->dyremaind = pDev->valuator->dyremaind -
286 (float)(*py);
294 * Clip an axis to its bounds, which are declared in the call to
295 * InitValuatorAxisClassStruct.
297 static void
298 clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
300 AxisInfoPtr axes = pDev->valuator->axes + axisNum;
302 if (*val < axes->min_value)
303 *val = axes->min_value;
304 if (axes->max_value >= 0 && *val > axes->max_value)
305 *val = axes->max_value;
309 * Clip every axis in the list of valuators to its bounds.
311 static void
312 clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
313 int *valuators)
315 AxisInfoPtr axes = pDev->valuator->axes + first_valuator;
316 int i;
318 for (i = 0; i < num_valuators; i++, axes++)
319 clipAxis(pDev, i + first_valuator, &(valuators[i]));
324 * Fills events with valuator events for pDev, as given by the other
325 * parameters.
327 * FIXME: Need to fix ValuatorClassRec to store all the valuators as
328 * last posted, not just x and y; otherwise relative non-x/y
329 * valuators, though a very narrow use case, will be broken.
331 static xEvent *
332 getValuatorEvents(xEvent *events, DeviceIntPtr pDev, int first_valuator,
333 int num_valuators, int *valuators) {
334 deviceValuator *xv = (deviceValuator *) events;
335 int i = 0, final_valuator = first_valuator + num_valuators;
337 for (i = first_valuator; i < final_valuator; i += 6, xv++, events++) {
338 xv->type = DeviceValuator;
339 xv->first_valuator = i;
340 xv->num_valuators = num_valuators;
341 xv->deviceid = pDev->id;
342 switch (final_valuator - i) {
343 case 6:
344 xv->valuator5 = valuators[i + 5];
345 case 5:
346 xv->valuator4 = valuators[i + 4];
347 case 4:
348 xv->valuator3 = valuators[i + 3];
349 case 3:
350 xv->valuator2 = valuators[i + 2];
351 case 2:
352 xv->valuator1 = valuators[i + 1];
353 case 1:
354 xv->valuator0 = valuators[i];
357 if (i + 6 < final_valuator)
358 xv->deviceid |= MORE_EVENTS;
361 return events;
366 * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
367 * valuators.
369 _X_EXPORT int
370 GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) {
371 return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL);
376 * Returns a set of keyboard events for KeyPress/KeyRelease, optionally
377 * also with valuator events. Handles Xi and XKB.
379 * events is not NULL-terminated; the return value is the number of events.
380 * The DDX is responsible for allocating the event structure in the first
381 * place via GetMaximumEventsNum(), and for freeing it.
383 * This function does not change the core keymap to that of the device;
384 * that is done by SwitchCoreKeyboard, which is called from
385 * mieqProcessInputEvents. If replacing that function, take care to call
386 * SetCoreKeyboard before processInputProc, so keymaps are altered to suit.
388 * Note that this function recurses! If called for non-XKB, a repeating
389 * key press will trigger a matching KeyRelease, as well as the
390 * KeyPresses.
392 _X_EXPORT int
393 GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
394 int key_code, int first_valuator,
395 int num_valuators, int *valuators) {
396 int numEvents = 0;
397 CARD32 ms = 0;
398 KeySym *map = pDev->key->curKeySyms.map;
399 KeySym sym = map[key_code * pDev->key->curKeySyms.mapWidth];
400 deviceKeyButtonPointer *kbp = NULL;
402 if (!events)
403 return 0;
405 if (type != KeyPress && type != KeyRelease)
406 return 0;
408 if (!pDev->key || !pDev->focus || !pDev->kbdfeed ||
409 (pDev->coreEvents && !inputInfo.keyboard->key))
410 return 0;
412 if (pDev->coreEvents)
413 numEvents = 2;
414 else
415 numEvents = 1;
417 if (num_valuators) {
418 if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS)
419 num_valuators = MAX_VALUATOR_EVENTS;
420 numEvents += (num_valuators / 6) + 1;
423 #ifdef XKB
424 if (noXkbExtension)
425 #endif
427 switch (sym) {
428 case XK_Num_Lock:
429 case XK_Caps_Lock:
430 case XK_Scroll_Lock:
431 case XK_Shift_Lock:
432 if (type == KeyRelease)
433 return 0;
434 else if (type == KeyPress && key_is_down(pDev, key_code))
435 type = KeyRelease;
439 /* Handle core repeating, via press/release/press/release.
440 * FIXME: In theory, if you're repeating with two keyboards in non-XKB,
441 * you could get unbalanced events here. */
442 if (type == KeyPress && key_is_down(pDev, key_code)) {
443 if (!pDev->kbdfeed->ctrl.autoRepeat ||
444 pDev->key->modifierMap[key_code] ||
445 !(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3]
446 & (1 << (key_code & 7))))
447 return 0;
449 #ifdef XKB
450 if (noXkbExtension)
451 #endif
453 numEvents += GetKeyboardValuatorEvents(events, pDev,
454 KeyRelease, key_code,
455 first_valuator, num_valuators,
456 valuators);
457 events += numEvents;
461 ms = GetTimeInMillis();
463 if (pDev->coreEvents) {
464 events->u.keyButtonPointer.time = ms;
465 events->u.u.type = type;
466 events->u.u.detail = key_code;
467 if (type == KeyPress)
468 set_key_down(inputInfo.keyboard, key_code);
469 else if (type == KeyRelease)
470 set_key_up(inputInfo.keyboard, key_code);
471 events++;
474 kbp = (deviceKeyButtonPointer *) events;
475 kbp->time = ms;
476 kbp->deviceid = pDev->id;
477 kbp->detail = key_code;
478 if (type == KeyPress) {
479 kbp->type = DeviceKeyPress;
480 set_key_down(pDev, key_code);
482 else if (type == KeyRelease) {
483 kbp->type = DeviceKeyRelease;
484 set_key_up(pDev, key_code);
487 events++;
488 if (num_valuators) {
489 kbp->deviceid |= MORE_EVENTS;
490 clipValuators(pDev, first_valuator, num_valuators, valuators);
491 events = getValuatorEvents(events, pDev, first_valuator,
492 num_valuators, valuators);
495 return numEvents;
500 * Generate a series of xEvents (returned in xE) representing pointer
501 * motion, or button presses. Xi and XKB-aware.
503 * events is not NULL-terminated; the return value is the number of events.
504 * The DDX is responsible for allocating the event structure in the first
505 * place via GetMaximumEventsNum(), and for freeing it.
507 _X_EXPORT int
508 GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
509 int flags, int first_valuator, int num_valuators,
510 int *valuators) {
511 int num_events = 0, final_valuator = 0;
512 CARD32 ms = 0;
513 deviceKeyButtonPointer *kbp = NULL;
514 /* Thanks to a broken lib, we _always_ have to chase DeviceMotionNotifies
515 * with DeviceValuators. */
516 Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE);
517 DeviceIntPtr cp = inputInfo.pointer;
518 int x = 0, y = 0;
519 Bool coreOnly = (pDev == inputInfo.pointer);
521 /* Sanity checks. */
522 if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
523 return 0;
525 if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
526 return 0;
528 /* FIXME: I guess it should, in theory, be possible to post button events
529 * from devices without valuators. */
530 if (!pDev->valuator)
531 return 0;
533 if (!coreOnly && pDev->coreEvents)
534 num_events = 2;
535 else
536 num_events = 1;
538 if (type == MotionNotify && num_valuators <= 0)
539 return 0;
541 /* Do we need to send a DeviceValuator event? */
542 if (!coreOnly && sendValuators) {
543 if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
544 num_valuators = MAX_VALUATOR_EVENTS * 6;
545 num_events += ((num_valuators - 1) / 6) + 1;
548 final_valuator = num_valuators + first_valuator;
550 /* You fail. */
551 if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes)
552 return 0;
554 ms = GetTimeInMillis();
556 /* Set x and y based on whether this is absolute or relative, and
557 * accelerate if we need to. */
558 if (flags & POINTER_ABSOLUTE) {
559 if (num_valuators >= 1 && first_valuator == 0) {
560 x = valuators[0];
562 else {
563 if (pDev->coreEvents)
564 x = cp->valuator->lastx;
565 else
566 x = pDev->valuator->lastx;
569 if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
570 y = valuators[1 - first_valuator];
572 else {
573 if (pDev->coreEvents)
574 y = cp->valuator->lasty;
575 else
576 y = pDev->valuator->lasty;
579 else {
580 if (flags & POINTER_ACCELERATE)
581 acceleratePointer(pDev, first_valuator, num_valuators,
582 valuators);
584 if (pDev->coreEvents) {
585 if (first_valuator == 0 && num_valuators >= 1)
586 x = cp->valuator->lastx + valuators[0];
587 else
588 x = cp->valuator->lastx;
590 if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
591 y = cp->valuator->lasty + valuators[1 - first_valuator];
592 else
593 y = cp->valuator->lasty;
595 else {
596 if (first_valuator == 0 && num_valuators >= 1)
597 x = pDev->valuator->lastx + valuators[0];
598 else
599 x = pDev->valuator->lastx;
601 if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
602 y = pDev->valuator->lasty + valuators[1 - first_valuator];
603 else
604 y = pDev->valuator->lasty;
608 /* Clip both x and y to the defined limits (usually co-ord space limit). */
609 clipAxis(pDev, 0, &x);
610 clipAxis(pDev, 1, &y);
612 /* This takes care of crossing screens for us, as well as clipping
613 * to the current screen. Right now, we only have one history buffer,
614 * so we don't set this for both the device and core.*/
615 miPointerSetPosition(pDev, &x, &y, ms);
617 /* Drop x and y back into the valuators list, if they were originally
618 * present. */
619 if (first_valuator == 0 && num_valuators >= 1)
620 valuators[0] = x;
621 if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
622 valuators[1 - first_valuator] = y;
624 updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
626 if (pDev->coreEvents) {
627 cp->valuator->lastx = x;
628 cp->valuator->lasty = y;
630 pDev->valuator->lastx = x;
631 pDev->valuator->lasty = y;
633 /* for some reason inputInfo.pointer does not have coreEvents set */
634 if (coreOnly || pDev->coreEvents) {
635 events->u.u.type = type;
636 events->u.keyButtonPointer.time = ms;
637 events->u.keyButtonPointer.rootX = x;
638 events->u.keyButtonPointer.rootY = y;
640 if (type == ButtonPress || type == ButtonRelease) {
641 /* We hijack SetPointerMapping to work on all core-sending
642 * devices, so we use the device-specific map here instead of
643 * the core one. */
644 events->u.u.detail = pDev->button->map[buttons];
646 else {
647 events->u.u.detail = 0;
650 events++;
653 if (!coreOnly) {
654 kbp = (deviceKeyButtonPointer *) events;
655 kbp->time = ms;
656 kbp->deviceid = pDev->id;
658 if (type == MotionNotify) {
659 kbp->type = DeviceMotionNotify;
661 else {
662 if (type == ButtonPress)
663 kbp->type = DeviceButtonPress;
664 else if (type == ButtonRelease)
665 kbp->type = DeviceButtonRelease;
666 kbp->detail = pDev->button->map[buttons];
669 kbp->root_x = x;
670 kbp->root_y = y;
672 events++;
673 if (sendValuators) {
674 kbp->deviceid |= MORE_EVENTS;
675 clipValuators(pDev, first_valuator, num_valuators, valuators);
676 events = getValuatorEvents(events, pDev, first_valuator,
677 num_valuators, valuators);
681 return num_events;
686 * Post ProximityIn/ProximityOut events, accompanied by valuators.
688 * events is not NULL-terminated; the return value is the number of events.
689 * The DDX is responsible for allocating the event structure in the first
690 * place via GetMaximumEventsNum(), and for freeing it.
692 _X_EXPORT int
693 GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type,
694 int first_valuator, int num_valuators, int *valuators)
696 int num_events = 0;
697 deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) events;
699 /* Sanity checks. */
700 if (type != ProximityIn && type != ProximityOut)
701 return 0;
703 if (!pDev->valuator)
704 return 0;
706 /* Do we need to send a DeviceValuator event? */
707 if ((pDev->valuator->mode & 1) == Relative)
708 num_valuators = 0;
710 if (num_valuators) {
711 if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
712 num_valuators = MAX_VALUATOR_EVENTS * 6;
713 num_events += ((num_valuators - 1) / 6) + 1;
716 /* You fail. */
717 if (first_valuator < 0 ||
718 (num_valuators + first_valuator) > pDev->valuator->numAxes)
719 return 0;
721 kbp->type = type;
722 kbp->deviceid = pDev->id;
723 kbp->detail = 0;
724 kbp->time = GetTimeInMillis();
726 if (num_valuators) {
727 kbp->deviceid |= MORE_EVENTS;
728 events++;
729 clipValuators(pDev, first_valuator, num_valuators, valuators);
730 events = getValuatorEvents(events, pDev, first_valuator,
731 num_valuators, valuators);
734 return num_events;
739 * Note that pDev was the last device to send a core event. This function
740 * copies the complete keymap from the originating device to the core
741 * device, and makes sure the appropriate notifications are generated.
743 * Call this just before processInputProc.
745 _X_EXPORT void
746 SwitchCoreKeyboard(DeviceIntPtr pDev)
748 KeyClassPtr ckeyc = inputInfo.keyboard->key;
749 int i = 0;
751 if (inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr != pDev) {
752 memcpy(ckeyc->modifierMap, pDev->key->modifierMap, MAP_LENGTH);
753 if (ckeyc->modifierKeyMap)
754 xfree(ckeyc->modifierKeyMap);
755 ckeyc->modifierKeyMap = xalloc(8 * pDev->key->maxKeysPerModifier);
756 memcpy(ckeyc->modifierKeyMap, pDev->key->modifierKeyMap,
757 (8 * pDev->key->maxKeysPerModifier));
759 ckeyc->maxKeysPerModifier = pDev->key->maxKeysPerModifier;
760 ckeyc->curKeySyms.minKeyCode = pDev->key->curKeySyms.minKeyCode;
761 ckeyc->curKeySyms.maxKeyCode = pDev->key->curKeySyms.maxKeyCode;
762 SetKeySymsMap(&ckeyc->curKeySyms, &pDev->key->curKeySyms);
765 * Copy state from the extended keyboard to core. If you omit this,
766 * holding Ctrl on keyboard one, and pressing Q on keyboard two, will
767 * cause your app to quit. This feels wrong to me, hence the below
768 * code.
770 * XXX: If you synthesise core modifier events, the state will get
771 * clobbered here. You'll have to work out something sensible
772 * to fix that. Good luck.
775 #define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \
776 Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
777 ckeyc->state &= ~(KEYBOARD_MASK);
778 ckeyc->state |= (pDev->key->state & KEYBOARD_MASK);
779 #undef KEYBOARD_MASK
780 for (i = 0; i < 8; i++)
781 ckeyc->modifierKeyCount[i] = pDev->key->modifierKeyCount[i];
783 #ifdef XKB
784 if (!noXkbExtension && pDev->key->xkbInfo && pDev->key->xkbInfo->desc) {
785 if (!XkbCopyKeymap(pDev->key->xkbInfo->desc, ckeyc->xkbInfo->desc,
786 True))
787 FatalError("Couldn't pivot keymap from device to core!\n");
789 #endif
791 SendMappingNotify(MappingKeyboard, ckeyc->curKeySyms.minKeyCode,
792 (ckeyc->curKeySyms.maxKeyCode -
793 ckeyc->curKeySyms.minKeyCode),
794 serverClient);
795 inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr = pDev;
801 * Note that pDev was the last function to send a core pointer event.
802 * Currently a no-op.
804 * Call this just before processInputProc.
806 _X_EXPORT void
807 SwitchCorePointer(DeviceIntPtr pDev)
809 if (inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr != pDev)
810 inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr = pDev;
815 * Synthesize a single motion event for the core pointer.
817 * Used in cursor functions, e.g. when cursor confinement changes, and we need
818 * to shift the pointer to get it inside the new bounds.
820 void
821 PostSyntheticMotion(int x, int y, int screen, unsigned long time)
823 xEvent xE;
825 #ifdef PANORAMIX
826 /* Translate back to the sprite screen since processInputProc
827 will translate from sprite screen to screen 0 upon reentry
828 to the DIX layer. */
829 if (!noPanoramiXExtension) {
830 x += panoramiXdataPtr[0].x - panoramiXdataPtr[screen].x;
831 y += panoramiXdataPtr[0].y - panoramiXdataPtr[screen].y;
833 #endif
835 memset(&xE, 0, sizeof(xEvent));
836 xE.u.u.type = MotionNotify;
837 xE.u.keyButtonPointer.rootX = x;
838 xE.u.keyButtonPointer.rootY = y;
839 xE.u.keyButtonPointer.time = time;
841 (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1);