diff --git a/configure.ac b/configure.ac index 339fdfc2e..56e51a407 100644 --- a/configure.ac +++ b/configure.ac @@ -725,9 +725,9 @@ case $host_os in save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -framework Carbon" AC_LINK_IFELSE([char FSFindFolder(); int main() { FSFindFolder(); return 0;}], - [xorg_cv_Carbon_framework=yes], - [xorg_cv_Carbon_framework=no]) - LDFLAGS=$save_LDFLAGS]) + [xorg_cv_Carbon_framework=yes], + [xorg_cv_Carbon_framework=no]) + LDFLAGS=$save_LDFLAGS]) if test "X$xorg_cv_Carbon_framework" = Xyes; then XQUARTZ=yes @@ -736,6 +736,10 @@ case $host_os in fi fi + AC_CHECK_FUNC(dispatch_async, + AC_DEFINE([HAVE_LIBDISPATCH], 1, [Define to 1 if you have the libdispatch (GCD) available]), + []) + if test "x$XQUARTZ" = xyes ; then XQUARTZ=yes XVFB=no diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m index 3521517a2..e56bf0cf3 100644 --- a/hw/xquartz/X11Application.m +++ b/hw/xquartz/X11Application.m @@ -61,6 +61,12 @@ extern int xpbproxy_run (void); #define XSERVER_VERSION "?" #endif +#ifdef HAVE_LIBDISPATCH +#include + +static dispatch_queue_t eventTranslationQueue; +#endif + /* Stuck modifier / button state... force release when we context switch */ static NSEventType keyState[NUM_KEYCODES]; @@ -385,7 +391,15 @@ static void message_kit_thread (SEL selector, NSObject *arg) { if (for_appkit) [super sendEvent:e]; - if (for_x) [self sendX11NSEvent:e]; + if (for_x) { +#ifdef HAVE_LIBDISPATCH + dispatch_async(eventTranslationQueue, ^{ +#endif + [self sendX11NSEvent:e]; +#ifdef HAVE_LIBDISPATCH + }); +#endif + } } - (void) set_window_menu:(NSArray *)list { @@ -950,7 +964,7 @@ environment the next time you start X11?", @"Startup xinitrc dialog"); [X11App prefs_synchronize]; } -static inline pthread_t create_thread(void *func, void *arg) { +static inline pthread_t create_thread(void *(*func)(void *), void *arg) { pthread_attr_t attr; pthread_t tid; @@ -999,6 +1013,11 @@ void X11ApplicationMain (int argc, char **argv, char **envp) { aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) - NSMaxY([[NSScreen mainScreen] visibleFrame]); +#ifdef HAVE_LIBDISPATCH + eventTranslationQueue = dispatch_queue_create(LAUNCHD_ID_PREFIX".X11.NSEventsToX11EventsQueue", NULL); + assert(eventTranslationQueue != NULL); +#endif + /* Set the key layout seed before we start the server */ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 last_key_layout = TISCopyCurrentKeyboardLayoutInputSource(); @@ -1079,13 +1098,29 @@ static const char *untrusted_str(NSEvent *e) { #endif - (void) sendX11NSEvent:(NSEvent *)e { - NSPoint location = NSZeroPoint, tilt = NSZeroPoint; + NSPoint location = NSZeroPoint; int ev_button, ev_type; - float pressure = 0.0; + static float pressure = 0.0; // static so ProximityOut will have the value from the previous tablet event + static NSPoint tilt; // static so ProximityOut will have the value from the previous tablet event + static DeviceIntPtr darwinTabletCurrent = NULL; + static BOOL needsProximityIn = NO; // Do we do need to handle a pending ProximityIn once we have pressure/tilt? DeviceIntPtr pDev; int modifierFlags; BOOL isMouseOrTabletEvent, isTabletEvent; +#ifdef HAVE_LIBDISPATCH + static dispatch_once_t once_pred; + dispatch_once(&once_pred, ^{ + tilt = NSZeroPoint; + darwinTabletCurrent = darwinTabletStylus; + }); +#else + if(!darwinTabletCurrent) { + tilt = NSZeroPoint; + darwinTabletCurrent = darwinTabletStylus; + } +#endif + isMouseOrTabletEvent = [e type] == NSLeftMouseDown || [e type] == NSOtherMouseDown || [e type] == NSRightMouseDown || [e type] == NSLeftMouseUp || [e type] == NSOtherMouseUp || [e type] == NSRightMouseUp || [e type] == NSLeftMouseDragged || [e type] == NSOtherMouseDragged || [e type] == NSRightMouseDragged || @@ -1207,19 +1242,14 @@ static const char *untrusted_str(NSEvent *e) { darwinTabletCurrent=darwinTabletCursor; break; } - - /* NSTabletProximityEventSubtype doesn't encode pressure ant tilt - * So we just pretend the motion was caused by the mouse. Hopefully - * we'll have a better solution for this in the future (like maybe - * NSTabletProximityEventSubtype will come from NSTabletPoint - * rather than NSMouseMoved. - pressure = [e pressure]; - tilt = [e tilt]; - pDev = darwinTabletCurrent; - */ - DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut, - location.x, location.y); + if([e isEnteringProximity]) + needsProximityIn = YES; + else + DarwinSendProximityEvents(darwinTabletCurrent, ProximityOut, + location.x, location.y, pressure, + tilt.x, tilt.y); + return; } if ([e type] == NSTabletPoint || [e subtype] == NSTabletPointEventSubtype) { @@ -1227,6 +1257,14 @@ static const char *untrusted_str(NSEvent *e) { tilt = [e tilt]; pDev = darwinTabletCurrent; + + if(needsProximityIn) { + DarwinSendProximityEvents(darwinTabletCurrent, ProximityIn, + location.x, location.y, pressure, + tilt.x, tilt.y); + + needsProximityIn = NO; + } } if(!XQuartzServerVisible && noTestExtensions) { @@ -1280,8 +1318,12 @@ static const char *untrusted_str(NSEvent *e) { break; } - DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut, - location.x, location.y); + if([e isEnteringProximity]) + needsProximityIn = YES; + else + DarwinSendProximityEvents(darwinTabletCurrent, ProximityOut, + location.x, location.y, pressure, + tilt.x, tilt.y); break; case NSScrollWheel: diff --git a/hw/xquartz/darwin.c b/hw/xquartz/darwin.c index 3b6f0a29e..00be74ba0 100644 --- a/hw/xquartz/darwin.c +++ b/hw/xquartz/darwin.c @@ -117,7 +117,6 @@ unsigned int windowItemModMask = NX_COMMANDMASK; // devices DeviceIntPtr darwinKeyboard = NULL; DeviceIntPtr darwinPointer = NULL; -DeviceIntPtr darwinTabletCurrent = NULL; DeviceIntPtr darwinTabletStylus = NULL; DeviceIntPtr darwinTabletCursor = NULL; DeviceIntPtr darwinTabletEraser = NULL; @@ -492,8 +491,6 @@ void InitInput( int argc, char **argv ) darwinTabletEraser = AddInputDevice(serverClient, DarwinTabletProc, TRUE); darwinTabletEraser->name = strdup("eraser"); - darwinTabletCurrent = darwinTabletStylus; - DarwinEQInit(); QuartzInitInput(argc, argv); diff --git a/hw/xquartz/darwin.h b/hw/xquartz/darwin.h index e874af24c..360225742 100644 --- a/hw/xquartz/darwin.h +++ b/hw/xquartz/darwin.h @@ -56,7 +56,6 @@ extern io_connect_t darwinParamConnect; extern int darwinEventReadFD; extern int darwinEventWriteFD; extern DeviceIntPtr darwinPointer; -extern DeviceIntPtr darwinTabletCurrent; extern DeviceIntPtr darwinTabletCursor; extern DeviceIntPtr darwinTabletStylus; extern DeviceIntPtr darwinTabletEraser; diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c index 451129e8b..40d8a4e9e 100644 --- a/hw/xquartz/darwinEvents.c +++ b/hw/xquartz/darwinEvents.c @@ -61,6 +61,7 @@ in this Software without prior written authorization from The Open Group. #include #include #include +#include #include @@ -93,7 +94,7 @@ static pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER; /*** Pthread Magics ***/ -static pthread_t create_thread(void *func, void *arg) { +static pthread_t create_thread(void *(*func)(void *), void *arg) { pthread_attr_t attr; pthread_t tid; @@ -304,7 +305,28 @@ void DarwinListenOnOpenFD(int fd) { pthread_mutex_unlock(&fd_add_lock); } -static void DarwinProcessFDAdditionQueue_thread(void *args) { +static void *DarwinProcessFDAdditionQueue_thread(void *args) { + /* TODO: Possibly adjust this to no longer be a race... maybe trigger this + * once a client connects and claims to be the WM. + * + * From ajax: + * There's already an internal callback chain for setting selection [in 1.5] + * ownership. See the CallSelectionCallback at the bottom of + * ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook + * into it. + */ + + struct timespec sleep_for; + struct timespec sleep_remaining; + + sleep_for.tv_sec = 3; + sleep_for.tv_nsec = 0; + + ErrorF("X11.app: DarwinProcessFDAdditionQueue_thread: Sleeping to allow xinitrc to catchup.\n"); + while(nanosleep(&sleep_for, &sleep_remaining) != 0) { + sleep_for = sleep_remaining; + } + pthread_mutex_lock(&fd_add_lock); while(true) { while(fd_add_count) { @@ -312,6 +334,8 @@ static void DarwinProcessFDAdditionQueue_thread(void *args) { } pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock); } + + return NULL; } Bool DarwinEQInit(void) { @@ -465,7 +489,7 @@ void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, floa DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y); darwinEvents_lock(); { ValuatorMask mask; - valuator_mask_set_range(&mask, 0, (pDev == darwinTabletCurrent) ? 5 : 2, valuators); + valuator_mask_set_range(&mask, 0, (pDev == darwinPointer) ? 2 : 5, valuators); num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button, POINTER_ABSOLUTE, &mask); for(i=0; i #include #include -#include #include #include +#ifdef HAVE_LIBDISPATCH +#include +#else +#include +#endif + #include #include -#include #include #include @@ -95,8 +99,9 @@ int server_main(int argc, char **argv, char **envp); static int execute(const char *command); static char *command_from_prefs(const char *key, const char *default_value); +#ifndef HAVE_LIBDISPATCH /*** Pthread Magics ***/ -static pthread_t create_thread(void *func, void *arg) { +static pthread_t create_thread(void *(*func)(void *), void *arg) { pthread_attr_t attr; pthread_t tid; @@ -108,6 +113,7 @@ static pthread_t create_thread(void *func, void *arg) { return tid; } +#endif /*** Mach-O IPC Stuffs ***/ @@ -200,11 +206,15 @@ typedef struct { /* This thread accepts an incoming connection and hands off the file * descriptor for the new connection to accept_fd_handoff() */ -static void socket_handoff_thread(void *arg) { +#ifdef HAVE_LIBDISPATCH +static void socket_handoff(socket_handoff_t *handoff_data) { +#else +static void *socket_handoff_thread(void *arg) { socket_handoff_t *handoff_data = (socket_handoff_t *)arg; +#endif + int launchd_fd = -1; int connected_fd; - unsigned remain; /* Now actually get the passed file descriptor from this connection * If we encounter an error, keep listening. @@ -227,22 +237,13 @@ static void socket_handoff_thread(void *arg) { close(handoff_data->fd); unlink(handoff_data->filename); free(handoff_data); - - /* TODO: Clean up this race better... giving xinitrc time to run... need to wait for 1.5 branch: - * - * From ajax: - * There's already an internal callback chain for setting selection [in 1.5] - * ownership. See the CallSelectionCallback at the bottom of - * ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook - * into it. - */ - - remain = 3000000; - fprintf(stderr, "X11.app: Received new $DISPLAY fd: %d ... sleeping to allow xinitrc to catchup.\n", launchd_fd); - while((remain = usleep(remain)) > 0); - + fprintf(stderr, "X11.app Handing off fd to server thread via DarwinListenOnOpenFD(%d)\n", launchd_fd); DarwinListenOnOpenFD(launchd_fd); + +#ifndef HAVE_LIBDISPATCH + return NULL; +#endif } static int create_socket(char *filename_out) { @@ -311,8 +312,14 @@ kern_return_t do_request_fd_handoff_socket(mach_port_t port, string_t filename) } strlcpy(filename, handoff_data->filename, STRING_T_SIZE); - + +#ifdef HAVE_LIBDISPATCH + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ + socket_handoff(handoff_data); + }); +#else create_thread(socket_handoff_thread, handoff_data); +#endif #ifdef DEBUG fprintf(stderr, "X11.app: Thread created for handoff. Returning success to tell caller to connect and push the fd.\n"); diff --git a/include/dix-config.h.in b/include/dix-config.h.in index fd9ecced2..14229b435 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -136,6 +136,9 @@ /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM +/* Define to 1 if you have the libdispatch (GCD) available */ +#undef HAVE_LIBDISPATCH + /* Define to 1 if you have the `link' function. */ #undef HAVE_LINK