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