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