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