darwinEvents.c revision 35c4bbdf
14642e01fSmrg/*
235c4bbdfSmrg * Darwin event queue and event handling
335c4bbdfSmrg *
435c4bbdfSmrg * Copyright 2007-2008 Apple Inc.
535c4bbdfSmrg * Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
635c4bbdfSmrg * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
735c4bbdfSmrg *
835c4bbdfSmrg * This file is based on mieq.c by Keith Packard,
935c4bbdfSmrg * which contains the following copyright:
1035c4bbdfSmrg * Copyright 1990, 1998  The Open Group
1135c4bbdfSmrg *
1235c4bbdfSmrg *
1335c4bbdfSmrg * Copyright (c) 2002-2012 Apple Inc. All rights reserved.
1435c4bbdfSmrg *
1535c4bbdfSmrg * Permission is hereby granted, free of charge, to any person
1635c4bbdfSmrg * obtaining a copy of this software and associated documentation files
1735c4bbdfSmrg * (the "Software"), to deal in the Software without restriction,
1835c4bbdfSmrg * including without limitation the rights to use, copy, modify, merge,
1935c4bbdfSmrg * publish, distribute, sublicense, and/or sell copies of the Software,
2035c4bbdfSmrg * and to permit persons to whom the Software is furnished to do so,
2135c4bbdfSmrg * subject to the following conditions:
2235c4bbdfSmrg *
2335c4bbdfSmrg * The above copyright notice and this permission notice shall be
2435c4bbdfSmrg * included in all copies or substantial portions of the Software.
2535c4bbdfSmrg *
2635c4bbdfSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2735c4bbdfSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2835c4bbdfSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2935c4bbdfSmrg * NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
3035c4bbdfSmrg * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
3135c4bbdfSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3235c4bbdfSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
3335c4bbdfSmrg * DEALINGS IN THE SOFTWARE.
3435c4bbdfSmrg *
3535c4bbdfSmrg * Except as contained in this notice, the name(s) of the above
3635c4bbdfSmrg * copyright holders shall not be used in advertising or otherwise to
3735c4bbdfSmrg * promote the sale, use or other dealings in this Software without
3835c4bbdfSmrg * prior written authorization.
394642e01fSmrg */
404642e01fSmrg
414642e01fSmrg#include "sanitizedCarbon.h"
424642e01fSmrg
434642e01fSmrg#ifdef HAVE_DIX_CONFIG_H
444642e01fSmrg#include <dix-config.h>
454642e01fSmrg#endif
464642e01fSmrg
4735c4bbdfSmrg#include <X11/X.h>
4835c4bbdfSmrg#include <X11/Xmd.h>
4935c4bbdfSmrg#include <X11/Xproto.h>
5035c4bbdfSmrg#include "misc.h"
5135c4bbdfSmrg#include "windowstr.h"
5235c4bbdfSmrg#include "pixmapstr.h"
5335c4bbdfSmrg#include "inputstr.h"
5435c4bbdfSmrg#include "inpututils.h"
5535c4bbdfSmrg#include "eventstr.h"
5635c4bbdfSmrg#include "mi.h"
5735c4bbdfSmrg#include "scrnintstr.h"
5835c4bbdfSmrg#include "mipointer.h"
5935c4bbdfSmrg#include "os.h"
6035c4bbdfSmrg#include "exglobals.h"
614642e01fSmrg
624642e01fSmrg#include "darwin.h"
634642e01fSmrg#include "quartz.h"
644642e01fSmrg#include "quartzKeyboard.h"
656747b715Smrg#include "quartzRandR.h"
664642e01fSmrg#include "darwinEvents.h"
674642e01fSmrg
684642e01fSmrg#include <sys/types.h>
694642e01fSmrg#include <sys/uio.h>
704642e01fSmrg#include <unistd.h>
714642e01fSmrg#include <pthread.h>
724642e01fSmrg#include <errno.h>
739ace9065Smrg#include <time.h>
744642e01fSmrg
754642e01fSmrg#include <IOKit/hidsystem/IOLLEvent.h>
764642e01fSmrg
776747b715Smrg#include <X11/extensions/applewmconst.h>
784642e01fSmrg#include "applewmExt.h"
794642e01fSmrg
804642e01fSmrg/* FIXME: Abstract this better */
8135c4bbdfSmrgextern Bool
8235c4bbdfSmrgQuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev);
834642e01fSmrg
846747b715Smrgint darwin_all_modifier_flags = 0;  // last known modifier state
856747b715Smrgint darwin_all_modifier_mask = 0;
866747b715Smrgint darwin_x11_modifier_mask = 0;
874642e01fSmrg
884642e01fSmrg#define FD_ADD_MAX 128
894642e01fSmrgstatic int fd_add[FD_ADD_MAX];
904642e01fSmrgint fd_add_count = 0;
914642e01fSmrgstatic pthread_mutex_t fd_add_lock = PTHREAD_MUTEX_INITIALIZER;
924642e01fSmrgstatic pthread_cond_t fd_add_ready_cond = PTHREAD_COND_INITIALIZER;
934642e01fSmrgstatic pthread_t fd_add_tid = NULL;
944642e01fSmrg
9535c4bbdfSmrgstatic InternalEvent* darwinEvents = NULL;
964642e01fSmrg
974642e01fSmrgstatic pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER;
984642e01fSmrgstatic pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER;
994642e01fSmrg
1004642e01fSmrg/*** Pthread Magics ***/
10135c4bbdfSmrgstatic pthread_t
10235c4bbdfSmrgcreate_thread(void *(*func)(void *), void *arg)
10335c4bbdfSmrg{
1044642e01fSmrg    pthread_attr_t attr;
1054642e01fSmrg    pthread_t tid;
1064642e01fSmrg
10735c4bbdfSmrg    pthread_attr_init(&attr);
10835c4bbdfSmrg    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
10935c4bbdfSmrg    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11035c4bbdfSmrg    pthread_create(&tid, &attr, func, arg);
11135c4bbdfSmrg    pthread_attr_destroy(&attr);
1124642e01fSmrg
1134642e01fSmrg    return tid;
1144642e01fSmrg}
1154642e01fSmrg
11635c4bbdfSmrgvoid
11735c4bbdfSmrgdarwinEvents_lock(void);
11835c4bbdfSmrgvoid
11935c4bbdfSmrgdarwinEvents_lock(void)
12035c4bbdfSmrg{
1214642e01fSmrg    int err;
12235c4bbdfSmrg    if ((err = pthread_mutex_lock(&mieq_lock))) {
1234642e01fSmrg        ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n",
1244642e01fSmrg               __FILE__, __FUNCTION__, __LINE__, err);
12535c4bbdfSmrg        xorg_backtrace();
1264642e01fSmrg    }
12735c4bbdfSmrg    if (darwinEvents == NULL) {
1284642e01fSmrg        pthread_cond_wait(&mieq_ready_cond, &mieq_lock);
1294642e01fSmrg    }
1304642e01fSmrg}
1314642e01fSmrg
13235c4bbdfSmrgvoid
13335c4bbdfSmrgdarwinEvents_unlock(void);
13435c4bbdfSmrgvoid
13535c4bbdfSmrgdarwinEvents_unlock(void)
13635c4bbdfSmrg{
1374642e01fSmrg    int err;
13835c4bbdfSmrg    if ((err = pthread_mutex_unlock(&mieq_lock))) {
1394642e01fSmrg        ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n",
1404642e01fSmrg               __FILE__, __FUNCTION__, __LINE__, err);
14135c4bbdfSmrg        xorg_backtrace();
1424642e01fSmrg    }
1434642e01fSmrg}
1444642e01fSmrg
1454642e01fSmrg/*
1464642e01fSmrg * DarwinPressModifierKey
1474642e01fSmrg * Press or release the given modifier key (one of NX_MODIFIERKEY_* constants)
1484642e01fSmrg */
14935c4bbdfSmrgstatic void
15035c4bbdfSmrgDarwinPressModifierKey(int pressed, int key)
15135c4bbdfSmrg{
1524642e01fSmrg    int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
1534642e01fSmrg
1544642e01fSmrg    if (keycode == 0) {
1554642e01fSmrg        ErrorF("DarwinPressModifierKey bad keycode: key=%d\n", key);
1564642e01fSmrg        return;
1574642e01fSmrg    }
1584642e01fSmrg
1594642e01fSmrg    DarwinSendKeyboardEvents(pressed, keycode);
1604642e01fSmrg}
1614642e01fSmrg
1624642e01fSmrg/*
1634642e01fSmrg * DarwinUpdateModifiers
1644642e01fSmrg *  Send events to update the modifier state.
1654642e01fSmrg */
1664642e01fSmrg
1676747b715Smrgstatic int darwin_x11_modifier_mask_list[] = {
1684642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK
16935c4bbdfSmrg    NX_DEVICELCTLKEYMASK,   NX_DEVICERCTLKEYMASK,
1704642e01fSmrg    NX_DEVICELSHIFTKEYMASK, NX_DEVICERSHIFTKEYMASK,
17135c4bbdfSmrg    NX_DEVICELCMDKEYMASK,   NX_DEVICERCMDKEYMASK,
17235c4bbdfSmrg    NX_DEVICELALTKEYMASK,   NX_DEVICERALTKEYMASK,
1734642e01fSmrg#else
17435c4bbdfSmrg    NX_CONTROLMASK,         NX_SHIFTMASK,          NX_COMMANDMASK,
17535c4bbdfSmrg    NX_ALTERNATEMASK,
1764642e01fSmrg#endif
1774642e01fSmrg    NX_ALPHASHIFTMASK,
1784642e01fSmrg    0
1794642e01fSmrg};
1804642e01fSmrg
18135c4bbdfSmrgstatic int darwin_all_modifier_mask_additions[] = { NX_SECONDARYFNMASK, 0 };
1826747b715Smrg
18335c4bbdfSmrgstatic void
18435c4bbdfSmrgDarwinUpdateModifiers(int pressed,                    // KeyPress or KeyRelease
18535c4bbdfSmrg                      int flags)                      // modifier flags that have changed
1864642e01fSmrg{
1874642e01fSmrg    int *f;
1884642e01fSmrg    int key;
1894642e01fSmrg
1904642e01fSmrg    /* Capslock is special.  This mask is the state of capslock (on/off),
1914642e01fSmrg     * not the state of the button.  Hopefully we can find a better solution.
1924642e01fSmrg     */
19335c4bbdfSmrg    if (NX_ALPHASHIFTMASK & flags) {
1944642e01fSmrg        DarwinPressModifierKey(KeyPress, NX_MODIFIERKEY_ALPHALOCK);
1954642e01fSmrg        DarwinPressModifierKey(KeyRelease, NX_MODIFIERKEY_ALPHALOCK);
1964642e01fSmrg    }
19735c4bbdfSmrg
19835c4bbdfSmrg    for (f = darwin_x11_modifier_mask_list; *f; f++)
19935c4bbdfSmrg        if (*f & flags && *f != NX_ALPHASHIFTMASK) {
2004642e01fSmrg            key = DarwinModifierNXMaskToNXKey(*f);
20135c4bbdfSmrg            if (key == -1)
20235c4bbdfSmrg                ErrorF("DarwinUpdateModifiers: Unsupported NXMask: 0x%x\n",
20335c4bbdfSmrg                       *f);
2044642e01fSmrg            else
2054642e01fSmrg                DarwinPressModifierKey(pressed, key);
2064642e01fSmrg        }
2074642e01fSmrg}
2084642e01fSmrg
2094642e01fSmrg/* Generic handler for Xquartz-specifc events.  When possible, these should
2104642e01fSmrg   be moved into their own individual functions and set as handlers using
2114642e01fSmrg   mieqSetHandler. */
2124642e01fSmrg
21335c4bbdfSmrgstatic void
21435c4bbdfSmrgDarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr dev)
21535c4bbdfSmrg{
2166747b715Smrg    XQuartzEvent *e = &(ie->xquartz_event);
2176747b715Smrg
21835c4bbdfSmrg    switch (e->subtype) {
21935c4bbdfSmrg    case kXquartzControllerNotify:
22035c4bbdfSmrg        DEBUG_LOG("kXquartzControllerNotify\n");
22135c4bbdfSmrg        AppleWMSendEvent(AppleWMControllerNotify,
22235c4bbdfSmrg                         AppleWMControllerNotifyMask,
22335c4bbdfSmrg                         e->data[0],
22435c4bbdfSmrg                         e->data[1]);
22535c4bbdfSmrg        break;
22635c4bbdfSmrg
22735c4bbdfSmrg    case kXquartzPasteboardNotify:
22835c4bbdfSmrg        DEBUG_LOG("kXquartzPasteboardNotify\n");
22935c4bbdfSmrg        AppleWMSendEvent(AppleWMPasteboardNotify,
23035c4bbdfSmrg                         AppleWMPasteboardNotifyMask,
23135c4bbdfSmrg                         e->data[0],
23235c4bbdfSmrg                         e->data[1]);
23335c4bbdfSmrg        break;
23435c4bbdfSmrg
23535c4bbdfSmrg    case kXquartzActivate:
23635c4bbdfSmrg        DEBUG_LOG("kXquartzActivate\n");
23735c4bbdfSmrg        QuartzShow();
23835c4bbdfSmrg        AppleWMSendEvent(AppleWMActivationNotify,
23935c4bbdfSmrg                         AppleWMActivationNotifyMask,
24035c4bbdfSmrg                         AppleWMIsActive, 0);
24135c4bbdfSmrg        break;
24235c4bbdfSmrg
24335c4bbdfSmrg    case kXquartzDeactivate:
24435c4bbdfSmrg        DEBUG_LOG("kXquartzDeactivate\n");
24535c4bbdfSmrg        AppleWMSendEvent(AppleWMActivationNotify,
24635c4bbdfSmrg                         AppleWMActivationNotifyMask,
24735c4bbdfSmrg                         AppleWMIsInactive, 0);
24835c4bbdfSmrg        QuartzHide();
24935c4bbdfSmrg        break;
25035c4bbdfSmrg
25135c4bbdfSmrg    case kXquartzReloadPreferences:
25235c4bbdfSmrg        DEBUG_LOG("kXquartzReloadPreferences\n");
25335c4bbdfSmrg        AppleWMSendEvent(AppleWMActivationNotify,
25435c4bbdfSmrg                         AppleWMActivationNotifyMask,
25535c4bbdfSmrg                         AppleWMReloadPreferences, 0);
25635c4bbdfSmrg        break;
25735c4bbdfSmrg
25835c4bbdfSmrg    case kXquartzToggleFullscreen:
25935c4bbdfSmrg        DEBUG_LOG("kXquartzToggleFullscreen\n");
26035c4bbdfSmrg        if (XQuartzIsRootless)
26135c4bbdfSmrg            ErrorF(
26235c4bbdfSmrg                "Ignoring kXquartzToggleFullscreen because of rootless mode.");
26335c4bbdfSmrg        else
26435c4bbdfSmrg            QuartzRandRToggleFullscreen();
26535c4bbdfSmrg        break;
26635c4bbdfSmrg
26735c4bbdfSmrg    case kXquartzSetRootless:
26835c4bbdfSmrg        DEBUG_LOG("kXquartzSetRootless\n");
26935c4bbdfSmrg        if (e->data[0]) {
27035c4bbdfSmrg            QuartzRandRSetFakeRootless();
27135c4bbdfSmrg        }
27235c4bbdfSmrg        else {
27335c4bbdfSmrg            QuartzRandRSetFakeFullscreen(FALSE);
27435c4bbdfSmrg        }
27535c4bbdfSmrg        break;
27635c4bbdfSmrg
27735c4bbdfSmrg    case kXquartzSetRootClip:
27835c4bbdfSmrg        QuartzSetRootClip(e->data[0]);
27935c4bbdfSmrg        break;
28035c4bbdfSmrg
28135c4bbdfSmrg    case kXquartzQuit:
28235c4bbdfSmrg        GiveUp(0);
28335c4bbdfSmrg        break;
28435c4bbdfSmrg
28535c4bbdfSmrg    case kXquartzSpaceChanged:
28635c4bbdfSmrg        DEBUG_LOG("kXquartzSpaceChanged\n");
28735c4bbdfSmrg        QuartzSpaceChanged(e->data[0]);
28835c4bbdfSmrg        break;
28935c4bbdfSmrg
29035c4bbdfSmrg    case kXquartzListenOnOpenFD:
29135c4bbdfSmrg        ErrorF("Calling ListenOnOpenFD() for new fd: %d\n", (int)e->data[0]);
29235c4bbdfSmrg        ListenOnOpenFD((int)e->data[0], 1);
29335c4bbdfSmrg        break;
29435c4bbdfSmrg
29535c4bbdfSmrg    case kXquartzReloadKeymap:
29635c4bbdfSmrg        DarwinKeyboardReloadHandler();
29735c4bbdfSmrg        break;
29835c4bbdfSmrg
29935c4bbdfSmrg    case kXquartzDisplayChanged:
30035c4bbdfSmrg        DEBUG_LOG("kXquartzDisplayChanged\n");
30135c4bbdfSmrg        QuartzUpdateScreens();
30235c4bbdfSmrg
30335c4bbdfSmrg        /* Update our RandR info */
30435c4bbdfSmrg        QuartzRandRUpdateFakeModes(TRUE);
30535c4bbdfSmrg        break;
30635c4bbdfSmrg
30735c4bbdfSmrg    default:
30835c4bbdfSmrg        if (!QuartzModeEventHandler(screenNum, e, dev))
30935c4bbdfSmrg            ErrorF("Unknown application defined event type %d.\n", e->subtype);
31035c4bbdfSmrg    }
3114642e01fSmrg}
3124642e01fSmrg
31335c4bbdfSmrgvoid
31435c4bbdfSmrgDarwinListenOnOpenFD(int fd)
31535c4bbdfSmrg{
3164642e01fSmrg    ErrorF("DarwinListenOnOpenFD: %d\n", fd);
31735c4bbdfSmrg
3184642e01fSmrg    pthread_mutex_lock(&fd_add_lock);
31935c4bbdfSmrg    if (fd_add_count < FD_ADD_MAX)
3204642e01fSmrg        fd_add[fd_add_count++] = fd;
3214642e01fSmrg    else
3224642e01fSmrg        ErrorF("FD Addition buffer at max.  Dropping fd addition request.\n");
3234642e01fSmrg
3244642e01fSmrg    pthread_cond_broadcast(&fd_add_ready_cond);
3254642e01fSmrg    pthread_mutex_unlock(&fd_add_lock);
3264642e01fSmrg}
3274642e01fSmrg
32835c4bbdfSmrgstatic void *
32935c4bbdfSmrgDarwinProcessFDAdditionQueue_thread(void *args)
33035c4bbdfSmrg{
3319ace9065Smrg    /* TODO: Possibly adjust this to no longer be a race... maybe trigger this
3329ace9065Smrg     *       once a client connects and claims to be the WM.
3339ace9065Smrg     *
3349ace9065Smrg     * From ajax:
3359ace9065Smrg     * There's already an internal callback chain for setting selection [in 1.5]
3369ace9065Smrg     * ownership.  See the CallSelectionCallback at the bottom of
3379ace9065Smrg     * ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook
3389ace9065Smrg     * into it.
3399ace9065Smrg     */
3409ace9065Smrg
3419ace9065Smrg    struct timespec sleep_for;
3429ace9065Smrg    struct timespec sleep_remaining;
3439ace9065Smrg
3449ace9065Smrg    sleep_for.tv_sec = 3;
3459ace9065Smrg    sleep_for.tv_nsec = 0;
3469ace9065Smrg
34735c4bbdfSmrg    ErrorF(
34835c4bbdfSmrg        "X11.app: DarwinProcessFDAdditionQueue_thread: Sleeping to allow xinitrc to catchup.\n");
34935c4bbdfSmrg    while (nanosleep(&sleep_for, &sleep_remaining) != 0) {
3509ace9065Smrg        sleep_for = sleep_remaining;
3519ace9065Smrg    }
3529ace9065Smrg
3534642e01fSmrg    pthread_mutex_lock(&fd_add_lock);
35435c4bbdfSmrg    while (true) {
35535c4bbdfSmrg        while (fd_add_count) {
35635c4bbdfSmrg            DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1,
35735c4bbdfSmrg                               fd_add[--fd_add_count]);
3584642e01fSmrg        }
3594642e01fSmrg        pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock);
3604642e01fSmrg    }
3619ace9065Smrg
3629ace9065Smrg    return NULL;
3634642e01fSmrg}
3644642e01fSmrg
36535c4bbdfSmrgBool
36635c4bbdfSmrgDarwinEQInit(void)
36735c4bbdfSmrg{
3686747b715Smrg    int *p;
3696747b715Smrg
37035c4bbdfSmrg    for (p = darwin_x11_modifier_mask_list; *p; p++) {
3716747b715Smrg        darwin_x11_modifier_mask |= *p;
3726747b715Smrg    }
37335c4bbdfSmrg
37435c4bbdfSmrg    darwin_all_modifier_mask = darwin_x11_modifier_mask;
37535c4bbdfSmrg    for (p = darwin_all_modifier_mask_additions; *p; p++) {
3766747b715Smrg        darwin_all_modifier_mask |= *p;
3774642e01fSmrg    }
37835c4bbdfSmrg
3796747b715Smrg    mieqInit();
3806747b715Smrg    mieqSetHandler(ET_XQuartz, DarwinEventHandler);
3814642e01fSmrg
3824642e01fSmrg    /* Note that this *could* cause a potential async issue, since we're checking
3834642e01fSmrg     * darwinEvents without holding the lock, but darwinEvents is only ever set
3844642e01fSmrg     * here, so I don't bother.
3854642e01fSmrg     */
3864642e01fSmrg    if (!darwinEvents) {
38735c4bbdfSmrg        darwinEvents = InitEventList(GetMaximumEventsNum());
38835c4bbdfSmrg
3894642e01fSmrg        if (!darwinEvents)
3904642e01fSmrg            FatalError("Couldn't allocate event buffer\n");
39135c4bbdfSmrg
3924642e01fSmrg        darwinEvents_lock();
3934642e01fSmrg        pthread_cond_broadcast(&mieq_ready_cond);
3944642e01fSmrg        darwinEvents_unlock();
3954642e01fSmrg    }
3964642e01fSmrg
39735c4bbdfSmrg    if (!fd_add_tid)
3984642e01fSmrg        fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL);
39935c4bbdfSmrg
4004642e01fSmrg    return TRUE;
4014642e01fSmrg}
4024642e01fSmrg
40335c4bbdfSmrgvoid
40435c4bbdfSmrgDarwinEQFini(void)
40535c4bbdfSmrg{
40635c4bbdfSmrg    mieqFini();
40735c4bbdfSmrg}
40835c4bbdfSmrg
4094642e01fSmrg/*
4104642e01fSmrg * ProcessInputEvents
4114642e01fSmrg *  Read and process events from the event queue until it is empty.
4124642e01fSmrg */
41335c4bbdfSmrgvoid
41435c4bbdfSmrgProcessInputEvents(void)
41535c4bbdfSmrg{
4166747b715Smrg    char nullbyte;
41735c4bbdfSmrg    int x = sizeof(nullbyte);
4184642e01fSmrg
4194642e01fSmrg    mieqProcessInputEvents();
4204642e01fSmrg
4214642e01fSmrg    // Empty the signaling pipe
4226747b715Smrg    while (x == sizeof(nullbyte)) {
42335c4bbdfSmrg        x = read(darwinEventReadFD, &nullbyte, sizeof(nullbyte));
4244642e01fSmrg    }
4254642e01fSmrg}
4264642e01fSmrg
4274642e01fSmrg/* Sends a null byte down darwinEventWriteFD, which will cause the
4284642e01fSmrg   Dispatch() event loop to check out event queue */
42935c4bbdfSmrgstatic void
43035c4bbdfSmrgDarwinPokeEQ(void)
43135c4bbdfSmrg{
43235c4bbdfSmrg    char nullbyte = 0;
43335c4bbdfSmrg    //  <daniels> oh, i ... er ... christ.
43435c4bbdfSmrg    write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte));
4354642e01fSmrg}
4364642e01fSmrg
43735c4bbdfSmrgvoid
43835c4bbdfSmrgDarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev)
43935c4bbdfSmrg{
44035c4bbdfSmrg    darwinEvents_lock();
44135c4bbdfSmrg    {
44235c4bbdfSmrg        int i;
44335c4bbdfSmrg        if (pDev->button) {
44435c4bbdfSmrg            for (i = 0; i < pDev->button->numButtons; i++) {
44535c4bbdfSmrg                if (BitIsOn(pDev->button->down, i)) {
44635c4bbdfSmrg                    QueuePointerEvents(pDev, ButtonRelease, i,
44735c4bbdfSmrg                                       POINTER_ABSOLUTE,
44835c4bbdfSmrg                                       NULL);
44935c4bbdfSmrg                }
45035c4bbdfSmrg            }
45135c4bbdfSmrg        }
45235c4bbdfSmrg
45335c4bbdfSmrg        if (pDev->key) {
45435c4bbdfSmrg            for (i = 0; i < NUM_KEYCODES; i++) {
45535c4bbdfSmrg                if (BitIsOn(pDev->key->down, i + MIN_KEYCODE)) {
45635c4bbdfSmrg                    QueueKeyboardEvents(pDev, KeyRelease, i + MIN_KEYCODE);
45735c4bbdfSmrg                }
45835c4bbdfSmrg            }
45935c4bbdfSmrg        }
46035c4bbdfSmrg        DarwinPokeEQ();
46135c4bbdfSmrg    } darwinEvents_unlock();
46235c4bbdfSmrg}
46335c4bbdfSmrg
46435c4bbdfSmrgvoid
46535c4bbdfSmrgDarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
46635c4bbdfSmrg                       double pointer_x, double pointer_y,
46735c4bbdfSmrg                       double pressure, double tilt_x,
46835c4bbdfSmrg                       double tilt_y)
46935c4bbdfSmrg{
47035c4bbdfSmrg    ScreenPtr screen;
47135c4bbdfSmrg    ValuatorMask valuators;
47235c4bbdfSmrg
47335c4bbdfSmrg    if (!darwinEvents) {
47435c4bbdfSmrg        DEBUG_LOG("%s called before darwinEvents was initialized\n",
47535c4bbdfSmrg                  __FUNCTION__);
47635c4bbdfSmrg        return;
47735c4bbdfSmrg    }
47835c4bbdfSmrg
47935c4bbdfSmrg    screen = miPointerGetScreen(pDev);
48035c4bbdfSmrg    if (!screen) {
48135c4bbdfSmrg        DEBUG_LOG("%s called before screen was initialized\n",
48235c4bbdfSmrg                  __FUNCTION__);
48335c4bbdfSmrg        return;
48435c4bbdfSmrg    }
48535c4bbdfSmrg
4864642e01fSmrg    /* Fix offset between darwin and X screens */
4876747b715Smrg    pointer_x -= darwinMainScreenX + screen->x;
4886747b715Smrg    pointer_y -= darwinMainScreenY + screen->y;
4894642e01fSmrg
49035c4bbdfSmrg    /* Adjust our pointer location to the [0,1] range */
49135c4bbdfSmrg    pointer_x = pointer_x / (double)screenInfo.width;
49235c4bbdfSmrg    pointer_y = pointer_y / (double)screenInfo.height;
49335c4bbdfSmrg
49435c4bbdfSmrg    valuator_mask_zero(&valuators);
49535c4bbdfSmrg    valuator_mask_set_double(&valuators, 0, XQUARTZ_VALUATOR_LIMIT * pointer_x);
49635c4bbdfSmrg    valuator_mask_set_double(&valuators, 1, XQUARTZ_VALUATOR_LIMIT * pointer_y);
49735c4bbdfSmrg    valuator_mask_set_double(&valuators, 2, XQUARTZ_VALUATOR_LIMIT * pressure);
49835c4bbdfSmrg    valuator_mask_set_double(&valuators, 3, XQUARTZ_VALUATOR_LIMIT * tilt_x);
49935c4bbdfSmrg    valuator_mask_set_double(&valuators, 4, XQUARTZ_VALUATOR_LIMIT * tilt_y);
50035c4bbdfSmrg
50135c4bbdfSmrg    darwinEvents_lock();
50235c4bbdfSmrg    {
50335c4bbdfSmrg        if (ev_type == ProximityIn || ev_type == ProximityOut) {
50435c4bbdfSmrg            QueueProximityEvents(pDev, ev_type, &valuators);
50535c4bbdfSmrg        } else {
50635c4bbdfSmrg            QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE,
50735c4bbdfSmrg                               &valuators);
50835c4bbdfSmrg        }
50935c4bbdfSmrg        DarwinPokeEQ();
51035c4bbdfSmrg    } darwinEvents_unlock();
5114642e01fSmrg}
5124642e01fSmrg
51335c4bbdfSmrgvoid
51435c4bbdfSmrgDarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
51535c4bbdfSmrg                        double pointer_x, double pointer_y,
51635c4bbdfSmrg                        double pointer_dx, double pointer_dy)
51735c4bbdfSmrg{
51835c4bbdfSmrg    static int darwinFakeMouseButtonDown = 0;
5194642e01fSmrg    ScreenPtr screen;
52035c4bbdfSmrg    ValuatorMask valuators;
52135c4bbdfSmrg
52235c4bbdfSmrg    if (!darwinEvents) {
52335c4bbdfSmrg        DEBUG_LOG("%s called before darwinEvents was initialized\n",
52435c4bbdfSmrg                  __FUNCTION__);
52535c4bbdfSmrg        return;
52635c4bbdfSmrg    }
5274642e01fSmrg
5284642e01fSmrg    screen = miPointerGetScreen(pDev);
52935c4bbdfSmrg    if (!screen) {
53035c4bbdfSmrg        DEBUG_LOG("%s called before screen was initialized\n",
53135c4bbdfSmrg                  __FUNCTION__);
5324642e01fSmrg        return;
5334642e01fSmrg    }
5344642e01fSmrg
5354642e01fSmrg    /* Handle fake click */
53635c4bbdfSmrg    if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) {
53735c4bbdfSmrg        if (darwinFakeMouseButtonDown != 0) {
5384642e01fSmrg            /* We're currently "down" with another button, so release it first */
53935c4bbdfSmrg            DarwinSendPointerEvents(pDev, ButtonRelease,
54035c4bbdfSmrg                                    darwinFakeMouseButtonDown,
54135c4bbdfSmrg                                    pointer_x, pointer_y, 0.0, 0.0);
54235c4bbdfSmrg            darwinFakeMouseButtonDown = 0;
5434642e01fSmrg        }
54435c4bbdfSmrg        if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
5454642e01fSmrg            ev_button = 2;
54635c4bbdfSmrg            darwinFakeMouseButtonDown = 2;
54735c4bbdfSmrg            DarwinUpdateModKeys(
54835c4bbdfSmrg                darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
54935c4bbdfSmrg        }
55035c4bbdfSmrg        else if (darwin_all_modifier_flags & darwinFakeMouse3Mask) {
5514642e01fSmrg            ev_button = 3;
55235c4bbdfSmrg            darwinFakeMouseButtonDown = 3;
55335c4bbdfSmrg            DarwinUpdateModKeys(
55435c4bbdfSmrg                darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
55535c4bbdfSmrg        }
55635c4bbdfSmrg    }
5574642e01fSmrg
55835c4bbdfSmrg    if (ev_type == ButtonRelease && ev_button == 1) {
55935c4bbdfSmrg        if (darwinFakeMouseButtonDown) {
5604642e01fSmrg            ev_button = darwinFakeMouseButtonDown;
5614642e01fSmrg        }
5624642e01fSmrg
56335c4bbdfSmrg        if (darwinFakeMouseButtonDown == 2) {
56435c4bbdfSmrg            DarwinUpdateModKeys(
56535c4bbdfSmrg                darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
56635c4bbdfSmrg        }
56735c4bbdfSmrg        else if (darwinFakeMouseButtonDown == 3) {
56835c4bbdfSmrg            DarwinUpdateModKeys(
56935c4bbdfSmrg                darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
5704642e01fSmrg        }
5714642e01fSmrg
5724642e01fSmrg        darwinFakeMouseButtonDown = 0;
57335c4bbdfSmrg    }
57435c4bbdfSmrg
57535c4bbdfSmrg    /* Fix offset between darwin and X screens */
57635c4bbdfSmrg    pointer_x -= darwinMainScreenX + screen->x;
57735c4bbdfSmrg    pointer_y -= darwinMainScreenY + screen->y;
57835c4bbdfSmrg
57935c4bbdfSmrg    valuator_mask_zero(&valuators);
58035c4bbdfSmrg    valuator_mask_set_double(&valuators, 0, pointer_x);
58135c4bbdfSmrg    valuator_mask_set_double(&valuators, 1, pointer_y);
58235c4bbdfSmrg
58335c4bbdfSmrg    if (ev_type == MotionNotify) {
58435c4bbdfSmrg        if (pointer_dx != 0.0)
58535c4bbdfSmrg            valuator_mask_set_double(&valuators, 2, pointer_dx);
58635c4bbdfSmrg        if (pointer_dy != 0.0)
58735c4bbdfSmrg            valuator_mask_set_double(&valuators, 3, pointer_dy);
58835c4bbdfSmrg    }
58935c4bbdfSmrg
59035c4bbdfSmrg    darwinEvents_lock();
59135c4bbdfSmrg    {
59235c4bbdfSmrg        QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE,
59335c4bbdfSmrg                           &valuators);
59435c4bbdfSmrg        DarwinPokeEQ();
5954642e01fSmrg    } darwinEvents_unlock();
5964642e01fSmrg}
5974642e01fSmrg
59835c4bbdfSmrgvoid
59935c4bbdfSmrgDarwinSendKeyboardEvents(int ev_type, int keycode)
60035c4bbdfSmrg{
6014642e01fSmrg
60235c4bbdfSmrg    if (!darwinEvents) {
60335c4bbdfSmrg        DEBUG_LOG(
60435c4bbdfSmrg            "DarwinSendKeyboardEvents called before darwinEvents was initialized\n");
60535c4bbdfSmrg        return;
60635c4bbdfSmrg    }
6074642e01fSmrg
60835c4bbdfSmrg    darwinEvents_lock();
60935c4bbdfSmrg    {
61035c4bbdfSmrg        QueueKeyboardEvents(darwinKeyboard, ev_type, keycode + MIN_KEYCODE);
61135c4bbdfSmrg        DarwinPokeEQ();
6124642e01fSmrg    } darwinEvents_unlock();
6134642e01fSmrg}
6144642e01fSmrg
61535c4bbdfSmrg/* Send the appropriate number of button clicks to emulate scroll wheel */
61635c4bbdfSmrgvoid
61735c4bbdfSmrgDarwinSendScrollEvents(double scroll_x, double scroll_y) {
6184642e01fSmrg    ScreenPtr screen;
61935c4bbdfSmrg    ValuatorMask valuators;
6204642e01fSmrg
62135c4bbdfSmrg    if (!darwinEvents) {
62235c4bbdfSmrg        DEBUG_LOG(
62335c4bbdfSmrg            "DarwinSendScrollEvents called before darwinEvents was initialized\n");
62435c4bbdfSmrg        return;
62535c4bbdfSmrg    }
6264642e01fSmrg
62735c4bbdfSmrg    screen = miPointerGetScreen(darwinPointer);
62835c4bbdfSmrg    if (!screen) {
62935c4bbdfSmrg        DEBUG_LOG(
63035c4bbdfSmrg            "DarwinSendScrollEvents called before screen was initialized\n");
6314642e01fSmrg        return;
63235c4bbdfSmrg    }
6334642e01fSmrg
63435c4bbdfSmrg    valuator_mask_zero(&valuators);
63535c4bbdfSmrg    valuator_mask_set_double(&valuators, 4, scroll_y);
63635c4bbdfSmrg    valuator_mask_set_double(&valuators, 5, scroll_x);
6374642e01fSmrg
63835c4bbdfSmrg    darwinEvents_lock();
63935c4bbdfSmrg    {
64035c4bbdfSmrg        QueuePointerEvents(darwinPointer, MotionNotify, 0,
64135c4bbdfSmrg                           POINTER_RELATIVE, &valuators);
64235c4bbdfSmrg        DarwinPokeEQ();
64335c4bbdfSmrg    } darwinEvents_unlock();
6444642e01fSmrg}
6454642e01fSmrg
6464642e01fSmrg/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to
6474642e01fSmrg   reflect changing modifier flags (alt, control, meta, etc) */
64835c4bbdfSmrgvoid
64935c4bbdfSmrgDarwinUpdateModKeys(int flags)
65035c4bbdfSmrg{
65135c4bbdfSmrg    DarwinUpdateModifiers(
65235c4bbdfSmrg        KeyRelease, darwin_all_modifier_flags & ~flags &
65335c4bbdfSmrg        darwin_x11_modifier_mask);
65435c4bbdfSmrg    DarwinUpdateModifiers(
65535c4bbdfSmrg        KeyPress, ~darwin_all_modifier_flags & flags &
65635c4bbdfSmrg        darwin_x11_modifier_mask);
65735c4bbdfSmrg    darwin_all_modifier_flags = flags;
6584642e01fSmrg}
6594642e01fSmrg
6604642e01fSmrg/*
6614642e01fSmrg * DarwinSendDDXEvent
6624642e01fSmrg *  Send the X server thread a message by placing it on the event queue.
6634642e01fSmrg */
66435c4bbdfSmrgvoid
66535c4bbdfSmrgDarwinSendDDXEvent(int type, int argc, ...)
66635c4bbdfSmrg{
6676747b715Smrg    XQuartzEvent e;
6686747b715Smrg    int i;
6694642e01fSmrg    va_list args;
6704642e01fSmrg
6716747b715Smrg    memset(&e, 0, sizeof(e));
6726747b715Smrg    e.header = ET_Internal;
6736747b715Smrg    e.type = ET_XQuartz;
6746747b715Smrg    e.length = sizeof(e);
6756747b715Smrg    e.time = GetTimeInMillis();
6766747b715Smrg    e.subtype = type;
6774642e01fSmrg
6786747b715Smrg    if (argc > 0 && argc < XQUARTZ_EVENT_MAXARGS) {
67935c4bbdfSmrg        va_start(args, argc);
6804642e01fSmrg        for (i = 0; i < argc; i++)
68135c4bbdfSmrg            e.data[i] = (uint32_t)va_arg(args, uint32_t);
68235c4bbdfSmrg        va_end(args);
6834642e01fSmrg    }
6844642e01fSmrg
68535c4bbdfSmrg    darwinEvents_lock();
68635c4bbdfSmrg    {
68735c4bbdfSmrg        mieqEnqueue(NULL, (InternalEvent *)&e);
6884642e01fSmrg        DarwinPokeEQ();
6894642e01fSmrg    } darwinEvents_unlock();
6904642e01fSmrg}
691