getevents.c revision 05b261ec
1/*
2 * Copyright © 2006 Nokia Corporation
3 * Copyright © 2006-2007 Daniel Stone
4 *
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:
11 *
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.
15 *
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.
23 *
24 * Author: Daniel Stone <daniel@fooishbar.org>
25 */
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <X11/X.h>
32#include <X11/keysym.h>
33#define NEED_EVENTS
34#define NEED_REPLIES
35#include <X11/Xproto.h>
36
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"
46
47#ifdef XKB
48#include <X11/extensions/XKBproto.h>
49#include <xkbsrv.h>
50extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
51#endif
52
53#ifdef PANORAMIX
54#include "panoramiX.h"
55#include "panoramiXsrv.h"
56#endif
57
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"
64
65
66/* Maximum number of valuators, divided by six, rounded up, to get number
67 * of events. */
68#define MAX_VALUATOR_EVENTS 6
69
70/* Number of motion history events to store. */
71#define MOTION_HISTORY_SIZE 256
72
73
74/**
75 * Pick some arbitrary size for Xi motion history.
76 */
77_X_EXPORT int
78GetMotionHistorySize(void)
79{
80    return MOTION_HISTORY_SIZE;
81}
82
83static void
84set_key_down(DeviceIntPtr pDev, int key_code)
85{
86    pDev->key->postdown[key_code >> 3] |= (1 << (key_code & 7));
87}
88
89static void
90set_key_up(DeviceIntPtr pDev, int key_code)
91{
92    pDev->key->postdown[key_code >> 3] &= ~(1 << (key_code & 7));
93}
94
95static Bool
96key_is_down(DeviceIntPtr pDev, int key_code)
97{
98    return !!(pDev->key->postdown[key_code >> 3] & (1 << (key_code & 7)));
99}
100
101static Bool
102key_autorepeats(DeviceIntPtr pDev, int key_code)
103{
104    return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
105              (1 << (key_code & 7)));
106}
107
108/**
109 * Allocate the motion history buffer.
110 */
111_X_EXPORT void
112AllocateMotionHistory(DeviceIntPtr pDev)
113{
114    if (pDev->valuator->motion)
115        xfree(pDev->valuator->motion);
116
117    if (pDev->valuator->numMotionEvents < 1)
118        return;
119
120    pDev->valuator->motion = xalloc(((sizeof(INT32) * pDev->valuator->numAxes) +
121                                     sizeof(Time)) *
122                                    pDev->valuator->numMotionEvents);
123    pDev->valuator->first_motion = 0;
124    pDev->valuator->last_motion = 0;
125}
126
127
128/**
129 * Dump the motion history between start and stop into the supplied buffer.
130 * Only records the event for a given screen in theory, but in practice, we
131 * sort of ignore this.
132 */
133_X_EXPORT int
134GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start,
135                 unsigned long stop, ScreenPtr pScreen)
136{
137    char *ibuff = NULL, *obuff = (char *) buff;
138    int i = 0, ret = 0;
139    Time current;
140    /* The size of a single motion event. */
141    int size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
142
143    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
144        return 0;
145
146    for (i = pDev->valuator->first_motion;
147         i != pDev->valuator->last_motion;
148         i = (i + 1) % pDev->valuator->numMotionEvents) {
149        /* We index the input buffer by which element we're accessing, which
150         * is not monotonic, and the output buffer by how many events we've
151         * written so far. */
152        ibuff = (char *) pDev->valuator->motion + (i * size);
153        memcpy(&current, ibuff, sizeof(Time));
154
155        if (current > stop) {
156            return ret;
157        }
158        else if (current >= start) {
159            memcpy(obuff, ibuff, size);
160            obuff += size;
161            ret++;
162        }
163    }
164
165    return ret;
166}
167
168
169/**
170 * Update the motion history for a specific device, with the list of
171 * valuators.
172 */
173static void
174updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
175                    int num_valuators, int *valuators)
176{
177    char *buff = (char *) pDev->valuator->motion;
178
179    if (!pDev->valuator->numMotionEvents)
180        return;
181
182    buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
183            pDev->valuator->last_motion;
184    memcpy(buff, &ms, sizeof(Time));
185
186    buff += sizeof(Time);
187    bzero(buff, sizeof(INT32) * pDev->valuator->numAxes);
188
189    buff += sizeof(INT32) * first_valuator;
190    memcpy(buff, valuators, sizeof(INT32) * num_valuators);
191
192    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
193                                  pDev->valuator->numMotionEvents;
194
195    /* If we're wrapping around, just keep the circular buffer going. */
196    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
197        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
198                                       pDev->valuator->numMotionEvents;
199
200    return;
201}
202
203
204/**
205 * Returns the maximum number of events GetKeyboardEvents,
206 * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
207 *
208 * Should be used in DIX as:
209 * xEvent *events = xcalloc(sizeof(xEvent), GetMaximumEventsNum());
210 */
211_X_EXPORT int
212GetMaximumEventsNum(void) {
213    /* Two base events -- core and device, plus valuator events.  Multiply
214     * by two if we're doing key repeats. */
215    int ret = 2 + MAX_VALUATOR_EVENTS;
216
217#ifdef XKB
218    if (noXkbExtension)
219#endif
220        ret *= 2;
221
222    return ret;
223}
224
225
226/* Originally a part of xf86PostMotionEvent; modifies valuators
227 * in-place. */
228static void
229acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators,
230                  int *valuators)
231{
232    float mult = 0.0;
233    int dx = 0, dy = 0;
234    int *px = NULL, *py = NULL;
235
236    if (!num_valuators || !valuators)
237        return;
238
239    if (first_valuator == 0) {
240        dx = valuators[0];
241        px = &valuators[0];
242    }
243    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
244        dy = valuators[1 - first_valuator];
245        py = &valuators[1 - first_valuator];
246    }
247
248    if (!dx && !dy)
249        return;
250
251    if (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) {
252        /* modeled from xf86Events.c */
253        if (pDev->ptrfeed->ctrl.threshold) {
254            if ((abs(dx) + abs(dy)) >= pDev->ptrfeed->ctrl.threshold) {
255                pDev->valuator->dxremaind = ((float)dx *
256                                             (float)(pDev->ptrfeed->ctrl.num)) /
257                                             (float)(pDev->ptrfeed->ctrl.den) +
258                                            pDev->valuator->dxremaind;
259                if (px) {
260                    *px = (int)pDev->valuator->dxremaind;
261                    pDev->valuator->dxremaind = pDev->valuator->dxremaind -
262                                                (float)(*px);
263                }
264
265                pDev->valuator->dyremaind = ((float)dy *
266                                             (float)(pDev->ptrfeed->ctrl.num)) /
267                                             (float)(pDev->ptrfeed->ctrl.den) +
268                                            pDev->valuator->dyremaind;
269                if (py) {
270                    *py = (int)pDev->valuator->dyremaind;
271                    pDev->valuator->dyremaind = pDev->valuator->dyremaind -
272                                                (float)(*py);
273                }
274            }
275        }
276        else {
277		mult = pow((float)dx * (float)dx + (float)dy * (float)dy,
278                       ((float)(pDev->ptrfeed->ctrl.num) /
279                        (float)(pDev->ptrfeed->ctrl.den) - 1.0) /
280                       2.0) / 2.0;
281            if (dx) {
282                pDev->valuator->dxremaind = mult * (float)dx +
283                                            pDev->valuator->dxremaind;
284                *px = (int)pDev->valuator->dxremaind;
285                pDev->valuator->dxremaind = pDev->valuator->dxremaind -
286                                            (float)(*px);
287            }
288            if (dy) {
289                pDev->valuator->dyremaind = mult * (float)dy +
290                                            pDev->valuator->dyremaind;
291                *py = (int)pDev->valuator->dyremaind;
292                pDev->valuator->dyremaind = pDev->valuator->dyremaind -
293                                            (float)(*py);
294            }
295        }
296    }
297}
298
299
300/**
301 * Clip an axis to its bounds, which are declared in the call to
302 * InitValuatorAxisClassStruct.
303 */
304static void
305clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
306{
307    AxisInfoPtr axes = pDev->valuator->axes + axisNum;
308
309    /* No clipping if the value-range <= 0 */
310    if(axes->min_value < axes->min_value) {
311        if (*val < axes->min_value)
312            *val = axes->min_value;
313        if (*val > axes->max_value)
314            *val = axes->max_value;
315    }
316}
317
318/**
319 * Clip every axis in the list of valuators to its bounds.
320 */
321static void
322clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
323              int *valuators)
324{
325    AxisInfoPtr axes = pDev->valuator->axes + first_valuator;
326    int i;
327
328    for (i = 0; i < num_valuators; i++, axes++)
329        clipAxis(pDev, i + first_valuator, &(valuators[i]));
330}
331
332
333/**
334 * Fills events with valuator events for pDev, as given by the other
335 * parameters.
336 *
337 * FIXME: Need to fix ValuatorClassRec to store all the valuators as
338 *        last posted, not just x and y; otherwise relative non-x/y
339 *        valuators, though a very narrow use case, will be broken.
340 */
341static xEvent *
342getValuatorEvents(xEvent *events, DeviceIntPtr pDev, int first_valuator,
343                  int num_valuators, int *valuators) {
344    deviceValuator *xv = (deviceValuator *) events;
345    int i = 0, final_valuator = first_valuator + num_valuators;
346
347    for (i = first_valuator; i < final_valuator; i += 6, xv++, events++) {
348        xv->type = DeviceValuator;
349        xv->first_valuator = i;
350        xv->num_valuators = ((final_valuator - i) > 6) ? 6 : (final_valuator - i);
351        xv->deviceid = pDev->id;
352        switch (final_valuator - i) {
353        case 6:
354            xv->valuator5 = valuators[i + 5];
355        case 5:
356            xv->valuator4 = valuators[i + 4];
357        case 4:
358            xv->valuator3 = valuators[i + 3];
359        case 3:
360            xv->valuator2 = valuators[i + 2];
361        case 2:
362            xv->valuator1 = valuators[i + 1];
363        case 1:
364            xv->valuator0 = valuators[i];
365        }
366
367        if (i + 6 < final_valuator)
368            xv->deviceid |= MORE_EVENTS;
369    }
370
371    return events;
372}
373
374
375/**
376 * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
377 * valuators.
378 */
379_X_EXPORT int
380GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) {
381    return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL);
382}
383
384
385/**
386 * Returns a set of keyboard events for KeyPress/KeyRelease, optionally
387 * also with valuator events.  Handles Xi and XKB.
388 *
389 * events is not NULL-terminated; the return value is the number of events.
390 * The DDX is responsible for allocating the event structure in the first
391 * place via GetMaximumEventsNum(), and for freeing it.
392 *
393 * This function does not change the core keymap to that of the device;
394 * that is done by SwitchCoreKeyboard, which is called from
395 * mieqProcessInputEvents.  If replacing that function, take care to call
396 * SetCoreKeyboard before processInputProc, so keymaps are altered to suit.
397 *
398 * Note that this function recurses!  If called for non-XKB, a repeating
399 * key press will trigger a matching KeyRelease, as well as the
400 * KeyPresses.
401 */
402_X_EXPORT int
403GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
404                          int key_code, int first_valuator,
405                          int num_valuators, int *valuators) {
406    int numEvents = 0;
407    CARD32 ms = 0;
408    KeySym *map = pDev->key->curKeySyms.map;
409    KeySym sym = map[key_code * pDev->key->curKeySyms.mapWidth];
410    deviceKeyButtonPointer *kbp = NULL;
411
412    if (!events)
413        return 0;
414
415    /* DO NOT WANT */
416    if (type != KeyPress && type != KeyRelease)
417        return 0;
418
419    if (!pDev->key || !pDev->focus || !pDev->kbdfeed ||
420        (pDev->coreEvents && !inputInfo.keyboard->key))
421        return 0;
422
423    if (key_code < 8 || key_code > 255)
424        return 0;
425
426    if (pDev->coreEvents)
427        numEvents = 2;
428    else
429        numEvents = 1;
430
431    if (num_valuators) {
432        if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS)
433            num_valuators = MAX_VALUATOR_EVENTS;
434        numEvents += (num_valuators / 6) + 1;
435    }
436
437#ifdef XKB
438    if (noXkbExtension)
439#endif
440    {
441        switch (sym) {
442            case XK_Num_Lock:
443            case XK_Caps_Lock:
444            case XK_Scroll_Lock:
445            case XK_Shift_Lock:
446                if (type == KeyRelease)
447                    return 0;
448                else if (type == KeyPress && key_is_down(pDev, key_code))
449                    type = KeyRelease;
450        }
451    }
452
453    /* Handle core repeating, via press/release/press/release.
454     * FIXME: In theory, if you're repeating with two keyboards in non-XKB,
455     *        you could get unbalanced events here. */
456    if (type == KeyPress && key_is_down(pDev, key_code)) {
457        /* If autorepeating is disabled either globally or just for that key,
458         * or we have a modifier, don't generate a repeat event. */
459        if (!pDev->kbdfeed->ctrl.autoRepeat ||
460            !key_autorepeats(pDev, key_code) ||
461            pDev->key->modifierMap[key_code])
462            return 0;
463
464#ifdef XKB
465        if (noXkbExtension)
466#endif
467        {
468            numEvents += GetKeyboardValuatorEvents(events, pDev,
469                                                   KeyRelease, key_code,
470                                                   first_valuator, num_valuators,
471                                                   valuators);
472            events += numEvents;
473        }
474    }
475
476    ms = GetTimeInMillis();
477
478    if (pDev->coreEvents) {
479        events->u.keyButtonPointer.time = ms;
480        events->u.u.type = type;
481        events->u.u.detail = key_code;
482        if (type == KeyPress)
483	    set_key_down(inputInfo.keyboard, key_code);
484        else if (type == KeyRelease)
485	    set_key_up(inputInfo.keyboard, key_code);
486        events++;
487    }
488
489    kbp = (deviceKeyButtonPointer *) events;
490    kbp->time = ms;
491    kbp->deviceid = pDev->id;
492    kbp->detail = key_code;
493    if (type == KeyPress) {
494        kbp->type = DeviceKeyPress;
495	set_key_down(pDev, key_code);
496    }
497    else if (type == KeyRelease) {
498        kbp->type = DeviceKeyRelease;
499	set_key_up(pDev, key_code);
500    }
501
502    events++;
503    if (num_valuators) {
504        kbp->deviceid |= MORE_EVENTS;
505        clipValuators(pDev, first_valuator, num_valuators, valuators);
506        events = getValuatorEvents(events, pDev, first_valuator,
507                                   num_valuators, valuators);
508    }
509
510    return numEvents;
511}
512
513
514/**
515 * Generate a series of xEvents (returned in xE) representing pointer
516 * motion, or button presses.  Xi and XKB-aware.
517 *
518 * events is not NULL-terminated; the return value is the number of events.
519 * The DDX is responsible for allocating the event structure in the first
520 * place via GetMaximumEventsNum(), and for freeing it.
521 */
522_X_EXPORT int
523GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
524                 int flags, int first_valuator, int num_valuators,
525                 int *valuators) {
526    int num_events = 0, final_valuator = 0;
527    CARD32 ms = 0;
528    deviceKeyButtonPointer *kbp = NULL;
529    DeviceIntPtr cp = inputInfo.pointer;
530    int x = 0, y = 0;
531    Bool coreOnly = (pDev == inputInfo.pointer);
532    ScreenPtr scr = miPointerGetScreen(pDev);
533
534    /* Sanity checks. */
535    if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
536        return 0;
537
538    if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
539        return 0;
540
541    /* FIXME: I guess it should, in theory, be possible to post button events
542     *        from devices without valuators. */
543    if (!pDev->valuator)
544        return 0;
545
546    if (!coreOnly && pDev->coreEvents)
547        num_events = 2;
548    else
549        num_events = 1;
550
551    if (type == MotionNotify && num_valuators <= 0)
552        return 0;
553
554    /* Do we need to send a DeviceValuator event? */
555    if (!coreOnly && num_valuators) {
556        if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
557            num_valuators = MAX_VALUATOR_EVENTS * 6;
558        num_events += ((num_valuators - 1) / 6) + 1;
559    }
560
561    final_valuator = num_valuators + first_valuator;
562
563    /* You fail. */
564    if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes)
565        return 0;
566
567    ms = GetTimeInMillis();
568
569    /* Set x and y based on whether this is absolute or relative, and
570     * accelerate if we need to. */
571    if (flags & POINTER_ABSOLUTE) {
572        if (num_valuators >= 1 && first_valuator == 0) {
573            x = valuators[0];
574        }
575        else {
576            /* If we're sending core events but didn't provide a value,
577             * translate the core value (but use the device coord if
578             * it translates to the same coord to preserve sub-pixel
579             * coord information). If we're not sending core events use
580             * whatever value we have */
581            x = pDev->valuator->lastx;
582            if(pDev->coreEvents) {
583                int min = pDev->valuator->axes[0].min_value;
584                int max = pDev->valuator->axes[0].max_value;
585                if(min < max) {
586                    if((int)((float)(x-min)*scr->width/(max-min+1)) != cp->valuator->lastx)
587                        x = (int)((float)(cp->valuator->lastx)*(max-min+1)/scr->width)+min;
588                }
589                else
590                    x = cp->valuator->lastx;
591            }
592        }
593
594        if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
595            y = valuators[1 - first_valuator];
596        }
597        else {
598            y = pDev->valuator->lasty;
599            if(pDev->coreEvents) {
600                int min = pDev->valuator->axes[1].min_value;
601                int max = pDev->valuator->axes[1].max_value;
602                if(min < max) {
603                    if((int)((float)(y-min)*scr->height/(max-min+1)) != cp->valuator->lasty)
604                        y = (int)((float)(cp->valuator->lasty)*(max-min+1)/scr->height)+min;
605                }
606                else
607                    y = cp->valuator->lasty;
608            }
609        }
610
611        /* Clip both x and y to the defined limits (usually co-ord space limit). */
612        clipAxis(pDev, 0, &x);
613        clipAxis(pDev, 1, &y);
614    }
615    else {
616        if (flags & POINTER_ACCELERATE)
617            acceleratePointer(pDev, first_valuator, num_valuators,
618                              valuators);
619
620        if (pDev->coreEvents) {
621            /* Get and convert the core pointer coordinate space into
622             * device coordinates. Use the device coords if it translates
623             * into the same position as the core to preserve relative sub-
624             * pixel movements from the device. */
625            int min = pDev->valuator->axes[0].min_value;
626            int max = pDev->valuator->axes[0].max_value;
627            if(min < max) {
628                x = pDev->valuator->lastx;
629                if((int)((float)(x-min)*scr->width/(max-min+1)) != cp->valuator->lastx)
630                    x = (int)((float)(cp->valuator->lastx)*(max-min+1)/scr->width)+min;
631            }
632            else
633                x = cp->valuator->lastx;
634
635            min = pDev->valuator->axes[1].min_value;
636            max = pDev->valuator->axes[1].max_value;
637            if(min < max) {
638                y = pDev->valuator->lasty;
639                if((int)((float)(y-min)*scr->height/(max-min+1)) != cp->valuator->lasty)
640                    y = (int)((float)(cp->valuator->lasty)*(max-min+1)/scr->height)+min;
641            }
642            else
643                y = cp->valuator->lasty;
644
645            /* Add relative movement */
646            if (first_valuator == 0 && num_valuators >= 1)
647                x += valuators[0];
648            if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
649                y += valuators[1 - first_valuator];
650        }
651        else {
652            x = pDev->valuator->lastx;
653            y = pDev->valuator->lasty;
654            if (first_valuator == 0 && num_valuators >= 1)
655                x += valuators[0];
656            if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
657                y += valuators[1 - first_valuator];
658
659            if(!coreOnly) {
660                /* Since we're not sending core-events we must clip both x and y
661                 * to the defined limits so we don't run outside the box. */
662                clipAxis(pDev, 0, &x);
663                clipAxis(pDev, 1, &y);
664            }
665        }
666    }
667
668    pDev->valuator->lastx = x;
669    pDev->valuator->lasty = y;
670    /* Convert the dev coord back to screen coord if we're
671     * sending core events */
672    if (pDev->coreEvents) {
673        int min = pDev->valuator->axes[0].min_value;
674        int max = pDev->valuator->axes[0].max_value;
675        if(min < max)
676            x = (int)((float)(x-min)*scr->width/(max-min+1));
677        cp->valuator->lastx = x;
678        min = pDev->valuator->axes[1].min_value;
679        max = pDev->valuator->axes[1].max_value;
680        if(min < max)
681            y = (int)((float)(y-min)*scr->height/(max-min+1));
682        cp->valuator->lasty = y;
683    }
684
685    /* This takes care of crossing screens for us, as well as clipping
686     * to the current screen.  Right now, we only have one history buffer,
687     * so we don't set this for both the device and core.*/
688    miPointerSetPosition(pDev, &x, &y, ms);
689
690    if (pDev->coreEvents) {
691        /* miPointerSetPosition may have changed screen */
692        scr = miPointerGetScreen(pDev);
693        if(x != cp->valuator->lastx) {
694            int min = pDev->valuator->axes[0].min_value;
695            int max = pDev->valuator->axes[0].max_value;
696            cp->valuator->lastx = pDev->valuator->lastx = x;
697            if(min < max)
698                pDev->valuator->lastx = (int)((float)(x)*(max-min+1)/scr->width)+min;
699        }
700        if(y != cp->valuator->lasty) {
701            int min = pDev->valuator->axes[1].min_value;
702            int max = pDev->valuator->axes[1].max_value;
703            cp->valuator->lasty = pDev->valuator->lasty = y;
704            if(min < max)
705                pDev->valuator->lasty = (int)((float)(y)*(max-min+1)/scr->height)+min;
706        }
707    }
708    else if (coreOnly) {
709        cp->valuator->lastx = x;
710        cp->valuator->lasty = y;
711    }
712
713    /* Drop x and y back into the valuators list, if they were originally
714     * present. */
715    if (first_valuator == 0 && num_valuators >= 1)
716        valuators[0] = pDev->valuator->lastx;
717    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
718        valuators[1 - first_valuator] = pDev->valuator->lasty;
719
720    updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
721
722    /* for some reason inputInfo.pointer does not have coreEvents set */
723    if (coreOnly || pDev->coreEvents) {
724        events->u.u.type = type;
725        events->u.keyButtonPointer.time = ms;
726        events->u.keyButtonPointer.rootX = x;
727        events->u.keyButtonPointer.rootY = y;
728
729        if (type == ButtonPress || type == ButtonRelease) {
730            /* We hijack SetPointerMapping to work on all core-sending
731             * devices, so we use the device-specific map here instead of
732             * the core one. */
733            events->u.u.detail = pDev->button->map[buttons];
734        }
735        else {
736            events->u.u.detail = 0;
737        }
738
739        events++;
740    }
741
742    if (!coreOnly) {
743        kbp = (deviceKeyButtonPointer *) events;
744        kbp->time = ms;
745        kbp->deviceid = pDev->id;
746
747        if (type == MotionNotify) {
748            kbp->type = DeviceMotionNotify;
749        }
750        else {
751            if (type == ButtonPress)
752                kbp->type = DeviceButtonPress;
753            else if (type == ButtonRelease)
754                kbp->type = DeviceButtonRelease;
755            kbp->detail = pDev->button->map[buttons];
756        }
757
758        kbp->root_x = pDev->valuator->lastx;
759        kbp->root_y = pDev->valuator->lasty;
760
761        events++;
762        if (num_valuators) {
763            kbp->deviceid |= MORE_EVENTS;
764            clipValuators(pDev, first_valuator, num_valuators, valuators);
765            events = getValuatorEvents(events, pDev, first_valuator,
766                                       num_valuators, valuators);
767        }
768    }
769
770    return num_events;
771}
772
773
774/**
775 * Post ProximityIn/ProximityOut events, accompanied by valuators.
776 *
777 * events is not NULL-terminated; the return value is the number of events.
778 * The DDX is responsible for allocating the event structure in the first
779 * place via GetMaximumEventsNum(), and for freeing it.
780 */
781_X_EXPORT int
782GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type,
783                   int first_valuator, int num_valuators, int *valuators)
784{
785    int num_events = 1;
786    deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) events;
787
788    /* Sanity checks. */
789    if (type != ProximityIn && type != ProximityOut)
790        return 0;
791
792    if (!pDev->valuator)
793        return 0;
794
795    /* Do we need to send a DeviceValuator event? */
796    if ((pDev->valuator->mode & 1) == Relative)
797        num_valuators = 0;
798
799    if (num_valuators) {
800        if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
801            num_valuators = MAX_VALUATOR_EVENTS * 6;
802        num_events += ((num_valuators - 1) / 6) + 1;
803    }
804
805    /* You fail. */
806    if (first_valuator < 0 ||
807        (num_valuators + first_valuator) > pDev->valuator->numAxes)
808        return 0;
809
810    kbp->type = type;
811    kbp->deviceid = pDev->id;
812    kbp->detail = 0;
813    kbp->time = GetTimeInMillis();
814
815    if (num_valuators) {
816        kbp->deviceid |= MORE_EVENTS;
817        events++;
818        clipValuators(pDev, first_valuator, num_valuators, valuators);
819        events = getValuatorEvents(events, pDev, first_valuator,
820                                   num_valuators, valuators);
821    }
822
823    return num_events;
824}
825
826
827/**
828 * Note that pDev was the last device to send a core event.  This function
829 * copies the complete keymap from the originating device to the core
830 * device, and makes sure the appropriate notifications are generated.
831 *
832 * Call this just before processInputProc.
833 */
834_X_EXPORT void
835SwitchCoreKeyboard(DeviceIntPtr pDev)
836{
837    KeyClassPtr ckeyc = inputInfo.keyboard->key;
838    int i = 0;
839
840    if (inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr != pDev) {
841        memcpy(ckeyc->modifierMap, pDev->key->modifierMap, MAP_LENGTH);
842        if (ckeyc->modifierKeyMap)
843            xfree(ckeyc->modifierKeyMap);
844        ckeyc->modifierKeyMap = xalloc(8 * pDev->key->maxKeysPerModifier);
845        memcpy(ckeyc->modifierKeyMap, pDev->key->modifierKeyMap,
846                (8 * pDev->key->maxKeysPerModifier));
847
848        ckeyc->maxKeysPerModifier = pDev->key->maxKeysPerModifier;
849        ckeyc->curKeySyms.minKeyCode = pDev->key->curKeySyms.minKeyCode;
850        ckeyc->curKeySyms.maxKeyCode = pDev->key->curKeySyms.maxKeyCode;
851        SetKeySymsMap(&ckeyc->curKeySyms, &pDev->key->curKeySyms);
852
853        /*
854         * Copy state from the extended keyboard to core.  If you omit this,
855         * holding Ctrl on keyboard one, and pressing Q on keyboard two, will
856         * cause your app to quit.  This feels wrong to me, hence the below
857         * code.
858         *
859         * XXX: If you synthesise core modifier events, the state will get
860         *      clobbered here.  You'll have to work out something sensible
861         *      to fix that.  Good luck.
862         */
863
864#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \
865                       Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
866        ckeyc->state &= ~(KEYBOARD_MASK);
867        ckeyc->state |= (pDev->key->state & KEYBOARD_MASK);
868#undef KEYBOARD_MASK
869        for (i = 0; i < 8; i++)
870            ckeyc->modifierKeyCount[i] = pDev->key->modifierKeyCount[i];
871
872#ifdef XKB
873        if (!noXkbExtension && pDev->key->xkbInfo && pDev->key->xkbInfo->desc) {
874            if (!XkbCopyKeymap(pDev->key->xkbInfo->desc, ckeyc->xkbInfo->desc,
875                               True))
876                FatalError("Couldn't pivot keymap from device to core!\n");
877        }
878#endif
879
880        SendMappingNotify(MappingKeyboard, ckeyc->curKeySyms.minKeyCode,
881                          (ckeyc->curKeySyms.maxKeyCode -
882                           ckeyc->curKeySyms.minKeyCode),
883                          serverClient);
884        inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr = pDev;
885    }
886}
887
888
889/**
890 * Note that pDev was the last function to send a core pointer event.
891 * Currently a no-op.
892 *
893 * Call this just before processInputProc.
894 */
895_X_EXPORT void
896SwitchCorePointer(DeviceIntPtr pDev)
897{
898    if (inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr != pDev)
899        inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr = pDev;
900}
901
902
903/**
904 * Synthesize a single motion event for the core pointer.
905 *
906 * Used in cursor functions, e.g. when cursor confinement changes, and we need
907 * to shift the pointer to get it inside the new bounds.
908 */
909void
910PostSyntheticMotion(int x, int y, int screen, unsigned long time)
911{
912    xEvent xE;
913
914#ifdef PANORAMIX
915    /* Translate back to the sprite screen since processInputProc
916       will translate from sprite screen to screen 0 upon reentry
917       to the DIX layer. */
918    if (!noPanoramiXExtension) {
919        x += panoramiXdataPtr[0].x - panoramiXdataPtr[screen].x;
920        y += panoramiXdataPtr[0].y - panoramiXdataPtr[screen].y;
921    }
922#endif
923
924    memset(&xE, 0, sizeof(xEvent));
925    xE.u.u.type = MotionNotify;
926    xE.u.keyButtonPointer.rootX = x;
927    xE.u.keyButtonPointer.rootY = y;
928    xE.u.keyButtonPointer.time = time;
929
930    (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1);
931}
932