darwinEvents.c revision 8223e2f2
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();
2828223e2f2Smrg
2836747b715Smrg            /* Update our RandR info */
2846747b715Smrg            QuartzRandRUpdateFakeModes(TRUE);
2856747b715Smrg            break;
2866747b715Smrg
2876747b715Smrg        default:
2886747b715Smrg            if(!QuartzModeEventHandler(screenNum, e, dev))
2896747b715Smrg                ErrorF("Unknown application defined event type %d.\n", e->subtype);
2906747b715Smrg    }
2914642e01fSmrg}
2924642e01fSmrg
2934642e01fSmrgvoid DarwinListenOnOpenFD(int fd) {
2944642e01fSmrg    ErrorF("DarwinListenOnOpenFD: %d\n", fd);
2954642e01fSmrg
2964642e01fSmrg    pthread_mutex_lock(&fd_add_lock);
2974642e01fSmrg    if(fd_add_count < FD_ADD_MAX)
2984642e01fSmrg        fd_add[fd_add_count++] = fd;
2994642e01fSmrg    else
3004642e01fSmrg        ErrorF("FD Addition buffer at max.  Dropping fd addition request.\n");
3014642e01fSmrg
3024642e01fSmrg    pthread_cond_broadcast(&fd_add_ready_cond);
3034642e01fSmrg    pthread_mutex_unlock(&fd_add_lock);
3044642e01fSmrg}
3054642e01fSmrg
3064642e01fSmrgstatic void DarwinProcessFDAdditionQueue_thread(void *args) {
3074642e01fSmrg    pthread_mutex_lock(&fd_add_lock);
3084642e01fSmrg    while(true) {
3094642e01fSmrg        while(fd_add_count) {
3104642e01fSmrg            DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1, fd_add[--fd_add_count]);
3114642e01fSmrg        }
3124642e01fSmrg        pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock);
3134642e01fSmrg    }
3144642e01fSmrg}
3154642e01fSmrg
3166747b715SmrgBool DarwinEQInit(void) {
3176747b715Smrg    int *p;
3186747b715Smrg
3196747b715Smrg    for(p=darwin_x11_modifier_mask_list, darwin_all_modifier_mask=0; *p; p++) {
3206747b715Smrg        darwin_x11_modifier_mask |= *p;
3216747b715Smrg    }
3224642e01fSmrg
3236747b715Smrg    for(p=darwin_all_modifier_mask_additions, darwin_all_modifier_mask= darwin_x11_modifier_mask; *p; p++) {
3246747b715Smrg        darwin_all_modifier_mask |= *p;
3254642e01fSmrg    }
3264642e01fSmrg
3276747b715Smrg    mieqInit();
3286747b715Smrg    mieqSetHandler(ET_XQuartz, DarwinEventHandler);
3294642e01fSmrg
3304642e01fSmrg    /* Note that this *could* cause a potential async issue, since we're checking
3314642e01fSmrg     * darwinEvents without holding the lock, but darwinEvents is only ever set
3324642e01fSmrg     * here, so I don't bother.
3334642e01fSmrg     */
3344642e01fSmrg    if (!darwinEvents) {
3354642e01fSmrg        darwinEvents = InitEventList(GetMaximumEventsNum());;
3364642e01fSmrg
3374642e01fSmrg        if (!darwinEvents)
3384642e01fSmrg            FatalError("Couldn't allocate event buffer\n");
3394642e01fSmrg
3404642e01fSmrg        darwinEvents_lock();
3414642e01fSmrg        pthread_cond_broadcast(&mieq_ready_cond);
3424642e01fSmrg        darwinEvents_unlock();
3434642e01fSmrg    }
3444642e01fSmrg
3454642e01fSmrg    if(!fd_add_tid)
3464642e01fSmrg        fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL);
3474642e01fSmrg
3484642e01fSmrg    return TRUE;
3494642e01fSmrg}
3504642e01fSmrg
3514642e01fSmrg/*
3524642e01fSmrg * ProcessInputEvents
3534642e01fSmrg *  Read and process events from the event queue until it is empty.
3544642e01fSmrg */
3554642e01fSmrgvoid ProcessInputEvents(void) {
3566747b715Smrg    char nullbyte;
3576747b715Smrg	int x = sizeof(nullbyte);
3584642e01fSmrg
3594642e01fSmrg    TA_SERVER();
3604642e01fSmrg
3614642e01fSmrg    mieqProcessInputEvents();
3624642e01fSmrg
3634642e01fSmrg    // Empty the signaling pipe
3646747b715Smrg    while (x == sizeof(nullbyte)) {
3656747b715Smrg      x = read(darwinEventReadFD, &nullbyte, sizeof(nullbyte));
3664642e01fSmrg    }
3674642e01fSmrg}
3684642e01fSmrg
3694642e01fSmrg/* Sends a null byte down darwinEventWriteFD, which will cause the
3704642e01fSmrg   Dispatch() event loop to check out event queue */
3714642e01fSmrgstatic void DarwinPokeEQ(void) {
3724642e01fSmrg	char nullbyte=0;
3734642e01fSmrg	//  <daniels> oh, i ... er ... christ.
3746747b715Smrg	write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte));
3754642e01fSmrg}
3764642e01fSmrg
3774642e01fSmrg/* Convert from Appkit pointer input values to X input values:
3784642e01fSmrg * Note: pointer_x and pointer_y are relative to the upper-left of primary
3794642e01fSmrg *       display.
3804642e01fSmrg */
3814642e01fSmrgstatic void DarwinPrepareValuators(DeviceIntPtr pDev, int *valuators, ScreenPtr screen,
3824642e01fSmrg                                   float pointer_x, float pointer_y,
3834642e01fSmrg                                   float pressure, float tilt_x, float tilt_y) {
3844642e01fSmrg    /* Fix offset between darwin and X screens */
3856747b715Smrg    pointer_x -= darwinMainScreenX + screen->x;
3866747b715Smrg    pointer_y -= darwinMainScreenY + screen->y;
3874642e01fSmrg
3884642e01fSmrg    if(pointer_x < 0.0)
3894642e01fSmrg        pointer_x = 0.0;
3904642e01fSmrg
3914642e01fSmrg    if(pointer_y < 0.0)
3924642e01fSmrg        pointer_y = 0.0;
3934642e01fSmrg
3944642e01fSmrg    if(pDev == darwinPointer) {
3954642e01fSmrg        valuators[0] = pointer_x;
3964642e01fSmrg        valuators[1] = pointer_y;
3974642e01fSmrg        valuators[2] = 0;
3984642e01fSmrg        valuators[3] = 0;
3994642e01fSmrg        valuators[4] = 0;
4004642e01fSmrg    } else {
4014642e01fSmrg        /* Setup our array of values */
4024642e01fSmrg        valuators[0] = XQUARTZ_VALUATOR_LIMIT * (pointer_x / (float)screenInfo.screens[0]->width);
4034642e01fSmrg        valuators[1] = XQUARTZ_VALUATOR_LIMIT * (pointer_y / (float)screenInfo.screens[0]->height);
4044642e01fSmrg        valuators[2] = XQUARTZ_VALUATOR_LIMIT * pressure;
4054642e01fSmrg        valuators[3] = XQUARTZ_VALUATOR_LIMIT * tilt_x;
4064642e01fSmrg        valuators[4] = XQUARTZ_VALUATOR_LIMIT * tilt_y;
4074642e01fSmrg    }
4084642e01fSmrg    //DEBUG_LOG("Pointer (%f, %f), Valuators: {%d,%d,%d,%d,%d}\n", pointer_x, pointer_y,
4094642e01fSmrg    //          valuators[0], valuators[1], valuators[2], valuators[3], valuators[4]);
4104642e01fSmrg}
4114642e01fSmrg
4124642e01fSmrgvoid DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, float pointer_x, float pointer_y,
4134642e01fSmrg			     float pressure, float tilt_x, float tilt_y) {
4144642e01fSmrg	static int darwinFakeMouseButtonDown = 0;
4154642e01fSmrg	int i, num_events;
4164642e01fSmrg    ScreenPtr screen;
4174642e01fSmrg    int valuators[5];
4184642e01fSmrg
4194642e01fSmrg    //DEBUG_LOG("x=%f, y=%f, p=%f, tx=%f, ty=%f\n", pointer_x, pointer_y, pressure, tilt_x, tilt_y);
4204642e01fSmrg
4214642e01fSmrg	if(!darwinEvents) {
4224642e01fSmrg		DEBUG_LOG("DarwinSendPointerEvents called before darwinEvents was initialized\n");
4234642e01fSmrg		return;
4244642e01fSmrg	}
4254642e01fSmrg
4264642e01fSmrg    screen = miPointerGetScreen(pDev);
4274642e01fSmrg    if(!screen) {
4284642e01fSmrg        DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
4294642e01fSmrg        return;
4304642e01fSmrg    }
4314642e01fSmrg
4324642e01fSmrg    /* Handle fake click */
4334642e01fSmrg	if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) {
4344642e01fSmrg        if(darwinFakeMouseButtonDown != 0) {
4354642e01fSmrg            /* We're currently "down" with another button, so release it first */
4364642e01fSmrg            DarwinSendPointerEvents(pDev, ButtonRelease, darwinFakeMouseButtonDown, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
4374642e01fSmrg            darwinFakeMouseButtonDown=0;
4384642e01fSmrg        }
4396747b715Smrg		if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
4404642e01fSmrg            ev_button = 2;
4414642e01fSmrg			darwinFakeMouseButtonDown = 2;
4426747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
4436747b715Smrg		} else if (darwin_all_modifier_flags & darwinFakeMouse3Mask) {
4444642e01fSmrg            ev_button = 3;
4454642e01fSmrg			darwinFakeMouseButtonDown = 3;
4466747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
4474642e01fSmrg		}
4484642e01fSmrg	}
4494642e01fSmrg
4504642e01fSmrg	if (ev_type == ButtonRelease && ev_button == 1) {
4514642e01fSmrg        if(darwinFakeMouseButtonDown) {
4524642e01fSmrg            ev_button = darwinFakeMouseButtonDown;
4534642e01fSmrg        }
4544642e01fSmrg
4554642e01fSmrg        if(darwinFakeMouseButtonDown == 2) {
4566747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
4574642e01fSmrg        } else if(darwinFakeMouseButtonDown == 3) {
4586747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
4594642e01fSmrg        }
4604642e01fSmrg
4614642e01fSmrg        darwinFakeMouseButtonDown = 0;
4624642e01fSmrg	}
4634642e01fSmrg
4644642e01fSmrg    DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
4654642e01fSmrg    darwinEvents_lock(); {
4664642e01fSmrg        num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button,
4674642e01fSmrg                                      POINTER_ABSOLUTE, 0, pDev==darwinTabletCurrent?5:2, valuators);
4686747b715Smrg        for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
4696747b715Smrg        if(num_events > 0) DarwinPokeEQ();
4704642e01fSmrg    } darwinEvents_unlock();
4714642e01fSmrg}
4724642e01fSmrg
4734642e01fSmrgvoid DarwinSendKeyboardEvents(int ev_type, int keycode) {
4744642e01fSmrg	int i, num_events;
4754642e01fSmrg
4764642e01fSmrg	if(!darwinEvents) {
4774642e01fSmrg		DEBUG_LOG("DarwinSendKeyboardEvents called before darwinEvents was initialized\n");
4784642e01fSmrg		return;
4794642e01fSmrg	}
4804642e01fSmrg
4814642e01fSmrg    darwinEvents_lock(); {
4824642e01fSmrg        num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE);
4836747b715Smrg        for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard, (InternalEvent*)darwinEvents[i].event);
4846747b715Smrg        if(num_events > 0) DarwinPokeEQ();
4854642e01fSmrg    } darwinEvents_unlock();
4864642e01fSmrg}
4874642e01fSmrg
4884642e01fSmrgvoid DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) {
4894642e01fSmrg	int i, num_events;
4904642e01fSmrg    ScreenPtr screen;
4914642e01fSmrg    DeviceIntPtr pDev = darwinTabletCurrent;
4924642e01fSmrg    int valuators[5];
4934642e01fSmrg
4944642e01fSmrg	DEBUG_LOG("DarwinSendProximityEvents(%d, %f, %f)\n", ev_type, pointer_x, pointer_y);
4954642e01fSmrg
4964642e01fSmrg	if(!darwinEvents) {
4974642e01fSmrg		DEBUG_LOG("DarwinSendProximityEvents called before darwinEvents was initialized\n");
4984642e01fSmrg		return;
4994642e01fSmrg	}
5004642e01fSmrg
5014642e01fSmrg    screen = miPointerGetScreen(pDev);
5024642e01fSmrg    if(!screen) {
5034642e01fSmrg        DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
5044642e01fSmrg        return;
5054642e01fSmrg    }
5064642e01fSmrg
5074642e01fSmrg    DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, 0.0f, 0.0f, 0.0f);
5084642e01fSmrg    darwinEvents_lock(); {
5094642e01fSmrg        num_events = GetProximityEvents(darwinEvents, pDev, ev_type,
5104642e01fSmrg                                        0, 5, valuators);
5116747b715Smrg        for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
5126747b715Smrg        if(num_events > 0) DarwinPokeEQ();
5134642e01fSmrg    } darwinEvents_unlock();
5144642e01fSmrg}
5154642e01fSmrg
5164642e01fSmrg
5174642e01fSmrg/* Send the appropriate number of button clicks to emulate scroll wheel */
5184642e01fSmrgvoid DarwinSendScrollEvents(float count_x, float count_y,
5194642e01fSmrg							float pointer_x, float pointer_y,
5204642e01fSmrg			    			float pressure, float tilt_x, float tilt_y) {
5216747b715Smrg	int sign_x, sign_y;
5224642e01fSmrg	if(!darwinEvents) {
5234642e01fSmrg		DEBUG_LOG("DarwinSendScrollEvents called before darwinEvents was initialized\n");
5244642e01fSmrg		return;
5254642e01fSmrg	}
5264642e01fSmrg
5276747b715Smrg	sign_x = count_x > 0.0f ? SCROLLWHEELLEFTFAKE : SCROLLWHEELRIGHTFAKE;
5286747b715Smrg	sign_y = count_y > 0.0f ? SCROLLWHEELUPFAKE : SCROLLWHEELDOWNFAKE;
5294642e01fSmrg	count_x = fabs(count_x);
5304642e01fSmrg	count_y = fabs(count_y);
5314642e01fSmrg
5324642e01fSmrg	while ((count_x > 0.0f) || (count_y > 0.0f)) {
5334642e01fSmrg		if (count_x > 0.0f) {
5344642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5354642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5364642e01fSmrg			count_x = count_x - 1.0f;
5374642e01fSmrg		}
5384642e01fSmrg		if (count_y > 0.0f) {
5394642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5404642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5414642e01fSmrg			count_y = count_y - 1.0f;
5424642e01fSmrg		}
5434642e01fSmrg	}
5444642e01fSmrg}
5454642e01fSmrg
5464642e01fSmrg/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to
5474642e01fSmrg   reflect changing modifier flags (alt, control, meta, etc) */
5484642e01fSmrgvoid DarwinUpdateModKeys(int flags) {
5496747b715Smrg	DarwinUpdateModifiers(KeyRelease, darwin_all_modifier_flags & ~flags & darwin_x11_modifier_mask);
5506747b715Smrg	DarwinUpdateModifiers(KeyPress, ~darwin_all_modifier_flags & flags & darwin_x11_modifier_mask);
5516747b715Smrg	darwin_all_modifier_flags = flags;
5524642e01fSmrg}
5534642e01fSmrg
5544642e01fSmrg/*
5554642e01fSmrg * DarwinSendDDXEvent
5564642e01fSmrg *  Send the X server thread a message by placing it on the event queue.
5574642e01fSmrg */
5584642e01fSmrgvoid DarwinSendDDXEvent(int type, int argc, ...) {
5596747b715Smrg    XQuartzEvent e;
5606747b715Smrg    int i;
5614642e01fSmrg    va_list args;
5624642e01fSmrg
5636747b715Smrg    memset(&e, 0, sizeof(e));
5646747b715Smrg    e.header = ET_Internal;
5656747b715Smrg    e.type = ET_XQuartz;
5666747b715Smrg    e.length = sizeof(e);
5676747b715Smrg    e.time = GetTimeInMillis();
5686747b715Smrg    e.subtype = type;
5694642e01fSmrg
5706747b715Smrg    if (argc > 0 && argc < XQUARTZ_EVENT_MAXARGS) {
5714642e01fSmrg        va_start (args, argc);
5724642e01fSmrg        for (i = 0; i < argc; i++)
5736747b715Smrg            e.data[i] = (uint32_t) va_arg (args, uint32_t);
5744642e01fSmrg        va_end (args);
5754642e01fSmrg    }
5764642e01fSmrg
5774642e01fSmrg    darwinEvents_lock(); {
5786747b715Smrg        mieqEnqueue(NULL, (InternalEvent*)&e);
5794642e01fSmrg        DarwinPokeEQ();
5804642e01fSmrg    } darwinEvents_unlock();
5814642e01fSmrg}
582