diff options
author | Jeremy Huddleston <jeremyhu@freedesktop.org> | 2008-09-24 22:51:03 -0700 |
---|---|---|
committer | Jeremy Huddleston <jeremyhu@freedesktop.org> | 2008-09-26 12:31:21 -0700 |
commit | 12a59c44cb68843a60fc43257930d1cbeb971b7a (patch) | |
tree | b27f4c93a99cd669605aa93ffdfea0f8ea705b16 /hw | |
parent | ee87c9b02401a7a08b396884ba412a503b078bbd (diff) |
XQuartz: Fixed threading issue with TSM.
(cherry picked from commit 93ab4e0071670bb80bfa1170dd97ed9d6d51c67a)
Diffstat (limited to 'hw')
-rw-r--r-- | hw/xquartz/X11Application.h | 1 | ||||
-rw-r--r-- | hw/xquartz/X11Application.m | 78 | ||||
-rw-r--r-- | hw/xquartz/darwinEvents.c | 13 | ||||
-rw-r--r-- | hw/xquartz/quartzKeyboard.c | 75 | ||||
-rw-r--r-- | hw/xquartz/quartzKeyboard.h | 4 |
5 files changed, 90 insertions, 81 deletions
diff --git a/hw/xquartz/X11Application.h b/hw/xquartz/X11Application.h index ce3fa7bda..0caaba83f 100644 --- a/hw/xquartz/X11Application.h +++ b/hw/xquartz/X11Application.h @@ -56,7 +56,6 @@ - (void) prefs_synchronize; - (OSX_BOOL) x_active; - @end extern X11Application *X11App; diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m index 213d9ed1d..0436db8f9 100644 --- a/hw/xquartz/X11Application.m +++ b/hw/xquartz/X11Application.m @@ -39,6 +39,7 @@ #include "darwin.h" #include "darwinEvents.h" +#include "quartzKeyboard.h" #include "quartz.h" #define _APPLEWM_SERVER_ #include "X11/extensions/applewm.h" @@ -61,6 +62,8 @@ int X11EnableKeyEquivalents = TRUE; int quartzHasRoot = FALSE, quartzEnableRootless = TRUE; +static TISInputSourceRef last_key_layout; + extern int darwinFakeButtons; extern Bool enable_stereo; @@ -163,8 +166,7 @@ static void message_kit_thread (SEL selector, NSObject *arg) { - (void) activateX:(OSX_BOOL)state { /* Create a TSM document that supports full Unicode input, and - have it activated while X is active (unless using the old - keymapping files) */ + have it activated while X is active */ static TSMDocumentID x11_document; DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active) if (state) { @@ -589,8 +591,8 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { - (void) prefs_set_boolean:(NSString *)key value:(int)value { CFPreferencesSetValue ((CFStringRef) key, - (CFTypeRef) value ? kCFBooleanTrue - : kCFBooleanFalse, CFSTR (APP_PREFS), + (CFTypeRef) (value ? kCFBooleanTrue + : kCFBooleanFalse), CFSTR (APP_PREFS), kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } @@ -847,9 +849,21 @@ void X11ApplicationMain (int argc, char **argv, char **envp) { aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) - NSMaxY([[NSScreen mainScreen] visibleFrame]); + /* Set the key layout seed before we start the server */ + last_key_layout = TISCopyCurrentKeyboardLayoutInputSource(); + + if(!last_key_layout) { + fprintf(stderr, "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n"); + } + + memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); + if (!QuartzReadSystemKeymap(&keyInfo)) { + fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n"); + } + /* Tell the server thread that it can proceed */ QuartzInitServer(argc, argv, envp); - + [NSApp run]; /* not reached */ } @@ -880,12 +894,12 @@ static void send_nsevent(NSEvent *e) { NSWindow *window; int pointer_x, pointer_y, ev_button, ev_type; float pressure, tilt_x, tilt_y; - + /* convert location to be relative to top-left of primary display */ location = [e locationInWindow]; window = [e window]; screen = [[[NSScreen screens] objectAtIndex:0] frame]; - + if (window != nil) { NSRect frame = [window frame]; pointer_x = location.x + frame.origin.x; @@ -895,18 +909,18 @@ static void send_nsevent(NSEvent *e) { pointer_x = location.x; pointer_y = (screen.origin.y + screen.size.height) - location.y; } - + pressure = 0; // for tablets tilt_x = 0; tilt_y = 0; - + /* We don't receive modifier key events while out of focus, and 3button * emulation mucks this up, so we need to check our modifier flag state * on every event... ugg */ if(darwin_modifier_flags != [e modifierFlags]) DarwinUpdateModKeys([e modifierFlags]); - + switch ([e type]) { case NSLeftMouseDown: ev_button=1; ev_type=ButtonPress; goto handle_mouse; case NSOtherMouseDown: ev_button=2; ev_type=ButtonPress; goto handle_mouse; @@ -919,7 +933,7 @@ static void send_nsevent(NSEvent *e) { case NSRightMouseDragged: ev_button=3; ev_type=MotionNotify; goto handle_mouse; case NSMouseMoved: ev_button=0; ev_type=MotionNotify; goto handle_mouse; case NSTabletPoint: ev_button=0; ev_type=MotionNotify; goto handle_mouse; - + handle_mouse: if ([e type] == NSTabletPoint || [e subtype] == NSTabletPointEventSubtype) { pressure = [e pressure]; @@ -941,16 +955,16 @@ static void send_nsevent(NSEvent *e) { darwinTabletCurrent=darwinTabletCursor; break; } - + DarwinSendProximityEvents([e isEnteringProximity]?ProximityIn:ProximityOut, pointer_x, pointer_y); } - + DarwinSendPointerEvents(ev_type, ev_button, pointer_x, pointer_y, pressure, tilt_x, tilt_y); - + break; - + case NSTabletProximity: switch([e pointingDeviceType]) { case NSEraserPointingDevice: @@ -965,20 +979,44 @@ static void send_nsevent(NSEvent *e) { darwinTabletCurrent=darwinTabletCursor; break; } - + DarwinSendProximityEvents([e isEnteringProximity]?ProximityIn:ProximityOut, pointer_x, pointer_y); break; - + case NSScrollWheel: DarwinSendScrollEvents([e deltaX], [e deltaY], pointer_x, pointer_y, pressure, tilt_x, tilt_y); break; - - case NSKeyDown: case NSKeyUp: + + case NSKeyDown: case NSKeyUp: + if(darwinSyncKeymap) { + TISInputSourceRef key_layout = TISCopyCurrentKeyboardLayoutInputSource(); + TISInputSourceRef clear; + if (CFEqual(key_layout, last_key_layout)) { + CFRelease(key_layout); + } else { + /* Swap/free thread-safely */ + clear = last_key_layout; + last_key_layout = key_layout; + CFRelease(clear); + + /* Update keyInfo */ + pthread_mutex_lock(&keyInfo_mutex); + memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); + if (!QuartzReadSystemKeymap(&keyInfo)) { + fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n"); + } + pthread_mutex_unlock(&keyInfo_mutex); + + /* Tell server thread to deal with new keyInfo */ + DarwinSendDDXEvent(kXquartzReloadKeymap, 0); + } + } + DarwinSendKeyboardEvents(([e type] == NSKeyDown) ? KeyPress : KeyRelease, [e keyCode]); break; - + default: break; /* for gcc */ } } diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c index 1db61d9e4..729cc9a4d 100644 --- a/hw/xquartz/darwinEvents.c +++ b/hw/xquartz/darwinEvents.c @@ -473,19 +473,6 @@ void DarwinSendKeyboardEvents(int ev_type, int keycode) { return; } - if (darwinSyncKeymap) { - /* See if keymap has changed. */ - - static unsigned int last_seed; - unsigned int this_seed; - - this_seed = QuartzSystemKeymapSeed(); - if (this_seed != last_seed) { - last_seed = this_seed; - DarwinSendDDXEvent(kXquartzReloadKeymap, 0); - } - } - darwinEvents_lock(); { num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE); for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard,&darwinEvents[i]); diff --git a/hw/xquartz/quartzKeyboard.c b/hw/xquartz/quartzKeyboard.c index cee582bbe..cd46fb2d9 100644 --- a/hw/xquartz/quartzKeyboard.c +++ b/hw/xquartz/quartzKeyboard.c @@ -52,6 +52,8 @@ #include "quartzKeyboard.h" #include "quartzAudio.h" +#include "threadSafety.h" + #ifdef NDEBUG #undef NDEBUG #include <assert.h> @@ -59,6 +61,7 @@ #else #include <assert.h> #endif +#include <pthread.h> #include "xkbsrv.h" #include "exevents.h" @@ -304,6 +307,7 @@ const static struct { }; darwinKeyboardInfo keyInfo; +pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER; static void DarwinChangeKeyboardControl( DeviceIntPtr device, KeybdCtrl *ctrl ) { @@ -411,18 +415,16 @@ static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) { * it to an equivalent X keyboard map and modifier map. */ static void DarwinLoadKeyboardMapping(KeySymsRec *keySyms) { - memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); - - if (!QuartzReadSystemKeymap(&keyInfo)) { - FatalError("Could not build a valid keymap."); - } - + pthread_mutex_lock(&keyInfo_mutex); + DarwinBuildModifierMaps(&keyInfo); keySyms->map = keyInfo.keyMap; keySyms->mapWidth = GLYPHS_PER_KEY; keySyms->minKeyCode = MIN_KEYCODE; keySyms->maxKeyCode = MAX_KEYCODE; + + pthread_mutex_unlock(&keyInfo_mutex); } void QuartzXkbUpdate(DeviceIntPtr pDev) { @@ -450,27 +452,27 @@ void DarwinKeyboardInit(DeviceIntPtr pDev) { assert( darwinParamConnect = NXOpenEventStatus() ); DarwinLoadKeyboardMapping(&keySyms); - /* Initialize the seed, so we don't reload the keymap unnecessarily - (and possibly overwrite xinitrc changes) */ - QuartzSystemKeymapSeed(); - #ifdef XQUARTZ_USE_XKB XkbComponentNamesRec names; bzero(&names, sizeof(names)); /* We need to really have rules... or something... */ XkbSetRulesDflts("base", "pc105", "us", NULL, NULL); + pthread_mutex_lock(&keyInfo_mutex); assert(XkbInitKeyboardDeviceStruct(pDev, &names, &keySyms, keyInfo.modMap, QuartzBell, DarwinChangeKeyboardControl)); assert(SetKeySymsMap(&pDev->key->curKeySyms, &keySyms)); assert(keyInfo.modMap!=NULL); assert(pDev->key->modifierMap!=NULL); memcpy(pDev->key->modifierMap, keyInfo.modMap, sizeof(keyInfo.modMap)); + pthread_mutex_unlock(&keyInfo_mutex); QuartzXkbUpdate(pDev); #else + pthread_mutex_lock(&keyInfo_mutex); assert( InitKeyboardDeviceStruct( (DevicePtr)pDev, &keySyms, keyInfo.modMap, QuartzBell, DarwinChangeKeyboardControl )); + pthread_mutex_unlock(&keyInfo_mutex); SwitchCoreKeyboard(pDev); #endif } @@ -492,11 +494,14 @@ void DarwinKeyboardReloadHandler(int screenNum, xEventPtr xe, DeviceIntPtr pDev, if (pDev->key->modifierKeyMap) xfree(pDev->key->modifierKeyMap); xfree(pDev->key); } - + + pthread_mutex_lock(&keyInfo_mutex); if (!InitKeyClassDeviceStruct(pDev, &keySyms, keyInfo.modMap)) { DEBUG_LOG("InitKeyClassDeviceStruct failed\n"); + pthread_mutex_unlock(&keyInfo_mutex); return; } + pthread_mutex_unlock(&keyInfo_mutex); SendMappingNotify(MappingKeyboard, MIN_KEYCODE, NUM_KEYCODES, 0); SendMappingNotify(MappingModifier, 0, 0, 0); @@ -521,7 +526,12 @@ void DarwinKeyboardReloadHandler(int screenNum, xEventPtr xe, DeviceIntPtr pDev, * Returns 0 if key+side is not a known modifier. */ int DarwinModifierNXKeyToNXKeycode(int key, int side) { - return keyInfo.modifierKeycodes[key][side]; + int retval; + pthread_mutex_lock(&keyInfo_mutex); + retval = keyInfo.modifierKeycodes[key][side]; + pthread_mutex_unlock(&keyInfo_mutex); + + return retval; } /* @@ -532,6 +542,7 @@ int DarwinModifierNXKeyToNXKeycode(int key, int side) { int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) { int key, side; + pthread_mutex_lock(&keyInfo_mutex); keycode += MIN_KEYCODE; // search modifierKeycodes for this keycode+side for (key = 0; key < NX_NUMMODIFIERS; key++) { @@ -539,8 +550,13 @@ int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) { if (keyInfo.modifierKeycodes[key][side] == keycode) break; } } - if (key == NX_NUMMODIFIERS) return -1; + if (key == NX_NUMMODIFIERS) { + pthread_mutex_unlock(&keyInfo_mutex); + return -1; + } if (outSide) *outSide = side; + + pthread_mutex_unlock(&keyInfo_mutex); return key; } @@ -666,39 +682,6 @@ Bool LegalModifier(unsigned int key, DeviceIntPtr pDev) return 1; } -/* TODO: Not thread safe */ -unsigned int QuartzSystemKeymapSeed(void) { - static unsigned int seed = 0; -//#if defined(__x86_64__) || defined(__ppc64__) -#if 1 - static TISInputSourceRef last_key_layout = NULL; - TISInputSourceRef key_layout; - - key_layout = TISCopyCurrentKeyboardLayoutInputSource(); - - if(last_key_layout) { - if (CFEqual(key_layout, last_key_layout)) { - CFRelease(key_layout); - } else { - seed++; - CFRelease(last_key_layout); - last_key_layout = key_layout; - } - } else { - last_key_layout = key_layout; - } -#else - static KeyboardLayoutRef last_key_layout; - KeyboardLayoutRef key_layout; - - KLGetCurrentKeyboardLayout (&key_layout); - if (key_layout != last_key_layout) - seed++; - last_key_layout = key_layout; -#endif - return seed; -} - static inline UniChar macroman2ucs(unsigned char c) { /* Precalculated table mapping MacRoman-128 to Unicode. Generated by creating single element CFStringRefs then extracting the diff --git a/hw/xquartz/quartzKeyboard.h b/hw/xquartz/quartzKeyboard.h index d62a79d8e..eb7936662 100644 --- a/hw/xquartz/quartzKeyboard.h +++ b/hw/xquartz/quartzKeyboard.h @@ -32,6 +32,8 @@ #include "X11/keysym.h" #include "inputstr.h" +#include <pthread.h> + // Each key can generate 4 glyphs. They are, in order: // unshifted, shifted, modeswitch unshifted, modeswitch shifted #define GLYPHS_PER_KEY 4 @@ -47,10 +49,10 @@ typedef struct darwinKeyboardInfo_struct { /* These functions need to be implemented by Xquartz, XDarwin, etc. */ Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info); -unsigned int QuartzSystemKeymapSeed(void); /* Provided for darwinEvents.c */ extern darwinKeyboardInfo keyInfo; +extern pthread_mutex_t keyInfo_mutex; void DarwinKeyboardReloadHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, int nevents); void DarwinKeyboardInit(DeviceIntPtr pDev); int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide); |