darwinEvents.c revision 9ace9065
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"
469ace9065Smrg#include   "inpututils.h"
476747b715Smrg#include   "eventstr.h"
484642e01fSmrg#include   "mi.h"
494642e01fSmrg#include   "scrnintstr.h"
504642e01fSmrg#include   "mipointer.h"
514642e01fSmrg#include   "os.h"
524642e01fSmrg
534642e01fSmrg#include "darwin.h"
544642e01fSmrg#include "quartz.h"
554642e01fSmrg#include "quartzKeyboard.h"
566747b715Smrg#include "quartzRandR.h"
574642e01fSmrg#include "darwinEvents.h"
584642e01fSmrg
594642e01fSmrg#include <sys/types.h>
604642e01fSmrg#include <sys/uio.h>
614642e01fSmrg#include <unistd.h>
624642e01fSmrg#include <pthread.h>
634642e01fSmrg#include <errno.h>
649ace9065Smrg#include <time.h>
654642e01fSmrg
664642e01fSmrg#include <IOKit/hidsystem/IOLLEvent.h>
674642e01fSmrg
684642e01fSmrg/* Fake button press/release for scroll wheel move. */
694642e01fSmrg#define SCROLLWHEELUPFAKE    4
704642e01fSmrg#define SCROLLWHEELDOWNFAKE  5
714642e01fSmrg#define SCROLLWHEELLEFTFAKE  6
724642e01fSmrg#define SCROLLWHEELRIGHTFAKE 7
734642e01fSmrg
746747b715Smrg#include <X11/extensions/applewmconst.h>
754642e01fSmrg#include "applewmExt.h"
764642e01fSmrg
774642e01fSmrg/* FIXME: Abstract this better */
786747b715Smrgextern Bool QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev);
794642e01fSmrg
806747b715Smrgint darwin_all_modifier_flags = 0;  // last known modifier state
816747b715Smrgint darwin_all_modifier_mask = 0;
826747b715Smrgint darwin_x11_modifier_mask = 0;
834642e01fSmrg
844642e01fSmrg#define FD_ADD_MAX 128
854642e01fSmrgstatic int fd_add[FD_ADD_MAX];
864642e01fSmrgint fd_add_count = 0;
874642e01fSmrgstatic pthread_mutex_t fd_add_lock = PTHREAD_MUTEX_INITIALIZER;
884642e01fSmrgstatic pthread_cond_t fd_add_ready_cond = PTHREAD_COND_INITIALIZER;
894642e01fSmrgstatic pthread_t fd_add_tid = NULL;
904642e01fSmrg
916747b715Smrgstatic EventListPtr darwinEvents = NULL;
924642e01fSmrg
934642e01fSmrgstatic pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER;
944642e01fSmrgstatic pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER;
954642e01fSmrg
964642e01fSmrg/*** Pthread Magics ***/
979ace9065Smrgstatic pthread_t create_thread(void *(*func)(void *), void *arg) {
984642e01fSmrg    pthread_attr_t attr;
994642e01fSmrg    pthread_t tid;
1004642e01fSmrg
1014642e01fSmrg    pthread_attr_init (&attr);
1024642e01fSmrg    pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
1034642e01fSmrg    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
1044642e01fSmrg    pthread_create (&tid, &attr, func, arg);
1054642e01fSmrg    pthread_attr_destroy (&attr);
1064642e01fSmrg
1074642e01fSmrg    return tid;
1084642e01fSmrg}
1094642e01fSmrg
1104642e01fSmrgvoid darwinEvents_lock(void);
1114642e01fSmrgvoid darwinEvents_lock(void) {
1124642e01fSmrg    int err;
1134642e01fSmrg    if((err = pthread_mutex_lock(&mieq_lock))) {
1144642e01fSmrg        ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n",
1154642e01fSmrg               __FILE__, __FUNCTION__, __LINE__, err);
1164642e01fSmrg        spewCallStack();
1174642e01fSmrg    }
1184642e01fSmrg    if(darwinEvents == NULL) {
1194642e01fSmrg        pthread_cond_wait(&mieq_ready_cond, &mieq_lock);
1204642e01fSmrg    }
1214642e01fSmrg}
1224642e01fSmrg
1234642e01fSmrgvoid darwinEvents_unlock(void);
1244642e01fSmrgvoid darwinEvents_unlock(void) {
1254642e01fSmrg    int err;
1264642e01fSmrg    if((err = pthread_mutex_unlock(&mieq_lock))) {
1274642e01fSmrg        ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n",
1284642e01fSmrg               __FILE__, __FUNCTION__, __LINE__, err);
1294642e01fSmrg        spewCallStack();
1304642e01fSmrg    }
1314642e01fSmrg}
1324642e01fSmrg
1334642e01fSmrg/*
1344642e01fSmrg * DarwinPressModifierKey
1354642e01fSmrg * Press or release the given modifier key (one of NX_MODIFIERKEY_* constants)
1364642e01fSmrg */
1374642e01fSmrgstatic void DarwinPressModifierKey(int pressed, int key) {
1384642e01fSmrg    int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
1394642e01fSmrg
1404642e01fSmrg    if (keycode == 0) {
1414642e01fSmrg        ErrorF("DarwinPressModifierKey bad keycode: key=%d\n", key);
1424642e01fSmrg        return;
1434642e01fSmrg    }
1444642e01fSmrg
1454642e01fSmrg    DarwinSendKeyboardEvents(pressed, keycode);
1464642e01fSmrg}
1474642e01fSmrg
1484642e01fSmrg/*
1494642e01fSmrg * DarwinUpdateModifiers
1504642e01fSmrg *  Send events to update the modifier state.
1514642e01fSmrg */
1524642e01fSmrg
1536747b715Smrgstatic int darwin_x11_modifier_mask_list[] = {
1544642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK
1554642e01fSmrg    NX_DEVICELCTLKEYMASK, NX_DEVICERCTLKEYMASK,
1564642e01fSmrg    NX_DEVICELSHIFTKEYMASK, NX_DEVICERSHIFTKEYMASK,
1574642e01fSmrg    NX_DEVICELCMDKEYMASK, NX_DEVICERCMDKEYMASK,
1584642e01fSmrg    NX_DEVICELALTKEYMASK, NX_DEVICERALTKEYMASK,
1594642e01fSmrg#else
1604642e01fSmrg    NX_CONTROLMASK, NX_SHIFTMASK, NX_COMMANDMASK, NX_ALTERNATEMASK,
1614642e01fSmrg#endif
1624642e01fSmrg    NX_ALPHASHIFTMASK,
1634642e01fSmrg    0
1644642e01fSmrg};
1654642e01fSmrg
1666747b715Smrgstatic int darwin_all_modifier_mask_additions[] = { NX_SECONDARYFNMASK, };
1676747b715Smrg
1684642e01fSmrgstatic void DarwinUpdateModifiers(
1694642e01fSmrg    int pressed,        // KeyPress or KeyRelease
1704642e01fSmrg    int flags )         // modifier flags that have changed
1714642e01fSmrg{
1724642e01fSmrg    int *f;
1734642e01fSmrg    int key;
1744642e01fSmrg
1754642e01fSmrg    /* Capslock is special.  This mask is the state of capslock (on/off),
1764642e01fSmrg     * not the state of the button.  Hopefully we can find a better solution.
1774642e01fSmrg     */
1784642e01fSmrg    if(NX_ALPHASHIFTMASK & flags) {
1794642e01fSmrg        DarwinPressModifierKey(KeyPress, NX_MODIFIERKEY_ALPHALOCK);
1804642e01fSmrg        DarwinPressModifierKey(KeyRelease, NX_MODIFIERKEY_ALPHALOCK);
1814642e01fSmrg    }
1824642e01fSmrg
1836747b715Smrg    for(f=darwin_x11_modifier_mask_list; *f; f++)
1844642e01fSmrg        if(*f & flags && *f != NX_ALPHASHIFTMASK) {
1854642e01fSmrg            key = DarwinModifierNXMaskToNXKey(*f);
1864642e01fSmrg            if(key == -1)
1874642e01fSmrg                ErrorF("DarwinUpdateModifiers: Unsupported NXMask: 0x%x\n", *f);
1884642e01fSmrg            else
1894642e01fSmrg                DarwinPressModifierKey(pressed, key);
1904642e01fSmrg        }
1914642e01fSmrg}
1924642e01fSmrg
1934642e01fSmrg/* Generic handler for Xquartz-specifc events.  When possible, these should
1944642e01fSmrg   be moved into their own individual functions and set as handlers using
1954642e01fSmrg   mieqSetHandler. */
1964642e01fSmrg
1976747b715Smrgstatic void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr dev) {
1986747b715Smrg    XQuartzEvent *e = &(ie->xquartz_event);
1996747b715Smrg
2004642e01fSmrg    TA_SERVER();
2014642e01fSmrg
2026747b715Smrg    switch(e->subtype) {
2036747b715Smrg        case kXquartzControllerNotify:
2046747b715Smrg            DEBUG_LOG("kXquartzControllerNotify\n");
2056747b715Smrg            AppleWMSendEvent(AppleWMControllerNotify,
2066747b715Smrg                             AppleWMControllerNotifyMask,
2076747b715Smrg                             e->data[0],
2086747b715Smrg                             e->data[1]);
2096747b715Smrg            break;
2106747b715Smrg
2116747b715Smrg        case kXquartzPasteboardNotify:
2126747b715Smrg            DEBUG_LOG("kXquartzPasteboardNotify\n");
2136747b715Smrg            AppleWMSendEvent(AppleWMPasteboardNotify,
2146747b715Smrg                             AppleWMPasteboardNotifyMask,
2156747b715Smrg                             e->data[0],
2166747b715Smrg                             e->data[1]);
2176747b715Smrg            break;
2186747b715Smrg
2196747b715Smrg        case kXquartzActivate:
2206747b715Smrg            DEBUG_LOG("kXquartzActivate\n");
2216747b715Smrg            QuartzShow();
2226747b715Smrg            AppleWMSendEvent(AppleWMActivationNotify,
2236747b715Smrg                             AppleWMActivationNotifyMask,
2246747b715Smrg                             AppleWMIsActive, 0);
2256747b715Smrg            break;
2266747b715Smrg
2276747b715Smrg        case kXquartzDeactivate:
2286747b715Smrg            DEBUG_LOG("kXquartzDeactivate\n");
2296747b715Smrg            AppleWMSendEvent(AppleWMActivationNotify,
2306747b715Smrg                             AppleWMActivationNotifyMask,
2316747b715Smrg                             AppleWMIsInactive, 0);
2326747b715Smrg            QuartzHide();
2336747b715Smrg            break;
2346747b715Smrg
2356747b715Smrg        case kXquartzReloadPreferences:
2366747b715Smrg            DEBUG_LOG("kXquartzReloadPreferences\n");
2376747b715Smrg            AppleWMSendEvent(AppleWMActivationNotify,
2386747b715Smrg                             AppleWMActivationNotifyMask,
2396747b715Smrg                             AppleWMReloadPreferences, 0);
2406747b715Smrg            break;
2416747b715Smrg
2426747b715Smrg        case kXquartzToggleFullscreen:
2436747b715Smrg            DEBUG_LOG("kXquartzToggleFullscreen\n");
2446747b715Smrg            if(XQuartzIsRootless)
2456747b715Smrg                ErrorF("Ignoring kXquartzToggleFullscreen because of rootless mode.");
2466747b715Smrg            else
2476747b715Smrg                QuartzRandRToggleFullscreen();
2486747b715Smrg            break;
2496747b715Smrg
2506747b715Smrg        case kXquartzSetRootless:
2516747b715Smrg            DEBUG_LOG("kXquartzSetRootless\n");
2526747b715Smrg            if(e->data[0]) {
2536747b715Smrg                QuartzRandRSetFakeRootless();
2546747b715Smrg            } else {
2556747b715Smrg                QuartzRandRSetFakeFullscreen(FALSE);
2566747b715Smrg            }
2576747b715Smrg            break;
2586747b715Smrg
2596747b715Smrg        case kXquartzSetRootClip:
2606747b715Smrg            QuartzSetRootClip((Bool)e->data[0]);
2616747b715Smrg            break;
2626747b715Smrg
2636747b715Smrg        case kXquartzQuit:
2646747b715Smrg            GiveUp(0);
2656747b715Smrg            break;
2666747b715Smrg
2676747b715Smrg        case kXquartzSpaceChanged:
2686747b715Smrg            DEBUG_LOG("kXquartzSpaceChanged\n");
2696747b715Smrg            QuartzSpaceChanged(e->data[0]);
2706747b715Smrg            break;
2716747b715Smrg
2726747b715Smrg        case kXquartzListenOnOpenFD:
2736747b715Smrg            ErrorF("Calling ListenOnOpenFD() for new fd: %d\n", (int)e->data[0]);
2746747b715Smrg            ListenOnOpenFD((int)e->data[0], 1);
2756747b715Smrg            break;
2766747b715Smrg
2776747b715Smrg        case kXquartzReloadKeymap:
2786747b715Smrg            DarwinKeyboardReloadHandler();
2796747b715Smrg            break;
2806747b715Smrg
2816747b715Smrg        case kXquartzDisplayChanged:
2826747b715Smrg            DEBUG_LOG("kXquartzDisplayChanged\n");
2836747b715Smrg            QuartzUpdateScreens();
2848223e2f2Smrg
2856747b715Smrg            /* Update our RandR info */
2866747b715Smrg            QuartzRandRUpdateFakeModes(TRUE);
2876747b715Smrg            break;
2886747b715Smrg
2896747b715Smrg        default:
2906747b715Smrg            if(!QuartzModeEventHandler(screenNum, e, dev))
2916747b715Smrg                ErrorF("Unknown application defined event type %d.\n", e->subtype);
2926747b715Smrg    }
2934642e01fSmrg}
2944642e01fSmrg
2954642e01fSmrgvoid DarwinListenOnOpenFD(int fd) {
2964642e01fSmrg    ErrorF("DarwinListenOnOpenFD: %d\n", fd);
2974642e01fSmrg
2984642e01fSmrg    pthread_mutex_lock(&fd_add_lock);
2994642e01fSmrg    if(fd_add_count < FD_ADD_MAX)
3004642e01fSmrg        fd_add[fd_add_count++] = fd;
3014642e01fSmrg    else
3024642e01fSmrg        ErrorF("FD Addition buffer at max.  Dropping fd addition request.\n");
3034642e01fSmrg
3044642e01fSmrg    pthread_cond_broadcast(&fd_add_ready_cond);
3054642e01fSmrg    pthread_mutex_unlock(&fd_add_lock);
3064642e01fSmrg}
3074642e01fSmrg
3089ace9065Smrgstatic void *DarwinProcessFDAdditionQueue_thread(void *args) {
3099ace9065Smrg    /* TODO: Possibly adjust this to no longer be a race... maybe trigger this
3109ace9065Smrg     *       once a client connects and claims to be the WM.
3119ace9065Smrg     *
3129ace9065Smrg     * From ajax:
3139ace9065Smrg     * There's already an internal callback chain for setting selection [in 1.5]
3149ace9065Smrg     * ownership.  See the CallSelectionCallback at the bottom of
3159ace9065Smrg     * ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook
3169ace9065Smrg     * into it.
3179ace9065Smrg     */
3189ace9065Smrg
3199ace9065Smrg    struct timespec sleep_for;
3209ace9065Smrg    struct timespec sleep_remaining;
3219ace9065Smrg
3229ace9065Smrg    sleep_for.tv_sec = 3;
3239ace9065Smrg    sleep_for.tv_nsec = 0;
3249ace9065Smrg
3259ace9065Smrg    ErrorF("X11.app: DarwinProcessFDAdditionQueue_thread: Sleeping to allow xinitrc to catchup.\n");
3269ace9065Smrg    while(nanosleep(&sleep_for, &sleep_remaining) != 0) {
3279ace9065Smrg        sleep_for = sleep_remaining;
3289ace9065Smrg    }
3299ace9065Smrg
3304642e01fSmrg    pthread_mutex_lock(&fd_add_lock);
3314642e01fSmrg    while(true) {
3324642e01fSmrg        while(fd_add_count) {
3334642e01fSmrg            DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1, fd_add[--fd_add_count]);
3344642e01fSmrg        }
3354642e01fSmrg        pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock);
3364642e01fSmrg    }
3379ace9065Smrg
3389ace9065Smrg    return NULL;
3394642e01fSmrg}
3404642e01fSmrg
3416747b715SmrgBool DarwinEQInit(void) {
3426747b715Smrg    int *p;
3436747b715Smrg
3446747b715Smrg    for(p=darwin_x11_modifier_mask_list, darwin_all_modifier_mask=0; *p; p++) {
3456747b715Smrg        darwin_x11_modifier_mask |= *p;
3466747b715Smrg    }
3474642e01fSmrg
3486747b715Smrg    for(p=darwin_all_modifier_mask_additions, darwin_all_modifier_mask= darwin_x11_modifier_mask; *p; p++) {
3496747b715Smrg        darwin_all_modifier_mask |= *p;
3504642e01fSmrg    }
3514642e01fSmrg
3526747b715Smrg    mieqInit();
3536747b715Smrg    mieqSetHandler(ET_XQuartz, DarwinEventHandler);
3544642e01fSmrg
3554642e01fSmrg    /* Note that this *could* cause a potential async issue, since we're checking
3564642e01fSmrg     * darwinEvents without holding the lock, but darwinEvents is only ever set
3574642e01fSmrg     * here, so I don't bother.
3584642e01fSmrg     */
3594642e01fSmrg    if (!darwinEvents) {
3604642e01fSmrg        darwinEvents = InitEventList(GetMaximumEventsNum());;
3614642e01fSmrg
3624642e01fSmrg        if (!darwinEvents)
3634642e01fSmrg            FatalError("Couldn't allocate event buffer\n");
3644642e01fSmrg
3654642e01fSmrg        darwinEvents_lock();
3664642e01fSmrg        pthread_cond_broadcast(&mieq_ready_cond);
3674642e01fSmrg        darwinEvents_unlock();
3684642e01fSmrg    }
3694642e01fSmrg
3704642e01fSmrg    if(!fd_add_tid)
3714642e01fSmrg        fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL);
3724642e01fSmrg
3734642e01fSmrg    return TRUE;
3744642e01fSmrg}
3754642e01fSmrg
3764642e01fSmrg/*
3774642e01fSmrg * ProcessInputEvents
3784642e01fSmrg *  Read and process events from the event queue until it is empty.
3794642e01fSmrg */
3804642e01fSmrgvoid ProcessInputEvents(void) {
3816747b715Smrg    char nullbyte;
3826747b715Smrg	int x = sizeof(nullbyte);
3834642e01fSmrg
3844642e01fSmrg    TA_SERVER();
3854642e01fSmrg
3864642e01fSmrg    mieqProcessInputEvents();
3874642e01fSmrg
3884642e01fSmrg    // Empty the signaling pipe
3896747b715Smrg    while (x == sizeof(nullbyte)) {
3906747b715Smrg      x = read(darwinEventReadFD, &nullbyte, sizeof(nullbyte));
3914642e01fSmrg    }
3924642e01fSmrg}
3934642e01fSmrg
3944642e01fSmrg/* Sends a null byte down darwinEventWriteFD, which will cause the
3954642e01fSmrg   Dispatch() event loop to check out event queue */
3964642e01fSmrgstatic void DarwinPokeEQ(void) {
3974642e01fSmrg	char nullbyte=0;
3984642e01fSmrg	//  <daniels> oh, i ... er ... christ.
3996747b715Smrg	write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte));
4004642e01fSmrg}
4014642e01fSmrg
4024642e01fSmrg/* Convert from Appkit pointer input values to X input values:
4034642e01fSmrg * Note: pointer_x and pointer_y are relative to the upper-left of primary
4044642e01fSmrg *       display.
4054642e01fSmrg */
4064642e01fSmrgstatic void DarwinPrepareValuators(DeviceIntPtr pDev, int *valuators, ScreenPtr screen,
4074642e01fSmrg                                   float pointer_x, float pointer_y,
4084642e01fSmrg                                   float pressure, float tilt_x, float tilt_y) {
4094642e01fSmrg    /* Fix offset between darwin and X screens */
4106747b715Smrg    pointer_x -= darwinMainScreenX + screen->x;
4116747b715Smrg    pointer_y -= darwinMainScreenY + screen->y;
4124642e01fSmrg
4134642e01fSmrg    if(pointer_x < 0.0)
4144642e01fSmrg        pointer_x = 0.0;
4154642e01fSmrg
4164642e01fSmrg    if(pointer_y < 0.0)
4174642e01fSmrg        pointer_y = 0.0;
4184642e01fSmrg
4194642e01fSmrg    if(pDev == darwinPointer) {
4204642e01fSmrg        valuators[0] = pointer_x;
4214642e01fSmrg        valuators[1] = pointer_y;
4224642e01fSmrg        valuators[2] = 0;
4234642e01fSmrg        valuators[3] = 0;
4244642e01fSmrg        valuators[4] = 0;
4254642e01fSmrg    } else {
4264642e01fSmrg        /* Setup our array of values */
4274642e01fSmrg        valuators[0] = XQUARTZ_VALUATOR_LIMIT * (pointer_x / (float)screenInfo.screens[0]->width);
4284642e01fSmrg        valuators[1] = XQUARTZ_VALUATOR_LIMIT * (pointer_y / (float)screenInfo.screens[0]->height);
4294642e01fSmrg        valuators[2] = XQUARTZ_VALUATOR_LIMIT * pressure;
4304642e01fSmrg        valuators[3] = XQUARTZ_VALUATOR_LIMIT * tilt_x;
4314642e01fSmrg        valuators[4] = XQUARTZ_VALUATOR_LIMIT * tilt_y;
4324642e01fSmrg    }
4334642e01fSmrg    //DEBUG_LOG("Pointer (%f, %f), Valuators: {%d,%d,%d,%d,%d}\n", pointer_x, pointer_y,
4344642e01fSmrg    //          valuators[0], valuators[1], valuators[2], valuators[3], valuators[4]);
4354642e01fSmrg}
4364642e01fSmrg
4374642e01fSmrgvoid DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, float pointer_x, float pointer_y,
4384642e01fSmrg			     float pressure, float tilt_x, float tilt_y) {
4394642e01fSmrg	static int darwinFakeMouseButtonDown = 0;
4404642e01fSmrg	int i, num_events;
4414642e01fSmrg    ScreenPtr screen;
4424642e01fSmrg    int valuators[5];
4434642e01fSmrg
4444642e01fSmrg    //DEBUG_LOG("x=%f, y=%f, p=%f, tx=%f, ty=%f\n", pointer_x, pointer_y, pressure, tilt_x, tilt_y);
4454642e01fSmrg
4464642e01fSmrg	if(!darwinEvents) {
4474642e01fSmrg		DEBUG_LOG("DarwinSendPointerEvents called before darwinEvents was initialized\n");
4484642e01fSmrg		return;
4494642e01fSmrg	}
4504642e01fSmrg
4514642e01fSmrg    screen = miPointerGetScreen(pDev);
4524642e01fSmrg    if(!screen) {
4534642e01fSmrg        DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
4544642e01fSmrg        return;
4554642e01fSmrg    }
4564642e01fSmrg
4574642e01fSmrg    /* Handle fake click */
4584642e01fSmrg	if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) {
4594642e01fSmrg        if(darwinFakeMouseButtonDown != 0) {
4604642e01fSmrg            /* We're currently "down" with another button, so release it first */
4614642e01fSmrg            DarwinSendPointerEvents(pDev, ButtonRelease, darwinFakeMouseButtonDown, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
4624642e01fSmrg            darwinFakeMouseButtonDown=0;
4634642e01fSmrg        }
4646747b715Smrg		if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
4654642e01fSmrg            ev_button = 2;
4664642e01fSmrg			darwinFakeMouseButtonDown = 2;
4676747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
4686747b715Smrg		} else if (darwin_all_modifier_flags & darwinFakeMouse3Mask) {
4694642e01fSmrg            ev_button = 3;
4704642e01fSmrg			darwinFakeMouseButtonDown = 3;
4716747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
4724642e01fSmrg		}
4734642e01fSmrg	}
4744642e01fSmrg
4754642e01fSmrg	if (ev_type == ButtonRelease && ev_button == 1) {
4764642e01fSmrg        if(darwinFakeMouseButtonDown) {
4774642e01fSmrg            ev_button = darwinFakeMouseButtonDown;
4784642e01fSmrg        }
4794642e01fSmrg
4804642e01fSmrg        if(darwinFakeMouseButtonDown == 2) {
4816747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
4824642e01fSmrg        } else if(darwinFakeMouseButtonDown == 3) {
4836747b715Smrg            DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
4844642e01fSmrg        }
4854642e01fSmrg
4864642e01fSmrg        darwinFakeMouseButtonDown = 0;
4874642e01fSmrg	}
4884642e01fSmrg
4894642e01fSmrg    DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
4904642e01fSmrg    darwinEvents_lock(); {
4919ace9065Smrg        ValuatorMask mask;
4929ace9065Smrg        valuator_mask_set_range(&mask, 0, (pDev == darwinTabletCurrent) ? 5 : 2, valuators);
4934642e01fSmrg        num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button,
4949ace9065Smrg                                      POINTER_ABSOLUTE, &mask);
4956747b715Smrg        for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
4966747b715Smrg        if(num_events > 0) DarwinPokeEQ();
4974642e01fSmrg    } darwinEvents_unlock();
4984642e01fSmrg}
4994642e01fSmrg
5004642e01fSmrgvoid DarwinSendKeyboardEvents(int ev_type, int keycode) {
5014642e01fSmrg	int i, num_events;
5024642e01fSmrg
5034642e01fSmrg	if(!darwinEvents) {
5044642e01fSmrg		DEBUG_LOG("DarwinSendKeyboardEvents called before darwinEvents was initialized\n");
5054642e01fSmrg		return;
5064642e01fSmrg	}
5074642e01fSmrg
5084642e01fSmrg    darwinEvents_lock(); {
5094642e01fSmrg        num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE);
5106747b715Smrg        for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard, (InternalEvent*)darwinEvents[i].event);
5116747b715Smrg        if(num_events > 0) DarwinPokeEQ();
5124642e01fSmrg    } darwinEvents_unlock();
5134642e01fSmrg}
5144642e01fSmrg
5154642e01fSmrgvoid DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) {
5164642e01fSmrg	int i, num_events;
5174642e01fSmrg    ScreenPtr screen;
5184642e01fSmrg    DeviceIntPtr pDev = darwinTabletCurrent;
5194642e01fSmrg    int valuators[5];
5204642e01fSmrg
5214642e01fSmrg	DEBUG_LOG("DarwinSendProximityEvents(%d, %f, %f)\n", ev_type, pointer_x, pointer_y);
5224642e01fSmrg
5234642e01fSmrg	if(!darwinEvents) {
5244642e01fSmrg		DEBUG_LOG("DarwinSendProximityEvents called before darwinEvents was initialized\n");
5254642e01fSmrg		return;
5264642e01fSmrg	}
5274642e01fSmrg
5284642e01fSmrg    screen = miPointerGetScreen(pDev);
5294642e01fSmrg    if(!screen) {
5304642e01fSmrg        DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
5314642e01fSmrg        return;
5324642e01fSmrg    }
5334642e01fSmrg
5344642e01fSmrg    DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, 0.0f, 0.0f, 0.0f);
5354642e01fSmrg    darwinEvents_lock(); {
5369ace9065Smrg        ValuatorMask mask;
5379ace9065Smrg        valuator_mask_set_range(&mask, 0, 5, valuators);
5389ace9065Smrg        num_events = GetProximityEvents(darwinEvents, pDev, ev_type, &mask);
5396747b715Smrg        for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
5406747b715Smrg        if(num_events > 0) DarwinPokeEQ();
5414642e01fSmrg    } darwinEvents_unlock();
5424642e01fSmrg}
5434642e01fSmrg
5444642e01fSmrg
5454642e01fSmrg/* Send the appropriate number of button clicks to emulate scroll wheel */
5464642e01fSmrgvoid DarwinSendScrollEvents(float count_x, float count_y,
5474642e01fSmrg							float pointer_x, float pointer_y,
5484642e01fSmrg			    			float pressure, float tilt_x, float tilt_y) {
5496747b715Smrg	int sign_x, sign_y;
5504642e01fSmrg	if(!darwinEvents) {
5514642e01fSmrg		DEBUG_LOG("DarwinSendScrollEvents called before darwinEvents was initialized\n");
5524642e01fSmrg		return;
5534642e01fSmrg	}
5544642e01fSmrg
5556747b715Smrg	sign_x = count_x > 0.0f ? SCROLLWHEELLEFTFAKE : SCROLLWHEELRIGHTFAKE;
5566747b715Smrg	sign_y = count_y > 0.0f ? SCROLLWHEELUPFAKE : SCROLLWHEELDOWNFAKE;
5574642e01fSmrg	count_x = fabs(count_x);
5584642e01fSmrg	count_y = fabs(count_y);
5594642e01fSmrg
5604642e01fSmrg	while ((count_x > 0.0f) || (count_y > 0.0f)) {
5614642e01fSmrg		if (count_x > 0.0f) {
5624642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5634642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5644642e01fSmrg			count_x = count_x - 1.0f;
5654642e01fSmrg		}
5664642e01fSmrg		if (count_y > 0.0f) {
5674642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5684642e01fSmrg			DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
5694642e01fSmrg			count_y = count_y - 1.0f;
5704642e01fSmrg		}
5714642e01fSmrg	}
5724642e01fSmrg}
5734642e01fSmrg
5744642e01fSmrg/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to
5754642e01fSmrg   reflect changing modifier flags (alt, control, meta, etc) */
5764642e01fSmrgvoid DarwinUpdateModKeys(int flags) {
5776747b715Smrg	DarwinUpdateModifiers(KeyRelease, darwin_all_modifier_flags & ~flags & darwin_x11_modifier_mask);
5786747b715Smrg	DarwinUpdateModifiers(KeyPress, ~darwin_all_modifier_flags & flags & darwin_x11_modifier_mask);
5796747b715Smrg	darwin_all_modifier_flags = flags;
5804642e01fSmrg}
5814642e01fSmrg
5824642e01fSmrg/*
5834642e01fSmrg * DarwinSendDDXEvent
5844642e01fSmrg *  Send the X server thread a message by placing it on the event queue.
5854642e01fSmrg */
5864642e01fSmrgvoid DarwinSendDDXEvent(int type, int argc, ...) {
5876747b715Smrg    XQuartzEvent e;
5886747b715Smrg    int i;
5894642e01fSmrg    va_list args;
5904642e01fSmrg
5916747b715Smrg    memset(&e, 0, sizeof(e));
5926747b715Smrg    e.header = ET_Internal;
5936747b715Smrg    e.type = ET_XQuartz;
5946747b715Smrg    e.length = sizeof(e);
5956747b715Smrg    e.time = GetTimeInMillis();
5966747b715Smrg    e.subtype = type;
5974642e01fSmrg
5986747b715Smrg    if (argc > 0 && argc < XQUARTZ_EVENT_MAXARGS) {
5994642e01fSmrg        va_start (args, argc);
6004642e01fSmrg        for (i = 0; i < argc; i++)
6016747b715Smrg            e.data[i] = (uint32_t) va_arg (args, uint32_t);
6024642e01fSmrg        va_end (args);
6034642e01fSmrg    }
6044642e01fSmrg
6054642e01fSmrg    darwinEvents_lock(); {
6066747b715Smrg        mieqEnqueue(NULL, (InternalEvent*)&e);
6074642e01fSmrg        DarwinPokeEQ();
6084642e01fSmrg    } darwinEvents_unlock();
6094642e01fSmrg}
610