diff options
Diffstat (limited to 'xorg-server/hw/xquartz/darwinEvents.c')
-rw-r--r-- | xorg-server/hw/xquartz/darwinEvents.c | 795 |
1 files changed, 457 insertions, 338 deletions
diff --git a/xorg-server/hw/xquartz/darwinEvents.c b/xorg-server/hw/xquartz/darwinEvents.c index 827fd81b8..374c4e07e 100644 --- a/xorg-server/hw/xquartz/darwinEvents.c +++ b/xorg-server/hw/xquartz/darwinEvents.c @@ -1,7 +1,7 @@ /* Darwin event queue and event handling -Copyright 2007 Apple Inc. +Copyright 2007-2008 Apple Inc. Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved. Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved. @@ -30,6 +30,12 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. */ +#include "sanitizedCarbon.h" + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + #define NEED_EVENTS #include <X11/X.h> #include <X11/Xmd.h> @@ -41,421 +47,534 @@ in this Software without prior written authorization from The Open Group. #include "mi.h" #include "scrnintstr.h" #include "mipointer.h" +#include "os.h" #include "darwin.h" #include "quartz.h" -#include "darwinKeyboard.h" +#include "quartzKeyboard.h" #include "darwinEvents.h" #include <sys/types.h> #include <sys/uio.h> #include <unistd.h> +#include <pthread.h> +#include <errno.h> + #include <IOKit/hidsystem/IOLLEvent.h> /* Fake button press/release for scroll wheel move. */ -#define SCROLLWHEELUPFAKE 4 -#define SCROLLWHEELDOWNFAKE 5 +#define SCROLLWHEELUPFAKE 4 +#define SCROLLWHEELDOWNFAKE 5 +#define SCROLLWHEELLEFTFAKE 6 +#define SCROLLWHEELRIGHTFAKE 7 -#define QUEUE_SIZE 256 +#define _APPLEWM_SERVER_ +#include "applewmExt.h" +#include <X11/extensions/applewm.h> -typedef struct _Event { - xEvent event; - ScreenPtr pScreen; -} EventRec, *EventPtr; +/* FIXME: Abstract this better */ +void QuartzModeEQInit(void); -int input_check_zero, input_check_flag; +int darwin_modifier_flags = 0; // last known modifier state -static int old_flags = 0; // last known modifier state +#define FD_ADD_MAX 128 +static int fd_add[FD_ADD_MAX]; +int fd_add_count = 0; +static pthread_mutex_t fd_add_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t fd_add_ready_cond = PTHREAD_COND_INITIALIZER; +static pthread_t fd_add_tid = NULL; -typedef struct _EventQueue { - HWEventQueueType head, tail; /* long for SetInputCheck */ - CARD32 lastEventTime; /* to avoid time running backwards */ - Bool lastMotion; - EventRec events[QUEUE_SIZE]; /* static allocation for signals */ - DevicePtr pKbd, pPtr; /* device pointer, to get funcs */ - ScreenPtr pEnqueueScreen; /* screen events are being delivered to */ - ScreenPtr pDequeueScreen; /* screen events are being dispatched to */ -} EventQueueRec, *EventQueuePtr; +static EventList *darwinEvents = NULL; -static EventQueueRec darwinEventQueue; -xEvent *darwinEvents; +static pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER; -/* - * DarwinPressModifierMask - * Press or release the given modifier key, specified by its mask. - */ -static void DarwinPressModifierMask( - int pressed, - int mask) // one of NX_*MASK constants -{ - int key = DarwinModifierNXMaskToNXKey(mask); +/*** Pthread Magics ***/ +static pthread_t create_thread(void *func, void *arg) { + pthread_attr_t attr; + pthread_t tid; - if (key != -1) { - int keycode = DarwinModifierNXKeyToNXKeycode(key, 0); - if (keycode != 0) - DarwinSendKeyboardEvents(pressed, keycode); - } -} - -#ifdef NX_DEVICELCTLKEYMASK -#define CONTROL_MASK(flags) (flags & (NX_DEVICELCTLKEYMASK|NX_DEVICERCTLKEYMASK)) -#else -#define CONTROL_MASK(flags) (NX_CONTROLMASK) -#endif /* NX_DEVICELCTLKEYMASK */ - -#ifdef NX_DEVICELSHIFTKEYMASK -#define SHIFT_MASK(flags) (flags & (NX_DEVICELSHIFTKEYMASK|NX_DEVICERSHIFTKEYMASK)) -#else -#define SHIFT_MASK(flags) (NX_SHIFTMASK) -#endif /* NX_DEVICELSHIFTKEYMASK */ - -#ifdef NX_DEVICELCMDKEYMASK -#define COMMAND_MASK(flags) (flags & (NX_DEVICELCMDKEYMASK|NX_DEVICERCMDKEYMASK)) -#else -#define COMMAND_MASK(flags) (NX_COMMANDMASK) -#endif /* NX_DEVICELCMDKEYMASK */ + pthread_attr_init (&attr); + pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + pthread_create (&tid, &attr, func, arg); + pthread_attr_destroy (&attr); -#ifdef NX_DEVICELALTKEYMASK -#define ALTERNATE_MASK(flags) (flags & (NX_DEVICELALTKEYMASK|NX_DEVICERALTKEYMASK)) -#else -#define ALTERNATE_MASK(flags) (NX_ALTERNATEMASK) -#endif /* NX_DEVICELALTKEYMASK */ + return tid; +} -/* - * DarwinUpdateModifiers - * Send events to update the modifier state. - */ -static void DarwinUpdateModifiers( - int pressed, // KeyPress or KeyRelease - int flags ) // modifier flags that have changed -{ - if (flags & NX_ALPHASHIFTMASK) { - DarwinPressModifierMask(pressed, NX_ALPHASHIFTMASK); - } - if (flags & NX_COMMANDMASK) { - DarwinPressModifierMask(pressed, COMMAND_MASK(flags)); - } - if (flags & NX_CONTROLMASK) { - DarwinPressModifierMask(pressed, CONTROL_MASK(flags)); - } - if (flags & NX_ALTERNATEMASK) { - DarwinPressModifierMask(pressed, ALTERNATE_MASK(flags)); - } - if (flags & NX_SHIFTMASK) { - DarwinPressModifierMask(pressed, SHIFT_MASK(flags)); +void darwinEvents_lock(void); +void darwinEvents_lock(void) { + int err; + if((err = pthread_mutex_lock(&mieq_lock))) { + ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n", + __FILE__, __FUNCTION__, __LINE__, err); + spewCallStack(); } - if (flags & NX_SECONDARYFNMASK) { - DarwinPressModifierMask(pressed, NX_SECONDARYFNMASK); + if(darwinEvents == NULL) { + pthread_cond_wait(&mieq_ready_cond, &mieq_lock); } } -/* - * DarwinReleaseModifiers - * This hacky function releases all modifier keys. It should be called when X11.app - * is deactivated (kXDarwinDeactivate) to prevent modifiers from getting stuck if they - * are held down during a "context" switch -- otherwise, we would miss the KeyUp. - */ -static void DarwinReleaseModifiers(void) { - DarwinUpdateModifiers(KeyRelease, COMMAND_MASK(-1) | CONTROL_MASK(-1) | ALTERNATE_MASK(-1) | SHIFT_MASK(-1)); +void darwinEvents_unlock(void); +void darwinEvents_unlock(void) { + int err; + if((err = pthread_mutex_unlock(&mieq_lock))) { + ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n", + __FILE__, __FUNCTION__, __LINE__, err); + spewCallStack(); + } } /* - * DarwinSimulateMouseClick - * Send a mouse click to X when multiple mouse buttons are simulated - * with modifier-clicks, such as command-click for button 2. The dix - * layer is told that the previously pressed modifier key(s) are - * released, the simulated click event is sent. After the mouse button - * is released, the modifier keys are reverted to their actual state, - * which may or may not be pressed at that point. This is usually - * closest to what the user wants. Ie. the user typically wants to - * simulate a button 2 press instead of Command-button 2. + * DarwinPressModifierKey + * Press or release the given modifier key (one of NX_MODIFIERKEY_* constants) */ -static void DarwinSimulateMouseClick( - int pointer_x, - int pointer_y, - int whichButton, // mouse button to be pressed - int modifierMask) // modifiers used for the fake click -{ - // first fool X into forgetting about the keys - // for some reason, it's not enough to tell X we released the Command key -- - // it has to be the *left* Command key. - if (modifierMask & NX_COMMANDMASK) modifierMask |=NX_DEVICELCMDKEYMASK ; - DarwinUpdateModifiers(KeyRelease, modifierMask); - - // push the mouse button - DarwinSendPointerEvents(ButtonPress, whichButton, pointer_x, pointer_y); - DarwinSendPointerEvents(ButtonRelease, whichButton, pointer_x, pointer_y); - - // restore old modifiers - DarwinUpdateModifiers(KeyPress, modifierMask); -} +static void DarwinPressModifierKey(int pressed, int key) { + int keycode = DarwinModifierNXKeyToNXKeycode(key, 0); + if (keycode == 0) { + ErrorF("DarwinPressModifierKey bad keycode: key=%d\n", key); + return; + } -Bool DarwinEQInit(DevicePtr pKbd, DevicePtr pPtr) { - darwinEvents = (xEvent *)malloc(sizeof(xEvent) * GetMaximumEventsNum()); - mieqInit(); - darwinEventQueue.head = darwinEventQueue.tail = 0; - darwinEventQueue.lastEventTime = GetTimeInMillis (); - darwinEventQueue.pKbd = pKbd; - darwinEventQueue.pPtr = pPtr; - darwinEventQueue.pEnqueueScreen = screenInfo.screens[0]; - darwinEventQueue.pDequeueScreen = darwinEventQueue.pEnqueueScreen; - SetInputCheck(&input_check_zero, &input_check_flag); - return TRUE; + DarwinSendKeyboardEvents(pressed, keycode); } - /* - * DarwinEQEnqueue - * Must be thread safe with ProcessInputEvents. - * DarwinEQEnqueue - called from event gathering thread - * ProcessInputEvents - called from X server thread - * DarwinEQEnqueue should never be called from more than one thread. - * - * This should be deprecated in favor of miEQEnqueue -- BB + * DarwinUpdateModifiers + * Send events to update the modifier state. */ -void DarwinEQEnqueue(const xEventPtr e) { - HWEventQueueType oldtail, newtail; - - oldtail = darwinEventQueue.tail; - // mieqEnqueue() collapses successive motion events into one event. - // This is difficult to do in a thread-safe way and rarely useful. - - newtail = oldtail + 1; - if (newtail == QUEUE_SIZE) newtail = 0; - /* Toss events which come in late */ - if (newtail == darwinEventQueue.head) return; +int darwin_modifier_mask_list[] = { +#ifdef NX_DEVICELCMDKEYMASK + NX_DEVICELCTLKEYMASK, NX_DEVICERCTLKEYMASK, + NX_DEVICELSHIFTKEYMASK, NX_DEVICERSHIFTKEYMASK, + NX_DEVICELCMDKEYMASK, NX_DEVICERCMDKEYMASK, + NX_DEVICELALTKEYMASK, NX_DEVICERALTKEYMASK, +#else + NX_CONTROLMASK, NX_SHIFTMASK, NX_COMMANDMASK, NX_ALTERNATEMASK, +#endif + NX_ALPHASHIFTMASK, + 0 +}; - darwinEventQueue.events[oldtail].event = *e; +static void DarwinUpdateModifiers( + int pressed, // KeyPress or KeyRelease + int flags ) // modifier flags that have changed +{ + int *f; + int key; - /* - * Make sure that event times don't go backwards - this - * is "unnecessary", but very useful + /* Capslock is special. This mask is the state of capslock (on/off), + * not the state of the button. Hopefully we can find a better solution. */ - if (e->u.keyButtonPointer.time < darwinEventQueue.lastEventTime && - darwinEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000) - { - darwinEventQueue.events[oldtail].event.u.keyButtonPointer.time = - darwinEventQueue.lastEventTime; + if(NX_ALPHASHIFTMASK & flags) { + DarwinPressModifierKey(KeyPress, NX_MODIFIERKEY_ALPHALOCK); + DarwinPressModifierKey(KeyRelease, NX_MODIFIERKEY_ALPHALOCK); } - darwinEventQueue.events[oldtail].pScreen = darwinEventQueue.pEnqueueScreen; + + for(f=darwin_modifier_mask_list; *f; f++) + if(*f & flags && *f != NX_ALPHASHIFTMASK) { + key = DarwinModifierNXMaskToNXKey(*f); + if(key == -1) + ErrorF("DarwinUpdateModifiers: Unsupported NXMask: 0x%x\n", *f); + else + DarwinPressModifierKey(pressed, key); + } +} - // Update the tail after the event is prepared - darwinEventQueue.tail = newtail; +/* Generic handler for Xquartz-specifc events. When possible, these should + be moved into their own individual functions and set as handlers using + mieqSetHandler. */ + +static void DarwinEventHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, int nevents) { + int i; + + TA_SERVER(); + +// DEBUG_LOG("DarwinEventHandler(%d, %p, %p, %d)\n", screenNum, xe, dev, nevents); + for (i=0; i<nevents; i++) { + switch(xe[i].u.u.type) { + case kXquartzControllerNotify: + DEBUG_LOG("kXquartzControllerNotify\n"); + AppleWMSendEvent(AppleWMControllerNotify, + AppleWMControllerNotifyMask, + xe[i].u.clientMessage.u.l.longs0, + xe[i].u.clientMessage.u.l.longs1); + break; + + case kXquartzPasteboardNotify: + DEBUG_LOG("kXquartzPasteboardNotify\n"); + AppleWMSendEvent(AppleWMPasteboardNotify, + AppleWMPasteboardNotifyMask, + xe[i].u.clientMessage.u.l.longs0, + xe[i].u.clientMessage.u.l.longs1); + break; + + case kXquartzActivate: + DEBUG_LOG("kXquartzActivate\n"); + QuartzShow(xe[i].u.keyButtonPointer.rootX, + xe[i].u.keyButtonPointer.rootY); + AppleWMSendEvent(AppleWMActivationNotify, + AppleWMActivationNotifyMask, + AppleWMIsActive, 0); + break; + + case kXquartzDeactivate: + DEBUG_LOG("kXquartzDeactivate\n"); + AppleWMSendEvent(AppleWMActivationNotify, + AppleWMActivationNotifyMask, + AppleWMIsInactive, 0); + QuartzHide(); + break; - // Signal there is an event ready to handle - DarwinPokeEQ(); -} + case kXquartzReloadPreferences: + DEBUG_LOG("kXquartzReloadPreferences\n"); + AppleWMSendEvent(AppleWMActivationNotify, + AppleWMActivationNotifyMask, + AppleWMReloadPreferences, 0); + break; + + case kXquartzToggleFullscreen: + DEBUG_LOG("kXquartzToggleFullscreen\n"); + if (quartzEnableRootless) + QuartzSetFullscreen(!quartzHasRoot); + else if (quartzHasRoot) + QuartzHide(); + else + QuartzShow(xe[i].u.keyButtonPointer.rootX, + xe[i].u.keyButtonPointer.rootY); + break; + + case kXquartzSetRootless: + DEBUG_LOG("kXquartzSetRootless\n"); + QuartzSetRootless(xe[i].u.clientMessage.u.l.longs0); + if (!quartzEnableRootless && !quartzHasRoot) + QuartzHide(); + break; + + case kXquartzSetRootClip: + QuartzSetRootClip((Bool)xe[i].u.clientMessage.u.l.longs0); + break; + + case kXquartzQuit: + GiveUp(0); + break; + + case kXquartzSpaceChanged: + DEBUG_LOG("kXquartzSpaceChanged\n"); + QuartzSpaceChanged(xe[i].u.clientMessage.u.l.longs0); + break; + default: + ErrorF("Unknown application defined event type %d.\n", xe[i].u.u.type); + } + } +} -/* - * DarwinEQPointerPost - * Post a pointer event. Used by the mipointer.c routines. - */ -void DarwinEQPointerPost(DeviceIntPtr pdev, xEventPtr e) { - (*darwinEventQueue.pPtr->processInputProc) - (e, (DeviceIntPtr)darwinEventQueue.pPtr, 1); +void DarwinListenOnOpenFD(int fd) { + ErrorF("DarwinListenOnOpenFD: %d\n", fd); + + pthread_mutex_lock(&fd_add_lock); + if(fd_add_count < FD_ADD_MAX) + fd_add[fd_add_count++] = fd; + else + ErrorF("FD Addition buffer at max. Dropping fd addition request.\n"); + + pthread_cond_broadcast(&fd_add_ready_cond); + pthread_mutex_unlock(&fd_add_lock); } +static void DarwinProcessFDAdditionQueue_thread(void *args) { + pthread_mutex_lock(&fd_add_lock); + while(true) { + while(fd_add_count) { + DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1, fd_add[--fd_add_count]); + } + pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock); + } +} -void DarwinEQSwitchScreen(ScreenPtr pScreen, Bool fromDIX) { - darwinEventQueue.pEnqueueScreen = pScreen; - if (fromDIX) - darwinEventQueue.pDequeueScreen = pScreen; +static void kXquartzListenOnOpenFDHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, int nevents) { + size_t i; + TA_SERVER(); + + for (i=0; i<nevents; i++) { + ErrorF("Calling ListenOnOpenFD() for new fd: %d\n", (int)xe[i].u.clientMessage.u.l.longs0); + ListenOnOpenFD((int)xe[i].u.clientMessage.u.l.longs0, 1); + } } +Bool DarwinEQInit(void) { + mieqInit(); + mieqSetHandler(kXquartzReloadKeymap, DarwinKeyboardReloadHandler); + mieqSetHandler(kXquartzActivate, DarwinEventHandler); + mieqSetHandler(kXquartzDeactivate, DarwinEventHandler); + mieqSetHandler(kXquartzReloadPreferences, DarwinEventHandler); + mieqSetHandler(kXquartzSetRootClip, DarwinEventHandler); + mieqSetHandler(kXquartzQuit, DarwinEventHandler); + mieqSetHandler(kXquartzReadPasteboard, QuartzReadPasteboard); + mieqSetHandler(kXquartzWritePasteboard, QuartzWritePasteboard); + mieqSetHandler(kXquartzToggleFullscreen, DarwinEventHandler); + mieqSetHandler(kXquartzSetRootless, DarwinEventHandler); + mieqSetHandler(kXquartzSpaceChanged, DarwinEventHandler); + mieqSetHandler(kXquartzControllerNotify, DarwinEventHandler); + mieqSetHandler(kXquartzPasteboardNotify, DarwinEventHandler); + mieqSetHandler(kXquartzDisplayChanged, QuartzDisplayChangedHandler); + mieqSetHandler(kXquartzListenOnOpenFD, kXquartzListenOnOpenFDHandler); + + QuartzModeEQInit(); + + /* Note that this *could* cause a potential async issue, since we're checking + * darwinEvents without holding the lock, but darwinEvents is only ever set + * here, so I don't bother. + */ + if (!darwinEvents) { + darwinEvents = InitEventList(GetMaximumEventsNum());; + + if (!darwinEvents) + FatalError("Couldn't allocate event buffer\n"); + + darwinEvents_lock(); + pthread_cond_broadcast(&mieq_ready_cond); + darwinEvents_unlock(); + } + + if(!fd_add_tid) + fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL); + + return TRUE; +} /* * ProcessInputEvents * Read and process events from the event queue until it is empty. */ void ProcessInputEvents(void) { - EventRec *e; - int x, y; xEvent xe; - // button number and modifier mask of currently pressed fake button - input_check_flag=0; + int x = sizeof(xe); + + TA_SERVER(); - // ErrorF("calling mieqProcessInputEvents\n"); mieqProcessInputEvents(); // Empty the signaling pipe - x = sizeof(xe); - while (x == sizeof(xe)) - x = read(darwinEventReadFD, &xe, sizeof(xe)); - - while (darwinEventQueue.head != darwinEventQueue.tail) - { - if (screenIsSaved == SCREEN_SAVER_ON) - dixSaveScreens (serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); - - e = &darwinEventQueue.events[darwinEventQueue.head]; - xe = e->event; - - // Shift from global screen coordinates to coordinates relative to - // the origin of the current screen. - xe.u.keyButtonPointer.rootX -= darwinMainScreenX + - dixScreenOrigins[miPointerCurrentScreen()->myNum].x; - xe.u.keyButtonPointer.rootY -= darwinMainScreenY + - dixScreenOrigins[miPointerCurrentScreen()->myNum].y; - - /* ErrorF("old rootX = (%d,%d) darwinMainScreen = (%d,%d) dixScreenOrigins[%d]=(%d,%d)\n", - xe.u.keyButtonPointer.rootX, xe.u.keyButtonPointer.rootY, - darwinMainScreenX, darwinMainScreenY, - miPointerCurrentScreen()->myNum, - dixScreenOrigins[miPointerCurrentScreen()->myNum].x, - dixScreenOrigins[miPointerCurrentScreen()->myNum].y); */ - - //Assumption - screen switching can only occur on motion events - - if (e->pScreen != darwinEventQueue.pDequeueScreen) - { - darwinEventQueue.pDequeueScreen = e->pScreen; - x = xe.u.keyButtonPointer.rootX; - y = xe.u.keyButtonPointer.rootY; - if (darwinEventQueue.head == QUEUE_SIZE - 1) - darwinEventQueue.head = 0; - else - ++darwinEventQueue.head; - NewCurrentScreen (darwinEventQueue.pDequeueScreen, x, y); - } - else - { - if (darwinEventQueue.head == QUEUE_SIZE - 1) - darwinEventQueue.head = 0; - else - ++darwinEventQueue.head; - switch (xe.u.u.type) { - case KeyPress: - case KeyRelease: - ErrorF("Unexpected Keyboard event in DarwinProcessInputEvents\n"); - break; - - case ButtonPress: - ErrorF("Unexpected ButtonPress event in DarwinProcessInputEvents\n"); - break; - - case ButtonRelease: - ErrorF("Unexpected ButtonRelease event in DarwinProcessInputEvents\n"); - break; - - case MotionNotify: - ErrorF("Unexpected ButtonRelease event in DarwinProcessInputEvents\n"); - break; - - case kXDarwinUpdateModifiers: - ErrorF("Unexpected ButtonRelease event in DarwinProcessInputEvents\n"); - break; - - case kXDarwinUpdateButtons: - ErrorF("Unexpected XDarwinScrollWheel event in DarwinProcessInputEvents\n"); - break; - - case kXDarwinScrollWheel: - ErrorF("Unexpected XDarwinScrollWheel event in DarwinProcessInputEvents\n"); - break; - - case kXDarwinDeactivate: - DarwinReleaseModifiers(); - // fall through - default: - // Check for mode specific event - QuartzProcessEvent(&xe); - } - } + while (x == sizeof(xe)) { + x = read(darwinEventReadFD, &xe, sizeof(xe)); } - - // miPointerUpdate(); } /* Sends a null byte down darwinEventWriteFD, which will cause the Dispatch() event loop to check out event queue */ -void DarwinPokeEQ(void) { - char nullbyte=0; - input_check_flag++; - // <daniels> bushing: oh, i ... er ... christ. - write(darwinEventWriteFD, &nullbyte, 1); +static void DarwinPokeEQ(void) { + char nullbyte=0; + // <daniels> oh, i ... er ... christ. + write(darwinEventWriteFD, &nullbyte, 1); } -void DarwinSendPointerEvents(int ev_type, int ev_button, int pointer_x, int pointer_y) { - static int darwinFakeMouseButtonDown = 0; - static int darwinFakeMouseButtonMask = 0; - int i, num_events; - int valuators[2] = {pointer_x, pointer_y}; - if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) { - // Mimic multi-button mouse with modifier-clicks - // If both sets of modifiers are pressed, - // button 2 is clicked. - if ((old_flags & darwinFakeMouse2Mask) == darwinFakeMouse2Mask) { - DarwinSimulateMouseClick(pointer_x, pointer_y, 2, darwinFakeMouse2Mask); - darwinFakeMouseButtonDown = 2; - darwinFakeMouseButtonMask = darwinFakeMouse2Mask; - } else if ((old_flags & darwinFakeMouse3Mask) == darwinFakeMouse3Mask) { - DarwinSimulateMouseClick(pointer_x, pointer_y, 3, darwinFakeMouse3Mask); - darwinFakeMouseButtonDown = 3; - darwinFakeMouseButtonMask = darwinFakeMouse3Mask; +/* Convert from Appkit pointer input values to X input values: + * Note: pointer_x and pointer_y are relative to the upper-left of primary + * display. + */ +static void DarwinPrepareValuators(DeviceIntPtr pDev, int *valuators, ScreenPtr screen, + float pointer_x, float pointer_y, + float pressure, float tilt_x, float tilt_y) { + /* Fix offset between darwin and X screens */ + pointer_x -= darwinMainScreenX + dixScreenOrigins[screen->myNum].x; + pointer_y -= darwinMainScreenY + dixScreenOrigins[screen->myNum].y; + + if(pointer_x < 0.0) + pointer_x = 0.0; + + if(pointer_y < 0.0) + pointer_y = 0.0; + + if(pDev == darwinPointer) { + valuators[0] = pointer_x; + valuators[1] = pointer_y; + valuators[2] = 0; + valuators[3] = 0; + valuators[4] = 0; + } else { + /* Setup our array of values */ + valuators[0] = XQUARTZ_VALUATOR_LIMIT * (pointer_x / (float)screenInfo.screens[0]->width); + valuators[1] = XQUARTZ_VALUATOR_LIMIT * (pointer_y / (float)screenInfo.screens[0]->height); + valuators[2] = XQUARTZ_VALUATOR_LIMIT * pressure; + valuators[3] = XQUARTZ_VALUATOR_LIMIT * tilt_x; + valuators[4] = XQUARTZ_VALUATOR_LIMIT * tilt_y; } - } - if (ev_type == ButtonRelease && darwinFakeButtons && darwinFakeMouseButtonDown) { - // If last mousedown was a fake click, don't check for - // mouse modifiers here. The user may have released the - // modifiers before the mouse button. - ev_button = darwinFakeMouseButtonDown; - darwinFakeMouseButtonDown = 0; - // Bring modifiers back up to date - DarwinUpdateModifiers(KeyPress, darwinFakeMouseButtonMask & old_flags); - darwinFakeMouseButtonMask = 0; - } - - num_events = GetPointerEvents(darwinEvents, darwinPointer, ev_type, ev_button, - POINTER_ABSOLUTE, 0, 2, valuators); - - for(i=0; i<num_events; i++) mieqEnqueue (darwinPointer,&darwinEvents[i]); - DarwinPokeEQ(); + //DEBUG_LOG("Pointer (%f, %f), Valuators: {%d,%d,%d,%d,%d}\n", pointer_x, pointer_y, + // valuators[0], valuators[1], valuators[2], valuators[3], valuators[4]); } -void DarwinSendKeyboardEvents(int ev_type, int keycode) { - int i, num_events; - if (old_flags == 0 && darwinSyncKeymap && darwinKeymapFile == NULL) { - /* See if keymap has changed. */ +void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, float pointer_x, float pointer_y, + float pressure, float tilt_x, float tilt_y) { + static int darwinFakeMouseButtonDown = 0; + int i, num_events; + ScreenPtr screen; + int valuators[5]; + + //DEBUG_LOG("x=%f, y=%f, p=%f, tx=%f, ty=%f\n", pointer_x, pointer_y, pressure, tilt_x, tilt_y); + + if(!darwinEvents) { + DEBUG_LOG("DarwinSendPointerEvents called before darwinEvents was initialized\n"); + return; + } + + screen = miPointerGetScreen(pDev); + if(!screen) { + DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n"); + return; + } - static unsigned int last_seed; - unsigned int this_seed; + /* Handle fake click */ + if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) { + if(darwinFakeMouseButtonDown != 0) { + /* We're currently "down" with another button, so release it first */ + DarwinSendPointerEvents(pDev, ButtonRelease, darwinFakeMouseButtonDown, pointer_x, pointer_y, pressure, tilt_x, tilt_y); + darwinFakeMouseButtonDown=0; + } + if (darwin_modifier_flags & darwinFakeMouse2Mask) { + ev_button = 2; + darwinFakeMouseButtonDown = 2; + DarwinUpdateModKeys(darwin_modifier_flags & ~darwinFakeMouse2Mask); + } else if (darwin_modifier_flags & darwinFakeMouse3Mask) { + ev_button = 3; + darwinFakeMouseButtonDown = 3; + DarwinUpdateModKeys(darwin_modifier_flags & ~darwinFakeMouse3Mask); + } + } + + if (ev_type == ButtonRelease && ev_button == 1) { + if(darwinFakeMouseButtonDown) { + ev_button = darwinFakeMouseButtonDown; + } - this_seed = QuartzSystemKeymapSeed(); - if (this_seed != last_seed) { - last_seed = this_seed; - DarwinKeyboardReload(darwinKeyboard); - } - } + if(darwinFakeMouseButtonDown == 2) { + DarwinUpdateModKeys(darwin_modifier_flags & ~darwinFakeMouse2Mask); + } else if(darwinFakeMouseButtonDown == 3) { + DarwinUpdateModKeys(darwin_modifier_flags & ~darwinFakeMouse3Mask); + } + + darwinFakeMouseButtonDown = 0; + } - num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE); - for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard,&darwinEvents[i]); - DarwinPokeEQ(); + DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y); + darwinEvents_lock(); { + num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button, + POINTER_ABSOLUTE, 0, pDev==darwinTabletCurrent?5:2, valuators); + for(i=0; i<num_events; i++) mieqEnqueue (pDev, darwinEvents[i].event); + DarwinPokeEQ(); + } darwinEvents_unlock(); } -/* Send the appropriate number of button 4 / 5 clicks to emulate scroll wheel */ -void DarwinSendScrollEvents(float count, int pointer_x, int pointer_y) { - int i; - int ev_button = count > 0.0f ? 4 : 5; - int valuators[2] = {pointer_x, pointer_y}; - - for (count = fabs(count); count > 0.0; count = count - 1.0f) { - int num_events = GetPointerEvents(darwinEvents, darwinPointer, ButtonPress, ev_button, - POINTER_ABSOLUTE, 0, 2, valuators); - for(i=0; i<num_events; i++) mieqEnqueue(darwinPointer,&darwinEvents[i]); - num_events = GetPointerEvents(darwinEvents, darwinPointer, ButtonRelease, ev_button, - POINTER_ABSOLUTE, 0, 2, valuators); - for(i=0; i<num_events; i++) mieqEnqueue(darwinPointer,&darwinEvents[i]); - } - DarwinPokeEQ(); +void DarwinSendKeyboardEvents(int ev_type, int keycode) { + int i, num_events; + + if(!darwinEvents) { + DEBUG_LOG("DarwinSendKeyboardEvents called before darwinEvents was initialized\n"); + return; + } + + darwinEvents_lock(); { + num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE); + for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard,darwinEvents[i].event); + DarwinPokeEQ(); + } darwinEvents_unlock(); +} + +void DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) { + int i, num_events; + ScreenPtr screen; + DeviceIntPtr pDev = darwinTabletCurrent; + int valuators[5]; + + DEBUG_LOG("DarwinSendProximityEvents(%d, %f, %f)\n", ev_type, pointer_x, pointer_y); + + if(!darwinEvents) { + DEBUG_LOG("DarwinSendProximityEvents called before darwinEvents was initialized\n"); + return; + } + + screen = miPointerGetScreen(pDev); + if(!screen) { + DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n"); + return; + } + + DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, 0.0f, 0.0f, 0.0f); + darwinEvents_lock(); { + num_events = GetProximityEvents(darwinEvents, pDev, ev_type, + 0, 5, valuators); + for(i=0; i<num_events; i++) mieqEnqueue (pDev,darwinEvents[i].event); + DarwinPokeEQ(); + } darwinEvents_unlock(); +} + + +/* Send the appropriate number of button clicks to emulate scroll wheel */ +void DarwinSendScrollEvents(float count_x, float count_y, + float pointer_x, float pointer_y, + float pressure, float tilt_x, float tilt_y) { + if(!darwinEvents) { + DEBUG_LOG("DarwinSendScrollEvents called before darwinEvents was initialized\n"); + return; + } + + int sign_x = count_x > 0.0f ? SCROLLWHEELLEFTFAKE : SCROLLWHEELRIGHTFAKE; + int sign_y = count_y > 0.0f ? SCROLLWHEELUPFAKE : SCROLLWHEELDOWNFAKE; + count_x = fabs(count_x); + count_y = fabs(count_y); + + while ((count_x > 0.0f) || (count_y > 0.0f)) { + if (count_x > 0.0f) { + DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y); + DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y); + count_x = count_x - 1.0f; + } + if (count_y > 0.0f) { + DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y); + DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y); + count_y = count_y - 1.0f; + } + } } /* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to reflect changing modifier flags (alt, control, meta, etc) */ void DarwinUpdateModKeys(int flags) { - DarwinUpdateModifiers(KeyRelease, old_flags & ~flags); - DarwinUpdateModifiers(KeyPress, ~old_flags & flags); - old_flags = flags; + DarwinUpdateModifiers(KeyRelease, darwin_modifier_flags & ~flags); + DarwinUpdateModifiers(KeyPress, ~darwin_modifier_flags & flags); + darwin_modifier_flags = flags; +} + +/* + * DarwinSendDDXEvent + * Send the X server thread a message by placing it on the event queue. + */ +void DarwinSendDDXEvent(int type, int argc, ...) { + xEvent xe; + INT32 *argv; + int i, max_args; + va_list args; + + memset(&xe, 0, sizeof(xe)); + xe.u.u.type = type; + xe.u.clientMessage.u.l.type = type; + + argv = &xe.u.clientMessage.u.l.longs0; + max_args = 4; + + if (argc > 0 && argc <= max_args) { + va_start (args, argc); + for (i = 0; i < argc; i++) + argv[i] = (int) va_arg (args, int); + va_end (args); + } + + darwinEvents_lock(); { + mieqEnqueue(darwinPointer, &xe); + DarwinPokeEQ(); + } darwinEvents_unlock(); } |