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