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