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