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