darwinEvents.c revision 6747b715
14642e01fSmrg/*
24642e01fSmrgDarwin event queue and event handling
34642e01fSmrg
44642e01fSmrgCopyright 2007-2008 Apple Inc.
54642e01fSmrgCopyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
64642e01fSmrgCopyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
74642e01fSmrg
84642e01fSmrgThis file is based on mieq.c by Keith Packard,
94642e01fSmrgwhich contains the following copyright:
104642e01fSmrgCopyright 1990, 1998  The Open Group
114642e01fSmrg
124642e01fSmrgPermission to use, copy, modify, distribute, and sell this software and its
134642e01fSmrgdocumentation for any purpose is hereby granted without fee, provided that
144642e01fSmrgthe above copyright notice appear in all copies and that both that
154642e01fSmrgcopyright notice and this permission notice appear in supporting
164642e01fSmrgdocumentation.
174642e01fSmrg
184642e01fSmrgThe above copyright notice and this permission notice shall be included in
194642e01fSmrgall copies or substantial portions of the Software.
204642e01fSmrg
214642e01fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
224642e01fSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
234642e01fSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
244642e01fSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
254642e01fSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
264642e01fSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
274642e01fSmrg
284642e01fSmrgExcept as contained in this notice, the name of The Open Group shall not be
294642e01fSmrgused in advertising or otherwise to promote the sale, use or other dealings
304642e01fSmrgin this Software without prior written authorization from The Open Group.
314642e01fSmrg */
324642e01fSmrg
334642e01fSmrg#include "sanitizedCarbon.h"
344642e01fSmrg
354642e01fSmrg#ifdef HAVE_DIX_CONFIG_H
364642e01fSmrg#include <dix-config.h>
374642e01fSmrg#endif
384642e01fSmrg
394642e01fSmrg#include   <X11/X.h>
404642e01fSmrg#include   <X11/Xmd.h>
414642e01fSmrg#include   <X11/Xproto.h>
424642e01fSmrg#include   "misc.h"
434642e01fSmrg#include   "windowstr.h"
444642e01fSmrg#include   "pixmapstr.h"
454642e01fSmrg#include   "inputstr.h"
466747b715Smrg#include   "eventstr.h"
474642e01fSmrg#include   "mi.h"
484642e01fSmrg#include   "scrnintstr.h"
494642e01fSmrg#include   "mipointer.h"
504642e01fSmrg#include   "os.h"
514642e01fSmrg
524642e01fSmrg#include "darwin.h"
534642e01fSmrg#include "quartz.h"
544642e01fSmrg#include "quartzKeyboard.h"
556747b715Smrg#include "quartzRandR.h"
564642e01fSmrg#include "darwinEvents.h"
574642e01fSmrg
584642e01fSmrg#include <sys/types.h>
594642e01fSmrg#include <sys/uio.h>
604642e01fSmrg#include <unistd.h>
614642e01fSmrg#include <pthread.h>
624642e01fSmrg#include <errno.h>
634642e01fSmrg
644642e01fSmrg#include <IOKit/hidsystem/IOLLEvent.h>
654642e01fSmrg
664642e01fSmrg/* Fake button press/release for scroll wheel move. */
674642e01fSmrg#define SCROLLWHEELUPFAKE    4
684642e01fSmrg#define SCROLLWHEELDOWNFAKE  5
694642e01fSmrg#define SCROLLWHEELLEFTFAKE  6
704642e01fSmrg#define SCROLLWHEELRIGHTFAKE 7
714642e01fSmrg
726747b715Smrg#include <X11/extensions/applewmconst.h>
734642e01fSmrg#include "applewmExt.h"
744642e01fSmrg
754642e01fSmrg/* FIXME: Abstract this better */
766747b715Smrgextern Bool QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev);
774642e01fSmrg
786747b715Smrgint darwin_all_modifier_flags = 0;  // last known modifier state
796747b715Smrgint darwin_all_modifier_mask = 0;
806747b715Smrgint darwin_x11_modifier_mask = 0;
814642e01fSmrg
824642e01fSmrg#define FD_ADD_MAX 128
834642e01fSmrgstatic int fd_add[FD_ADD_MAX];
844642e01fSmrgint fd_add_count = 0;
854642e01fSmrgstatic pthread_mutex_t fd_add_lock = PTHREAD_MUTEX_INITIALIZER;
864642e01fSmrgstatic pthread_cond_t fd_add_ready_cond = PTHREAD_COND_INITIALIZER;
874642e01fSmrgstatic pthread_t fd_add_tid = NULL;
884642e01fSmrg
896747b715Smrgstatic EventListPtr darwinEvents = NULL;
904642e01fSmrg
914642e01fSmrgstatic pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER;
924642e01fSmrgstatic pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER;
934642e01fSmrg
944642e01fSmrg/*** Pthread Magics ***/
954642e01fSmrgstatic pthread_t create_thread(void *func, void *arg) {
964642e01fSmrg    pthread_attr_t attr;
974642e01fSmrg    pthread_t tid;
984642e01fSmrg
994642e01fSmrg    pthread_attr_init (&attr);
1004642e01fSmrg    pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
1014642e01fSmrg    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
1024642e01fSmrg    pthread_create (&tid, &attr, func, arg);
1034642e01fSmrg    pthread_attr_destroy (&attr);
1044642e01fSmrg
1054642e01fSmrg    return tid;
1064642e01fSmrg}
1074642e01fSmrg
1084642e01fSmrgvoid darwinEvents_lock(void);
1094642e01fSmrgvoid darwinEvents_lock(void) {
1104642e01fSmrg    int err;
1114642e01fSmrg    if((err = pthread_mutex_lock(&mieq_lock))) {
1124642e01fSmrg        ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n",
1134642e01fSmrg               __FILE__, __FUNCTION__, __LINE__, err);
1144642e01fSmrg        spewCallStack();
1154642e01fSmrg    }
1164642e01fSmrg    if(darwinEvents == NULL) {
1174642e01fSmrg        pthread_cond_wait(&mieq_ready_cond, &mieq_lock);
1184642e01fSmrg    }
1194642e01fSmrg}
1204642e01fSmrg
1214642e01fSmrgvoid darwinEvents_unlock(void);
1224642e01fSmrgvoid darwinEvents_unlock(void) {
1234642e01fSmrg    int err;
1244642e01fSmrg    if((err = pthread_mutex_unlock(&mieq_lock))) {
1254642e01fSmrg        ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n",
1264642e01fSmrg               __FILE__, __FUNCTION__, __LINE__, err);
1274642e01fSmrg        spewCallStack();
1284642e01fSmrg    }
1294642e01fSmrg}
1304642e01fSmrg
1314642e01fSmrg/*
1324642e01fSmrg * DarwinPressModifierKey
1334642e01fSmrg * Press or release the given modifier key (one of NX_MODIFIERKEY_* constants)
1344642e01fSmrg */
1354642e01fSmrgstatic void DarwinPressModifierKey(int pressed, int key) {
1364642e01fSmrg    int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
1374642e01fSmrg
1384642e01fSmrg    if (keycode == 0) {
1394642e01fSmrg        ErrorF("DarwinPressModifierKey bad keycode: key=%d\n", key);
1404642e01fSmrg        return;
1414642e01fSmrg    }
1424642e01fSmrg
1434642e01fSmrg    DarwinSendKeyboardEvents(pressed, keycode);
1444642e01fSmrg}
1454642e01fSmrg
1464642e01fSmrg/*
1474642e01fSmrg * DarwinUpdateModifiers
1484642e01fSmrg *  Send events to update the modifier state.
1494642e01fSmrg */
1504642e01fSmrg
1516747b715Smrgstatic int darwin_x11_modifier_mask_list[] = {
1524642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK
1534642e01fSmrg    NX_DEVICELCTLKEYMASK, NX_DEVICERCTLKEYMASK,
1544642e01fSmrg    NX_DEVICELSHIFTKEYMASK, NX_DEVICERSHIFTKEYMASK,
1554642e01fSmrg    NX_DEVICELCMDKEYMASK, NX_DEVICERCMDKEYMASK,
1564642e01fSmrg    NX_DEVICELALTKEYMASK, NX_DEVICERALTKEYMASK,
1574642e01fSmrg#else
1584642e01fSmrg    NX_CONTROLMASK, NX_SHIFTMASK, NX_COMMANDMASK, NX_ALTERNATEMASK,
1594642e01fSmrg#endif
1604642e01fSmrg    NX_ALPHASHIFTMASK,
1614642e01fSmrg    0
1624642e01fSmrg};
1634642e01fSmrg
1646747b715Smrgstatic int darwin_all_modifier_mask_additions[] = { NX_SECONDARYFNMASK, };
1656747b715Smrg
1664642e01fSmrgstatic void DarwinUpdateModifiers(
1674642e01fSmrg    int pressed,        // KeyPress or KeyRelease
1684642e01fSmrg    int flags )         // modifier flags that have changed
1694642e01fSmrg{
1704642e01fSmrg    int *f;
1714642e01fSmrg    int key;
1724642e01fSmrg
1734642e01fSmrg    /* Capslock is special.  This mask is the state of capslock (on/off),
1744642e01fSmrg     * not the state of the button.  Hopefully we can find a better solution.
1754642e01fSmrg     */
1764642e01fSmrg    if(NX_ALPHASHIFTMASK & flags) {
1774642e01fSmrg        DarwinPressModifierKey(KeyPress, NX_MODIFIERKEY_ALPHALOCK);
1784642e01fSmrg        DarwinPressModifierKey(KeyRelease, NX_MODIFIERKEY_ALPHALOCK);
1794642e01fSmrg    }
1804642e01fSmrg
1816747b715Smrg    for(f=darwin_x11_modifier_mask_list; *f; f++)
1824642e01fSmrg        if(*f & flags && *f != NX_ALPHASHIFTMASK) {
1834642e01fSmrg            key = DarwinModifierNXMaskToNXKey(*f);
1844642e01fSmrg            if(key == -1)
1854642e01fSmrg                ErrorF("DarwinUpdateModifiers: Unsupported NXMask: 0x%x\n", *f);
1864642e01fSmrg            else
1874642e01fSmrg                DarwinPressModifierKey(pressed, key);
1884642e01fSmrg        }
1894642e01fSmrg}
1904642e01fSmrg
1914642e01fSmrg/* Generic handler for Xquartz-specifc events.  When possible, these should
1924642e01fSmrg   be moved into their own individual functions and set as handlers using
1934642e01fSmrg   mieqSetHandler. */
1944642e01fSmrg
1956747b715Smrgstatic void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr dev) {
1966747b715Smrg    XQuartzEvent *e = &(ie->xquartz_event);
1976747b715Smrg
1984642e01fSmrg    TA_SERVER();
1994642e01fSmrg
2006747b715Smrg    switch(e->subtype) {
2016747b715Smrg        case kXquartzControllerNotify:
2026747b715Smrg            DEBUG_LOG("kXquartzControllerNotify\n");
2036747b715Smrg            AppleWMSendEvent(AppleWMControllerNotify,
2046747b715Smrg                             AppleWMControllerNotifyMask,
2056747b715Smrg                             e->data[0],
2066747b715Smrg                             e->data[1]);
2076747b715Smrg            break;
2086747b715Smrg
2096747b715Smrg        case kXquartzPasteboardNotify:
2106747b715Smrg            DEBUG_LOG("kXquartzPasteboardNotify\n");
2116747b715Smrg            AppleWMSendEvent(AppleWMPasteboardNotify,
2126747b715Smrg                             AppleWMPasteboardNotifyMask,
2136747b715Smrg                             e->data[0],
2146747b715Smrg                             e->data[1]);
2156747b715Smrg            break;
2166747b715Smrg
2176747b715Smrg        case kXquartzActivate:
2186747b715Smrg            DEBUG_LOG("kXquartzActivate\n");
2196747b715Smrg            QuartzShow();
2206747b715Smrg            AppleWMSendEvent(AppleWMActivationNotify,
2216747b715Smrg                             AppleWMActivationNotifyMask,
2226747b715Smrg                             AppleWMIsActive, 0);
2236747b715Smrg            break;
2246747b715Smrg
2256747b715Smrg        case kXquartzDeactivate:
2266747b715Smrg            DEBUG_LOG("kXquartzDeactivate\n");
2276747b715Smrg            AppleWMSendEvent(AppleWMActivationNotify,
2286747b715Smrg                             AppleWMActivationNotifyMask,
2296747b715Smrg                             AppleWMIsInactive, 0);
2306747b715Smrg            QuartzHide();
2316747b715Smrg            break;
2326747b715Smrg
2336747b715Smrg        case kXquartzReloadPreferences:
2346747b715Smrg            DEBUG_LOG("kXquartzReloadPreferences\n");
2356747b715Smrg            AppleWMSendEvent(AppleWMActivationNotify,
2366747b715Smrg                             AppleWMActivationNotifyMask,
2376747b715Smrg                             AppleWMReloadPreferences, 0);
2386747b715Smrg            break;
2396747b715Smrg
2406747b715Smrg        case kXquartzToggleFullscreen:
2416747b715Smrg            DEBUG_LOG("kXquartzToggleFullscreen\n");
2426747b715Smrg            if(XQuartzIsRootless)
2436747b715Smrg                ErrorF("Ignoring kXquartzToggleFullscreen because of rootless mode.");
2446747b715Smrg            else
2456747b715Smrg                QuartzRandRToggleFullscreen();
2466747b715Smrg            break;
2476747b715Smrg
2486747b715Smrg        case kXquartzSetRootless:
2496747b715Smrg            DEBUG_LOG("kXquartzSetRootless\n");
2506747b715Smrg            if(e->data[0]) {
2516747b715Smrg                QuartzRandRSetFakeRootless();
2526747b715Smrg            } else {
2536747b715Smrg                QuartzRandRSetFakeFullscreen(FALSE);
2546747b715Smrg            }
2556747b715Smrg            break;
2566747b715Smrg
2576747b715Smrg        case kXquartzSetRootClip:
2586747b715Smrg            QuartzSetRootClip((Bool)e->data[0]);
2596747b715Smrg            break;
2606747b715Smrg
2616747b715Smrg        case kXquartzQuit:
2626747b715Smrg            GiveUp(0);
2636747b715Smrg            break;
2646747b715Smrg
2656747b715Smrg        case kXquartzSpaceChanged:
2666747b715Smrg            DEBUG_LOG("kXquartzSpaceChanged\n");
2676747b715Smrg            QuartzSpaceChanged(e->data[0]);
2686747b715Smrg            break;
2696747b715Smrg
2706747b715Smrg        case kXquartzListenOnOpenFD:
2716747b715Smrg            ErrorF("Calling ListenOnOpenFD() for new fd: %d\n", (int)e->data[0]);
2726747b715Smrg            ListenOnOpenFD((int)e->data[0], 1);
2736747b715Smrg            break;
2746747b715Smrg
2756747b715Smrg        case kXquartzReloadKeymap:
2766747b715Smrg            DarwinKeyboardReloadHandler();
2776747b715Smrg            break;
2786747b715Smrg
2796747b715Smrg        case kXquartzDisplayChanged:
2806747b715Smrg            DEBUG_LOG("kXquartzDisplayChanged\n");
2816747b715Smrg            QuartzUpdateScreens();
2826747b715Smrg#ifdef RANDR
2836747b715Smrg            /* Update our RandR info */
2846747b715Smrg            QuartzRandRUpdateFakeModes(TRUE);
2856747b715Smrg#endif
2866747b715Smrg            break;
2876747b715Smrg
2886747b715Smrg        default:
2896747b715Smrg            if(!QuartzModeEventHandler(screenNum, e, dev))
2906747b715Smrg                ErrorF("Unknown application defined event type %d.\n", e->subtype);
2916747b715Smrg    }
2924642e01fSmrg}
2934642e01fSmrg
2944642e01fSmrgvoid DarwinListenOnOpenFD(int fd) {
2954642e01fSmrg    ErrorF("DarwinListenOnOpenFD: %d\n", fd);
2964642e01fSmrg
2974642e01fSmrg    pthread_mutex_lock(&fd_add_lock);
2984642e01fSmrg    if(fd_add_count < FD_ADD_MAX)
2994642e01fSmrg        fd_add[fd_add_count++] = fd;
3004642e01fSmrg    else
3014642e01fSmrg        ErrorF("FD Addition buffer at max.  Dropping fd addition request.\n");
3024642e01fSmrg
3034642e01fSmrg    pthread_cond_broadcast(&fd_add_ready_cond);
3044642e01fSmrg    pthread_mutex_unlock(&fd_add_lock);
3054642e01fSmrg}
3064642e01fSmrg
3074642e01fSmrgstatic void DarwinProcessFDAdditionQueue_thread(void *args) {
3084642e01fSmrg    pthread_mutex_lock(&fd_add_lock);
3094642e01fSmrg    while(true) {
3104642e01fSmrg        while(fd_add_count) {
3114642e01fSmrg            DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1, fd_add[--fd_add_count]);
3124642e01fSmrg        }
3134642e01fSmrg        pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock);
3144642e01fSmrg    }
3154642e01fSmrg}
3164642e01fSmrg
3176747b715SmrgBool DarwinEQInit(void) {
3186747b715Smrg    int *p;
3196747b715Smrg
3206747b715Smrg    for(p=darwin_x11_modifier_mask_list, darwin_all_modifier_mask=0; *p; p++) {
3216747b715Smrg        darwin_x11_modifier_mask |= *p;
3226747b715Smrg    }
3234642e01fSmrg
3246747b715Smrg    for(p=darwin_all_modifier_mask_additions, darwin_all_modifier_mask= darwin_x11_modifier_mask; *p; p++) {
3256747b715Smrg        darwin_all_modifier_mask |= *p;
3264642e01fSmrg    }
3274642e01fSmrg
3286747b715Smrg    mieqInit();
3296747b715Smrg    mieqSetHandler(ET_XQuartz, DarwinEventHandler);
3304642e01fSmrg
3314642e01fSmrg    /* Note that this *could* cause a potential async issue, since we're checking
3324642e01fSmrg     * darwinEvents without holding the lock, but darwinEvents is only ever set
3334642e01fSmrg     * here, so I don't bother.
3344642e01fSmrg     */
3354642e01fSmrg    if (!darwinEvents) {
3364642e01fSmrg        darwinEvents = InitEventList(GetMaximumEventsNum());;
3374642e01fSmrg
3384642e01fSmrg        if (!darwinEvents)
3394642e01fSmrg            FatalError("Couldn't allocate event buffer\n");
3404642e01fSmrg
3414642e01fSmrg        darwinEvents_lock();
3424642e01fSmrg        pthread_cond_broadcast(&mieq_ready_cond);
3434642e01fSmrg        darwinEvents_unlock();
3444642e01fSmrg    }
3454642e01fSmrg
3464642e01fSmrg    if(!fd_add_tid)
3474642e01fSmrg        fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL);
3484642e01fSmrg
3494642e01fSmrg    return TRUE;
3504642e01fSmrg}
3514642e01fSmrg
3524642e01fSmrg/*
3534642e01fSmrg * ProcessInputEvents
3544642e01fSmrg *  Read and process events from the event queue until it is empty.
3554642e01fSmrg */
3564642e01fSmrgvoid ProcessInputEvents(void) {
3576747b715Smrg    char nullbyte;
3586747b715Smrg	int x = sizeof(nullbyte);
3594642e01fSmrg
3604642e01fSmrg    TA_SERVER();
3614642e01fSmrg
3624642e01fSmrg    mieqProcessInputEvents();
3634642e01fSmrg
3644642e01fSmrg    // Empty the signaling pipe
3656747b715Smrg    while (x == sizeof(nullbyte)) {
3666747b715Smrg      x = read(darwinEventReadFD, &nullbyte, sizeof(nullbyte));
3674642e01fSmrg    }
3684642e01fSmrg}
3694642e01fSmrg
3704642e01fSmrg/* Sends a null byte down darwinEventWriteFD, which will cause the
3714642e01fSmrg   Dispatch() event loop to check out event queue */
3724642e01fSmrgstatic void DarwinPokeEQ(void) {
3734642e01fSmrg	char nullbyte=0;
3744642e01fSmrg	//  <daniels> oh, i ... er ... christ.
3756747b715Smrg	write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte));
3764642e01fSmrg}
3774642e01fSmrg
3784642e01fSmrg/* Convert from Appkit pointer input values to X input values:
3794642e01fSmrg * Note: pointer_x and pointer_y are relative to the upper-left of primary
3804642e01fSmrg *       display.
3814642e01fSmrg */
3824642e01fSmrgstatic void DarwinPrepareValuators(DeviceIntPtr pDev, int *valuators, ScreenPtr screen,
3834642e01fSmrg                                   float pointer_x, float pointer_y,
3844642e01fSmrg                                   float pressure, float tilt_x, float tilt_y) {
3854642e01fSmrg    /* Fix offset between darwin and X screens */
3866747b715Smrg    pointer_x -= darwinMainScreenX + screen->x;
3876747b715Smrg    pointer_y -= darwinMainScreenY + screen->y;
3884642e01fSmrg
3894642e01fSmrg    if(pointer_x < 0.0)
3904642e01fSmrg        pointer_x = 0.0;
3914642e01fSmrg
3924642e01fSmrg    if(pointer_y < 0.0)
3934642e01fSmrg        pointer_y = 0.0;
3944642e01fSmrg
3954642e01fSmrg    if(pDev == darwinPointer) {
3964642e01fSmrg        valuators[0] = pointer_x;
3974642e01fSmrg        valuators[1] = pointer_y;
3984642e01fSmrg        valuators[2] = 0;
3994642e01fSmrg        valuators[3] = 0;
4004642e01fSmrg        valuators[4] = 0;
4014642e01fSmrg    } else {
4024642e01fSmrg        /* Setup our array of values */
4034642e01fSmrg        valuators[0] = XQUARTZ_VALUATOR_LIMIT * (pointer_x / (float)screenInfo.screens[0]->width);
4044642e01fSmrg        valuators[1] = XQUARTZ_VALUATOR_LIMIT * (pointer_y / (float)screenInfo.screens[0]->height);
4054642e01fSmrg        valuators[2] = XQUARTZ_VALUATOR_LIMIT * pressure;
4064642e01fSmrg        valuators[3] = XQUARTZ_VALUATOR_LIMIT * tilt_x;
4074642e01fSmrg        valuators[4] = XQUARTZ_VALUATOR_LIMIT * tilt_y;
4084642e01fSmrg    }
4094642e01fSmrg    //DEBUG_LOG("Pointer (%f, %f), Valuators: {%d,%d,%d,%d,%d}\n", pointer_x, pointer_y,
4104642e01fSmrg    //          valuators[0], valuators[1], valuators[2], valuators[3], valuators[4]);
4114642e01fSmrg}
4124642e01fSmrg
4134642e01fSmrgvoid DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, float pointer_x, float pointer_y,
4144642e01fSmrg			     float pressure, float tilt_x, float tilt_y) {
4154642e01fSmrg	static int darwinFakeMouseButtonDown = 0;
4164642e01fSmrg	int i, num_events;
4174642e01fSmrg    ScreenPtr screen;
4184642e01fSmrg    int valuators[5];
4194642e01fSmrg
4204642e01fSmrg    //DEBUG_LOG("x=%f, y=%f, p=%f, tx=%f, ty=%f\n", pointer_x, pointer_y, pressure, tilt_x, tilt_y);
4214642e01fSmrg
4224642e01fSmrg	if(!darwinEvents) {
4234642e01fSmrg		DEBUG_LOG("DarwinSendPointerEvents called before darwinEvents was initialized\n");
4244642e01fSmrg		return;
4254642e01fSmrg	}
4264642e01fSmrg
4274642e01fSmrg    screen = miPointerGetScreen(pDev);
4284642e01fSmrg    if(!screen) {
4294642e01fSmrg        DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
4304642e01fSmrg        return;
4314642e01fSmrg    }
4324642e01fSmrg
4334642e01fSmrg    /* Handle fake click */
4344642e01fSmrg	if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) {
4354642e01fSmrg        if(darwinFakeMouseButtonDown != 0) {
4364642e01fSmrg            /* We're currently "down" with another button, so release it first */
4374642e01fSmrg            DarwinSendPointerEvents(pDev, ButtonRelease, darwinFakeMouseButtonDown, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
4384642e01fSmrg            darwinFakeMouseButtonDown=0;
4394642e01fSmrg        }
4406747b715Smrg		if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
4414642e01fSmrg            ev_button = 2;
4424642e01fSmrg			darwinFakeMouseButtonDown = 2;
4436747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
4446747b715Smrg		} else if (darwin_all_modifier_flags & darwinFakeMouse3Mask) {
4454642e01fSmrg            ev_button = 3;
4464642e01fSmrg			darwinFakeMouseButtonDown = 3;
4476747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
4484642e01fSmrg		}
4494642e01fSmrg	}
4504642e01fSmrg
4514642e01fSmrg	if (ev_type == ButtonRelease && ev_button == 1) {
4524642e01fSmrg        if(darwinFakeMouseButtonDown) {
4534642e01fSmrg            ev_button = darwinFakeMouseButtonDown;
4544642e01fSmrg        }
4554642e01fSmrg
4564642e01fSmrg        if(darwinFakeMouseButtonDown == 2) {
4576747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
4584642e01fSmrg        } else if(darwinFakeMouseButtonDown == 3) {
4596747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
4604642e01fSmrg        }
4614642e01fSmrg
4624642e01fSmrg        darwinFakeMouseButtonDown = 0;
4634642e01fSmrg	}
4644642e01fSmrg
4654642e01fSmrg    DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
4664642e01fSmrg    darwinEvents_lock(); {
4674642e01fSmrg        num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button,
4684642e01fSmrg                                      POINTER_ABSOLUTE, 0, pDev==darwinTabletCurrent?5:2, valuators);
4696747b715Smrg        for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
4706747b715Smrg        if(num_events > 0) DarwinPokeEQ();
4714642e01fSmrg    } darwinEvents_unlock();
4724642e01fSmrg}
4734642e01fSmrg
4744642e01fSmrgvoid DarwinSendKeyboardEvents(int ev_type, int keycode) {
4754642e01fSmrg	int i, num_events;
4764642e01fSmrg
4774642e01fSmrg	if(!darwinEvents) {
4784642e01fSmrg		DEBUG_LOG("DarwinSendKeyboardEvents called before darwinEvents was initialized\n");
4794642e01fSmrg		return;
4804642e01fSmrg	}
4814642e01fSmrg
4824642e01fSmrg    darwinEvents_lock(); {
4834642e01fSmrg        num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE);
4846747b715Smrg        for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard, (InternalEvent*)darwinEvents[i].event);
4856747b715Smrg        if(num_events > 0) DarwinPokeEQ();
4864642e01fSmrg    } darwinEvents_unlock();
4874642e01fSmrg}
4884642e01fSmrg
4894642e01fSmrgvoid DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) {
4904642e01fSmrg	int i, num_events;
4914642e01fSmrg    ScreenPtr screen;
4924642e01fSmrg    DeviceIntPtr pDev = darwinTabletCurrent;
4934642e01fSmrg    int valuators[5];
4944642e01fSmrg
4954642e01fSmrg	DEBUG_LOG("DarwinSendProximityEvents(%d, %f, %f)\n", ev_type, pointer_x, pointer_y);
4964642e01fSmrg
4974642e01fSmrg	if(!darwinEvents) {
4984642e01fSmrg		DEBUG_LOG("DarwinSendProximityEvents called before darwinEvents was initialized\n");
4994642e01fSmrg		return;
5004642e01fSmrg	}
5014642e01fSmrg
5024642e01fSmrg    screen = miPointerGetScreen(pDev);
5034642e01fSmrg    if(!screen) {
5044642e01fSmrg        DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
5054642e01fSmrg        return;
5064642e01fSmrg    }
5074642e01fSmrg
5084642e01fSmrg    DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, 0.0f, 0.0f, 0.0f);
5094642e01fSmrg    darwinEvents_lock(); {
5104642e01fSmrg        num_events = GetProximityEvents(darwinEvents, pDev, ev_type,
5114642e01fSmrg                                        0, 5, valuators);
5126747b715Smrg        for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
5136747b715Smrg        if(num_events > 0) DarwinPokeEQ();
5144642e01fSmrg    } darwinEvents_unlock();
5154642e01fSmrg}
5164642e01fSmrg
5174642e01fSmrg
5184642e01fSmrg/* Send the appropriate number of button clicks to emulate scroll wheel */
5194642e01fSmrgvoid DarwinSendScrollEvents(float count_x, float count_y,
5204642e01fSmrg							float pointer_x, float pointer_y,
5214642e01fSmrg			    			float pressure, float tilt_x, float tilt_y) {
5226747b715Smrg	int sign_x, sign_y;
5234642e01fSmrg	if(!darwinEvents) {
5244642e01fSmrg		DEBUG_LOG("DarwinSendScrollEvents called before darwinEvents was initialized\n");
5254642e01fSmrg		return;
5264642e01fSmrg	}
5274642e01fSmrg
5286747b715Smrg	sign_x = count_x > 0.0f ? SCROLLWHEELLEFTFAKE : SCROLLWHEELRIGHTFAKE;
5296747b715Smrg	sign_y = count_y > 0.0f ? SCROLLWHEELUPFAKE : SCROLLWHEELDOWNFAKE;
5304642e01fSmrg	count_x = fabs(count_x);
5314642e01fSmrg	count_y = fabs(count_y);
5324642e01fSmrg
5334642e01fSmrg	while ((count_x > 0.0f) || (count_y > 0.0f)) {
5344642e01fSmrg		if (count_x > 0.0f) {
5354642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5364642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5374642e01fSmrg			count_x = count_x - 1.0f;
5384642e01fSmrg		}
5394642e01fSmrg		if (count_y > 0.0f) {
5404642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5414642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5424642e01fSmrg			count_y = count_y - 1.0f;
5434642e01fSmrg		}
5444642e01fSmrg	}
5454642e01fSmrg}
5464642e01fSmrg
5474642e01fSmrg/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to
5484642e01fSmrg   reflect changing modifier flags (alt, control, meta, etc) */
5494642e01fSmrgvoid DarwinUpdateModKeys(int flags) {
5506747b715Smrg	DarwinUpdateModifiers(KeyRelease, darwin_all_modifier_flags & ~flags & darwin_x11_modifier_mask);
5516747b715Smrg	DarwinUpdateModifiers(KeyPress, ~darwin_all_modifier_flags & flags & darwin_x11_modifier_mask);
5526747b715Smrg	darwin_all_modifier_flags = flags;
5534642e01fSmrg}
5544642e01fSmrg
5554642e01fSmrg/*
5564642e01fSmrg * DarwinSendDDXEvent
5574642e01fSmrg *  Send the X server thread a message by placing it on the event queue.
5584642e01fSmrg */
5594642e01fSmrgvoid DarwinSendDDXEvent(int type, int argc, ...) {
5606747b715Smrg    XQuartzEvent e;
5616747b715Smrg    int i;
5624642e01fSmrg    va_list args;
5634642e01fSmrg
5646747b715Smrg    memset(&e, 0, sizeof(e));
5656747b715Smrg    e.header = ET_Internal;
5666747b715Smrg    e.type = ET_XQuartz;
5676747b715Smrg    e.length = sizeof(e);
5686747b715Smrg    e.time = GetTimeInMillis();
5696747b715Smrg    e.subtype = type;
5704642e01fSmrg
5716747b715Smrg    if (argc > 0 && argc < XQUARTZ_EVENT_MAXARGS) {
5724642e01fSmrg        va_start (args, argc);
5734642e01fSmrg        for (i = 0; i < argc; i++)
5746747b715Smrg            e.data[i] = (uint32_t) va_arg (args, uint32_t);
5754642e01fSmrg        va_end (args);
5764642e01fSmrg    }
5774642e01fSmrg
5784642e01fSmrg    darwinEvents_lock(); {
5796747b715Smrg        mieqEnqueue(NULL, (InternalEvent*)&e);
5804642e01fSmrg        DarwinPokeEQ();
5814642e01fSmrg    } darwinEvents_unlock();
5824642e01fSmrg}
583