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