getevents.c revision 4642e01f
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>
50#endif
51
52#ifdef PANORAMIX
53#include "panoramiX.h"
54#include "panoramiXsrv.h"
55#endif
56
57#include <X11/extensions/XI.h>
58#include <X11/extensions/XIproto.h>
59#include "exglobals.h"
60#include "exevents.h"
61#include "exglobals.h"
62#include "extnsionst.h"
63
64/* Number of motion history events to store. */
65#define MOTION_HISTORY_SIZE 256
66
67/* InputEventList is the container list for all input events generated by the
68 * DDX. The DDX is expected to call GetEventList() and then pass the list into
69 * Get{Pointer|Keyboard}Events.
70 */
71EventListPtr InputEventList = NULL;
72int InputEventListLen = 0;
73
74_X_EXPORT int
75GetEventList(EventListPtr* list)
76{
77    *list = InputEventList;
78    return InputEventListLen;
79}
80
81/**
82 * Pick some arbitrary size for Xi motion history.
83 */
84_X_EXPORT int
85GetMotionHistorySize(void)
86{
87    return MOTION_HISTORY_SIZE;
88}
89
90static void
91set_key_down(DeviceIntPtr pDev, int key_code)
92{
93    pDev->key->postdown[key_code >> 3] |= (1 << (key_code & 7));
94}
95
96static void
97set_key_up(DeviceIntPtr pDev, int key_code)
98{
99    pDev->key->postdown[key_code >> 3] &= ~(1 << (key_code & 7));
100}
101
102static Bool
103key_is_down(DeviceIntPtr pDev, int key_code)
104{
105    return !!(pDev->key->postdown[key_code >> 3] & (1 << (key_code & 7)));
106}
107
108static Bool
109key_autorepeats(DeviceIntPtr pDev, int key_code)
110{
111    return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
112              (1 << (key_code & 7)));
113}
114
115/**
116 * Rescale the coord between the two axis ranges.
117 */
118static int
119rescaleValuatorAxis(int coord, AxisInfoPtr from, AxisInfoPtr to,
120                    int defmax)
121{
122    int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax;
123
124    if(from && from->min_value < from->max_value) {
125        fmin = from->min_value;
126        fmax = from->max_value;
127    }
128    if(to && to->min_value < to->max_value) {
129        tmin = to->min_value;
130        tmax = to->max_value;
131    }
132
133    if(fmin == tmin && fmax == tmax)
134        return coord;
135
136    if(fmax == fmin) /* avoid division by 0 */
137        return 0;
138
139    return roundf(((float)(coord - fmin)) * (tmax - tmin) /
140                 (fmax - fmin)) + tmin;
141}
142
143/**
144 * Update all coordinates when changing to a different SD
145 * to ensure that relative reporting will work as expected
146 * without loss of precision.
147 *
148 * pDev->last.valuators will be in absolute device coordinates after this
149 * function.
150 */
151static void
152updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
153{
154    ScreenPtr scr = miPointerGetScreen(pDev);
155    int i;
156    DeviceIntPtr lastSlave;
157
158    /* master->last.valuators[0]/[1] is in screen coords and the actual
159     * position of the pointer */
160    pDev->last.valuators[0] = master->last.valuators[0];
161    pDev->last.valuators[1] = master->last.valuators[1];
162
163    if (!pDev->valuator)
164        return;
165
166    /* scale back to device coordinates */
167    if(pDev->valuator->numAxes > 0)
168        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL, pDev->valuator->axes + 0, scr->width);
169    if(pDev->valuator->numAxes > 1)
170        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL, pDev->valuator->axes + 1, scr->height);
171
172    /* calculate the other axis as well based on info from the old
173     * slave-device. If the old slave had less axes than this one,
174     * last.valuators is reset to 0.
175     */
176    if ((lastSlave = master->u.lastSlave) && lastSlave->valuator) {
177        for (i = 2; i < pDev->valuator->numAxes; i++) {
178            if (i >= lastSlave->valuator->numAxes)
179                pDev->last.valuators[i] = 0;
180            else
181                pDev->last.valuators[i] =
182                    rescaleValuatorAxis(pDev->last.valuators[i],
183                            lastSlave->valuator->axes + i,
184                            pDev->valuator->axes + i, 0);
185        }
186    }
187
188}
189
190/**
191 * Allocate the motion history buffer.
192 */
193_X_EXPORT void
194AllocateMotionHistory(DeviceIntPtr pDev)
195{
196    int size;
197    if (pDev->valuator->motion)
198        xfree(pDev->valuator->motion);
199
200    if (pDev->valuator->numMotionEvents < 1)
201        return;
202
203    /* An MD must have a motion history size large enough to keep all
204     * potential valuators, plus the respective range of the valuators.
205     * 3 * INT32 for (min_val, max_val, curr_val))
206     */
207    if (pDev->isMaster)
208        size = sizeof(INT32) * 3 * MAX_VALUATORS;
209    else
210        size = sizeof(INT32) * pDev->valuator->numAxes;
211
212    size += sizeof(Time);
213
214    pDev->valuator->motion = xcalloc(pDev->valuator->numMotionEvents, size);
215    pDev->valuator->first_motion = 0;
216    pDev->valuator->last_motion = 0;
217    if (!pDev->valuator->motion)
218        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
219                pDev->name, size * pDev->valuator->numMotionEvents);
220}
221
222/**
223 * Dump the motion history between start and stop into the supplied buffer.
224 * Only records the event for a given screen in theory, but in practice, we
225 * sort of ignore this.
226 *
227 * If core is set, we only generate x/y, in INT16, scaled to screen coords.
228 */
229_X_EXPORT int
230GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
231                 unsigned long stop, ScreenPtr pScreen, BOOL core)
232{
233    char *ibuff = NULL, *obuff;
234    int i = 0, ret = 0;
235    int j, coord;
236    Time current;
237    /* The size of a single motion event. */
238    int size;
239    int dflt;
240    AxisInfo from, *to; /* for scaling */
241    INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
242    INT16 *corebuf;
243    AxisInfo core_axis = {0};
244
245    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
246        return 0;
247
248    if (core && !pScreen)
249        return 0;
250
251    if (pDev->isMaster)
252        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
253    else
254        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
255
256    *buff = xalloc(size * pDev->valuator->numMotionEvents);
257    if (!(*buff))
258        return 0;
259    obuff = (char *)*buff;
260
261    for (i = pDev->valuator->first_motion;
262         i != pDev->valuator->last_motion;
263         i = (i + 1) % pDev->valuator->numMotionEvents) {
264        /* We index the input buffer by which element we're accessing, which
265         * is not monotonic, and the output buffer by how many events we've
266         * written so far. */
267        ibuff = (char *) pDev->valuator->motion + (i * size);
268        memcpy(&current, ibuff, sizeof(Time));
269
270        if (current > stop) {
271            return ret;
272        }
273        else if (current >= start) {
274            if (core)
275            {
276                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
277
278                icbuf = (INT32*)(ibuff + sizeof(Time));
279                corebuf = (INT16*)(obuff + sizeof(Time));
280
281                /* fetch x coordinate + range */
282                memcpy(&from.min_value, icbuf++, sizeof(INT32));
283                memcpy(&from.max_value, icbuf++, sizeof(INT32));
284                memcpy(&coord, icbuf++, sizeof(INT32));
285
286                /* scale to screen coords */
287                to = &core_axis;
288                to->max_value = pScreen->width;
289                coord = rescaleValuatorAxis(coord, &from, to, pScreen->width);
290
291                memcpy(corebuf, &coord, sizeof(INT16));
292                corebuf++;
293
294                /* fetch y coordinate + range */
295                memcpy(&from.min_value, icbuf++, sizeof(INT32));
296                memcpy(&from.max_value, icbuf++, sizeof(INT32));
297                memcpy(&coord, icbuf++, sizeof(INT32));
298
299                to->max_value = pScreen->height;
300                coord = rescaleValuatorAxis(coord, &from, to, pScreen->height);
301                memcpy(corebuf, &coord, sizeof(INT16));
302
303            } else if (pDev->isMaster)
304            {
305                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
306
307                ocbuf = (INT32*)(obuff + sizeof(Time));
308                icbuf = (INT32*)(ibuff + sizeof(Time));
309                for (j = 0; j < MAX_VALUATORS; j++)
310                {
311                    if (j >= pDev->valuator->numAxes)
312                        break;
313
314                    /* fetch min/max/coordinate */
315                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
316                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
317                    memcpy(&coord, icbuf++, sizeof(INT32));
318
319                    to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
320
321                    /* x/y scaled to screen if no range is present */
322                    if (j == 0 && (from.max_value < from.min_value))
323                        from.max_value = pScreen->width;
324                    else if (j == 1 && (from.max_value < from.min_value))
325                        from.max_value = pScreen->height;
326
327                    if (j == 0 && (to->max_value < to->min_value))
328                        dflt = pScreen->width;
329                    else if (j == 1 && (to->max_value < to->min_value))
330                        dflt = pScreen->height;
331                    else
332                        dflt = 0;
333
334                    /* scale from stored range into current range */
335                    coord = rescaleValuatorAxis(coord, &from, to, 0);
336                    memcpy(ocbuf, &coord, sizeof(INT32));
337                    ocbuf++;
338                }
339            } else
340                memcpy(obuff, ibuff, size);
341
342            /* don't advance by size here. size may be different to the
343             * actually written size if the MD has less valuators than MAX */
344            if (core)
345                obuff += sizeof(INT32) + sizeof(Time);
346            else
347                obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
348            ret++;
349        }
350    }
351
352    return ret;
353}
354
355
356/**
357 * Update the motion history for a specific device, with the list of
358 * valuators.
359 *
360 * Layout of the history buffer:
361 *   for SDs: [time] [val0] [val1] ... [valn]
362 *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
363 *
364 * For events that have some valuators unset (first_valuator > 0):
365 *      min_val == max_val == val == 0.
366 */
367static void
368updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
369                    int num_valuators, int *valuators)
370{
371    char *buff = (char *) pDev->valuator->motion;
372    ValuatorClassPtr v;
373    int i;
374
375    if (!pDev->valuator->numMotionEvents)
376        return;
377
378    v = pDev->valuator;
379    if (pDev->isMaster)
380    {
381        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
382                v->last_motion;
383
384        memcpy(buff, &ms, sizeof(Time));
385        buff += sizeof(Time);
386
387        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
388        buff += 3 * sizeof(INT32) * first_valuator;
389
390        for (i = first_valuator; i < first_valuator + num_valuators; i++)
391        {
392            if (i >= v->numAxes)
393                break;
394            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
395            buff += sizeof(INT32);
396            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
397            buff += sizeof(INT32);
398            memcpy(buff, &valuators[i - first_valuator], sizeof(INT32));
399            buff += sizeof(INT32);
400        }
401    } else
402    {
403
404        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
405            pDev->valuator->last_motion;
406
407        memcpy(buff, &ms, sizeof(Time));
408        buff += sizeof(Time);
409
410        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
411        buff += sizeof(INT32) * first_valuator;
412
413        memcpy(buff, valuators, sizeof(INT32) * num_valuators);
414    }
415
416    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
417        pDev->valuator->numMotionEvents;
418    /* If we're wrapping around, just keep the circular buffer going. */
419    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
420        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
421                                       pDev->valuator->numMotionEvents;
422
423    return;
424}
425
426
427/**
428 * Returns the maximum number of events GetKeyboardEvents,
429 * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
430 *
431 * Should be used in DIX as:
432 * xEvent *events = xcalloc(sizeof(xEvent), GetMaximumEventsNum());
433 *
434 * This MUST be absolutely constant, from init until exit.
435 */
436_X_EXPORT int
437GetMaximumEventsNum(void) {
438    /* One base event -- device, plus valuator events.
439     *  Multiply by two if we're doing non-XKB key repeats. */
440    int ret = 1 + MAX_VALUATOR_EVENTS;
441
442#ifdef XKB
443    if (noXkbExtension)
444#endif
445        ret *= 2;
446
447    return ret;
448}
449
450
451/**
452 * Clip an axis to its bounds, which are declared in the call to
453 * InitValuatorAxisClassStruct.
454 */
455static void
456clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
457{
458    AxisInfoPtr axis = pDev->valuator->axes + axisNum;
459    /* InitValuatoraAxisStruct ensures that (min < max). */
460
461    /* If a value range is defined, clip. If not, do nothing */
462    if (axis->max_value <= axis->min_value)
463        return;
464
465    if (*val < axis->min_value)
466        *val = axis->min_value;
467    if (*val > axis->max_value)
468        *val = axis->max_value;
469}
470
471/**
472 * Clip every axis in the list of valuators to its bounds.
473 */
474static void
475clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
476              int *valuators)
477{
478    AxisInfoPtr axes = pDev->valuator->axes + first_valuator;
479    int i;
480
481    for (i = 0; i < num_valuators; i++, axes++)
482        clipAxis(pDev, i + first_valuator, &(valuators[i]));
483}
484
485
486/**
487 * Fills events with valuator events for pDev, as given by the other
488 * parameters.
489 */
490static EventList *
491getValuatorEvents(EventList *events, DeviceIntPtr pDev,
492        int first_valuator, int num_valuators, int *valuators) {
493    deviceValuator *xv;
494    int i;
495
496    for (i = 0; i < num_valuators; i += 6, events++) {
497        xv = (deviceValuator*)events->event;
498        xv->type = DeviceValuator;
499        xv->first_valuator = first_valuator + i;
500        xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i);
501        xv->deviceid = pDev->id;
502        switch (num_valuators - i) {
503        case 6:
504            xv->valuator5 = valuators[i + 5];
505        case 5:
506            xv->valuator4 = valuators[i + 4];
507        case 4:
508            xv->valuator3 = valuators[i + 3];
509        case 3:
510            xv->valuator2 = valuators[i + 2];
511        case 2:
512            xv->valuator1 = valuators[i + 1];
513        case 1:
514            xv->valuator0 = valuators[i + 0];
515        }
516
517        if (i + 6 < num_valuators)
518            xv->deviceid |= MORE_EVENTS;
519    }
520
521    return events;
522}
523
524/**
525 * Create the DCCE event (does not update the master's device state yet, this
526 * is done in the event processing).
527 * Pull in the coordinates from the MD if necessary.
528 *
529 * @param events Pointer to a pre-allocated event list.
530 * @param dev The slave device that generated an event.
531 * @param num_events The current number of events, returns the number of
532 *        events if a DCCE was generated.
533 * @return The updated @events pointer.
534 */
535static EventListPtr
536updateFromMaster(EventListPtr events, DeviceIntPtr dev, int *num_events)
537{
538    DeviceIntPtr master = dev->u.master;
539    if (master && master->u.lastSlave != dev)
540    {
541        updateSlaveDeviceCoords(master, dev);
542        master->u.lastSlave = dev;
543        master->last.numValuators = dev->last.numValuators;
544    }
545    return events;
546}
547
548/**
549 * Move the device's pointer to the position given in the valuators.
550 *
551 * @param dev The device which's pointer is to be moved.
552 * @param x Returns the x position of the pointer after the move.
553 * @param y Returns the y position of the pointer after the move.
554 * @param first The first valuator in @valuators
555 * @param num Total number of valuators in @valuators.
556 * @param valuators Valuator data for each axis between @first and
557 *        @first+@num.
558 */
559static void
560moveAbsolute(DeviceIntPtr dev, int *x, int *y,
561             int first, int num, int *valuators)
562{
563    int i;
564
565
566    if (num >= 1 && first == 0)
567        *x = *(valuators + 0);
568    else
569        *x = dev->last.valuators[0];
570
571    if (first <= 1 && num >= (2 - first))
572        *y = *(valuators + 1 - first);
573    else
574        *y = dev->last.valuators[1];
575
576    clipAxis(dev, 0, x);
577    clipAxis(dev, 1, y);
578
579    i = (first > 2) ? 0 : 2;
580    for (; i < num; i++)
581    {
582        dev->last.valuators[i + first] = valuators[i];
583        clipAxis(dev, i, &dev->last.valuators[i + first]);
584    }
585}
586
587/**
588 * Move the device's pointer by the values given in @valuators.
589 *
590 * @param dev The device which's pointer is to be moved.
591 * @param x Returns the x position of the pointer after the move.
592 * @param y Returns the y position of the pointer after the move.
593 * @param first The first valuator in @valuators
594 * @param num Total number of valuators in @valuators.
595 * @param valuators Valuator data for each axis between @first and
596 *        @first+@num.
597 */
598static void
599moveRelative(DeviceIntPtr dev, int *x, int *y,
600             int first, int num, int *valuators)
601{
602    int i;
603
604    *x = dev->last.valuators[0];
605    *y = dev->last.valuators[1];
606
607    if (num >= 1 && first == 0)
608        *x += *(valuators +0);
609
610    if (first <= 1 && num >= (2 - first))
611        *y += *(valuators + 1 - first);
612
613    /* if attached, clip both x and y to the defined limits (usually
614     * co-ord space limit). If it is attached, we need x/y to go over the
615     * limits to be able to change screens. */
616    if(dev->u.master) {
617        clipAxis(dev, 0, x);
618        clipAxis(dev, 1, y);
619    }
620
621    /* calc other axes, clip, drop back into valuators */
622    i = (first > 2) ? 0 : 2;
623    for (; i < num; i++)
624    {
625        dev->last.valuators[i + first] += valuators[i];
626        clipAxis(dev, i, &dev->last.valuators[i + first]);
627        valuators[i] = dev->last.valuators[i + first];
628    }
629}
630
631/**
632 * Accelerate the data in valuators based on the device's acceleration scheme.
633 *
634 * @param dev The device which's pointer is to be moved.
635 * @param first The first valuator in @valuators
636 * @param num Total number of valuators in @valuators.
637 * @param valuators Valuator data for each axis between @first and
638 *        @first+@num.
639 * @param ms Current time.
640 */
641static void
642accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
643{
644    if (dev->valuator->accelScheme.AccelSchemeProc)
645        dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms);
646}
647
648/**
649 * If we have HW cursors, this actually moves the visible sprite. If not, we
650 * just do all the screen crossing, etc.
651 *
652 * We scale from device to screen coordinates here, call
653 * miPointerSetPosition() and then scale back into device coordinates (if
654 * needed). miPSP will change x/y if the screen was crossed.
655 *
656 * @param dev The device to be moved.
657 * @param x Pointer to current x-axis value, may be modified.
658 * @param y Pointer to current y-axis value, may be modified.
659 * @param scr Screen the device's sprite is currently on.
660 * @param screenx Screen x coordinate the sprite is on after the update.
661 * @param screeny Screen y coordinate the sprite is on after the update.
662 */
663static void
664positionSprite(DeviceIntPtr dev, int *x, int *y,
665               ScreenPtr scr, int *screenx, int *screeny)
666{
667    /* scale x&y to screen */
668    *screenx = rescaleValuatorAxis(*x, dev->valuator->axes + 0, NULL, scr->width);
669    *screeny = rescaleValuatorAxis(*y, dev->valuator->axes + 1, NULL, scr->height);
670    dev->last.valuators[0] = *screenx;
671    dev->last.valuators[1] = *screeny;
672
673    /* This takes care of crossing screens for us, as well as clipping
674     * to the current screen. */
675    miPointerSetPosition(dev, &dev->last.valuators[0], &dev->last.valuators[1]);
676
677    if (dev->u.master) {
678        dev->u.master->last.valuators[0] = dev->last.valuators[0];
679        dev->u.master->last.valuators[1] = dev->last.valuators[1];
680    }
681
682    /* Crossed screen? Scale back to device coordiantes */
683    if(*screenx != dev->last.valuators[0])
684    {
685        scr = miPointerGetScreen(dev);
686        *x = rescaleValuatorAxis(dev->last.valuators[0], NULL,
687                                dev->valuator->axes + 0, scr->width);
688        *screenx = dev->last.valuators[0];
689    }
690    if(*screeny != dev->last.valuators[1])
691    {
692        scr = miPointerGetScreen(dev);
693        *screeny = dev->last.valuators[1];
694        *y = rescaleValuatorAxis(dev->last.valuators[1], NULL,
695                                 dev->valuator->axes + 1, scr->height);
696    }
697
698    /* dropy x/y (device coordinates) back into valuators for next event */
699    dev->last.valuators[0] = *x;
700    dev->last.valuators[1] = *y;
701}
702
703/**
704 * Update the motion history for the device and (if appropriate) for its
705 * master device.
706 * @param dev Slave device to update.
707 * @param first First valuator to append to history.
708 * @param num Total number of valuators to append to history.
709 * @param ms Current time
710 */
711static void
712updateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms)
713{
714    updateMotionHistory(dev, ms, first, num, &dev->last.valuators[first]);
715    if (dev->u.master)
716        updateMotionHistory(dev->u.master, ms, first, num,
717                            &dev->last.valuators[first]);
718}
719
720/**
721 * Calculate how many DeviceValuator events are needed given a number of
722 * valuators.
723 * @param num_valuators Number of valuators to attach to event.
724 * @return the number of DeviceValuator events needed.
725 */
726static int
727countValuatorEvents(int num_valuators)
728{
729    if (num_valuators) {
730        if (((num_valuators - 1) / 6) + 1 > MAX_VALUATOR_EVENTS)
731            num_valuators = MAX_VALUATOR_EVENTS * 6;
732        return ((num_valuators - 1)/ 6) + 1;
733    } else
734        return 0;
735}
736
737/**
738 * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
739 * valuators.
740 */
741_X_EXPORT int
742GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
743    return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL);
744}
745
746
747/**
748 * Returns a set of keyboard events for KeyPress/KeyRelease, optionally
749 * also with valuator events.  Handles Xi and XKB.
750 *
751 * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
752 * event (ProcessOtherEvent).
753 *
754 * events is not NULL-terminated; the return value is the number of events.
755 * The DDX is responsible for allocating the event structure in the first
756 * place via GetMaximumEventsNum(), and for freeing it.
757 *
758 * This function does not change the core keymap to that of the device;
759 * that is done by SwitchCoreKeyboard, which is called from
760 * mieqProcessInputEvents.  If replacing that function, take care to call
761 * SetCoreKeyboard before processInputProc, so keymaps are altered to suit.
762 *
763 * Note that this function recurses!  If called for non-XKB, a repeating
764 * key press will trigger a matching KeyRelease, as well as the
765 * KeyPresses.
766 */
767_X_EXPORT int
768GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
769                          int key_code, int first_valuator,
770                          int num_valuators, int *valuators) {
771    int numEvents = 0;
772    CARD32 ms = 0;
773    KeySym *map;
774    KeySym sym;
775    deviceKeyButtonPointer *kbp = NULL;
776
777    if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
778       (type != KeyPress && type != KeyRelease) ||
779       (key_code < 8 || key_code > 255))
780        return 0;
781
782    numEvents = 1;
783
784    map = pDev->key->curKeySyms.map;
785    sym = map[(key_code - pDev->key->curKeySyms.minKeyCode)
786              * pDev->key->curKeySyms.mapWidth];
787
788    events = updateFromMaster(events, pDev, &numEvents);
789
790    numEvents += countValuatorEvents(num_valuators);
791
792#ifdef XKB
793    if (noXkbExtension)
794#endif
795    {
796        switch (sym) {
797            case XK_Num_Lock:
798            case XK_Caps_Lock:
799            case XK_Scroll_Lock:
800            case XK_Shift_Lock:
801                if (type == KeyRelease)
802                    return 0;
803                else if (type == KeyPress && key_is_down(pDev, key_code))
804                    type = KeyRelease;
805        }
806    }
807
808    /* Handle core repeating, via press/release/press/release.
809     * FIXME: In theory, if you're repeating with two keyboards in non-XKB,
810     *        you could get unbalanced events here. */
811    if (type == KeyPress && key_is_down(pDev, key_code)) {
812        /* If autorepeating is disabled either globally or just for that key,
813         * or we have a modifier, don't generate a repeat event. */
814        if (!pDev->kbdfeed->ctrl.autoRepeat ||
815            !key_autorepeats(pDev, key_code) ||
816            pDev->key->modifierMap[key_code])
817            return 0;
818
819#ifdef XKB
820        if (noXkbExtension)
821#endif
822        {
823            int numReleaseEvents;
824
825            numReleaseEvents = GetKeyboardValuatorEvents(events, pDev,
826                                                         KeyRelease, key_code,
827                                                         first_valuator,
828                                                         num_valuators,
829                                                         valuators);
830            numEvents += numReleaseEvents;
831            events += numReleaseEvents;
832        }
833    }
834
835    ms = GetTimeInMillis();
836
837    kbp = (deviceKeyButtonPointer *) events->event;
838    kbp->time = ms;
839    kbp->deviceid = pDev->id;
840    kbp->detail = key_code;
841    if (type == KeyPress) {
842        kbp->type = DeviceKeyPress;
843	set_key_down(pDev, key_code);
844    }
845    else if (type == KeyRelease) {
846        kbp->type = DeviceKeyRelease;
847	set_key_up(pDev, key_code);
848    }
849
850    events++;
851    if (num_valuators) {
852        kbp->deviceid |= MORE_EVENTS;
853        clipValuators(pDev, first_valuator, num_valuators, valuators);
854        events = getValuatorEvents(events, pDev, first_valuator,
855                                   num_valuators, valuators);
856    }
857
858    return numEvents;
859}
860
861/**
862 * Initialize an event list and fill with 32 byte sized events.
863 * This event list is to be passed into GetPointerEvents() and
864 * GetKeyboardEvents().
865 *
866 * @param num_events Number of elements in list.
867 */
868EventListPtr
869InitEventList(int num_events)
870{
871    EventListPtr events;
872    int i;
873
874    events = (EventListPtr)xcalloc(num_events, sizeof(EventList));
875    if (!events)
876        return NULL;
877
878    for (i = 0; i < num_events; i++)
879    {
880        events[i].evlen = sizeof(xEvent);
881        events[i].event = xcalloc(1, sizeof(xEvent));
882        if (!events[i].event)
883        {
884            /* rollback */
885            while(i--)
886                xfree(events[i].event);
887            xfree(events);
888            events = NULL;
889            break;
890        }
891    }
892
893    return events;
894}
895
896/**
897 * Allocs min_size memory for each event in the list.
898 */
899_X_EXPORT void
900SetMinimumEventSize(EventListPtr list, int num_events, int min_size)
901{
902    if (!list)
903        return;
904
905    while(num_events--)
906    {
907        if (list[num_events].evlen < min_size)
908        {
909            list[num_events].evlen = min_size;
910            list[num_events].event = realloc(list[num_events].event, min_size);
911            if (!list[num_events].event)
912            {
913                FatalError("[dix] Failed to set event list's "
914                        "min_size to %d.\n", min_size);
915            }
916        }
917    }
918}
919
920/**
921 * Free an event list.
922 *
923 * @param list The list to be freed.
924 * @param num_events Number of elements in list.
925 */
926_X_EXPORT void
927FreeEventList(EventListPtr list, int num_events)
928{
929    if (!list)
930        return;
931    while(num_events--)
932        xfree(list[num_events].event);
933    xfree(list);
934}
935
936/**
937 * Generate a series of xEvents (filled into the EventList) representing
938 * pointer motion, or button presses.  Xi and XKB-aware.
939 *
940 * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
941 * event (ProcessOtherEvent).
942 *
943 * events is not NULL-terminated; the return value is the number of events.
944 * The DDX is responsible for allocating the event structure in the first
945 * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
946 *
947 * In the generated events rootX/Y will be in absolute screen coords and
948 * the valuator information in the absolute or relative device coords.
949 *
950 * last.valuators[x] of the device is always in absolute device coords.
951 * last.valuators[x] of the master device is in absolute screen coords.
952 *
953 * master->last.valuators[x] for x > 2 is undefined.
954 */
955_X_EXPORT int
956GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
957                 int flags, int first_valuator, int num_valuators,
958                 int *valuators) {
959    int num_events = 1;
960    CARD32 ms;
961    deviceKeyButtonPointer *kbp = NULL;
962    int x, y, /* switches between device and screen coords */
963        cx, cy; /* only screen coordinates */
964    ScreenPtr scr = miPointerGetScreen(pDev);
965
966    ms = GetTimeInMillis(); /* before pointer update to help precision */
967
968    if (!scr || !pDev->valuator || first_valuator < 0 ||
969        ((num_valuators + first_valuator) > pDev->valuator->numAxes) ||
970        (type != MotionNotify && type != ButtonPress && type != ButtonRelease) ||
971        (type != MotionNotify && !pDev->button) ||
972        (type == MotionNotify && num_valuators <= 0))
973        return 0;
974
975    num_events += countValuatorEvents(num_valuators);
976
977    events = updateFromMaster(events, pDev, &num_events);
978
979    if (flags & POINTER_ABSOLUTE)
980    {
981        if (flags & POINTER_SCREEN) /* valuators are in screen coords */
982        {
983
984            valuators[0] = rescaleValuatorAxis(valuators[0], NULL,
985                                               pDev->valuator->axes + 0,
986                                               scr->width);
987            valuators[1] = rescaleValuatorAxis(valuators[1], NULL,
988                                               pDev->valuator->axes + 1,
989                                               scr->height);
990        }
991
992        moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators);
993    } else {
994        if (flags & POINTER_ACCELERATE)
995            accelPointer(pDev, first_valuator, num_valuators, valuators, ms);
996        moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators);
997    }
998
999    positionSprite(pDev, &x, &y, scr, &cx, &cy);
1000    updateHistory(pDev, first_valuator, num_valuators, ms);
1001
1002
1003    /* Update the valuators with the true value sent to the client*/
1004    if (num_valuators >= 1 && first_valuator == 0)
1005        valuators[0] = x;
1006    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
1007        valuators[1 - first_valuator] = y;
1008
1009    kbp = (deviceKeyButtonPointer *) events->event;
1010    kbp->time = ms;
1011    kbp->deviceid = pDev->id;
1012
1013    if (type == MotionNotify) {
1014        kbp->type = DeviceMotionNotify;
1015    }
1016    else {
1017        if (type == ButtonPress)
1018            kbp->type = DeviceButtonPress;
1019        else if (type == ButtonRelease)
1020            kbp->type = DeviceButtonRelease;
1021        kbp->detail = buttons;
1022    }
1023
1024    kbp->root_x = cx; /* root_x/y always in screen coords */
1025    kbp->root_y = cy;
1026
1027    events++;
1028    if (num_valuators) {
1029        kbp->deviceid |= MORE_EVENTS;
1030        if (flags & POINTER_ABSOLUTE)
1031            clipValuators(pDev, first_valuator, num_valuators, valuators);
1032        events = getValuatorEvents(events, pDev, first_valuator,
1033                                   num_valuators, valuators);
1034    }
1035
1036    return num_events;
1037}
1038
1039
1040/**
1041 * Post ProximityIn/ProximityOut events, accompanied by valuators.
1042 *
1043 * events is not NULL-terminated; the return value is the number of events.
1044 * The DDX is responsible for allocating the event structure in the first
1045 * place via GetMaximumEventsNum(), and for freeing it.
1046 */
1047_X_EXPORT int
1048GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
1049                   int first_valuator, int num_valuators, int *valuators)
1050{
1051    int num_events = 1;
1052    deviceKeyButtonPointer *kbp;
1053    DeviceIntPtr master;
1054
1055    /* Sanity checks. */
1056    if (type != ProximityIn && type != ProximityOut)
1057        return 0;
1058    if (!pDev->valuator)
1059        return 0;
1060    /* Do we need to send a DeviceValuator event? */
1061    if ((pDev->valuator->mode & 1) == Relative)
1062        num_valuators = 0;
1063
1064    if (num_valuators) {
1065        if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
1066            num_valuators = MAX_VALUATOR_EVENTS * 6;
1067        num_events += ((num_valuators - 1) / 6) + 1;
1068    }
1069
1070    /* You fail. */
1071    if (first_valuator < 0 ||
1072        (num_valuators + first_valuator) > pDev->valuator->numAxes)
1073        return 0;
1074
1075    master = pDev->u.master;
1076    if (master && master->u.lastSlave != pDev)
1077    {
1078        updateSlaveDeviceCoords(master, pDev);
1079        master->u.lastSlave = pDev;
1080        master->last.numValuators = pDev->last.numValuators;
1081    }
1082
1083    kbp = (deviceKeyButtonPointer *) events->event;
1084    kbp->type = type;
1085    kbp->deviceid = pDev->id;
1086    kbp->detail = 0;
1087    kbp->time = GetTimeInMillis();
1088
1089    if (num_valuators) {
1090        kbp->deviceid |= MORE_EVENTS;
1091        events++;
1092        clipValuators(pDev, first_valuator, num_valuators, valuators);
1093        events = getValuatorEvents(events, pDev, first_valuator,
1094                                   num_valuators, valuators);
1095    }
1096
1097    return num_events;
1098}
1099
1100/**
1101 * Synthesize a single motion event for the core pointer.
1102 *
1103 * Used in cursor functions, e.g. when cursor confinement changes, and we need
1104 * to shift the pointer to get it inside the new bounds.
1105 */
1106void
1107PostSyntheticMotion(DeviceIntPtr pDev,
1108                    int x,
1109                    int y,
1110                    int screen,
1111                    unsigned long time)
1112{
1113    xEvent xE;
1114
1115#ifdef PANORAMIX
1116    /* Translate back to the sprite screen since processInputProc
1117       will translate from sprite screen to screen 0 upon reentry
1118       to the DIX layer. */
1119    if (!noPanoramiXExtension) {
1120        x += panoramiXdataPtr[0].x - panoramiXdataPtr[screen].x;
1121        y += panoramiXdataPtr[0].y - panoramiXdataPtr[screen].y;
1122    }
1123#endif
1124
1125    memset(&xE, 0, sizeof(xEvent));
1126    xE.u.u.type = MotionNotify;
1127    xE.u.keyButtonPointer.rootX = x;
1128    xE.u.keyButtonPointer.rootY = y;
1129    xE.u.keyButtonPointer.time = time;
1130
1131    (*pDev->public.processInputProc)(&xE, pDev, 1);
1132}
1133