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