getevents.c revision 65b04b38
1/*
2 * Copyright © 2006 Nokia Corporation
3 * Copyright © 2006-2007 Daniel Stone
4 * Copyright © 2008 Red Hat, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 *
25 * Authors: Daniel Stone <daniel@fooishbar.org>
26 *          Peter Hutterer <peter.hutterer@who-t.net>
27 */
28
29#ifdef HAVE_DIX_CONFIG_H
30#include <dix-config.h>
31#endif
32
33#include <X11/X.h>
34#include <X11/keysym.h>
35#include <X11/Xproto.h>
36#include <math.h>
37
38#include "misc.h"
39#include "resource.h"
40#include "inputstr.h"
41#include "scrnintstr.h"
42#include "cursorstr.h"
43#include "dixstruct.h"
44#include "globals.h"
45#include "dixevents.h"
46#include "mipointer.h"
47#include "eventstr.h"
48#include "eventconvert.h"
49#include "inpututils.h"
50
51#include <X11/extensions/XKBproto.h>
52#include "xkbsrv.h"
53
54#ifdef PANORAMIX
55#include "panoramiX.h"
56#include "panoramiXsrv.h"
57#endif
58
59#include <X11/extensions/XI.h>
60#include <X11/extensions/XIproto.h>
61#include <pixman.h>
62#include "exglobals.h"
63#include "exevents.h"
64#include "exglobals.h"
65#include "extnsionst.h"
66#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */
67
68/* Number of motion history events to store. */
69#define MOTION_HISTORY_SIZE 256
70
71/* InputEventList is the container list for all input events generated by the
72 * DDX. The DDX is expected to call GetEventList() and then pass the list into
73 * Get{Pointer|Keyboard}Events.
74 */
75EventListPtr InputEventList = NULL;
76int InputEventListLen = 0;
77
78int
79GetEventList(EventListPtr* list)
80{
81    *list = InputEventList;
82    return InputEventListLen;
83}
84
85/**
86 * Pick some arbitrary size for Xi motion history.
87 */
88int
89GetMotionHistorySize(void)
90{
91    return MOTION_HISTORY_SIZE;
92}
93
94void
95set_button_down(DeviceIntPtr pDev, int button, int type)
96{
97    if (type == BUTTON_PROCESSED)
98        SetBit(pDev->button->down, button);
99    else
100        SetBit(pDev->button->postdown, button);
101}
102
103void
104set_button_up(DeviceIntPtr pDev, int button, int type)
105{
106    if (type == BUTTON_PROCESSED)
107        ClearBit(pDev->button->down, button);
108    else
109        ClearBit(pDev->button->postdown, button);
110}
111
112Bool
113button_is_down(DeviceIntPtr pDev, int button, int type)
114{
115    Bool ret = FALSE;
116
117    if (type & BUTTON_PROCESSED)
118        ret = ret || BitIsOn(pDev->button->down, button);
119    if (type & BUTTON_POSTED)
120        ret = ret || BitIsOn(pDev->button->postdown, button);
121
122    return ret;
123}
124
125void
126set_key_down(DeviceIntPtr pDev, int key_code, int type)
127{
128    if (type == KEY_PROCESSED)
129        SetBit(pDev->key->down, key_code);
130    else
131        SetBit(pDev->key->postdown, key_code);
132}
133
134void
135set_key_up(DeviceIntPtr pDev, int key_code, int type)
136{
137    if (type == KEY_PROCESSED)
138        ClearBit(pDev->key->down, key_code);
139    else
140        ClearBit(pDev->key->postdown, key_code);
141}
142
143Bool
144key_is_down(DeviceIntPtr pDev, int key_code, int type)
145{
146    Bool ret = FALSE;
147
148    if (type & KEY_PROCESSED)
149        ret = ret || BitIsOn(pDev->key->down, key_code);
150    if (type & KEY_POSTED)
151        ret = ret || BitIsOn(pDev->key->postdown, key_code);
152
153    return ret;
154}
155
156static Bool
157key_autorepeats(DeviceIntPtr pDev, int key_code)
158{
159    return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
160              (1 << (key_code & 7)));
161}
162
163static void
164init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
165{
166    memset(event, 0, sizeof(DeviceEvent));
167    event->header = ET_Internal;
168    event->length = sizeof(DeviceEvent);
169    event->time = ms;
170    event->deviceid = dev->id;
171    event->sourceid = dev->id;
172}
173
174static void
175init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
176{
177    memset(event, 0, sizeof(RawDeviceEvent));
178    event->header = ET_Internal;
179    event->length = sizeof(RawDeviceEvent);
180    event->type = ET_RawKeyPress - ET_KeyPress + type;
181    event->time = ms;
182    event->deviceid = dev->id;
183    event->sourceid = dev->id;
184    event->detail.button = detail;
185}
186
187static void
188set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data)
189{
190    int i;
191
192    for (i = 0; i < valuator_mask_size(mask); i++)
193    {
194        if (valuator_mask_isset(mask, i))
195        {
196            SetBit(event->valuators.mask, i);
197            data[i] = valuator_mask_get(mask, i);
198        }
199    }
200}
201
202
203static void
204set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask)
205{
206    int i;
207
208    /* Set the data to the previous value for unset absolute axes. The values
209     * may be used when sent as part of an XI 1.x valuator event. */
210    for (i = 0; i < valuator_mask_size(mask); i++)
211    {
212        if (valuator_mask_isset(mask, i))
213        {
214            SetBit(event->valuators.mask, i);
215            if (valuator_get_mode(dev, i) == Absolute)
216                SetBit(event->valuators.mode, i);
217            event->valuators.data[i] = valuator_mask_get(mask, i);
218            event->valuators.data_frac[i] =
219                dev->last.remainder[i] * (1 << 16) * (1 << 16);
220        }
221        else if (valuator_get_mode(dev, i) == Absolute)
222            event->valuators.data[i] = dev->valuator->axisVal[i];
223    }
224}
225
226void
227CreateClassesChangedEvent(EventList* event,
228                          DeviceIntPtr master,
229                          DeviceIntPtr slave,
230                          int type)
231{
232    int i;
233    DeviceChangedEvent *dce;
234    CARD32 ms = GetTimeInMillis();
235
236    dce = (DeviceChangedEvent*)event->event;
237    memset(dce, 0, sizeof(DeviceChangedEvent));
238    dce->deviceid = slave->id;
239    dce->masterid = master->id;
240    dce->header = ET_Internal;
241    dce->length = sizeof(DeviceChangedEvent);
242    dce->type = ET_DeviceChanged;
243    dce->time = ms;
244    dce->flags = type;
245    dce->flags |= DEVCHANGE_SLAVE_SWITCH;
246    dce->sourceid = slave->id;
247
248    if (slave->button)
249    {
250        dce->buttons.num_buttons = slave->button->numButtons;
251        for (i = 0; i < dce->buttons.num_buttons; i++)
252            dce->buttons.names[i] = slave->button->labels[i];
253    }
254    if (slave->valuator)
255    {
256        dce->num_valuators = slave->valuator->numAxes;
257        for (i = 0; i < dce->num_valuators; i++)
258        {
259            dce->valuators[i].min = slave->valuator->axes[i].min_value;
260            dce->valuators[i].max = slave->valuator->axes[i].max_value;
261            dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
262            dce->valuators[i].mode = slave->valuator->axes[i].mode;
263            dce->valuators[i].name = slave->valuator->axes[i].label;
264        }
265    }
266    if (slave->key)
267    {
268        dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
269        dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
270    }
271}
272
273/**
274 * Rescale the coord between the two axis ranges.
275 */
276static int
277rescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to,
278                    int defmax)
279{
280    int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return;
281    float value;
282
283    if(from && from->min_value < from->max_value) {
284        fmin = from->min_value;
285        fmax = from->max_value;
286    }
287    if(to && to->min_value < to->max_value) {
288        tmin = to->min_value;
289        tmax = to->max_value;
290    }
291
292    if(fmin == tmin && fmax == tmax) {
293        if (remainder_return)
294            *remainder_return = remainder;
295        return coord;
296    }
297
298    if(fmax == fmin) { /* avoid division by 0 */
299        if (remainder_return)
300            *remainder_return = 0.0;
301        return 0;
302    }
303
304    value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
305    coord_return = lroundf(value);
306    if (remainder_return)
307        *remainder_return = value - coord_return;
308    return coord_return;
309}
310
311/**
312 * Update all coordinates when changing to a different SD
313 * to ensure that relative reporting will work as expected
314 * without loss of precision.
315 *
316 * pDev->last.valuators will be in absolute device coordinates after this
317 * function.
318 */
319static void
320updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
321{
322    ScreenPtr scr = miPointerGetScreen(pDev);
323    int i;
324    DeviceIntPtr lastSlave;
325
326    /* master->last.valuators[0]/[1] is in screen coords and the actual
327     * position of the pointer */
328    pDev->last.valuators[0] = master->last.valuators[0];
329    pDev->last.valuators[1] = master->last.valuators[1];
330
331    if (!pDev->valuator)
332        return;
333
334    /* scale back to device coordinates */
335    if(pDev->valuator->numAxes > 0)
336        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0],
337                        &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width);
338    if(pDev->valuator->numAxes > 1)
339        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1],
340                        &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height);
341
342    /* calculate the other axis as well based on info from the old
343     * slave-device. If the old slave had less axes than this one,
344     * last.valuators is reset to 0.
345     */
346    if ((lastSlave = master->last.slave) && lastSlave->valuator) {
347        for (i = 2; i < pDev->valuator->numAxes; i++) {
348            if (i >= lastSlave->valuator->numAxes)
349                pDev->last.valuators[i] = 0;
350            else
351                pDev->last.valuators[i] =
352                    rescaleValuatorAxis(pDev->last.valuators[i],
353                            pDev->last.remainder[i],
354                            &pDev->last.remainder[i],
355                            lastSlave->valuator->axes + i,
356                            pDev->valuator->axes + i, 0);
357        }
358    }
359
360}
361
362/**
363 * Allocate the motion history buffer.
364 */
365void
366AllocateMotionHistory(DeviceIntPtr pDev)
367{
368    int size;
369    free(pDev->valuator->motion);
370
371    if (pDev->valuator->numMotionEvents < 1)
372        return;
373
374    /* An MD must have a motion history size large enough to keep all
375     * potential valuators, plus the respective range of the valuators.
376     * 3 * INT32 for (min_val, max_val, curr_val))
377     */
378    if (IsMaster(pDev))
379        size = sizeof(INT32) * 3 * MAX_VALUATORS;
380    else {
381        ValuatorClassPtr v = pDev->valuator;
382        int numAxes;
383        /* XI1 doesn't understand mixed mode devices */
384        for (numAxes = 0; numAxes < v->numAxes; numAxes++)
385            if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0))
386                break;
387        size = sizeof(INT32) * numAxes;
388    }
389
390    size += sizeof(Time);
391
392    pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size);
393    pDev->valuator->first_motion = 0;
394    pDev->valuator->last_motion = 0;
395    if (!pDev->valuator->motion)
396        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
397                pDev->name, size * pDev->valuator->numMotionEvents);
398}
399
400/**
401 * Dump the motion history between start and stop into the supplied buffer.
402 * Only records the event for a given screen in theory, but in practice, we
403 * sort of ignore this.
404 *
405 * If core is set, we only generate x/y, in INT16, scaled to screen coords.
406 */
407int
408GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
409                 unsigned long stop, ScreenPtr pScreen, BOOL core)
410{
411    char *ibuff = NULL, *obuff;
412    int i = 0, ret = 0;
413    int j, coord;
414    Time current;
415    /* The size of a single motion event. */
416    int size;
417    int dflt;
418    AxisInfo from, *to; /* for scaling */
419    INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
420    INT16 *corebuf;
421    AxisInfo core_axis = {0};
422
423    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
424        return 0;
425
426    if (core && !pScreen)
427        return 0;
428
429    if (IsMaster(pDev))
430        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
431    else
432        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
433
434    *buff = malloc(size * pDev->valuator->numMotionEvents);
435    if (!(*buff))
436        return 0;
437    obuff = (char *)*buff;
438
439    for (i = pDev->valuator->first_motion;
440         i != pDev->valuator->last_motion;
441         i = (i + 1) % pDev->valuator->numMotionEvents) {
442        /* We index the input buffer by which element we're accessing, which
443         * is not monotonic, and the output buffer by how many events we've
444         * written so far. */
445        ibuff = (char *) pDev->valuator->motion + (i * size);
446        memcpy(&current, ibuff, sizeof(Time));
447
448        if (current > stop) {
449            return ret;
450        }
451        else if (current >= start) {
452            if (core)
453            {
454                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
455
456                icbuf = (INT32*)(ibuff + sizeof(Time));
457                corebuf = (INT16*)(obuff + sizeof(Time));
458
459                /* fetch x coordinate + range */
460                memcpy(&from.min_value, icbuf++, sizeof(INT32));
461                memcpy(&from.max_value, icbuf++, sizeof(INT32));
462                memcpy(&coord, icbuf++, sizeof(INT32));
463
464                /* scale to screen coords */
465                to = &core_axis;
466                to->max_value = pScreen->width;
467                coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width);
468
469                memcpy(corebuf, &coord, sizeof(INT16));
470                corebuf++;
471
472                /* fetch y coordinate + range */
473                memcpy(&from.min_value, icbuf++, sizeof(INT32));
474                memcpy(&from.max_value, icbuf++, sizeof(INT32));
475                memcpy(&coord, icbuf++, sizeof(INT32));
476
477                to->max_value = pScreen->height;
478                coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height);
479                memcpy(corebuf, &coord, sizeof(INT16));
480
481            } else if (IsMaster(pDev))
482            {
483                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
484
485                ocbuf = (INT32*)(obuff + sizeof(Time));
486                icbuf = (INT32*)(ibuff + sizeof(Time));
487                for (j = 0; j < MAX_VALUATORS; j++)
488                {
489                    if (j >= pDev->valuator->numAxes)
490                        break;
491
492                    /* fetch min/max/coordinate */
493                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
494                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
495                    memcpy(&coord, icbuf++, sizeof(INT32));
496
497                    to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
498
499                    /* x/y scaled to screen if no range is present */
500                    if (j == 0 && (from.max_value < from.min_value))
501                        from.max_value = pScreen->width;
502                    else if (j == 1 && (from.max_value < from.min_value))
503                        from.max_value = pScreen->height;
504
505                    if (j == 0 && (to->max_value < to->min_value))
506                        dflt = pScreen->width;
507                    else if (j == 1 && (to->max_value < to->min_value))
508                        dflt = pScreen->height;
509                    else
510                        dflt = 0;
511
512                    /* scale from stored range into current range */
513                    coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
514                    memcpy(ocbuf, &coord, sizeof(INT32));
515                    ocbuf++;
516                }
517            } else
518                memcpy(obuff, ibuff, size);
519
520            /* don't advance by size here. size may be different to the
521             * actually written size if the MD has less valuators than MAX */
522            if (core)
523                obuff += sizeof(INT32) + sizeof(Time);
524            else
525                obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
526            ret++;
527        }
528    }
529
530    return ret;
531}
532
533
534/**
535 * Update the motion history for a specific device, with the list of
536 * valuators.
537 *
538 * Layout of the history buffer:
539 *   for SDs: [time] [val0] [val1] ... [valn]
540 *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
541 *
542 * For events that have some valuators unset:
543 *      min_val == max_val == val == 0.
544 */
545static void
546updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
547                    int *valuators)
548{
549    char *buff = (char *) pDev->valuator->motion;
550    ValuatorClassPtr v;
551    int i;
552
553    if (!pDev->valuator->numMotionEvents)
554        return;
555
556    v = pDev->valuator;
557    if (IsMaster(pDev))
558    {
559        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
560                v->last_motion;
561
562        memcpy(buff, &ms, sizeof(Time));
563        buff += sizeof(Time);
564
565        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
566
567        for (i = 0; i < v->numAxes; i++)
568        {
569            /* XI1 doesn't support mixed mode devices */
570            if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0))
571                break;
572            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
573            {
574                buff += 3 * sizeof(INT32);
575                continue;
576            }
577            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
578            buff += sizeof(INT32);
579            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
580            buff += sizeof(INT32);
581            memcpy(buff, &valuators[i], sizeof(INT32));
582            buff += sizeof(INT32);
583        }
584    } else
585    {
586
587        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
588            pDev->valuator->last_motion;
589
590        memcpy(buff, &ms, sizeof(Time));
591        buff += sizeof(Time);
592
593        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
594
595        for (i = 0; i < MAX_VALUATORS; i++)
596        {
597            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
598            {
599                buff += sizeof(INT32);
600                continue;
601            }
602            memcpy(buff, &valuators[i], sizeof(INT32));
603            buff += sizeof(INT32);
604        }
605    }
606
607    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
608        pDev->valuator->numMotionEvents;
609    /* If we're wrapping around, just keep the circular buffer going. */
610    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
611        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
612                                       pDev->valuator->numMotionEvents;
613
614    return;
615}
616
617
618/**
619 * Returns the maximum number of events GetKeyboardEvents,
620 * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
621 *
622 * This MUST be absolutely constant, from init until exit.
623 */
624int
625GetMaximumEventsNum(void) {
626    /* One raw event
627     * One device event
628     * One possible device changed event
629     */
630    return 3;
631}
632
633
634/**
635 * Clip an axis to its bounds, which are declared in the call to
636 * InitValuatorAxisClassStruct.
637 */
638static void
639clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
640{
641    AxisInfoPtr axis;
642
643    if (axisNum >= pDev->valuator->numAxes)
644        return;
645
646    axis = pDev->valuator->axes + axisNum;
647
648    /* If a value range is defined, clip. If not, do nothing */
649    if (axis->max_value <= axis->min_value)
650        return;
651
652    if (*val < axis->min_value)
653        *val = axis->min_value;
654    if (*val > axis->max_value)
655        *val = axis->max_value;
656}
657
658/**
659 * Clip every axis in the list of valuators to its bounds.
660 */
661static void
662clipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
663{
664    int i;
665
666    for (i = 0; i < valuator_mask_size(mask); i++)
667        if (valuator_mask_isset(mask, i))
668        {
669            int val = valuator_mask_get(mask, i);
670            clipAxis(pDev, i, &val);
671            valuator_mask_set(mask, i, val);
672        }
673}
674
675/**
676 * Create the DCCE event (does not update the master's device state yet, this
677 * is done in the event processing).
678 * Pull in the coordinates from the MD if necessary.
679 *
680 * @param events Pointer to a pre-allocated event list.
681 * @param dev The slave device that generated an event.
682 * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
683 * @param num_events The current number of events, returns the number of
684 *        events if a DCCE was generated.
685 * @return The updated @events pointer.
686 */
687EventListPtr
688UpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
689{
690    DeviceIntPtr master;
691
692    master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ?  MASTER_POINTER : MASTER_KEYBOARD);
693
694    if (master && master->last.slave != dev)
695    {
696        CreateClassesChangedEvent(events, master, dev, type);
697        if (IsPointerDevice(master))
698        {
699            updateSlaveDeviceCoords(master, dev);
700            master->last.numValuators = dev->last.numValuators;
701        }
702        master->last.slave = dev;
703        (*num_events)++;
704        events++;
705    }
706    return events;
707}
708
709/**
710 * Move the device's pointer to the position given in the valuators.
711 *
712 * @param dev The device which's pointer is to be moved.
713 * @param x Returns the x position of the pointer after the move.
714 * @param y Returns the y position of the pointer after the move.
715 * @param mask Bit mask of valid valuators.
716 * @param valuators Valuator data for each axis between @first and
717 *        @first+@num.
718 */
719static void
720moveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
721{
722    int i;
723
724    if (valuator_mask_isset(mask, 0))
725        *x = valuator_mask_get(mask, 0);
726    else
727        *x = dev->last.valuators[0];
728
729    if (valuator_mask_isset(mask, 1))
730        *y = valuator_mask_get(mask, 1);
731    else
732        *y = dev->last.valuators[1];
733
734    clipAxis(dev, 0, x);
735    clipAxis(dev, 1, y);
736
737    for (i = 2; i < valuator_mask_size(mask); i++)
738    {
739        if (valuator_mask_isset(mask, i))
740        {
741            dev->last.valuators[i] = valuator_mask_get(mask, i);
742            clipAxis(dev, i, &dev->last.valuators[i]);
743        }
744    }
745}
746
747/**
748 * Move the device's pointer by the values given in @valuators.
749 *
750 * @param dev The device which's pointer is to be moved.
751 * @param x Returns the x position of the pointer after the move.
752 * @param y Returns the y position of the pointer after the move.
753 * @param mask Bit mask of valid valuators.
754 * @param valuators Valuator data for each axis between @first and
755 *        @first+@num.
756 */
757static void
758moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
759{
760    int i;
761
762    *x = dev->last.valuators[0];
763    *y = dev->last.valuators[1];
764
765    if (valuator_mask_isset(mask, 0))
766        *x += valuator_mask_get(mask, 0);
767
768    if (valuator_mask_isset(mask, 1))
769        *y += valuator_mask_get(mask, 1);
770
771    /* if attached, clip both x and y to the defined limits (usually
772     * co-ord space limit). If it is attached, we need x/y to go over the
773     * limits to be able to change screens. */
774    if(dev->u.master && dev->valuator) {
775        if (valuator_get_mode(dev, 0) == Absolute)
776            clipAxis(dev, 0, x);
777        if (valuator_get_mode(dev, 1) == Absolute)
778            clipAxis(dev, 1, y);
779    }
780
781    /* calc other axes, clip, drop back into valuators */
782    for (i = 2; i < valuator_mask_size(mask); i++)
783    {
784        if (valuator_mask_isset(mask, i))
785        {
786            dev->last.valuators[i] += valuator_mask_get(mask, i);
787            if (valuator_get_mode(dev, i) == Absolute)
788                clipAxis(dev, i, &dev->last.valuators[i]);
789            valuator_mask_set(mask, i, dev->last.valuators[i]);
790        }
791    }
792}
793
794/**
795 * Accelerate the data in valuators based on the device's acceleration scheme.
796 *
797 * @param dev The device which's pointer is to be moved.
798 * @param first The first valuator in @valuators
799 * @param num Total number of valuators in @valuators.
800 * @param valuators Valuator data for each axis between @first and
801 *        @first+@num.
802 * @param ms Current time.
803 */
804static void
805accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
806{
807    if (dev->valuator->accelScheme.AccelSchemeProc)
808        dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms);
809}
810
811/**
812 * If we have HW cursors, this actually moves the visible sprite. If not, we
813 * just do all the screen crossing, etc.
814 *
815 * We scale from device to screen coordinates here, call
816 * miPointerSetPosition() and then scale back into device coordinates (if
817 * needed). miPSP will change x/y if the screen was crossed.
818 *
819 * @param dev The device to be moved.
820 * @param x Pointer to current x-axis value, may be modified.
821 * @param y Pointer to current y-axis value, may be modified.
822 * @param x_frac Fractional part of current x-axis value, may be modified.
823 * @param y_frac Fractional part of current y-axis value, may be modified.
824 * @param scr Screen the device's sprite is currently on.
825 * @param screenx Screen x coordinate the sprite is on after the update.
826 * @param screeny Screen y coordinate the sprite is on after the update.
827 * @param screenx_frac Fractional part of screen x coordinate, as above.
828 * @param screeny_frac Fractional part of screen y coordinate, as above.
829 */
830static void
831positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
832               ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
833{
834    int old_screenx, old_screeny;
835
836    /* scale x&y to screen */
837    if (dev->valuator && dev->valuator->numAxes > 0) {
838        *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac,
839                dev->valuator->axes + 0, NULL, scr->width);
840    } else {
841        *screenx = dev->last.valuators[0];
842        *screenx_frac = dev->last.remainder[0];
843    }
844
845    if (dev->valuator && dev->valuator->numAxes > 1) {
846        *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac,
847                dev->valuator->axes + 1, NULL, scr->height);
848    } else {
849        *screeny = dev->last.valuators[1];
850        *screeny_frac = dev->last.remainder[1];
851    }
852
853    /* Hit the left screen edge? */
854    if (*screenx <= 0 && *screenx_frac < 0.0f)
855    {
856        *screenx_frac = 0.0f;
857        x_frac = 0.0f;
858    }
859    if (*screeny <= 0 && *screeny_frac < 0.0f)
860    {
861        *screeny_frac = 0.0f;
862        y_frac = 0.0f;
863    }
864
865
866    old_screenx = *screenx;
867    old_screeny = *screeny;
868    /* This takes care of crossing screens for us, as well as clipping
869     * to the current screen. */
870    miPointerSetPosition(dev, screenx, screeny);
871
872    if (dev->u.master) {
873        dev->u.master->last.valuators[0] = *screenx;
874        dev->u.master->last.valuators[1] = *screeny;
875        dev->u.master->last.remainder[0] = *screenx_frac;
876        dev->u.master->last.remainder[1] = *screeny_frac;
877    }
878
879    if (dev->valuator)
880    {
881        /* Crossed screen? Scale back to device coordiantes */
882        if(*screenx != old_screenx)
883        {
884            scr = miPointerGetScreen(dev);
885            *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL,
886                                    dev->valuator->axes + 0, scr->width);
887        }
888        if(*screeny != old_screeny)
889        {
890            scr = miPointerGetScreen(dev);
891            *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL,
892                                     dev->valuator->axes + 1, scr->height);
893        }
894    }
895
896    /* dropy x/y (device coordinates) back into valuators for next event */
897    dev->last.valuators[0] = *x;
898    dev->last.valuators[1] = *y;
899    dev->last.remainder[0] = x_frac;
900    dev->last.remainder[1] = y_frac;
901}
902
903/**
904 * Update the motion history for the device and (if appropriate) for its
905 * master device.
906 * @param dev Slave device to update.
907 * @param mask Bit mask of valid valuators to append to history.
908 * @param num Total number of valuators to append to history.
909 * @param ms Current time
910 */
911static void
912updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
913{
914    if (!dev->valuator)
915        return;
916
917    updateMotionHistory(dev, ms, mask, dev->last.valuators);
918    if (dev->u.master)
919    {
920        DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
921        updateMotionHistory(master, ms, mask, dev->last.valuators);
922    }
923}
924
925/**
926 * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
927 * valuators.
928 */
929int
930GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
931    ValuatorMask mask;
932
933    valuator_mask_zero(&mask);
934    return GetKeyboardValuatorEvents(events, pDev, type, key_code, &mask);
935}
936
937
938/**
939 * Returns a set of InternalEvents for KeyPress/KeyRelease, optionally
940 * also with valuator events.
941 *
942 * events is not NULL-terminated; the return value is the number of events.
943 * The DDX is responsible for allocating the event structure in the first
944 * place via GetMaximumEventsNum(), and for freeing it.
945 */
946int
947GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
948                          int key_code, const ValuatorMask *mask_in) {
949    int num_events = 0;
950    CARD32 ms = 0;
951    DeviceEvent *event;
952    RawDeviceEvent *raw;
953    ValuatorMask mask;
954
955    /* refuse events from disabled devices */
956    if (!pDev->enabled)
957        return 0;
958
959    if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
960       (type != KeyPress && type != KeyRelease) ||
961       (key_code < 8 || key_code > 255))
962        return 0;
963
964    num_events = 1;
965
966    events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
967
968    /* Handle core repeating, via press/release/press/release. */
969    if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
970        /* If autorepeating is disabled either globally or just for that key,
971         * or we have a modifier, don't generate a repeat event. */
972        if (!pDev->kbdfeed->ctrl.autoRepeat ||
973            !key_autorepeats(pDev, key_code) ||
974            pDev->key->xkbInfo->desc->map->modmap[key_code])
975            return 0;
976    }
977
978    ms = GetTimeInMillis();
979
980    raw = (RawDeviceEvent*)events->event;
981    events++;
982    num_events++;
983
984    valuator_mask_copy(&mask, mask_in);
985
986    init_raw(pDev, raw, ms, type, key_code);
987    set_raw_valuators(raw, &mask, raw->valuators.data_raw);
988
989    clipValuators(pDev, &mask);
990
991    set_raw_valuators(raw, &mask, raw->valuators.data);
992
993    event = (DeviceEvent*) events->event;
994    init_event(pDev, event, ms);
995    event->detail.key = key_code;
996
997    if (type == KeyPress) {
998        event->type = ET_KeyPress;
999	set_key_down(pDev, key_code, KEY_POSTED);
1000    }
1001    else if (type == KeyRelease) {
1002        event->type = ET_KeyRelease;
1003	set_key_up(pDev, key_code, KEY_POSTED);
1004    }
1005
1006    clipValuators(pDev, &mask);
1007
1008    set_valuators(pDev, event, &mask);
1009
1010    return num_events;
1011}
1012
1013/**
1014 * Initialize an event list and fill with 32 byte sized events.
1015 * This event list is to be passed into GetPointerEvents() and
1016 * GetKeyboardEvents().
1017 *
1018 * @param num_events Number of elements in list.
1019 */
1020EventListPtr
1021InitEventList(int num_events)
1022{
1023    EventListPtr events;
1024    int i;
1025
1026    events = (EventListPtr)calloc(num_events, sizeof(EventList));
1027    if (!events)
1028        return NULL;
1029
1030    for (i = 0; i < num_events; i++)
1031    {
1032        events[i].evlen = sizeof(InternalEvent);
1033        events[i].event = calloc(1, sizeof(InternalEvent));
1034        if (!events[i].event)
1035        {
1036            /* rollback */
1037            while(i--)
1038                free(events[i].event);
1039            free(events);
1040            events = NULL;
1041            break;
1042        }
1043    }
1044
1045    return events;
1046}
1047
1048/**
1049 * Free an event list.
1050 *
1051 * @param list The list to be freed.
1052 * @param num_events Number of elements in list.
1053 */
1054void
1055FreeEventList(EventListPtr list, int num_events)
1056{
1057    if (!list)
1058        return;
1059    while(num_events--)
1060        free(list[num_events].event);
1061    free(list);
1062}
1063
1064static void
1065transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
1066{
1067    struct pixman_f_vector p;
1068
1069    /* p' = M * p in homogeneous coordinates */
1070    p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) :
1071              dev->last.valuators[0]);
1072    p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) :
1073              dev->last.valuators[1]);
1074    p.v[2] = 1.0;
1075
1076    pixman_f_transform_point(&dev->transform, &p);
1077
1078    if (lround(p.v[0]) != dev->last.valuators[0])
1079        valuator_mask_set(mask, 0, lround(p.v[0]));
1080    if (lround(p.v[1]) != dev->last.valuators[1])
1081        valuator_mask_set(mask, 1, lround(p.v[1]));
1082}
1083
1084/**
1085 * Generate a series of InternalEvents (filled into the EventList)
1086 * representing pointer motion, or button presses.
1087 *
1088 * events is not NULL-terminated; the return value is the number of events.
1089 * The DDX is responsible for allocating the event structure in the first
1090 * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
1091 *
1092 * In the generated events rootX/Y will be in absolute screen coords and
1093 * the valuator information in the absolute or relative device coords.
1094 *
1095 * last.valuators[x] of the device is always in absolute device coords.
1096 * last.valuators[x] of the master device is in absolute screen coords.
1097 *
1098 * master->last.valuators[x] for x > 2 is undefined.
1099 */
1100int
1101GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
1102                 int flags, const ValuatorMask *mask_in) {
1103    int num_events = 1;
1104    CARD32 ms;
1105    DeviceEvent *event;
1106    RawDeviceEvent    *raw;
1107    int x = 0, y = 0, /* device coords */
1108        cx, cy; /* only screen coordinates */
1109    float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
1110    ScreenPtr scr = miPointerGetScreen(pDev);
1111    ValuatorMask mask;
1112
1113    /* refuse events from disabled devices */
1114    if (!pDev->enabled)
1115        return 0;
1116
1117    if (!scr)
1118        return 0;
1119
1120    switch (type)
1121    {
1122        case MotionNotify:
1123            if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0)
1124                return 0;
1125            break;
1126        case ButtonPress:
1127        case ButtonRelease:
1128            if (!pDev->button || !buttons)
1129                return 0;
1130            break;
1131        default:
1132            return 0;
1133    }
1134
1135    ms = GetTimeInMillis(); /* before pointer update to help precision */
1136
1137    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
1138
1139    raw = (RawDeviceEvent*)events->event;
1140    events++;
1141    num_events++;
1142
1143    valuator_mask_copy(&mask, mask_in);
1144
1145    init_raw(pDev, raw, ms, type, buttons);
1146    set_raw_valuators(raw, &mask, raw->valuators.data_raw);
1147
1148    if (flags & POINTER_ABSOLUTE)
1149    {
1150        if (flags & POINTER_SCREEN) /* valuators are in screen coords */
1151        {
1152            int scaled;
1153
1154            if (valuator_mask_isset(&mask, 0))
1155            {
1156                scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0),
1157                                             0.0, &x_frac, NULL,
1158                                             pDev->valuator->axes + 0,
1159                                             scr->width);
1160                valuator_mask_set(&mask, 0, scaled);
1161            }
1162            if (valuator_mask_isset(&mask, 1))
1163            {
1164                scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1),
1165                                             0.0, &y_frac, NULL,
1166                                             pDev->valuator->axes + 1,
1167                                             scr->height);
1168                valuator_mask_set(&mask, 1, scaled);
1169            }
1170        }
1171
1172        transformAbsolute(pDev, &mask);
1173        moveAbsolute(pDev, &x, &y, &mask);
1174    } else {
1175        if (flags & POINTER_ACCELERATE) {
1176            /* FIXME: Pointer acceleration only requires X and Y values. This
1177             * should be converted to masked valuators. */
1178            int vals[2];
1179            vals[0] = valuator_mask_isset(&mask, 0) ?
1180                      valuator_mask_get(&mask, 0) : 0;
1181            vals[1] = valuator_mask_isset(&mask, 1) ?
1182                      valuator_mask_get(&mask, 1) : 0;
1183            accelPointer(pDev, 0, 2, vals, ms);
1184
1185            if (valuator_mask_isset(&mask, 0))
1186                valuator_mask_set(&mask, 0, vals[0]);
1187            if (valuator_mask_isset(&mask, 1))
1188                valuator_mask_set(&mask, 1, vals[1]);
1189
1190            /* The pointer acceleration code modifies the fractional part
1191             * in-place, so we need to extract this information first */
1192            x_frac = pDev->last.remainder[0];
1193            y_frac = pDev->last.remainder[1];
1194        }
1195        moveRelative(pDev, &x, &y, &mask);
1196    }
1197
1198    set_raw_valuators(raw, &mask, raw->valuators.data);
1199
1200    positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
1201    updateHistory(pDev, &mask, ms);
1202
1203    /* Update the valuators with the true value sent to the client*/
1204    if (valuator_mask_isset(&mask, 0))
1205        valuator_mask_set(&mask, 0, x);
1206    if (valuator_mask_isset(&mask, 1))
1207        valuator_mask_set(&mask, 1, y);
1208
1209    clipValuators(pDev, &mask);
1210
1211    event = (DeviceEvent*) events->event;
1212    init_event(pDev, event, ms);
1213
1214    if (type == MotionNotify) {
1215        event->type = ET_Motion;
1216        event->detail.button = 0;
1217    }
1218    else {
1219        if (type == ButtonPress) {
1220            event->type = ET_ButtonPress;
1221            set_button_down(pDev, buttons, BUTTON_POSTED);
1222        }
1223        else if (type == ButtonRelease) {
1224            event->type = ET_ButtonRelease;
1225            set_button_up(pDev, buttons, BUTTON_POSTED);
1226        }
1227        event->detail.button = buttons;
1228    }
1229
1230    event->root_x = cx; /* root_x/y always in screen coords */
1231    event->root_y = cy;
1232    event->root_x_frac = cx_frac;
1233    event->root_y_frac = cy_frac;
1234
1235    set_valuators(pDev, event, &mask);
1236
1237    return num_events;
1238}
1239
1240
1241/**
1242 * Generate ProximityIn/ProximityOut InternalEvents, accompanied by
1243 * valuators.
1244 *
1245 * events is not NULL-terminated; the return value is the number of events.
1246 * The DDX is responsible for allocating the event structure in the first
1247 * place via GetMaximumEventsNum(), and for freeing it.
1248 */
1249int
1250GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in)
1251{
1252    int num_events = 1, i;
1253    DeviceEvent *event;
1254    ValuatorMask mask;
1255
1256    /* refuse events from disabled devices */
1257    if (!pDev->enabled)
1258        return 0;
1259
1260    /* Sanity checks. */
1261    if ((type != ProximityIn && type != ProximityOut) || !mask_in)
1262        return 0;
1263    if (!pDev->valuator)
1264        return 0;
1265
1266    valuator_mask_copy(&mask, mask_in);
1267
1268    /* ignore relative axes for proximity. */
1269    for (i = 0; i < valuator_mask_size(&mask); i++)
1270    {
1271        if (valuator_mask_isset(&mask, i) &&
1272            valuator_get_mode(pDev, i) == Relative)
1273            valuator_mask_unset(&mask, i);
1274    }
1275
1276    /* FIXME: posting proximity events with relative valuators only results
1277     * in an empty event, EventToXI() will fail to convert → no event sent
1278     * to client. */
1279
1280    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
1281
1282    event = (DeviceEvent *) events->event;
1283    init_event(pDev, event, GetTimeInMillis());
1284    event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
1285
1286    clipValuators(pDev, &mask);
1287
1288    set_valuators(pDev, event, &mask);
1289
1290    return num_events;
1291}
1292
1293/**
1294 * Synthesize a single motion event for the core pointer.
1295 *
1296 * Used in cursor functions, e.g. when cursor confinement changes, and we need
1297 * to shift the pointer to get it inside the new bounds.
1298 */
1299void
1300PostSyntheticMotion(DeviceIntPtr pDev,
1301                    int x,
1302                    int y,
1303                    int screen,
1304                    unsigned long time)
1305{
1306    DeviceEvent ev;
1307
1308#ifdef PANORAMIX
1309    /* Translate back to the sprite screen since processInputProc
1310       will translate from sprite screen to screen 0 upon reentry
1311       to the DIX layer. */
1312    if (!noPanoramiXExtension) {
1313        x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x;
1314        y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y;
1315    }
1316#endif
1317
1318    memset(&ev, 0, sizeof(DeviceEvent));
1319    init_event(pDev, &ev, time);
1320    ev.root_x = x;
1321    ev.root_y = y;
1322    ev.type = ET_Motion;
1323    ev.time = time;
1324
1325    /* FIXME: MD/SD considerations? */
1326    (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev);
1327}
1328