exevents.c revision 05b261ec
1/************************************************************ 2 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. 26 27 All Rights Reserved 28 29Permission to use, copy, modify, and distribute this software and its 30documentation for any purpose and without fee is hereby granted, 31provided that the above copyright notice appear in all copies and that 32both that copyright notice and this permission notice appear in 33supporting documentation, and that the name of Hewlett-Packard not be 34used in advertising or publicity pertaining to distribution of the 35software without specific, written prior permission. 36 37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43SOFTWARE. 44 45********************************************************/ 46 47/******************************************************************** 48 * 49 * Routines to register and initialize extension input devices. 50 * This also contains ProcessOtherEvent, the routine called from DDX 51 * to route extension events. 52 * 53 */ 54 55#define NEED_EVENTS 56#ifdef HAVE_DIX_CONFIG_H 57#include <dix-config.h> 58#endif 59 60#include <X11/X.h> 61#include <X11/Xproto.h> 62#include <X11/extensions/XI.h> 63#include <X11/extensions/XIproto.h> 64#include "inputstr.h" 65#include "windowstr.h" 66#include "miscstruct.h" 67#include "region.h" 68#include "exevents.h" 69#include "extnsionst.h" 70#include "extinit.h" /* LookupDeviceIntRec */ 71#include "exglobals.h" 72#include "dixevents.h" /* DeliverFocusedEvent */ 73#include "dixgrabs.h" /* CreateGrab() */ 74#include "scrnintstr.h" 75 76#ifdef XKB 77#include "xkbsrv.h" 78#endif 79 80#define WID(w) ((w) ? ((w)->drawable.id) : 0) 81#define AllModifiersMask ( \ 82 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ 83 Mod3Mask | Mod4Mask | Mod5Mask ) 84#define AllButtonsMask ( \ 85 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) 86#define Motion_Filter(class) (DevicePointerMotionMask | \ 87 (class)->state | (class)->motionMask) 88 89static Bool ShouldFreeInputMasks(WindowPtr /* pWin */ , 90 Bool /* ignoreSelectedEvents */ 91 ); 92static Bool MakeInputMasks(WindowPtr /* pWin */ 93 ); 94 95/************************************************************************** 96 * 97 * Procedures for extension device event routing. 98 * 99 */ 100 101void 102RegisterOtherDevice(DeviceIntPtr device) 103{ 104 device->public.processInputProc = ProcessOtherEvent; 105 device->public.realInputProc = ProcessOtherEvent; 106 (device)->ActivateGrab = ActivateKeyboardGrab; 107 (device)->DeactivateGrab = DeactivateKeyboardGrab; 108} 109 110 /*ARGSUSED*/ void 111ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count) 112{ 113 BYTE *kptr; 114 int i; 115 CARD16 modifiers; 116 CARD16 mask; 117 GrabPtr grab = other->grab; 118 Bool deactivateDeviceGrab = FALSE; 119 int key = 0, bit = 0, rootX, rootY; 120 ButtonClassPtr b = other->button; 121 KeyClassPtr k = other->key; 122 ValuatorClassPtr v = other->valuator; 123 deviceValuator *xV = (deviceValuator *) xE; 124 125 if (xE->u.u.type != DeviceValuator) { 126 /* Other types already have root{X,Y} filled in. */ 127 if (xE->u.u.type == DeviceKeyPress || 128 xE->u.u.type == DeviceKeyRelease) { 129 GetSpritePosition(&rootX, &rootY); 130 xE->u.keyButtonPointer.rootX = rootX; 131 xE->u.keyButtonPointer.rootY = rootY; 132 } 133 134 key = xE->u.u.detail; 135 NoticeEventTime(xE); 136 xE->u.keyButtonPointer.state = inputInfo.keyboard->key->state | 137 inputInfo.pointer->button->state; 138 bit = 1 << (key & 7); 139 } 140 if (DeviceEventCallback) { 141 DeviceEventInfoRec eventinfo; 142 143 eventinfo.events = (xEventPtr) xE; 144 eventinfo.count = count; 145 CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo); 146 } 147 for (i = 1; i < count; i++) 148 if ((++xV)->type == DeviceValuator) { 149 int first = xV->first_valuator; 150 int *axisvals; 151 152 if (xV->num_valuators 153 && (!v 154 || (xV->num_valuators 155 && (first + xV->num_valuators > v->numAxes)))) 156 FatalError("Bad valuators reported for device %s\n", 157 other->name); 158 xV->device_state = 0; 159 if (k) 160 xV->device_state |= k->state; 161 if (b) 162 xV->device_state |= b->state; 163 if (v && v->axisVal) { 164 axisvals = v->axisVal; 165 switch (xV->num_valuators) { 166 case 6: 167 *(axisvals + first + 5) = xV->valuator5; 168 case 5: 169 *(axisvals + first + 4) = xV->valuator4; 170 case 4: 171 *(axisvals + first + 3) = xV->valuator3; 172 case 3: 173 *(axisvals + first + 2) = xV->valuator2; 174 case 2: 175 *(axisvals + first + 1) = xV->valuator1; 176 case 1: 177 *(axisvals + first) = xV->valuator0; 178 case 0: 179 default: 180 break; 181 } 182 } 183 } 184 185 if (xE->u.u.type == DeviceKeyPress) { 186 if (!k) 187 return; 188 189 modifiers = k->modifierMap[key]; 190 kptr = &k->down[key >> 3]; 191 if (*kptr & bit) { /* allow ddx to generate multiple downs */ 192 if (!modifiers) { 193 xE->u.u.type = DeviceKeyRelease; 194 ProcessOtherEvent(xE, other, count); 195 xE->u.u.type = DeviceKeyPress; 196 /* release can have side effects, don't fall through */ 197 ProcessOtherEvent(xE, other, count); 198 } 199 return; 200 } 201 if (other->valuator) 202 other->valuator->motionHintWindow = NullWindow; 203 *kptr |= bit; 204 k->prev_state = k->state; 205 for (i = 0, mask = 1; modifiers; i++, mask <<= 1) { 206 if (mask & modifiers) { 207 /* This key affects modifier "i" */ 208 k->modifierKeyCount[i]++; 209 k->state |= mask; 210 modifiers &= ~mask; 211 } 212 } 213 if (!grab && CheckDeviceGrabs(other, xE, 0, count)) { 214 other->activatingKey = key; 215 return; 216 } 217 } else if (xE->u.u.type == DeviceKeyRelease) { 218 if (!k) 219 return; 220 221 kptr = &k->down[key >> 3]; 222 if (!(*kptr & bit)) /* guard against duplicates */ 223 return; 224 modifiers = k->modifierMap[key]; 225 if (other->valuator) 226 other->valuator->motionHintWindow = NullWindow; 227 *kptr &= ~bit; 228 k->prev_state = k->state; 229 for (i = 0, mask = 1; modifiers; i++, mask <<= 1) { 230 if (mask & modifiers) { 231 /* This key affects modifier "i" */ 232 if (--k->modifierKeyCount[i] <= 0) { 233 k->modifierKeyCount[i] = 0; 234 k->state &= ~mask; 235 } 236 modifiers &= ~mask; 237 } 238 } 239 240 if (other->fromPassiveGrab && (key == other->activatingKey)) 241 deactivateDeviceGrab = TRUE; 242 } else if (xE->u.u.type == DeviceButtonPress) { 243 if (!b) 244 return; 245 246 kptr = &b->down[key >> 3]; 247 *kptr |= bit; 248 if (other->valuator) 249 other->valuator->motionHintWindow = NullWindow; 250 b->buttonsDown++; 251 b->motionMask = DeviceButtonMotionMask; 252 xE->u.u.detail = key; 253 if (xE->u.u.detail == 0) 254 return; 255 if (xE->u.u.detail <= 5) 256 b->state |= (Button1Mask >> 1) << xE->u.u.detail; 257 SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify); 258 if (!grab) 259 if (CheckDeviceGrabs(other, xE, 0, count)) 260 /* if a passive grab was activated, the event has been sent 261 * already */ 262 return; 263 264 } else if (xE->u.u.type == DeviceButtonRelease) { 265 if (!b) 266 return; 267 268 kptr = &b->down[key >> 3]; 269 *kptr &= ~bit; 270 if (other->valuator) 271 other->valuator->motionHintWindow = NullWindow; 272 if (b->buttonsDown >= 1 && !--b->buttonsDown) 273 b->motionMask = 0; 274 xE->u.u.detail = key; 275 if (xE->u.u.detail == 0) 276 return; 277 if (xE->u.u.detail <= 5) 278 b->state &= ~((Button1Mask >> 1) << xE->u.u.detail); 279 SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify); 280 if (!b->state && other->fromPassiveGrab) 281 deactivateDeviceGrab = TRUE; 282 } else if (xE->u.u.type == ProximityIn) 283 other->valuator->mode &= ~OutOfProximity; 284 else if (xE->u.u.type == ProximityOut) 285 other->valuator->mode |= OutOfProximity; 286 287 if (grab) 288 DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count); 289 else if (other->focus) 290 DeliverFocusedEvent(other, xE, GetSpriteWindow(), count); 291 else 292 DeliverDeviceEvents(GetSpriteWindow(), xE, NullGrab, NullWindow, 293 other, count); 294 295 if (deactivateDeviceGrab == TRUE) 296 (*other->DeactivateGrab) (other); 297} 298 299_X_EXPORT int 300InitProximityClassDeviceStruct(DeviceIntPtr dev) 301{ 302 ProximityClassPtr proxc; 303 304 proxc = (ProximityClassPtr) xalloc(sizeof(ProximityClassRec)); 305 if (!proxc) 306 return FALSE; 307 dev->proximity = proxc; 308 return TRUE; 309} 310 311_X_EXPORT void 312InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval, 313 int resolution, int min_res, int max_res) 314{ 315 AxisInfoPtr ax; 316 317 if (!dev || !dev->valuator) 318 return; 319 320 ax = dev->valuator->axes + axnum; 321 322 ax->min_value = minval; 323 ax->max_value = maxval; 324 ax->resolution = resolution; 325 ax->min_resolution = min_res; 326 ax->max_resolution = max_res; 327} 328 329static void 330FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k, 331 ButtonClassPtr b, ValuatorClassPtr v, int first) 332{ 333 ev->type = DeviceStateNotify; 334 ev->deviceid = dev->id; 335 ev->time = currentTime.milliseconds; 336 ev->classes_reported = 0; 337 ev->num_keys = 0; 338 ev->num_buttons = 0; 339 ev->num_valuators = 0; 340 341 if (b) { 342 ev->classes_reported |= (1 << ButtonClass); 343 ev->num_buttons = b->numButtons; 344 memmove((char *)&ev->buttons[0], (char *)b->down, 4); 345 } else if (k) { 346 ev->classes_reported |= (1 << KeyClass); 347 ev->num_keys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode; 348 memmove((char *)&ev->keys[0], (char *)k->down, 4); 349 } 350 if (v) { 351 int nval = v->numAxes - first; 352 353 ev->classes_reported |= (1 << ValuatorClass); 354 ev->classes_reported |= (dev->valuator->mode << ModeBitsShift); 355 ev->num_valuators = nval < 3 ? nval : 3; 356 switch (ev->num_valuators) { 357 case 3: 358 ev->valuator2 = v->axisVal[first + 2]; 359 case 2: 360 ev->valuator1 = v->axisVal[first + 1]; 361 case 1: 362 ev->valuator0 = v->axisVal[first]; 363 break; 364 } 365 } 366} 367 368static void 369FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v, 370 int first) 371{ 372 int nval = v->numAxes - first; 373 374 ev->type = DeviceValuator; 375 ev->deviceid = dev->id; 376 ev->num_valuators = nval < 3 ? nval : 3; 377 ev->first_valuator = first; 378 switch (ev->num_valuators) { 379 case 3: 380 ev->valuator2 = v->axisVal[first + 2]; 381 case 2: 382 ev->valuator1 = v->axisVal[first + 1]; 383 case 1: 384 ev->valuator0 = v->axisVal[first]; 385 break; 386 } 387 first += ev->num_valuators; 388} 389 390void 391DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, 392 WindowPtr pWin) 393{ 394 deviceFocus event; 395 396 if (type == FocusIn) 397 type = DeviceFocusIn; 398 else 399 type = DeviceFocusOut; 400 401 event.deviceid = dev->id; 402 event.mode = mode; 403 event.type = type; 404 event.detail = detail; 405 event.window = pWin->drawable.id; 406 event.time = currentTime.milliseconds; 407 408 (void)DeliverEventsToWindow(pWin, (xEvent *) & event, 1, 409 DeviceFocusChangeMask, NullGrab, dev->id); 410 411 if ((type == DeviceFocusIn) && 412 (wOtherInputMasks(pWin)) && 413 (wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask)) 414 { 415 int evcount = 1; 416 deviceStateNotify *ev, *sev; 417 deviceKeyStateNotify *kev; 418 deviceButtonStateNotify *bev; 419 420 KeyClassPtr k; 421 ButtonClassPtr b; 422 ValuatorClassPtr v; 423 int nval = 0, nkeys = 0, nbuttons = 0, first = 0; 424 425 if ((b = dev->button) != NULL) { 426 nbuttons = b->numButtons; 427 if (nbuttons > 32) 428 evcount++; 429 } 430 if ((k = dev->key) != NULL) { 431 nkeys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode; 432 if (nkeys > 32) 433 evcount++; 434 if (nbuttons > 0) { 435 evcount++; 436 } 437 } 438 if ((v = dev->valuator) != NULL) { 439 nval = v->numAxes; 440 441 if (nval > 3) 442 evcount++; 443 if (nval > 6) { 444 if (!(k && b)) 445 evcount++; 446 if (nval > 9) 447 evcount += ((nval - 7) / 3); 448 } 449 } 450 451 sev = ev = (deviceStateNotify *) xalloc(evcount * sizeof(xEvent)); 452 FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first); 453 454 if (b != NULL) { 455 FixDeviceStateNotify(dev, ev++, NULL, b, v, first); 456 first += 3; 457 nval -= 3; 458 if (nbuttons > 32) { 459 (ev - 1)->deviceid |= MORE_EVENTS; 460 bev = (deviceButtonStateNotify *) ev++; 461 bev->type = DeviceButtonStateNotify; 462 bev->deviceid = dev->id; 463 memmove((char *)&bev->buttons[0], (char *)&b->down[4], 28); 464 } 465 if (nval > 0) { 466 (ev - 1)->deviceid |= MORE_EVENTS; 467 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first); 468 first += 3; 469 nval -= 3; 470 } 471 } 472 473 if (k != NULL) { 474 FixDeviceStateNotify(dev, ev++, k, NULL, v, first); 475 first += 3; 476 nval -= 3; 477 if (nkeys > 32) { 478 (ev - 1)->deviceid |= MORE_EVENTS; 479 kev = (deviceKeyStateNotify *) ev++; 480 kev->type = DeviceKeyStateNotify; 481 kev->deviceid = dev->id; 482 memmove((char *)&kev->keys[0], (char *)&k->down[4], 28); 483 } 484 if (nval > 0) { 485 (ev - 1)->deviceid |= MORE_EVENTS; 486 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first); 487 first += 3; 488 nval -= 3; 489 } 490 } 491 492 while (nval > 0) { 493 FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first); 494 first += 3; 495 nval -= 3; 496 if (nval > 0) { 497 (ev - 1)->deviceid |= MORE_EVENTS; 498 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first); 499 first += 3; 500 nval -= 3; 501 } 502 } 503 504 (void)DeliverEventsToWindow(pWin, (xEvent *) sev, evcount, 505 DeviceStateNotifyMask, NullGrab, dev->id); 506 xfree(sev); 507 } 508} 509 510int 511GrabButton(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode, 512 BYTE other_devices_mode, CARD16 modifiers, 513 DeviceIntPtr modifier_device, CARD8 button, Window grabWindow, 514 BOOL ownerEvents, Cursor rcursor, Window rconfineTo, Mask eventMask) 515{ 516 WindowPtr pWin, confineTo; 517 CursorPtr cursor; 518 GrabPtr grab; 519 int rc; 520 521 if ((this_device_mode != GrabModeSync) && 522 (this_device_mode != GrabModeAsync)) { 523 client->errorValue = this_device_mode; 524 return BadValue; 525 } 526 if ((other_devices_mode != GrabModeSync) && 527 (other_devices_mode != GrabModeAsync)) { 528 client->errorValue = other_devices_mode; 529 return BadValue; 530 } 531 if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) { 532 client->errorValue = modifiers; 533 return BadValue; 534 } 535 if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) { 536 client->errorValue = ownerEvents; 537 return BadValue; 538 } 539 rc = dixLookupWindow(&pWin, grabWindow, client, DixUnknownAccess); 540 if (rc != Success) 541 return rc; 542 if (rconfineTo == None) 543 confineTo = NullWindow; 544 else { 545 rc = dixLookupWindow(&confineTo, rconfineTo, client, DixUnknownAccess); 546 if (rc != Success) 547 return rc; 548 } 549 if (rcursor == None) 550 cursor = NullCursor; 551 else { 552 cursor = (CursorPtr) LookupIDByType(rcursor, RT_CURSOR); 553 if (!cursor) { 554 client->errorValue = rcursor; 555 return BadCursor; 556 } 557 } 558 559 grab = CreateGrab(client->index, dev, pWin, eventMask, 560 (Bool) ownerEvents, (Bool) this_device_mode, 561 (Bool) other_devices_mode, modifier_device, modifiers, 562 DeviceButtonPress, button, confineTo, cursor); 563 if (!grab) 564 return BadAlloc; 565 return AddPassiveGrabToList(grab); 566} 567 568int 569GrabKey(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode, 570 BYTE other_devices_mode, CARD16 modifiers, 571 DeviceIntPtr modifier_device, CARD8 key, Window grabWindow, 572 BOOL ownerEvents, Mask mask) 573{ 574 WindowPtr pWin; 575 GrabPtr grab; 576 KeyClassPtr k = dev->key; 577 int rc; 578 579 if (k == NULL) 580 return BadMatch; 581 if ((other_devices_mode != GrabModeSync) && 582 (other_devices_mode != GrabModeAsync)) { 583 client->errorValue = other_devices_mode; 584 return BadValue; 585 } 586 if ((this_device_mode != GrabModeSync) && 587 (this_device_mode != GrabModeAsync)) { 588 client->errorValue = this_device_mode; 589 return BadValue; 590 } 591 if (((key > k->curKeySyms.maxKeyCode) || (key < k->curKeySyms.minKeyCode)) 592 && (key != AnyKey)) { 593 client->errorValue = key; 594 return BadValue; 595 } 596 if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) { 597 client->errorValue = modifiers; 598 return BadValue; 599 } 600 if ((ownerEvents != xTrue) && (ownerEvents != xFalse)) { 601 client->errorValue = ownerEvents; 602 return BadValue; 603 } 604 rc = dixLookupWindow(&pWin, grabWindow, client, DixUnknownAccess); 605 if (rc != Success) 606 return rc; 607 608 grab = CreateGrab(client->index, dev, pWin, 609 mask, ownerEvents, this_device_mode, other_devices_mode, 610 modifier_device, modifiers, DeviceKeyPress, key, 611 NullWindow, NullCursor); 612 if (!grab) 613 return BadAlloc; 614 return AddPassiveGrabToList(grab); 615} 616 617int 618SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client, 619 Mask mask, Mask exclusivemasks, Mask validmasks) 620{ 621 int mskidx = dev->id; 622 int i, ret; 623 Mask check; 624 InputClientsPtr others; 625 626 if (mask & ~validmasks) { 627 client->errorValue = mask; 628 return BadValue; 629 } 630 check = (mask & exclusivemasks); 631 if (wOtherInputMasks(pWin)) { 632 if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { /* It is illegal for two different 633 * clients to select on any of the 634 * events for maskcheck. However, 635 * it is OK, for some client to 636 * continue selecting on one of those 637 * events. */ 638 for (others = wOtherInputMasks(pWin)->inputClients; others; 639 others = others->next) { 640 if (!SameClient(others, client) && (check & 641 others->mask[mskidx])) 642 return BadAccess; 643 } 644 } 645 for (others = wOtherInputMasks(pWin)->inputClients; others; 646 others = others->next) { 647 if (SameClient(others, client)) { 648 check = others->mask[mskidx]; 649 others->mask[mskidx] = mask; 650 if (mask == 0) { 651 for (i = 0; i < EMASKSIZE; i++) 652 if (i != mskidx && others->mask[i] != 0) 653 break; 654 if (i == EMASKSIZE) { 655 RecalculateDeviceDeliverableEvents(pWin); 656 if (ShouldFreeInputMasks(pWin, FALSE)) 657 FreeResource(others->resource, RT_NONE); 658 return Success; 659 } 660 } 661 goto maskSet; 662 } 663 } 664 } 665 check = 0; 666 if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success) 667 return ret; 668 maskSet: 669 if (dev->valuator) 670 if ((dev->valuator->motionHintWindow == pWin) && 671 (mask & DevicePointerMotionHintMask) && 672 !(check & DevicePointerMotionHintMask) && !dev->grab) 673 dev->valuator->motionHintWindow = NullWindow; 674 RecalculateDeviceDeliverableEvents(pWin); 675 return Success; 676} 677 678int 679AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx) 680{ 681 InputClientsPtr others; 682 683 if (!pWin->optional && !MakeWindowOptional(pWin)) 684 return BadAlloc; 685 others = (InputClients *) xalloc(sizeof(InputClients)); 686 if (!others) 687 return BadAlloc; 688 if (!pWin->optional->inputMasks && !MakeInputMasks(pWin)) 689 return BadAlloc; 690 bzero((char *)&others->mask[0], sizeof(Mask) * EMASKSIZE); 691 others->mask[mskidx] = mask; 692 others->resource = FakeClientID(client->index); 693 others->next = pWin->optional->inputMasks->inputClients; 694 pWin->optional->inputMasks->inputClients = others; 695 if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin)) 696 return BadAlloc; 697 return Success; 698} 699 700static Bool 701MakeInputMasks(WindowPtr pWin) 702{ 703 struct _OtherInputMasks *imasks; 704 705 imasks = (struct _OtherInputMasks *) 706 xalloc(sizeof(struct _OtherInputMasks)); 707 if (!imasks) 708 return FALSE; 709 bzero((char *)imasks, sizeof(struct _OtherInputMasks)); 710 pWin->optional->inputMasks = imasks; 711 return TRUE; 712} 713 714void 715RecalculateDeviceDeliverableEvents(WindowPtr pWin) 716{ 717 InputClientsPtr others; 718 struct _OtherInputMasks *inputMasks; /* default: NULL */ 719 WindowPtr pChild, tmp; 720 int i; 721 722 pChild = pWin; 723 while (1) { 724 if ((inputMasks = wOtherInputMasks(pChild)) != 0) { 725 for (others = inputMasks->inputClients; others; 726 others = others->next) { 727 for (i = 0; i < EMASKSIZE; i++) 728 inputMasks->inputEvents[i] |= others->mask[i]; 729 } 730 for (i = 0; i < EMASKSIZE; i++) 731 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i]; 732 for (tmp = pChild->parent; tmp; tmp = tmp->parent) 733 if (wOtherInputMasks(tmp)) 734 for (i = 0; i < EMASKSIZE; i++) 735 inputMasks->deliverableEvents[i] |= 736 (wOtherInputMasks(tmp)->deliverableEvents[i] 737 & ~inputMasks-> 738 dontPropagateMask[i] & PropagateMask[i]); 739 } 740 if (pChild->firstChild) { 741 pChild = pChild->firstChild; 742 continue; 743 } 744 while (!pChild->nextSib && (pChild != pWin)) 745 pChild = pChild->parent; 746 if (pChild == pWin) 747 break; 748 pChild = pChild->nextSib; 749 } 750} 751 752int 753InputClientGone(WindowPtr pWin, XID id) 754{ 755 InputClientsPtr other, prev; 756 757 if (!wOtherInputMasks(pWin)) 758 return (Success); 759 prev = 0; 760 for (other = wOtherInputMasks(pWin)->inputClients; other; 761 other = other->next) { 762 if (other->resource == id) { 763 if (prev) { 764 prev->next = other->next; 765 xfree(other); 766 } else if (!(other->next)) { 767 if (ShouldFreeInputMasks(pWin, TRUE)) { 768 wOtherInputMasks(pWin)->inputClients = other->next; 769 xfree(wOtherInputMasks(pWin)); 770 pWin->optional->inputMasks = (OtherInputMasks *) NULL; 771 CheckWindowOptionalNeed(pWin); 772 xfree(other); 773 } else { 774 other->resource = FakeClientID(0); 775 if (!AddResource(other->resource, RT_INPUTCLIENT, 776 (pointer) pWin)) 777 return BadAlloc; 778 } 779 } else { 780 wOtherInputMasks(pWin)->inputClients = other->next; 781 xfree(other); 782 } 783 RecalculateDeviceDeliverableEvents(pWin); 784 return (Success); 785 } 786 prev = other; 787 } 788 FatalError("client not on device event list"); 789} 790 791int 792SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, 793 xEvent * ev, Mask mask, int count) 794{ 795 WindowPtr pWin; 796 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 797 WindowPtr spriteWin = GetSpriteWindow(); 798 799 if (dest == PointerWindow) 800 pWin = spriteWin; 801 else if (dest == InputFocus) { 802 WindowPtr inputFocus; 803 804 if (!d->focus) 805 inputFocus = spriteWin; 806 else 807 inputFocus = d->focus->win; 808 809 if (inputFocus == FollowKeyboardWin) 810 inputFocus = inputInfo.keyboard->focus->win; 811 812 if (inputFocus == NoneWin) 813 return Success; 814 815 /* If the input focus is PointerRootWin, send the event to where 816 * the pointer is if possible, then perhaps propogate up to root. */ 817 if (inputFocus == PointerRootWin) 818 inputFocus = GetCurrentRootWindow(); 819 820 if (IsParent(inputFocus, spriteWin)) { 821 effectiveFocus = inputFocus; 822 pWin = spriteWin; 823 } else 824 effectiveFocus = pWin = inputFocus; 825 } else 826 dixLookupWindow(&pWin, dest, client, DixUnknownAccess); 827 if (!pWin) 828 return BadWindow; 829 if ((propagate != xFalse) && (propagate != xTrue)) { 830 client->errorValue = propagate; 831 return BadValue; 832 } 833 ev->u.u.type |= 0x80; 834 if (propagate) { 835 for (; pWin; pWin = pWin->parent) { 836 if (DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id)) 837 return Success; 838 if (pWin == effectiveFocus) 839 return Success; 840 if (wOtherInputMasks(pWin)) 841 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id]; 842 if (!mask) 843 break; 844 } 845 } else 846 (void)(DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id)); 847 return Success; 848} 849 850int 851SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map) 852{ 853 int i; 854 ButtonClassPtr b = dev->button; 855 856 if (b == NULL) 857 return BadMatch; 858 859 if (nElts != b->numButtons) { 860 client->errorValue = nElts; 861 return BadValue; 862 } 863 if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue)) 864 return BadValue; 865 for (i = 0; i < nElts; i++) 866 if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1)) 867 return MappingBusy; 868 for (i = 0; i < nElts; i++) 869 b->map[i + 1] = map[i]; 870 return Success; 871} 872 873int 874SetModifierMapping(ClientPtr client, DeviceIntPtr dev, int len, int rlen, 875 int numKeyPerModifier, KeyCode * inputMap, KeyClassPtr * k) 876{ 877 KeyCode *map = NULL; 878 int inputMapLen; 879 int i; 880 881 *k = dev->key; 882 if (*k == NULL) 883 return BadMatch; 884 if (len != ((numKeyPerModifier << 1) + rlen)) 885 return BadLength; 886 887 inputMapLen = 8 * numKeyPerModifier; 888 889 /* 890 * Now enforce the restriction that "all of the non-zero keycodes must be 891 * in the range specified by min-keycode and max-keycode in the 892 * connection setup (else a Value error)" 893 */ 894 i = inputMapLen; 895 while (i--) { 896 if (inputMap[i] 897 && (inputMap[i] < (*k)->curKeySyms.minKeyCode 898 || inputMap[i] > (*k)->curKeySyms.maxKeyCode)) { 899 client->errorValue = inputMap[i]; 900 return -1; /* BadValue collides with MappingFailed */ 901 } 902 } 903 904 /* 905 * Now enforce the restriction that none of the old or new 906 * modifier keys may be down while we change the mapping, and 907 * that the DDX layer likes the choice. 908 */ 909 if (!AllModifierKeysAreUp(dev, (*k)->modifierKeyMap, 910 (int)(*k)->maxKeysPerModifier, inputMap, 911 (int)numKeyPerModifier) 912 || !AllModifierKeysAreUp(dev, inputMap, (int)numKeyPerModifier, 913 (*k)->modifierKeyMap, 914 (int)(*k)->maxKeysPerModifier)) { 915 return MappingBusy; 916 } else { 917 for (i = 0; i < inputMapLen; i++) { 918 if (inputMap[i] && !LegalModifier(inputMap[i], dev)) { 919 return MappingFailed; 920 } 921 } 922 } 923 924 /* 925 * Now build the keyboard's modifier bitmap from the 926 * list of keycodes. 927 */ 928 if (inputMapLen) { 929 map = (KeyCode *) xalloc(inputMapLen); 930 if (!map) 931 return BadAlloc; 932 } 933 if ((*k)->modifierKeyMap) 934 xfree((*k)->modifierKeyMap); 935 if (inputMapLen) { 936 (*k)->modifierKeyMap = map; 937 memmove((char *)(*k)->modifierKeyMap, (char *)inputMap, inputMapLen); 938 } else 939 (*k)->modifierKeyMap = NULL; 940 941 (*k)->maxKeysPerModifier = numKeyPerModifier; 942 for (i = 0; i < MAP_LENGTH; i++) 943 (*k)->modifierMap[i] = 0; 944 for (i = 0; i < inputMapLen; i++) 945 if (inputMap[i]) { 946 (*k)->modifierMap[inputMap[i]] 947 |= (1 << (i / (*k)->maxKeysPerModifier)); 948 } 949 950 return (MappingSuccess); 951} 952 953void 954SendDeviceMappingNotify(ClientPtr client, CARD8 request, 955 KeyCode firstKeyCode, CARD8 count, DeviceIntPtr dev) 956{ 957 xEvent event; 958 deviceMappingNotify *ev = (deviceMappingNotify *) & event; 959 960 ev->type = DeviceMappingNotify; 961 ev->request = request; 962 ev->deviceid = dev->id; 963 ev->time = currentTime.milliseconds; 964 if (request == MappingKeyboard) { 965 ev->firstKeyCode = firstKeyCode; 966 ev->count = count; 967 } 968 969#ifdef XKB 970 if (request == MappingKeyboard || request == MappingModifier) 971 XkbApplyMappingChange(dev, request, firstKeyCode, count, client); 972#endif 973 974 SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) ev, 1); 975} 976 977int 978ChangeKeyMapping(ClientPtr client, 979 DeviceIntPtr dev, 980 unsigned len, 981 int type, 982 KeyCode firstKeyCode, 983 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map) 984{ 985 KeySymsRec keysyms; 986 KeyClassPtr k = dev->key; 987 988 if (k == NULL) 989 return (BadMatch); 990 991 if (len != (keyCodes * keySymsPerKeyCode)) 992 return BadLength; 993 994 if ((firstKeyCode < k->curKeySyms.minKeyCode) || 995 (firstKeyCode + keyCodes - 1 > k->curKeySyms.maxKeyCode)) { 996 client->errorValue = firstKeyCode; 997 return BadValue; 998 } 999 if (keySymsPerKeyCode == 0) { 1000 client->errorValue = 0; 1001 return BadValue; 1002 } 1003 keysyms.minKeyCode = firstKeyCode; 1004 keysyms.maxKeyCode = firstKeyCode + keyCodes - 1; 1005 keysyms.mapWidth = keySymsPerKeyCode; 1006 keysyms.map = map; 1007 if (!SetKeySymsMap(&k->curKeySyms, &keysyms)) 1008 return BadAlloc; 1009 SendDeviceMappingNotify(client, MappingKeyboard, firstKeyCode, keyCodes, dev); 1010 return client->noClientException; 1011} 1012 1013static void 1014DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev) 1015{ 1016 WindowPtr parent; 1017 1018 /* Deactivate any grabs performed on this window, before making 1019 * any input focus changes. 1020 * Deactivating a device grab should cause focus events. */ 1021 1022 if (dev->grab && (dev->grab->window == pWin)) 1023 (*dev->DeactivateGrab) (dev); 1024 1025 /* If the focus window is a root window (ie. has no parent) 1026 * then don't delete the focus from it. */ 1027 1028 if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) { 1029 int focusEventMode = NotifyNormal; 1030 1031 /* If a grab is in progress, then alter the mode of focus events. */ 1032 1033 if (dev->grab) 1034 focusEventMode = NotifyWhileGrabbed; 1035 1036 switch (dev->focus->revert) { 1037 case RevertToNone: 1038 DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 1039 dev->focus->win = NoneWin; 1040 dev->focus->traceGood = 0; 1041 break; 1042 case RevertToParent: 1043 parent = pWin; 1044 do { 1045 parent = parent->parent; 1046 dev->focus->traceGood--; 1047 } 1048 while (!parent->realized); 1049 DoFocusEvents(dev, pWin, parent, focusEventMode); 1050 dev->focus->win = parent; 1051 dev->focus->revert = RevertToNone; 1052 break; 1053 case RevertToPointerRoot: 1054 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode); 1055 dev->focus->win = PointerRootWin; 1056 dev->focus->traceGood = 0; 1057 break; 1058 case RevertToFollowKeyboard: 1059 if (inputInfo.keyboard->focus->win) { 1060 DoFocusEvents(dev, pWin, inputInfo.keyboard->focus->win, 1061 focusEventMode); 1062 dev->focus->win = FollowKeyboardWin; 1063 dev->focus->traceGood = 0; 1064 } else { 1065 DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 1066 dev->focus->win = NoneWin; 1067 dev->focus->traceGood = 0; 1068 } 1069 break; 1070 } 1071 } 1072 1073 if (dev->valuator) 1074 if (dev->valuator->motionHintWindow == pWin) 1075 dev->valuator->motionHintWindow = NullWindow; 1076} 1077 1078void 1079DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources) 1080{ 1081 int i; 1082 DeviceIntPtr dev; 1083 InputClientsPtr ic; 1084 struct _OtherInputMasks *inputMasks; 1085 1086 for (dev = inputInfo.devices; dev; dev = dev->next) { 1087 if (dev == inputInfo.pointer || dev == inputInfo.keyboard) 1088 continue; 1089 DeleteDeviceFromAnyExtEvents(pWin, dev); 1090 } 1091 1092 for (dev = inputInfo.off_devices; dev; dev = dev->next) 1093 DeleteDeviceFromAnyExtEvents(pWin, dev); 1094 1095 if (freeResources) 1096 while ((inputMasks = wOtherInputMasks(pWin)) != 0) { 1097 ic = inputMasks->inputClients; 1098 for (i = 0; i < EMASKSIZE; i++) 1099 inputMasks->dontPropagateMask[i] = 0; 1100 FreeResource(ic->resource, RT_NONE); 1101 } 1102} 1103 1104int 1105MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask) 1106{ 1107 DeviceIntPtr dev; 1108 1109 dev = LookupDeviceIntRec(pEvents->deviceid & DEVICE_BITS); 1110 if (!dev) 1111 return 0; 1112 1113 if (pEvents->type == DeviceMotionNotify) { 1114 if (mask & DevicePointerMotionHintMask) { 1115 if (WID(dev->valuator->motionHintWindow) == pEvents->event) { 1116 return 1; /* don't send, but pretend we did */ 1117 } 1118 pEvents->detail = NotifyHint; 1119 } else { 1120 pEvents->detail = NotifyNormal; 1121 } 1122 } 1123 return (0); 1124} 1125 1126void 1127CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, 1128 deviceKeyButtonPointer * xE, GrabPtr grab, 1129 ClientPtr client, Mask deliveryMask) 1130{ 1131 DeviceIntPtr dev; 1132 1133 dev = LookupDeviceIntRec(xE->deviceid & DEVICE_BITS); 1134 if (!dev) 1135 return; 1136 1137 if (type == DeviceMotionNotify) 1138 dev->valuator->motionHintWindow = pWin; 1139 else if ((type == DeviceButtonPress) && (!grab) && 1140 (deliveryMask & DeviceButtonGrabMask)) { 1141 GrabRec tempGrab; 1142 1143 tempGrab.device = dev; 1144 tempGrab.resource = client->clientAsMask; 1145 tempGrab.window = pWin; 1146 tempGrab.ownerEvents = 1147 (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE; 1148 tempGrab.eventMask = deliveryMask; 1149 tempGrab.keyboardMode = GrabModeAsync; 1150 tempGrab.pointerMode = GrabModeAsync; 1151 tempGrab.confineTo = NullWindow; 1152 tempGrab.cursor = NullCursor; 1153 (*dev->ActivateGrab) (dev, &tempGrab, currentTime, TRUE); 1154 } 1155} 1156 1157static Mask 1158DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client) 1159{ 1160 InputClientsPtr other; 1161 1162 if (!wOtherInputMasks(pWin)) 1163 return 0; 1164 for (other = wOtherInputMasks(pWin)->inputClients; other; 1165 other = other->next) { 1166 if (SameClient(other, client)) 1167 return other->mask[dev->id]; 1168 } 1169 return 0; 1170} 1171 1172void 1173MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client) 1174{ 1175 WindowPtr pWin; 1176 GrabPtr grab = dev->grab; 1177 1178 pWin = dev->valuator->motionHintWindow; 1179 1180 if ((grab && SameClient(grab, client) && 1181 ((grab->eventMask & DevicePointerMotionHintMask) || 1182 (grab->ownerEvents && 1183 (DeviceEventMaskForClient(dev, pWin, client) & 1184 DevicePointerMotionHintMask)))) || 1185 (!grab && 1186 (DeviceEventMaskForClient(dev, pWin, client) & 1187 DevicePointerMotionHintMask))) 1188 dev->valuator->motionHintWindow = NullWindow; 1189} 1190 1191int 1192DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask, 1193 int maskndx) 1194{ 1195 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 1196 1197 if (mask & ~PropagateMask[maskndx]) { 1198 client->errorValue = mask; 1199 return BadValue; 1200 } 1201 1202 if (mask == 0) { 1203 if (inputMasks) 1204 inputMasks->dontPropagateMask[maskndx] = mask; 1205 } else { 1206 if (!inputMasks) 1207 AddExtensionClient(pWin, client, 0, 0); 1208 inputMasks = wOtherInputMasks(pWin); 1209 inputMasks->dontPropagateMask[maskndx] = mask; 1210 } 1211 RecalculateDeviceDeliverableEvents(pWin); 1212 if (ShouldFreeInputMasks(pWin, FALSE)) 1213 FreeResource(inputMasks->inputClients->resource, RT_NONE); 1214 return Success; 1215} 1216 1217static Bool 1218ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents) 1219{ 1220 int i; 1221 Mask allInputEventMasks = 0; 1222 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 1223 1224 for (i = 0; i < EMASKSIZE; i++) 1225 allInputEventMasks |= inputMasks->dontPropagateMask[i]; 1226 if (!ignoreSelectedEvents) 1227 for (i = 0; i < EMASKSIZE; i++) 1228 allInputEventMasks |= inputMasks->inputEvents[i]; 1229 if (allInputEventMasks == 0) 1230 return TRUE; 1231 else 1232 return FALSE; 1233} 1234 1235/*********************************************************************** 1236 * 1237 * Walk through the window tree, finding all clients that want to know 1238 * about the Event. 1239 * 1240 */ 1241 1242static void 1243FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask, 1244 xEvent * ev, int count) 1245{ 1246 WindowPtr p2; 1247 1248 while (p1) { 1249 p2 = p1->firstChild; 1250 (void)DeliverEventsToWindow(p1, ev, count, mask, NullGrab, dev->id); 1251 FindInterestedChildren(dev, p2, mask, ev, count); 1252 p1 = p1->nextSib; 1253 } 1254} 1255 1256/*********************************************************************** 1257 * 1258 * Send an event to interested clients in all windows on all screens. 1259 * 1260 */ 1261 1262void 1263SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count) 1264{ 1265 int i; 1266 WindowPtr pWin, p1; 1267 1268 for (i = 0; i < screenInfo.numScreens; i++) { 1269 pWin = WindowTable[i]; 1270 (void)DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, dev->id); 1271 p1 = pWin->firstChild; 1272 FindInterestedChildren(dev, p1, mask, ev, count); 1273 } 1274} 1275