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