darwinEvents.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. /*
  2. * Darwin event queue and event handling
  3. *
  4. * Copyright 2007-2008 Apple Inc.
  5. * Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
  6. * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
  7. *
  8. * This file is based on mieq.c by Keith Packard,
  9. * which contains the following copyright:
  10. * Copyright 1990, 1998 The Open Group
  11. *
  12. *
  13. * Copyright (c) 2002-2012 Apple Inc. All rights reserved.
  14. *
  15. * Permission is hereby granted, free of charge, to any person
  16. * obtaining a copy of this software and associated documentation files
  17. * (the "Software"), to deal in the Software without restriction,
  18. * including without limitation the rights to use, copy, modify, merge,
  19. * publish, distribute, sublicense, and/or sell copies of the Software,
  20. * and to permit persons to whom the Software is furnished to do so,
  21. * subject to the following conditions:
  22. *
  23. * The above copyright notice and this permission notice shall be
  24. * included in all copies or substantial portions of the Software.
  25. *
  26. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  27. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  28. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  29. * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
  30. * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  31. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  32. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  33. * DEALINGS IN THE SOFTWARE.
  34. *
  35. * Except as contained in this notice, the name(s) of the above
  36. * copyright holders shall not be used in advertising or otherwise to
  37. * promote the sale, use or other dealings in this Software without
  38. * prior written authorization.
  39. */
  40. #include "sanitizedCarbon.h"
  41. #ifdef HAVE_DIX_CONFIG_H
  42. #include <dix-config.h>
  43. #endif
  44. #include <X11/X.h>
  45. #include <X11/Xmd.h>
  46. #include <X11/Xproto.h>
  47. #include "misc.h"
  48. #include "windowstr.h"
  49. #include "pixmapstr.h"
  50. #include "inputstr.h"
  51. #include "inpututils.h"
  52. #include "eventstr.h"
  53. #include "mi.h"
  54. #include "scrnintstr.h"
  55. #include "mipointer.h"
  56. #include "os.h"
  57. #include "exglobals.h"
  58. #include "darwin.h"
  59. #include "quartz.h"
  60. #include "quartzKeyboard.h"
  61. #include "quartzRandR.h"
  62. #include "darwinEvents.h"
  63. #include <sys/types.h>
  64. #include <sys/uio.h>
  65. #include <unistd.h>
  66. #include <pthread.h>
  67. #include <errno.h>
  68. #include <time.h>
  69. #include <IOKit/hidsystem/IOLLEvent.h>
  70. #include <X11/extensions/applewmconst.h>
  71. #include "applewmExt.h"
  72. /* FIXME: Abstract this better */
  73. extern Bool
  74. QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev);
  75. int darwin_all_modifier_flags = 0; // last known modifier state
  76. int darwin_all_modifier_mask = 0;
  77. int darwin_x11_modifier_mask = 0;
  78. #define FD_ADD_MAX 128
  79. static int fd_add[FD_ADD_MAX];
  80. int fd_add_count = 0;
  81. static pthread_mutex_t fd_add_lock = PTHREAD_MUTEX_INITIALIZER;
  82. static pthread_cond_t fd_add_ready_cond = PTHREAD_COND_INITIALIZER;
  83. static pthread_t fd_add_tid = NULL;
  84. static InternalEvent* darwinEvents = NULL;
  85. static pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER;
  86. static pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER;
  87. /*** Pthread Magics ***/
  88. static pthread_t
  89. create_thread(void *(*func)(void *), void *arg)
  90. {
  91. pthread_attr_t attr;
  92. pthread_t tid;
  93. pthread_attr_init(&attr);
  94. pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
  95. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  96. pthread_create(&tid, &attr, func, arg);
  97. pthread_attr_destroy(&attr);
  98. return tid;
  99. }
  100. void
  101. darwinEvents_lock(void);
  102. void
  103. darwinEvents_lock(void)
  104. {
  105. int err;
  106. if ((err = pthread_mutex_lock(&mieq_lock))) {
  107. ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n",
  108. __FILE__, __FUNCTION__, __LINE__, err);
  109. xorg_backtrace();
  110. }
  111. if (darwinEvents == NULL) {
  112. pthread_cond_wait(&mieq_ready_cond, &mieq_lock);
  113. }
  114. }
  115. void
  116. darwinEvents_unlock(void);
  117. void
  118. darwinEvents_unlock(void)
  119. {
  120. int err;
  121. if ((err = pthread_mutex_unlock(&mieq_lock))) {
  122. ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n",
  123. __FILE__, __FUNCTION__, __LINE__, err);
  124. xorg_backtrace();
  125. }
  126. }
  127. /*
  128. * DarwinPressModifierKey
  129. * Press or release the given modifier key (one of NX_MODIFIERKEY_* constants)
  130. */
  131. static void
  132. DarwinPressModifierKey(int pressed, int key)
  133. {
  134. int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
  135. if (keycode == 0) {
  136. ErrorF("DarwinPressModifierKey bad keycode: key=%d\n", key);
  137. return;
  138. }
  139. DarwinSendKeyboardEvents(pressed, keycode);
  140. }
  141. /*
  142. * DarwinUpdateModifiers
  143. * Send events to update the modifier state.
  144. */
  145. static int darwin_x11_modifier_mask_list[] = {
  146. #ifdef NX_DEVICELCMDKEYMASK
  147. NX_DEVICELCTLKEYMASK, NX_DEVICERCTLKEYMASK,
  148. NX_DEVICELSHIFTKEYMASK, NX_DEVICERSHIFTKEYMASK,
  149. NX_DEVICELCMDKEYMASK, NX_DEVICERCMDKEYMASK,
  150. NX_DEVICELALTKEYMASK, NX_DEVICERALTKEYMASK,
  151. #else
  152. NX_CONTROLMASK, NX_SHIFTMASK, NX_COMMANDMASK,
  153. NX_ALTERNATEMASK,
  154. #endif
  155. NX_ALPHASHIFTMASK,
  156. 0
  157. };
  158. static int darwin_all_modifier_mask_additions[] = { NX_SECONDARYFNMASK, };
  159. static void
  160. DarwinUpdateModifiers(int pressed, // KeyPress or KeyRelease
  161. int flags) // modifier flags that have changed
  162. {
  163. int *f;
  164. int key;
  165. /* Capslock is special. This mask is the state of capslock (on/off),
  166. * not the state of the button. Hopefully we can find a better solution.
  167. */
  168. if (NX_ALPHASHIFTMASK & flags) {
  169. DarwinPressModifierKey(KeyPress, NX_MODIFIERKEY_ALPHALOCK);
  170. DarwinPressModifierKey(KeyRelease, NX_MODIFIERKEY_ALPHALOCK);
  171. }
  172. for (f = darwin_x11_modifier_mask_list; *f; f++)
  173. if (*f & flags && *f != NX_ALPHASHIFTMASK) {
  174. key = DarwinModifierNXMaskToNXKey(*f);
  175. if (key == -1)
  176. ErrorF("DarwinUpdateModifiers: Unsupported NXMask: 0x%x\n",
  177. *f);
  178. else
  179. DarwinPressModifierKey(pressed, key);
  180. }
  181. }
  182. /* Generic handler for Xquartz-specifc events. When possible, these should
  183. be moved into their own individual functions and set as handlers using
  184. mieqSetHandler. */
  185. static void
  186. DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr dev)
  187. {
  188. XQuartzEvent *e = &(ie->xquartz_event);
  189. switch (e->subtype) {
  190. case kXquartzControllerNotify:
  191. DEBUG_LOG("kXquartzControllerNotify\n");
  192. AppleWMSendEvent(AppleWMControllerNotify,
  193. AppleWMControllerNotifyMask,
  194. e->data[0],
  195. e->data[1]);
  196. break;
  197. case kXquartzPasteboardNotify:
  198. DEBUG_LOG("kXquartzPasteboardNotify\n");
  199. AppleWMSendEvent(AppleWMPasteboardNotify,
  200. AppleWMPasteboardNotifyMask,
  201. e->data[0],
  202. e->data[1]);
  203. break;
  204. case kXquartzActivate:
  205. DEBUG_LOG("kXquartzActivate\n");
  206. QuartzShow();
  207. AppleWMSendEvent(AppleWMActivationNotify,
  208. AppleWMActivationNotifyMask,
  209. AppleWMIsActive, 0);
  210. break;
  211. case kXquartzDeactivate:
  212. DEBUG_LOG("kXquartzDeactivate\n");
  213. AppleWMSendEvent(AppleWMActivationNotify,
  214. AppleWMActivationNotifyMask,
  215. AppleWMIsInactive, 0);
  216. QuartzHide();
  217. break;
  218. case kXquartzReloadPreferences:
  219. DEBUG_LOG("kXquartzReloadPreferences\n");
  220. AppleWMSendEvent(AppleWMActivationNotify,
  221. AppleWMActivationNotifyMask,
  222. AppleWMReloadPreferences, 0);
  223. break;
  224. case kXquartzToggleFullscreen:
  225. DEBUG_LOG("kXquartzToggleFullscreen\n");
  226. if (XQuartzIsRootless)
  227. ErrorF(
  228. "Ignoring kXquartzToggleFullscreen because of rootless mode.");
  229. else
  230. QuartzRandRToggleFullscreen();
  231. break;
  232. case kXquartzSetRootless:
  233. DEBUG_LOG("kXquartzSetRootless\n");
  234. if (e->data[0]) {
  235. QuartzRandRSetFakeRootless();
  236. }
  237. else {
  238. QuartzRandRSetFakeFullscreen(FALSE);
  239. }
  240. break;
  241. case kXquartzSetRootClip:
  242. QuartzSetRootClip((Bool)e->data[0]);
  243. break;
  244. case kXquartzQuit:
  245. GiveUp(0);
  246. break;
  247. case kXquartzSpaceChanged:
  248. DEBUG_LOG("kXquartzSpaceChanged\n");
  249. QuartzSpaceChanged(e->data[0]);
  250. break;
  251. case kXquartzListenOnOpenFD:
  252. ErrorF("Calling ListenOnOpenFD() for new fd: %d\n", (int)e->data[0]);
  253. ListenOnOpenFD((int)e->data[0], 1);
  254. break;
  255. case kXquartzReloadKeymap:
  256. DarwinKeyboardReloadHandler();
  257. break;
  258. case kXquartzDisplayChanged:
  259. DEBUG_LOG("kXquartzDisplayChanged\n");
  260. QuartzUpdateScreens();
  261. /* Update our RandR info */
  262. QuartzRandRUpdateFakeModes(TRUE);
  263. break;
  264. default:
  265. if (!QuartzModeEventHandler(screenNum, e, dev))
  266. ErrorF("Unknown application defined event type %d.\n", e->subtype);
  267. }
  268. }
  269. void
  270. DarwinListenOnOpenFD(int fd)
  271. {
  272. ErrorF("DarwinListenOnOpenFD: %d\n", fd);
  273. pthread_mutex_lock(&fd_add_lock);
  274. if (fd_add_count < FD_ADD_MAX)
  275. fd_add[fd_add_count++] = fd;
  276. else
  277. ErrorF("FD Addition buffer at max. Dropping fd addition request.\n");
  278. pthread_cond_broadcast(&fd_add_ready_cond);
  279. pthread_mutex_unlock(&fd_add_lock);
  280. }
  281. static void *
  282. DarwinProcessFDAdditionQueue_thread(void *args)
  283. {
  284. /* TODO: Possibly adjust this to no longer be a race... maybe trigger this
  285. * once a client connects and claims to be the WM.
  286. *
  287. * From ajax:
  288. * There's already an internal callback chain for setting selection [in 1.5]
  289. * ownership. See the CallSelectionCallback at the bottom of
  290. * ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook
  291. * into it.
  292. */
  293. struct timespec sleep_for;
  294. struct timespec sleep_remaining;
  295. sleep_for.tv_sec = 3;
  296. sleep_for.tv_nsec = 0;
  297. ErrorF(
  298. "X11.app: DarwinProcessFDAdditionQueue_thread: Sleeping to allow xinitrc to catchup.\n");
  299. while (nanosleep(&sleep_for, &sleep_remaining) != 0) {
  300. sleep_for = sleep_remaining;
  301. }
  302. pthread_mutex_lock(&fd_add_lock);
  303. while (true) {
  304. while (fd_add_count) {
  305. DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1,
  306. fd_add[--fd_add_count]);
  307. }
  308. pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock);
  309. }
  310. return NULL;
  311. }
  312. Bool
  313. DarwinEQInit(void)
  314. {
  315. int *p;
  316. for (p = darwin_x11_modifier_mask_list, darwin_all_modifier_mask = 0; *p;
  317. p++) {
  318. darwin_x11_modifier_mask |= *p;
  319. }
  320. for (p = darwin_all_modifier_mask_additions,
  321. darwin_all_modifier_mask = darwin_x11_modifier_mask;
  322. *p; p++) {
  323. darwin_all_modifier_mask |= *p;
  324. }
  325. mieqInit();
  326. mieqSetHandler(ET_XQuartz, DarwinEventHandler);
  327. /* Note that this *could* cause a potential async issue, since we're checking
  328. * darwinEvents without holding the lock, but darwinEvents is only ever set
  329. * here, so I don't bother.
  330. */
  331. if (!darwinEvents) {
  332. darwinEvents = InitEventList(GetMaximumEventsNum());
  333. ;
  334. if (!darwinEvents)
  335. FatalError("Couldn't allocate event buffer\n");
  336. darwinEvents_lock();
  337. pthread_cond_broadcast(&mieq_ready_cond);
  338. darwinEvents_unlock();
  339. }
  340. if (!fd_add_tid)
  341. fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL);
  342. return TRUE;
  343. }
  344. void
  345. DarwinEQFini(void)
  346. {
  347. mieqFini();
  348. }
  349. /*
  350. * ProcessInputEvents
  351. * Read and process events from the event queue until it is empty.
  352. */
  353. void
  354. ProcessInputEvents(void)
  355. {
  356. char nullbyte;
  357. int x = sizeof(nullbyte);
  358. mieqProcessInputEvents();
  359. // Empty the signaling pipe
  360. while (x == sizeof(nullbyte)) {
  361. x = read(darwinEventReadFD, &nullbyte, sizeof(nullbyte));
  362. }
  363. }
  364. /* Sends a null byte down darwinEventWriteFD, which will cause the
  365. Dispatch() event loop to check out event queue */
  366. static void
  367. DarwinPokeEQ(void)
  368. {
  369. char nullbyte = 0;
  370. // <daniels> oh, i ... er ... christ.
  371. write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte));
  372. }
  373. void
  374. DarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev)
  375. {
  376. darwinEvents_lock();
  377. {
  378. int i;
  379. if (pDev->button) {
  380. for (i = 0; i < pDev->button->numButtons; i++) {
  381. if (BitIsOn(pDev->button->down, i)) {
  382. QueuePointerEvents(pDev, ButtonRelease, i,
  383. POINTER_ABSOLUTE,
  384. NULL);
  385. }
  386. }
  387. }
  388. if (pDev->key) {
  389. for (i = 0; i < NUM_KEYCODES; i++) {
  390. if (BitIsOn(pDev->key->down, i + MIN_KEYCODE)) {
  391. QueueKeyboardEvents(pDev, KeyRelease, i + MIN_KEYCODE,
  392. NULL);
  393. }
  394. }
  395. }
  396. DarwinPokeEQ();
  397. } darwinEvents_unlock();
  398. }
  399. void
  400. DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
  401. double pointer_x, double pointer_y,
  402. double pressure, double tilt_x,
  403. double tilt_y)
  404. {
  405. ScreenPtr screen;
  406. ValuatorMask valuators;
  407. if (!darwinEvents) {
  408. DEBUG_LOG("%s called before darwinEvents was initialized\n",
  409. __FUNCTION__);
  410. return;
  411. }
  412. screen = miPointerGetScreen(pDev);
  413. if (!screen) {
  414. DEBUG_LOG("%s called before screen was initialized\n",
  415. __FUNCTION__);
  416. return;
  417. }
  418. /* Fix offset between darwin and X screens */
  419. pointer_x -= darwinMainScreenX + screen->x;
  420. pointer_y -= darwinMainScreenY + screen->y;
  421. /* Adjust our pointer location to the [0,1] range */
  422. pointer_x = pointer_x / (double)screenInfo.width;
  423. pointer_y = pointer_y / (double)screenInfo.height;
  424. valuator_mask_zero(&valuators);
  425. valuator_mask_set_double(&valuators, 0, XQUARTZ_VALUATOR_LIMIT * pointer_x);
  426. valuator_mask_set_double(&valuators, 1, XQUARTZ_VALUATOR_LIMIT * pointer_y);
  427. valuator_mask_set_double(&valuators, 2, XQUARTZ_VALUATOR_LIMIT * pressure);
  428. valuator_mask_set_double(&valuators, 3, XQUARTZ_VALUATOR_LIMIT * tilt_x);
  429. valuator_mask_set_double(&valuators, 4, XQUARTZ_VALUATOR_LIMIT * tilt_y);
  430. darwinEvents_lock();
  431. {
  432. if (ev_type == ProximityIn || ev_type == ProximityOut) {
  433. QueueProximityEvents(pDev, ev_type, &valuators);
  434. } else {
  435. QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE,
  436. &valuators);
  437. }
  438. DarwinPokeEQ();
  439. } darwinEvents_unlock();
  440. }
  441. void
  442. DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
  443. double pointer_x, double pointer_y,
  444. double pointer_dx, double pointer_dy)
  445. {
  446. static int darwinFakeMouseButtonDown = 0;
  447. ScreenPtr screen;
  448. ValuatorMask valuators;
  449. if (!darwinEvents) {
  450. DEBUG_LOG("%s called before darwinEvents was initialized\n",
  451. __FUNCTION__);
  452. return;
  453. }
  454. screen = miPointerGetScreen(pDev);
  455. if (!screen) {
  456. DEBUG_LOG("%s called before screen was initialized\n",
  457. __FUNCTION__);
  458. return;
  459. }
  460. /* Handle fake click */
  461. if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) {
  462. if (darwinFakeMouseButtonDown != 0) {
  463. /* We're currently "down" with another button, so release it first */
  464. DarwinSendPointerEvents(pDev, ButtonRelease,
  465. darwinFakeMouseButtonDown,
  466. pointer_x, pointer_y, 0.0, 0.0);
  467. darwinFakeMouseButtonDown = 0;
  468. }
  469. if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
  470. ev_button = 2;
  471. darwinFakeMouseButtonDown = 2;
  472. DarwinUpdateModKeys(
  473. darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
  474. }
  475. else if (darwin_all_modifier_flags & darwinFakeMouse3Mask) {
  476. ev_button = 3;
  477. darwinFakeMouseButtonDown = 3;
  478. DarwinUpdateModKeys(
  479. darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
  480. }
  481. }
  482. if (ev_type == ButtonRelease && ev_button == 1) {
  483. if (darwinFakeMouseButtonDown) {
  484. ev_button = darwinFakeMouseButtonDown;
  485. }
  486. if (darwinFakeMouseButtonDown == 2) {
  487. DarwinUpdateModKeys(
  488. darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
  489. }
  490. else if (darwinFakeMouseButtonDown == 3) {
  491. DarwinUpdateModKeys(
  492. darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
  493. }
  494. darwinFakeMouseButtonDown = 0;
  495. }
  496. /* Fix offset between darwin and X screens */
  497. pointer_x -= darwinMainScreenX + screen->x;
  498. pointer_y -= darwinMainScreenY + screen->y;
  499. valuator_mask_zero(&valuators);
  500. valuator_mask_set_double(&valuators, 0, pointer_x);
  501. valuator_mask_set_double(&valuators, 1, pointer_y);
  502. if (ev_type == MotionNotify) {
  503. if (pointer_dx != 0.0)
  504. valuator_mask_set_double(&valuators, 2, pointer_dx);
  505. if (pointer_dy != 0.0)
  506. valuator_mask_set_double(&valuators, 3, pointer_dy);
  507. }
  508. darwinEvents_lock();
  509. {
  510. QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE,
  511. &valuators);
  512. DarwinPokeEQ();
  513. } darwinEvents_unlock();
  514. }
  515. void
  516. DarwinSendKeyboardEvents(int ev_type, int keycode)
  517. {
  518. if (!darwinEvents) {
  519. DEBUG_LOG(
  520. "DarwinSendKeyboardEvents called before darwinEvents was initialized\n");
  521. return;
  522. }
  523. darwinEvents_lock();
  524. {
  525. QueueKeyboardEvents(darwinKeyboard, ev_type, keycode + MIN_KEYCODE,
  526. NULL);
  527. DarwinPokeEQ();
  528. } darwinEvents_unlock();
  529. }
  530. /* Send the appropriate number of button clicks to emulate scroll wheel */
  531. void
  532. DarwinSendScrollEvents(double scroll_x, double scroll_y) {
  533. ScreenPtr screen;
  534. ValuatorMask valuators;
  535. if (!darwinEvents) {
  536. DEBUG_LOG(
  537. "DarwinSendScrollEvents called before darwinEvents was initialized\n");
  538. return;
  539. }
  540. screen = miPointerGetScreen(darwinPointer);
  541. if (!screen) {
  542. DEBUG_LOG(
  543. "DarwinSendScrollEvents called before screen was initialized\n");
  544. return;
  545. }
  546. valuator_mask_zero(&valuators);
  547. valuator_mask_set_double(&valuators, 4, scroll_y);
  548. valuator_mask_set_double(&valuators, 5, scroll_x);
  549. darwinEvents_lock();
  550. {
  551. QueuePointerEvents(darwinPointer, MotionNotify, 0,
  552. POINTER_RELATIVE, &valuators);
  553. DarwinPokeEQ();
  554. } darwinEvents_unlock();
  555. }
  556. /* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to
  557. reflect changing modifier flags (alt, control, meta, etc) */
  558. void
  559. DarwinUpdateModKeys(int flags)
  560. {
  561. DarwinUpdateModifiers(
  562. KeyRelease, darwin_all_modifier_flags & ~flags &
  563. darwin_x11_modifier_mask);
  564. DarwinUpdateModifiers(
  565. KeyPress, ~darwin_all_modifier_flags & flags &
  566. darwin_x11_modifier_mask);
  567. darwin_all_modifier_flags = flags;
  568. }
  569. /*
  570. * DarwinSendDDXEvent
  571. * Send the X server thread a message by placing it on the event queue.
  572. */
  573. void
  574. DarwinSendDDXEvent(int type, int argc, ...)
  575. {
  576. XQuartzEvent e;
  577. int i;
  578. va_list args;
  579. memset(&e, 0, sizeof(e));
  580. e.header = ET_Internal;
  581. e.type = ET_XQuartz;
  582. e.length = sizeof(e);
  583. e.time = GetTimeInMillis();
  584. e.subtype = type;
  585. if (argc > 0 && argc < XQUARTZ_EVENT_MAXARGS) {
  586. va_start(args, argc);
  587. for (i = 0; i < argc; i++)
  588. e.data[i] = (uint32_t)va_arg(args, uint32_t);
  589. va_end(args);
  590. }
  591. darwinEvents_lock();
  592. {
  593. mieqEnqueue(NULL, (InternalEvent *)&e);
  594. DarwinPokeEQ();
  595. } darwinEvents_unlock();
  596. }