mipointer.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. * mipointer.c
  3. */
  4. /*
  5. Copyright 1989, 1998 The Open Group
  6. Permission to use, copy, modify, distribute, and sell this software and its
  7. documentation for any purpose is hereby granted without fee, provided that
  8. the above copyright notice appear in all copies and that both that
  9. copyright notice and this permission notice appear in supporting
  10. documentation.
  11. The above copyright notice and this permission notice shall be included in
  12. all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  17. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  18. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. Except as contained in this notice, the name of The Open Group shall not be
  20. used in advertising or otherwise to promote the sale, use or other dealings
  21. in this Software without prior written authorization from The Open Group.
  22. */
  23. #ifdef HAVE_DIX_CONFIG_H
  24. #include <dix-config.h>
  25. #endif
  26. # include <X11/X.h>
  27. # include <X11/Xmd.h>
  28. # include <X11/Xproto.h>
  29. # include "misc.h"
  30. # include "windowstr.h"
  31. # include "pixmapstr.h"
  32. # include "mi.h"
  33. # include "scrnintstr.h"
  34. # include "mipointrst.h"
  35. # include "cursorstr.h"
  36. # include "dixstruct.h"
  37. _X_EXPORT int miPointerScreenIndex;
  38. static unsigned long miPointerGeneration = 0;
  39. #define GetScreenPrivate(s) ((miPointerScreenPtr) ((s)->devPrivates[miPointerScreenIndex].ptr))
  40. #define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
  41. /*
  42. * until more than one pointer device exists.
  43. */
  44. static miPointerRec miPointer;
  45. static Bool miPointerRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
  46. static Bool miPointerUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
  47. static Bool miPointerDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
  48. static void miPointerConstrainCursor(ScreenPtr pScreen, BoxPtr pBox);
  49. static void miPointerPointerNonInterestBox(ScreenPtr pScreen, BoxPtr pBox);
  50. static void miPointerCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
  51. BoxPtr pHotBox, BoxPtr pTopLeftBox);
  52. static Bool miPointerSetCursorPosition(ScreenPtr pScreen, int x, int y,
  53. Bool generateEvent);
  54. static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
  55. static void miPointerMove(ScreenPtr pScreen, int x, int y, unsigned long time);
  56. _X_EXPORT Bool
  57. miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
  58. ScreenPtr pScreen;
  59. const miPointerSpriteFuncRec * spriteFuncs;
  60. miPointerScreenFuncPtr screenFuncs;
  61. Bool waitForUpdate;
  62. {
  63. miPointerScreenPtr pScreenPriv;
  64. if (miPointerGeneration != serverGeneration)
  65. {
  66. miPointerScreenIndex = AllocateScreenPrivateIndex();
  67. if (miPointerScreenIndex < 0)
  68. return FALSE;
  69. miPointerGeneration = serverGeneration;
  70. }
  71. pScreenPriv = malloc(sizeof (miPointerScreenRec));
  72. if (!pScreenPriv)
  73. return FALSE;
  74. pScreenPriv->spriteFuncs = spriteFuncs;
  75. pScreenPriv->screenFuncs = screenFuncs;
  76. /*
  77. * check for uninitialized methods
  78. */
  79. if (!screenFuncs->EnqueueEvent)
  80. screenFuncs->EnqueueEvent = mieqEnqueue;
  81. if (!screenFuncs->NewEventScreen)
  82. screenFuncs->NewEventScreen = mieqSwitchScreen;
  83. pScreenPriv->waitForUpdate = waitForUpdate;
  84. pScreenPriv->showTransparent = FALSE;
  85. pScreenPriv->CloseScreen = pScreen->CloseScreen;
  86. pScreen->CloseScreen = miPointerCloseScreen;
  87. pScreen->devPrivates[miPointerScreenIndex].ptr = (pointer) pScreenPriv;
  88. /*
  89. * set up screen cursor method table
  90. */
  91. pScreen->ConstrainCursor = miPointerConstrainCursor;
  92. pScreen->CursorLimits = miPointerCursorLimits;
  93. pScreen->DisplayCursor = miPointerDisplayCursor;
  94. pScreen->RealizeCursor = miPointerRealizeCursor;
  95. pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
  96. pScreen->SetCursorPosition = miPointerSetCursorPosition;
  97. pScreen->RecolorCursor = miRecolorCursor;
  98. pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox;
  99. /*
  100. * set up the pointer object
  101. */
  102. miPointer.pScreen = NULL;
  103. miPointer.pSpriteScreen = NULL;
  104. miPointer.pCursor = NULL;
  105. miPointer.pSpriteCursor = NULL;
  106. miPointer.limits.x1 = 0;
  107. miPointer.limits.x2 = 32767;
  108. miPointer.limits.y1 = 0;
  109. miPointer.limits.y2 = 32767;
  110. miPointer.confined = FALSE;
  111. miPointer.x = 0;
  112. miPointer.y = 0;
  113. miPointer.history_start = miPointer.history_end = 0;
  114. return TRUE;
  115. }
  116. static Bool
  117. miPointerCloseScreen (index, pScreen)
  118. int index;
  119. ScreenPtr pScreen;
  120. {
  121. SetupScreen(pScreen);
  122. if (pScreen == miPointer.pScreen)
  123. miPointer.pScreen = 0;
  124. if (pScreen == miPointer.pSpriteScreen)
  125. miPointer.pSpriteScreen = 0;
  126. pScreen->CloseScreen = pScreenPriv->CloseScreen;
  127. free((pointer) pScreenPriv);
  128. return (*pScreen->CloseScreen) (index, pScreen);
  129. }
  130. /*
  131. * DIX/DDX interface routines
  132. */
  133. static Bool
  134. miPointerRealizeCursor (pScreen, pCursor)
  135. ScreenPtr pScreen;
  136. CursorPtr pCursor;
  137. {
  138. SetupScreen(pScreen);
  139. return (*pScreenPriv->spriteFuncs->RealizeCursor) (pScreen, pCursor);
  140. }
  141. static Bool
  142. miPointerUnrealizeCursor (pScreen, pCursor)
  143. ScreenPtr pScreen;
  144. CursorPtr pCursor;
  145. {
  146. SetupScreen(pScreen);
  147. return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pScreen, pCursor);
  148. }
  149. static Bool
  150. miPointerDisplayCursor (pScreen, pCursor)
  151. ScreenPtr pScreen;
  152. CursorPtr pCursor;
  153. {
  154. miPointer.pCursor = pCursor;
  155. miPointer.pScreen = pScreen;
  156. miPointerUpdate ();
  157. return TRUE;
  158. }
  159. static void
  160. miPointerConstrainCursor (pScreen, pBox)
  161. ScreenPtr pScreen;
  162. BoxPtr pBox;
  163. {
  164. miPointer.limits = *pBox;
  165. miPointer.confined = PointerConfinedToScreen();
  166. }
  167. /*ARGSUSED*/
  168. static void
  169. miPointerPointerNonInterestBox (pScreen, pBox)
  170. ScreenPtr pScreen;
  171. BoxPtr pBox;
  172. {
  173. /* until DIX uses this, this will remain a stub */
  174. }
  175. /*ARGSUSED*/
  176. static void
  177. miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox)
  178. ScreenPtr pScreen;
  179. CursorPtr pCursor;
  180. BoxPtr pHotBox;
  181. BoxPtr pTopLeftBox;
  182. {
  183. *pTopLeftBox = *pHotBox;
  184. }
  185. static Bool GenerateEvent;
  186. static Bool
  187. miPointerSetCursorPosition(pScreen, x, y, generateEvent)
  188. ScreenPtr pScreen;
  189. int x, y;
  190. Bool generateEvent;
  191. {
  192. SetupScreen (pScreen);
  193. GenerateEvent = generateEvent;
  194. /* device dependent - must pend signal and call miPointerWarpCursor */
  195. (*pScreenPriv->screenFuncs->WarpCursor) (pScreen, x, y);
  196. if (!generateEvent)
  197. miPointerUpdate();
  198. return TRUE;
  199. }
  200. /* Once signals are ignored, the WarpCursor function can call this */
  201. _X_EXPORT void
  202. miPointerWarpCursor (pScreen, x, y)
  203. ScreenPtr pScreen;
  204. int x, y;
  205. {
  206. SetupScreen (pScreen);
  207. if (miPointer.pScreen != pScreen)
  208. (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
  209. if (GenerateEvent)
  210. {
  211. miPointerMove (pScreen, x, y, GetTimeInMillis());
  212. }
  213. else
  214. {
  215. /* everything from miPointerMove except the event and history */
  216. if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
  217. {
  218. miPointer.devx = x;
  219. miPointer.devy = y;
  220. if(!miPointer.pCursor->bits->emptyMask)
  221. (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
  222. }
  223. miPointer.x = x;
  224. miPointer.y = y;
  225. miPointer.pScreen = pScreen;
  226. }
  227. }
  228. /*
  229. * Pointer/CursorDisplay interface routines
  230. */
  231. _X_EXPORT int
  232. miPointerGetMotionBufferSize ()
  233. {
  234. return MOTION_SIZE;
  235. }
  236. _X_EXPORT int
  237. miPointerGetMotionEvents (pPtr, coords, start, stop, pScreen)
  238. DeviceIntPtr pPtr;
  239. xTimecoord *coords;
  240. unsigned long start, stop;
  241. ScreenPtr pScreen;
  242. {
  243. int i;
  244. int count = 0;
  245. miHistoryPtr h;
  246. for (i = miPointer.history_start; i != miPointer.history_end;)
  247. {
  248. h = &miPointer.history[i];
  249. if (h->event.time >= stop)
  250. break;
  251. if (h->event.time >= start)
  252. {
  253. *coords++ = h->event;
  254. count++;
  255. }
  256. if (++i == MOTION_SIZE) i = 0;
  257. }
  258. return count;
  259. }
  260. /*
  261. * miPointerUpdate
  262. *
  263. * Syncronize the sprite with the cursor - called from ProcessInputEvents
  264. */
  265. void
  266. miPointerUpdate ()
  267. {
  268. ScreenPtr pScreen;
  269. miPointerScreenPtr pScreenPriv;
  270. CursorPtr pCursor;
  271. int x, y, devx, devy;
  272. pScreen = miPointer.pScreen;
  273. x = miPointer.x;
  274. y = miPointer.y;
  275. devx = miPointer.devx;
  276. devy = miPointer.devy;
  277. if (!pScreen)
  278. return;
  279. pScreenPriv = GetScreenPrivate (pScreen);
  280. /*
  281. * if the cursor has switched screens, disable the sprite
  282. * on the old screen
  283. */
  284. if (pScreen != miPointer.pSpriteScreen)
  285. {
  286. if (miPointer.pSpriteScreen)
  287. {
  288. miPointerScreenPtr pOldPriv;
  289. pOldPriv = GetScreenPrivate (miPointer.pSpriteScreen);
  290. if (miPointer.pCursor)
  291. {
  292. (*pOldPriv->spriteFuncs->SetCursor)
  293. (miPointer.pSpriteScreen, NullCursor, 0, 0);
  294. }
  295. (*pOldPriv->screenFuncs->CrossScreen) (miPointer.pSpriteScreen, FALSE);
  296. }
  297. (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
  298. (*pScreenPriv->spriteFuncs->SetCursor)
  299. (pScreen, miPointer.pCursor, x, y);
  300. miPointer.devx = x;
  301. miPointer.devy = y;
  302. miPointer.pSpriteCursor = miPointer.pCursor;
  303. miPointer.pSpriteScreen = pScreen;
  304. }
  305. /*
  306. * if the cursor has changed, display the new one
  307. */
  308. else if (miPointer.pCursor != miPointer.pSpriteCursor)
  309. {
  310. pCursor = miPointer.pCursor;
  311. if (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)
  312. pCursor = NullCursor;
  313. (*pScreenPriv->spriteFuncs->SetCursor) (pScreen, pCursor, x, y);
  314. miPointer.devx = x;
  315. miPointer.devy = y;
  316. miPointer.pSpriteCursor = miPointer.pCursor;
  317. }
  318. else if (x != devx || y != devy)
  319. {
  320. miPointer.devx = x;
  321. miPointer.devy = y;
  322. if(!miPointer.pCursor->bits->emptyMask)
  323. (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
  324. }
  325. }
  326. /*
  327. * miPointerDeltaCursor. The pointer has moved dx,dy from it's previous
  328. * position.
  329. */
  330. void
  331. miPointerDeltaCursor (dx, dy, time)
  332. int dx, dy;
  333. unsigned long time;
  334. {
  335. miPointerAbsoluteCursor (miPointer.x + dx, miPointer.y + dy, time);
  336. }
  337. void
  338. miPointerSetNewScreen(int screen_no, int x, int y)
  339. {
  340. miPointerScreenPtr pScreenPriv;
  341. ScreenPtr pScreen;
  342. pScreen = screenInfo.screens[screen_no];
  343. pScreenPriv = GetScreenPrivate (pScreen);
  344. (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
  345. NewCurrentScreen (pScreen, x, y);
  346. miPointer.limits.x2 = pScreen->width;
  347. miPointer.limits.y2 = pScreen->height;
  348. }
  349. _X_EXPORT ScreenPtr
  350. miPointerCurrentScreen ()
  351. {
  352. return (miPointer.pScreen);
  353. }
  354. /*
  355. * miPointerAbsoluteCursor. The pointer has moved to x,y
  356. */
  357. _X_EXPORT void
  358. miPointerAbsoluteCursor (x, y, time)
  359. int x, y;
  360. unsigned long time;
  361. {
  362. miPointerScreenPtr pScreenPriv;
  363. ScreenPtr pScreen;
  364. ScreenPtr newScreen;
  365. pScreen = miPointer.pScreen;
  366. if (!pScreen)
  367. return; /* called before ready */
  368. if (x < 0 || x >= pScreen->width || y < 0 || y >= pScreen->height)
  369. {
  370. pScreenPriv = GetScreenPrivate (pScreen);
  371. if (!miPointer.confined)
  372. {
  373. newScreen = pScreen;
  374. (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, &x, &y);
  375. if (newScreen != pScreen)
  376. {
  377. pScreen = newScreen;
  378. (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
  379. /* Smash the confine to the new screen */
  380. miPointer.limits.x2 = pScreen->width;
  381. miPointer.limits.y2 = pScreen->height;
  382. }
  383. }
  384. }
  385. /*
  386. * constrain the hot-spot to the current
  387. * limits
  388. */
  389. if (x < miPointer.limits.x1)
  390. x = miPointer.limits.x1;
  391. if (x >= miPointer.limits.x2)
  392. x = miPointer.limits.x2 - 1;
  393. if (y < miPointer.limits.y1)
  394. y = miPointer.limits.y1;
  395. if (y >= miPointer.limits.y2)
  396. y = miPointer.limits.y2 - 1;
  397. if (miPointer.x == x && miPointer.y == y && miPointer.pScreen == pScreen)
  398. return;
  399. miPointerMove (pScreen, x, y, time);
  400. }
  401. _X_EXPORT void
  402. miPointerPosition (x, y)
  403. int *x, *y;
  404. {
  405. *x = miPointer.x;
  406. *y = miPointer.y;
  407. }
  408. /*
  409. * miPointerMove. The pointer has moved to x,y on current screen
  410. */
  411. static void
  412. miPointerMove (pScreen, x, y, time)
  413. ScreenPtr pScreen;
  414. int x, y;
  415. unsigned long time;
  416. {
  417. SetupScreen(pScreen);
  418. xEvent xE;
  419. miHistoryPtr history;
  420. int prev, end, start;
  421. if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
  422. {
  423. miPointer.devx = x;
  424. miPointer.devy = y;
  425. if(!miPointer.pCursor->bits->emptyMask)
  426. (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
  427. }
  428. miPointer.x = x;
  429. miPointer.y = y;
  430. miPointer.pScreen = pScreen;
  431. xE.u.u.type = MotionNotify;
  432. xE.u.keyButtonPointer.rootX = x;
  433. xE.u.keyButtonPointer.rootY = y;
  434. xE.u.keyButtonPointer.time = time;
  435. (*pScreenPriv->screenFuncs->EnqueueEvent) (&xE);
  436. end = miPointer.history_end;
  437. start = miPointer.history_start;
  438. prev = end - 1;
  439. if (end == 0)
  440. prev = MOTION_SIZE - 1;
  441. history = &miPointer.history[prev];
  442. if (end == start || history->event.time != time)
  443. {
  444. history = &miPointer.history[end];
  445. if (++end == MOTION_SIZE)
  446. end = 0;
  447. if (end == start)
  448. {
  449. start = end + 1;
  450. if (start == MOTION_SIZE)
  451. start = 0;
  452. miPointer.history_start = start;
  453. }
  454. miPointer.history_end = end;
  455. }
  456. history->event.x = x;
  457. history->event.y = y;
  458. history->event.time = time;
  459. history->pScreen = pScreen;
  460. }
  461. void
  462. miRegisterPointerDevice (pScreen, pDevice)
  463. ScreenPtr pScreen;
  464. DeviceIntPtr pDevice;
  465. {
  466. miPointer.pPointer = (DevicePtr)pDevice;
  467. }