getevents.c revision 7e31ba66
1/*
2 * Copyright © 2006 Nokia Corporation
3 * Copyright © 2006-2007 Daniel Stone
4 * Copyright © 2008 Red Hat, Inc.
5 * Copyright © 2011 The Chromium Authors
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors: Daniel Stone <daniel@fooishbar.org>
27 *          Peter Hutterer <peter.hutterer@who-t.net>
28 */
29
30#ifdef HAVE_DIX_CONFIG_H
31#include <dix-config.h>
32#endif
33
34#include <X11/X.h>
35#include <X11/keysym.h>
36#include <X11/Xproto.h>
37#include <math.h>
38#include <limits.h>
39
40#include "misc.h"
41#include "resource.h"
42#include "inputstr.h"
43#include "scrnintstr.h"
44#include "cursorstr.h"
45#include "dixstruct.h"
46#include "globals.h"
47#include "dixevents.h"
48#include "mipointer.h"
49#include "eventstr.h"
50#include "eventconvert.h"
51#include "inpututils.h"
52#include "mi.h"
53#include "windowstr.h"
54
55#include <X11/extensions/XKBproto.h>
56#include "xkbsrv.h"
57
58#ifdef PANORAMIX
59#include "panoramiX.h"
60#include "panoramiXsrv.h"
61#endif
62
63#include <X11/extensions/XI.h>
64#include <X11/extensions/XI2.h>
65#include <X11/extensions/XIproto.h>
66#include <pixman.h>
67#include "exglobals.h"
68#include "exevents.h"
69#include "extnsionst.h"
70#include "listdev.h"            /* for sizing up DeviceClassesChangedEvent */
71#include "probes.h"
72
73/* Number of motion history events to store. */
74#define MOTION_HISTORY_SIZE 256
75
76/**
77 * InputEventList is the storage for input events generated by
78 * QueuePointerEvents, QueueKeyboardEvents, and QueueProximityEvents.
79 * This list is allocated on startup by the DIX.
80 */
81InternalEvent *InputEventList = NULL;
82
83/**
84 * Pick some arbitrary size for Xi motion history.
85 */
86int
87GetMotionHistorySize(void)
88{
89    return MOTION_HISTORY_SIZE;
90}
91
92void
93set_button_down(DeviceIntPtr pDev, int button, int type)
94{
95    if (type == BUTTON_PROCESSED)
96        SetBit(pDev->button->down, button);
97    else
98        SetBit(pDev->button->postdown, button);
99}
100
101void
102set_button_up(DeviceIntPtr pDev, int button, int type)
103{
104    if (type == BUTTON_PROCESSED)
105        ClearBit(pDev->button->down, button);
106    else
107        ClearBit(pDev->button->postdown, button);
108}
109
110Bool
111button_is_down(DeviceIntPtr pDev, int button, int type)
112{
113    Bool ret = FALSE;
114
115    if (type & BUTTON_PROCESSED)
116        ret = ret || BitIsOn(pDev->button->down, button);
117    if (type & BUTTON_POSTED)
118        ret = ret || BitIsOn(pDev->button->postdown, button);
119
120    return ret;
121}
122
123void
124set_key_down(DeviceIntPtr pDev, int key_code, int type)
125{
126    if (type == KEY_PROCESSED)
127        SetBit(pDev->key->down, key_code);
128    else
129        SetBit(pDev->key->postdown, key_code);
130}
131
132void
133set_key_up(DeviceIntPtr pDev, int key_code, int type)
134{
135    if (type == KEY_PROCESSED)
136        ClearBit(pDev->key->down, key_code);
137    else
138        ClearBit(pDev->key->postdown, key_code);
139}
140
141Bool
142key_is_down(DeviceIntPtr pDev, int key_code, int type)
143{
144    Bool ret = FALSE;
145
146    if (type & KEY_PROCESSED)
147        ret = ret || BitIsOn(pDev->key->down, key_code);
148    if (type & KEY_POSTED)
149        ret = ret || BitIsOn(pDev->key->postdown, key_code);
150
151    return ret;
152}
153
154static Bool
155key_autorepeats(DeviceIntPtr pDev, int key_code)
156{
157    return ! !(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
158               (1 << (key_code & 7)));
159}
160
161static void
162init_touch_ownership(DeviceIntPtr dev, TouchOwnershipEvent *event, Time ms)
163{
164    memset(event, 0, sizeof(TouchOwnershipEvent));
165    event->header = ET_Internal;
166    event->type = ET_TouchOwnership;
167    event->length = sizeof(TouchOwnershipEvent);
168    event->time = ms;
169    event->deviceid = dev->id;
170}
171
172static void
173init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
174{
175    memset(event, 0, sizeof(RawDeviceEvent));
176    event->header = ET_Internal;
177    event->length = sizeof(RawDeviceEvent);
178    switch (type) {
179    case MotionNotify:
180        event->type = ET_RawMotion;
181        break;
182    case ButtonPress:
183        event->type = ET_RawButtonPress;
184        break;
185    case ButtonRelease:
186        event->type = ET_RawButtonRelease;
187        break;
188    case KeyPress:
189        event->type = ET_RawKeyPress;
190        break;
191    case KeyRelease:
192        event->type = ET_RawKeyRelease;
193        break;
194    case XI_TouchBegin:
195        event->type = ET_RawTouchBegin;
196        break;
197    case XI_TouchUpdate:
198        event->type = ET_RawTouchUpdate;
199        break;
200    case XI_TouchEnd:
201        event->type = ET_RawTouchEnd;
202        break;
203    }
204    event->time = ms;
205    event->deviceid = dev->id;
206    event->sourceid = dev->id;
207    event->detail.button = detail;
208}
209
210static void
211set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask,
212                  BOOL use_unaccel, double *data)
213{
214    int i;
215
216    use_unaccel = use_unaccel && valuator_mask_has_unaccelerated(mask);
217
218    for (i = 0; i < valuator_mask_size(mask); i++) {
219        if (valuator_mask_isset(mask, i)) {
220            double v;
221
222            SetBit(event->valuators.mask, i);
223
224            if (use_unaccel)
225                v = valuator_mask_get_unaccelerated(mask, i);
226            else
227                v = valuator_mask_get_double(mask, i);
228
229            data[i] = v;
230        }
231    }
232}
233
234static void
235set_valuators(DeviceIntPtr dev, DeviceEvent *event, ValuatorMask *mask)
236{
237    int i;
238
239    /* Set the data to the previous value for unset absolute axes. The values
240     * may be used when sent as part of an XI 1.x valuator event. */
241    for (i = 0; i < valuator_mask_size(mask); i++) {
242        if (valuator_mask_isset(mask, i)) {
243            SetBit(event->valuators.mask, i);
244            if (valuator_get_mode(dev, i) == Absolute)
245                SetBit(event->valuators.mode, i);
246            event->valuators.data[i] = valuator_mask_get_double(mask, i);
247        }
248        else
249            event->valuators.data[i] = dev->valuator->axisVal[i];
250    }
251}
252
253void
254CreateClassesChangedEvent(InternalEvent *event,
255                          DeviceIntPtr master, DeviceIntPtr slave, int flags)
256{
257    int i;
258    DeviceChangedEvent *dce;
259    CARD32 ms = GetTimeInMillis();
260
261    dce = &event->changed_event;
262    memset(dce, 0, sizeof(DeviceChangedEvent));
263    dce->deviceid = slave->id;
264    dce->masterid = master ? master->id : 0;
265    dce->header = ET_Internal;
266    dce->length = sizeof(DeviceChangedEvent);
267    dce->type = ET_DeviceChanged;
268    dce->time = ms;
269    dce->flags = flags;
270    dce->sourceid = slave->id;
271
272    if (slave->button) {
273        dce->buttons.num_buttons = slave->button->numButtons;
274        for (i = 0; i < dce->buttons.num_buttons; i++)
275            dce->buttons.names[i] = slave->button->labels[i];
276    }
277    if (slave->valuator) {
278        dce->num_valuators = slave->valuator->numAxes;
279        for (i = 0; i < dce->num_valuators; i++) {
280            dce->valuators[i].min = slave->valuator->axes[i].min_value;
281            dce->valuators[i].max = slave->valuator->axes[i].max_value;
282            dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
283            dce->valuators[i].mode = slave->valuator->axes[i].mode;
284            dce->valuators[i].name = slave->valuator->axes[i].label;
285            dce->valuators[i].scroll = slave->valuator->axes[i].scroll;
286            dce->valuators[i].value = slave->valuator->axisVal[i];
287        }
288    }
289    if (slave->key) {
290        dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
291        dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
292    }
293}
294
295/**
296 * Rescale the coord between the two axis ranges.
297 */
298static double
299rescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to,
300                    double defmin, double defmax)
301{
302    double fmin = defmin, fmax = defmax;
303    double tmin = defmin, tmax = defmax;
304
305    if (from && from->min_value < from->max_value) {
306        fmin = from->min_value;
307        fmax = from->max_value + 1;
308    }
309    if (to && to->min_value < to->max_value) {
310        tmin = to->min_value;
311        tmax = to->max_value + 1;
312    }
313
314    if (fmin == tmin && fmax == tmax)
315        return coord;
316
317    if (fmax == fmin)           /* avoid division by 0 */
318        return 0.0;
319
320    return (coord - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
321}
322
323/**
324 * Update all coordinates when changing to a different SD
325 * to ensure that relative reporting will work as expected
326 * without loss of precision.
327 *
328 * pDev->last.valuators will be in absolute device coordinates after this
329 * function.
330 */
331static void
332updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
333{
334    int i;
335    DeviceIntPtr lastSlave;
336
337    /* master->last.valuators[0]/[1] is in desktop-wide coords and the actual
338     * position of the pointer */
339    pDev->last.valuators[0] = master->last.valuators[0];
340    pDev->last.valuators[1] = master->last.valuators[1];
341
342    if (!pDev->valuator)
343        return;
344
345    /* scale back to device coordinates */
346    if (pDev->valuator->numAxes > 0) {
347        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0],
348                                                      NULL,
349                                                      pDev->valuator->axes + 0,
350                                                      screenInfo.x,
351                                                      screenInfo.width);
352    }
353    if (pDev->valuator->numAxes > 1) {
354        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1],
355                                                      NULL,
356                                                      pDev->valuator->axes + 1,
357                                                      screenInfo.y,
358                                                      screenInfo.height);
359    }
360
361    /* calculate the other axis as well based on info from the old
362     * slave-device. If the old slave had less axes than this one,
363     * last.valuators is reset to 0.
364     */
365    if ((lastSlave = master->last.slave) && lastSlave->valuator) {
366        for (i = 2; i < pDev->valuator->numAxes; i++) {
367            if (i >= lastSlave->valuator->numAxes) {
368                pDev->last.valuators[i] = 0;
369                valuator_mask_set_double(pDev->last.scroll, i, 0);
370            }
371            else {
372                double val = pDev->last.valuators[i];
373
374                val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i,
375                                          pDev->valuator->axes + i, 0, 0);
376                pDev->last.valuators[i] = val;
377                valuator_mask_set_double(pDev->last.scroll, i, val);
378            }
379        }
380    }
381
382}
383
384/**
385 * Allocate the motion history buffer.
386 */
387void
388AllocateMotionHistory(DeviceIntPtr pDev)
389{
390    int size;
391
392    free(pDev->valuator->motion);
393
394    if (pDev->valuator->numMotionEvents < 1)
395        return;
396
397    /* An MD must have a motion history size large enough to keep all
398     * potential valuators, plus the respective range of the valuators.
399     * 3 * INT32 for (min_val, max_val, curr_val))
400     */
401    if (IsMaster(pDev))
402        size = sizeof(INT32) * 3 * MAX_VALUATORS;
403    else {
404        ValuatorClassPtr v = pDev->valuator;
405        int numAxes;
406
407        /* XI1 doesn't understand mixed mode devices */
408        for (numAxes = 0; numAxes < v->numAxes; numAxes++)
409            if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0))
410                break;
411        size = sizeof(INT32) * numAxes;
412    }
413
414    size += sizeof(Time);
415
416    pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size);
417    pDev->valuator->first_motion = 0;
418    pDev->valuator->last_motion = 0;
419    if (!pDev->valuator->motion)
420        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
421               pDev->name, size * pDev->valuator->numMotionEvents);
422}
423
424/**
425 * Dump the motion history between start and stop into the supplied buffer.
426 * Only records the event for a given screen in theory, but in practice, we
427 * sort of ignore this.
428 *
429 * If core is set, we only generate x/y, in INT16, scaled to screen coords.
430 */
431int
432GetMotionHistory(DeviceIntPtr pDev, xTimecoord ** buff, unsigned long start,
433                 unsigned long stop, ScreenPtr pScreen, BOOL core)
434{
435    char *ibuff = NULL, *obuff;
436    int i = 0, ret = 0;
437    int j, coord;
438    Time current;
439
440    /* The size of a single motion event. */
441    int size;
442    AxisInfo from, *to;         /* for scaling */
443    INT32 *ocbuf, *icbuf;       /* pointer to coordinates for copying */
444    INT16 *corebuf;
445    AxisInfo core_axis = { 0 };
446
447    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
448        return 0;
449
450    if (core && !pScreen)
451        return 0;
452
453    if (IsMaster(pDev))
454        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
455    else
456        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
457
458    *buff = malloc(size * pDev->valuator->numMotionEvents);
459    if (!(*buff))
460        return 0;
461    obuff = (char *) *buff;
462
463    for (i = pDev->valuator->first_motion;
464         i != pDev->valuator->last_motion;
465         i = (i + 1) % pDev->valuator->numMotionEvents) {
466        /* We index the input buffer by which element we're accessing, which
467         * is not monotonic, and the output buffer by how many events we've
468         * written so far. */
469        ibuff = (char *) pDev->valuator->motion + (i * size);
470        memcpy(&current, ibuff, sizeof(Time));
471
472        if (current > stop) {
473            return ret;
474        }
475        else if (current >= start) {
476            if (core) {
477                memcpy(obuff, ibuff, sizeof(Time));     /* copy timestamp */
478
479                icbuf = (INT32 *) (ibuff + sizeof(Time));
480                corebuf = (INT16 *) (obuff + sizeof(Time));
481
482                /* fetch x coordinate + range */
483                memcpy(&from.min_value, icbuf++, sizeof(INT32));
484                memcpy(&from.max_value, icbuf++, sizeof(INT32));
485                memcpy(&coord, icbuf++, sizeof(INT32));
486
487                /* scale to screen coords */
488                to = &core_axis;
489                to->max_value = pScreen->width;
490                coord =
491                    rescaleValuatorAxis(coord, &from, to, 0, pScreen->width);
492
493                memcpy(corebuf, &coord, sizeof(INT16));
494                corebuf++;
495
496                /* fetch y coordinate + range */
497                memcpy(&from.min_value, icbuf++, sizeof(INT32));
498                memcpy(&from.max_value, icbuf++, sizeof(INT32));
499                memcpy(&coord, icbuf++, sizeof(INT32));
500
501                to->max_value = pScreen->height;
502                coord =
503                    rescaleValuatorAxis(coord, &from, to, 0, pScreen->height);
504                memcpy(corebuf, &coord, sizeof(INT16));
505
506            }
507            else if (IsMaster(pDev)) {
508                memcpy(obuff, ibuff, sizeof(Time));     /* copy timestamp */
509
510                ocbuf = (INT32 *) (obuff + sizeof(Time));
511                icbuf = (INT32 *) (ibuff + sizeof(Time));
512                for (j = 0; j < MAX_VALUATORS; j++) {
513                    if (j >= pDev->valuator->numAxes)
514                        break;
515
516                    /* fetch min/max/coordinate */
517                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
518                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
519                    memcpy(&coord, icbuf++, sizeof(INT32));
520
521                    to = (j <
522                          pDev->valuator->numAxes) ? &pDev->valuator->
523                        axes[j] : NULL;
524
525                    /* x/y scaled to screen if no range is present */
526                    if (j == 0 && (from.max_value < from.min_value))
527                        from.max_value = pScreen->width;
528                    else if (j == 1 && (from.max_value < from.min_value))
529                        from.max_value = pScreen->height;
530
531                    /* scale from stored range into current range */
532                    coord = rescaleValuatorAxis(coord, &from, to, 0, 0);
533                    memcpy(ocbuf, &coord, sizeof(INT32));
534                    ocbuf++;
535                }
536            }
537            else
538                memcpy(obuff, ibuff, size);
539
540            /* don't advance by size here. size may be different to the
541             * actually written size if the MD has less valuators than MAX */
542            if (core)
543                obuff += sizeof(INT32) + sizeof(Time);
544            else
545                obuff +=
546                    (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
547            ret++;
548        }
549    }
550
551    return ret;
552}
553
554/**
555 * Update the motion history for a specific device, with the list of
556 * valuators.
557 *
558 * Layout of the history buffer:
559 *   for SDs: [time] [val0] [val1] ... [valn]
560 *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
561 *
562 * For events that have some valuators unset:
563 *      min_val == max_val == val == 0.
564 */
565static void
566updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
567                    double *valuators)
568{
569    char *buff = (char *) pDev->valuator->motion;
570    ValuatorClassPtr v;
571    int i;
572
573    if (!pDev->valuator->numMotionEvents)
574        return;
575
576    v = pDev->valuator;
577    if (IsMaster(pDev)) {
578        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
579            v->last_motion;
580
581        memcpy(buff, &ms, sizeof(Time));
582        buff += sizeof(Time);
583
584        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
585
586        for (i = 0; i < v->numAxes; i++) {
587            int val;
588
589            /* XI1 doesn't support mixed mode devices */
590            if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0))
591                break;
592            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) {
593                buff += 3 * sizeof(INT32);
594                continue;
595            }
596            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
597            buff += sizeof(INT32);
598            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
599            buff += sizeof(INT32);
600            val = valuators[i];
601            memcpy(buff, &val, sizeof(INT32));
602            buff += sizeof(INT32);
603        }
604    }
605    else {
606
607        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
608            pDev->valuator->last_motion;
609
610        memcpy(buff, &ms, sizeof(Time));
611        buff += sizeof(Time);
612
613        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
614
615        for (i = 0; i < MAX_VALUATORS; i++) {
616            int val;
617
618            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) {
619                buff += sizeof(INT32);
620                continue;
621            }
622            val = valuators[i];
623            memcpy(buff, &val, sizeof(INT32));
624            buff += sizeof(INT32);
625        }
626    }
627
628    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
629        pDev->valuator->numMotionEvents;
630    /* If we're wrapping around, just keep the circular buffer going. */
631    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
632        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
633            pDev->valuator->numMotionEvents;
634
635    return;
636}
637
638/**
639 * Returns the maximum number of events GetKeyboardEvents
640 * and GetPointerEvents will ever return.
641 *
642 * This MUST be absolutely constant, from init until exit.
643 */
644int
645GetMaximumEventsNum(void)
646{
647    /* One raw event
648     * One device event
649     * One possible device changed event
650     * Lots of possible separate button scroll events (horiz + vert)
651     * Lots of possible separate raw button scroll events (horiz + vert)
652     */
653    return 100;
654}
655
656/**
657 * Clip an axis to its bounds, which are declared in the call to
658 * InitValuatorAxisClassStruct.
659 */
660static void
661clipAxis(DeviceIntPtr pDev, int axisNum, double *val)
662{
663    AxisInfoPtr axis;
664
665    if (axisNum >= pDev->valuator->numAxes)
666        return;
667
668    axis = pDev->valuator->axes + axisNum;
669
670    /* If a value range is defined, clip. If not, do nothing */
671    if (axis->max_value <= axis->min_value)
672        return;
673
674    if (*val < axis->min_value)
675        *val = axis->min_value;
676    if (*val > axis->max_value)
677        *val = axis->max_value;
678}
679
680/**
681 * Clip every axis in the list of valuators to its bounds.
682 */
683static void
684clipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
685{
686    int i;
687
688    for (i = 0; i < valuator_mask_size(mask); i++)
689        if (valuator_mask_isset(mask, i)) {
690            double val = valuator_mask_get_double(mask, i);
691
692            clipAxis(pDev, i, &val);
693            valuator_mask_set_double(mask, i, val);
694        }
695}
696
697/**
698 * Create the DCCE event (does not update the master's device state yet, this
699 * is done in the event processing).
700 * Pull in the coordinates from the MD if necessary.
701 *
702 * @param events Pointer to a pre-allocated event array.
703 * @param dev The slave device that generated an event.
704 * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
705 * @param num_events The current number of events, returns the number of
706 *        events if a DCCE was generated.
707 * @return The updated @events pointer.
708 */
709InternalEvent *
710UpdateFromMaster(InternalEvent *events, DeviceIntPtr dev, int type,
711                 int *num_events)
712{
713    DeviceIntPtr master;
714
715    master =
716        GetMaster(dev,
717                  (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER :
718                  MASTER_KEYBOARD);
719
720    if (master && master->last.slave != dev) {
721        CreateClassesChangedEvent(events, master, dev,
722                                  type | DEVCHANGE_SLAVE_SWITCH);
723        if (IsPointerDevice(master)) {
724            updateSlaveDeviceCoords(master, dev);
725            master->last.numValuators = dev->last.numValuators;
726        }
727        master->last.slave = dev;
728        (*num_events)++;
729        events++;
730    }
731    return events;
732}
733
734/**
735 * Move the device's pointer to the position given in the valuators.
736 *
737 * @param dev The device whose pointer is to be moved.
738 * @param mask Valuator data for this event.
739 */
740static void
741clipAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
742{
743    int i;
744
745    for (i = 0; i < valuator_mask_size(mask); i++) {
746        double val;
747
748        if (!valuator_mask_isset(mask, i))
749            continue;
750        val = valuator_mask_get_double(mask, i);
751        clipAxis(dev, i, &val);
752        valuator_mask_set_double(mask, i, val);
753    }
754}
755
756static void
757add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, double value)
758{
759    double v;
760
761    if (!valuator_mask_fetch_double(mask, valuator, &v))
762        return;
763
764    /* protect against scrolling overflow. INT_MAX for double, because
765     * we'll eventually write this as 32.32 fixed point */
766    if ((value > 0 && v > INT_MAX - value) || (value < 0 && v < INT_MIN - value)) {
767        v = 0;
768
769        /* reset last.scroll to avoid a button storm */
770        valuator_mask_set_double(dev->last.scroll, valuator, 0);
771    }
772    else
773        v += value;
774
775    valuator_mask_set_double(mask, valuator, v);
776}
777
778
779static void
780scale_for_device_resolution(DeviceIntPtr dev, ValuatorMask *mask)
781{
782    double y;
783    ValuatorClassPtr v = dev->valuator;
784    int xrange = v->axes[0].max_value - v->axes[0].min_value + 1;
785    int yrange = v->axes[1].max_value - v->axes[1].min_value + 1;
786
787    double screen_ratio = 1.0 * screenInfo.width/screenInfo.height;
788    double device_ratio = 1.0 * xrange/yrange;
789    double resolution_ratio = 1.0;
790    double ratio;
791
792    if (!valuator_mask_fetch_double(mask, 1, &y))
793        return;
794
795    if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0)
796        resolution_ratio = 1.0 * v->axes[0].resolution/v->axes[1].resolution;
797
798    ratio = device_ratio/resolution_ratio/screen_ratio;
799    valuator_mask_set_double(mask, 1, y / ratio);
800}
801
802/**
803 * Move the device's pointer by the values given in @valuators.
804 *
805 * @param dev The device whose pointer is to be moved.
806 * @param[in,out] mask Valuator data for this event, modified in-place.
807 */
808static void
809moveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask)
810{
811    int i;
812    Bool clip_xy = IsMaster(dev) || !IsFloating(dev);
813    ValuatorClassPtr v = dev->valuator;
814
815    /* for abs devices in relative mode, we've just scaled wrong, since we
816       mapped the device's shape into the screen shape. Undo this. */
817    if ((flags & POINTER_ABSOLUTE) == 0 && v && v->numAxes > 1 &&
818        v->axes[0].min_value < v->axes[0].max_value &&
819        v->axes[1].min_value < v->axes[1].max_value) {
820        scale_for_device_resolution(dev, mask);
821    }
822
823    /* calc other axes, clip, drop back into valuators */
824    for (i = 0; i < valuator_mask_size(mask); i++) {
825        double val = dev->last.valuators[i];
826
827        if (!valuator_mask_isset(mask, i))
828            continue;
829
830        add_to_scroll_valuator(dev, mask, i, val);
831
832        /* x & y need to go over the limits to cross screens if the SD
833         * isn't currently attached; otherwise, clip to screen bounds. */
834        if (valuator_get_mode(dev, i) == Absolute &&
835            ((i != 0 && i != 1) || clip_xy)) {
836            val = valuator_mask_get_double(mask, i);
837            clipAxis(dev, i, &val);
838            valuator_mask_set_double(mask, i, val);
839        }
840    }
841}
842
843/**
844 * Accelerate the data in valuators based on the device's acceleration scheme.
845 *
846 * @param dev The device which's pointer is to be moved.
847 * @param valuators Valuator mask
848 * @param ms Current time.
849 */
850static void
851accelPointer(DeviceIntPtr dev, ValuatorMask *valuators, CARD32 ms)
852{
853    if (dev->valuator->accelScheme.AccelSchemeProc)
854        dev->valuator->accelScheme.AccelSchemeProc(dev, valuators, ms);
855}
856
857/**
858 * Scale from absolute screen coordinates to absolute coordinates in the
859 * device's coordinate range.
860 *
861 * @param dev The device to scale for.
862 * @param[in, out] mask The mask in desktop/screen coordinates, modified in place
863 * to contain device coordinate range.
864 * @param flags If POINTER_SCREEN is set, mask is in per-screen coordinates.
865 *              Otherwise, mask is in desktop coords.
866 */
867static void
868scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask, int flags)
869{
870    double scaled;
871    ScreenPtr scr = miPointerGetScreen(dev);
872
873    if (valuator_mask_isset(mask, 0)) {
874        scaled = valuator_mask_get_double(mask, 0);
875        if (flags & POINTER_SCREEN)
876            scaled += scr->x;
877        scaled = rescaleValuatorAxis(scaled,
878                                     NULL, dev->valuator->axes + 0,
879                                     screenInfo.x, screenInfo.width);
880        valuator_mask_set_double(mask, 0, scaled);
881    }
882    if (valuator_mask_isset(mask, 1)) {
883        scaled = valuator_mask_get_double(mask, 1);
884        if (flags & POINTER_SCREEN)
885            scaled += scr->y;
886        scaled = rescaleValuatorAxis(scaled,
887                                     NULL, dev->valuator->axes + 1,
888                                     screenInfo.y, screenInfo.height);
889        valuator_mask_set_double(mask, 1, scaled);
890    }
891}
892
893/**
894 * Scale from (absolute) device to screen coordinates here,
895 *
896 * The coordinates provided are always absolute. see fill_pointer_events for
897 * information on coordinate systems.
898 *
899 * @param dev The device to be moved.
900 * @param mask Mask of axis values for this event
901 * @param[out] devx x desktop-wide coordinate in device coordinate system
902 * @param[out] devy y desktop-wide coordinate in device coordinate system
903 * @param[out] screenx x coordinate in desktop coordinate system
904 * @param[out] screeny y coordinate in desktop coordinate system
905 */
906static ScreenPtr
907scale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask,
908                 double *devx, double *devy, double *screenx, double *screeny)
909{
910    ScreenPtr scr = miPointerGetScreen(dev);
911    double x, y;
912
913    BUG_WARN(dev->valuator && dev->valuator->numAxes < 2);
914    if (!dev->valuator || dev->valuator->numAxes < 2) {
915        /* if we have no axes, last.valuators must be in screen coords
916         * anyway */
917        *devx = *screenx = dev->last.valuators[0];
918        *devy = *screeny = dev->last.valuators[1];
919        return scr;
920    }
921
922    if (valuator_mask_isset(mask, 0))
923        x = valuator_mask_get_double(mask, 0);
924    else
925        x = dev->last.valuators[0];
926    if (valuator_mask_isset(mask, 1))
927        y = valuator_mask_get_double(mask, 1);
928    else
929        y = dev->last.valuators[1];
930
931    /* scale x&y to desktop coordinates */
932    *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
933                                   screenInfo.x, screenInfo.width);
934    *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
935                                   screenInfo.y, screenInfo.height);
936
937    *devx = x;
938    *devy = y;
939
940    return scr;
941}
942
943/**
944 * If we have HW cursors, this actually moves the visible sprite. If not, we
945 * just do all the screen crossing, etc.
946 *
947 * We use the screen coordinates here, call miPointerSetPosition() and then
948 * scale back into device coordinates (if needed). miPSP will change x/y if
949 * the screen was crossed.
950 *
951 * The coordinates provided are always absolute. The parameter mode
952 * specifies whether it was relative or absolute movement that landed us at
953 * those coordinates. see fill_pointer_events for information on coordinate
954 * systems.
955 *
956 * @param dev The device to be moved.
957 * @param mode Movement mode (Absolute or Relative)
958 * @param[out] mask Mask of axis values for this event, returns the
959 * per-screen device coordinates after confinement
960 * @param[in,out] devx x desktop-wide coordinate in device coordinate system
961 * @param[in,out] devy y desktop-wide coordinate in device coordinate system
962 * @param[in,out] screenx x coordinate in desktop coordinate system
963 * @param[in,out] screeny y coordinate in desktop coordinate system
964 * @param[out] nevents Number of barrier events added to events
965 * @param[in,out] events List of events barrier events are added to
966 */
967static ScreenPtr
968positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
969               double *devx, double *devy, double *screenx, double *screeny,
970               int *nevents, InternalEvent* events)
971{
972    ScreenPtr scr = miPointerGetScreen(dev);
973    double tmpx, tmpy;
974
975    if (!dev->valuator || dev->valuator->numAxes < 2)
976        return scr;
977
978    tmpx = *screenx;
979    tmpy = *screeny;
980
981    /* miPointerSetPosition takes care of crossing screens for us, as well as
982     * clipping to the current screen. Coordinates returned are in desktop
983     * coord system */
984    scr = miPointerSetPosition(dev, mode, screenx, screeny, nevents, events);
985
986    /* If we were constrained, rescale x/y from the screen coordinates so
987     * the device valuators reflect the correct position. For screen
988     * crossing this doesn't matter much, the coords would be 0 or max.
989     */
990    if (tmpx != *screenx)
991        *devx = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
992                                    screenInfo.x, screenInfo.width);
993
994    if (tmpy != *screeny)
995        *devy = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
996                                    screenInfo.y, screenInfo.height);
997
998    /* Recalculate the per-screen device coordinates */
999    if (valuator_mask_isset(mask, 0)) {
1000        double x;
1001
1002        x = rescaleValuatorAxis(*screenx - scr->x, NULL,
1003                                dev->valuator->axes + 0, 0, scr->width);
1004        valuator_mask_set_double(mask, 0, x);
1005    }
1006    if (valuator_mask_isset(mask, 1)) {
1007        double y;
1008
1009        y = rescaleValuatorAxis(*screeny - scr->y, NULL,
1010                                dev->valuator->axes + 1, 0, scr->height);
1011        valuator_mask_set_double(mask, 1, y);
1012    }
1013
1014    return scr;
1015}
1016
1017/**
1018 * Update the motion history for the device and (if appropriate) for its
1019 * master device.
1020 * @param dev Slave device to update.
1021 * @param mask Bit mask of valid valuators to append to history.
1022 * @param num Total number of valuators to append to history.
1023 * @param ms Current time
1024 */
1025static void
1026updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
1027{
1028    if (!dev->valuator)
1029        return;
1030
1031    updateMotionHistory(dev, ms, mask, dev->last.valuators);
1032    if (!IsMaster(dev) && !IsFloating(dev)) {
1033        DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
1034
1035        updateMotionHistory(master, ms, mask, dev->last.valuators);
1036    }
1037}
1038
1039static void
1040queueEventList(DeviceIntPtr device, InternalEvent *events, int nevents)
1041{
1042    int i;
1043
1044    for (i = 0; i < nevents; i++)
1045        mieqEnqueue(device, &events[i]);
1046}
1047
1048static void
1049event_set_root_coordinates(DeviceEvent *event, double x, double y)
1050{
1051    event->root_x = trunc(x);
1052    event->root_y = trunc(y);
1053    event->root_x_frac = x - trunc(x);
1054    event->root_y_frac = y - trunc(y);
1055}
1056
1057/**
1058 * Generate internal events representing this keyboard event and enqueue
1059 * them on the event queue.
1060 *
1061 * This function is not reentrant. Disable signals before calling.
1062 *
1063 * @param device The device to generate the event for
1064 * @param type Event type, one of KeyPress or KeyRelease
1065 * @param keycode Key code of the pressed/released key
1066 *
1067 */
1068void
1069QueueKeyboardEvents(DeviceIntPtr device, int type,
1070                    int keycode)
1071{
1072    int nevents;
1073
1074    nevents = GetKeyboardEvents(InputEventList, device, type, keycode);
1075    queueEventList(device, InputEventList, nevents);
1076}
1077
1078/**
1079 * Returns a set of InternalEvents for KeyPress/KeyRelease, optionally
1080 * also with valuator events.
1081 *
1082 * The DDX is responsible for allocating the event list in the first
1083 * place via InitEventList(), and for freeing it.
1084 *
1085 * @return the number of events written into events.
1086 */
1087int
1088GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
1089                  int key_code)
1090{
1091    int num_events = 0;
1092    CARD32 ms = 0;
1093    DeviceEvent *event;
1094    RawDeviceEvent *raw;
1095    enum DeviceEventSource source_type = EVENT_SOURCE_NORMAL;
1096
1097#if XSERVER_DTRACE
1098    if (XSERVER_INPUT_EVENT_ENABLED()) {
1099        XSERVER_INPUT_EVENT(pDev->id, type, key_code, 0, 0,
1100                            NULL, NULL);
1101    }
1102#endif
1103
1104    if (type == EnterNotify) {
1105        source_type = EVENT_SOURCE_FOCUS;
1106        type = KeyPress;
1107    } else if (type == LeaveNotify) {
1108        source_type = EVENT_SOURCE_FOCUS;
1109        type = KeyRelease;
1110    }
1111
1112    /* refuse events from disabled devices */
1113    if (!pDev->enabled)
1114        return 0;
1115
1116    if (!events || !pDev->key || !pDev->focus || !pDev->kbdfeed ||
1117        (type != KeyPress && type != KeyRelease) ||
1118        (key_code < 8 || key_code > 255))
1119        return 0;
1120
1121    num_events = 1;
1122
1123    events =
1124        UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
1125
1126    /* Handle core repeating, via press/release/press/release. */
1127    if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
1128        /* If autorepeating is disabled either globally or just for that key,
1129         * or we have a modifier, don't generate a repeat event. */
1130        if (!pDev->kbdfeed->ctrl.autoRepeat ||
1131            !key_autorepeats(pDev, key_code) ||
1132            pDev->key->xkbInfo->desc->map->modmap[key_code])
1133            return 0;
1134    }
1135
1136    ms = GetTimeInMillis();
1137
1138    if (source_type == EVENT_SOURCE_NORMAL) {
1139        raw = &events->raw_event;
1140        init_raw(pDev, raw, ms, type, key_code);
1141        events++;
1142        num_events++;
1143    }
1144
1145    event = &events->device_event;
1146    init_device_event(event, pDev, ms, source_type);
1147    event->detail.key = key_code;
1148
1149    if (type == KeyPress) {
1150        event->type = ET_KeyPress;
1151        set_key_down(pDev, key_code, KEY_POSTED);
1152    }
1153    else if (type == KeyRelease) {
1154        event->type = ET_KeyRelease;
1155        set_key_up(pDev, key_code, KEY_POSTED);
1156    }
1157
1158    return num_events;
1159}
1160
1161/**
1162 * Initialize an event array large enough for num_events arrays.
1163 * This event list is to be passed into GetPointerEvents() and
1164 * GetKeyboardEvents().
1165 *
1166 * @param num_events Number of elements in list.
1167 */
1168InternalEvent *
1169InitEventList(int num_events)
1170{
1171    InternalEvent *events = calloc(num_events, sizeof(InternalEvent));
1172
1173    return events;
1174}
1175
1176/**
1177 * Free an event list.
1178 *
1179 * @param list The list to be freed.
1180 * @param num_events Number of elements in list.
1181 */
1182void
1183FreeEventList(InternalEvent *list, int num_events)
1184{
1185    free(list);
1186}
1187
1188/**
1189 * Transform vector x/y according to matrix m and drop the rounded coords
1190 * back into x/y.
1191 */
1192static void
1193transform(struct pixman_f_transform *m, double *x, double *y)
1194{
1195    struct pixman_f_vector p = {.v = {*x, *y, 1} };
1196    pixman_f_transform_point(m, &p);
1197
1198    *x = p.v[0];
1199    *y = p.v[1];
1200}
1201
1202static void
1203transformRelative(DeviceIntPtr dev, ValuatorMask *mask)
1204{
1205    double x = 0, y = 0;
1206
1207    valuator_mask_fetch_double(mask, 0, &x);
1208    valuator_mask_fetch_double(mask, 1, &y);
1209
1210    transform(&dev->relative_transform, &x, &y);
1211
1212    if (x)
1213        valuator_mask_set_double(mask, 0, x);
1214    else
1215        valuator_mask_unset(mask, 0);
1216
1217    if (y)
1218        valuator_mask_set_double(mask, 1, y);
1219    else
1220        valuator_mask_unset(mask, 1);
1221}
1222
1223/**
1224 * Apply the device's transformation matrix to the valuator mask and replace
1225 * the scaled values in mask. This transformation only applies to valuators
1226 * 0 and 1, others will be untouched.
1227 *
1228 * @param dev The device the valuators came from
1229 * @param[in,out] mask The valuator mask.
1230 */
1231static void
1232transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
1233{
1234    double x, y, ox = 0.0, oy = 0.0;
1235    int has_x, has_y;
1236
1237    has_x = valuator_mask_isset(mask, 0);
1238    has_y = valuator_mask_isset(mask, 1);
1239
1240    if (!has_x && !has_y)
1241        return;
1242
1243    if (!has_x || !has_y) {
1244        struct pixman_f_transform invert;
1245
1246        /* undo transformation from last event */
1247        ox = dev->last.valuators[0];
1248        oy = dev->last.valuators[1];
1249
1250        pixman_f_transform_invert(&invert, &dev->scale_and_transform);
1251        transform(&invert, &ox, &oy);
1252    }
1253
1254    if (has_x)
1255        ox = valuator_mask_get_double(mask, 0);
1256
1257    if (has_y)
1258        oy = valuator_mask_get_double(mask, 1);
1259
1260    x = ox;
1261    y = oy;
1262
1263    transform(&dev->scale_and_transform, &x, &y);
1264
1265    if (has_x || ox != x)
1266        valuator_mask_set_double(mask, 0, x);
1267
1268    if (has_y || oy != y)
1269        valuator_mask_set_double(mask, 1, y);
1270}
1271
1272static void
1273storeLastValuators(DeviceIntPtr dev, ValuatorMask *mask,
1274                   int xaxis, int yaxis, double devx, double devy)
1275{
1276    int i;
1277
1278    /* store desktop-wide in last.valuators */
1279    if (valuator_mask_isset(mask, xaxis))
1280        dev->last.valuators[0] = devx;
1281    if (valuator_mask_isset(mask, yaxis))
1282        dev->last.valuators[1] = devy;
1283
1284    for (i = 0; i < valuator_mask_size(mask); i++) {
1285        if (i == xaxis || i == yaxis)
1286            continue;
1287
1288        if (valuator_mask_isset(mask, i))
1289            dev->last.valuators[i] = valuator_mask_get_double(mask, i);
1290    }
1291
1292}
1293
1294/**
1295 * Generate internal events representing this pointer event and enqueue them
1296 * on the event queue.
1297 *
1298 * This function is not reentrant. Disable signals before calling.
1299 *
1300 * @param device The device to generate the event for
1301 * @param type Event type, one of ButtonPress, ButtonRelease, MotionNotify
1302 * @param buttons Button number of the buttons modified. Must be 0 for
1303 * MotionNotify
1304 * @param flags Event modification flags
1305 * @param mask Valuator mask for valuators present for this event.
1306 */
1307void
1308QueuePointerEvents(DeviceIntPtr device, int type,
1309                   int buttons, int flags, const ValuatorMask *mask)
1310{
1311    int nevents;
1312
1313    nevents =
1314        GetPointerEvents(InputEventList, device, type, buttons, flags, mask);
1315    queueEventList(device, InputEventList, nevents);
1316}
1317
1318/**
1319 * Helper function for GetPointerEvents, which only generates motion and
1320 * raw motion events for the slave device: does not update the master device.
1321 *
1322 * Should not be called by anyone other than GetPointerEvents.
1323 *
1324 * We use several different coordinate systems and need to switch between
1325 * the three in fill_pointer_events, positionSprite and
1326 * miPointerSetPosition. "desktop" refers to the width/height of all
1327 * screenInfo.screens[n]->width/height added up. "screen" is ScreenRec, not
1328 * output.
1329 *
1330 * Coordinate systems:
1331 * - relative events have a mask_in in relative coordinates, mapped to
1332 *   pixels. These events are mapped to the current position±delta.
1333 * - absolute events have a mask_in in absolute device coordinates in
1334 *   device-specific range. This range is mapped to the desktop.
1335 * - POINTER_SCREEN absolute events (x86WarpCursor) are in screen-relative
1336 *   screen coordinate range.
1337 * - rootx/rooty in events must be be relative to the current screen's
1338 *   origin (screen coordinate system)
1339 * - XI2 valuators must be relative to the current screen's origin. On
1340 *   the protocol the device min/max range maps to the current screen.
1341 *
1342 * For screen switching we need to get the desktop coordinates for each
1343 * event, then map that to the respective position on each screen and
1344 * position the cursor there.
1345 * The device's last.valuator[] stores the last position in desktop-wide
1346 * coordinates (in device range for slave devices, desktop range for master
1347 * devices).
1348 *
1349 * screen-relative device coordinates requires scaling: A device coordinate
1350 * x/y of range [n..m] that maps to positions Sx/Sy on Screen S must be
1351 * rescaled to match Sx/Sy for [n..m]. In the simplest example, x of (m/2-1)
1352 * is the last coordinate on the first screen and must be rescaled for the
1353 * event to be m. XI2 clients that do their own coordinate mapping would
1354 * otherwise interpret the position of the device elsewere to the cursor.
1355 * However, this scaling leads to losses:
1356 * if we have two ScreenRecs we scale from e.g. [0..44704]  (Wacom I4) to
1357 * [0..2048[. that gives us 2047.954 as desktop coord, or the per-screen
1358 * coordinate 1023.954. Scaling that back into the device coordinate range
1359 * gives us 44703. So off by one device unit. It's a bug, but we'll have to
1360 * live with it because with all this scaling, we just cannot win.
1361 *
1362 * @return the number of events written into events.
1363 */
1364static int
1365fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
1366                    int buttons, CARD32 ms, int flags,
1367                    const ValuatorMask *mask_in)
1368{
1369    int num_events = 1;
1370    DeviceEvent *event;
1371    RawDeviceEvent *raw = NULL;
1372    double screenx = 0.0, screeny = 0.0;        /* desktop coordinate system */
1373    double devx = 0.0, devy = 0.0;      /* desktop-wide in device coords */
1374    int sx = 0, sy = 0;                 /* for POINTER_SCREEN */
1375    ValuatorMask mask;
1376    ScreenPtr scr;
1377    int num_barrier_events = 0;
1378
1379    switch (type) {
1380    case MotionNotify:
1381        if (!pDev->valuator) {
1382            ErrorF("[dix] motion events from device %d without valuators\n",
1383                   pDev->id);
1384            return 0;
1385        }
1386        if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0)
1387            return 0;
1388        break;
1389    case ButtonPress:
1390    case ButtonRelease:
1391        if (!pDev->button || !buttons)
1392            return 0;
1393        if (mask_in && valuator_mask_size(mask_in) > 0 && !pDev->valuator) {
1394            ErrorF
1395                ("[dix] button event with valuator from device %d without valuators\n",
1396                 pDev->id);
1397            return 0;
1398        }
1399        break;
1400    default:
1401        return 0;
1402    }
1403
1404    valuator_mask_copy(&mask, mask_in);
1405
1406    if ((flags & POINTER_NORAW) == 0) {
1407        raw = &events->raw_event;
1408        events++;
1409        num_events++;
1410
1411        init_raw(pDev, raw, ms, type, buttons);
1412        set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw);
1413    }
1414
1415    valuator_mask_drop_unaccelerated(&mask);
1416
1417    /* valuators are in driver-native format (rel or abs) */
1418
1419    if (flags & POINTER_ABSOLUTE) {
1420        if (flags & (POINTER_SCREEN | POINTER_DESKTOP)) {    /* valuators are in screen/desktop coords */
1421            sx = valuator_mask_get(&mask, 0);
1422            sy = valuator_mask_get(&mask, 1);
1423            scale_from_screen(pDev, &mask, flags);
1424        }
1425
1426        transformAbsolute(pDev, &mask);
1427        clipAbsolute(pDev, &mask);
1428        if ((flags & POINTER_NORAW) == 0 && raw)
1429            set_raw_valuators(raw, &mask, FALSE, raw->valuators.data);
1430    }
1431    else {
1432        transformRelative(pDev, &mask);
1433
1434        if (flags & POINTER_ACCELERATE)
1435            accelPointer(pDev, &mask, ms);
1436        if ((flags & POINTER_NORAW) == 0 && raw)
1437            set_raw_valuators(raw, &mask, FALSE, raw->valuators.data);
1438
1439        moveRelative(pDev, flags, &mask);
1440    }
1441
1442    /* valuators are in device coordinate system in absolute coordinates */
1443    scale_to_desktop(pDev, &mask, &devx, &devy, &screenx, &screeny);
1444
1445    /* #53037 XWarpPointer's scaling back and forth between screen and
1446       device may leave us with rounding errors. End result is that the
1447       pointer doesn't end up on the pixel it should.
1448       Avoid this by forcing screenx/screeny back to what the input
1449       coordinates were.
1450     */
1451    if (flags & POINTER_SCREEN) {
1452        scr = miPointerGetScreen(pDev);
1453        screenx = sx + scr->x;
1454        screeny = sy + scr->y;
1455    }
1456
1457    scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
1458                         &mask, &devx, &devy, &screenx, &screeny,
1459                         &num_barrier_events, events);
1460    num_events += num_barrier_events;
1461    events += num_barrier_events;
1462
1463    /* screenx, screeny are in desktop coordinates,
1464       mask is in device coordinates per-screen (the event data)
1465       devx/devy is in device coordinate desktop-wide */
1466    updateHistory(pDev, &mask, ms);
1467
1468    clipValuators(pDev, &mask);
1469
1470    storeLastValuators(pDev, &mask, 0, 1, devx, devy);
1471
1472    /* Update the MD's co-ordinates, which are always in desktop space. */
1473    if (!IsMaster(pDev) && !IsFloating(pDev)) {
1474        DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER);
1475
1476        master->last.valuators[0] = screenx;
1477        master->last.valuators[1] = screeny;
1478    }
1479
1480    event = &events->device_event;
1481    init_device_event(event, pDev, ms, EVENT_SOURCE_NORMAL);
1482
1483    if (type == MotionNotify) {
1484        event->type = ET_Motion;
1485        event->detail.button = 0;
1486    }
1487    else {
1488        if (type == ButtonPress) {
1489            event->type = ET_ButtonPress;
1490            set_button_down(pDev, buttons, BUTTON_POSTED);
1491        }
1492        else if (type == ButtonRelease) {
1493            event->type = ET_ButtonRelease;
1494            set_button_up(pDev, buttons, BUTTON_POSTED);
1495        }
1496        event->detail.button = buttons;
1497    }
1498
1499    /* root_x and root_y must be in per-screen co-ordinates */
1500    event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
1501
1502    if (flags & POINTER_EMULATED) {
1503        if (raw)
1504            raw->flags = XIPointerEmulated;
1505        event->flags = XIPointerEmulated;
1506    }
1507
1508    set_valuators(pDev, event, &mask);
1509
1510    return num_events;
1511}
1512
1513/**
1514 * Generate events for each scroll axis that changed between before/after
1515 * for the device.
1516 *
1517 * @param events The pointer to the event list to fill the events
1518 * @param dev The device to generate the events for
1519 * @param type The real type of the event
1520 * @param axis The axis number to generate events for
1521 * @param mask State before this event in absolute coords
1522 * @param[in,out] last Last scroll state posted in absolute coords (modified
1523 * in-place)
1524 * @param ms Current time in ms
1525 * @param max_events Max number of events to be generated
1526 * @return The number of events generated
1527 */
1528static int
1529emulate_scroll_button_events(InternalEvent *events,
1530                             DeviceIntPtr dev,
1531                             int type,
1532                             int axis,
1533                             const ValuatorMask *mask,
1534                             ValuatorMask *last, CARD32 ms, int max_events)
1535{
1536    AxisInfoPtr ax;
1537    double delta;
1538    double incr;
1539    int num_events = 0;
1540    double total;
1541    int b;
1542    int flags = 0;
1543
1544    if (dev->valuator->axes[axis].scroll.type == SCROLL_TYPE_NONE)
1545        return 0;
1546
1547    if (!valuator_mask_isset(mask, axis))
1548        return 0;
1549
1550    ax = &dev->valuator->axes[axis];
1551    incr = ax->scroll.increment;
1552
1553    BUG_WARN_MSG(incr == 0, "for device %s\n", dev->name);
1554    if (incr == 0)
1555        return 0;
1556
1557    if (type != ButtonPress && type != ButtonRelease)
1558        flags |= POINTER_EMULATED;
1559
1560    if (!valuator_mask_isset(last, axis))
1561        valuator_mask_set_double(last, axis, 0);
1562
1563    delta =
1564        valuator_mask_get_double(mask, axis) - valuator_mask_get_double(last,
1565                                                                        axis);
1566    total = delta;
1567    b = (ax->scroll.type == SCROLL_TYPE_VERTICAL) ? 5 : 7;
1568
1569    if ((incr > 0 && delta < 0) || (incr < 0 && delta > 0))
1570        b--;                    /* we're scrolling up or left → button 4 or 6 */
1571
1572    while (fabs(delta) >= fabs(incr)) {
1573        int nev_tmp;
1574
1575        if (delta > 0)
1576            delta -= fabs(incr);
1577        else if (delta < 0)
1578            delta += fabs(incr);
1579
1580        /* fill_pointer_events() generates four events: one normal and one raw
1581         * event for button press and button release.
1582         * We may get a bigger scroll delta than we can generate events
1583         * for. In that case, we keep decreasing delta, but skip events.
1584         */
1585        if (num_events + 4 < max_events) {
1586            if (type != ButtonRelease) {
1587                nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms,
1588                                              flags, NULL);
1589                events += nev_tmp;
1590                num_events += nev_tmp;
1591            }
1592            if (type != ButtonPress) {
1593                nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms,
1594                                              flags, NULL);
1595                events += nev_tmp;
1596                num_events += nev_tmp;
1597            }
1598        }
1599    }
1600
1601    /* We emulated, update last.scroll */
1602    if (total != delta) {
1603        total -= delta;
1604        valuator_mask_set_double(last, axis,
1605                                 valuator_mask_get_double(last, axis) + total);
1606    }
1607
1608    return num_events;
1609}
1610
1611
1612/**
1613 * Generate a complete series of InternalEvents (filled into the EventList)
1614 * representing pointer motion, or button presses.  If the device is a slave
1615 * device, also potentially generate a DeviceClassesChangedEvent to update
1616 * the master device.
1617 *
1618 * events is not NULL-terminated; the return value is the number of events.
1619 * The DDX is responsible for allocating the event structure in the first
1620 * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
1621 *
1622 * In the generated events rootX/Y will be in absolute screen coords and
1623 * the valuator information in the absolute or relative device coords.
1624 *
1625 * last.valuators[x] of the device is always in absolute device coords.
1626 * last.valuators[x] of the master device is in absolute screen coords.
1627 *
1628 * master->last.valuators[x] for x > 2 is undefined.
1629 */
1630int
1631GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
1632                 int buttons, int flags, const ValuatorMask *mask_in)
1633{
1634    CARD32 ms = GetTimeInMillis();
1635    int num_events = 0, nev_tmp;
1636    ValuatorMask mask;
1637    ValuatorMask scroll;
1638    int i;
1639    int realtype = type;
1640
1641#if XSERVER_DTRACE
1642    if (XSERVER_INPUT_EVENT_ENABLED()) {
1643        XSERVER_INPUT_EVENT(pDev->id, type, buttons, flags,
1644                            mask_in ? mask_in->last_bit + 1 : 0,
1645                            mask_in ? mask_in->mask : NULL,
1646                            mask_in ? mask_in->valuators : NULL);
1647    }
1648#endif
1649
1650    BUG_RETURN_VAL(buttons >= MAX_BUTTONS, 0);
1651
1652    /* refuse events from disabled devices */
1653    if (!pDev->enabled)
1654        return 0;
1655
1656    if (!miPointerGetScreen(pDev))
1657        return 0;
1658
1659    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT,
1660                              &num_events);
1661
1662    valuator_mask_copy(&mask, mask_in);
1663
1664    /* Turn a scroll button press into a smooth-scrolling event if
1665     * necessary. This only needs to cater for the XIScrollFlagPreferred
1666     * axis (if more than one scrolling axis is present) */
1667    if (type == ButtonPress) {
1668        double adj;
1669        int axis;
1670        int h_scroll_axis = -1;
1671        int v_scroll_axis = -1;
1672
1673        if (pDev->valuator) {
1674            h_scroll_axis = pDev->valuator->h_scroll_axis;
1675            v_scroll_axis = pDev->valuator->v_scroll_axis;
1676        }
1677
1678        /* Up is negative on valuators, down positive */
1679        switch (buttons) {
1680        case 4:
1681            adj = -1.0;
1682            axis = v_scroll_axis;
1683            break;
1684        case 5:
1685            adj = 1.0;
1686            axis = v_scroll_axis;
1687            break;
1688        case 6:
1689            adj = -1.0;
1690            axis = h_scroll_axis;
1691            break;
1692        case 7:
1693            adj = 1.0;
1694            axis = h_scroll_axis;
1695            break;
1696        default:
1697            adj = 0.0;
1698            axis = -1;
1699            break;
1700        }
1701
1702        if (adj != 0.0 && axis != -1) {
1703            adj *= pDev->valuator->axes[axis].scroll.increment;
1704            if (!valuator_mask_isset(&mask, axis))
1705                valuator_mask_set(&mask, axis, 0);
1706            add_to_scroll_valuator(pDev, &mask, axis, adj);
1707            type = MotionNotify;
1708            buttons = 0;
1709            flags |= POINTER_EMULATED;
1710        }
1711    }
1712
1713    /* First fill out the original event set, with smooth-scrolling axes. */
1714    nev_tmp = fill_pointer_events(events, pDev, type, buttons, ms, flags,
1715                                  &mask);
1716    events += nev_tmp;
1717    num_events += nev_tmp;
1718
1719    valuator_mask_zero(&scroll);
1720
1721    /* Now turn the smooth-scrolling axes back into emulated button presses
1722     * for legacy clients, based on the integer delta between before and now */
1723    for (i = 0; i < valuator_mask_size(&mask); i++) {
1724        if ( !pDev->valuator || (i >= pDev->valuator->numAxes))
1725            break;
1726
1727        if (!valuator_mask_isset(&mask, i))
1728            continue;
1729
1730        valuator_mask_set_double(&scroll, i, pDev->last.valuators[i]);
1731
1732        nev_tmp =
1733            emulate_scroll_button_events(events, pDev, realtype, i, &scroll,
1734                                         pDev->last.scroll, ms,
1735                                         GetMaximumEventsNum() - num_events);
1736        events += nev_tmp;
1737        num_events += nev_tmp;
1738    }
1739
1740    return num_events;
1741}
1742
1743/**
1744 * Generate internal events representing this proximity event and enqueue
1745 * them on the event queue.
1746 *
1747 * This function is not reentrant. Disable signals before calling.
1748 *
1749 * @param device The device to generate the event for
1750 * @param type Event type, one of ProximityIn or ProximityOut
1751 * @param keycode Key code of the pressed/released key
1752 * @param mask Valuator mask for valuators present for this event.
1753 *
1754 */
1755void
1756QueueProximityEvents(DeviceIntPtr device, int type, const ValuatorMask *mask)
1757{
1758    int nevents;
1759
1760    nevents = GetProximityEvents(InputEventList, device, type, mask);
1761    queueEventList(device, InputEventList, nevents);
1762}
1763
1764/**
1765 * Generate ProximityIn/ProximityOut InternalEvents, accompanied by
1766 * valuators.
1767 *
1768 * The DDX is responsible for allocating the events in the first place via
1769 * InitEventList(), and for freeing it.
1770 *
1771 * @return the number of events written into events.
1772 */
1773int
1774GetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
1775                   const ValuatorMask *mask_in)
1776{
1777    int num_events = 1, i;
1778    DeviceEvent *event;
1779    ValuatorMask mask;
1780
1781#if XSERVER_DTRACE
1782    if (XSERVER_INPUT_EVENT_ENABLED()) {
1783        XSERVER_INPUT_EVENT(pDev->id, type, 0, 0,
1784                            mask_in ? mask_in->last_bit + 1 : 0,
1785                            mask_in ? mask_in->mask : NULL,
1786                            mask_in ? mask_in->valuators : NULL);
1787    }
1788#endif
1789
1790    /* refuse events from disabled devices */
1791    if (!pDev->enabled)
1792        return 0;
1793
1794    /* Sanity checks. */
1795    if ((type != ProximityIn && type != ProximityOut) || !mask_in)
1796        return 0;
1797    if (!pDev->valuator || !pDev->proximity)
1798        return 0;
1799
1800    valuator_mask_copy(&mask, mask_in);
1801
1802    /* ignore relative axes for proximity. */
1803    for (i = 0; i < valuator_mask_size(&mask); i++) {
1804        if (valuator_mask_isset(&mask, i) &&
1805            valuator_get_mode(pDev, i) == Relative)
1806            valuator_mask_unset(&mask, i);
1807    }
1808
1809    /* FIXME: posting proximity events with relative valuators only results
1810     * in an empty event, EventToXI() will fail to convert → no event sent
1811     * to client. */
1812
1813    events =
1814        UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
1815
1816    event = &events->device_event;
1817    init_device_event(event, pDev, GetTimeInMillis(), EVENT_SOURCE_NORMAL);
1818    event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
1819
1820    clipValuators(pDev, &mask);
1821
1822    set_valuators(pDev, event, &mask);
1823
1824    return num_events;
1825}
1826
1827int
1828GetTouchOwnershipEvents(InternalEvent *events, DeviceIntPtr pDev,
1829                        TouchPointInfoPtr ti, uint8_t reason, XID resource,
1830                        uint32_t flags)
1831{
1832    TouchClassPtr t = pDev->touch;
1833    TouchOwnershipEvent *event;
1834    CARD32 ms = GetTimeInMillis();
1835
1836    if (!pDev->enabled || !t || !ti)
1837        return 0;
1838
1839    event = &events->touch_ownership_event;
1840    init_touch_ownership(pDev, event, ms);
1841
1842    event->touchid = ti->client_id;
1843    event->sourceid = ti->sourceid;
1844    event->resource = resource;
1845    event->flags = flags;
1846    event->reason = reason;
1847
1848    return 1;
1849}
1850
1851/**
1852 * Generate internal events representing this touch event and enqueue them
1853 * on the event queue.
1854 *
1855 * This function is not reentrant. Disable signals before calling.
1856 *
1857 * @param device The device to generate the event for
1858 * @param type Event type, one of XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd
1859 * @param touchid Touch point ID
1860 * @param flags Event modification flags
1861 * @param mask Valuator mask for valuators present for this event.
1862 */
1863void
1864QueueTouchEvents(DeviceIntPtr device, int type,
1865                 uint32_t ddx_touchid, int flags, const ValuatorMask *mask)
1866{
1867    int nevents;
1868
1869    nevents =
1870        GetTouchEvents(InputEventList, device, ddx_touchid, type, flags, mask);
1871    queueEventList(device, InputEventList, nevents);
1872}
1873
1874/**
1875 * Get events for a touch. Generates a TouchBegin event if end is not set and
1876 * the touch id is not active. Generates a TouchUpdate event if end is not set
1877 * and the touch id is active. Generates a TouchEnd event if end is set and the
1878 * touch id is active.
1879 *
1880 * events is not NULL-terminated; the return value is the number of events.
1881 * The DDX is responsible for allocating the event structure in the first
1882 * place via GetMaximumEventsNum(), and for freeing it.
1883 *
1884 * @param[out] events The list of events generated
1885 * @param dev The device to generate the events for
1886 * @param ddx_touchid The touch ID as assigned by the DDX
1887 * @param type XI_TouchBegin, XI_TouchUpdate or XI_TouchEnd
1888 * @param flags Event flags
1889 * @param mask_in Valuator information for this event
1890 */
1891int
1892GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid,
1893               uint16_t type, uint32_t flags, const ValuatorMask *mask_in)
1894{
1895    ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen;
1896    TouchClassPtr t = dev->touch;
1897    ValuatorClassPtr v = dev->valuator;
1898    DeviceEvent *event;
1899    CARD32 ms = GetTimeInMillis();
1900    ValuatorMask mask;
1901    double screenx = 0.0, screeny = 0.0;        /* desktop coordinate system */
1902    double devx = 0.0, devy = 0.0;      /* desktop-wide in device coords */
1903    int i;
1904    int num_events = 0;
1905    RawDeviceEvent *raw;
1906    DDXTouchPointInfoPtr ti;
1907    int need_rawevent = TRUE;
1908    Bool emulate_pointer = FALSE;
1909    int client_id = 0;
1910
1911#if XSERVER_DTRACE
1912    if (XSERVER_INPUT_EVENT_ENABLED()) {
1913        XSERVER_INPUT_EVENT(dev->id, type, ddx_touchid, flags,
1914                            mask_in ? mask_in->last_bit + 1 : 0,
1915                            mask_in ? mask_in->mask : NULL,
1916                            mask_in ? mask_in->valuators : NULL);
1917    }
1918#endif
1919
1920    if (!dev->enabled || !t || !v)
1921        return 0;
1922
1923    /* Find and/or create the DDX touch info */
1924
1925    ti = TouchFindByDDXID(dev, ddx_touchid, (type == XI_TouchBegin));
1926    if (!ti) {
1927        ErrorFSigSafe("[dix] %s: unable to %s touch point %u\n", dev->name,
1928                      type == XI_TouchBegin ? "begin" : "find", ddx_touchid);
1929        return 0;
1930    }
1931    client_id = ti->client_id;
1932
1933    emulate_pointer = ti->emulate_pointer;
1934
1935    if (!IsMaster(dev))
1936        events =
1937            UpdateFromMaster(events, dev, DEVCHANGE_POINTER_EVENT, &num_events);
1938
1939    valuator_mask_copy(&mask, mask_in);
1940
1941    if (need_rawevent) {
1942        raw = &events->raw_event;
1943        events++;
1944        num_events++;
1945        init_raw(dev, raw, ms, type, client_id);
1946        set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw);
1947    }
1948
1949    event = &events->device_event;
1950    num_events++;
1951
1952    init_device_event(event, dev, ms, EVENT_SOURCE_NORMAL);
1953
1954    switch (type) {
1955    case XI_TouchBegin:
1956        event->type = ET_TouchBegin;
1957        /* If we're starting a touch, we must have x & y co-ordinates. */
1958        if (!mask_in ||
1959            !valuator_mask_isset(mask_in, 0) ||
1960            !valuator_mask_isset(mask_in, 1)) {
1961            ErrorFSigSafe("%s: Attempted to start touch without x/y "
1962                          "(driver bug)\n", dev->name);
1963            return 0;
1964        }
1965        break;
1966    case XI_TouchUpdate:
1967        event->type = ET_TouchUpdate;
1968        if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0) {
1969            ErrorFSigSafe("%s: TouchUpdate with no valuators? Driver bug\n",
1970                          dev->name);
1971        }
1972        break;
1973    case XI_TouchEnd:
1974        event->type = ET_TouchEnd;
1975        /* We can end the DDX touch here, since we don't use the active
1976         * field below */
1977        TouchEndDDXTouch(dev, ti);
1978        break;
1979    default:
1980        return 0;
1981    }
1982
1983    /* Get our screen event co-ordinates (root_x/root_y/event_x/event_y):
1984     * these come from the touchpoint in Absolute mode, or the sprite in
1985     * Relative. */
1986    if (t->mode == XIDirectTouch) {
1987        for (i = 0; i < max(valuator_mask_size(&mask), 2); i++) {
1988            double val;
1989
1990            if (valuator_mask_fetch_double(&mask, i, &val))
1991                valuator_mask_set_double(ti->valuators, i, val);
1992            /* If the device doesn't post new X and Y axis values,
1993             * use the last values posted.
1994             */
1995            else if (i < 2 &&
1996                valuator_mask_fetch_double(ti->valuators, i, &val))
1997                valuator_mask_set_double(&mask, i, val);
1998        }
1999
2000        transformAbsolute(dev, &mask);
2001        clipAbsolute(dev, &mask);
2002    }
2003    else {
2004        screenx = dev->spriteInfo->sprite->hotPhys.x;
2005        screeny = dev->spriteInfo->sprite->hotPhys.y;
2006    }
2007    if (need_rawevent)
2008        set_raw_valuators(raw, &mask, FALSE, raw->valuators.data);
2009
2010    /* Indirect device touch coordinates are not used for cursor positioning.
2011     * They are merely informational, and are provided in device coordinates.
2012     * The device sprite is used for positioning instead, and it is already
2013     * scaled. */
2014    if (t->mode == XIDirectTouch)
2015        scr = scale_to_desktop(dev, &mask, &devx, &devy, &screenx, &screeny);
2016    if (emulate_pointer)
2017        scr = positionSprite(dev, Absolute, &mask,
2018                             &devx, &devy, &screenx, &screeny, NULL, NULL);
2019
2020    /* see fill_pointer_events for coordinate systems */
2021    if (emulate_pointer)
2022        updateHistory(dev, &mask, ms);
2023
2024    clipValuators(dev, &mask);
2025
2026    if (emulate_pointer)
2027        storeLastValuators(dev, &mask, 0, 1, devx, devy);
2028
2029    /* Update the MD's co-ordinates, which are always in desktop space. */
2030    if (emulate_pointer && !IsMaster(dev) && !IsFloating(dev)) {
2031	    DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
2032
2033	    master->last.valuators[0] = screenx;
2034	    master->last.valuators[1] = screeny;
2035    }
2036
2037    event->root = scr->root->drawable.id;
2038
2039    event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
2040    event->touchid = client_id;
2041    event->flags = flags;
2042
2043    if (emulate_pointer) {
2044        event->flags |= TOUCH_POINTER_EMULATED;
2045        event->detail.button = 1;
2046    }
2047
2048    set_valuators(dev, event, &mask);
2049    for (i = 0; i < v->numAxes; i++) {
2050        if (valuator_mask_isset(&mask, i))
2051            v->axisVal[i] = valuator_mask_get(&mask, i);
2052    }
2053
2054    return num_events;
2055}
2056
2057void
2058GetDixTouchEnd(InternalEvent *ievent, DeviceIntPtr dev, TouchPointInfoPtr ti,
2059               uint32_t flags)
2060{
2061    ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen;
2062    DeviceEvent *event = &ievent->device_event;
2063    CARD32 ms = GetTimeInMillis();
2064
2065    BUG_WARN(!dev->enabled);
2066
2067    init_device_event(event, dev, ms, EVENT_SOURCE_NORMAL);
2068
2069    event->sourceid = ti->sourceid;
2070    event->type = ET_TouchEnd;
2071
2072    event->root = scr->root->drawable.id;
2073
2074    /* Get screen event coordinates from the sprite.  Is this really the best
2075     * we can do? */
2076    event_set_root_coordinates(event,
2077                               dev->last.valuators[0] - scr->x,
2078                               dev->last.valuators[1] - scr->y);
2079    event->touchid = ti->client_id;
2080    event->flags = flags;
2081
2082    if (flags & TOUCH_POINTER_EMULATED) {
2083        event->flags |= TOUCH_POINTER_EMULATED;
2084        event->detail.button = 1;
2085    }
2086}
2087
2088/**
2089 * Synthesize a single motion event for the core pointer.
2090 *
2091 * Used in cursor functions, e.g. when cursor confinement changes, and we need
2092 * to shift the pointer to get it inside the new bounds.
2093 */
2094void
2095PostSyntheticMotion(DeviceIntPtr pDev,
2096                    int x, int y, int screen, unsigned long time)
2097{
2098    DeviceEvent ev;
2099
2100#ifdef PANORAMIX
2101    /* Translate back to the sprite screen since processInputProc
2102       will translate from sprite screen to screen 0 upon reentry
2103       to the DIX layer. */
2104    if (!noPanoramiXExtension) {
2105        x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x;
2106        y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y;
2107    }
2108#endif
2109
2110    memset(&ev, 0, sizeof(DeviceEvent));
2111    init_device_event(&ev, pDev, time, EVENT_SOURCE_NORMAL);
2112    ev.root_x = x;
2113    ev.root_y = y;
2114    ev.type = ET_Motion;
2115    ev.time = time;
2116
2117    /* FIXME: MD/SD considerations? */
2118    (*pDev->public.processInputProc) ((InternalEvent *) &ev, pDev);
2119}
2120