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