1706f2543Smrg/*
2706f2543SmrgDarwin event queue and event handling
3706f2543Smrg
4706f2543SmrgCopyright 2007-2008 Apple Inc.
5706f2543SmrgCopyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
6706f2543SmrgCopyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
7706f2543Smrg
8706f2543SmrgThis file is based on mieq.c by Keith Packard,
9706f2543Smrgwhich contains the following copyright:
10706f2543SmrgCopyright 1990, 1998  The Open Group
11706f2543Smrg
12706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
13706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
14706f2543Smrgthe above copyright notice appear in all copies and that both that
15706f2543Smrgcopyright notice and this permission notice appear in supporting
16706f2543Smrgdocumentation.
17706f2543Smrg
18706f2543SmrgThe above copyright notice and this permission notice shall be included in
19706f2543Smrgall copies or substantial portions of the Software.
20706f2543Smrg
21706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27706f2543Smrg
28706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
29706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
30706f2543Smrgin this Software without prior written authorization from The Open Group.
31706f2543Smrg */
32706f2543Smrg
33706f2543Smrg#include "sanitizedCarbon.h"
34706f2543Smrg
35706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
36706f2543Smrg#include <dix-config.h>
37706f2543Smrg#endif
38706f2543Smrg
39706f2543Smrg#include   <X11/X.h>
40706f2543Smrg#include   <X11/Xmd.h>
41706f2543Smrg#include   <X11/Xproto.h>
42706f2543Smrg#include   "misc.h"
43706f2543Smrg#include   "windowstr.h"
44706f2543Smrg#include   "pixmapstr.h"
45706f2543Smrg#include   "inputstr.h"
46706f2543Smrg#include   "inpututils.h"
47706f2543Smrg#include   "eventstr.h"
48706f2543Smrg#include   "mi.h"
49706f2543Smrg#include   "scrnintstr.h"
50706f2543Smrg#include   "mipointer.h"
51706f2543Smrg#include   "os.h"
52706f2543Smrg
53706f2543Smrg#include "darwin.h"
54706f2543Smrg#include "quartz.h"
55706f2543Smrg#include "quartzKeyboard.h"
56706f2543Smrg#include "quartzRandR.h"
57706f2543Smrg#include "darwinEvents.h"
58706f2543Smrg
59706f2543Smrg#include <sys/types.h>
60706f2543Smrg#include <sys/uio.h>
61706f2543Smrg#include <unistd.h>
62706f2543Smrg#include <pthread.h>
63706f2543Smrg#include <errno.h>
64706f2543Smrg#include <time.h>
65706f2543Smrg
66706f2543Smrg#include <IOKit/hidsystem/IOLLEvent.h>
67706f2543Smrg
68706f2543Smrg/* Fake button press/release for scroll wheel move. */
69706f2543Smrg#define SCROLLWHEELUPFAKE    4
70706f2543Smrg#define SCROLLWHEELDOWNFAKE  5
71706f2543Smrg#define SCROLLWHEELLEFTFAKE  6
72706f2543Smrg#define SCROLLWHEELRIGHTFAKE 7
73706f2543Smrg
74706f2543Smrg#include <X11/extensions/applewmconst.h>
75706f2543Smrg#include "applewmExt.h"
76706f2543Smrg
77706f2543Smrg/* FIXME: Abstract this better */
78706f2543Smrgextern Bool QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev);
79706f2543Smrg
80706f2543Smrgint darwin_all_modifier_flags = 0;  // last known modifier state
81706f2543Smrgint darwin_all_modifier_mask = 0;
82706f2543Smrgint darwin_x11_modifier_mask = 0;
83706f2543Smrg
84706f2543Smrg#define FD_ADD_MAX 128
85706f2543Smrgstatic int fd_add[FD_ADD_MAX];
86706f2543Smrgint fd_add_count = 0;
87706f2543Smrgstatic pthread_mutex_t fd_add_lock = PTHREAD_MUTEX_INITIALIZER;
88706f2543Smrgstatic pthread_cond_t fd_add_ready_cond = PTHREAD_COND_INITIALIZER;
89706f2543Smrgstatic pthread_t fd_add_tid = NULL;
90706f2543Smrg
91706f2543Smrgstatic EventListPtr darwinEvents = NULL;
92706f2543Smrg
93706f2543Smrgstatic pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER;
94706f2543Smrgstatic pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER;
95706f2543Smrg
96706f2543Smrg/*** Pthread Magics ***/
97706f2543Smrgstatic pthread_t create_thread(void *(*func)(void *), void *arg) {
98706f2543Smrg    pthread_attr_t attr;
99706f2543Smrg    pthread_t tid;
100706f2543Smrg
101706f2543Smrg    pthread_attr_init (&attr);
102706f2543Smrg    pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
103706f2543Smrg    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
104706f2543Smrg    pthread_create (&tid, &attr, func, arg);
105706f2543Smrg    pthread_attr_destroy (&attr);
106706f2543Smrg
107706f2543Smrg    return tid;
108706f2543Smrg}
109706f2543Smrg
110706f2543Smrgvoid darwinEvents_lock(void);
111706f2543Smrgvoid darwinEvents_lock(void) {
112706f2543Smrg    int err;
113706f2543Smrg    if((err = pthread_mutex_lock(&mieq_lock))) {
114706f2543Smrg        ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n",
115706f2543Smrg               __FILE__, __FUNCTION__, __LINE__, err);
116706f2543Smrg        spewCallStack();
117706f2543Smrg    }
118706f2543Smrg    if(darwinEvents == NULL) {
119706f2543Smrg        pthread_cond_wait(&mieq_ready_cond, &mieq_lock);
120706f2543Smrg    }
121706f2543Smrg}
122706f2543Smrg
123706f2543Smrgvoid darwinEvents_unlock(void);
124706f2543Smrgvoid darwinEvents_unlock(void) {
125706f2543Smrg    int err;
126706f2543Smrg    if((err = pthread_mutex_unlock(&mieq_lock))) {
127706f2543Smrg        ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n",
128706f2543Smrg               __FILE__, __FUNCTION__, __LINE__, err);
129706f2543Smrg        spewCallStack();
130706f2543Smrg    }
131706f2543Smrg}
132706f2543Smrg
133706f2543Smrg/*
134706f2543Smrg * DarwinPressModifierKey
135706f2543Smrg * Press or release the given modifier key (one of NX_MODIFIERKEY_* constants)
136706f2543Smrg */
137706f2543Smrgstatic void DarwinPressModifierKey(int pressed, int key) {
138706f2543Smrg    int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
139706f2543Smrg
140706f2543Smrg    if (keycode == 0) {
141706f2543Smrg        ErrorF("DarwinPressModifierKey bad keycode: key=%d\n", key);
142706f2543Smrg        return;
143706f2543Smrg    }
144706f2543Smrg
145706f2543Smrg    DarwinSendKeyboardEvents(pressed, keycode);
146706f2543Smrg}
147706f2543Smrg
148706f2543Smrg/*
149706f2543Smrg * DarwinUpdateModifiers
150706f2543Smrg *  Send events to update the modifier state.
151706f2543Smrg */
152706f2543Smrg
153706f2543Smrgstatic int darwin_x11_modifier_mask_list[] = {
154706f2543Smrg#ifdef NX_DEVICELCMDKEYMASK
155706f2543Smrg    NX_DEVICELCTLKEYMASK, NX_DEVICERCTLKEYMASK,
156706f2543Smrg    NX_DEVICELSHIFTKEYMASK, NX_DEVICERSHIFTKEYMASK,
157706f2543Smrg    NX_DEVICELCMDKEYMASK, NX_DEVICERCMDKEYMASK,
158706f2543Smrg    NX_DEVICELALTKEYMASK, NX_DEVICERALTKEYMASK,
159706f2543Smrg#else
160706f2543Smrg    NX_CONTROLMASK, NX_SHIFTMASK, NX_COMMANDMASK, NX_ALTERNATEMASK,
161706f2543Smrg#endif
162706f2543Smrg    NX_ALPHASHIFTMASK,
163706f2543Smrg    0
164706f2543Smrg};
165706f2543Smrg
166706f2543Smrgstatic int darwin_all_modifier_mask_additions[] = { NX_SECONDARYFNMASK, };
167706f2543Smrg
168706f2543Smrgstatic void DarwinUpdateModifiers(
169706f2543Smrg    int pressed,        // KeyPress or KeyRelease
170706f2543Smrg    int flags )         // modifier flags that have changed
171706f2543Smrg{
172706f2543Smrg    int *f;
173706f2543Smrg    int key;
174706f2543Smrg
175706f2543Smrg    /* Capslock is special.  This mask is the state of capslock (on/off),
176706f2543Smrg     * not the state of the button.  Hopefully we can find a better solution.
177706f2543Smrg     */
178706f2543Smrg    if(NX_ALPHASHIFTMASK & flags) {
179706f2543Smrg        DarwinPressModifierKey(KeyPress, NX_MODIFIERKEY_ALPHALOCK);
180706f2543Smrg        DarwinPressModifierKey(KeyRelease, NX_MODIFIERKEY_ALPHALOCK);
181706f2543Smrg    }
182706f2543Smrg
183706f2543Smrg    for(f=darwin_x11_modifier_mask_list; *f; f++)
184706f2543Smrg        if(*f & flags && *f != NX_ALPHASHIFTMASK) {
185706f2543Smrg            key = DarwinModifierNXMaskToNXKey(*f);
186706f2543Smrg            if(key == -1)
187706f2543Smrg                ErrorF("DarwinUpdateModifiers: Unsupported NXMask: 0x%x\n", *f);
188706f2543Smrg            else
189706f2543Smrg                DarwinPressModifierKey(pressed, key);
190706f2543Smrg        }
191706f2543Smrg}
192706f2543Smrg
193706f2543Smrg/* Generic handler for Xquartz-specifc events.  When possible, these should
194706f2543Smrg   be moved into their own individual functions and set as handlers using
195706f2543Smrg   mieqSetHandler. */
196706f2543Smrg
197706f2543Smrgstatic void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr dev) {
198706f2543Smrg    XQuartzEvent *e = &(ie->xquartz_event);
199706f2543Smrg
200706f2543Smrg    TA_SERVER();
201706f2543Smrg
202706f2543Smrg    switch(e->subtype) {
203706f2543Smrg        case kXquartzControllerNotify:
204706f2543Smrg            DEBUG_LOG("kXquartzControllerNotify\n");
205706f2543Smrg            AppleWMSendEvent(AppleWMControllerNotify,
206706f2543Smrg                             AppleWMControllerNotifyMask,
207706f2543Smrg                             e->data[0],
208706f2543Smrg                             e->data[1]);
209706f2543Smrg            break;
210706f2543Smrg
211706f2543Smrg        case kXquartzPasteboardNotify:
212706f2543Smrg            DEBUG_LOG("kXquartzPasteboardNotify\n");
213706f2543Smrg            AppleWMSendEvent(AppleWMPasteboardNotify,
214706f2543Smrg                             AppleWMPasteboardNotifyMask,
215706f2543Smrg                             e->data[0],
216706f2543Smrg                             e->data[1]);
217706f2543Smrg            break;
218706f2543Smrg
219706f2543Smrg        case kXquartzActivate:
220706f2543Smrg            DEBUG_LOG("kXquartzActivate\n");
221706f2543Smrg            QuartzShow();
222706f2543Smrg            AppleWMSendEvent(AppleWMActivationNotify,
223706f2543Smrg                             AppleWMActivationNotifyMask,
224706f2543Smrg                             AppleWMIsActive, 0);
225706f2543Smrg            break;
226706f2543Smrg
227706f2543Smrg        case kXquartzDeactivate:
228706f2543Smrg            DEBUG_LOG("kXquartzDeactivate\n");
229706f2543Smrg            AppleWMSendEvent(AppleWMActivationNotify,
230706f2543Smrg                             AppleWMActivationNotifyMask,
231706f2543Smrg                             AppleWMIsInactive, 0);
232706f2543Smrg            QuartzHide();
233706f2543Smrg            break;
234706f2543Smrg
235706f2543Smrg        case kXquartzReloadPreferences:
236706f2543Smrg            DEBUG_LOG("kXquartzReloadPreferences\n");
237706f2543Smrg            AppleWMSendEvent(AppleWMActivationNotify,
238706f2543Smrg                             AppleWMActivationNotifyMask,
239706f2543Smrg                             AppleWMReloadPreferences, 0);
240706f2543Smrg            break;
241706f2543Smrg
242706f2543Smrg        case kXquartzToggleFullscreen:
243706f2543Smrg            DEBUG_LOG("kXquartzToggleFullscreen\n");
244706f2543Smrg            if(XQuartzIsRootless)
245706f2543Smrg                ErrorF("Ignoring kXquartzToggleFullscreen because of rootless mode.");
246706f2543Smrg            else
247706f2543Smrg                QuartzRandRToggleFullscreen();
248706f2543Smrg            break;
249706f2543Smrg
250706f2543Smrg        case kXquartzSetRootless:
251706f2543Smrg            DEBUG_LOG("kXquartzSetRootless\n");
252706f2543Smrg            if(e->data[0]) {
253706f2543Smrg                QuartzRandRSetFakeRootless();
254706f2543Smrg            } else {
255706f2543Smrg                QuartzRandRSetFakeFullscreen(FALSE);
256706f2543Smrg            }
257706f2543Smrg            break;
258706f2543Smrg
259706f2543Smrg        case kXquartzSetRootClip:
260706f2543Smrg            QuartzSetRootClip((Bool)e->data[0]);
261706f2543Smrg            break;
262706f2543Smrg
263706f2543Smrg        case kXquartzQuit:
264706f2543Smrg            GiveUp(0);
265706f2543Smrg            break;
266706f2543Smrg
267706f2543Smrg        case kXquartzSpaceChanged:
268706f2543Smrg            DEBUG_LOG("kXquartzSpaceChanged\n");
269706f2543Smrg            QuartzSpaceChanged(e->data[0]);
270706f2543Smrg            break;
271706f2543Smrg
272706f2543Smrg        case kXquartzListenOnOpenFD:
273706f2543Smrg            ErrorF("Calling ListenOnOpenFD() for new fd: %d\n", (int)e->data[0]);
274706f2543Smrg            ListenOnOpenFD((int)e->data[0], 1);
275706f2543Smrg            break;
276706f2543Smrg
277706f2543Smrg        case kXquartzReloadKeymap:
278706f2543Smrg            DarwinKeyboardReloadHandler();
279706f2543Smrg            break;
280706f2543Smrg
281706f2543Smrg        case kXquartzDisplayChanged:
282706f2543Smrg            DEBUG_LOG("kXquartzDisplayChanged\n");
283706f2543Smrg            QuartzUpdateScreens();
284706f2543Smrg
285706f2543Smrg            /* Update our RandR info */
286706f2543Smrg            QuartzRandRUpdateFakeModes(TRUE);
287706f2543Smrg            break;
288706f2543Smrg
289706f2543Smrg        default:
290706f2543Smrg            if(!QuartzModeEventHandler(screenNum, e, dev))
291706f2543Smrg                ErrorF("Unknown application defined event type %d.\n", e->subtype);
292706f2543Smrg    }
293706f2543Smrg}
294706f2543Smrg
295706f2543Smrgvoid DarwinListenOnOpenFD(int fd) {
296706f2543Smrg    ErrorF("DarwinListenOnOpenFD: %d\n", fd);
297706f2543Smrg
298706f2543Smrg    pthread_mutex_lock(&fd_add_lock);
299706f2543Smrg    if(fd_add_count < FD_ADD_MAX)
300706f2543Smrg        fd_add[fd_add_count++] = fd;
301706f2543Smrg    else
302706f2543Smrg        ErrorF("FD Addition buffer at max.  Dropping fd addition request.\n");
303706f2543Smrg
304706f2543Smrg    pthread_cond_broadcast(&fd_add_ready_cond);
305706f2543Smrg    pthread_mutex_unlock(&fd_add_lock);
306706f2543Smrg}
307706f2543Smrg
308706f2543Smrgstatic void *DarwinProcessFDAdditionQueue_thread(void *args) {
309706f2543Smrg    /* TODO: Possibly adjust this to no longer be a race... maybe trigger this
310706f2543Smrg     *       once a client connects and claims to be the WM.
311706f2543Smrg     *
312706f2543Smrg     * From ajax:
313706f2543Smrg     * There's already an internal callback chain for setting selection [in 1.5]
314706f2543Smrg     * ownership.  See the CallSelectionCallback at the bottom of
315706f2543Smrg     * ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook
316706f2543Smrg     * into it.
317706f2543Smrg     */
318706f2543Smrg
319706f2543Smrg    struct timespec sleep_for;
320706f2543Smrg    struct timespec sleep_remaining;
321706f2543Smrg
322706f2543Smrg    sleep_for.tv_sec = 3;
323706f2543Smrg    sleep_for.tv_nsec = 0;
324706f2543Smrg
325706f2543Smrg    ErrorF("X11.app: DarwinProcessFDAdditionQueue_thread: Sleeping to allow xinitrc to catchup.\n");
326706f2543Smrg    while(nanosleep(&sleep_for, &sleep_remaining) != 0) {
327706f2543Smrg        sleep_for = sleep_remaining;
328706f2543Smrg    }
329706f2543Smrg
330706f2543Smrg    pthread_mutex_lock(&fd_add_lock);
331706f2543Smrg    while(true) {
332706f2543Smrg        while(fd_add_count) {
333706f2543Smrg            DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1, fd_add[--fd_add_count]);
334706f2543Smrg        }
335706f2543Smrg        pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock);
336706f2543Smrg    }
337706f2543Smrg
338706f2543Smrg    return NULL;
339706f2543Smrg}
340706f2543Smrg
341706f2543SmrgBool DarwinEQInit(void) {
342706f2543Smrg    int *p;
343706f2543Smrg
344706f2543Smrg    for(p=darwin_x11_modifier_mask_list, darwin_all_modifier_mask=0; *p; p++) {
345706f2543Smrg        darwin_x11_modifier_mask |= *p;
346706f2543Smrg    }
347706f2543Smrg
348706f2543Smrg    for(p=darwin_all_modifier_mask_additions, darwin_all_modifier_mask= darwin_x11_modifier_mask; *p; p++) {
349706f2543Smrg        darwin_all_modifier_mask |= *p;
350706f2543Smrg    }
351706f2543Smrg
352706f2543Smrg    mieqInit();
353706f2543Smrg    mieqSetHandler(ET_XQuartz, DarwinEventHandler);
354706f2543Smrg
355706f2543Smrg    /* Note that this *could* cause a potential async issue, since we're checking
356706f2543Smrg     * darwinEvents without holding the lock, but darwinEvents is only ever set
357706f2543Smrg     * here, so I don't bother.
358706f2543Smrg     */
359706f2543Smrg    if (!darwinEvents) {
360706f2543Smrg        darwinEvents = InitEventList(GetMaximumEventsNum());;
361706f2543Smrg
362706f2543Smrg        if (!darwinEvents)
363706f2543Smrg            FatalError("Couldn't allocate event buffer\n");
364706f2543Smrg
365706f2543Smrg        darwinEvents_lock();
366706f2543Smrg        pthread_cond_broadcast(&mieq_ready_cond);
367706f2543Smrg        darwinEvents_unlock();
368706f2543Smrg    }
369706f2543Smrg
370706f2543Smrg    if(!fd_add_tid)
371706f2543Smrg        fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL);
372706f2543Smrg
373706f2543Smrg    return TRUE;
374706f2543Smrg}
375706f2543Smrg
376706f2543Smrg/*
377706f2543Smrg * ProcessInputEvents
378706f2543Smrg *  Read and process events from the event queue until it is empty.
379706f2543Smrg */
380706f2543Smrgvoid ProcessInputEvents(void) {
381706f2543Smrg    char nullbyte;
382706f2543Smrg	int x = sizeof(nullbyte);
383706f2543Smrg
384706f2543Smrg    TA_SERVER();
385706f2543Smrg
386706f2543Smrg    mieqProcessInputEvents();
387706f2543Smrg
388706f2543Smrg    // Empty the signaling pipe
389706f2543Smrg    while (x == sizeof(nullbyte)) {
390706f2543Smrg      x = read(darwinEventReadFD, &nullbyte, sizeof(nullbyte));
391706f2543Smrg    }
392706f2543Smrg}
393706f2543Smrg
394706f2543Smrg/* Sends a null byte down darwinEventWriteFD, which will cause the
395706f2543Smrg   Dispatch() event loop to check out event queue */
396706f2543Smrgstatic void DarwinPokeEQ(void) {
397706f2543Smrg	char nullbyte=0;
398706f2543Smrg	//  <daniels> oh, i ... er ... christ.
399706f2543Smrg	write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte));
400706f2543Smrg}
401706f2543Smrg
402706f2543Smrg/* Convert from Appkit pointer input values to X input values:
403706f2543Smrg * Note: pointer_x and pointer_y are relative to the upper-left of primary
404706f2543Smrg *       display.
405706f2543Smrg */
406706f2543Smrgstatic void DarwinPrepareValuators(DeviceIntPtr pDev, int *valuators, ScreenPtr screen,
407706f2543Smrg                                   float pointer_x, float pointer_y,
408706f2543Smrg                                   float pressure, float tilt_x, float tilt_y) {
409706f2543Smrg    /* Fix offset between darwin and X screens */
410706f2543Smrg    pointer_x -= darwinMainScreenX + screen->x;
411706f2543Smrg    pointer_y -= darwinMainScreenY + screen->y;
412706f2543Smrg
413706f2543Smrg    if(pointer_x < 0.0)
414706f2543Smrg        pointer_x = 0.0;
415706f2543Smrg
416706f2543Smrg    if(pointer_y < 0.0)
417706f2543Smrg        pointer_y = 0.0;
418706f2543Smrg
419706f2543Smrg    if(pDev == darwinPointer) {
420706f2543Smrg        valuators[0] = pointer_x;
421706f2543Smrg        valuators[1] = pointer_y;
422706f2543Smrg        valuators[2] = 0;
423706f2543Smrg        valuators[3] = 0;
424706f2543Smrg        valuators[4] = 0;
425706f2543Smrg    } else {
426706f2543Smrg        /* Setup our array of values */
427706f2543Smrg        valuators[0] = XQUARTZ_VALUATOR_LIMIT * (pointer_x / (float)screenInfo.screens[0]->width);
428706f2543Smrg        valuators[1] = XQUARTZ_VALUATOR_LIMIT * (pointer_y / (float)screenInfo.screens[0]->height);
429706f2543Smrg        valuators[2] = XQUARTZ_VALUATOR_LIMIT * pressure;
430706f2543Smrg        valuators[3] = XQUARTZ_VALUATOR_LIMIT * tilt_x;
431706f2543Smrg        valuators[4] = XQUARTZ_VALUATOR_LIMIT * tilt_y;
432706f2543Smrg    }
433706f2543Smrg    //DEBUG_LOG("Pointer (%f, %f), Valuators: {%d,%d,%d,%d,%d}\n", pointer_x, pointer_y,
434706f2543Smrg    //          valuators[0], valuators[1], valuators[2], valuators[3], valuators[4]);
435706f2543Smrg}
436706f2543Smrg
437706f2543Smrgvoid DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, float pointer_x, float pointer_y,
438706f2543Smrg			     float pressure, float tilt_x, float tilt_y) {
439706f2543Smrg	static int darwinFakeMouseButtonDown = 0;
440706f2543Smrg	int i, num_events;
441706f2543Smrg    ScreenPtr screen;
442706f2543Smrg    int valuators[5];
443706f2543Smrg
444706f2543Smrg    //DEBUG_LOG("x=%f, y=%f, p=%f, tx=%f, ty=%f\n", pointer_x, pointer_y, pressure, tilt_x, tilt_y);
445706f2543Smrg
446706f2543Smrg	if(!darwinEvents) {
447706f2543Smrg		DEBUG_LOG("DarwinSendPointerEvents called before darwinEvents was initialized\n");
448706f2543Smrg		return;
449706f2543Smrg	}
450706f2543Smrg
451706f2543Smrg    screen = miPointerGetScreen(pDev);
452706f2543Smrg    if(!screen) {
453706f2543Smrg        DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
454706f2543Smrg        return;
455706f2543Smrg    }
456706f2543Smrg
457706f2543Smrg    /* Handle fake click */
458706f2543Smrg	if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) {
459706f2543Smrg        if(darwinFakeMouseButtonDown != 0) {
460706f2543Smrg            /* We're currently "down" with another button, so release it first */
461706f2543Smrg            DarwinSendPointerEvents(pDev, ButtonRelease, darwinFakeMouseButtonDown, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
462706f2543Smrg            darwinFakeMouseButtonDown=0;
463706f2543Smrg        }
464706f2543Smrg		if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
465706f2543Smrg            ev_button = 2;
466706f2543Smrg			darwinFakeMouseButtonDown = 2;
467706f2543Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
468706f2543Smrg		} else if (darwin_all_modifier_flags & darwinFakeMouse3Mask) {
469706f2543Smrg            ev_button = 3;
470706f2543Smrg			darwinFakeMouseButtonDown = 3;
471706f2543Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
472706f2543Smrg		}
473706f2543Smrg	}
474706f2543Smrg
475706f2543Smrg	if (ev_type == ButtonRelease && ev_button == 1) {
476706f2543Smrg        if(darwinFakeMouseButtonDown) {
477706f2543Smrg            ev_button = darwinFakeMouseButtonDown;
478706f2543Smrg        }
479706f2543Smrg
480706f2543Smrg        if(darwinFakeMouseButtonDown == 2) {
481706f2543Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
482706f2543Smrg        } else if(darwinFakeMouseButtonDown == 3) {
483706f2543Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
484706f2543Smrg        }
485706f2543Smrg
486706f2543Smrg        darwinFakeMouseButtonDown = 0;
487706f2543Smrg	}
488706f2543Smrg
489706f2543Smrg    DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
490706f2543Smrg    darwinEvents_lock(); {
491706f2543Smrg        ValuatorMask mask;
492706f2543Smrg        valuator_mask_set_range(&mask, 0, (pDev == darwinTabletCurrent) ? 5 : 2, valuators);
493706f2543Smrg        num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button,
494706f2543Smrg                                      POINTER_ABSOLUTE, &mask);
495706f2543Smrg        for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
496706f2543Smrg        if(num_events > 0) DarwinPokeEQ();
497706f2543Smrg    } darwinEvents_unlock();
498706f2543Smrg}
499706f2543Smrg
500706f2543Smrgvoid DarwinSendKeyboardEvents(int ev_type, int keycode) {
501706f2543Smrg	int i, num_events;
502706f2543Smrg
503706f2543Smrg	if(!darwinEvents) {
504706f2543Smrg		DEBUG_LOG("DarwinSendKeyboardEvents called before darwinEvents was initialized\n");
505706f2543Smrg		return;
506706f2543Smrg	}
507706f2543Smrg
508706f2543Smrg    darwinEvents_lock(); {
509706f2543Smrg        num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE);
510706f2543Smrg        for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard, (InternalEvent*)darwinEvents[i].event);
511706f2543Smrg        if(num_events > 0) DarwinPokeEQ();
512706f2543Smrg    } darwinEvents_unlock();
513706f2543Smrg}
514706f2543Smrg
515706f2543Smrgvoid DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) {
516706f2543Smrg	int i, num_events;
517706f2543Smrg    ScreenPtr screen;
518706f2543Smrg    DeviceIntPtr pDev = darwinTabletCurrent;
519706f2543Smrg    int valuators[5];
520706f2543Smrg
521706f2543Smrg	DEBUG_LOG("DarwinSendProximityEvents(%d, %f, %f)\n", ev_type, pointer_x, pointer_y);
522706f2543Smrg
523706f2543Smrg	if(!darwinEvents) {
524706f2543Smrg		DEBUG_LOG("DarwinSendProximityEvents called before darwinEvents was initialized\n");
525706f2543Smrg		return;
526706f2543Smrg	}
527706f2543Smrg
528706f2543Smrg    screen = miPointerGetScreen(pDev);
529706f2543Smrg    if(!screen) {
530706f2543Smrg        DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
531706f2543Smrg        return;
532706f2543Smrg    }
533706f2543Smrg
534706f2543Smrg    DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, 0.0f, 0.0f, 0.0f);
535706f2543Smrg    darwinEvents_lock(); {
536706f2543Smrg        ValuatorMask mask;
537706f2543Smrg        valuator_mask_set_range(&mask, 0, 5, valuators);
538706f2543Smrg        num_events = GetProximityEvents(darwinEvents, pDev, ev_type, &mask);
539706f2543Smrg        for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
540706f2543Smrg        if(num_events > 0) DarwinPokeEQ();
541706f2543Smrg    } darwinEvents_unlock();
542706f2543Smrg}
543706f2543Smrg
544706f2543Smrg
545706f2543Smrg/* Send the appropriate number of button clicks to emulate scroll wheel */
546706f2543Smrgvoid DarwinSendScrollEvents(float count_x, float count_y,
547706f2543Smrg							float pointer_x, float pointer_y,
548706f2543Smrg			    			float pressure, float tilt_x, float tilt_y) {
549706f2543Smrg	int sign_x, sign_y;
550706f2543Smrg	if(!darwinEvents) {
551706f2543Smrg		DEBUG_LOG("DarwinSendScrollEvents called before darwinEvents was initialized\n");
552706f2543Smrg		return;
553706f2543Smrg	}
554706f2543Smrg
555706f2543Smrg	sign_x = count_x > 0.0f ? SCROLLWHEELLEFTFAKE : SCROLLWHEELRIGHTFAKE;
556706f2543Smrg	sign_y = count_y > 0.0f ? SCROLLWHEELUPFAKE : SCROLLWHEELDOWNFAKE;
557706f2543Smrg	count_x = fabs(count_x);
558706f2543Smrg	count_y = fabs(count_y);
559706f2543Smrg
560706f2543Smrg	while ((count_x > 0.0f) || (count_y > 0.0f)) {
561706f2543Smrg		if (count_x > 0.0f) {
562706f2543Smrg			DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
563706f2543Smrg			DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
564706f2543Smrg			count_x = count_x - 1.0f;
565706f2543Smrg		}
566706f2543Smrg		if (count_y > 0.0f) {
567706f2543Smrg			DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
568706f2543Smrg			DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
569706f2543Smrg			count_y = count_y - 1.0f;
570706f2543Smrg		}
571706f2543Smrg	}
572706f2543Smrg}
573706f2543Smrg
574706f2543Smrg/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to
575706f2543Smrg   reflect changing modifier flags (alt, control, meta, etc) */
576706f2543Smrgvoid DarwinUpdateModKeys(int flags) {
577706f2543Smrg	DarwinUpdateModifiers(KeyRelease, darwin_all_modifier_flags & ~flags & darwin_x11_modifier_mask);
578706f2543Smrg	DarwinUpdateModifiers(KeyPress, ~darwin_all_modifier_flags & flags & darwin_x11_modifier_mask);
579706f2543Smrg	darwin_all_modifier_flags = flags;
580706f2543Smrg}
581706f2543Smrg
582706f2543Smrg/*
583706f2543Smrg * DarwinSendDDXEvent
584706f2543Smrg *  Send the X server thread a message by placing it on the event queue.
585706f2543Smrg */
586706f2543Smrgvoid DarwinSendDDXEvent(int type, int argc, ...) {
587706f2543Smrg    XQuartzEvent e;
588706f2543Smrg    int i;
589706f2543Smrg    va_list args;
590706f2543Smrg
591706f2543Smrg    memset(&e, 0, sizeof(e));
592706f2543Smrg    e.header = ET_Internal;
593706f2543Smrg    e.type = ET_XQuartz;
594706f2543Smrg    e.length = sizeof(e);
595706f2543Smrg    e.time = GetTimeInMillis();
596706f2543Smrg    e.subtype = type;
597706f2543Smrg
598706f2543Smrg    if (argc > 0 && argc < XQUARTZ_EVENT_MAXARGS) {
599706f2543Smrg        va_start (args, argc);
600706f2543Smrg        for (i = 0; i < argc; i++)
601706f2543Smrg            e.data[i] = (uint32_t) va_arg (args, uint32_t);
602706f2543Smrg        va_end (args);
603706f2543Smrg    }
604706f2543Smrg
605706f2543Smrg    darwinEvents_lock(); {
606706f2543Smrg        mieqEnqueue(NULL, (InternalEvent*)&e);
607706f2543Smrg        DarwinPokeEQ();
608706f2543Smrg    } darwinEvents_unlock();
609706f2543Smrg}
610