PageRenderTime 77ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/dix/events.c

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