PageRenderTime 64ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 1ms

/nx-3.5.0/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c

#
C | 5044 lines | 4292 code | 404 blank | 348 comment | 1131 complexity | 722de54a9fd7e12ab16578bae30522a6 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0

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

  1. /**************************************************************************/
  2. /* */
  3. /* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
  4. /* */
  5. /* NXAGENT, NX protocol compression and NX extensions to this software */
  6. /* are copyright of NoMachine. Redistribution and use of the present */
  7. /* software is allowed according to terms specified in the file LICENSE */
  8. /* which comes in the source distribution. */
  9. /* */
  10. /* Check http://www.nomachine.com/licensing.html for applicability. */
  11. /* */
  12. /* NX and NoMachine are trademarks of Medialogic S.p.A. */
  13. /* */
  14. /* All rights reserved. */
  15. /* */
  16. /**************************************************************************/
  17. /* $XdotOrg: xc/programs/Xserver/dix/events.c,v 1.17 2005/08/25 22:11:04 anholt Exp $ */
  18. /* $XFree86: xc/programs/Xserver/dix/events.c,v 3.51 2004/01/12 17:04:52 tsi Exp $ */
  19. /************************************************************
  20. Copyright 1987, 1998 The Open Group
  21. Permission to use, copy, modify, distribute, and sell this software and its
  22. documentation for any purpose is hereby granted without fee, provided that
  23. the above copyright notice appear in all copies and that both that
  24. copyright notice and this permission notice appear in supporting
  25. documentation.
  26. The above copyright notice and this permission notice shall be included in
  27. all copies or substantial portions of the Software.
  28. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  29. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  30. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  31. OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  32. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  33. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  34. Except as contained in this notice, the name of The Open Group shall not be
  35. used in advertising or otherwise to promote the sale, use or other dealings
  36. in this Software without prior written authorization from The Open Group.
  37. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  38. All Rights Reserved
  39. Permission to use, copy, modify, and distribute this software and its
  40. documentation for any purpose and without fee is hereby granted,
  41. provided that the above copyright notice appear in all copies and that
  42. both that copyright notice and this permission notice appear in
  43. supporting documentation, and that the name of Digital not be
  44. used in advertising or publicity pertaining to distribution of the
  45. software without specific, written prior permission.
  46. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  47. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  48. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  49. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  50. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  51. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  52. SOFTWARE.
  53. ********************************************************/
  54. /* The panoramix components contained the following notice */
  55. /*****************************************************************
  56. Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
  57. Permission is hereby granted, free of charge, to any person obtaining a copy
  58. of this software and associated documentation files (the "Software"), to deal
  59. in the Software without restriction, including without limitation the rights
  60. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  61. copies of the Software.
  62. The above copyright notice and this permission notice shall be included in
  63. all copies or substantial portions of the Software.
  64. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  65. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  66. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  67. DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
  68. BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
  69. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
  70. IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  71. Except as contained in this notice, the name of Digital Equipment Corporation
  72. shall not be used in advertising or otherwise to promote the sale, use or other
  73. dealings in this Software without prior written authorization from Digital
  74. Equipment Corporation.
  75. ******************************************************************/
  76. /*****************************************************************
  77. Copyright 2003-2005 Sun Microsystems, Inc.
  78. All rights reserved.
  79. Permission is hereby granted, free of charge, to any person obtaining a
  80. copy of this software and associated documentation files (the
  81. "Software"), to deal in the Software without restriction, including
  82. without limitation the rights to use, copy, modify, merge, publish,
  83. distribute, and/or sell copies of the Software, and to permit persons
  84. to whom the Software is furnished to do so, provided that the above
  85. copyright notice(s) and this permission notice appear in all copies of
  86. the Software and that both the above copyright notice(s) and this
  87. permission notice appear in supporting documentation.
  88. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  89. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  90. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
  91. OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  92. HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
  93. INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
  94. FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  95. NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  96. WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  97. Except as contained in this notice, the name of a copyright holder
  98. shall not be used in advertising or otherwise to promote the sale, use
  99. or other dealings in this Software without prior written authorization
  100. of the copyright holder.
  101. ******************************************************************/
  102. /* $Xorg: events.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */
  103. #ifdef HAVE_DIX_CONFIG_H
  104. #include <dix-config.h>
  105. #endif
  106. #include <X11/X.h>
  107. #include "Xlib.h"
  108. #include "misc.h"
  109. #include "resource.h"
  110. #define NEED_EVENTS
  111. #define NEED_REPLIES
  112. #include <X11/Xproto.h>
  113. #include "windowstr.h"
  114. #include "inputstr.h"
  115. #include "scrnintstr.h"
  116. #include "cursorstr.h"
  117. #include "dixstruct.h"
  118. #ifdef PANORAMIX
  119. #include "panoramiX.h"
  120. #include "panoramiXsrv.h"
  121. #endif
  122. #include "globals.h"
  123. #ifdef XKB
  124. #include <X11/extensions/XKBsrv.h>
  125. extern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
  126. #endif
  127. #ifdef XCSECURITY
  128. #define _SECURITY_SERVER
  129. #include <X11/extensions/security.h>
  130. #endif
  131. #ifdef XEVIE
  132. extern WindowPtr *WindowTable;
  133. extern int xevieFlag;
  134. extern int xevieClientIndex;
  135. extern DeviceIntPtr xeviemouse;
  136. extern DeviceIntPtr xeviekb;
  137. extern Mask xevieMask;
  138. extern Mask xevieFilters[128];
  139. extern int xevieEventSent;
  140. extern int xevieKBEventSent;
  141. int xeviegrabState = 0;
  142. xEvent *xeviexE;
  143. #endif
  144. #include <X11/extensions/XIproto.h>
  145. #include "exevents.h"
  146. #include "extnsionst.h"
  147. #include "dixevents.h"
  148. #include "dixgrabs.h"
  149. #include "../../dix/dispatch.h"
  150. #include "NXlib.h"
  151. #include "Events.h"
  152. #include "Windows.h"
  153. #include "Args.h"
  154. #ifdef NX_DEBUG_INPUT
  155. extern int nxagentDebugInput;
  156. extern int nxagentDebugInputDevices;
  157. #endif
  158. extern Display *nxagentDisplay;
  159. extern WindowPtr nxagentLastEnteredWindow;
  160. #define EXTENSION_EVENT_BASE 64
  161. #define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
  162. #define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
  163. #define AllButtonsMask ( \
  164. Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
  165. #define MotionMask ( \
  166. PointerMotionMask | Button1MotionMask | \
  167. Button2MotionMask | Button3MotionMask | Button4MotionMask | \
  168. Button5MotionMask | ButtonMotionMask )
  169. #define PropagateMask ( \
  170. KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
  171. MotionMask )
  172. #define PointerGrabMask ( \
  173. ButtonPressMask | ButtonReleaseMask | \
  174. EnterWindowMask | LeaveWindowMask | \
  175. PointerMotionHintMask | KeymapStateMask | \
  176. MotionMask )
  177. #define AllModifiersMask ( \
  178. ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
  179. Mod3Mask | Mod4Mask | Mod5Mask )
  180. #define AllEventMasks (lastEventMask|(lastEventMask-1))
  181. /*
  182. * The following relies on the fact that the Button<n>MotionMasks are equal
  183. * to the corresponding Button<n>Masks from the current modifier/button state.
  184. */
  185. #define Motion_Filter(class) (PointerMotionMask | \
  186. (class)->state | (class)->motionMask)
  187. #define WID(w) ((w) ? ((w)->drawable.id) : 0)
  188. #define XE_KBPTR (xE->u.keyButtonPointer)
  189. #define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
  190. CallbackListPtr EventCallback;
  191. CallbackListPtr DeviceEventCallback;
  192. #define DNPMCOUNT 8
  193. Mask DontPropagateMasks[DNPMCOUNT];
  194. static int DontPropagateRefCnts[DNPMCOUNT];
  195. #ifdef DEBUG
  196. static debug_events = 0;
  197. #endif
  198. InputInfo inputInfo;
  199. static struct {
  200. QdEventPtr pending, *pendtail;
  201. DeviceIntPtr replayDev; /* kludgy rock to put flag for */
  202. WindowPtr replayWin; /* ComputeFreezes */
  203. Bool playingEvents;
  204. TimeStamp time;
  205. } syncEvents;
  206. /*
  207. * The window trace information is used to avoid having to compute all the
  208. * windows between the root and the current pointer window each time a button
  209. * or key goes down. The grabs on each of those windows must be checked.
  210. */
  211. static WindowPtr *spriteTrace = (WindowPtr *)NULL;
  212. #define ROOT spriteTrace[0]
  213. static int spriteTraceSize = 0;
  214. static int spriteTraceGood;
  215. static struct {
  216. CursorPtr current;
  217. BoxRec hotLimits; /* logical constraints of hot spot */
  218. Bool confined; /* confined to screen */
  219. #if defined(SHAPE) || defined(PANORAMIX)
  220. RegionPtr hotShape; /* additional logical shape constraint */
  221. #endif
  222. BoxRec physLimits; /* physical constraints of hot spot */
  223. WindowPtr win; /* window of logical position */
  224. HotSpot hot; /* logical pointer position */
  225. HotSpot hotPhys; /* physical pointer position */
  226. #ifdef PANORAMIX
  227. ScreenPtr screen; /* all others are in Screen 0 coordinates */
  228. RegionRec Reg1; /* Region 1 for confining motion */
  229. RegionRec Reg2; /* Region 2 for confining virtual motion */
  230. WindowPtr windows[MAXSCREENS];
  231. WindowPtr confineWin; /* confine window */
  232. #endif
  233. } sprite; /* info about the cursor sprite */
  234. #ifdef XEVIE
  235. WindowPtr xeviewin;
  236. HotSpot xeviehot;
  237. #endif
  238. static void DoEnterLeaveEvents(
  239. WindowPtr fromWin,
  240. WindowPtr toWin,
  241. int mode
  242. );
  243. static WindowPtr XYToWindow(
  244. int x,
  245. int y
  246. );
  247. extern int lastEvent;
  248. static Mask lastEventMask;
  249. #ifdef XINPUT
  250. extern int DeviceMotionNotify;
  251. #endif
  252. #define CantBeFiltered NoEventMask
  253. static Mask filters[128] =
  254. {
  255. NoSuchEvent, /* 0 */
  256. NoSuchEvent, /* 1 */
  257. KeyPressMask, /* KeyPress */
  258. KeyReleaseMask, /* KeyRelease */
  259. ButtonPressMask, /* ButtonPress */
  260. ButtonReleaseMask, /* ButtonRelease */
  261. PointerMotionMask, /* MotionNotify (initial state) */
  262. EnterWindowMask, /* EnterNotify */
  263. LeaveWindowMask, /* LeaveNotify */
  264. FocusChangeMask, /* FocusIn */
  265. FocusChangeMask, /* FocusOut */
  266. KeymapStateMask, /* KeymapNotify */
  267. ExposureMask, /* Expose */
  268. CantBeFiltered, /* GraphicsExpose */
  269. CantBeFiltered, /* NoExpose */
  270. VisibilityChangeMask, /* VisibilityNotify */
  271. SubstructureNotifyMask, /* CreateNotify */
  272. StructureAndSubMask, /* DestroyNotify */
  273. StructureAndSubMask, /* UnmapNotify */
  274. StructureAndSubMask, /* MapNotify */
  275. SubstructureRedirectMask, /* MapRequest */
  276. StructureAndSubMask, /* ReparentNotify */
  277. StructureAndSubMask, /* ConfigureNotify */
  278. SubstructureRedirectMask, /* ConfigureRequest */
  279. StructureAndSubMask, /* GravityNotify */
  280. ResizeRedirectMask, /* ResizeRequest */
  281. StructureAndSubMask, /* CirculateNotify */
  282. SubstructureRedirectMask, /* CirculateRequest */
  283. PropertyChangeMask, /* PropertyNotify */
  284. CantBeFiltered, /* SelectionClear */
  285. CantBeFiltered, /* SelectionRequest */
  286. CantBeFiltered, /* SelectionNotify */
  287. ColormapChangeMask, /* ColormapNotify */
  288. CantBeFiltered, /* ClientMessage */
  289. CantBeFiltered /* MappingNotify */
  290. };
  291. static CARD8 criticalEvents[32] =
  292. {
  293. 0x7c /* key and button events */
  294. };
  295. #ifdef PANORAMIX
  296. static void ConfineToShape(RegionPtr shape, int *px, int *py);
  297. static void SyntheticMotion(int x, int y);
  298. static void PostNewCursor(void);
  299. static Bool
  300. XineramaSetCursorPosition(
  301. int x,
  302. int y,
  303. Bool generateEvent
  304. ){
  305. ScreenPtr pScreen;
  306. BoxRec box;
  307. int i;
  308. /* x,y are in Screen 0 coordinates. We need to decide what Screen
  309. to send the message too and what the coordinates relative to
  310. that screen are. */
  311. pScreen = sprite.screen;
  312. x += panoramiXdataPtr[0].x;
  313. y += panoramiXdataPtr[0].y;
  314. if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
  315. x, y, &box))
  316. {
  317. FOR_NSCREENS(i)
  318. {
  319. if(i == pScreen->myNum)
  320. continue;
  321. if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box))
  322. {
  323. pScreen = screenInfo.screens[i];
  324. break;
  325. }
  326. }
  327. }
  328. sprite.screen = pScreen;
  329. sprite.hotPhys.x = x - panoramiXdataPtr[0].x;
  330. sprite.hotPhys.y = y - panoramiXdataPtr[0].y;
  331. x -= panoramiXdataPtr[pScreen->myNum].x;
  332. y -= panoramiXdataPtr[pScreen->myNum].y;
  333. return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent);
  334. }
  335. static void
  336. XineramaConstrainCursor(void)
  337. {
  338. ScreenPtr pScreen = sprite.screen;
  339. BoxRec newBox = sprite.physLimits;
  340. /* Translate the constraining box to the screen
  341. the sprite is actually on */
  342. newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
  343. newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
  344. newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
  345. newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
  346. (* pScreen->ConstrainCursor)(pScreen, &newBox);
  347. }
  348. static void
  349. XineramaCheckPhysLimits(
  350. CursorPtr cursor,
  351. Bool generateEvents
  352. ){
  353. HotSpot new;
  354. if (!cursor)
  355. return;
  356. new = sprite.hotPhys;
  357. /* I don't care what the DDX has to say about it */
  358. sprite.physLimits = sprite.hotLimits;
  359. /* constrain the pointer to those limits */
  360. if (new.x < sprite.physLimits.x1)
  361. new.x = sprite.physLimits.x1;
  362. else
  363. if (new.x >= sprite.physLimits.x2)
  364. new.x = sprite.physLimits.x2 - 1;
  365. if (new.y < sprite.physLimits.y1)
  366. new.y = sprite.physLimits.y1;
  367. else
  368. if (new.y >= sprite.physLimits.y2)
  369. new.y = sprite.physLimits.y2 - 1;
  370. if (sprite.hotShape) /* more work if the shape is a mess */
  371. ConfineToShape(sprite.hotShape, &new.x, &new.y);
  372. if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
  373. {
  374. XineramaSetCursorPosition (new.x, new.y, generateEvents);
  375. if (!generateEvents)
  376. SyntheticMotion(new.x, new.y);
  377. }
  378. /* Tell DDX what the limits are */
  379. XineramaConstrainCursor();
  380. }
  381. static Bool
  382. XineramaSetWindowPntrs(WindowPtr pWin)
  383. {
  384. if(pWin == WindowTable[0]) {
  385. memcpy(sprite.windows, WindowTable,
  386. PanoramiXNumScreens*sizeof(WindowPtr));
  387. } else {
  388. PanoramiXRes *win;
  389. int i;
  390. win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW);
  391. if(!win)
  392. return FALSE;
  393. for(i = 0; i < PanoramiXNumScreens; i++) {
  394. sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW);
  395. if(!sprite.windows[i]) /* window is being unmapped */
  396. return FALSE;
  397. }
  398. }
  399. return TRUE;
  400. }
  401. static void
  402. XineramaCheckVirtualMotion(
  403. QdEventPtr qe,
  404. WindowPtr pWin
  405. ){
  406. if (qe)
  407. {
  408. sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */
  409. #ifdef XEVIE
  410. xeviehot.x =
  411. #endif
  412. sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
  413. #ifdef XEVIE
  414. xeviehot.y =
  415. #endif
  416. sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
  417. pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
  418. NullWindow;
  419. }
  420. if (pWin)
  421. {
  422. int x, y, off_x, off_y, i;
  423. BoxRec lims;
  424. if(!XineramaSetWindowPntrs(pWin))
  425. return;
  426. i = PanoramiXNumScreens - 1;
  427. REGION_COPY(sprite.screen, &sprite.Reg2,
  428. &sprite.windows[i]->borderSize);
  429. off_x = panoramiXdataPtr[i].x;
  430. off_y = panoramiXdataPtr[i].y;
  431. while(i--) {
  432. x = off_x - panoramiXdataPtr[i].x;
  433. y = off_y - panoramiXdataPtr[i].y;
  434. if(x || y)
  435. REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y);
  436. REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2,
  437. &sprite.windows[i]->borderSize);
  438. off_x = panoramiXdataPtr[i].x;
  439. off_y = panoramiXdataPtr[i].y;
  440. }
  441. lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2);
  442. if (sprite.hot.x < lims.x1)
  443. #ifdef XEVIE
  444. xeviehot.x =
  445. #endif
  446. sprite.hot.x = lims.x1;
  447. else if (sprite.hot.x >= lims.x2)
  448. #ifdef XEVIE
  449. xeviehot.x =
  450. #endif
  451. sprite.hot.x = lims.x2 - 1;
  452. if (sprite.hot.y < lims.y1)
  453. #ifdef XEVIE
  454. xeviehot.y =
  455. #endif
  456. sprite.hot.y = lims.y1;
  457. else if (sprite.hot.y >= lims.y2)
  458. #ifdef XEVIE
  459. xeviehot.y =
  460. #endif
  461. sprite.hot.y = lims.y2 - 1;
  462. if (REGION_NUM_RECTS(&sprite.Reg2) > 1)
  463. ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y);
  464. if (qe)
  465. {
  466. qe->pScreen = sprite.hot.pScreen;
  467. qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
  468. qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
  469. }
  470. }
  471. }
  472. static Bool
  473. XineramaCheckMotion(xEvent *xE)
  474. {
  475. WindowPtr prevSpriteWin = sprite.win;
  476. if (xE && !syncEvents.playingEvents)
  477. {
  478. /* Motion events entering DIX get translated to Screen 0
  479. coordinates. Replayed events have already been
  480. translated since they've entered DIX before */
  481. XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x -
  482. panoramiXdataPtr[0].x;
  483. XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y -
  484. panoramiXdataPtr[0].y;
  485. #ifdef XEVIE
  486. xeviehot.x =
  487. #endif
  488. sprite.hot.x = XE_KBPTR.rootX;
  489. #ifdef XEVIE
  490. xeviehot.y =
  491. #endif
  492. sprite.hot.y = XE_KBPTR.rootY;
  493. if (sprite.hot.x < sprite.physLimits.x1)
  494. #ifdef XEVIE
  495. xeviehot.x =
  496. #endif
  497. sprite.hot.x = sprite.physLimits.x1;
  498. else if (sprite.hot.x >= sprite.physLimits.x2)
  499. #ifdef XEVIE
  500. xeviehot.x =
  501. #endif
  502. sprite.hot.x = sprite.physLimits.x2 - 1;
  503. if (sprite.hot.y < sprite.physLimits.y1)
  504. #ifdef XEVIE
  505. xeviehot.y =
  506. #endif
  507. sprite.hot.y = sprite.physLimits.y1;
  508. else if (sprite.hot.y >= sprite.physLimits.y2)
  509. #ifdef XEVIE
  510. xeviehot.y =
  511. #endif
  512. sprite.hot.y = sprite.physLimits.y2 - 1;
  513. if (sprite.hotShape)
  514. ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
  515. sprite.hotPhys = sprite.hot;
  516. if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
  517. (sprite.hotPhys.y != XE_KBPTR.rootY))
  518. {
  519. XineramaSetCursorPosition(
  520. sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
  521. }
  522. XE_KBPTR.rootX = sprite.hot.x;
  523. XE_KBPTR.rootY = sprite.hot.y;
  524. }
  525. #ifdef XEVIE
  526. xeviewin =
  527. #endif
  528. sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
  529. if (sprite.win != prevSpriteWin)
  530. {
  531. if (prevSpriteWin != NullWindow) {
  532. if (!xE)
  533. UpdateCurrentTimeIf();
  534. DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
  535. }
  536. PostNewCursor();
  537. return FALSE;
  538. }
  539. return TRUE;
  540. }
  541. static void
  542. XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
  543. {
  544. if (syncEvents.playingEvents)
  545. {
  546. XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin);
  547. SyntheticMotion(sprite.hot.x, sprite.hot.y);
  548. }
  549. else
  550. {
  551. int x, y, off_x, off_y, i;
  552. if(!XineramaSetWindowPntrs(pWin))
  553. return;
  554. i = PanoramiXNumScreens - 1;
  555. REGION_COPY(sprite.screen, &sprite.Reg1,
  556. &sprite.windows[i]->borderSize);
  557. off_x = panoramiXdataPtr[i].x;
  558. off_y = panoramiXdataPtr[i].y;
  559. while(i--) {
  560. x = off_x - panoramiXdataPtr[i].x;
  561. y = off_y - panoramiXdataPtr[i].y;
  562. if(x || y)
  563. REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y);
  564. REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1,
  565. &sprite.windows[i]->borderSize);
  566. off_x = panoramiXdataPtr[i].x;
  567. off_y = panoramiXdataPtr[i].y;
  568. }
  569. sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1);
  570. if(REGION_NUM_RECTS(&sprite.Reg1) > 1)
  571. sprite.hotShape = &sprite.Reg1;
  572. else
  573. sprite.hotShape = NullRegion;
  574. sprite.confined = FALSE;
  575. sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
  576. XineramaCheckPhysLimits(sprite.current, generateEvents);
  577. }
  578. }
  579. static void
  580. XineramaChangeToCursor(CursorPtr cursor)
  581. {
  582. if (cursor != sprite.current)
  583. {
  584. if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
  585. (sprite.current->bits->yhot != cursor->bits->yhot))
  586. XineramaCheckPhysLimits(cursor, FALSE);
  587. (*sprite.screen->DisplayCursor)(sprite.screen, cursor);
  588. FreeCursor(sprite.current, (Cursor)0);
  589. sprite.current = cursor;
  590. sprite.current->refcnt++;
  591. }
  592. }
  593. #endif /* PANORAMIX */
  594. void
  595. SetMaskForEvent(Mask mask, int event)
  596. {
  597. if ((event < LASTEvent) || (event >= 128))
  598. FatalError("SetMaskForEvent: bogus event number");
  599. filters[event] = mask;
  600. }
  601. void
  602. SetCriticalEvent(int event)
  603. {
  604. if (event >= 128)
  605. FatalError("SetCriticalEvent: bogus event number");
  606. criticalEvents[event >> 3] |= 1 << (event & 7);
  607. }
  608. static void
  609. SyntheticMotion(int x, int y)
  610. {
  611. xEvent xE;
  612. #ifdef PANORAMIX
  613. /* Translate back to the sprite screen since processInputProc
  614. will translate from sprite screen to screen 0 upon reentry
  615. to the DIX layer */
  616. if(!noPanoramiXExtension) {
  617. x += panoramiXdataPtr[0].x - panoramiXdataPtr[sprite.screen->myNum].x;
  618. y += panoramiXdataPtr[0].y - panoramiXdataPtr[sprite.screen->myNum].y;
  619. }
  620. #endif
  621. xE.u.keyButtonPointer.rootX = x;
  622. xE.u.keyButtonPointer.rootY = y;
  623. if (syncEvents.playingEvents)
  624. xE.u.keyButtonPointer.time = syncEvents.time.milliseconds;
  625. else
  626. xE.u.keyButtonPointer.time = currentTime.milliseconds;
  627. xE.u.u.type = MotionNotify;
  628. (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1);
  629. }
  630. #ifdef SHAPE
  631. static void
  632. ConfineToShape(RegionPtr shape, int *px, int *py)
  633. {
  634. BoxRec box;
  635. int x = *px, y = *py;
  636. int incx = 1, incy = 1;
  637. if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box))
  638. return;
  639. box = *REGION_EXTENTS(sprite.hot.pScreen, shape);
  640. /* this is rather crude */
  641. do {
  642. x += incx;
  643. if (x >= box.x2)
  644. {
  645. incx = -1;
  646. x = *px - 1;
  647. }
  648. else if (x < box.x1)
  649. {
  650. incx = 1;
  651. x = *px;
  652. y += incy;
  653. if (y >= box.y2)
  654. {
  655. incy = -1;
  656. y = *py - 1;
  657. }
  658. else if (y < box.y1)
  659. return; /* should never get here! */
  660. }
  661. } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box));
  662. *px = x;
  663. *py = y;
  664. }
  665. #endif
  666. static void
  667. CheckPhysLimits(
  668. CursorPtr cursor,
  669. Bool generateEvents,
  670. Bool confineToScreen,
  671. ScreenPtr pScreen)
  672. {
  673. HotSpot new;
  674. if (!cursor)
  675. return;
  676. new = sprite.hotPhys;
  677. if (pScreen)
  678. new.pScreen = pScreen;
  679. else
  680. pScreen = new.pScreen;
  681. (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits,
  682. &sprite.physLimits);
  683. sprite.confined = confineToScreen;
  684. (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits);
  685. if (new.x < sprite.physLimits.x1)
  686. new.x = sprite.physLimits.x1;
  687. else
  688. if (new.x >= sprite.physLimits.x2)
  689. new.x = sprite.physLimits.x2 - 1;
  690. if (new.y < sprite.physLimits.y1)
  691. new.y = sprite.physLimits.y1;
  692. else
  693. if (new.y >= sprite.physLimits.y2)
  694. new.y = sprite.physLimits.y2 - 1;
  695. #ifdef SHAPE
  696. if (sprite.hotShape)
  697. ConfineToShape(sprite.hotShape, &new.x, &new.y);
  698. #endif
  699. if ((pScreen != sprite.hotPhys.pScreen) ||
  700. (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
  701. {
  702. if (pScreen != sprite.hotPhys.pScreen)
  703. sprite.hotPhys = new;
  704. (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents);
  705. if (!generateEvents)
  706. SyntheticMotion(new.x, new.y);
  707. }
  708. }
  709. static void
  710. CheckVirtualMotion(
  711. register QdEventPtr qe,
  712. register WindowPtr pWin)
  713. {
  714. #ifdef PANORAMIX
  715. if(!noPanoramiXExtension) {
  716. XineramaCheckVirtualMotion(qe, pWin);
  717. return;
  718. }
  719. #endif
  720. if (qe)
  721. {
  722. sprite.hot.pScreen = qe->pScreen;
  723. #ifdef XEVIE
  724. xeviehot.x =
  725. #endif
  726. sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
  727. #ifdef XEVIE
  728. xeviehot.y =
  729. #endif
  730. sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
  731. pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
  732. NullWindow;
  733. }
  734. if (pWin)
  735. {
  736. BoxRec lims;
  737. if (sprite.hot.pScreen != pWin->drawable.pScreen)
  738. {
  739. sprite.hot.pScreen = pWin->drawable.pScreen;
  740. #ifdef XEVIE
  741. xeviehot.x = xeviehot.y = 0;
  742. #endif
  743. sprite.hot.x = sprite.hot.y = 0;
  744. }
  745. lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
  746. if (sprite.hot.x < lims.x1)
  747. #ifdef XEVIE
  748. xeviehot.x =
  749. #endif
  750. sprite.hot.x = lims.x1;
  751. else if (sprite.hot.x >= lims.x2)
  752. #ifdef XEVIE
  753. xeviehot.x =
  754. #endif
  755. sprite.hot.x = lims.x2 - 1;
  756. if (sprite.hot.y < lims.y1)
  757. #ifdef XEVIE
  758. xeviehot.y =
  759. #endif
  760. sprite.hot.y = lims.y1;
  761. else if (sprite.hot.y >= lims.y2)
  762. #ifdef XEVIE
  763. xeviehot.y =
  764. #endif
  765. sprite.hot.y = lims.y2 - 1;
  766. #ifdef SHAPE
  767. if (wBoundingShape(pWin))
  768. ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y);
  769. #endif
  770. if (qe)
  771. {
  772. qe->pScreen = sprite.hot.pScreen;
  773. qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
  774. qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
  775. }
  776. }
  777. ROOT = WindowTable[sprite.hot.pScreen->myNum];
  778. }
  779. static void
  780. ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
  781. {
  782. ScreenPtr pScreen = pWin->drawable.pScreen;
  783. #ifdef PANORAMIX
  784. if(!noPanoramiXExtension) {
  785. XineramaConfineCursorToWindow(pWin, generateEvents);
  786. return;
  787. }
  788. #endif
  789. if (syncEvents.playingEvents)
  790. {
  791. CheckVirtualMotion((QdEventPtr)NULL, pWin);
  792. SyntheticMotion(sprite.hot.x, sprite.hot.y);
  793. }
  794. else
  795. {
  796. sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
  797. #ifdef SHAPE
  798. sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize
  799. : NullRegion;
  800. #endif
  801. CheckPhysLimits(sprite.current, generateEvents, confineToScreen,
  802. pScreen);
  803. }
  804. }
  805. Bool
  806. PointerConfinedToScreen()
  807. {
  808. return sprite.confined;
  809. }
  810. static void
  811. ChangeToCursor(CursorPtr cursor)
  812. {
  813. #ifdef PANORAMIX
  814. if(!noPanoramiXExtension) {
  815. XineramaChangeToCursor(cursor);
  816. return;
  817. }
  818. #endif
  819. if (cursor != sprite.current)
  820. {
  821. if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
  822. (sprite.current->bits->yhot != cursor->bits->yhot))
  823. CheckPhysLimits(cursor, FALSE, sprite.confined,
  824. (ScreenPtr)NULL);
  825. (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen,
  826. cursor);
  827. FreeCursor(sprite.current, (Cursor)0);
  828. sprite.current = cursor;
  829. sprite.current->refcnt++;
  830. }
  831. }
  832. /* returns true if b is a descendent of a */
  833. Bool
  834. IsParent(register WindowPtr a, register WindowPtr b)
  835. {
  836. for (b = b->parent; b; b = b->parent)
  837. if (b == a) return TRUE;
  838. return FALSE;
  839. }
  840. static void
  841. PostNewCursor(void)
  842. {
  843. register WindowPtr win;
  844. register GrabPtr grab = inputInfo.pointer->grab;
  845. if (syncEvents.playingEvents)
  846. return;
  847. if (grab)
  848. {
  849. if (grab->cursor)
  850. {
  851. ChangeToCursor(grab->cursor);
  852. return;
  853. }
  854. if (IsParent(grab->window, sprite.win))
  855. win = sprite.win;
  856. else
  857. win = grab->window;
  858. }
  859. else
  860. win = sprite.win;
  861. for (; win; win = win->parent)
  862. if (win->optional && win->optional->cursor != NullCursor)
  863. {
  864. ChangeToCursor(win->optional->cursor);
  865. return;
  866. }
  867. }
  868. WindowPtr
  869. GetCurrentRootWindow()
  870. {
  871. return ROOT;
  872. }
  873. WindowPtr
  874. GetSpriteWindow()
  875. {
  876. return sprite.win;
  877. }
  878. CursorPtr
  879. GetSpriteCursor()
  880. {
  881. return sprite.current;
  882. }
  883. void
  884. GetSpritePosition(int *px, int *py)
  885. {
  886. *px = sprite.hotPhys.x;
  887. *py = sprite.hotPhys.y;
  888. }
  889. #ifdef PANORAMIX
  890. int
  891. XineramaGetCursorScreen()
  892. {
  893. if(!noPanoramiXExtension) {
  894. return sprite.screen->myNum;
  895. } else {
  896. return 0;
  897. }
  898. }
  899. #endif /* PANORAMIX */
  900. #define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
  901. static void
  902. MonthChangedOrBadTime(register xEvent *xE)
  903. {
  904. /* If the ddx/OS is careless about not processing timestamped events from
  905. * different sources in sorted order, then it's possible for time to go
  906. * backwards when it should not. Here we ensure a decent time.
  907. */
  908. if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP)
  909. currentTime.months++;
  910. else
  911. XE_KBPTR.time = currentTime.milliseconds;
  912. }
  913. #define NoticeTime(xE) { \
  914. if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \
  915. MonthChangedOrBadTime(xE); \
  916. currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \
  917. lastDeviceEventTime = currentTime; }
  918. void
  919. NoticeEventTime(register xEvent *xE)
  920. {
  921. if (!syncEvents.playingEvents)
  922. NoticeTime(xE);
  923. }
  924. /**************************************************************************
  925. * The following procedures deal with synchronous events *
  926. **************************************************************************/
  927. void
  928. EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
  929. {
  930. register QdEventPtr tail = *syncEvents.pendtail;
  931. register QdEventPtr qe;
  932. xEvent *qxE;
  933. NoticeTime(xE);
  934. #ifdef XKB
  935. /* Fix for key repeating bug. */
  936. if (device->key != NULL && device->key->xkbInfo != NULL &&
  937. xE->u.u.type == KeyRelease)
  938. AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail);
  939. #endif
  940. if (DeviceEventCallback)
  941. {
  942. DeviceEventInfoRec eventinfo;
  943. /* The RECORD spec says that the root window field of motion events
  944. * must be valid. At this point, it hasn't been filled in yet, so
  945. * we do it here. The long expression below is necessary to get
  946. * the current root window; the apparently reasonable alternative
  947. * GetCurrentRootWindow()->drawable.id doesn't give you the right
  948. * answer on the first motion event after a screen change because
  949. * the data that GetCurrentRootWindow relies on hasn't been
  950. * updated yet.
  951. */
  952. if (xE->u.u.type == MotionNotify)
  953. XE_KBPTR.root =
  954. WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
  955. eventinfo.events = xE;
  956. eventinfo.count = count;
  957. CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
  958. }
  959. if (xE->u.u.type == MotionNotify)
  960. {
  961. #ifdef PANORAMIX
  962. if(!noPanoramiXExtension) {
  963. XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x -
  964. panoramiXdataPtr[0].x;
  965. XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y -
  966. panoramiXdataPtr[0].y;
  967. }
  968. #endif
  969. sprite.hotPhys.x = XE_KBPTR.rootX;
  970. sprite.hotPhys.y = XE_KBPTR.rootY;
  971. /* do motion compression */
  972. if (tail &&
  973. (tail->event->u.u.type == MotionNotify) &&
  974. (tail->pScreen == sprite.hotPhys.pScreen))
  975. {
  976. tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x;
  977. tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y;
  978. tail->event->u.keyButtonPointer.time = XE_KBPTR.time;
  979. tail->months = currentTime.months;
  980. return;
  981. }
  982. }
  983. qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent)));
  984. if (!qe)
  985. return;
  986. qe->next = (QdEventPtr)NULL;
  987. qe->device = device;
  988. qe->pScreen = sprite.hotPhys.pScreen;
  989. qe->months = currentTime.months;
  990. qe->event = (xEvent *)(qe + 1);
  991. qe->evcount = count;
  992. for (qxE = qe->event; --count >= 0; qxE++, xE++)
  993. *qxE = *xE;
  994. if (tail)
  995. syncEvents.pendtail = &tail->next;
  996. *syncEvents.pendtail = qe;
  997. }
  998. static void
  999. PlayReleasedEvents(void)
  1000. {
  1001. register QdEventPtr *prev, qe;
  1002. register DeviceIntPtr dev;
  1003. prev = &syncEvents.pending;
  1004. while ( (qe = *prev) )
  1005. {
  1006. if (!qe->device->sync.frozen)
  1007. {
  1008. *prev = qe->next;
  1009. if (*syncEvents.pendtail == *prev)
  1010. syncEvents.pendtail = prev;
  1011. if (qe->event->u.u.type == MotionNotify)
  1012. CheckVirtualMotion(qe, NullWindow);
  1013. syncEvents.time.months = qe->months;
  1014. syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
  1015. #ifdef PANORAMIX
  1016. /* Translate back to the sprite screen since processInputProc
  1017. will translate from sprite screen to screen 0 upon reentry
  1018. to the DIX layer */
  1019. if(!noPanoramiXExtension) {
  1020. qe->event->u.keyButtonPointer.rootX +=
  1021. panoramiXdataPtr[0].x -
  1022. panoramiXdataPtr[sprite.screen->myNum].x;
  1023. qe->event->u.keyButtonPointer.rootY +=
  1024. panoramiXdataPtr[0].y -
  1025. panoramiXdataPtr[sprite.screen->myNum].y;
  1026. }
  1027. #endif
  1028. (*qe->device->public.processInputProc)(qe->event, qe->device,
  1029. qe->evcount);
  1030. xfree(qe);
  1031. for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next)
  1032. ;
  1033. if (!dev)
  1034. break;
  1035. /* Playing the event may have unfrozen another device. */
  1036. /* So to play it safe, restart at the head of the queue */
  1037. prev = &syncEvents.pending;
  1038. }
  1039. else
  1040. prev = &qe->next;
  1041. }
  1042. }
  1043. static void
  1044. FreezeThaw(register DeviceIntPtr dev, Bool frozen)
  1045. {
  1046. dev->sync.frozen = frozen;
  1047. if (frozen)
  1048. dev->public.processInputProc = dev->public.enqueueInputProc;
  1049. else
  1050. dev->public.processInputProc = dev->public.realInputProc;
  1051. }
  1052. void
  1053. ComputeFreezes()
  1054. {
  1055. register DeviceIntPtr replayDev = syncEvents.replayDev;
  1056. register int i;
  1057. WindowPtr w;
  1058. register xEvent *xE;
  1059. int count;
  1060. GrabPtr grab;
  1061. register DeviceIntPtr dev;
  1062. for (dev = inputInfo.devices; dev; dev = dev->next)
  1063. FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN));
  1064. if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
  1065. return;
  1066. syncEvents.playingEvents = TRUE;
  1067. if (replayDev)
  1068. {
  1069. xE = replayDev->sync.event;
  1070. count = replayDev->sync.evcount;
  1071. syncEvents.replayDev = (DeviceIntPtr)NULL;
  1072. w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY);
  1073. for (i = 0; i < spriteTraceGood; i++)
  1074. {
  1075. if (syncEvents.replayWin == spriteTrace[i])
  1076. {
  1077. if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
  1078. if (replayDev->focus)
  1079. DeliverFocusedEvent(replayDev, xE, w, count);
  1080. else
  1081. DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
  1082. replayDev, count);
  1083. }
  1084. goto playmore;
  1085. }
  1086. }
  1087. /* must not still be in the same stack */
  1088. if (replayDev->focus)
  1089. DeliverFocusedEvent(replayDev, xE, w, count);
  1090. else
  1091. DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
  1092. }
  1093. playmore:
  1094. for (dev = inputInfo.devices; dev; dev = dev->next)
  1095. {
  1096. if (!dev->sync.frozen)
  1097. {
  1098. PlayReleasedEvents();
  1099. break;
  1100. }
  1101. }
  1102. syncEvents.playingEvents = FALSE;
  1103. /* the following may have been skipped during replay, so do it now */
  1104. if ((grab = inputInfo.pointer->grab) && grab->confineTo)
  1105. {
  1106. if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
  1107. sprite.hotPhys.x = sprite.hotPhys.y = 0;
  1108. ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
  1109. }
  1110. else
  1111. ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
  1112. TRUE, FALSE);
  1113. PostNewCursor();
  1114. }
  1115. #ifdef RANDR
  1116. void
  1117. ScreenRestructured (ScreenPtr pScreen)
  1118. {
  1119. GrabPtr grab;
  1120. if ((grab = inputInfo.pointer->grab) && grab->confineTo)
  1121. {
  1122. if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
  1123. sprite.hotPhys.x = sprite.hotPhys.y = 0;
  1124. ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
  1125. }
  1126. else
  1127. ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
  1128. TRUE, FALSE);
  1129. }
  1130. #endif
  1131. void
  1132. CheckGrabForSyncs(register DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
  1133. {
  1134. register GrabPtr grab = thisDev->grab;
  1135. register DeviceIntPtr dev;
  1136. if (thisMode == GrabModeSync)
  1137. thisDev->sync.state = FROZEN_NO_EVENT;
  1138. else
  1139. { /* free both if same client owns both */
  1140. thisDev->sync.state = THAWED;
  1141. if (thisDev->sync.other &&
  1142. (CLIENT_BITS(thisDev->sync.other->resource) ==
  1143. CLIENT_BITS(grab->resource)))
  1144. thisDev->sync.other = NullGrab;
  1145. }
  1146. for (dev = inputInfo.devices; dev; dev = dev->next)
  1147. {
  1148. if (dev != thisDev)
  1149. {
  1150. if (otherMode == GrabModeSync)
  1151. dev->sync.other = grab;
  1152. else
  1153. { /* free both if same client owns both */
  1154. if (dev->sync.other &&
  1155. (CLIENT_BITS(dev->sync.other->resource) ==
  1156. CLIENT_BITS(grab->resource)))
  1157. dev->sync.other = NullGrab;
  1158. }
  1159. }
  1160. }
  1161. ComputeFreezes();
  1162. }
  1163. void
  1164. ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab,
  1165. TimeStamp time, Bool autoGrab)
  1166. {
  1167. WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
  1168. : sprite.win;
  1169. if (grab->confineTo)
  1170. {
  1171. if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
  1172. sprite.hotPhys.x = sprite.hotPhys.y = 0;
  1173. ConfineCursorToWindow(grab->confineTo, FALSE, TRUE);
  1174. }
  1175. DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab);
  1176. mouse->valuator->motionHintWindow = NullWindow;
  1177. if (syncEvents.playingEvents)
  1178. mouse->grabTime = syncEvents.time;
  1179. else
  1180. mouse->grabTime = time;
  1181. if (grab->cursor)
  1182. grab->cursor->refcnt++;
  1183. mouse->activeGrab = *grab;
  1184. mouse->grab = &mouse->activeGrab;
  1185. mouse->fromPassiveGrab = autoGrab;
  1186. PostNewCursor();
  1187. CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
  1188. #ifdef NXAGENT_SERVER
  1189. /*
  1190. * If grab is synchronous, events are delivered to clients only if they send
  1191. * an AllowEvent request. If mode field in AllowEvent request is SyncPointer, the
  1192. * delivered event is saved in a queue and replayed later, when grab is released.
  1193. * We should export sync grab to X as async in order to avoid events to be
  1194. * queued twice, in the agent and in the X server. This solution have a drawback:
  1195. * replayed events are not delivered to that application that are not clients of
  1196. * the agent.
  1197. * A different solution could be to make the grab asynchronous in the agent and
  1198. * to export it as synchronous. But this seems to be less safe.
  1199. *
  1200. * To make internal grab asynchronous, change previous line as follows.
  1201. *
  1202. * if (nxagentOption(Rootless))
  1203. * {
  1204. * CheckGrabForSyncs(mouse, GrabModeAsync, (Bool)grab->keyboardMode);
  1205. * }
  1206. * else
  1207. * {
  1208. * CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
  1209. * }
  1210. */
  1211. if (nxagentOption(Rootless) == 1)
  1212. {
  1213. /*
  1214. * FIXME: We should use the correct value
  1215. * for the cursor. Temporarily we set it
  1216. * to None.
  1217. */
  1218. int resource = nxagentWaitForResource(NXGetCollectGrabPointerResource,
  1219. nxagentCollectGrabPointerPredicate);
  1220. NXCollectGrabPointer(nxagentDisplay, resource, nxagentWindow(grab -> window),
  1221. 1, grab -> eventMask & PointerGrabMask,
  1222. GrabModeAsync, GrabModeAsync, (grab -> confineTo) ?
  1223. nxagentWindow(grab -> confineTo) : None,
  1224. None, CurrentTime);
  1225. }
  1226. #endif
  1227. }
  1228. void
  1229. DeactivatePointerGrab(register DeviceIntPtr mouse)
  1230. {
  1231. register GrabPtr grab = mouse->grab;
  1232. register DeviceIntPtr dev;
  1233. mouse->valuator->motionHintWindow = NullWindow;
  1234. mouse->grab = NullGrab;
  1235. mouse->sync.state = NOT_GRABBED;
  1236. mouse->fromPassiveGrab = FALSE;
  1237. for (dev = inputInfo.devices; dev; dev = dev->next)
  1238. {
  1239. if (dev->sync.other == grab)
  1240. dev->sync.other = NullGrab;
  1241. }
  1242. DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab);
  1243. if (grab->confineTo)
  1244. ConfineCursorToWindow(ROOT, FALSE, FALSE);
  1245. PostNewCursor();
  1246. if (grab->cursor)
  1247. FreeCursor(grab->cursor, (Cursor)0);
  1248. ComputeFreezes();
  1249. #ifdef NXAGENT_SERVER
  1250. if (nxagentOption(Rootless) == 1)
  1251. {
  1252. XUngrabPointer(nxagentDisplay, CurrentTime);
  1253. if (sprite.win == ROOT)
  1254. {
  1255. mouse -> button -> state &=
  1256. ~(Button1Mask | Button2Mask | Button3Mask |
  1257. Button4Mask | Button5Mask);
  1258. }
  1259. }
  1260. #endif
  1261. }
  1262. void
  1263. ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
  1264. {
  1265. WindowPtr oldWin;
  1266. if (keybd->grab)
  1267. oldWin = keybd->grab->window;
  1268. else if (keybd->focus)
  1269. oldWin = keybd->focus->win;
  1270. else
  1271. oldWin = sprite.win;
  1272. if (oldWin == FollowKeyboardWin)
  1273. oldWin = inputInfo.keyboard->focus->win;
  1274. if (keybd->valuator)
  1275. keybd->valuator->motionHintWindow = NullWindow;
  1276. DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
  1277. if (syncEvents.playingEvents)
  1278. keybd->grabTime = syncEvents.time;
  1279. else
  1280. keybd->grabTime = time;
  1281. keybd->activeGrab = *grab;
  1282. keybd->grab = &keybd->activeGrab;
  1283. keybd->fromPassiveGrab = passive;
  1284. CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
  1285. }
  1286. void
  1287. DeactivateKeyboardGrab(register DeviceIntPtr keybd)
  1288. {
  1289. register GrabPtr grab = keybd->grab;
  1290. register DeviceIntPtr dev;
  1291. register WindowPtr focusWin = keybd->focus ? keybd->focus->win
  1292. : sprite.win;
  1293. if (focusWin == FollowKeyboardWin)
  1294. focusWin = inputInfo.keyboard->focus->win;
  1295. if (keybd->valuator)
  1296. keybd->valuator->motionHintWindow = NullWindow;
  1297. keybd->grab = NullGrab;
  1298. keybd->sync.state = NOT_GRABBED;
  1299. keybd->fromPassiveGrab = FALSE;
  1300. for (dev = inputInfo.devices; dev; dev = dev->next)
  1301. {
  1302. if (dev->sync.other == grab)
  1303. dev->sync.other = NullGrab;
  1304. }
  1305. DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
  1306. ComputeFreezes();
  1307. }
  1308. void
  1309. AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
  1310. {
  1311. Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
  1312. TimeStamp grabTime;
  1313. register DeviceIntPtr dev;
  1314. thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client);
  1315. thisSynced = FALSE;
  1316. otherGrabbed = FALSE;
  1317. othersFrozen = TRUE;
  1318. grabTime = thisDev->grabTime;
  1319. for (dev = inputInfo.devices; dev; dev = dev->next)
  1320. {
  1321. if (dev == thisDev)
  1322. continue;
  1323. if (dev->grab && SameClient(dev->grab, client))
  1324. {
  1325. if (!(thisGrabbed || otherGrabbed) ||
  1326. (CompareTimeStamps(dev->grabTime, grabTime) == LATER))
  1327. grabTime = dev->grabTime;
  1328. otherGrabbed = TRUE;
  1329. if (thisDev->sync.other == dev->grab)
  1330. thisSynced = TRUE;
  1331. if (dev->sync.state < FROZEN)
  1332. othersFrozen = FALSE;
  1333. }
  1334. else if (!dev->sync.other || !SameClient(dev->sync.other, client))
  1335. othersFrozen = FALSE;
  1336. }
  1337. if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced))
  1338. return;
  1339. if ((CompareTimeStamps(time, currentTime) == LATER) ||
  1340. (CompareTimeStamps(time, grabTime) == EARLIER))
  1341. return;
  1342. switch (newState)
  1343. {
  1344. case THAWED: /* Async */
  1345. if (thisGrabbed)
  1346. thisDev->sync.state = THAWED;
  1347. if (thisSynced)
  1348. thisDev->sync.other = NullGrab;
  1349. ComputeFreezes();
  1350. break;
  1351. case FREEZE_NEXT_EVENT: /* Sync */
  1352. if (thisGrabbed)
  1353. {
  1354. thisDev->sync.state = FREEZE_NEXT_EVENT;
  1355. if (thisSynced)
  1356. thisDev->sync.other = NullGrab;
  1357. ComputeFreezes();
  1358. }
  1359. break;
  1360. case THAWED_BOTH: /* AsyncBoth */
  1361. if (othersFrozen)
  1362. {
  1363. for (dev = inputInfo.devices; dev; dev = dev->next)
  1364. {
  1365. if (dev->grab && SameClient(dev->grab, client))
  1366. dev->sync.state = THAWED;
  1367. if (dev->sync.other && SameClient(dev->sync.other, client))
  1368. dev->sync.other = NullGrab;
  1369. }
  1370. ComputeFreezes();
  1371. }
  1372. break;
  1373. case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */
  1374. if (othersFrozen)
  1375. {
  1376. for (dev = inputInfo.devices; dev; dev = dev->next)
  1377. {
  1378. if (dev->grab && SameClient(dev->grab, client))
  1379. dev->sync.state = FREEZE_BOTH_NEXT_EVENT;
  1380. if (dev->sync.other && SameClient(dev->sync.other, client))
  1381. dev->sync.other = NullGrab;
  1382. }
  1383. ComputeFreezes();
  1384. }
  1385. break;
  1386. case NOT_GRABBED: /* Replay */
  1387. if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT)
  1388. {
  1389. if (thisSynced)
  1390. thisDev->sync.other = NullGrab;
  1391. syncEvents.replayDev = thisDev;
  1392. syncEvents.replayWin = thisDev->grab->window;
  1393. (*thisDev->DeactivateGrab)(thisDev);
  1394. syncEvents.replayDev = (DeviceIntPtr)NULL;
  1395. }
  1396. break;
  1397. case THAW_OTHERS: /* AsyncOthers */
  1398. if (othersFrozen)
  1399. {
  1400. for (dev = inputInfo.devices; dev; dev = dev->next)
  1401. {
  1402. if (dev == thisDev)
  1403. continue;
  1404. if (dev->grab && SameClient(dev->grab, client))
  1405. dev->sync.state = THAWED;
  1406. if (dev->sync.other && SameClient(dev->sync.other, client))
  1407. dev->sync.other = NullGrab;
  1408. }
  1409. ComputeFreezes();
  1410. }
  1411. break;
  1412. }
  1413. }
  1414. int
  1415. ProcAllowEvents(register ClientPtr client)
  1416. {
  1417. TimeStamp time;
  1418. DeviceIntPtr mouse = inputInfo.pointer;
  1419. DeviceIntPtr keybd = inputInfo.keyboard;
  1420. REQUEST(xAllowEventsReq);
  1421. REQUEST_SIZE_MATCH(xAllowEventsReq);
  1422. time = ClientTimeToServerTime(stuff->time);
  1423. switch (stuff->mode)
  1424. {
  1425. case ReplayPointer:
  1426. AllowSome(client, time, mouse, NOT_GRABBED);
  1427. break;
  1428. case SyncPointer:
  1429. AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
  1430. break;
  1431. case AsyncPointer:
  1432. AllowSome(client, time, mouse, THAWED);
  1433. break;
  1434. case ReplayKeyboard:
  1435. AllowSome(client, time, keybd, NOT_GRABBED);
  1436. break;
  1437. case SyncKeyboard:
  1438. AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
  1439. break;
  1440. case AsyncKeyboard:
  1441. AllowSome(client, time, keybd, THAWED);
  1442. break;
  1443. case SyncBoth:
  1444. AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
  1445. break;
  1446. case AsyncBoth:
  1447. AllowSome(client, time, keybd, THAWED_BOTH);
  1448. break;
  1449. default:
  1450. client->errorValue = stuff->mode;
  1451. return BadValue;
  1452. }
  1453. /*
  1454. * This is not necessary if we export grab to X as asynchronous.
  1455. *
  1456. * if (nxagentOption(Rootless) && stuff -> mode != ReplayKeyboard &&
  1457. * stuff -> mode != SyncKeyboard && stuff -> mode != AsyncKeyboard)
  1458. * {
  1459. * XAllowEvents(nxagentDisplay, stuff -> mode, CurrentTime);
  1460. * }
  1461. */
  1462. return Success;
  1463. }
  1464. void
  1465. ReleaseActiveGrabs(ClientPtr client)
  1466. {
  1467. register DeviceIntPtr dev;
  1468. Bool done;
  1469. /* XXX CloseDownClient should remove passive grabs before
  1470. * releasing active grabs.
  1471. */
  1472. do {
  1473. done = TRUE;
  1474. for (dev = inputInfo.devices; dev; dev = dev->next)
  1475. {
  1476. if (dev->grab && SameClient(dev->grab, client))
  1477. {
  1478. (*dev->DeactivateGrab)(dev);
  1479. done = FALSE;
  1480. }
  1481. }
  1482. } while (!done);
  1483. }
  1484. /**************************************************************************
  1485. * The following procedures deal with delivering events *
  1486. **************************************************************************/
  1487. int
  1488. TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
  1489. Mask filter, GrabPtr grab)
  1490. {
  1491. int i;
  1492. int type;
  1493. #ifdef NX_DEBUG_INPUT
  1494. if (grab && nxagentDebugInput && grab->window)
  1495. {
  1496. fprintf(stderr, "TryClientEvents: Grab window is [0x%x].\n",
  1497. (unsigned int)grab->window->drawable.id);
  1498. if (!SameClient(grab, client))
  1499. fprintf(stderr, "TryClientEvents: Events are going to be "
  1500. "discarded.\n");
  1501. }
  1502. #endif
  1503. #if defined(DEBUG) || defined(NX_DEBUG_INPUT)
  1504. #ifdef NX_DEBUG_INPUT
  1505. if (nxagentDebugInput == 1)
  1506. fprintf(stderr, "Event([%d, %d], mask=0x%x), client=%d",
  1507. pEvents->u.u.type, pEvents->u.u.detail, (unsigned int)mask,
  1508. client->index);
  1509. #else
  1510. if (debug_events) ErrorF(
  1511. "Event([%d, %d], mask=0x%x), client=%d",
  1512. pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
  1513. #endif
  1514. #endif
  1515. if ((client) && (client != serverClient) && (!client->clientGone) &&
  1516. ((filter == CantBeFiltered) || (mask & filter)))
  1517. {
  1518. if (grab && !SameClient(grab, client))
  1519. return -1; /* don't send, but notify caller */
  1520. type = pEvents->u.u.type;
  1521. if (type == MotionNotify)
  1522. {
  1523. if (mask & PointerMotionHintMask)
  1524. {
  1525. if (WID(inputInfo.pointer->valuator->motionHintWindow) ==
  1526. pEvents->u.keyButtonPointer.event)
  1527. {
  1528. #if defined(DEBUG) || defined(NX_DEBUG_INPUT)
  1529. #ifdef NX_DEBUG_INPUT
  1530. if (nxagentDebugInput == 1)
  1531. {
  1532. fprintf(stderr,"\nmotionHintWindow == keyButtonPointer.event\n");
  1533. }
  1534. #else
  1535. if (debug_events) ErrorF("\n");
  1536. fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n");
  1537. #endif
  1538. #endif
  1539. return 1; /* don't send, but pretend we did */
  1540. }
  1541. pEvents->u.u.detail = NotifyHint;
  1542. }
  1543. else
  1544. {
  1545. pEvents->u.u.detail = NotifyNormal;
  1546. }
  1547. }
  1548. #ifdef XINPUT
  1549. else
  1550. {
  1551. if ((type == DeviceMotionNotify) &&
  1552. MaybeSendDeviceMotionNotifyHint
  1553. ((deviceKeyButtonPointer*)pEvents, mask) != 0)
  1554. return 1;
  1555. }
  1556. #endif
  1557. type &= 0177;
  1558. if (type != KeymapNotify)
  1559. {
  1560. /* all extension events must have a sequence number */
  1561. for (i = 0; i < count; i++)
  1562. pEvents[i].u.u.sequenceNumber = client->sequence;
  1563. }
  1564. if (BitIsOn(criticalEvents, type))
  1565. {
  1566. #ifdef SMART_SCHEDULE
  1567. if (client->smart_priority < SMART_MAX_PRIORITY)
  1568. client->smart_priority++;
  1569. #endif
  1570. SetCriticalOutputPending();
  1571. }
  1572. WriteEventsToClient(client, count, pEvents);
  1573. #if defined(DEBUG) || defined(NX_DEBUG_INPUT)
  1574. #ifdef NX_DEBUG_INPUT
  1575. if (nxagentDebugInput == 1)
  1576. fprintf(stderr, " delivered\n");
  1577. #else
  1578. if (debug_events) ErrorF( " delivered\n");
  1579. #endif
  1580. #endif
  1581. return 1;
  1582. }
  1583. else
  1584. {
  1585. #if defined(DEBUG) || define

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