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