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