events.c revision 475c125c
1/************************************************************ 2 3Copyright 1987, 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 25 26Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 27 28 All Rights Reserved 29 30Permission to use, copy, modify, and distribute this software and its 31documentation for any purpose and without fee is hereby granted, 32provided that the above copyright notice appear in all copies and that 33both that copyright notice and this permission notice appear in 34supporting documentation, and that the name of Digital not be 35used in advertising or publicity pertaining to distribution of the 36software without specific, written prior permission. 37 38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 44SOFTWARE. 45 46********************************************************/ 47 48/* The panoramix components contained the following notice */ 49/***************************************************************** 50 51Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 52 53Permission is hereby granted, free of charge, to any person obtaining a copy 54of this software and associated documentation files (the "Software"), to deal 55in the Software without restriction, including without limitation the rights 56to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 57copies of the Software. 58 59The above copyright notice and this permission notice shall be included in 60all copies or substantial portions of the Software. 61 62THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 65DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 66BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 67WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 68IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 69 70Except as contained in this notice, the name of Digital Equipment Corporation 71shall not be used in advertising or otherwise to promote the sale, use or other 72dealings in this Software without prior written authorization from Digital 73Equipment Corporation. 74 75******************************************************************/ 76 77/* 78 * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved. 79 * 80 * Permission is hereby granted, free of charge, to any person obtaining a 81 * copy of this software and associated documentation files (the "Software"), 82 * to deal in the Software without restriction, including without limitation 83 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 84 * and/or sell copies of the Software, and to permit persons to whom the 85 * Software is furnished to do so, subject to the following conditions: 86 * 87 * The above copyright notice and this permission notice (including the next 88 * paragraph) shall be included in all copies or substantial portions of the 89 * Software. 90 * 91 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 92 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 93 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 94 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 95 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 96 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 97 * DEALINGS IN THE SOFTWARE. 98 */ 99 100/** @file events.c 101 * This file handles event delivery and a big part of the server-side protocol 102 * handling (the parts for input devices). 103 */ 104 105#ifdef HAVE_DIX_CONFIG_H 106#include <dix-config.h> 107#endif 108 109#include <X11/X.h> 110#include "misc.h" 111#include "resource.h" 112#include <X11/Xproto.h> 113#include "windowstr.h" 114#include "inputstr.h" 115#include "scrnintstr.h" 116#include "cursorstr.h" 117 118#include "dixstruct.h" 119#ifdef PANORAMIX 120#include "panoramiX.h" 121#include "panoramiXsrv.h" 122#endif 123#include "globals.h" 124 125#include <X11/extensions/XKBproto.h> 126#include "xkbsrv.h" 127#include "xace.h" 128 129#ifdef XSERVER_DTRACE 130#include <sys/types.h> 131typedef const char *string; 132#include "Xserver-dtrace.h" 133#endif 134 135#include <X11/extensions/XIproto.h> 136#include <X11/extensions/XI2proto.h> 137#include <X11/extensions/XI.h> 138#include <X11/extensions/XI2.h> 139#include "exglobals.h" 140#include "exevents.h" 141#include "exglobals.h" 142#include "extnsionst.h" 143 144#include "dixevents.h" 145#include "dixgrabs.h" 146#include "dispatch.h" 147 148#include <X11/extensions/ge.h> 149#include "geext.h" 150#include "geint.h" 151 152#include "eventstr.h" 153#include "enterleave.h" 154#include "eventconvert.h" 155 156/* Extension events type numbering starts at EXTENSION_EVENT_BASE. */ 157#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ 158#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) 159#define AllButtonsMask ( \ 160 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) 161#define MotionMask ( \ 162 PointerMotionMask | Button1MotionMask | \ 163 Button2MotionMask | Button3MotionMask | Button4MotionMask | \ 164 Button5MotionMask | ButtonMotionMask ) 165#define PropagateMask ( \ 166 KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ 167 MotionMask ) 168#define PointerGrabMask ( \ 169 ButtonPressMask | ButtonReleaseMask | \ 170 EnterWindowMask | LeaveWindowMask | \ 171 PointerMotionHintMask | KeymapStateMask | \ 172 MotionMask ) 173#define AllModifiersMask ( \ 174 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ 175 Mod3Mask | Mod4Mask | Mod5Mask ) 176#define LastEventMask OwnerGrabButtonMask 177#define AllEventMasks (LastEventMask|(LastEventMask-1)) 178 179 180#define CORE_EVENT(event) \ 181 (!((event)->u.u.type & EXTENSION_EVENT_BASE) && \ 182 (event)->u.u.type != GenericEvent) 183#define XI2_EVENT(event) \ 184 (((event)->u.u.type == GenericEvent) && \ 185 ((xGenericEvent*)(event))->extension == IReqCode) 186 187/** 188 * Used to indicate a implicit passive grab created by a ButtonPress event. 189 * See DeliverEventsToWindow(). 190 */ 191#define ImplicitGrabMask (1 << 7) 192 193#define WID(w) ((w) ? ((w)->drawable.id) : 0) 194 195#define XE_KBPTR (xE->u.keyButtonPointer) 196 197 198CallbackListPtr EventCallback; 199CallbackListPtr DeviceEventCallback; 200 201#define DNPMCOUNT 8 202 203Mask DontPropagateMasks[DNPMCOUNT]; 204static int DontPropagateRefCnts[DNPMCOUNT]; 205 206static void CheckVirtualMotion( DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin); 207static void CheckPhysLimits(DeviceIntPtr pDev, 208 CursorPtr cursor, 209 Bool generateEvents, 210 Bool confineToScreen, 211 ScreenPtr pScreen); 212 213/** Key repeat hack. Do not use but in TryClientEvents */ 214extern BOOL EventIsKeyRepeat(xEvent *event); 215 216/** 217 * Main input device struct. 218 * inputInfo.pointer 219 * is the core pointer. Referred to as "virtual core pointer", "VCP", 220 * "core pointer" or inputInfo.pointer. The VCP is the first master 221 * pointer device and cannot be deleted. 222 * 223 * inputInfo.keyboard 224 * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard"). 225 * See inputInfo.pointer. 226 * 227 * inputInfo.devices 228 * linked list containing all devices including VCP and VCK. 229 * 230 * inputInfo.off_devices 231 * Devices that have not been initialized and are thus turned off. 232 * 233 * inputInfo.numDevices 234 * Total number of devices. 235 * 236 * inputInfo.all_devices 237 * Virtual device used for XIAllDevices passive grabs. This device is 238 * not part of the inputInfo.devices list and mostly unset except for 239 * the deviceid. It exists because passivegrabs need a valid device 240 * reference. 241 * 242 * inputInfo.all_master_devices 243 * Virtual device used for XIAllMasterDevices passive grabs. This device 244 * is not part of the inputInfo.devices list and mostly unset except for 245 * the deviceid. It exists because passivegrabs need a valid device 246 * reference. 247 */ 248InputInfo inputInfo; 249 250EventSyncInfoRec syncEvents; 251 252/** 253 * The root window the given device is currently on. 254 */ 255#define RootWindow(sprite) sprite->spriteTrace[0] 256 257static xEvent* swapEvent = NULL; 258static int swapEventLen = 0; 259 260void 261NotImplemented(xEvent *from, xEvent *to) 262{ 263 FatalError("Not implemented"); 264} 265 266/** 267 * Convert the given event type from an XI event to a core event. 268 * @param[in] The XI 1.x event type. 269 * @return The matching core event type or 0 if there is none. 270 */ 271int 272XItoCoreType(int xitype) 273{ 274 int coretype = 0; 275 if (xitype == DeviceMotionNotify) 276 coretype = MotionNotify; 277 else if (xitype == DeviceButtonPress) 278 coretype = ButtonPress; 279 else if (xitype == DeviceButtonRelease) 280 coretype = ButtonRelease; 281 else if (xitype == DeviceKeyPress) 282 coretype = KeyPress; 283 else if (xitype == DeviceKeyRelease) 284 coretype = KeyRelease; 285 286 return coretype; 287} 288 289/** 290 * @return true if the device owns a cursor, false if device shares a cursor 291 * sprite with another device. 292 */ 293Bool 294DevHasCursor(DeviceIntPtr pDev) 295{ 296 return pDev->spriteInfo->spriteOwner; 297} 298 299/* 300 * @return true if a device is a pointer, check is the same as used by XI to 301 * fill the 'use' field. 302 */ 303Bool 304IsPointerDevice(DeviceIntPtr dev) 305{ 306 return (dev->type == MASTER_POINTER) || 307 (dev->valuator && dev->button) || 308 (dev->valuator && !dev->key); 309} 310 311/* 312 * @return true if a device is a keyboard, check is the same as used by XI to 313 * fill the 'use' field. 314 * 315 * Some pointer devices have keys as well (e.g. multimedia keys). Try to not 316 * count them as keyboard devices. 317 */ 318Bool 319IsKeyboardDevice(DeviceIntPtr dev) 320{ 321 return (dev->type == MASTER_KEYBOARD) || 322 ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev)); 323} 324 325Bool 326IsMaster(DeviceIntPtr dev) 327{ 328 return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD; 329} 330 331/** 332 * Max event opcode. 333 */ 334extern int lastEvent; 335 336extern int DeviceMotionNotify; 337 338#define CantBeFiltered NoEventMask 339/** 340 * Event masks for each event type. 341 * 342 * One set of filters for each device, but only the first layer 343 * is initialized. The rest is memcpy'd in InitEvents. 344 * 345 * Filters are used whether a given event may be delivered to a client, 346 * usually in the form of if (window-event-mask & filter); then deliver event. 347 * 348 * One notable filter is for PointerMotion/DevicePointerMotion events. Each 349 * time a button is pressed, the filter is modified to also contain the 350 * matching ButtonXMotion mask. 351 */ 352static Mask filters[MAXDEVICES][128] = { 353{ 354 NoSuchEvent, /* 0 */ 355 NoSuchEvent, /* 1 */ 356 KeyPressMask, /* KeyPress */ 357 KeyReleaseMask, /* KeyRelease */ 358 ButtonPressMask, /* ButtonPress */ 359 ButtonReleaseMask, /* ButtonRelease */ 360 PointerMotionMask, /* MotionNotify (initial state) */ 361 EnterWindowMask, /* EnterNotify */ 362 LeaveWindowMask, /* LeaveNotify */ 363 FocusChangeMask, /* FocusIn */ 364 FocusChangeMask, /* FocusOut */ 365 KeymapStateMask, /* KeymapNotify */ 366 ExposureMask, /* Expose */ 367 CantBeFiltered, /* GraphicsExpose */ 368 CantBeFiltered, /* NoExpose */ 369 VisibilityChangeMask, /* VisibilityNotify */ 370 SubstructureNotifyMask, /* CreateNotify */ 371 StructureAndSubMask, /* DestroyNotify */ 372 StructureAndSubMask, /* UnmapNotify */ 373 StructureAndSubMask, /* MapNotify */ 374 SubstructureRedirectMask, /* MapRequest */ 375 StructureAndSubMask, /* ReparentNotify */ 376 StructureAndSubMask, /* ConfigureNotify */ 377 SubstructureRedirectMask, /* ConfigureRequest */ 378 StructureAndSubMask, /* GravityNotify */ 379 ResizeRedirectMask, /* ResizeRequest */ 380 StructureAndSubMask, /* CirculateNotify */ 381 SubstructureRedirectMask, /* CirculateRequest */ 382 PropertyChangeMask, /* PropertyNotify */ 383 CantBeFiltered, /* SelectionClear */ 384 CantBeFiltered, /* SelectionRequest */ 385 CantBeFiltered, /* SelectionNotify */ 386 ColormapChangeMask, /* ColormapNotify */ 387 CantBeFiltered, /* ClientMessage */ 388 CantBeFiltered /* MappingNotify */ 389}}; 390 391/** 392 * For the given event, return the matching event filter. This filter may then 393 * be AND'ed with the selected event mask. 394 * 395 * For XI2 events, the returned filter is simply the byte containing the event 396 * mask we're interested in. E.g. for a mask of (1 << 13), this would be 397 * byte[1]. 398 * 399 * @param[in] dev The device the event belongs to, may be NULL. 400 * @param[in] event The event to get the filter for. Only the type of the 401 * event matters, or the extension + evtype for GenericEvents. 402 * @return The filter mask for the given event. 403 * 404 * @see GetEventMask 405 */ 406Mask 407GetEventFilter(DeviceIntPtr dev, xEvent *event) 408{ 409 if (event->u.u.type != GenericEvent) 410 return filters[dev ? dev->id : 0][event->u.u.type]; 411 else if (XI2_EVENT(event)) 412 return (1 << (((xXIDeviceEvent*)event)->evtype % 8)); 413 ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type); 414 return 0; 415} 416 417/** 418 * Return the windows complete XI2 mask for the given XI2 event type. 419 */ 420Mask 421GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev) 422{ 423 OtherInputMasks *inputMasks = wOtherInputMasks(win); 424 int filter; 425 int evtype; 426 427 if (!inputMasks || !XI2_EVENT(ev)) 428 return 0; 429 430 evtype = ((xGenericEvent*)ev)->evtype; 431 filter = GetEventFilter(dev, ev); 432 433 return ((inputMasks->xi2mask[dev->id][evtype/8] & filter) || 434 inputMasks->xi2mask[XIAllDevices][evtype/8] || 435 (inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev))); 436} 437 438Mask 439GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other) 440{ 441 /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */ 442 if (XI2_EVENT(event)) 443 { 444 int byte = ((xGenericEvent*)event)->evtype / 8; 445 return (other->xi2mask[dev->id][byte] | 446 other->xi2mask[XIAllDevices][byte] | 447 (IsMaster(dev)? other->xi2mask[XIAllMasterDevices][byte] : 0)); 448 } else if (CORE_EVENT(event)) 449 return other->mask[XIAllDevices]; 450 else 451 return other->mask[dev->id]; 452} 453 454 455static CARD8 criticalEvents[32] = 456{ 457 0x7c, 0x30, 0x40 /* key, button, expose, and configure events */ 458}; 459 460static void 461SyntheticMotion(DeviceIntPtr dev, int x, int y) { 462 int screenno = 0; 463 464#ifdef PANORAMIX 465 if (!noPanoramiXExtension) 466 screenno = dev->spriteInfo->sprite->screen->myNum; 467#endif 468 PostSyntheticMotion(dev, x, y, screenno, 469 (syncEvents.playingEvents) ? syncEvents.time.milliseconds : currentTime.milliseconds); 470 471} 472 473#ifdef PANORAMIX 474static void PostNewCursor(DeviceIntPtr pDev); 475 476static Bool 477pointOnScreen(ScreenPtr pScreen, int x, int y) 478{ 479 return x >= pScreen->x && x < pScreen->x + pScreen->width && 480 y >= pScreen->y && y < pScreen->y + pScreen->height; 481} 482 483static Bool 484XineramaSetCursorPosition( 485 DeviceIntPtr pDev, 486 int x, 487 int y, 488 Bool generateEvent 489){ 490 ScreenPtr pScreen; 491 int i; 492 SpritePtr pSprite = pDev->spriteInfo->sprite; 493 494 /* x,y are in Screen 0 coordinates. We need to decide what Screen 495 to send the message too and what the coordinates relative to 496 that screen are. */ 497 498 pScreen = pSprite->screen; 499 x += screenInfo.screens[0]->x; 500 y += screenInfo.screens[0]->y; 501 502 if(!pointOnScreen(pScreen, x, y)) 503 { 504 FOR_NSCREENS(i) 505 { 506 if(i == pScreen->myNum) 507 continue; 508 if(pointOnScreen(screenInfo.screens[i], x, y)) 509 { 510 pScreen = screenInfo.screens[i]; 511 break; 512 } 513 } 514 } 515 516 pSprite->screen = pScreen; 517 pSprite->hotPhys.x = x - screenInfo.screens[0]->x; 518 pSprite->hotPhys.y = y - screenInfo.screens[0]->y; 519 x -= pScreen->x; 520 y -= pScreen->y; 521 522 return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent); 523} 524 525 526static void 527XineramaConstrainCursor(DeviceIntPtr pDev) 528{ 529 SpritePtr pSprite = pDev->spriteInfo->sprite; 530 ScreenPtr pScreen; 531 BoxRec newBox; 532 533 pScreen = pSprite->screen; 534 newBox = pSprite->physLimits; 535 536 /* Translate the constraining box to the screen 537 the sprite is actually on */ 538 newBox.x1 += screenInfo.screens[0]->x - pScreen->x; 539 newBox.x2 += screenInfo.screens[0]->x - pScreen->x; 540 newBox.y1 += screenInfo.screens[0]->y - pScreen->y; 541 newBox.y2 += screenInfo.screens[0]->y - pScreen->y; 542 543 (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox); 544} 545 546 547static Bool 548XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin) 549{ 550 SpritePtr pSprite = pDev->spriteInfo->sprite; 551 552 if(pWin == screenInfo.screens[0]->root) { 553 int i; 554 for (i = 0; i < PanoramiXNumScreens; i++) 555 pSprite->windows[i] = screenInfo.screens[i]->root; 556 } else { 557 PanoramiXRes *win; 558 int rc, i; 559 560 rc = dixLookupResourceByType((pointer *)&win, pWin->drawable.id, 561 XRT_WINDOW, serverClient, DixReadAccess); 562 if (rc != Success) 563 return FALSE; 564 565 for(i = 0; i < PanoramiXNumScreens; i++) { 566 rc = dixLookupWindow(pSprite->windows + i, win->info[i].id, 567 serverClient, DixReadAccess); 568 if (rc != Success) /* window is being unmapped */ 569 return FALSE; 570 } 571 } 572 return TRUE; 573} 574 575static void 576XineramaConfineCursorToWindow(DeviceIntPtr pDev, 577 WindowPtr pWin, 578 Bool generateEvents) 579{ 580 SpritePtr pSprite = pDev->spriteInfo->sprite; 581 582 int x, y, off_x, off_y, i; 583 584 if(!XineramaSetWindowPntrs(pDev, pWin)) 585 return; 586 587 i = PanoramiXNumScreens - 1; 588 589 RegionCopy(&pSprite->Reg1, 590 &pSprite->windows[i]->borderSize); 591 off_x = screenInfo.screens[i]->x; 592 off_y = screenInfo.screens[i]->y; 593 594 while(i--) { 595 x = off_x - screenInfo.screens[i]->x; 596 y = off_y - screenInfo.screens[i]->y; 597 598 if(x || y) 599 RegionTranslate(&pSprite->Reg1, x, y); 600 601 RegionUnion(&pSprite->Reg1, &pSprite->Reg1, 602 &pSprite->windows[i]->borderSize); 603 604 off_x = screenInfo.screens[i]->x; 605 off_y = screenInfo.screens[i]->y; 606 } 607 608 pSprite->hotLimits = *RegionExtents(&pSprite->Reg1); 609 610 if(RegionNumRects(&pSprite->Reg1) > 1) 611 pSprite->hotShape = &pSprite->Reg1; 612 else 613 pSprite->hotShape = NullRegion; 614 615 pSprite->confined = FALSE; 616 pSprite->confineWin = (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin; 617 618 CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL); 619} 620 621#endif /* PANORAMIX */ 622 623/** 624 * Modifies the filter for the given protocol event type to the given masks. 625 * 626 * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent(). 627 * The latter initialises masks for the matching XI events, it's a once-off 628 * setting. 629 * UDS however changes the mask for MotionNotify and DeviceMotionNotify each 630 * time a button is pressed to include the matching ButtonXMotion mask in the 631 * filter. 632 * 633 * @param[in] deviceid The device to modify the filter for. 634 * @param[in] mask The new filter mask. 635 * @param[in] event Protocol event type. 636 */ 637void 638SetMaskForEvent(int deviceid, Mask mask, int event) 639{ 640 if (deviceid < 0 || deviceid >= MAXDEVICES) 641 FatalError("SetMaskForEvent: bogus device id"); 642 filters[deviceid][event] = mask; 643} 644 645void 646SetCriticalEvent(int event) 647{ 648 if (event >= 128) 649 FatalError("SetCriticalEvent: bogus event number"); 650 criticalEvents[event >> 3] |= 1 << (event & 7); 651} 652 653void 654ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py) 655{ 656 BoxRec box; 657 int x = *px, y = *py; 658 int incx = 1, incy = 1; 659 SpritePtr pSprite; 660 661 pSprite = pDev->spriteInfo->sprite; 662 if (RegionContainsPoint(shape, x, y, &box)) 663 return; 664 box = *RegionExtents(shape); 665 /* this is rather crude */ 666 do { 667 x += incx; 668 if (x >= box.x2) 669 { 670 incx = -1; 671 x = *px - 1; 672 } 673 else if (x < box.x1) 674 { 675 incx = 1; 676 x = *px; 677 y += incy; 678 if (y >= box.y2) 679 { 680 incy = -1; 681 y = *py - 1; 682 } 683 else if (y < box.y1) 684 return; /* should never get here! */ 685 } 686 } while (!RegionContainsPoint(shape, x, y, &box)); 687 *px = x; 688 *py = y; 689} 690 691static void 692CheckPhysLimits( 693 DeviceIntPtr pDev, 694 CursorPtr cursor, 695 Bool generateEvents, 696 Bool confineToScreen, /* unused if PanoramiX on */ 697 ScreenPtr pScreen) /* unused if PanoramiX on */ 698{ 699 HotSpot new; 700 SpritePtr pSprite = pDev->spriteInfo->sprite; 701 702 if (!cursor) 703 return; 704 new = pSprite->hotPhys; 705#ifdef PANORAMIX 706 if (!noPanoramiXExtension) 707 /* I don't care what the DDX has to say about it */ 708 pSprite->physLimits = pSprite->hotLimits; 709 else 710#endif 711 { 712 if (pScreen) 713 new.pScreen = pScreen; 714 else 715 pScreen = new.pScreen; 716 (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits, 717 &pSprite->physLimits); 718 pSprite->confined = confineToScreen; 719 (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits); 720 } 721 722 /* constrain the pointer to those limits */ 723 if (new.x < pSprite->physLimits.x1) 724 new.x = pSprite->physLimits.x1; 725 else 726 if (new.x >= pSprite->physLimits.x2) 727 new.x = pSprite->physLimits.x2 - 1; 728 if (new.y < pSprite->physLimits.y1) 729 new.y = pSprite->physLimits.y1; 730 else 731 if (new.y >= pSprite->physLimits.y2) 732 new.y = pSprite->physLimits.y2 - 1; 733 if (pSprite->hotShape) 734 ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); 735 if (( 736#ifdef PANORAMIX 737 noPanoramiXExtension && 738#endif 739 (pScreen != pSprite->hotPhys.pScreen)) || 740 (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) 741 { 742#ifdef PANORAMIX 743 if (!noPanoramiXExtension) 744 XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents); 745 else 746#endif 747 { 748 if (pScreen != pSprite->hotPhys.pScreen) 749 pSprite->hotPhys = new; 750 (*pScreen->SetCursorPosition) 751 (pDev, pScreen, new.x, new.y, generateEvents); 752 } 753 if (!generateEvents) 754 SyntheticMotion(pDev, new.x, new.y); 755 } 756 757#ifdef PANORAMIX 758 /* Tell DDX what the limits are */ 759 if (!noPanoramiXExtension) 760 XineramaConstrainCursor(pDev); 761#endif 762} 763 764static void 765CheckVirtualMotion( 766 DeviceIntPtr pDev, 767 QdEventPtr qe, 768 WindowPtr pWin) 769{ 770 SpritePtr pSprite = pDev->spriteInfo->sprite; 771 RegionPtr reg = NULL; 772 DeviceEvent *ev = NULL; 773 774 if (qe) 775 { 776 ev = &qe->event->device_event; 777 switch(ev->type) 778 { 779 case ET_Motion: 780 case ET_ButtonPress: 781 case ET_ButtonRelease: 782 case ET_KeyPress: 783 case ET_KeyRelease: 784 case ET_ProximityIn: 785 case ET_ProximityOut: 786 pSprite->hot.pScreen = qe->pScreen; 787 pSprite->hot.x = ev->root_x; 788 pSprite->hot.y = ev->root_y; 789 pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow; 790 break; 791 default: 792 break; 793 } 794 } 795 if (pWin) 796 { 797 BoxRec lims; 798 799#ifdef PANORAMIX 800 if (!noPanoramiXExtension) { 801 int x, y, off_x, off_y, i; 802 803 if(!XineramaSetWindowPntrs(pDev, pWin)) 804 return; 805 806 i = PanoramiXNumScreens - 1; 807 808 RegionCopy(&pSprite->Reg2, 809 &pSprite->windows[i]->borderSize); 810 off_x = screenInfo.screens[i]->x; 811 off_y = screenInfo.screens[i]->y; 812 813 while(i--) { 814 x = off_x - screenInfo.screens[i]->x; 815 y = off_y - screenInfo.screens[i]->y; 816 817 if(x || y) 818 RegionTranslate(&pSprite->Reg2, x, y); 819 820 RegionUnion(&pSprite->Reg2, &pSprite->Reg2, 821 &pSprite->windows[i]->borderSize); 822 823 off_x = screenInfo.screens[i]->x; 824 off_y = screenInfo.screens[i]->y; 825 } 826 } else 827#endif 828 { 829 if (pSprite->hot.pScreen != pWin->drawable.pScreen) 830 { 831 pSprite->hot.pScreen = pWin->drawable.pScreen; 832 pSprite->hot.x = pSprite->hot.y = 0; 833 } 834 } 835 836 lims = *RegionExtents(&pWin->borderSize); 837 if (pSprite->hot.x < lims.x1) 838 pSprite->hot.x = lims.x1; 839 else if (pSprite->hot.x >= lims.x2) 840 pSprite->hot.x = lims.x2 - 1; 841 if (pSprite->hot.y < lims.y1) 842 pSprite->hot.y = lims.y1; 843 else if (pSprite->hot.y >= lims.y2) 844 pSprite->hot.y = lims.y2 - 1; 845 846#ifdef PANORAMIX 847 if (!noPanoramiXExtension) 848 { 849 if (RegionNumRects(&pSprite->Reg2) > 1) 850 reg = &pSprite->Reg2; 851 852 } else 853#endif 854 { 855 if (wBoundingShape(pWin)) 856 reg = &pWin->borderSize; 857 } 858 859 if (reg) 860 ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y); 861 862 if (qe && ev) 863 { 864 qe->pScreen = pSprite->hot.pScreen; 865 ev->root_x = pSprite->hot.x; 866 ev->root_y = pSprite->hot.y; 867 } 868 } 869#ifdef PANORAMIX 870 if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */ 871#endif 872 RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root; 873} 874 875static void 876ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen) 877{ 878 SpritePtr pSprite = pDev->spriteInfo->sprite; 879 880 if (syncEvents.playingEvents) 881 { 882 CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin); 883 SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); 884 } 885 else 886 { 887#ifdef PANORAMIX 888 if(!noPanoramiXExtension) { 889 XineramaConfineCursorToWindow(pDev, pWin, generateEvents); 890 return; 891 } 892#endif 893 pSprite->hotLimits = *RegionExtents(&pWin->borderSize); 894 pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize 895 : NullRegion; 896 CheckPhysLimits(pDev, pSprite->current, generateEvents, 897 confineToScreen, pWin->drawable.pScreen); 898 } 899} 900 901Bool 902PointerConfinedToScreen(DeviceIntPtr pDev) 903{ 904 return pDev->spriteInfo->sprite->confined; 905} 906 907/** 908 * Update the sprite cursor to the given cursor. 909 * 910 * ChangeToCursor() will display the new cursor and free the old cursor (if 911 * applicable). If the provided cursor is already the updated cursor, nothing 912 * happens. 913 */ 914static void 915ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) 916{ 917 SpritePtr pSprite = pDev->spriteInfo->sprite; 918 ScreenPtr pScreen; 919 920 if (cursor != pSprite->current) 921 { 922 if ((pSprite->current->bits->xhot != cursor->bits->xhot) || 923 (pSprite->current->bits->yhot != cursor->bits->yhot)) 924 CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined, 925 (ScreenPtr)NULL); 926#ifdef PANORAMIX 927 /* XXX: is this really necessary?? (whot) */ 928 if (!noPanoramiXExtension) 929 pScreen = pSprite->screen; 930 else 931#endif 932 pScreen = pSprite->hotPhys.pScreen; 933 934 (*pScreen->DisplayCursor)(pDev, pScreen, cursor); 935 FreeCursor(pSprite->current, (Cursor)0); 936 pSprite->current = cursor; 937 pSprite->current->refcnt++; 938 } 939} 940 941/** 942 * @returns true if b is a descendent of a 943 */ 944Bool 945IsParent(WindowPtr a, WindowPtr b) 946{ 947 for (b = b->parent; b; b = b->parent) 948 if (b == a) return TRUE; 949 return FALSE; 950} 951 952/** 953 * Update the cursor displayed on the screen. 954 * 955 * Called whenever a cursor may have changed shape or position. 956 */ 957static void 958PostNewCursor(DeviceIntPtr pDev) 959{ 960 WindowPtr win; 961 GrabPtr grab = pDev->deviceGrab.grab; 962 SpritePtr pSprite = pDev->spriteInfo->sprite; 963 CursorPtr pCursor; 964 965 if (syncEvents.playingEvents) 966 return; 967 if (grab) 968 { 969 if (grab->cursor) 970 { 971 ChangeToCursor(pDev, grab->cursor); 972 return; 973 } 974 if (IsParent(grab->window, pSprite->win)) 975 win = pSprite->win; 976 else 977 win = grab->window; 978 } 979 else 980 win = pSprite->win; 981 for (; win; win = win->parent) 982 { 983 if (win->optional) 984 { 985 pCursor = WindowGetDeviceCursor(win, pDev); 986 if (!pCursor && win->optional->cursor != NullCursor) 987 pCursor = win->optional->cursor; 988 if (pCursor) 989 { 990 ChangeToCursor(pDev, pCursor); 991 return; 992 } 993 } 994 } 995} 996 997 998/** 999 * @param dev device which you want to know its current root window 1000 * @return root window where dev's sprite is located 1001 */ 1002WindowPtr 1003GetCurrentRootWindow(DeviceIntPtr dev) 1004{ 1005 return RootWindow(dev->spriteInfo->sprite); 1006} 1007 1008/** 1009 * @return window underneath the cursor sprite. 1010 */ 1011WindowPtr 1012GetSpriteWindow(DeviceIntPtr pDev) 1013{ 1014 return pDev->spriteInfo->sprite->win; 1015} 1016 1017/** 1018 * @return current sprite cursor. 1019 */ 1020CursorPtr 1021GetSpriteCursor(DeviceIntPtr pDev) 1022{ 1023 return pDev->spriteInfo->sprite->current; 1024} 1025 1026/** 1027 * Set x/y current sprite position in screen coordinates. 1028 */ 1029void 1030GetSpritePosition(DeviceIntPtr pDev, int *px, int *py) 1031{ 1032 SpritePtr pSprite = pDev->spriteInfo->sprite; 1033 *px = pSprite->hotPhys.x; 1034 *py = pSprite->hotPhys.y; 1035} 1036 1037#ifdef PANORAMIX 1038int 1039XineramaGetCursorScreen(DeviceIntPtr pDev) 1040{ 1041 if(!noPanoramiXExtension) { 1042 return pDev->spriteInfo->sprite->screen->myNum; 1043 } else { 1044 return 0; 1045 } 1046} 1047#endif /* PANORAMIX */ 1048 1049#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ 1050 1051static void 1052MonthChangedOrBadTime(InternalEvent *ev) 1053{ 1054 /* If the ddx/OS is careless about not processing timestamped events from 1055 * different sources in sorted order, then it's possible for time to go 1056 * backwards when it should not. Here we ensure a decent time. 1057 */ 1058 if ((currentTime.milliseconds - ev->any.time) > TIMESLOP) 1059 currentTime.months++; 1060 else 1061 ev->any.time = currentTime.milliseconds; 1062} 1063 1064static void 1065NoticeTime(InternalEvent *ev) 1066{ 1067 if (ev->any.time < currentTime.milliseconds) 1068 MonthChangedOrBadTime(ev); 1069 currentTime.milliseconds = ev->any.time; 1070 lastDeviceEventTime = currentTime; 1071} 1072 1073void 1074NoticeEventTime(InternalEvent *ev) 1075{ 1076 if (!syncEvents.playingEvents) 1077 NoticeTime(ev); 1078} 1079 1080/************************************************************************** 1081 * The following procedures deal with synchronous events * 1082 **************************************************************************/ 1083 1084/** 1085 * EnqueueEvent is a device's processInputProc if a device is frozen. 1086 * Instead of delivering the events to the client, the event is tacked onto a 1087 * linked list for later delivery. 1088 */ 1089void 1090EnqueueEvent(InternalEvent *ev, DeviceIntPtr device) 1091{ 1092 QdEventPtr tail = *syncEvents.pendtail; 1093 QdEventPtr qe; 1094 SpritePtr pSprite = device->spriteInfo->sprite; 1095 int eventlen; 1096 DeviceEvent *event = &ev->device_event; 1097 1098 NoticeTime((InternalEvent*)event); 1099 1100 /* Fix for key repeating bug. */ 1101 if (device->key != NULL && device->key->xkbInfo != NULL && 1102 event->type == ET_KeyRelease) 1103 AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key); 1104 1105 if (DeviceEventCallback) 1106 { 1107 DeviceEventInfoRec eventinfo; 1108 1109 /* The RECORD spec says that the root window field of motion events 1110 * must be valid. At this point, it hasn't been filled in yet, so 1111 * we do it here. The long expression below is necessary to get 1112 * the current root window; the apparently reasonable alternative 1113 * GetCurrentRootWindow()->drawable.id doesn't give you the right 1114 * answer on the first motion event after a screen change because 1115 * the data that GetCurrentRootWindow relies on hasn't been 1116 * updated yet. 1117 */ 1118 if (ev->any.type == ET_Motion) 1119 ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id; 1120 1121 eventinfo.event = ev; 1122 eventinfo.device = device; 1123 CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); 1124 } 1125 1126 if (event->type == ET_Motion) 1127 { 1128#ifdef PANORAMIX 1129 if(!noPanoramiXExtension) { 1130 event->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 1131 event->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 1132 } 1133#endif 1134 pSprite->hotPhys.x = event->root_x; 1135 pSprite->hotPhys.y = event->root_y; 1136 /* do motion compression, but not if from different devices */ 1137 if (tail && 1138 (tail->event->any.type == ET_Motion) && 1139 (tail->device == device) && 1140 (tail->pScreen == pSprite->hotPhys.pScreen)) 1141 { 1142 DeviceEvent *tailev = &tail->event->device_event; 1143 tailev->root_x = pSprite->hotPhys.x; 1144 tailev->root_y = pSprite->hotPhys.y; 1145 tailev->time = event->time; 1146 tail->months = currentTime.months; 1147 return; 1148 } 1149 } 1150 1151 eventlen = event->length; 1152 1153 qe = malloc(sizeof(QdEventRec) + eventlen); 1154 if (!qe) 1155 return; 1156 qe->next = (QdEventPtr)NULL; 1157 qe->device = device; 1158 qe->pScreen = pSprite->hotPhys.pScreen; 1159 qe->months = currentTime.months; 1160 qe->event = (InternalEvent *)(qe + 1); 1161 memcpy(qe->event, event, eventlen); 1162 if (tail) 1163 syncEvents.pendtail = &tail->next; 1164 *syncEvents.pendtail = qe; 1165} 1166 1167/** 1168 * Run through the list of events queued up in syncEvents. 1169 * For each event do: 1170 * If the device for this event is not frozen anymore, take it and process it 1171 * as usually. 1172 * After that, check if there's any devices in the list that are not frozen. 1173 * If there is none, we're done. If there is at least one device that is not 1174 * frozen, then re-run from the beginning of the event queue. 1175 */ 1176static void 1177PlayReleasedEvents(void) 1178{ 1179 QdEventPtr *prev, qe; 1180 DeviceIntPtr dev; 1181 DeviceIntPtr pDev; 1182 1183 prev = &syncEvents.pending; 1184 while ( (qe = *prev) ) 1185 { 1186 if (!qe->device->deviceGrab.sync.frozen) 1187 { 1188 *prev = qe->next; 1189 pDev = qe->device; 1190 if (*syncEvents.pendtail == *prev) 1191 syncEvents.pendtail = prev; 1192 if (qe->event->any.type == ET_Motion) 1193 CheckVirtualMotion(pDev, qe, NullWindow); 1194 syncEvents.time.months = qe->months; 1195 syncEvents.time.milliseconds = qe->event->any.time; 1196#ifdef PANORAMIX 1197 /* Translate back to the sprite screen since processInputProc 1198 will translate from sprite screen to screen 0 upon reentry 1199 to the DIX layer */ 1200 if(!noPanoramiXExtension) { 1201 DeviceEvent *ev = &qe->event->device_event; 1202 switch(ev->type) 1203 { 1204 case ET_Motion: 1205 case ET_ButtonPress: 1206 case ET_ButtonRelease: 1207 case ET_KeyPress: 1208 case ET_KeyRelease: 1209 case ET_ProximityIn: 1210 case ET_ProximityOut: 1211 ev->root_x += screenInfo.screens[0]->x - 1212 pDev->spriteInfo->sprite->screen->x; 1213 ev->root_y += screenInfo.screens[0]->y - 1214 pDev->spriteInfo->sprite->screen->y; 1215 break; 1216 default: 1217 break; 1218 } 1219 1220 } 1221#endif 1222 (*qe->device->public.processInputProc)(qe->event, qe->device); 1223 free(qe); 1224 for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next) 1225 ; 1226 if (!dev) 1227 break; 1228 /* Playing the event may have unfrozen another device. */ 1229 /* So to play it safe, restart at the head of the queue */ 1230 prev = &syncEvents.pending; 1231 } 1232 else 1233 prev = &qe->next; 1234 } 1235} 1236 1237/** 1238 * Freeze or thaw the given devices. The device's processing proc is 1239 * switched to either the real processing proc (in case of thawing) or an 1240 * enqueuing processing proc (usually EnqueueEvent()). 1241 * 1242 * @param dev The device to freeze/thaw 1243 * @param frozen True to freeze or false to thaw. 1244 */ 1245static void 1246FreezeThaw(DeviceIntPtr dev, Bool frozen) 1247{ 1248 dev->deviceGrab.sync.frozen = frozen; 1249 if (frozen) 1250 dev->public.processInputProc = dev->public.enqueueInputProc; 1251 else 1252 dev->public.processInputProc = dev->public.realInputProc; 1253} 1254 1255/** 1256 * Unfreeze devices and replay all events to the respective clients. 1257 * 1258 * ComputeFreezes takes the first event in the device's frozen event queue. It 1259 * runs up the sprite tree (spriteTrace) and searches for the window to replay 1260 * the events from. If it is found, it checks for passive grabs one down from 1261 * the window or delivers the events. 1262 */ 1263static void 1264ComputeFreezes(void) 1265{ 1266 DeviceIntPtr replayDev = syncEvents.replayDev; 1267 WindowPtr w; 1268 GrabPtr grab; 1269 DeviceIntPtr dev; 1270 1271 for (dev = inputInfo.devices; dev; dev = dev->next) 1272 FreezeThaw(dev, dev->deviceGrab.sync.other || 1273 (dev->deviceGrab.sync.state >= FROZEN)); 1274 if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) 1275 return; 1276 syncEvents.playingEvents = TRUE; 1277 if (replayDev) 1278 { 1279 DeviceEvent* event = replayDev->deviceGrab.sync.event; 1280 1281 syncEvents.replayDev = (DeviceIntPtr)NULL; 1282 1283 w = XYToWindow(replayDev->spriteInfo->sprite, 1284 event->root_x, event->root_y); 1285 if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) 1286 { 1287 if (replayDev->focus && !IsPointerEvent((InternalEvent*)event)) 1288 DeliverFocusedEvent(replayDev, (InternalEvent*)event, w); 1289 else 1290 DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab, 1291 NullWindow, replayDev); 1292 } 1293 } 1294 for (dev = inputInfo.devices; dev; dev = dev->next) 1295 { 1296 if (!dev->deviceGrab.sync.frozen) 1297 { 1298 PlayReleasedEvents(); 1299 break; 1300 } 1301 } 1302 syncEvents.playingEvents = FALSE; 1303 for (dev = inputInfo.devices; dev; dev = dev->next) 1304 { 1305 if (DevHasCursor(dev)) 1306 { 1307 /* the following may have been skipped during replay, 1308 so do it now */ 1309 if ((grab = dev->deviceGrab.grab) && grab->confineTo) 1310 { 1311 if (grab->confineTo->drawable.pScreen != 1312 dev->spriteInfo->sprite->hotPhys.pScreen) 1313 dev->spriteInfo->sprite->hotPhys.x = 1314 dev->spriteInfo->sprite->hotPhys.y = 0; 1315 ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE); 1316 } 1317 else 1318 ConfineCursorToWindow(dev, 1319 dev->spriteInfo->sprite->hotPhys.pScreen->root, 1320 TRUE, FALSE); 1321 PostNewCursor(dev); 1322 } 1323 } 1324} 1325 1326#ifdef RANDR 1327void 1328ScreenRestructured (ScreenPtr pScreen) 1329{ 1330 GrabPtr grab; 1331 DeviceIntPtr pDev; 1332 1333 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 1334 { 1335 if (!DevHasCursor(pDev)) 1336 continue; 1337 1338 /* GrabDevice doesn't have a confineTo field, so we don't need to 1339 * worry about it. */ 1340 if ((grab = pDev->deviceGrab.grab) && grab->confineTo) 1341 { 1342 if (grab->confineTo->drawable.pScreen 1343 != pDev->spriteInfo->sprite->hotPhys.pScreen) 1344 pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0; 1345 ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 1346 } 1347 else 1348 ConfineCursorToWindow(pDev, 1349 pDev->spriteInfo->sprite->hotPhys.pScreen->root, 1350 TRUE, FALSE); 1351 } 1352} 1353#endif 1354 1355static void 1356CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) 1357{ 1358 GrabPtr grab = thisDev->deviceGrab.grab; 1359 DeviceIntPtr dev; 1360 1361 if (thisMode == GrabModeSync) 1362 thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT; 1363 else 1364 { /* free both if same client owns both */ 1365 thisDev->deviceGrab.sync.state = THAWED; 1366 if (thisDev->deviceGrab.sync.other && 1367 (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) == 1368 CLIENT_BITS(grab->resource))) 1369 thisDev->deviceGrab.sync.other = NullGrab; 1370 } 1371 1372 if (IsMaster(thisDev)) 1373 { 1374 dev = GetPairedDevice(thisDev); 1375 if (otherMode == GrabModeSync) 1376 dev->deviceGrab.sync.other = grab; 1377 else 1378 { /* free both if same client owns both */ 1379 if (dev->deviceGrab.sync.other && 1380 (CLIENT_BITS(dev->deviceGrab.sync.other->resource) == 1381 CLIENT_BITS(grab->resource))) 1382 dev->deviceGrab.sync.other = NullGrab; 1383 } 1384 } 1385 ComputeFreezes(); 1386} 1387 1388/** 1389 * Save the device's master device id. This needs to be done 1390 * if a client directly grabs a slave device that is attached to a master. For 1391 * the duration of the grab, the device is detached, ungrabbing re-attaches it 1392 * though. 1393 * 1394 * We store the ID of the master device only in case the master disappears 1395 * while the device has a grab. 1396 */ 1397static void 1398DetachFromMaster(DeviceIntPtr dev) 1399{ 1400 if (!dev->u.master) 1401 return; 1402 1403 dev->saved_master_id = dev->u.master->id; 1404 1405 AttachDevice(NULL, dev, NULL); 1406} 1407 1408static void 1409ReattachToOldMaster(DeviceIntPtr dev) 1410{ 1411 DeviceIntPtr master = NULL; 1412 1413 if (IsMaster(dev)) 1414 return; 1415 1416 dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess); 1417 1418 if (master) 1419 { 1420 AttachDevice(serverClient, dev, master); 1421 dev->saved_master_id = 0; 1422 } 1423} 1424 1425/** 1426 * Activate a pointer grab on the given device. A pointer grab will cause all 1427 * core pointer events of this device to be delivered to the grabbing client only. 1428 * No other device will send core events to the grab client while the grab is 1429 * on, but core events will be sent to other clients. 1430 * Can cause the cursor to change if a grab cursor is set. 1431 * 1432 * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab 1433 * is an implicit grab caused by a ButtonPress event. 1434 * 1435 * @param mouse The device to grab. 1436 * @param grab The grab structure, needs to be setup. 1437 * @param autoGrab True if the grab was caused by a button down event and not 1438 * explicitely by a client. 1439 */ 1440void 1441ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 1442 TimeStamp time, Bool autoGrab) 1443{ 1444 GrabInfoPtr grabinfo = &mouse->deviceGrab; 1445 WindowPtr oldWin = (grabinfo->grab) ? 1446 grabinfo->grab->window 1447 : mouse->spriteInfo->sprite->win; 1448 Bool isPassive = autoGrab & ~ImplicitGrabMask; 1449 1450 /* slave devices need to float for the duration of the grab. */ 1451 if (grab->grabtype == GRABTYPE_XI2 && 1452 !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse)) 1453 DetachFromMaster(mouse); 1454 1455 if (grab->confineTo) 1456 { 1457 if (grab->confineTo->drawable.pScreen 1458 != mouse->spriteInfo->sprite->hotPhys.pScreen) 1459 mouse->spriteInfo->sprite->hotPhys.x = 1460 mouse->spriteInfo->sprite->hotPhys.y = 0; 1461 ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); 1462 } 1463 DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab); 1464 mouse->valuator->motionHintWindow = NullWindow; 1465 if (syncEvents.playingEvents) 1466 grabinfo->grabTime = syncEvents.time; 1467 else 1468 grabinfo->grabTime = time; 1469 if (grab->cursor) 1470 grab->cursor->refcnt++; 1471 grabinfo->activeGrab = *grab; 1472 grabinfo->grab = &grabinfo->activeGrab; 1473 grabinfo->fromPassiveGrab = isPassive; 1474 grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; 1475 PostNewCursor(mouse); 1476 CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); 1477} 1478 1479/** 1480 * Delete grab on given device, update the sprite. 1481 * 1482 * Extension devices are set up for ActivateKeyboardGrab(). 1483 */ 1484void 1485DeactivatePointerGrab(DeviceIntPtr mouse) 1486{ 1487 GrabPtr grab = mouse->deviceGrab.grab; 1488 DeviceIntPtr dev; 1489 Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab && 1490 mouse->deviceGrab.implicitGrab); 1491 1492 mouse->valuator->motionHintWindow = NullWindow; 1493 mouse->deviceGrab.grab = NullGrab; 1494 mouse->deviceGrab.sync.state = NOT_GRABBED; 1495 mouse->deviceGrab.fromPassiveGrab = FALSE; 1496 1497 for (dev = inputInfo.devices; dev; dev = dev->next) 1498 { 1499 if (dev->deviceGrab.sync.other == grab) 1500 dev->deviceGrab.sync.other = NullGrab; 1501 } 1502 DoEnterLeaveEvents(mouse, mouse->id, grab->window, 1503 mouse->spriteInfo->sprite->win, NotifyUngrab); 1504 if (grab->confineTo) 1505 ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE); 1506 PostNewCursor(mouse); 1507 if (grab->cursor) 1508 FreeCursor(grab->cursor, (Cursor)0); 1509 1510 if (!wasImplicit && grab->grabtype == GRABTYPE_XI2) 1511 ReattachToOldMaster(mouse); 1512 1513 ComputeFreezes(); 1514} 1515 1516/** 1517 * Activate a keyboard grab on the given device. 1518 * 1519 * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. 1520 */ 1521void 1522ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive) 1523{ 1524 GrabInfoPtr grabinfo = &keybd->deviceGrab; 1525 WindowPtr oldWin; 1526 1527 /* slave devices need to float for the duration of the grab. */ 1528 if (grab->grabtype == GRABTYPE_XI2 && 1529 !(passive & ImplicitGrabMask) && 1530 !IsMaster(keybd)) 1531 DetachFromMaster(keybd); 1532 1533 if (grabinfo->grab) 1534 oldWin = grabinfo->grab->window; 1535 else if (keybd->focus) 1536 oldWin = keybd->focus->win; 1537 else 1538 oldWin = keybd->spriteInfo->sprite->win; 1539 if (oldWin == FollowKeyboardWin) 1540 oldWin = keybd->focus->win; 1541 if (keybd->valuator) 1542 keybd->valuator->motionHintWindow = NullWindow; 1543 DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); 1544 if (syncEvents.playingEvents) 1545 grabinfo->grabTime = syncEvents.time; 1546 else 1547 grabinfo->grabTime = time; 1548 grabinfo->activeGrab = *grab; 1549 grabinfo->grab = &grabinfo->activeGrab; 1550 grabinfo->fromPassiveGrab = passive; 1551 grabinfo->implicitGrab = passive & ImplicitGrabMask; 1552 CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); 1553} 1554 1555/** 1556 * Delete keyboard grab for the given device. 1557 */ 1558void 1559DeactivateKeyboardGrab(DeviceIntPtr keybd) 1560{ 1561 GrabPtr grab = keybd->deviceGrab.grab; 1562 DeviceIntPtr dev; 1563 WindowPtr focusWin = keybd->focus ? keybd->focus->win 1564 : keybd->spriteInfo->sprite->win; 1565 Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab && 1566 keybd->deviceGrab.implicitGrab); 1567 1568 if (focusWin == FollowKeyboardWin) 1569 focusWin = inputInfo.keyboard->focus->win; 1570 if (keybd->valuator) 1571 keybd->valuator->motionHintWindow = NullWindow; 1572 keybd->deviceGrab.grab = NullGrab; 1573 keybd->deviceGrab.sync.state = NOT_GRABBED; 1574 keybd->deviceGrab.fromPassiveGrab = FALSE; 1575 1576 for (dev = inputInfo.devices; dev; dev = dev->next) 1577 { 1578 if (dev->deviceGrab.sync.other == grab) 1579 dev->deviceGrab.sync.other = NullGrab; 1580 } 1581 DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); 1582 1583 if (!wasImplicit && grab->grabtype == GRABTYPE_XI2) 1584 ReattachToOldMaster(keybd); 1585 1586 ComputeFreezes(); 1587} 1588 1589void 1590AllowSome(ClientPtr client, 1591 TimeStamp time, 1592 DeviceIntPtr thisDev, 1593 int newState) 1594{ 1595 Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; 1596 TimeStamp grabTime; 1597 DeviceIntPtr dev; 1598 GrabInfoPtr devgrabinfo, 1599 grabinfo = &thisDev->deviceGrab; 1600 1601 thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client); 1602 thisSynced = FALSE; 1603 otherGrabbed = FALSE; 1604 othersFrozen = FALSE; 1605 grabTime = grabinfo->grabTime; 1606 for (dev = inputInfo.devices; dev; dev = dev->next) 1607 { 1608 devgrabinfo = &dev->deviceGrab; 1609 1610 if (dev == thisDev) 1611 continue; 1612 if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 1613 { 1614 if (!(thisGrabbed || otherGrabbed) || 1615 (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER)) 1616 grabTime = devgrabinfo->grabTime; 1617 otherGrabbed = TRUE; 1618 if (grabinfo->sync.other == devgrabinfo->grab) 1619 thisSynced = TRUE; 1620 if (devgrabinfo->sync.state >= FROZEN) 1621 othersFrozen = TRUE; 1622 } 1623 } 1624 if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced)) 1625 return; 1626 if ((CompareTimeStamps(time, currentTime) == LATER) || 1627 (CompareTimeStamps(time, grabTime) == EARLIER)) 1628 return; 1629 switch (newState) 1630 { 1631 case THAWED: /* Async */ 1632 if (thisGrabbed) 1633 grabinfo->sync.state = THAWED; 1634 if (thisSynced) 1635 grabinfo->sync.other = NullGrab; 1636 ComputeFreezes(); 1637 break; 1638 case FREEZE_NEXT_EVENT: /* Sync */ 1639 if (thisGrabbed) 1640 { 1641 grabinfo->sync.state = FREEZE_NEXT_EVENT; 1642 if (thisSynced) 1643 grabinfo->sync.other = NullGrab; 1644 ComputeFreezes(); 1645 } 1646 break; 1647 case THAWED_BOTH: /* AsyncBoth */ 1648 if (othersFrozen) 1649 { 1650 for (dev = inputInfo.devices; dev; dev = dev->next) 1651 { 1652 devgrabinfo = &dev->deviceGrab; 1653 if (devgrabinfo->grab 1654 && SameClient(devgrabinfo->grab, client)) 1655 devgrabinfo->sync.state = THAWED; 1656 if (devgrabinfo->sync.other && 1657 SameClient(devgrabinfo->sync.other, client)) 1658 devgrabinfo->sync.other = NullGrab; 1659 } 1660 ComputeFreezes(); 1661 } 1662 break; 1663 case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ 1664 if (othersFrozen) 1665 { 1666 for (dev = inputInfo.devices; dev; dev = dev->next) 1667 { 1668 devgrabinfo = &dev->deviceGrab; 1669 if (devgrabinfo->grab 1670 && SameClient(devgrabinfo->grab, client)) 1671 devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT; 1672 if (devgrabinfo->sync.other 1673 && SameClient(devgrabinfo->sync.other, client)) 1674 devgrabinfo->sync.other = NullGrab; 1675 } 1676 ComputeFreezes(); 1677 } 1678 break; 1679 case NOT_GRABBED: /* Replay */ 1680 if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) 1681 { 1682 if (thisSynced) 1683 grabinfo->sync.other = NullGrab; 1684 syncEvents.replayDev = thisDev; 1685 syncEvents.replayWin = grabinfo->grab->window; 1686 (*grabinfo->DeactivateGrab)(thisDev); 1687 syncEvents.replayDev = (DeviceIntPtr)NULL; 1688 } 1689 break; 1690 case THAW_OTHERS: /* AsyncOthers */ 1691 if (othersFrozen) 1692 { 1693 for (dev = inputInfo.devices; dev; dev = dev->next) 1694 { 1695 if (dev == thisDev) 1696 continue; 1697 devgrabinfo = &dev->deviceGrab; 1698 if (devgrabinfo->grab 1699 && SameClient(devgrabinfo->grab, client)) 1700 devgrabinfo->sync.state = THAWED; 1701 if (devgrabinfo->sync.other 1702 && SameClient(devgrabinfo->sync.other, client)) 1703 devgrabinfo->sync.other = NullGrab; 1704 } 1705 ComputeFreezes(); 1706 } 1707 break; 1708 } 1709} 1710 1711/** 1712 * Server-side protocol handling for AllowEvents request. 1713 * 1714 * Release some events from a frozen device. 1715 */ 1716int 1717ProcAllowEvents(ClientPtr client) 1718{ 1719 TimeStamp time; 1720 DeviceIntPtr mouse = NULL; 1721 DeviceIntPtr keybd = NULL; 1722 REQUEST(xAllowEventsReq); 1723 1724 REQUEST_SIZE_MATCH(xAllowEventsReq); 1725 time = ClientTimeToServerTime(stuff->time); 1726 1727 mouse = PickPointer(client); 1728 keybd = PickKeyboard(client); 1729 1730 switch (stuff->mode) 1731 { 1732 case ReplayPointer: 1733 AllowSome(client, time, mouse, NOT_GRABBED); 1734 break; 1735 case SyncPointer: 1736 AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); 1737 break; 1738 case AsyncPointer: 1739 AllowSome(client, time, mouse, THAWED); 1740 break; 1741 case ReplayKeyboard: 1742 AllowSome(client, time, keybd, NOT_GRABBED); 1743 break; 1744 case SyncKeyboard: 1745 AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); 1746 break; 1747 case AsyncKeyboard: 1748 AllowSome(client, time, keybd, THAWED); 1749 break; 1750 case SyncBoth: 1751 AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); 1752 break; 1753 case AsyncBoth: 1754 AllowSome(client, time, keybd, THAWED_BOTH); 1755 break; 1756 default: 1757 client->errorValue = stuff->mode; 1758 return BadValue; 1759 } 1760 return Success; 1761} 1762 1763/** 1764 * Deactivate grabs from any device that has been grabbed by the client. 1765 */ 1766void 1767ReleaseActiveGrabs(ClientPtr client) 1768{ 1769 DeviceIntPtr dev; 1770 Bool done; 1771 1772 /* XXX CloseDownClient should remove passive grabs before 1773 * releasing active grabs. 1774 */ 1775 do { 1776 done = TRUE; 1777 for (dev = inputInfo.devices; dev; dev = dev->next) 1778 { 1779 if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 1780 { 1781 (*dev->deviceGrab.DeactivateGrab)(dev); 1782 done = FALSE; 1783 } 1784 } 1785 } while (!done); 1786} 1787 1788/************************************************************************** 1789 * The following procedures deal with delivering events * 1790 **************************************************************************/ 1791 1792/** 1793 * Deliver the given events to the given client. 1794 * 1795 * More than one event may be delivered at a time. This is the case with 1796 * DeviceMotionNotifies which may be followed by DeviceValuator events. 1797 * 1798 * TryClientEvents() is the last station before actually writing the events to 1799 * the socket. Anything that is not filtered here, will get delivered to the 1800 * client. 1801 * An event is only delivered if 1802 * - mask and filter match up. 1803 * - no other client has a grab on the device that caused the event. 1804 * 1805 * 1806 * @param client The target client to deliver to. 1807 * @param dev The device the event came from. May be NULL. 1808 * @param pEvents The events to be delivered. 1809 * @param count Number of elements in pEvents. 1810 * @param mask Event mask as set by the window. 1811 * @param filter Mask based on event type. 1812 * @param grab Possible grab on the device that caused the event. 1813 * 1814 * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the 1815 * client. 1816 */ 1817int 1818TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, 1819 int count, Mask mask, Mask filter, GrabPtr grab) 1820{ 1821 int type; 1822 1823#ifdef DEBUG_EVENTS 1824 ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s", 1825 pEvents->u.u.type, pEvents->u.u.detail, mask, 1826 client ? client->index : -1, 1827 (client && client->clientGone) ? " (gone)" : ""); 1828#endif 1829 1830 if (!client || client == serverClient || client->clientGone) { 1831#ifdef DEBUG_EVENTS 1832 ErrorF(" not delivered to fake/dead client\n"); 1833#endif 1834 return 0; 1835 } 1836 1837 if (filter != CantBeFiltered && !(mask & filter)) 1838 { 1839 #ifdef DEBUG_EVENTS 1840 ErrorF(" filtered\n"); 1841 #endif 1842 return 0; 1843 } 1844 1845 if (grab && !SameClient(grab, client)) 1846 { 1847#ifdef DEBUG_EVENTS 1848 ErrorF(" not delivered due to grab\n"); 1849#endif 1850 return -1; /* don't send, but notify caller */ 1851 } 1852 1853 type = pEvents->u.u.type; 1854 if (type == MotionNotify) 1855 { 1856 if (mask & PointerMotionHintMask) 1857 { 1858 if (WID(dev->valuator->motionHintWindow) == 1859 pEvents->u.keyButtonPointer.event) 1860 { 1861#ifdef DEBUG_EVENTS 1862 ErrorF("[dix] \n"); 1863 ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); 1864#endif 1865 return 1; /* don't send, but pretend we did */ 1866 } 1867 pEvents->u.u.detail = NotifyHint; 1868 } 1869 else 1870 { 1871 pEvents->u.u.detail = NotifyNormal; 1872 } 1873 } 1874 else if (type == DeviceMotionNotify) 1875 { 1876 if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer*)pEvents, 1877 mask) != 0) 1878 return 1; 1879 } else if (type == KeyPress) 1880 { 1881 if (EventIsKeyRepeat(pEvents)) 1882 { 1883 if (!_XkbWantsDetectableAutoRepeat(client)) 1884 { 1885 xEvent release = *pEvents; 1886 release.u.u.type = KeyRelease; 1887 WriteEventsToClient(client, 1, &release); 1888#ifdef DEBUG_EVENTS 1889 ErrorF(" (plus fake core release for repeat)"); 1890#endif 1891 } else 1892 { 1893#ifdef DEBUG_EVENTS 1894 ErrorF(" (detectable autorepeat for core)"); 1895#endif 1896 } 1897 } 1898 1899 } else if (type == DeviceKeyPress) 1900 { 1901 if (EventIsKeyRepeat(pEvents)) 1902 { 1903 if (!_XkbWantsDetectableAutoRepeat(client)) 1904 { 1905 deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents; 1906 release.type = DeviceKeyRelease; 1907#ifdef DEBUG_EVENTS 1908 ErrorF(" (plus fake xi1 release for repeat)"); 1909#endif 1910 WriteEventsToClient(client, 1, (xEvent *) &release); 1911 } 1912 else { 1913#ifdef DEBUG_EVENTS 1914 ErrorF(" (detectable autorepeat for core)"); 1915#endif 1916 } 1917 } 1918 } 1919 1920 if (BitIsOn(criticalEvents, type)) 1921 { 1922 if (client->smart_priority < SMART_MAX_PRIORITY) 1923 client->smart_priority++; 1924 SetCriticalOutputPending(); 1925 } 1926 1927 WriteEventsToClient(client, count, pEvents); 1928#ifdef DEBUG_EVENTS 1929 ErrorF("[dix] delivered\n"); 1930#endif 1931 return 1; 1932} 1933 1934/** 1935 * Deliver events to a window. At this point, we do not yet know if the event 1936 * actually needs to be delivered. May activate a grab if the event is a 1937 * button press. 1938 * 1939 * Core events are always delivered to the window owner. If the filter is 1940 * something other than CantBeFiltered, the event is also delivered to other 1941 * clients with the matching mask on the window. 1942 * 1943 * More than one event may be delivered at a time. This is the case with 1944 * DeviceMotionNotifies which may be followed by DeviceValuator events. 1945 * 1946 * @param pWin The window that would get the event. 1947 * @param pEvents The events to be delivered. 1948 * @param count Number of elements in pEvents. 1949 * @param filter Mask based on event type. 1950 * @param grab Possible grab on the device that caused the event. 1951 * 1952 * @return Number of events delivered to various clients. 1953 */ 1954int 1955DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent 1956 *pEvents, int count, Mask filter, GrabPtr grab) 1957{ 1958 int deliveries = 0, nondeliveries = 0; 1959 int attempt; 1960 InputClients *other; 1961 ClientPtr client = NullClient; 1962 Mask deliveryMask = 0; /* If a grab occurs due to a button press, then 1963 this mask is the mask of the grab. */ 1964 int type = pEvents->u.u.type; 1965 1966 1967 /* Deliver to window owner */ 1968 if ((filter == CantBeFiltered) || CORE_EVENT(pEvents)) 1969 { 1970 /* if nobody ever wants to see this event, skip some work */ 1971 if (filter != CantBeFiltered && 1972 !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) 1973 return 0; 1974 1975 if (IsInterferingGrab(wClient(pWin), pDev, pEvents)) 1976 return 0; 1977 1978 if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 1979 /* do nothing */; 1980 else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents, 1981 count, pWin->eventMask, 1982 filter, grab)) ) 1983 { 1984 if (attempt > 0) 1985 { 1986 deliveries++; 1987 client = wClient(pWin); 1988 deliveryMask = pWin->eventMask; 1989 } else 1990 nondeliveries--; 1991 } 1992 } 1993 1994 /* CantBeFiltered means only window owner gets the event */ 1995 if (filter != CantBeFiltered) 1996 { 1997 if (CORE_EVENT(pEvents)) 1998 other = (InputClients *)wOtherClients(pWin); 1999 else if (XI2_EVENT(pEvents)) 2000 { 2001 OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 2002 /* Has any client selected for the event? */ 2003 if (!GetWindowXI2Mask(pDev, pWin, pEvents)) 2004 return 0; 2005 other = inputMasks->inputClients; 2006 } else { 2007 OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 2008 /* Has any client selected for the event? */ 2009 if (!inputMasks || 2010 !(inputMasks->inputEvents[pDev->id] & filter)) 2011 return 0; 2012 2013 other = inputMasks->inputClients; 2014 } 2015 2016 for (; other; other = other->next) 2017 { 2018 Mask mask; 2019 if (IsInterferingGrab(rClient(other), pDev, pEvents)) 2020 continue; 2021 2022 mask = GetEventMask(pDev, pEvents, other); 2023 2024 if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, 2025 pEvents, count)) 2026 /* do nothing */; 2027 else if ( (attempt = TryClientEvents(rClient(other), pDev, 2028 pEvents, count, 2029 mask, filter, grab)) ) 2030 { 2031 if (attempt > 0) 2032 { 2033 deliveries++; 2034 client = rClient(other); 2035 deliveryMask = mask; 2036 } else 2037 nondeliveries--; 2038 } 2039 } 2040 } 2041 /* 2042 * Note that since core events are delivered first, an implicit grab may 2043 * be activated on a core grab, stopping the XI events. 2044 */ 2045 if ((type == DeviceButtonPress || type == ButtonPress || 2046 ((XI2_EVENT(pEvents) && ((xGenericEvent*)pEvents)->evtype == XI_ButtonPress))) 2047 && deliveries 2048 && (!grab)) 2049 { 2050 GrabRec tempGrab; 2051 OtherInputMasks *inputMasks; 2052 2053 memset(&tempGrab, 0, sizeof(GrabRec)); 2054 tempGrab.next = NULL; 2055 tempGrab.device = pDev; 2056 tempGrab.resource = client->clientAsMask; 2057 tempGrab.window = pWin; 2058 tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; 2059 tempGrab.eventMask = deliveryMask; 2060 tempGrab.keyboardMode = GrabModeAsync; 2061 tempGrab.pointerMode = GrabModeAsync; 2062 tempGrab.confineTo = NullWindow; 2063 tempGrab.cursor = NullCursor; 2064 tempGrab.type = type; 2065 if (type == ButtonPress) 2066 tempGrab.grabtype = GRABTYPE_CORE; 2067 else if (type == DeviceButtonPress) 2068 tempGrab.grabtype = GRABTYPE_XI; 2069 else 2070 { 2071 tempGrab.type = ((xGenericEvent*)pEvents)->evtype; 2072 tempGrab.grabtype = GRABTYPE_XI2; 2073 } 2074 2075 /* get the XI and XI2 device mask */ 2076 inputMasks = wOtherInputMasks(pWin); 2077 tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0; 2078 2079 if (inputMasks) 2080 memcpy(tempGrab.xi2mask, inputMasks->xi2mask, 2081 sizeof(tempGrab.xi2mask)); 2082 2083 (*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab, 2084 currentTime, TRUE | ImplicitGrabMask); 2085 } 2086 else if ((type == MotionNotify) && deliveries) 2087 pDev->valuator->motionHintWindow = pWin; 2088 else 2089 { 2090 if ((type == DeviceMotionNotify || type == DeviceButtonPress) && 2091 deliveries) 2092 CheckDeviceGrabAndHintWindow (pWin, type, 2093 (deviceKeyButtonPointer*) pEvents, 2094 grab, client, deliveryMask); 2095 } 2096 if (deliveries) 2097 return deliveries; 2098 return nondeliveries; 2099} 2100 2101/* If the event goes to dontClient, don't send it and return 0. if 2102 send works, return 1 or if send didn't work, return 2. 2103 Only works for core events. 2104*/ 2105 2106#ifdef PANORAMIX 2107static int 2108XineramaTryClientEventsResult( 2109 ClientPtr client, 2110 GrabPtr grab, 2111 Mask mask, 2112 Mask filter 2113){ 2114 if ((client) && (client != serverClient) && (!client->clientGone) && 2115 ((filter == CantBeFiltered) || (mask & filter))) 2116 { 2117 if (grab && !SameClient(grab, client)) return -1; 2118 else return 1; 2119 } 2120 return 0; 2121} 2122#endif 2123 2124/** 2125 * Try to deliver events to the interested parties. 2126 * 2127 * @param pWin The window that would get the event. 2128 * @param pEvents The events to be delivered. 2129 * @param count Number of elements in pEvents. 2130 * @param filter Mask based on event type. 2131 * @param dontClient Don't deliver to the dontClient. 2132 */ 2133int 2134MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, 2135 int count, Mask filter, ClientPtr dontClient) 2136{ 2137 OtherClients *other; 2138 2139 2140 if (pWin->eventMask & filter) 2141 { 2142 if (wClient(pWin) == dontClient) 2143 return 0; 2144#ifdef PANORAMIX 2145 if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 2146 return XineramaTryClientEventsResult( 2147 wClient(pWin), NullGrab, pWin->eventMask, filter); 2148#endif 2149 if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 2150 return 1; /* don't send, but pretend we did */ 2151 return TryClientEvents(wClient(pWin), NULL, pEvents, count, 2152 pWin->eventMask, filter, NullGrab); 2153 } 2154 for (other = wOtherClients(pWin); other; other = other->next) 2155 { 2156 if (other->mask & filter) 2157 { 2158 if (SameClient(other, dontClient)) 2159 return 0; 2160#ifdef PANORAMIX 2161 if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 2162 return XineramaTryClientEventsResult( 2163 rClient(other), NullGrab, other->mask, filter); 2164#endif 2165 if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, 2166 count)) 2167 return 1; /* don't send, but pretend we did */ 2168 return TryClientEvents(rClient(other), NULL, pEvents, count, 2169 other->mask, filter, NullGrab); 2170 } 2171 } 2172 return 2; 2173} 2174 2175static Window FindChildForEvent(SpritePtr pSprite, WindowPtr event) 2176{ 2177 WindowPtr w = pSprite->spriteTrace[pSprite->spriteTraceGood-1]; 2178 Window child = None; 2179 2180 /* If the search ends up past the root should the child field be 2181 set to none or should the value in the argument be passed 2182 through. It probably doesn't matter since everyone calls 2183 this function with child == None anyway. */ 2184 while (w) 2185 { 2186 /* If the source window is same as event window, child should be 2187 none. Don't bother going all all the way back to the root. */ 2188 2189 if (w == event) 2190 { 2191 child = None; 2192 break; 2193 } 2194 2195 if (w->parent == event) 2196 { 2197 child = w->drawable.id; 2198 break; 2199 } 2200 w = w->parent; 2201 } 2202 return child; 2203} 2204 2205/** 2206 * Adjust event fields to comply with the window properties. 2207 * 2208 * @param xE Event to be modified in place 2209 * @param pWin The window to get the information from. 2210 * @param child Child window setting for event (if applicable) 2211 * @param calcChild If True, calculate the child window. 2212 */ 2213void 2214FixUpEventFromWindow( 2215 SpritePtr pSprite, 2216 xEvent *xE, 2217 WindowPtr pWin, 2218 Window child, 2219 Bool calcChild) 2220{ 2221 if (calcChild) 2222 child = FindChildForEvent(pSprite, pWin); 2223 2224 if (XI2_EVENT(xE)) 2225 { 2226 xXIDeviceEvent* event = (xXIDeviceEvent*)xE; 2227 2228 if (event->evtype == XI_RawKeyPress || 2229 event->evtype == XI_RawKeyRelease || 2230 event->evtype == XI_RawButtonPress || 2231 event->evtype == XI_RawButtonRelease || 2232 event->evtype == XI_RawMotion || 2233 event->evtype == XI_DeviceChanged || 2234 event->evtype == XI_HierarchyChanged || 2235 event->evtype == XI_PropertyEvent) 2236 return; 2237 2238 event->root = RootWindow(pSprite)->drawable.id; 2239 event->event = pWin->drawable.id; 2240 if (pSprite->hot.pScreen == pWin->drawable.pScreen) 2241 { 2242 event->event_x = event->root_x - FP1616(pWin->drawable.x, 0); 2243 event->event_y = event->root_y - FP1616(pWin->drawable.y, 0); 2244 event->child = child; 2245 } else 2246 { 2247 event->event_x = 0; 2248 event->event_y = 0; 2249 event->child = None; 2250 } 2251 2252 if (event->evtype == XI_Enter || event->evtype == XI_Leave || 2253 event->evtype == XI_FocusIn || event->evtype == XI_FocusOut) 2254 ((xXIEnterEvent*)event)->same_screen = 2255 (pSprite->hot.pScreen == pWin->drawable.pScreen); 2256 2257 } else 2258 { 2259 XE_KBPTR.root = RootWindow(pSprite)->drawable.id; 2260 XE_KBPTR.event = pWin->drawable.id; 2261 if (pSprite->hot.pScreen == pWin->drawable.pScreen) 2262 { 2263 XE_KBPTR.sameScreen = xTrue; 2264 XE_KBPTR.child = child; 2265 XE_KBPTR.eventX = 2266 XE_KBPTR.rootX - pWin->drawable.x; 2267 XE_KBPTR.eventY = 2268 XE_KBPTR.rootY - pWin->drawable.y; 2269 } 2270 else 2271 { 2272 XE_KBPTR.sameScreen = xFalse; 2273 XE_KBPTR.child = None; 2274 XE_KBPTR.eventX = 0; 2275 XE_KBPTR.eventY = 0; 2276 } 2277 } 2278} 2279 2280/** 2281 * Check if a given event is deliverable at all on a given window. 2282 * 2283 * This function only checks if any client wants it, not for a specific 2284 * client. 2285 * 2286 * @param[in] dev The device this event is being sent for. 2287 * @param[in] event The event that is to be sent. 2288 * @param[in] win The current event window. 2289 * 2290 * @return Bitmask of ::XI2_MASK, ::XI_MASK, ::CORE_MASK, and 2291 * ::DONT_PROPAGATE_MASK. 2292 */ 2293int 2294EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win) 2295{ 2296 int rc = 0; 2297 int filter = 0; 2298 int type; 2299 OtherInputMasks *inputMasks = wOtherInputMasks(win); 2300 xEvent ev; 2301 2302 /* XXX: this makes me gag */ 2303 type = GetXI2Type(event); 2304 ev.u.u.type = GenericEvent; /* GetEventFilter only cares about type and evtype*/ 2305 ((xGenericEvent*)&ev)->extension = IReqCode; 2306 ((xGenericEvent*)&ev)->evtype = type; 2307 filter = GetEventFilter(dev, &ev); 2308 if (type && inputMasks && 2309 ((inputMasks->xi2mask[XIAllDevices][type/8] & filter) || 2310 ((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) || 2311 (inputMasks->xi2mask[dev->id][type/8] & filter))) 2312 rc |= XI2_MASK; 2313 2314 type = GetXIType(event); 2315 ev.u.u.type = type; 2316 filter = GetEventFilter(dev, &ev); 2317 2318 /* Check for XI mask */ 2319 if (type && inputMasks && 2320 (inputMasks->deliverableEvents[dev->id] & filter) && 2321 (inputMasks->inputEvents[dev->id] & filter)) 2322 rc |= XI_MASK; 2323 2324 /* Check for XI DontPropagate mask */ 2325 if (type && inputMasks && 2326 (inputMasks->dontPropagateMask[dev->id] & filter)) 2327 rc |= DONT_PROPAGATE_MASK; 2328 2329 /* Check for core mask */ 2330 type = GetCoreType(event); 2331 if (type && (win->deliverableEvents & filter) && 2332 ((wOtherEventMasks(win) | win->eventMask) & filter)) 2333 rc |= CORE_MASK; 2334 2335 /* Check for core DontPropagate mask */ 2336 if (type && (filter & wDontPropagateMask(win))) 2337 rc |= DONT_PROPAGATE_MASK; 2338 2339 return rc; 2340} 2341 2342/** 2343 * Deliver events caused by input devices. 2344 * 2345 * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is 2346 * called directly from the processInputProc. 2347 * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call 2348 * DeliverDeviceEvents. 2349 * For focused events, DeliverFocusedEvent is called first, and _may_ call 2350 * DeliverDeviceEvents. 2351 * 2352 * @param pWin Window to deliver event to. 2353 * @param event The events to deliver, not yet in wire format. 2354 * @param grab Possible grab on a device. 2355 * @param stopAt Don't recurse up to the root window. 2356 * @param dev The device that is responsible for the event. 2357 * 2358 * @see DeliverGrabbedEvent 2359 * @see DeliverFocusedEvent 2360 */ 2361int 2362DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, 2363 WindowPtr stopAt, DeviceIntPtr dev) 2364{ 2365 SpritePtr pSprite = dev->spriteInfo->sprite; 2366 Window child = None; 2367 Mask filter; 2368 int deliveries = 0; 2369 xEvent core; 2370 xEvent *xE = NULL; 2371 int rc, mask, count = 0; 2372 2373 CHECKEVENT(event); 2374 2375 while (pWin) 2376 { 2377 if ((mask = EventIsDeliverable(dev, event, pWin))) 2378 { 2379 /* XI2 events first */ 2380 if (mask & XI2_MASK) 2381 { 2382 xEvent *xi2 = NULL; 2383 rc = EventToXI2(event, &xi2); 2384 if (rc == Success) 2385 { 2386 /* XXX: XACE */ 2387 filter = GetEventFilter(dev, xi2); 2388 FixUpEventFromWindow(pSprite, xi2, pWin, child, FALSE); 2389 deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1, 2390 filter, grab); 2391 free(xi2); 2392 if (deliveries > 0) 2393 goto unwind; 2394 } else if (rc != BadMatch) 2395 ErrorF("[dix] %s: XI2 conversion failed in DDE (%d).\n", 2396 dev->name, rc); 2397 } 2398 2399 /* XI events */ 2400 if (mask & XI_MASK) 2401 { 2402 rc = EventToXI(event, &xE, &count); 2403 if (rc == Success) { 2404 if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count) == Success) { 2405 filter = GetEventFilter(dev, xE); 2406 FixUpEventFromWindow(pSprite, xE, pWin, child, FALSE); 2407 deliveries = DeliverEventsToWindow(dev, pWin, xE, count, 2408 filter, grab); 2409 if (deliveries > 0) 2410 goto unwind; 2411 } 2412 } else if (rc != BadMatch) 2413 ErrorF("[dix] %s: XI conversion failed in DDE (%d, %d). Skipping delivery.\n", 2414 dev->name, event->any.type, rc); 2415 } 2416 2417 /* Core event */ 2418 if ((mask & CORE_MASK) && IsMaster(dev) && dev->coreEvents) 2419 { 2420 rc = EventToCore(event, &core); 2421 if (rc == Success) { 2422 if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) { 2423 filter = GetEventFilter(dev, &core); 2424 FixUpEventFromWindow(pSprite, &core, pWin, child, FALSE); 2425 deliveries = DeliverEventsToWindow(dev, pWin, &core, 1, 2426 filter, grab); 2427 if (deliveries > 0) 2428 goto unwind; 2429 } 2430 } else if (rc != BadMatch) 2431 ErrorF("[dix] %s: Core conversion failed in DDE (%d, %d).\n", 2432 dev->name, event->any.type, rc); 2433 } 2434 2435 if ((deliveries < 0) || (pWin == stopAt) || 2436 (mask & DONT_PROPAGATE_MASK)) 2437 { 2438 deliveries = 0; 2439 goto unwind; 2440 } 2441 } 2442 2443 child = pWin->drawable.id; 2444 pWin = pWin->parent; 2445 } 2446 2447unwind: 2448 free(xE); 2449 return deliveries; 2450} 2451 2452#undef XI_MASK 2453#undef CORE_MASK 2454#undef DONT_PROPAGATE_MASK 2455 2456/** 2457 * Deliver event to a window and it's immediate parent. Used for most window 2458 * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that 2459 * propagate up the tree or extension events 2460 * 2461 * In case of a ReparentNotify event, the event will be delivered to the 2462 * otherParent as well. 2463 * 2464 * @param pWin Window to deliver events to. 2465 * @param xE Events to deliver. 2466 * @param count number of events in xE. 2467 * @param otherParent Used for ReparentNotify events. 2468 */ 2469int 2470DeliverEvents(WindowPtr pWin, xEvent *xE, int count, 2471 WindowPtr otherParent) 2472{ 2473 Mask filter; 2474 int deliveries; 2475 DeviceIntRec dummy; 2476 2477#ifdef PANORAMIX 2478 if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 2479 return count; 2480#endif 2481 2482 if (!count) 2483 return 0; 2484 2485 dummy.id = XIAllDevices; 2486 filter = GetEventFilter(&dummy, xE); 2487 if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) 2488 xE->u.destroyNotify.event = pWin->drawable.id; 2489 if (filter != StructureAndSubMask) 2490 return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab); 2491 deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count, 2492 StructureNotifyMask, NullGrab); 2493 if (pWin->parent) 2494 { 2495 xE->u.destroyNotify.event = pWin->parent->drawable.id; 2496 deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count, 2497 SubstructureNotifyMask, NullGrab); 2498 if (xE->u.u.type == ReparentNotify) 2499 { 2500 xE->u.destroyNotify.event = otherParent->drawable.id; 2501 deliveries += DeliverEventsToWindow(&dummy, 2502 otherParent, xE, count, SubstructureNotifyMask, 2503 NullGrab); 2504 } 2505 } 2506 return deliveries; 2507} 2508 2509 2510static Bool 2511PointInBorderSize(WindowPtr pWin, int x, int y) 2512{ 2513 BoxRec box; 2514 2515 if(RegionContainsPoint(&pWin->borderSize, x, y, &box)) 2516 return TRUE; 2517 2518#ifdef PANORAMIX 2519 if(!noPanoramiXExtension && 2520 XineramaSetWindowPntrs(inputInfo.pointer, pWin)) { 2521 SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite; 2522 int i; 2523 2524 for(i = 1; i < PanoramiXNumScreens; i++) { 2525 if(RegionContainsPoint(&pSprite->windows[i]->borderSize, 2526 x + screenInfo.screens[0]->x - screenInfo.screens[i]->x, 2527 y + screenInfo.screens[0]->y - screenInfo.screens[i]->y, 2528 &box)) 2529 return TRUE; 2530 } 2531 } 2532#endif 2533 return FALSE; 2534} 2535 2536/** 2537 * Traversed from the root window to the window at the position x/y. While 2538 * traversing, it sets up the traversal history in the spriteTrace array. 2539 * After completing, the spriteTrace history is set in the following way: 2540 * spriteTrace[0] ... root window 2541 * spriteTrace[1] ... top level window that encloses x/y 2542 * ... 2543 * spriteTrace[spriteTraceGood - 1] ... window at x/y 2544 * 2545 * @returns the window at the given coordinates. 2546 */ 2547WindowPtr 2548XYToWindow(SpritePtr pSprite, int x, int y) 2549{ 2550 WindowPtr pWin; 2551 BoxRec box; 2552 2553 pSprite->spriteTraceGood = 1; /* root window still there */ 2554 pWin = RootWindow(pSprite)->firstChild; 2555 while (pWin) 2556 { 2557 if ((pWin->mapped) && 2558 (x >= pWin->drawable.x - wBorderWidth (pWin)) && 2559 (x < pWin->drawable.x + (int)pWin->drawable.width + 2560 wBorderWidth(pWin)) && 2561 (y >= pWin->drawable.y - wBorderWidth (pWin)) && 2562 (y < pWin->drawable.y + (int)pWin->drawable.height + 2563 wBorderWidth (pWin)) 2564 /* When a window is shaped, a further check 2565 * is made to see if the point is inside 2566 * borderSize 2567 */ 2568 && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) 2569 && (!wInputShape(pWin) || 2570 RegionContainsPoint(wInputShape(pWin), 2571 x - pWin->drawable.x, 2572 y - pWin->drawable.y, &box)) 2573#ifdef ROOTLESS 2574 /* In rootless mode windows may be offscreen, even when 2575 * they're in X's stack. (E.g. if the native window system 2576 * implements some form of virtual desktop system). 2577 */ 2578 && !pWin->rootlessUnhittable 2579#endif 2580 ) 2581 { 2582 if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) 2583 { 2584 pSprite->spriteTraceSize += 10; 2585 pSprite->spriteTrace = realloc(pSprite->spriteTrace, 2586 pSprite->spriteTraceSize*sizeof(WindowPtr)); 2587 } 2588 pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin; 2589 pWin = pWin->firstChild; 2590 } 2591 else 2592 pWin = pWin->nextSib; 2593 } 2594 return pSprite->spriteTrace[pSprite->spriteTraceGood-1]; 2595} 2596 2597/** 2598 * Ungrab a currently FocusIn grabbed device and grab the device on the 2599 * given window. If the win given is the NoneWin, the device is ungrabbed if 2600 * applicable and FALSE is returned. 2601 * 2602 * @returns TRUE if the device has been grabbed, or FALSE otherwise. 2603 */ 2604BOOL 2605ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 2606{ 2607 BOOL rc = FALSE; 2608 DeviceEvent event; 2609 2610 if (dev->deviceGrab.grab) 2611 { 2612 if (!dev->deviceGrab.fromPassiveGrab || 2613 dev->deviceGrab.grab->type != XI_Enter || 2614 dev->deviceGrab.grab->window == win || 2615 IsParent(dev->deviceGrab.grab->window, win)) 2616 return FALSE; 2617 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 2618 (*dev->deviceGrab.DeactivateGrab)(dev); 2619 } 2620 2621 if (win == NoneWin || win == PointerRootWin) 2622 return FALSE; 2623 2624 memset(&event, 0, sizeof(DeviceEvent)); 2625 event.header = ET_Internal; 2626 event.type = ET_FocusIn; 2627 event.length = sizeof(DeviceEvent); 2628 event.time = GetTimeInMillis(); 2629 event.deviceid = dev->id; 2630 event.sourceid = dev->id; 2631 event.detail.button = 0; 2632 rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL); 2633 if (rc) 2634 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 2635 return rc; 2636} 2637 2638/** 2639 * Ungrab a currently Enter grabbed device and grab the device for the given 2640 * window. 2641 * 2642 * @returns TRUE if the device has been grabbed, or FALSE otherwise. 2643 */ 2644static BOOL 2645ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 2646{ 2647 BOOL rc = FALSE; 2648 DeviceEvent event; 2649 2650 if (dev->deviceGrab.grab) 2651 { 2652 if (!dev->deviceGrab.fromPassiveGrab || 2653 dev->deviceGrab.grab->type != XI_Enter || 2654 dev->deviceGrab.grab->window == win || 2655 IsParent(dev->deviceGrab.grab->window, win)) 2656 return FALSE; 2657 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 2658 (*dev->deviceGrab.DeactivateGrab)(dev); 2659 } 2660 2661 memset(&event, 0, sizeof(DeviceEvent)); 2662 event.header = ET_Internal; 2663 event.type = ET_Enter; 2664 event.length = sizeof(DeviceEvent); 2665 event.time = GetTimeInMillis(); 2666 event.deviceid = dev->id; 2667 event.sourceid = dev->id; 2668 event.detail.button = 0; 2669 rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL); 2670 if (rc) 2671 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 2672 return rc; 2673} 2674 2675/** 2676 * Update the sprite coordinates based on the event. Update the cursor 2677 * position, then update the event with the new coordinates that may have been 2678 * changed. If the window underneath the sprite has changed, change to new 2679 * cursor and send enter/leave events. 2680 * 2681 * CheckMotion() will not do anything and return FALSE if the event is not a 2682 * pointer event. 2683 * 2684 * @return TRUE if the sprite has moved or FALSE otherwise. 2685 */ 2686Bool 2687CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) 2688{ 2689 WindowPtr prevSpriteWin, newSpriteWin; 2690 SpritePtr pSprite = pDev->spriteInfo->sprite; 2691 2692 CHECKEVENT(ev); 2693 2694 prevSpriteWin = pSprite->win; 2695 2696 if (ev && !syncEvents.playingEvents) 2697 { 2698 /* GetPointerEvents() guarantees that pointer events have the correct 2699 rootX/Y set already. */ 2700 switch (ev->type) 2701 { 2702 case ET_ButtonPress: 2703 case ET_ButtonRelease: 2704 case ET_Motion: 2705 break; 2706 default: 2707 /* all other events return FALSE */ 2708 return FALSE; 2709 } 2710 2711 2712#ifdef PANORAMIX 2713 if (!noPanoramiXExtension) 2714 { 2715 /* Motion events entering DIX get translated to Screen 0 2716 coordinates. Replayed events have already been 2717 translated since they've entered DIX before */ 2718 ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 2719 ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 2720 } else 2721#endif 2722 { 2723 if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) 2724 { 2725 pSprite->hot.pScreen = pSprite->hotPhys.pScreen; 2726 RootWindow(pDev->spriteInfo->sprite) = 2727 pSprite->hot.pScreen->root; 2728 } 2729 } 2730 2731 pSprite->hot.x = ev->root_x; 2732 pSprite->hot.y = ev->root_y; 2733 if (pSprite->hot.x < pSprite->physLimits.x1) 2734 pSprite->hot.x = pSprite->physLimits.x1; 2735 else if (pSprite->hot.x >= pSprite->physLimits.x2) 2736 pSprite->hot.x = pSprite->physLimits.x2 - 1; 2737 if (pSprite->hot.y < pSprite->physLimits.y1) 2738 pSprite->hot.y = pSprite->physLimits.y1; 2739 else if (pSprite->hot.y >= pSprite->physLimits.y2) 2740 pSprite->hot.y = pSprite->physLimits.y2 - 1; 2741 if (pSprite->hotShape) 2742 ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y); 2743 pSprite->hotPhys = pSprite->hot; 2744 2745 if ((pSprite->hotPhys.x != ev->root_x) || 2746 (pSprite->hotPhys.y != ev->root_y)) 2747 { 2748#ifdef PANORAMIX 2749 if (!noPanoramiXExtension) 2750 { 2751 XineramaSetCursorPosition( 2752 pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE); 2753 } else 2754#endif 2755 { 2756 (*pSprite->hotPhys.pScreen->SetCursorPosition)( 2757 pDev, pSprite->hotPhys.pScreen, 2758 pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE); 2759 } 2760 } 2761 2762 ev->root_x = pSprite->hot.x; 2763 ev->root_y = pSprite->hot.y; 2764 } 2765 2766 newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y); 2767 2768 if (newSpriteWin != prevSpriteWin) 2769 { 2770 int sourceid; 2771 if (!ev) { 2772 UpdateCurrentTimeIf(); 2773 sourceid = pDev->id; /* when from WindowsRestructured */ 2774 } else 2775 sourceid = ev->sourceid; 2776 2777 if (prevSpriteWin != NullWindow) { 2778 if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin)) 2779 DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin, 2780 newSpriteWin, NotifyNormal); 2781 } 2782 /* set pSprite->win after ActivateEnterGrab, otherwise 2783 sprite window == grab_window and no enter/leave events are 2784 sent. */ 2785 pSprite->win = newSpriteWin; 2786 PostNewCursor(pDev); 2787 return FALSE; 2788 } 2789 return TRUE; 2790} 2791 2792/** 2793 * Windows have restructured, we need to update the sprite position and the 2794 * sprite's cursor. 2795 */ 2796void 2797WindowsRestructured(void) 2798{ 2799 DeviceIntPtr pDev = inputInfo.devices; 2800 while(pDev) 2801 { 2802 if (IsMaster(pDev) || !pDev->u.master) 2803 CheckMotion(NULL, pDev); 2804 pDev = pDev->next; 2805 } 2806} 2807 2808#ifdef PANORAMIX 2809/* This was added to support reconfiguration under Xdmx. The problem is 2810 * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin 2811 * other than 0,0, the information in the private sprite structure must 2812 * be updated accordingly, or XYToWindow (and other routines) will not 2813 * compute correctly. */ 2814void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff) 2815{ 2816 GrabPtr grab; 2817 DeviceIntPtr pDev; 2818 SpritePtr pSprite; 2819 2820 if (noPanoramiXExtension) return; 2821 2822 pDev = inputInfo.devices; 2823 while(pDev) 2824 { 2825 if (DevHasCursor(pDev)) 2826 { 2827 pSprite = pDev->spriteInfo->sprite; 2828 pSprite->hot.x -= xoff; 2829 pSprite->hot.y -= yoff; 2830 2831 pSprite->hotPhys.x -= xoff; 2832 pSprite->hotPhys.y -= yoff; 2833 2834 pSprite->hotLimits.x1 -= xoff; 2835 pSprite->hotLimits.y1 -= yoff; 2836 pSprite->hotLimits.x2 -= xoff; 2837 pSprite->hotLimits.y2 -= yoff; 2838 2839 if (RegionNotEmpty(&pSprite->Reg1)) 2840 RegionTranslate(&pSprite->Reg1, xoff, yoff); 2841 if (RegionNotEmpty(&pSprite->Reg2)) 2842 RegionTranslate(&pSprite->Reg2, xoff, yoff); 2843 2844 /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ 2845 if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 2846 if (grab->confineTo->drawable.pScreen 2847 != pSprite->hotPhys.pScreen) 2848 pSprite->hotPhys.x = pSprite->hotPhys.y = 0; 2849 ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 2850 } else 2851 ConfineCursorToWindow( 2852 pDev, 2853 pSprite->hotPhys.pScreen->root, 2854 TRUE, FALSE); 2855 2856 } 2857 pDev = pDev->next; 2858 } 2859} 2860#endif 2861 2862/** 2863 * Initialize a sprite for the given device and set it to some sane values. If 2864 * the device already has a sprite alloc'd, don't realloc but just reset to 2865 * default values. 2866 * If a window is supplied, the sprite will be initialized with the window's 2867 * cursor and positioned in the center of the window's screen. The root window 2868 * is a good choice to pass in here. 2869 * 2870 * It's a good idea to call it only for pointer devices, unless you have a 2871 * really talented keyboard. 2872 * 2873 * @param pDev The device to initialize. 2874 * @param pWin The window where to generate the sprite in. 2875 * 2876 */ 2877void 2878InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) 2879{ 2880 SpritePtr pSprite; 2881 ScreenPtr pScreen; 2882 CursorPtr pCursor; 2883 2884 if (!pDev->spriteInfo->sprite) 2885 { 2886 DeviceIntPtr it; 2887 2888 pDev->spriteInfo->sprite = (SpritePtr)calloc(1, sizeof(SpriteRec)); 2889 if (!pDev->spriteInfo->sprite) 2890 FatalError("InitializeSprite: failed to allocate sprite struct"); 2891 2892 /* We may have paired another device with this device before our 2893 * device had a actual sprite. We need to check for this and reset the 2894 * sprite field for all paired devices. 2895 * 2896 * The VCK is always paired with the VCP before the VCP has a sprite. 2897 */ 2898 for (it = inputInfo.devices; it; it = it->next) 2899 { 2900 if (it->spriteInfo->paired == pDev) 2901 it->spriteInfo->sprite = pDev->spriteInfo->sprite; 2902 } 2903 if (inputInfo.keyboard->spriteInfo->paired == pDev) 2904 inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite; 2905 } 2906 2907 pSprite = pDev->spriteInfo->sprite; 2908 pDev->spriteInfo->spriteOwner = TRUE; 2909 2910 pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL; 2911 pSprite->hot.pScreen = pScreen; 2912 pSprite->hotPhys.pScreen = pScreen; 2913 if (pScreen) 2914 { 2915 pSprite->hotPhys.x = pScreen->width / 2; 2916 pSprite->hotPhys.y = pScreen->height / 2; 2917 pSprite->hotLimits.x2 = pScreen->width; 2918 pSprite->hotLimits.y2 = pScreen->height; 2919 } 2920 2921 pSprite->hot = pSprite->hotPhys; 2922 pSprite->win = pWin; 2923 2924 if (pWin) 2925 { 2926 pCursor = wCursor(pWin); 2927 pSprite->spriteTrace = (WindowPtr *)calloc(1, 32*sizeof(WindowPtr)); 2928 if (!pSprite->spriteTrace) 2929 FatalError("Failed to allocate spriteTrace"); 2930 pSprite->spriteTraceSize = 32; 2931 2932 RootWindow(pDev->spriteInfo->sprite) = pWin; 2933 pSprite->spriteTraceGood = 1; 2934 2935 pSprite->pEnqueueScreen = pScreen; 2936 pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 2937 2938 } else { 2939 pCursor = NullCursor; 2940 pSprite->spriteTrace = NULL; 2941 pSprite->spriteTraceSize = 0; 2942 pSprite->spriteTraceGood = 0; 2943 pSprite->pEnqueueScreen = screenInfo.screens[0]; 2944 pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 2945 } 2946 if (pCursor) 2947 pCursor->refcnt++; 2948 if (pSprite->current) 2949 FreeCursor(pSprite->current, None); 2950 pSprite->current = pCursor; 2951 2952 if (pScreen) 2953 { 2954 (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current); 2955 (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current, 2956 &pSprite->hotLimits, &pSprite->physLimits); 2957 pSprite->confined = FALSE; 2958 2959 (*pScreen->ConstrainCursor) (pDev, pScreen, 2960 &pSprite->physLimits); 2961 (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x, 2962 pSprite->hot.y, 2963 FALSE); 2964 (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 2965 } 2966#ifdef PANORAMIX 2967 if(!noPanoramiXExtension) { 2968 pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 2969 pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 2970 pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 2971 pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 2972 pSprite->physLimits = pSprite->hotLimits; 2973 pSprite->confineWin = NullWindow; 2974 pSprite->hotShape = NullRegion; 2975 pSprite->screen = pScreen; 2976 /* gotta UNINIT these someplace */ 2977 RegionNull(&pSprite->Reg1); 2978 RegionNull(&pSprite->Reg2); 2979 } 2980#endif 2981} 2982 2983/** 2984 * Update the mouse sprite info when the server switches from a pScreen to another. 2985 * Otherwise, the pScreen of the mouse sprite is never updated when we switch 2986 * from a pScreen to another. Never updating the pScreen of the mouse sprite 2987 * implies that windows that are in pScreen whose pScreen->myNum >0 will never 2988 * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen 2989 * always points to the first pScreen it has been set by 2990 * DefineInitialRootWindow(). 2991 * 2992 * Calling this function is useful for use cases where the server 2993 * has more than one pScreen. 2994 * This function is similar to DefineInitialRootWindow() but it does not 2995 * reset the mouse pointer position. 2996 * @param win must be the new pScreen we are switching to. 2997 */ 2998void 2999UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) 3000{ 3001 SpritePtr pSprite = NULL; 3002 WindowPtr win = NULL; 3003 CursorPtr pCursor; 3004 if (!pScreen) 3005 return ; 3006 3007 if (!pDev->spriteInfo->sprite) 3008 return; 3009 3010 pSprite = pDev->spriteInfo->sprite; 3011 3012 win = pScreen->root; 3013 3014 pSprite->hotPhys.pScreen = pScreen; 3015 pSprite->hot = pSprite->hotPhys; 3016 pSprite->hotLimits.x2 = pScreen->width; 3017 pSprite->hotLimits.y2 = pScreen->height; 3018 pSprite->win = win; 3019 pCursor = wCursor(win); 3020 if (pCursor) 3021 pCursor->refcnt++; 3022 if (pSprite->current) 3023 FreeCursor(pSprite->current, 0); 3024 pSprite->current = pCursor; 3025 pSprite->spriteTraceGood = 1; 3026 pSprite->spriteTrace[0] = win; 3027 (*pScreen->CursorLimits) (pDev, 3028 pScreen, 3029 pSprite->current, 3030 &pSprite->hotLimits, 3031 &pSprite->physLimits); 3032 pSprite->confined = FALSE; 3033 (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 3034 (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 3035 3036#ifdef PANORAMIX 3037 if(!noPanoramiXExtension) { 3038 pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 3039 pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 3040 pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 3041 pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 3042 pSprite->physLimits = pSprite->hotLimits; 3043 pSprite->screen = pScreen; 3044 } 3045#endif 3046} 3047 3048/* 3049 * This does not take any shortcuts, and even ignores its argument, since 3050 * it does not happen very often, and one has to walk up the tree since 3051 * this might be a newly instantiated cursor for an intermediate window 3052 * between the one the pointer is in and the one that the last cursor was 3053 * instantiated from. 3054 */ 3055void 3056WindowHasNewCursor(WindowPtr pWin) 3057{ 3058 DeviceIntPtr pDev; 3059 3060 for(pDev = inputInfo.devices; pDev; pDev = pDev->next) 3061 if (DevHasCursor(pDev)) 3062 PostNewCursor(pDev); 3063} 3064 3065void 3066NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y) 3067{ 3068 SpritePtr pSprite = pDev->spriteInfo->sprite; 3069 3070 pSprite->hotPhys.x = x; 3071 pSprite->hotPhys.y = y; 3072#ifdef PANORAMIX 3073 if(!noPanoramiXExtension) { 3074 pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x; 3075 pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y; 3076 if (newScreen != pSprite->screen) { 3077 pSprite->screen = newScreen; 3078 /* Make sure we tell the DDX to update its copy of the screen */ 3079 if(pSprite->confineWin) 3080 XineramaConfineCursorToWindow(pDev, 3081 pSprite->confineWin, TRUE); 3082 else 3083 XineramaConfineCursorToWindow(pDev, screenInfo.screens[0]->root, TRUE); 3084 /* if the pointer wasn't confined, the DDX won't get 3085 told of the pointer warp so we reposition it here */ 3086 if(!syncEvents.playingEvents) 3087 (*pSprite->screen->SetCursorPosition)( 3088 pDev, 3089 pSprite->screen, 3090 pSprite->hotPhys.x + screenInfo.screens[0]->x - 3091 pSprite->screen->x, 3092 pSprite->hotPhys.y + screenInfo.screens[0]->y - 3093 pSprite->screen->y, FALSE); 3094 } 3095 } else 3096#endif 3097 if (newScreen != pSprite->hotPhys.pScreen) 3098 ConfineCursorToWindow(pDev, newScreen->root, TRUE, FALSE); 3099} 3100 3101#ifdef PANORAMIX 3102 3103static Bool 3104XineramaPointInWindowIsVisible( 3105 WindowPtr pWin, 3106 int x, 3107 int y 3108) 3109{ 3110 BoxRec box; 3111 int i, xoff, yoff; 3112 3113 if (!pWin->realized) return FALSE; 3114 3115 if (RegionContainsPoint(&pWin->borderClip, x, y, &box)) 3116 return TRUE; 3117 3118 if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE; 3119 3120 xoff = x + screenInfo.screens[0]->x; 3121 yoff = y + screenInfo.screens[0]->y; 3122 3123 for(i = 1; i < PanoramiXNumScreens; i++) { 3124 pWin = inputInfo.pointer->spriteInfo->sprite->windows[i]; 3125 x = xoff - screenInfo.screens[i]->x; 3126 y = yoff - screenInfo.screens[i]->y; 3127 3128 if(RegionContainsPoint(&pWin->borderClip, x, y, &box) 3129 && (!wInputShape(pWin) || 3130 RegionContainsPoint(wInputShape(pWin), 3131 x - pWin->drawable.x, 3132 y - pWin->drawable.y, &box))) 3133 return TRUE; 3134 3135 } 3136 3137 return FALSE; 3138} 3139 3140static int 3141XineramaWarpPointer(ClientPtr client) 3142{ 3143 WindowPtr dest = NULL; 3144 int x, y, rc; 3145 SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 3146 3147 REQUEST(xWarpPointerReq); 3148 3149 3150 if (stuff->dstWid != None) { 3151 rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess); 3152 if (rc != Success) 3153 return rc; 3154 } 3155 x = pSprite->hotPhys.x; 3156 y = pSprite->hotPhys.y; 3157 3158 if (stuff->srcWid != None) 3159 { 3160 int winX, winY; 3161 XID winID = stuff->srcWid; 3162 WindowPtr source; 3163 3164 rc = dixLookupWindow(&source, winID, client, DixReadAccess); 3165 if (rc != Success) 3166 return rc; 3167 3168 winX = source->drawable.x; 3169 winY = source->drawable.y; 3170 if(source == screenInfo.screens[0]->root) { 3171 winX -= screenInfo.screens[0]->x; 3172 winY -= screenInfo.screens[0]->y; 3173 } 3174 if (x < winX + stuff->srcX || 3175 y < winY + stuff->srcY || 3176 (stuff->srcWidth != 0 && 3177 winX + stuff->srcX + (int)stuff->srcWidth < x) || 3178 (stuff->srcHeight != 0 && 3179 winY + stuff->srcY + (int)stuff->srcHeight < y) || 3180 !XineramaPointInWindowIsVisible(source, x, y)) 3181 return Success; 3182 } 3183 if (dest) { 3184 x = dest->drawable.x; 3185 y = dest->drawable.y; 3186 if(dest == screenInfo.screens[0]->root) { 3187 x -= screenInfo.screens[0]->x; 3188 y -= screenInfo.screens[0]->y; 3189 } 3190 } 3191 3192 x += stuff->dstX; 3193 y += stuff->dstY; 3194 3195 if (x < pSprite->physLimits.x1) 3196 x = pSprite->physLimits.x1; 3197 else if (x >= pSprite->physLimits.x2) 3198 x = pSprite->physLimits.x2 - 1; 3199 if (y < pSprite->physLimits.y1) 3200 y = pSprite->physLimits.y1; 3201 else if (y >= pSprite->physLimits.y2) 3202 y = pSprite->physLimits.y2 - 1; 3203 if (pSprite->hotShape) 3204 ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); 3205 3206 XineramaSetCursorPosition(PickPointer(client), x, y, TRUE); 3207 3208 return Success; 3209} 3210 3211#endif 3212 3213 3214/** 3215 * Server-side protocol handling for WarpPointer request. 3216 * Warps the cursor position to the coordinates given in the request. 3217 */ 3218int 3219ProcWarpPointer(ClientPtr client) 3220{ 3221 WindowPtr dest = NULL; 3222 int x, y, rc; 3223 ScreenPtr newScreen; 3224 DeviceIntPtr dev, tmp; 3225 SpritePtr pSprite; 3226 3227 REQUEST(xWarpPointerReq); 3228 REQUEST_SIZE_MATCH(xWarpPointerReq); 3229 3230 dev = PickPointer(client); 3231 3232 for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 3233 if ((tmp == dev) || (!IsMaster(tmp) && tmp->u.master == dev)) { 3234 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); 3235 if (rc != Success) 3236 return rc; 3237 } 3238 } 3239 3240 if (dev->u.lastSlave) 3241 dev = dev->u.lastSlave; 3242 pSprite = dev->spriteInfo->sprite; 3243 3244#ifdef PANORAMIX 3245 if(!noPanoramiXExtension) 3246 return XineramaWarpPointer(client); 3247#endif 3248 3249 if (stuff->dstWid != None) { 3250 rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess); 3251 if (rc != Success) 3252 return rc; 3253 } 3254 x = pSprite->hotPhys.x; 3255 y = pSprite->hotPhys.y; 3256 3257 if (stuff->srcWid != None) 3258 { 3259 int winX, winY; 3260 XID winID = stuff->srcWid; 3261 WindowPtr source; 3262 3263 rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess); 3264 if (rc != Success) 3265 return rc; 3266 3267 winX = source->drawable.x; 3268 winY = source->drawable.y; 3269 if (source->drawable.pScreen != pSprite->hotPhys.pScreen || 3270 x < winX + stuff->srcX || 3271 y < winY + stuff->srcY || 3272 (stuff->srcWidth != 0 && 3273 winX + stuff->srcX + (int)stuff->srcWidth < x) || 3274 (stuff->srcHeight != 0 && 3275 winY + stuff->srcY + (int)stuff->srcHeight < y) || 3276 !PointInWindowIsVisible(source, x, y)) 3277 return Success; 3278 } 3279 if (dest) 3280 { 3281 x = dest->drawable.x; 3282 y = dest->drawable.y; 3283 newScreen = dest->drawable.pScreen; 3284 } else 3285 newScreen = pSprite->hotPhys.pScreen; 3286 3287 x += stuff->dstX; 3288 y += stuff->dstY; 3289 3290 if (x < 0) 3291 x = 0; 3292 else if (x >= newScreen->width) 3293 x = newScreen->width - 1; 3294 if (y < 0) 3295 y = 0; 3296 else if (y >= newScreen->height) 3297 y = newScreen->height - 1; 3298 3299 if (newScreen == pSprite->hotPhys.pScreen) 3300 { 3301 if (x < pSprite->physLimits.x1) 3302 x = pSprite->physLimits.x1; 3303 else if (x >= pSprite->physLimits.x2) 3304 x = pSprite->physLimits.x2 - 1; 3305 if (y < pSprite->physLimits.y1) 3306 y = pSprite->physLimits.y1; 3307 else if (y >= pSprite->physLimits.y2) 3308 y = pSprite->physLimits.y2 - 1; 3309 if (pSprite->hotShape) 3310 ConfineToShape(dev, pSprite->hotShape, &x, &y); 3311 (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE); 3312 } 3313 else if (!PointerConfinedToScreen(dev)) 3314 { 3315 NewCurrentScreen(dev, newScreen, x, y); 3316 } 3317 return Success; 3318} 3319 3320static Bool 3321BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) 3322{ 3323 if(RegionNotEmpty(&pWin->borderSize)) 3324 return TRUE; 3325 3326#ifdef PANORAMIX 3327 if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) { 3328 int i; 3329 3330 for(i = 1; i < PanoramiXNumScreens; i++) { 3331 if(RegionNotEmpty(&pDev->spriteInfo->sprite->windows[i]->borderSize)) 3332 return TRUE; 3333 } 3334 } 3335#endif 3336 return FALSE; 3337} 3338 3339/** 3340 * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a 3341 * passive grab set on the window to be activated. 3342 * If activate is true and a passive grab is found, it will be activated, 3343 * and the event will be delivered to the client. 3344 * 3345 * @param pWin The window that may be subject to a passive grab. 3346 * @param device Device that caused the event. 3347 * @param event The current device event. 3348 * @param checkCore Check for core grabs too. 3349 * @param activate If a grab is found, activate it and deliver the event. 3350 */ 3351 3352GrabPtr 3353CheckPassiveGrabsOnWindow( 3354 WindowPtr pWin, 3355 DeviceIntPtr device, 3356 DeviceEvent *event, 3357 BOOL checkCore, 3358 BOOL activate) 3359{ 3360 SpritePtr pSprite = device->spriteInfo->sprite; 3361 GrabPtr grab = wPassiveGrabs(pWin); 3362 GrabRec tempGrab; 3363 GrabInfoPtr grabinfo; 3364#define CORE_MATCH 0x1 3365#define XI_MATCH 0x2 3366#define XI2_MATCH 0x4 3367 int match = 0; 3368 3369 if (!grab) 3370 return NULL; 3371 /* Fill out the grab details, but leave the type for later before 3372 * comparing */ 3373 tempGrab.window = pWin; 3374 tempGrab.device = device; 3375 tempGrab.detail.exact = event->detail.key; 3376 tempGrab.detail.pMask = NULL; 3377 tempGrab.modifiersDetail.pMask = NULL; 3378 tempGrab.next = NULL; 3379 for (; grab; grab = grab->next) 3380 { 3381 DeviceIntPtr gdev; 3382 XkbSrvInfoPtr xkbi = NULL; 3383 3384 gdev= grab->modifierDevice; 3385 if (grab->grabtype == GRABTYPE_CORE) 3386 { 3387 if (IsPointerDevice(device)) 3388 gdev = GetPairedDevice(device); 3389 else 3390 gdev = device; 3391 } else if (grab->grabtype == GRABTYPE_XI2) 3392 { 3393 /* if the device is an attached slave device, gdev must be the 3394 * attached master keyboard. Since the slave may have been 3395 * reattached after the grab, the modifier device may not be the 3396 * same. */ 3397 if (!IsMaster(grab->device) && device->u.master) 3398 gdev = GetMaster(device, MASTER_KEYBOARD); 3399 } 3400 3401 3402 if (gdev && gdev->key) 3403 xkbi= gdev->key->xkbInfo; 3404 tempGrab.modifierDevice = grab->modifierDevice; 3405 tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; 3406 3407 /* Check for XI2 and XI grabs first */ 3408 tempGrab.type = GetXI2Type((InternalEvent*)event); 3409 tempGrab.grabtype = GRABTYPE_XI2; 3410 if (GrabMatchesSecond(&tempGrab, grab, FALSE)) 3411 match = XI2_MATCH; 3412 3413 tempGrab.detail.exact = event->detail.key; 3414 if (!match) 3415 { 3416 tempGrab.grabtype = GRABTYPE_XI; 3417 if ((tempGrab.type = GetXIType((InternalEvent*)event)) && 3418 (GrabMatchesSecond(&tempGrab, grab, FALSE))) 3419 match = XI_MATCH; 3420 } 3421 3422 /* Check for a core grab (ignore the device when comparing) */ 3423 if (!match && checkCore) 3424 { 3425 tempGrab.grabtype = GRABTYPE_CORE; 3426 if ((tempGrab.type = GetCoreType((InternalEvent*)event)) && 3427 (GrabMatchesSecond(&tempGrab, grab, TRUE))) 3428 match = CORE_MATCH; 3429 } 3430 3431 if (match && (!grab->confineTo || 3432 (grab->confineTo->realized && 3433 BorderSizeNotEmpty(device, grab->confineTo)))) 3434 { 3435 int rc, count = 0; 3436 xEvent *xE = NULL; 3437 xEvent core; 3438 3439 event->corestate &= 0x1f00; 3440 event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00); 3441 grabinfo = &device->deviceGrab; 3442 /* In some cases a passive core grab may exist, but the client 3443 * already has a core grab on some other device. In this case we 3444 * must not get the grab, otherwise we may never ungrab the 3445 * device. 3446 */ 3447 3448 if (grab->grabtype == GRABTYPE_CORE) 3449 { 3450 DeviceIntPtr other; 3451 BOOL interfering = FALSE; 3452 3453 /* A passive grab may have been created for a different device 3454 than it is assigned to at this point in time. 3455 Update the grab's device and modifier device to reflect the 3456 current state. 3457 Since XGrabDeviceButton requires to specify the 3458 modifierDevice explicitly, we don't override this choice. 3459 */ 3460 if (tempGrab.type < GenericEvent) 3461 { 3462 grab->device = device; 3463 grab->modifierDevice = GetPairedDevice(device); 3464 } 3465 3466 for (other = inputInfo.devices; other; other = other->next) 3467 { 3468 GrabPtr othergrab = other->deviceGrab.grab; 3469 if (othergrab && othergrab->grabtype == GRABTYPE_CORE && 3470 SameClient(grab, rClient(othergrab)) && 3471 ((IsPointerDevice(grab->device) && 3472 IsPointerDevice(othergrab->device)) || 3473 (IsKeyboardDevice(grab->device) && 3474 IsKeyboardDevice(othergrab->device)))) 3475 { 3476 interfering = TRUE; 3477 break; 3478 } 3479 } 3480 if (interfering) 3481 continue; 3482 } 3483 3484 if (!activate) 3485 return grab; 3486 3487 if (match & CORE_MATCH) 3488 { 3489 rc = EventToCore((InternalEvent*)event, &core); 3490 if (rc != Success) 3491 { 3492 if (rc != BadMatch) 3493 ErrorF("[dix] %s: core conversion failed in CPGFW " 3494 "(%d, %d).\n", device->name, event->type, rc); 3495 continue; 3496 } 3497 xE = &core; 3498 count = 1; 3499 } else if (match & XI2_MATCH) 3500 { 3501 rc = EventToXI2((InternalEvent*)event, &xE); 3502 if (rc != Success) 3503 { 3504 if (rc != BadMatch) 3505 ErrorF("[dix] %s: XI2 conversion failed in CPGFW " 3506 "(%d, %d).\n", device->name, event->type, rc); 3507 continue; 3508 } 3509 count = 1; 3510 } else 3511 { 3512 rc = EventToXI((InternalEvent*)event, &xE, &count); 3513 if (rc != Success) 3514 { 3515 if (rc != BadMatch) 3516 ErrorF("[dix] %s: XI conversion failed in CPGFW " 3517 "(%d, %d).\n", device->name, event->type, rc); 3518 continue; 3519 } 3520 } 3521 3522 (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE); 3523 3524 if (xE) 3525 { 3526 FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 3527 3528 TryClientEvents(rClient(grab), device, xE, count, 3529 GetEventFilter(device, xE), 3530 GetEventFilter(device, xE), grab); 3531 } 3532 3533 if (grabinfo->sync.state == FROZEN_NO_EVENT) 3534 { 3535 if (!grabinfo->sync.event) 3536 grabinfo->sync.event = calloc(1, sizeof(InternalEvent)); 3537 *grabinfo->sync.event = *event; 3538 grabinfo->sync.state = FROZEN_WITH_EVENT; 3539 } 3540 3541 if (match & (XI_MATCH | XI2_MATCH)) 3542 free(xE); /* on core match xE == &core */ 3543 return grab; 3544 } 3545 } 3546 return NULL; 3547#undef CORE_MATCH 3548#undef XI_MATCH 3549#undef XI2_MATCH 3550} 3551 3552/** 3553 * CheckDeviceGrabs handles both keyboard and pointer events that may cause 3554 * a passive grab to be activated. 3555 * 3556 * If the event is a keyboard event, the ancestors of the focus window are 3557 * traced down and tried to see if they have any passive grabs to be 3558 * activated. If the focus window itself is reached and it's descendants 3559 * contain the pointer, the ancestors of the window that the pointer is in 3560 * are then traced down starting at the focus window, otherwise no grabs are 3561 * activated. 3562 * If the event is a pointer event, the ancestors of the window that the 3563 * pointer is in are traced down starting at the root until CheckPassiveGrabs 3564 * causes a passive grab to activate or all the windows are 3565 * tried. PRH 3566 * 3567 * If a grab is activated, the event has been sent to the client already! 3568 * 3569 * The event we pass in must always be an XI event. From this, we then emulate 3570 * the core event and then check for grabs. 3571 * 3572 * @param device The device that caused the event. 3573 * @param xE The event to handle (Device{Button|Key}Press). 3574 * @param count Number of events in list. 3575 * @return TRUE if a grab has been activated or false otherwise. 3576*/ 3577 3578Bool 3579CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor) 3580{ 3581 int i; 3582 WindowPtr pWin = NULL; 3583 FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus; 3584 BOOL sendCore = (IsMaster(device) && device->coreEvents); 3585 3586 if (event->type != ET_ButtonPress && 3587 event->type != ET_KeyPress) 3588 return FALSE; 3589 3590 if (event->type == ET_ButtonPress 3591 && (device->button->buttonsDown != 1)) 3592 return FALSE; 3593 3594 if (device->deviceGrab.grab) 3595 return FALSE; 3596 3597 i = 0; 3598 if (ancestor) 3599 { 3600 while (i < device->spriteInfo->sprite->spriteTraceGood) 3601 if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor) 3602 break; 3603 if (i == device->spriteInfo->sprite->spriteTraceGood) 3604 return FALSE; 3605 } 3606 3607 if (focus) 3608 { 3609 for (; i < focus->traceGood; i++) 3610 { 3611 pWin = focus->trace[i]; 3612 if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE)) 3613 return TRUE; 3614 } 3615 3616 if ((focus->win == NoneWin) || 3617 (i >= device->spriteInfo->sprite->spriteTraceGood) || 3618 (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i-1])) 3619 return FALSE; 3620 } 3621 3622 for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) 3623 { 3624 pWin = device->spriteInfo->sprite->spriteTrace[i]; 3625 if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE)) 3626 return TRUE; 3627 } 3628 3629 return FALSE; 3630} 3631 3632/** 3633 * Called for keyboard events to deliver event to whatever client owns the 3634 * focus. 3635 * 3636 * The event is delivered to the keyboard's focus window, the root window or 3637 * to the window owning the input focus. 3638 * 3639 * @param keybd The keyboard originating the event. 3640 * @param event The event, not yet in wire format. 3641 * @param window Window underneath the sprite. 3642 */ 3643void 3644DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) 3645{ 3646 DeviceIntPtr ptr; 3647 WindowPtr focus = keybd->focus->win; 3648 BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents); 3649 xEvent core; 3650 xEvent *xE = NULL, *xi2 = NULL; 3651 int count, rc; 3652 int deliveries = 0; 3653 3654 if (focus == FollowKeyboardWin) 3655 focus = inputInfo.keyboard->focus->win; 3656 if (!focus) 3657 return; 3658 if (focus == PointerRootWin) 3659 { 3660 DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd); 3661 return; 3662 } 3663 if ((focus == window) || IsParent(focus, window)) 3664 { 3665 if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd)) 3666 return; 3667 } 3668 3669 /* just deliver it to the focus window */ 3670 ptr = GetPairedDevice(keybd); 3671 3672 3673 rc = EventToXI2(event, &xi2); 3674 if (rc == Success) 3675 { 3676 /* XXX: XACE */ 3677 int filter = GetEventFilter(keybd, xi2); 3678 FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE); 3679 deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1, 3680 filter, NullGrab); 3681 if (deliveries > 0) 3682 goto unwind; 3683 } else if (rc != BadMatch) 3684 ErrorF("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n", 3685 keybd->name, event->any.type, rc); 3686 3687 rc = EventToXI(event, &xE, &count); 3688 if (rc == Success && 3689 XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) 3690 { 3691 FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE); 3692 deliveries = DeliverEventsToWindow(keybd, focus, xE, count, 3693 GetEventFilter(keybd, xE), 3694 NullGrab); 3695 3696 if (deliveries > 0) 3697 goto unwind; 3698 } else if (rc != BadMatch) 3699 ErrorF("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n", 3700 keybd->name, event->any.type, rc); 3701 3702 if (sendCore) 3703 { 3704 rc = EventToCore(event, &core); 3705 if (rc == Success) { 3706 if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) { 3707 FixUpEventFromWindow(keybd->spriteInfo->sprite, &core, focus, 3708 None, FALSE); 3709 deliveries = DeliverEventsToWindow(keybd, focus, &core, 1, 3710 GetEventFilter(keybd, &core), 3711 NullGrab); 3712 } 3713 } else if (rc != BadMatch) 3714 ErrorF("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n", 3715 keybd->name, event->any.type, rc); 3716 } 3717 3718unwind: 3719 free(xE); 3720 free(xi2); 3721 return; 3722} 3723 3724/** 3725 * Deliver an event from a device that is currently grabbed. Uses 3726 * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the 3727 * grab. If not, TryClientEvents() is used. 3728 * 3729 * @param deactivateGrab True if the device's grab should be deactivated. 3730 */ 3731void 3732DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, 3733 Bool deactivateGrab) 3734{ 3735 GrabPtr grab; 3736 GrabInfoPtr grabinfo; 3737 int deliveries = 0; 3738 DeviceIntPtr dev; 3739 SpritePtr pSprite = thisDev->spriteInfo->sprite; 3740 BOOL sendCore = FALSE; 3741 int rc, count = 0; 3742 xEvent *xi = NULL; 3743 xEvent *xi2 = NULL; 3744 3745 grabinfo = &thisDev->deviceGrab; 3746 grab = grabinfo->grab; 3747 3748 if (grab->ownerEvents) 3749 { 3750 WindowPtr focus; 3751 3752 /* Hack: Some pointer device have a focus class. So we need to check 3753 * for the type of event, to see if we really want to deliver it to 3754 * the focus window. For pointer events, the answer is no. 3755 */ 3756 if (IsPointerEvent(event)) 3757 focus = PointerRootWin; 3758 else if (thisDev->focus) 3759 { 3760 focus = thisDev->focus->win; 3761 if (focus == FollowKeyboardWin) 3762 focus = inputInfo.keyboard->focus->win; 3763 } 3764 else 3765 focus = PointerRootWin; 3766 if (focus == PointerRootWin) 3767 deliveries = DeliverDeviceEvents(pSprite->win, event, grab, 3768 NullWindow, thisDev); 3769 else if (focus && (focus == pSprite->win || 3770 IsParent(focus, pSprite->win))) 3771 deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus, 3772 thisDev); 3773 else if (focus) 3774 deliveries = DeliverDeviceEvents(focus, event, grab, focus, 3775 thisDev); 3776 } 3777 if (!deliveries) 3778 { 3779 Mask mask; 3780 3781 /* XXX: In theory, we could pass the internal events through to 3782 * everything and only convert just before hitting the wire. We can't 3783 * do that yet, so DGE is the last stop for internal events. From here 3784 * onwards, we deal with core/XI events. 3785 */ 3786 3787 mask = grab->eventMask; 3788 3789 sendCore = (IsMaster(thisDev) && thisDev->coreEvents); 3790 /* try core event */ 3791 if (sendCore && grab->grabtype == GRABTYPE_CORE) 3792 { 3793 xEvent core; 3794 3795 rc = EventToCore(event, &core); 3796 if (rc == Success) 3797 { 3798 FixUpEventFromWindow(pSprite, &core, grab->window, None, TRUE); 3799 if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, 3800 grab->window, &core, 1) || 3801 XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 3802 grab->window, &core, 1)) 3803 deliveries = 1; /* don't send, but pretend we did */ 3804 else if (!IsInterferingGrab(rClient(grab), thisDev, &core)) 3805 { 3806 deliveries = TryClientEvents(rClient(grab), thisDev, 3807 &core, 1, mask, 3808 GetEventFilter(thisDev, &core), 3809 grab); 3810 } 3811 } else if (rc != BadMatch) 3812 ErrorF("[dix] DeliverGrabbedEvent. Core conversion failed.\n"); 3813 } 3814 3815 if (!deliveries) 3816 { 3817 rc = EventToXI2(event, &xi2); 3818 if (rc == Success) 3819 { 3820 int evtype = ((xGenericEvent*)xi2)->evtype; 3821 mask = grab->xi2mask[XIAllDevices][evtype/8] | 3822 grab->xi2mask[XIAllMasterDevices][evtype/8] | 3823 grab->xi2mask[thisDev->id][evtype/8]; 3824 /* try XI2 event */ 3825 FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE); 3826 /* XXX: XACE */ 3827 deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask, 3828 GetEventFilter(thisDev, xi2), grab); 3829 } else if (rc != BadMatch) 3830 ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n", 3831 thisDev->name, event->any.type, rc); 3832 } 3833 3834 if (!deliveries) 3835 { 3836 rc = EventToXI(event, &xi, &count); 3837 if (rc == Success) 3838 { 3839 /* try XI event */ 3840 if (grabinfo->fromPassiveGrab && 3841 grabinfo->implicitGrab) 3842 mask = grab->deviceMask; 3843 else 3844 mask = grab->eventMask; 3845 3846 FixUpEventFromWindow(pSprite, xi, grab->window, None, TRUE); 3847 3848 if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, 3849 grab->window, xi, count) || 3850 XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 3851 grab->window, xi, count)) 3852 deliveries = 1; /* don't send, but pretend we did */ 3853 else 3854 { 3855 deliveries = 3856 TryClientEvents(rClient(grab), thisDev, 3857 xi, count, 3858 mask, 3859 GetEventFilter(thisDev, xi), 3860 grab); 3861 } 3862 } else if (rc != BadMatch) 3863 ErrorF("[dix] %s: XI conversion failed in DGE (%d, %d). Skipping delivery.\n", 3864 thisDev->name, event->any.type, rc); 3865 } 3866 3867 if (deliveries && (event->any.type == ET_Motion)) 3868 thisDev->valuator->motionHintWindow = grab->window; 3869 } 3870 if (deliveries && !deactivateGrab && event->any.type != ET_Motion) 3871 { 3872 switch (grabinfo->sync.state) 3873 { 3874 case FREEZE_BOTH_NEXT_EVENT: 3875 dev = GetPairedDevice(thisDev); 3876 if (dev) 3877 { 3878 FreezeThaw(dev, TRUE); 3879 if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) && 3880 (CLIENT_BITS(grab->resource) == 3881 CLIENT_BITS(dev->deviceGrab.grab->resource))) 3882 dev->deviceGrab.sync.state = FROZEN_NO_EVENT; 3883 else 3884 dev->deviceGrab.sync.other = grab; 3885 } 3886 /* fall through */ 3887 case FREEZE_NEXT_EVENT: 3888 grabinfo->sync.state = FROZEN_WITH_EVENT; 3889 FreezeThaw(thisDev, TRUE); 3890 if (!grabinfo->sync.event) 3891 grabinfo->sync.event = calloc(1, sizeof(InternalEvent)); 3892 *grabinfo->sync.event = event->device_event; 3893 break; 3894 } 3895 } 3896 3897 free(xi); 3898 free(xi2); 3899} 3900 3901/* This function is used to set the key pressed or key released state - 3902 this is only used when the pressing of keys does not cause 3903 the device's processInputProc to be called, as in for example Mouse Keys. 3904*/ 3905void 3906FixKeyState (DeviceEvent *event, DeviceIntPtr keybd) 3907{ 3908 int key = event->detail.key; 3909 3910 if (event->type == ET_KeyPress) { 3911 DebugF("FixKeyState: Key %d %s\n",key, 3912 ((event->type == ET_KeyPress) ? "down" : "up")); 3913 } 3914 3915 if (event->type == ET_KeyPress) 3916 set_key_down(keybd, key, KEY_PROCESSED); 3917 else if (event->type == ET_KeyRelease) 3918 set_key_up(keybd, key, KEY_PROCESSED); 3919 else 3920 FatalError("Impossible keyboard event"); 3921} 3922 3923#define AtMostOneClient \ 3924 (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) 3925#define ManagerMask \ 3926 (SubstructureRedirectMask | ResizeRedirectMask) 3927 3928/** 3929 * Recalculate which events may be deliverable for the given window. 3930 * Recalculated mask is used for quicker determination which events may be 3931 * delivered to a window. 3932 * 3933 * The otherEventMasks on a WindowOptional is the combination of all event 3934 * masks set by all clients on the window. 3935 * deliverableEventMask is the combination of the eventMask and the 3936 * otherEventMask plus the events that may be propagated to the parent. 3937 * 3938 * Traverses to siblings and parents of the window. 3939 */ 3940void 3941RecalculateDeliverableEvents(WindowPtr pWin) 3942{ 3943 OtherClients *others; 3944 WindowPtr pChild; 3945 3946 pChild = pWin; 3947 while (1) 3948 { 3949 if (pChild->optional) 3950 { 3951 pChild->optional->otherEventMasks = 0; 3952 for (others = wOtherClients(pChild); others; others = others->next) 3953 { 3954 pChild->optional->otherEventMasks |= others->mask; 3955 } 3956 } 3957 pChild->deliverableEvents = pChild->eventMask| 3958 wOtherEventMasks(pChild); 3959 if (pChild->parent) 3960 pChild->deliverableEvents |= 3961 (pChild->parent->deliverableEvents & 3962 ~wDontPropagateMask(pChild) & PropagateMask); 3963 if (pChild->firstChild) 3964 { 3965 pChild = pChild->firstChild; 3966 continue; 3967 } 3968 while (!pChild->nextSib && (pChild != pWin)) 3969 pChild = pChild->parent; 3970 if (pChild == pWin) 3971 break; 3972 pChild = pChild->nextSib; 3973 } 3974} 3975 3976/** 3977 * 3978 * \param value must conform to DeleteType 3979 */ 3980int 3981OtherClientGone(pointer value, XID id) 3982{ 3983 OtherClientsPtr other, prev; 3984 WindowPtr pWin = (WindowPtr)value; 3985 3986 prev = 0; 3987 for (other = wOtherClients(pWin); other; other = other->next) 3988 { 3989 if (other->resource == id) 3990 { 3991 if (prev) 3992 prev->next = other->next; 3993 else 3994 { 3995 if (!(pWin->optional->otherClients = other->next)) 3996 CheckWindowOptionalNeed (pWin); 3997 } 3998 free(other); 3999 RecalculateDeliverableEvents(pWin); 4000 return Success; 4001 } 4002 prev = other; 4003 } 4004 FatalError("client not on event list"); 4005 /*NOTREACHED*/ 4006 return -1; /* make compiler happy */ 4007} 4008 4009int 4010EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) 4011{ 4012 Mask check; 4013 OtherClients * others; 4014 DeviceIntPtr dev; 4015 int rc; 4016 4017 if (mask & ~AllEventMasks) 4018 { 4019 client->errorValue = mask; 4020 return BadValue; 4021 } 4022 check = (mask & ManagerMask); 4023 if (check) { 4024 rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, 4025 RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess); 4026 if (rc != Success) 4027 return rc; 4028 } 4029 check = (mask & AtMostOneClient); 4030 if (check & (pWin->eventMask|wOtherEventMasks(pWin))) 4031 { /* It is illegal for two different 4032 clients to select on any of the 4033 events for AtMostOneClient. However, 4034 it is OK, for some client to 4035 continue selecting on one of those 4036 events. */ 4037 if ((wClient(pWin) != client) && (check & pWin->eventMask)) 4038 return BadAccess; 4039 for (others = wOtherClients (pWin); others; others = others->next) 4040 { 4041 if (!SameClient(others, client) && (check & others->mask)) 4042 return BadAccess; 4043 } 4044 } 4045 if (wClient (pWin) == client) 4046 { 4047 check = pWin->eventMask; 4048 pWin->eventMask = mask; 4049 } 4050 else 4051 { 4052 for (others = wOtherClients (pWin); others; others = others->next) 4053 { 4054 if (SameClient(others, client)) 4055 { 4056 check = others->mask; 4057 if (mask == 0) 4058 { 4059 FreeResource(others->resource, RT_NONE); 4060 return Success; 4061 } 4062 else 4063 others->mask = mask; 4064 goto maskSet; 4065 } 4066 } 4067 check = 0; 4068 if (!pWin->optional && !MakeWindowOptional (pWin)) 4069 return BadAlloc; 4070 others = malloc(sizeof(OtherClients)); 4071 if (!others) 4072 return BadAlloc; 4073 others->mask = mask; 4074 others->resource = FakeClientID(client->index); 4075 others->next = pWin->optional->otherClients; 4076 pWin->optional->otherClients = others; 4077 if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) 4078 return BadAlloc; 4079 } 4080maskSet: 4081 if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) 4082 { 4083 for (dev = inputInfo.devices; dev; dev = dev->next) 4084 { 4085 if (dev->valuator && dev->valuator->motionHintWindow == pWin) 4086 dev->valuator->motionHintWindow = NullWindow; 4087 } 4088 } 4089 RecalculateDeliverableEvents(pWin); 4090 return Success; 4091} 4092 4093int 4094EventSuppressForWindow(WindowPtr pWin, ClientPtr client, 4095 Mask mask, Bool *checkOptional) 4096{ 4097 int i, free; 4098 4099 if (mask & ~PropagateMask) 4100 { 4101 client->errorValue = mask; 4102 return BadValue; 4103 } 4104 if (pWin->dontPropagate) 4105 DontPropagateRefCnts[pWin->dontPropagate]--; 4106 if (!mask) 4107 i = 0; 4108 else 4109 { 4110 for (i = DNPMCOUNT, free = 0; --i > 0; ) 4111 { 4112 if (!DontPropagateRefCnts[i]) 4113 free = i; 4114 else if (mask == DontPropagateMasks[i]) 4115 break; 4116 } 4117 if (!i && free) 4118 { 4119 i = free; 4120 DontPropagateMasks[i] = mask; 4121 } 4122 } 4123 if (i || !mask) 4124 { 4125 pWin->dontPropagate = i; 4126 if (i) 4127 DontPropagateRefCnts[i]++; 4128 if (pWin->optional) 4129 { 4130 pWin->optional->dontPropagateMask = mask; 4131 *checkOptional = TRUE; 4132 } 4133 } 4134 else 4135 { 4136 if (!pWin->optional && !MakeWindowOptional (pWin)) 4137 { 4138 if (pWin->dontPropagate) 4139 DontPropagateRefCnts[pWin->dontPropagate]++; 4140 return BadAlloc; 4141 } 4142 pWin->dontPropagate = 0; 4143 pWin->optional->dontPropagateMask = mask; 4144 } 4145 RecalculateDeliverableEvents(pWin); 4146 return Success; 4147} 4148 4149/** 4150 * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 4151 * Uses the paired keyboard to get some additional information. 4152 */ 4153void 4154CoreEnterLeaveEvent( 4155 DeviceIntPtr mouse, 4156 int type, 4157 int mode, 4158 int detail, 4159 WindowPtr pWin, 4160 Window child) 4161{ 4162 xEvent event; 4163 WindowPtr focus; 4164 DeviceIntPtr keybd; 4165 GrabPtr grab = mouse->deviceGrab.grab; 4166 Mask mask; 4167 4168 keybd = GetPairedDevice(mouse); 4169 4170 if ((pWin == mouse->valuator->motionHintWindow) && 4171 (detail != NotifyInferior)) 4172 mouse->valuator->motionHintWindow = NullWindow; 4173 if (grab) 4174 { 4175 mask = (pWin == grab->window) ? grab->eventMask : 0; 4176 if (grab->ownerEvents) 4177 mask |= EventMaskForClient(pWin, rClient(grab)); 4178 } 4179 else 4180 { 4181 mask = pWin->eventMask | wOtherEventMasks(pWin); 4182 } 4183 4184 memset(&event, 0, sizeof(xEvent)); 4185 event.u.u.type = type; 4186 event.u.u.detail = detail; 4187 event.u.enterLeave.time = currentTime.milliseconds; 4188 event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; 4189 event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; 4190 /* Counts on the same initial structure of crossing & button events! */ 4191 FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE); 4192 /* Enter/Leave events always set child */ 4193 event.u.enterLeave.child = child; 4194 event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? 4195 ELFlagSameScreen : 0; 4196 event.u.enterLeave.state = mouse->button ? (mouse->button->state & 0x1f00) : 0; 4197 if (keybd) 4198 event.u.enterLeave.state |= 4199 XkbGrabStateFromRec(&keybd->key->xkbInfo->state); 4200 event.u.enterLeave.mode = mode; 4201 focus = (keybd) ? keybd->focus->win : None; 4202 if ((focus != NoneWin) && 4203 ((pWin == focus) || (focus == PointerRootWin) || 4204 IsParent(focus, pWin))) 4205 event.u.enterLeave.flags |= ELFlagFocus; 4206 4207 if ((mask & GetEventFilter(mouse, &event))) 4208 { 4209 if (grab) 4210 TryClientEvents(rClient(grab), mouse, &event, 1, mask, 4211 GetEventFilter(mouse, &event), grab); 4212 else 4213 DeliverEventsToWindow(mouse, pWin, &event, 1, 4214 GetEventFilter(mouse, &event), 4215 NullGrab); 4216 } 4217 4218 if ((type == EnterNotify) && (mask & KeymapStateMask)) 4219 { 4220 xKeymapEvent ke; 4221 ClientPtr client = grab ? rClient(grab) : wClient(pWin); 4222 if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess)) 4223 memset((char *)&ke.map[0], 0, 31); 4224 else 4225 memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); 4226 4227 ke.type = KeymapNotify; 4228 if (grab) 4229 TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1, 4230 mask, KeymapStateMask, grab); 4231 else 4232 DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1, 4233 KeymapStateMask, NullGrab); 4234 } 4235} 4236 4237void 4238DeviceEnterLeaveEvent( 4239 DeviceIntPtr mouse, 4240 int sourceid, 4241 int type, 4242 int mode, 4243 int detail, 4244 WindowPtr pWin, 4245 Window child) 4246{ 4247 GrabPtr grab = mouse->deviceGrab.grab; 4248 xXIEnterEvent *event; 4249 int filter; 4250 int btlen, len, i; 4251 DeviceIntPtr kbd; 4252 4253 if ((mode == XINotifyPassiveGrab && type == XI_Leave) || 4254 (mode == XINotifyPassiveUngrab && type == XI_Enter)) 4255 return; 4256 4257 btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; 4258 btlen = bytes_to_int32(btlen); 4259 len = sizeof(xXIEnterEvent) + btlen * 4; 4260 4261 event = calloc(1, len); 4262 event->type = GenericEvent; 4263 event->extension = IReqCode; 4264 event->evtype = type; 4265 event->length = (len - sizeof(xEvent))/4; 4266 event->buttons_len = btlen; 4267 event->detail = detail; 4268 event->time = currentTime.milliseconds; 4269 event->deviceid = mouse->id; 4270 event->sourceid = sourceid; 4271 event->mode = mode; 4272 event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0); 4273 event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0); 4274 4275 for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) 4276 if (BitIsOn(mouse->button->down, i)) 4277 SetBit(&event[1], i); 4278 4279 kbd = (IsMaster(mouse) || mouse->u.master) ? GetPairedDevice(mouse) : NULL; 4280 if (kbd && kbd->key) 4281 { 4282 event->mods.base_mods = kbd->key->xkbInfo->state.base_mods; 4283 event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods; 4284 event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods; 4285 4286 event->group.base_group = kbd->key->xkbInfo->state.base_group; 4287 event->group.latched_group = kbd->key->xkbInfo->state.latched_group; 4288 event->group.locked_group = kbd->key->xkbInfo->state.locked_group; 4289 } 4290 4291 FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent*)event, pWin, 4292 None, FALSE); 4293 4294 filter = GetEventFilter(mouse, (xEvent*)event); 4295 4296 if (grab) 4297 { 4298 Mask mask; 4299 mask = grab->xi2mask[XIAllDevices][type/8] | 4300 grab->xi2mask[XIAllMasterDevices][type/8] | 4301 grab->xi2mask[mouse->id][type/8]; 4302 TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask, 4303 filter, grab); 4304 } else { 4305 if (!GetWindowXI2Mask(mouse, pWin, (xEvent*)event)) 4306 goto out; 4307 DeliverEventsToWindow(mouse, pWin, (xEvent*)event, 1, filter, 4308 NullGrab); 4309 } 4310 4311out: 4312 free(event); 4313} 4314 4315void 4316CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) 4317{ 4318 xEvent event; 4319 4320 memset(&event, 0, sizeof(xEvent)); 4321 event.u.focus.mode = mode; 4322 event.u.u.type = type; 4323 event.u.u.detail = detail; 4324 event.u.focus.window = pWin->drawable.id; 4325 4326 DeliverEventsToWindow(dev, pWin, &event, 1, 4327 GetEventFilter(dev, &event), NullGrab); 4328 if ((type == FocusIn) && 4329 ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) 4330 { 4331 xKeymapEvent ke; 4332 ClientPtr client = wClient(pWin); 4333 if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess)) 4334 memset((char *)&ke.map[0], 0, 31); 4335 else 4336 memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); 4337 4338 ke.type = KeymapNotify; 4339 DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1, 4340 KeymapStateMask, NullGrab); 4341 } 4342} 4343 4344/** 4345 * Set the input focus to the given window. Subsequent keyboard events will be 4346 * delivered to the given window. 4347 * 4348 * Usually called from ProcSetInputFocus as result of a client request. If so, 4349 * the device is the inputInfo.keyboard. 4350 * If called from ProcXSetInputFocus as result of a client xinput request, the 4351 * device is set to the device specified by the client. 4352 * 4353 * @param client Client that requested input focus change. 4354 * @param dev Focus device. 4355 * @param focusID The window to obtain the focus. Can be PointerRoot or None. 4356 * @param revertTo Specifies where the focus reverts to when window becomes 4357 * unviewable. 4358 * @param ctime Specifies the time. 4359 * @param followOK True if pointer is allowed to follow the keyboard. 4360 */ 4361int 4362SetInputFocus( 4363 ClientPtr client, 4364 DeviceIntPtr dev, 4365 Window focusID, 4366 CARD8 revertTo, 4367 Time ctime, 4368 Bool followOK) 4369{ 4370 FocusClassPtr focus; 4371 WindowPtr focusWin; 4372 int mode, rc; 4373 TimeStamp time; 4374 DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */ 4375 4376 4377 UpdateCurrentTime(); 4378 if ((revertTo != RevertToParent) && 4379 (revertTo != RevertToPointerRoot) && 4380 (revertTo != RevertToNone) && 4381 ((revertTo != RevertToFollowKeyboard) || !followOK)) 4382 { 4383 client->errorValue = revertTo; 4384 return BadValue; 4385 } 4386 time = ClientTimeToServerTime(ctime); 4387 4388 if (IsKeyboardDevice(dev)) 4389 keybd = dev; 4390 else 4391 keybd = GetPairedDevice(dev); 4392 4393 if ((focusID == None) || (focusID == PointerRoot)) 4394 focusWin = (WindowPtr)(long)focusID; 4395 else if ((focusID == FollowKeyboard) && followOK) 4396 { 4397 focusWin = keybd->focus->win; 4398 } 4399 else { 4400 rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess); 4401 if (rc != Success) 4402 return rc; 4403 /* It is a match error to try to set the input focus to an 4404 unviewable window. */ 4405 if(!focusWin->realized) 4406 return BadMatch; 4407 } 4408 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess); 4409 if (rc != Success) 4410 return Success; 4411 4412 focus = dev->focus; 4413 if ((CompareTimeStamps(time, currentTime) == LATER) || 4414 (CompareTimeStamps(time, focus->time) == EARLIER)) 4415 return Success; 4416 mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal; 4417 if (focus->win == FollowKeyboardWin) 4418 { 4419 if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin)) 4420 DoFocusEvents(dev, keybd->focus->win, focusWin, mode); 4421 } else 4422 { 4423 if (!ActivateFocusInGrab(dev, focus->win, focusWin)) 4424 DoFocusEvents(dev, focus->win, focusWin, mode); 4425 } 4426 focus->time = time; 4427 focus->revert = revertTo; 4428 if (focusID == FollowKeyboard) 4429 focus->win = FollowKeyboardWin; 4430 else 4431 focus->win = focusWin; 4432 if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) 4433 focus->traceGood = 0; 4434 else 4435 { 4436 int depth = 0; 4437 WindowPtr pWin; 4438 4439 for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; 4440 if (depth > focus->traceSize) 4441 { 4442 focus->traceSize = depth+1; 4443 focus->trace = realloc(focus->trace, 4444 focus->traceSize * sizeof(WindowPtr)); 4445 } 4446 focus->traceGood = depth; 4447 for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 4448 focus->trace[depth] = pWin; 4449 } 4450 return Success; 4451} 4452 4453/** 4454 * Server-side protocol handling for SetInputFocus request. 4455 * 4456 * Sets the input focus for the virtual core keyboard. 4457 */ 4458int 4459ProcSetInputFocus(ClientPtr client) 4460{ 4461 DeviceIntPtr kbd = PickKeyboard(client); 4462 REQUEST(xSetInputFocusReq); 4463 4464 REQUEST_SIZE_MATCH(xSetInputFocusReq); 4465 4466 return SetInputFocus(client, kbd, stuff->focus, 4467 stuff->revertTo, stuff->time, FALSE); 4468} 4469 4470/** 4471 * Server-side protocol handling for GetInputFocus request. 4472 * 4473 * Sends the current input focus for the client's keyboard back to the 4474 * client. 4475 */ 4476int 4477ProcGetInputFocus(ClientPtr client) 4478{ 4479 DeviceIntPtr kbd = PickKeyboard(client); 4480 xGetInputFocusReply rep; 4481 FocusClassPtr focus = kbd->focus; 4482 int rc; 4483 /* REQUEST(xReq); */ 4484 REQUEST_SIZE_MATCH(xReq); 4485 4486 rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess); 4487 if (rc != Success) 4488 return rc; 4489 4490 memset(&rep, 0, sizeof(xGetInputFocusReply)); 4491 rep.type = X_Reply; 4492 rep.length = 0; 4493 rep.sequenceNumber = client->sequence; 4494 if (focus->win == NoneWin) 4495 rep.focus = None; 4496 else if (focus->win == PointerRootWin) 4497 rep.focus = PointerRoot; 4498 else rep.focus = focus->win->drawable.id; 4499 rep.revertTo = focus->revert; 4500 WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); 4501 return Success; 4502} 4503 4504/** 4505 * Server-side protocol handling for GrabPointer request. 4506 * 4507 * Sets an active grab on the client's ClientPointer and returns success 4508 * status to client. 4509 */ 4510int 4511ProcGrabPointer(ClientPtr client) 4512{ 4513 xGrabPointerReply rep; 4514 DeviceIntPtr device = PickPointer(client); 4515 GrabPtr grab; 4516 GrabMask mask; 4517 WindowPtr confineTo; 4518 CursorPtr oldCursor; 4519 REQUEST(xGrabPointerReq); 4520 TimeStamp time; 4521 int rc; 4522 4523 REQUEST_SIZE_MATCH(xGrabPointerReq); 4524 UpdateCurrentTime(); 4525 4526 if (stuff->eventMask & ~PointerGrabMask) 4527 { 4528 client->errorValue = stuff->eventMask; 4529 return BadValue; 4530 } 4531 4532 if (stuff->confineTo == None) 4533 confineTo = NullWindow; 4534 else 4535 { 4536 rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 4537 DixSetAttrAccess); 4538 if (rc != Success) 4539 return rc; 4540 } 4541 4542 memset(&rep, 0, sizeof(xGrabPointerReply)); 4543 oldCursor = NullCursor; 4544 grab = device->deviceGrab.grab; 4545 4546 if (grab) 4547 { 4548 if (grab->confineTo && !confineTo) 4549 ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, 4550 FALSE); 4551 oldCursor = grab->cursor; 4552 } 4553 4554 mask.core = stuff->eventMask; 4555 4556 rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode, 4557 stuff->grabWindow, stuff->ownerEvents, stuff->time, 4558 &mask, GRABTYPE_CORE, stuff->cursor, 4559 stuff->confineTo, &rep.status); 4560 if (rc != Success) 4561 return rc; 4562 4563 if (oldCursor && rep.status == GrabSuccess) 4564 FreeCursor (oldCursor, (Cursor)0); 4565 4566 time = ClientTimeToServerTime(stuff->time); 4567 rep.type = X_Reply; 4568 rep.sequenceNumber = client->sequence; 4569 rep.length = 0; 4570 WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); 4571 return Success; 4572} 4573 4574/** 4575 * Server-side protocol handling for ChangeActivePointerGrab request. 4576 * 4577 * Changes properties of the grab hold by the client. If the client does not 4578 * hold an active grab on the device, nothing happens. 4579 */ 4580int 4581ProcChangeActivePointerGrab(ClientPtr client) 4582{ 4583 DeviceIntPtr device; 4584 GrabPtr grab; 4585 CursorPtr newCursor, oldCursor; 4586 REQUEST(xChangeActivePointerGrabReq); 4587 TimeStamp time; 4588 4589 REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); 4590 if (stuff->eventMask & ~PointerGrabMask) 4591 { 4592 client->errorValue = stuff->eventMask; 4593 return BadValue; 4594 } 4595 if (stuff->cursor == None) 4596 newCursor = NullCursor; 4597 else 4598 { 4599 int rc = dixLookupResourceByType((pointer *)&newCursor, stuff->cursor, 4600 RT_CURSOR, client, DixUseAccess); 4601 if (rc != Success) 4602 { 4603 client->errorValue = stuff->cursor; 4604 return rc; 4605 } 4606 } 4607 4608 device = PickPointer(client); 4609 grab = device->deviceGrab.grab; 4610 4611 if (!grab) 4612 return Success; 4613 if (!SameClient(grab, client)) 4614 return Success; 4615 time = ClientTimeToServerTime(stuff->time); 4616 if ((CompareTimeStamps(time, currentTime) == LATER) || 4617 (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) 4618 return Success; 4619 oldCursor = grab->cursor; 4620 grab->cursor = newCursor; 4621 if (newCursor) 4622 newCursor->refcnt++; 4623 PostNewCursor(device); 4624 if (oldCursor) 4625 FreeCursor(oldCursor, (Cursor)0); 4626 grab->eventMask = stuff->eventMask; 4627 return Success; 4628} 4629 4630/** 4631 * Server-side protocol handling for UngrabPointer request. 4632 * 4633 * Deletes a pointer grab on a device the client has grabbed. 4634 */ 4635int 4636ProcUngrabPointer(ClientPtr client) 4637{ 4638 DeviceIntPtr device = PickPointer(client); 4639 GrabPtr grab; 4640 TimeStamp time; 4641 REQUEST(xResourceReq); 4642 4643 REQUEST_SIZE_MATCH(xResourceReq); 4644 UpdateCurrentTime(); 4645 grab = device->deviceGrab.grab; 4646 4647 time = ClientTimeToServerTime(stuff->id); 4648 if ((CompareTimeStamps(time, currentTime) != LATER) && 4649 (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 4650 (grab) && SameClient(grab, client)) 4651 (*device->deviceGrab.DeactivateGrab)(device); 4652 return Success; 4653} 4654 4655/** 4656 * Sets a grab on the given device. 4657 * 4658 * Called from ProcGrabKeyboard to work on the client's keyboard. 4659 * Called from ProcXGrabDevice to work on the device specified by the client. 4660 * 4661 * The parameters this_mode and other_mode represent the keyboard_mode and 4662 * pointer_mode parameters of XGrabKeyboard(). 4663 * See man page for details on all the parameters 4664 * 4665 * @param client Client that owns the grab. 4666 * @param dev The device to grab. 4667 * @param this_mode GrabModeSync or GrabModeAsync 4668 * @param other_mode GrabModeSync or GrabModeAsync 4669 * @param status Return code to be returned to the caller. 4670 * 4671 * @returns Success or BadValue. 4672 */ 4673int 4674GrabDevice(ClientPtr client, DeviceIntPtr dev, 4675 unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow, 4676 unsigned ownerEvents, Time ctime, GrabMask *mask, 4677 int grabtype, Cursor curs, Window confineToWin, CARD8 *status) 4678{ 4679 WindowPtr pWin, confineTo; 4680 GrabPtr grab; 4681 TimeStamp time; 4682 Mask access_mode = DixGrabAccess; 4683 int rc; 4684 GrabInfoPtr grabInfo = &dev->deviceGrab; 4685 CursorPtr cursor; 4686 4687 UpdateCurrentTime(); 4688 if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) 4689 { 4690 client->errorValue = keyboard_mode; 4691 return BadValue; 4692 } 4693 if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) 4694 { 4695 client->errorValue = pointer_mode; 4696 return BadValue; 4697 } 4698 if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) 4699 { 4700 client->errorValue = ownerEvents; 4701 return BadValue; 4702 } 4703 4704 rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess); 4705 if (rc != Success) 4706 return rc; 4707 4708 if (confineToWin == None) 4709 confineTo = NullWindow; 4710 else 4711 { 4712 rc = dixLookupWindow(&confineTo, confineToWin, client, 4713 DixSetAttrAccess); 4714 if (rc != Success) 4715 return rc; 4716 } 4717 4718 if (curs == None) 4719 cursor = NullCursor; 4720 else 4721 { 4722 rc = dixLookupResourceByType((pointer *)&cursor, curs, RT_CURSOR, 4723 client, DixUseAccess); 4724 if (rc != Success) 4725 { 4726 client->errorValue = curs; 4727 return rc; 4728 } 4729 access_mode |= DixForceAccess; 4730 } 4731 4732 if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync) 4733 access_mode |= DixFreezeAccess; 4734 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 4735 if (rc != Success) 4736 return rc; 4737 4738 time = ClientTimeToServerTime(ctime); 4739 grab = grabInfo->grab; 4740 if (grab && grab->grabtype != grabtype) 4741 *status = AlreadyGrabbed; 4742 if (grab && !SameClient(grab, client)) 4743 *status = AlreadyGrabbed; 4744 else if ((!pWin->realized) || 4745 (confineTo && 4746 !(confineTo->realized 4747 && BorderSizeNotEmpty(dev, confineTo)))) 4748 *status = GrabNotViewable; 4749 else if ((CompareTimeStamps(time, currentTime) == LATER) || 4750 (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER)) 4751 *status = GrabInvalidTime; 4752 else if (grabInfo->sync.frozen && 4753 grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)) 4754 *status = GrabFrozen; 4755 else 4756 { 4757 GrabRec tempGrab; 4758 4759 /* Otherwise segfaults happen on grabbed MPX devices */ 4760 memset(&tempGrab, 0, sizeof(GrabRec)); 4761 4762 tempGrab.next = NULL; 4763 tempGrab.window = pWin; 4764 tempGrab.resource = client->clientAsMask; 4765 tempGrab.ownerEvents = ownerEvents; 4766 tempGrab.keyboardMode = keyboard_mode; 4767 tempGrab.pointerMode = pointer_mode; 4768 if (grabtype == GRABTYPE_CORE) 4769 tempGrab.eventMask = mask->core; 4770 else if (grabtype == GRABTYPE_XI) 4771 tempGrab.eventMask = mask->xi; 4772 else 4773 memcpy(tempGrab.xi2mask, mask->xi2mask, sizeof(tempGrab.xi2mask)); 4774 tempGrab.device = dev; 4775 tempGrab.cursor = cursor; 4776 tempGrab.confineTo = confineTo; 4777 tempGrab.grabtype = grabtype; 4778 (*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE); 4779 *status = GrabSuccess; 4780 } 4781 return Success; 4782} 4783 4784/** 4785 * Server-side protocol handling for GrabKeyboard request. 4786 * 4787 * Grabs the client's keyboard and returns success status to client. 4788 */ 4789int 4790ProcGrabKeyboard(ClientPtr client) 4791{ 4792 xGrabKeyboardReply rep; 4793 REQUEST(xGrabKeyboardReq); 4794 int result; 4795 DeviceIntPtr keyboard = PickKeyboard(client); 4796 GrabMask mask; 4797 4798 REQUEST_SIZE_MATCH(xGrabKeyboardReq); 4799 4800 memset(&rep, 0, sizeof(xGrabKeyboardReply)); 4801 mask.core = KeyPressMask | KeyReleaseMask; 4802 4803 result = GrabDevice(client, keyboard, stuff->pointerMode, 4804 stuff->keyboardMode, stuff->grabWindow, stuff->ownerEvents, 4805 stuff->time, &mask, GRABTYPE_CORE, None, None, 4806 &rep.status); 4807 4808 if (result != Success) 4809 return result; 4810 rep.type = X_Reply; 4811 rep.sequenceNumber = client->sequence; 4812 rep.length = 0; 4813 WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); 4814 return Success; 4815} 4816 4817/** 4818 * Server-side protocol handling for UngrabKeyboard request. 4819 * 4820 * Deletes a possible grab on the client's keyboard. 4821 */ 4822int 4823ProcUngrabKeyboard(ClientPtr client) 4824{ 4825 DeviceIntPtr device = PickKeyboard(client); 4826 GrabPtr grab; 4827 TimeStamp time; 4828 REQUEST(xResourceReq); 4829 4830 REQUEST_SIZE_MATCH(xResourceReq); 4831 UpdateCurrentTime(); 4832 4833 grab = device->deviceGrab.grab; 4834 4835 time = ClientTimeToServerTime(stuff->id); 4836 if ((CompareTimeStamps(time, currentTime) != LATER) && 4837 (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 4838 (grab) && SameClient(grab, client) && grab->grabtype == GRABTYPE_CORE) 4839 (*device->deviceGrab.DeactivateGrab)(device); 4840 return Success; 4841} 4842 4843/** 4844 * Server-side protocol handling for QueryPointer request. 4845 * 4846 * Returns the current state and position of the client's ClientPointer to the 4847 * client. 4848 */ 4849int 4850ProcQueryPointer(ClientPtr client) 4851{ 4852 xQueryPointerReply rep; 4853 WindowPtr pWin, t; 4854 DeviceIntPtr mouse = PickPointer(client); 4855 DeviceIntPtr keyboard; 4856 SpritePtr pSprite; 4857 int rc; 4858 REQUEST(xResourceReq); 4859 REQUEST_SIZE_MATCH(xResourceReq); 4860 4861 rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 4862 if (rc != Success) 4863 return rc; 4864 rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); 4865 if (rc != Success && rc != BadAccess) 4866 return rc; 4867 4868 keyboard = GetPairedDevice(mouse); 4869 4870 pSprite = mouse->spriteInfo->sprite; 4871 if (mouse->valuator->motionHintWindow) 4872 MaybeStopHint(mouse, client); 4873 memset(&rep, 0, sizeof(xQueryPointerReply)); 4874 rep.type = X_Reply; 4875 rep.sequenceNumber = client->sequence; 4876 rep.mask = mouse->button ? (mouse->button->state) : 0; 4877 rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state); 4878 rep.length = 0; 4879 rep.root = (GetCurrentRootWindow(mouse))->drawable.id; 4880 rep.rootX = pSprite->hot.x; 4881 rep.rootY = pSprite->hot.y; 4882 rep.child = None; 4883 if (pSprite->hot.pScreen == pWin->drawable.pScreen) 4884 { 4885 rep.sameScreen = xTrue; 4886 rep.winX = pSprite->hot.x - pWin->drawable.x; 4887 rep.winY = pSprite->hot.y - pWin->drawable.y; 4888 for (t = pSprite->win; t; t = t->parent) 4889 if (t->parent == pWin) 4890 { 4891 rep.child = t->drawable.id; 4892 break; 4893 } 4894 } 4895 else 4896 { 4897 rep.sameScreen = xFalse; 4898 rep.winX = 0; 4899 rep.winY = 0; 4900 } 4901 4902#ifdef PANORAMIX 4903 if(!noPanoramiXExtension) { 4904 rep.rootX += screenInfo.screens[0]->x; 4905 rep.rootY += screenInfo.screens[0]->y; 4906 if(stuff->id == rep.root) { 4907 rep.winX += screenInfo.screens[0]->x; 4908 rep.winY += screenInfo.screens[0]->y; 4909 } 4910 } 4911#endif 4912 4913 if (rc == BadAccess) { 4914 rep.mask = 0; 4915 rep.child = None; 4916 rep.rootX = 0; 4917 rep.rootY = 0; 4918 rep.winX = 0; 4919 rep.winY = 0; 4920 } 4921 4922 WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); 4923 4924 return Success; 4925} 4926 4927/** 4928 * Initializes the device list and the DIX sprite to sane values. Allocates 4929 * trace memory used for quick window traversal. 4930 */ 4931void 4932InitEvents(void) 4933{ 4934 int i; 4935 4936 inputInfo.numDevices = 0; 4937 inputInfo.devices = (DeviceIntPtr)NULL; 4938 inputInfo.off_devices = (DeviceIntPtr)NULL; 4939 inputInfo.keyboard = (DeviceIntPtr)NULL; 4940 inputInfo.pointer = (DeviceIntPtr)NULL; 4941 /* The mask for pointer motion events may have changed in the last server 4942 * generation. See comment above definition of filters. */ 4943 filters[0][PointerMotionMask] = MotionNotify; 4944 for (i = 1; i < MAXDEVICES; i++) 4945 { 4946 memcpy(&filters[i], filters[0], sizeof(filters[0])); 4947 } 4948 4949 syncEvents.replayDev = (DeviceIntPtr)NULL; 4950 syncEvents.replayWin = NullWindow; 4951 while (syncEvents.pending) 4952 { 4953 QdEventPtr next = syncEvents.pending->next; 4954 free(syncEvents.pending); 4955 syncEvents.pending = next; 4956 } 4957 syncEvents.pendtail = &syncEvents.pending; 4958 syncEvents.playingEvents = FALSE; 4959 syncEvents.time.months = 0; 4960 syncEvents.time.milliseconds = 0; /* hardly matters */ 4961 currentTime.months = 0; 4962 currentTime.milliseconds = GetTimeInMillis(); 4963 lastDeviceEventTime = currentTime; 4964 for (i = 0; i < DNPMCOUNT; i++) 4965 { 4966 DontPropagateMasks[i] = 0; 4967 DontPropagateRefCnts[i] = 0; 4968 } 4969 4970 InputEventListLen = GetMaximumEventsNum(); 4971 InputEventList = InitEventList(InputEventListLen); 4972 if (!InputEventList) 4973 FatalError("[dix] Failed to allocate input event list.\n"); 4974} 4975 4976void 4977CloseDownEvents(void) 4978{ 4979 FreeEventList(InputEventList, InputEventListLen); 4980 InputEventListLen = 0; 4981 InputEventList = NULL; 4982} 4983 4984#define SEND_EVENT_BIT 0x80 4985 4986/** 4987 * Server-side protocol handling for SendEvent request. 4988 * 4989 * Locates the window to send the event to and forwards the event. 4990 */ 4991int 4992ProcSendEvent(ClientPtr client) 4993{ 4994 WindowPtr pWin; 4995 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 4996 DeviceIntPtr dev = PickPointer(client); 4997 DeviceIntPtr keybd = GetPairedDevice(dev); 4998 SpritePtr pSprite = dev->spriteInfo->sprite; 4999 REQUEST(xSendEventReq); 5000 5001 REQUEST_SIZE_MATCH(xSendEventReq); 5002 5003 /* libXext and other extension libraries may set the bit indicating 5004 * that this event came from a SendEvent request so remove it 5005 * since otherwise the event type may fail the range checks 5006 * and cause an invalid BadValue error to be returned. 5007 * 5008 * This is safe to do since we later add the SendEvent bit (0x80) 5009 * back in once we send the event to the client */ 5010 5011 stuff->event.u.u.type &= ~(SEND_EVENT_BIT); 5012 5013 /* The client's event type must be a core event type or one defined by an 5014 extension. */ 5015 5016 if ( ! ((stuff->event.u.u.type > X_Reply && 5017 stuff->event.u.u.type < LASTEvent) || 5018 (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && 5019 stuff->event.u.u.type < (unsigned)lastEvent))) 5020 { 5021 client->errorValue = stuff->event.u.u.type; 5022 return BadValue; 5023 } 5024 if (stuff->event.u.u.type == ClientMessage && 5025 stuff->event.u.u.detail != 8 && 5026 stuff->event.u.u.detail != 16 && 5027 stuff->event.u.u.detail != 32) 5028 { 5029 client->errorValue = stuff->event.u.u.detail; 5030 return BadValue; 5031 } 5032 if (stuff->eventMask & ~AllEventMasks) 5033 { 5034 client->errorValue = stuff->eventMask; 5035 return BadValue; 5036 } 5037 5038 if (stuff->destination == PointerWindow) 5039 pWin = pSprite->win; 5040 else if (stuff->destination == InputFocus) 5041 { 5042 WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin; 5043 5044 if (inputFocus == NoneWin) 5045 return Success; 5046 5047 /* If the input focus is PointerRootWin, send the event to where 5048 the pointer is if possible, then perhaps propogate up to root. */ 5049 if (inputFocus == PointerRootWin) 5050 inputFocus = GetCurrentRootWindow(dev); 5051 5052 if (IsParent(inputFocus, pSprite->win)) 5053 { 5054 effectiveFocus = inputFocus; 5055 pWin = pSprite->win; 5056 } 5057 else 5058 effectiveFocus = pWin = inputFocus; 5059 } 5060 else 5061 dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess); 5062 5063 if (!pWin) 5064 return BadWindow; 5065 if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) 5066 { 5067 client->errorValue = stuff->propagate; 5068 return BadValue; 5069 } 5070 stuff->event.u.u.type |= SEND_EVENT_BIT; 5071 if (stuff->propagate) 5072 { 5073 for (;pWin; pWin = pWin->parent) 5074 { 5075 if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, 5076 &stuff->event, 1)) 5077 return Success; 5078 if (DeliverEventsToWindow(dev, pWin, 5079 &stuff->event, 1, stuff->eventMask, NullGrab)) 5080 return Success; 5081 if (pWin == effectiveFocus) 5082 return Success; 5083 stuff->eventMask &= ~wDontPropagateMask(pWin); 5084 if (!stuff->eventMask) 5085 break; 5086 } 5087 } 5088 else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) 5089 DeliverEventsToWindow(dev, pWin, &stuff->event, 5090 1, stuff->eventMask, NullGrab); 5091 return Success; 5092} 5093 5094/** 5095 * Server-side protocol handling for UngrabKey request. 5096 * 5097 * Deletes a passive grab for the given key. Works on the 5098 * client's keyboard. 5099 */ 5100int 5101ProcUngrabKey(ClientPtr client) 5102{ 5103 REQUEST(xUngrabKeyReq); 5104 WindowPtr pWin; 5105 GrabRec tempGrab; 5106 DeviceIntPtr keybd = PickKeyboard(client); 5107 int rc; 5108 5109 REQUEST_SIZE_MATCH(xUngrabKeyReq); 5110 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess); 5111 if (rc != Success) 5112 return rc; 5113 5114 if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 5115 (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 5116 && (stuff->key != AnyKey)) 5117 { 5118 client->errorValue = stuff->key; 5119 return BadValue; 5120 } 5121 if ((stuff->modifiers != AnyModifier) && 5122 (stuff->modifiers & ~AllModifiersMask)) 5123 { 5124 client->errorValue = stuff->modifiers; 5125 return BadValue; 5126 } 5127 tempGrab.resource = client->clientAsMask; 5128 tempGrab.device = keybd; 5129 tempGrab.window = pWin; 5130 tempGrab.modifiersDetail.exact = stuff->modifiers; 5131 tempGrab.modifiersDetail.pMask = NULL; 5132 tempGrab.modifierDevice = GetPairedDevice(keybd); 5133 tempGrab.type = KeyPress; 5134 tempGrab.grabtype = GRABTYPE_CORE; 5135 tempGrab.detail.exact = stuff->key; 5136 tempGrab.detail.pMask = NULL; 5137 tempGrab.next = NULL; 5138 5139 if (!DeletePassiveGrabFromList(&tempGrab)) 5140 return BadAlloc; 5141 return Success; 5142} 5143 5144/** 5145 * Server-side protocol handling for GrabKey request. 5146 * 5147 * Creates a grab for the client's keyboard and adds it to the list of passive 5148 * grabs. 5149 */ 5150int 5151ProcGrabKey(ClientPtr client) 5152{ 5153 WindowPtr pWin; 5154 REQUEST(xGrabKeyReq); 5155 GrabPtr grab; 5156 DeviceIntPtr keybd = PickKeyboard(client); 5157 int rc; 5158 GrabParameters param; 5159 GrabMask mask; 5160 5161 REQUEST_SIZE_MATCH(xGrabKeyReq); 5162 5163 memset(¶m, 0, sizeof(param)); 5164 param.grabtype = GRABTYPE_CORE; 5165 param.ownerEvents = stuff->ownerEvents; 5166 param.this_device_mode = stuff->keyboardMode; 5167 param.other_devices_mode = stuff->pointerMode; 5168 param.modifiers = stuff->modifiers; 5169 5170 rc = CheckGrabValues(client, ¶m); 5171 if (rc != Success) 5172 return rc; 5173 5174 if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 5175 (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 5176 && (stuff->key != AnyKey)) 5177 { 5178 client->errorValue = stuff->key; 5179 return BadValue; 5180 } 5181 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 5182 if (rc != Success) 5183 return rc; 5184 5185 5186 mask.core = (KeyPressMask | KeyReleaseMask); 5187 5188 grab = CreateGrab(client->index, keybd, keybd, pWin, GRABTYPE_CORE, &mask, 5189 ¶m, KeyPress, stuff->key, NullWindow, NullCursor); 5190 if (!grab) 5191 return BadAlloc; 5192 return AddPassiveGrabToList(client, grab); 5193} 5194 5195 5196/** 5197 * Server-side protocol handling for GrabButton request. 5198 * 5199 * Creates a grab for the client's ClientPointer and adds it as a passive grab 5200 * to the list. 5201 */ 5202int 5203ProcGrabButton(ClientPtr client) 5204{ 5205 WindowPtr pWin, confineTo; 5206 REQUEST(xGrabButtonReq); 5207 CursorPtr cursor; 5208 GrabPtr grab; 5209 DeviceIntPtr ptr, modifierDevice; 5210 Mask access_mode = DixGrabAccess; 5211 GrabMask mask; 5212 GrabParameters param; 5213 int rc; 5214 5215 REQUEST_SIZE_MATCH(xGrabButtonReq); 5216 if ((stuff->pointerMode != GrabModeSync) && 5217 (stuff->pointerMode != GrabModeAsync)) 5218 { 5219 client->errorValue = stuff->pointerMode; 5220 return BadValue; 5221 } 5222 if ((stuff->keyboardMode != GrabModeSync) && 5223 (stuff->keyboardMode != GrabModeAsync)) 5224 { 5225 client->errorValue = stuff->keyboardMode; 5226 return BadValue; 5227 } 5228 if ((stuff->modifiers != AnyModifier) && 5229 (stuff->modifiers & ~AllModifiersMask)) 5230 { 5231 client->errorValue = stuff->modifiers; 5232 return BadValue; 5233 } 5234 if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) 5235 { 5236 client->errorValue = stuff->ownerEvents; 5237 return BadValue; 5238 } 5239 if (stuff->eventMask & ~PointerGrabMask) 5240 { 5241 client->errorValue = stuff->eventMask; 5242 return BadValue; 5243 } 5244 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 5245 if (rc != Success) 5246 return rc; 5247 if (stuff->confineTo == None) 5248 confineTo = NullWindow; 5249 else { 5250 rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 5251 DixSetAttrAccess); 5252 if (rc != Success) 5253 return rc; 5254 } 5255 if (stuff->cursor == None) 5256 cursor = NullCursor; 5257 else 5258 { 5259 rc = dixLookupResourceByType((pointer *)&cursor, stuff->cursor, RT_CURSOR, 5260 client, DixUseAccess); 5261 if (rc != Success) 5262 { 5263 client->errorValue = stuff->cursor; 5264 return rc; 5265 } 5266 access_mode |= DixForceAccess; 5267 } 5268 5269 ptr = PickPointer(client); 5270 modifierDevice = GetPairedDevice(ptr); 5271 if (stuff->pointerMode == GrabModeSync || 5272 stuff->keyboardMode == GrabModeSync) 5273 access_mode |= DixFreezeAccess; 5274 rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode); 5275 if (rc != Success) 5276 return rc; 5277 5278 memset(¶m, 0, sizeof(param)); 5279 param.grabtype = GRABTYPE_CORE; 5280 param.ownerEvents = stuff->ownerEvents; 5281 param.this_device_mode = stuff->keyboardMode; 5282 param.other_devices_mode = stuff->pointerMode; 5283 param.modifiers = stuff->modifiers; 5284 5285 mask.core = stuff->eventMask; 5286 5287 grab = CreateGrab(client->index, ptr, modifierDevice, pWin, 5288 GRABTYPE_CORE, &mask, ¶m, ButtonPress, 5289 stuff->button, confineTo, cursor); 5290 if (!grab) 5291 return BadAlloc; 5292 return AddPassiveGrabToList(client, grab); 5293} 5294 5295/** 5296 * Server-side protocol handling for UngrabButton request. 5297 * 5298 * Deletes a passive grab on the client's ClientPointer from the list. 5299 */ 5300int 5301ProcUngrabButton(ClientPtr client) 5302{ 5303 REQUEST(xUngrabButtonReq); 5304 WindowPtr pWin; 5305 GrabRec tempGrab; 5306 int rc; 5307 DeviceIntPtr ptr; 5308 5309 REQUEST_SIZE_MATCH(xUngrabButtonReq); 5310 if ((stuff->modifiers != AnyModifier) && 5311 (stuff->modifiers & ~AllModifiersMask)) 5312 { 5313 client->errorValue = stuff->modifiers; 5314 return BadValue; 5315 } 5316 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 5317 if (rc != Success) 5318 return rc; 5319 5320 ptr = PickPointer(client); 5321 5322 tempGrab.resource = client->clientAsMask; 5323 tempGrab.device = ptr; 5324 tempGrab.window = pWin; 5325 tempGrab.modifiersDetail.exact = stuff->modifiers; 5326 tempGrab.modifiersDetail.pMask = NULL; 5327 tempGrab.modifierDevice = GetPairedDevice(ptr); 5328 tempGrab.type = ButtonPress; 5329 tempGrab.detail.exact = stuff->button; 5330 tempGrab.grabtype = GRABTYPE_CORE; 5331 tempGrab.detail.pMask = NULL; 5332 tempGrab.next = NULL; 5333 5334 if (!DeletePassiveGrabFromList(&tempGrab)) 5335 return BadAlloc; 5336 return Success; 5337} 5338 5339/** 5340 * Deactivate any grab that may be on the window, remove the focus. 5341 * Delete any XInput extension events from the window too. Does not change the 5342 * window mask. Use just before the window is deleted. 5343 * 5344 * If freeResources is set, passive grabs on the window are deleted. 5345 * 5346 * @param pWin The window to delete events from. 5347 * @param freeResources True if resources associated with the window should be 5348 * deleted. 5349 */ 5350void 5351DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) 5352{ 5353 WindowPtr parent; 5354 DeviceIntPtr mouse = inputInfo.pointer; 5355 DeviceIntPtr keybd = inputInfo.keyboard; 5356 FocusClassPtr focus; 5357 OtherClientsPtr oc; 5358 GrabPtr passive; 5359 GrabPtr grab; 5360 5361 5362 /* Deactivate any grabs performed on this window, before making any 5363 input focus changes. */ 5364 grab = mouse->deviceGrab.grab; 5365 if (grab && 5366 ((grab->window == pWin) || (grab->confineTo == pWin))) 5367 (*mouse->deviceGrab.DeactivateGrab)(mouse); 5368 5369 5370 /* Deactivating a keyboard grab should cause focus events. */ 5371 grab = keybd->deviceGrab.grab; 5372 if (grab && (grab->window == pWin)) 5373 (*keybd->deviceGrab.DeactivateGrab)(keybd); 5374 5375 /* And now the real devices */ 5376 for (mouse = inputInfo.devices; mouse; mouse = mouse->next) 5377 { 5378 grab = mouse->deviceGrab.grab; 5379 if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 5380 (*mouse->deviceGrab.DeactivateGrab)(mouse); 5381 } 5382 5383 5384 for (keybd = inputInfo.devices; keybd; keybd = keybd->next) 5385 { 5386 if (IsKeyboardDevice(keybd)) 5387 { 5388 focus = keybd->focus; 5389 5390 /* If the focus window is a root window (ie. has no parent) then don't 5391 delete the focus from it. */ 5392 5393 if ((pWin == focus->win) && (pWin->parent != NullWindow)) 5394 { 5395 int focusEventMode = NotifyNormal; 5396 5397 /* If a grab is in progress, then alter the mode of focus events. */ 5398 5399 if (keybd->deviceGrab.grab) 5400 focusEventMode = NotifyWhileGrabbed; 5401 5402 switch (focus->revert) 5403 { 5404 case RevertToNone: 5405 DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); 5406 focus->win = NoneWin; 5407 focus->traceGood = 0; 5408 break; 5409 case RevertToParent: 5410 parent = pWin; 5411 do 5412 { 5413 parent = parent->parent; 5414 focus->traceGood--; 5415 } while (!parent->realized 5416 /* This would be a good protocol change -- windows being reparented 5417 during SaveSet processing would cause the focus to revert to the 5418 nearest enclosing window which will survive the death of the exiting 5419 client, instead of ending up reverting to a dying window and thence 5420 to None 5421 */ 5422#ifdef NOTDEF 5423 || wClient(parent)->clientGone 5424#endif 5425 ); 5426 if (!ActivateFocusInGrab(keybd, pWin, parent)) 5427 DoFocusEvents(keybd, pWin, parent, focusEventMode); 5428 focus->win = parent; 5429 focus->revert = RevertToNone; 5430 break; 5431 case RevertToPointerRoot: 5432 if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin)) 5433 DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); 5434 focus->win = PointerRootWin; 5435 focus->traceGood = 0; 5436 break; 5437 } 5438 } 5439 } 5440 5441 if (IsPointerDevice(keybd)) 5442 { 5443 if (keybd->valuator->motionHintWindow == pWin) 5444 keybd->valuator->motionHintWindow = NullWindow; 5445 } 5446 } 5447 5448 if (freeResources) 5449 { 5450 if (pWin->dontPropagate) 5451 DontPropagateRefCnts[pWin->dontPropagate]--; 5452 while ( (oc = wOtherClients(pWin)) ) 5453 FreeResource(oc->resource, RT_NONE); 5454 while ( (passive = wPassiveGrabs(pWin)) ) 5455 FreeResource(passive->resource, RT_NONE); 5456 } 5457 5458 DeleteWindowFromAnyExtEvents(pWin, freeResources); 5459} 5460 5461/** 5462 * Call this whenever some window at or below pWin has changed geometry. If 5463 * there is a grab on the window, the cursor will be re-confined into the 5464 * window. 5465 */ 5466void 5467CheckCursorConfinement(WindowPtr pWin) 5468{ 5469 GrabPtr grab; 5470 WindowPtr confineTo; 5471 DeviceIntPtr pDev; 5472 5473#ifdef PANORAMIX 5474 if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; 5475#endif 5476 5477 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 5478 { 5479 if (DevHasCursor(pDev)) 5480 { 5481 grab = pDev->deviceGrab.grab; 5482 if (grab && (confineTo = grab->confineTo)) 5483 { 5484 if (!BorderSizeNotEmpty(pDev, confineTo)) 5485 (*pDev->deviceGrab.DeactivateGrab)(pDev); 5486 else if ((pWin == confineTo) || IsParent(pWin, confineTo)) 5487 ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE); 5488 } 5489 } 5490 } 5491} 5492 5493Mask 5494EventMaskForClient(WindowPtr pWin, ClientPtr client) 5495{ 5496 OtherClientsPtr other; 5497 5498 if (wClient (pWin) == client) 5499 return pWin->eventMask; 5500 for (other = wOtherClients(pWin); other; other = other->next) 5501 { 5502 if (SameClient(other, client)) 5503 return other->mask; 5504 } 5505 return 0; 5506} 5507 5508/** 5509 * Server-side protocol handling for RecolorCursor request. 5510 */ 5511int 5512ProcRecolorCursor(ClientPtr client) 5513{ 5514 CursorPtr pCursor; 5515 int rc, nscr; 5516 ScreenPtr pscr; 5517 Bool displayed; 5518 SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 5519 REQUEST(xRecolorCursorReq); 5520 5521 REQUEST_SIZE_MATCH(xRecolorCursorReq); 5522 rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR, 5523 client, DixWriteAccess); 5524 if (rc != Success) 5525 { 5526 client->errorValue = stuff->cursor; 5527 return rc; 5528 } 5529 5530 pCursor->foreRed = stuff->foreRed; 5531 pCursor->foreGreen = stuff->foreGreen; 5532 pCursor->foreBlue = stuff->foreBlue; 5533 5534 pCursor->backRed = stuff->backRed; 5535 pCursor->backGreen = stuff->backGreen; 5536 pCursor->backBlue = stuff->backBlue; 5537 5538 for (nscr = 0; nscr < screenInfo.numScreens; nscr++) 5539 { 5540 pscr = screenInfo.screens[nscr]; 5541#ifdef PANORAMIX 5542 if(!noPanoramiXExtension) 5543 displayed = (pscr == pSprite->screen); 5544 else 5545#endif 5546 displayed = (pscr == pSprite->hotPhys.pScreen); 5547 ( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor, 5548 (pCursor == pSprite->current) && displayed); 5549 } 5550 return Success; 5551} 5552 5553/** 5554 * Write the given events to a client, swapping the byte order if necessary. 5555 * To swap the byte ordering, a callback is called that has to be set up for 5556 * the given event type. 5557 * 5558 * In the case of DeviceMotionNotify trailed by DeviceValuators, the events 5559 * can be more than one. Usually it's just one event. 5560 * 5561 * Do not modify the event structure passed in. See comment below. 5562 * 5563 * @param pClient Client to send events to. 5564 * @param count Number of events. 5565 * @param events The event list. 5566 */ 5567void 5568WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) 5569{ 5570#ifdef PANORAMIX 5571 xEvent eventCopy; 5572#endif 5573 xEvent *eventTo, *eventFrom; 5574 int i, 5575 eventlength = sizeof(xEvent); 5576 5577 if (!pClient || pClient == serverClient || pClient->clientGone) 5578 return; 5579 5580 for (i = 0; i < count; i++) 5581 if ((events[i].u.u.type & 0x7f) != KeymapNotify) 5582 events[i].u.u.sequenceNumber = pClient->sequence; 5583 5584 /* Let XKB rewrite the state, as it depends on client preferences. */ 5585 XkbFilterEvents(pClient, count, events); 5586 5587#ifdef PANORAMIX 5588 if(!noPanoramiXExtension && 5589 (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) 5590 { 5591 switch(events->u.u.type) { 5592 case MotionNotify: 5593 case ButtonPress: 5594 case ButtonRelease: 5595 case KeyPress: 5596 case KeyRelease: 5597 case EnterNotify: 5598 case LeaveNotify: 5599 /* 5600 When multiple clients want the same event DeliverEventsToWindow 5601 passes the same event structure multiple times so we can't 5602 modify the one passed to us 5603 */ 5604 count = 1; /* should always be 1 */ 5605 memcpy(&eventCopy, events, sizeof(xEvent)); 5606 eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x; 5607 eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y; 5608 if(eventCopy.u.keyButtonPointer.event == 5609 eventCopy.u.keyButtonPointer.root) 5610 { 5611 eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x; 5612 eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y; 5613 } 5614 events = &eventCopy; 5615 break; 5616 default: break; 5617 } 5618 } 5619#endif 5620 5621 if (EventCallback) 5622 { 5623 EventInfoRec eventinfo; 5624 eventinfo.client = pClient; 5625 eventinfo.events = events; 5626 eventinfo.count = count; 5627 CallCallbacks(&EventCallback, (pointer)&eventinfo); 5628 } 5629#ifdef XSERVER_DTRACE 5630 if (XSERVER_SEND_EVENT_ENABLED()) { 5631 for (i = 0; i < count; i++) 5632 { 5633 XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); 5634 } 5635 } 5636#endif 5637 /* Just a safety check to make sure we only have one GenericEvent, it just 5638 * makes things easier for me right now. (whot) */ 5639 for (i = 1; i < count; i++) 5640 { 5641 if (events[i].u.u.type == GenericEvent) 5642 { 5643 ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n"); 5644 return; 5645 } 5646 } 5647 5648 if (events->u.u.type == GenericEvent) 5649 { 5650 eventlength += ((xGenericEvent*)events)->length * 4; 5651 } 5652 5653 if(pClient->swapped) 5654 { 5655 if (eventlength > swapEventLen) 5656 { 5657 swapEventLen = eventlength; 5658 swapEvent = realloc(swapEvent, swapEventLen); 5659 if (!swapEvent) 5660 { 5661 FatalError("WriteEventsToClient: Out of memory.\n"); 5662 return; 5663 } 5664 } 5665 5666 for(i = 0; i < count; i++) 5667 { 5668 eventFrom = &events[i]; 5669 eventTo = swapEvent; 5670 5671 /* Remember to strip off the leading bit of type in case 5672 this event was sent with "SendEvent." */ 5673 (*EventSwapVector[eventFrom->u.u.type & 0177]) 5674 (eventFrom, eventTo); 5675 5676 WriteToClient(pClient, eventlength, (char *)eventTo); 5677 } 5678 } 5679 else 5680 { 5681 /* only one GenericEvent, remember? that means either count is 1 and 5682 * eventlength is arbitrary or eventlength is 32 and count doesn't 5683 * matter. And we're all set. Woohoo. */ 5684 WriteToClient(pClient, count * eventlength, (char *) events); 5685 } 5686} 5687 5688/* 5689 * Set the client pointer for the given client. 5690 * 5691 * A client can have exactly one ClientPointer. Each time a 5692 * request/reply/event is processed and the choice of devices is ambiguous 5693 * (e.g. QueryPointer request), the server will pick the ClientPointer (see 5694 * PickPointer()). 5695 * If a keyboard is needed, the first keyboard paired with the CP is used. 5696 */ 5697int 5698SetClientPointer(ClientPtr client, DeviceIntPtr device) 5699{ 5700 int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess); 5701 if (rc != Success) 5702 return rc; 5703 5704 if (!IsMaster(device)) 5705 { 5706 ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); 5707 return BadDevice; 5708 } else if (!device->spriteInfo->spriteOwner) 5709 { 5710 ErrorF("[dix] Device %d does not have a sprite. " 5711 "Cannot be ClientPointer\n", device->id); 5712 return BadDevice; 5713 } 5714 client->clientPtr = device; 5715 return Success; 5716} 5717 5718/* PickPointer will pick an appropriate pointer for the given client. 5719 * 5720 * An "appropriate device" is (in order of priority): 5721 * 1) A device the given client has a core grab on. 5722 * 2) A device set as ClientPointer for the given client. 5723 * 3) The first master device. 5724 */ 5725DeviceIntPtr 5726PickPointer(ClientPtr client) 5727{ 5728 DeviceIntPtr it = inputInfo.devices; 5729 5730 /* First, check if the client currently has a grab on a device. Even 5731 * keyboards count. */ 5732 for(it = inputInfo.devices; it; it = it->next) 5733 { 5734 GrabPtr grab = it->deviceGrab.grab; 5735 if (grab && grab->grabtype == GRABTYPE_CORE && SameClient(grab, client)) 5736 { 5737 it = GetMaster(it, MASTER_POINTER); 5738 return it; /* Always return a core grabbed device */ 5739 } 5740 } 5741 5742 if (!client->clientPtr) 5743 { 5744 DeviceIntPtr it = inputInfo.devices; 5745 while (it) 5746 { 5747 if (IsMaster(it) && it->spriteInfo->spriteOwner) 5748 { 5749 client->clientPtr = it; 5750 break; 5751 } 5752 it = it->next; 5753 } 5754 } 5755 return client->clientPtr; 5756} 5757 5758/* PickKeyboard will pick an appropriate keyboard for the given client by 5759 * searching the list of devices for the keyboard device that is paired with 5760 * the client's pointer. 5761 */ 5762DeviceIntPtr 5763PickKeyboard(ClientPtr client) 5764{ 5765 DeviceIntPtr ptr = PickPointer(client); 5766 DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD); 5767 5768 if (!kbd) 5769 { 5770 ErrorF("[dix] ClientPointer not paired with a keyboard. This " 5771 "is a bug.\n"); 5772 } 5773 5774 return kbd; 5775} 5776 5777/* A client that has one or more core grabs does not get core events from 5778 * devices it does not have a grab on. Legacy applications behave bad 5779 * otherwise because they are not used to it and the events interfere. 5780 * Only applies for core events. 5781 * 5782 * Return true if a core event from the device would interfere and should not 5783 * be delivered. 5784 */ 5785Bool 5786IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event) 5787{ 5788 DeviceIntPtr it = inputInfo.devices; 5789 5790 switch(event->u.u.type) 5791 { 5792 case KeyPress: 5793 case KeyRelease: 5794 case ButtonPress: 5795 case ButtonRelease: 5796 case MotionNotify: 5797 case EnterNotify: 5798 case LeaveNotify: 5799 break; 5800 default: 5801 return FALSE; 5802 } 5803 5804 if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 5805 return FALSE; 5806 5807 while(it) 5808 { 5809 if (it != dev) 5810 { 5811 if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client) 5812 && !it->deviceGrab.fromPassiveGrab) 5813 { 5814 if ((IsPointerDevice(it) && IsPointerDevice(dev)) || 5815 (IsKeyboardDevice(it) && IsKeyboardDevice(dev))) 5816 return TRUE; 5817 } 5818 } 5819 it = it->next; 5820 } 5821 5822 return FALSE; 5823} 5824 5825