PageRenderTime 78ms CodeModel.GetById 27ms RepoModel.GetById 1ms 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

Large files files are truncated, but you can click here to view the full file

  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 ||

Large files files are truncated, but you can click here to view the full file