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