XQuartz: Fixed threading issue with TSM.

(cherry picked from commit 93ab4e0071670bb80bfa1170dd97ed9d6d51c67a)
This commit is contained in:
Jeremy Huddleston 2008-09-24 22:51:03 -07:00
parent ee87c9b024
commit 12a59c44cb
5 changed files with 89 additions and 80 deletions

View File

@ -56,7 +56,6 @@
- (void) prefs_synchronize; - (void) prefs_synchronize;
- (OSX_BOOL) x_active; - (OSX_BOOL) x_active;
@end @end
extern X11Application *X11App; extern X11Application *X11App;

View File

@ -39,6 +39,7 @@
#include "darwin.h" #include "darwin.h"
#include "darwinEvents.h" #include "darwinEvents.h"
#include "quartzKeyboard.h"
#include "quartz.h" #include "quartz.h"
#define _APPLEWM_SERVER_ #define _APPLEWM_SERVER_
#include "X11/extensions/applewm.h" #include "X11/extensions/applewm.h"
@ -61,6 +62,8 @@
int X11EnableKeyEquivalents = TRUE; int X11EnableKeyEquivalents = TRUE;
int quartzHasRoot = FALSE, quartzEnableRootless = TRUE; int quartzHasRoot = FALSE, quartzEnableRootless = TRUE;
static TISInputSourceRef last_key_layout;
extern int darwinFakeButtons; extern int darwinFakeButtons;
extern Bool enable_stereo; extern Bool enable_stereo;
@ -163,8 +166,7 @@ static void message_kit_thread (SEL selector, NSObject *arg) {
- (void) activateX:(OSX_BOOL)state { - (void) activateX:(OSX_BOOL)state {
/* Create a TSM document that supports full Unicode input, and /* Create a TSM document that supports full Unicode input, and
have it activated while X is active (unless using the old have it activated while X is active */
keymapping files) */
static TSMDocumentID x11_document; static TSMDocumentID x11_document;
DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active) DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active)
if (state) { if (state) {
@ -589,8 +591,8 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) {
- (void) prefs_set_boolean:(NSString *)key value:(int)value { - (void) prefs_set_boolean:(NSString *)key value:(int)value {
CFPreferencesSetValue ((CFStringRef) key, CFPreferencesSetValue ((CFStringRef) key,
(CFTypeRef) value ? kCFBooleanTrue (CFTypeRef) (value ? kCFBooleanTrue
: kCFBooleanFalse, CFSTR (APP_PREFS), : kCFBooleanFalse), CFSTR (APP_PREFS),
kCFPreferencesCurrentUser, kCFPreferencesAnyHost); kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
} }
@ -847,6 +849,18 @@ void X11ApplicationMain (int argc, char **argv, char **envp) {
aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) - aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) -
NSMaxY([[NSScreen mainScreen] visibleFrame]); 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 */ /* Tell the server thread that it can proceed */
QuartzInitServer(argc, argv, envp); QuartzInitServer(argc, argv, envp);
@ -976,6 +990,30 @@ static void send_nsevent(NSEvent *e) {
break; 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]); DarwinSendKeyboardEvents(([e type] == NSKeyDown) ? KeyPress : KeyRelease, [e keyCode]);
break; break;

View File

@ -473,19 +473,6 @@ void DarwinSendKeyboardEvents(int ev_type, int keycode) {
return; 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(); { darwinEvents_lock(); {
num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE); num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE);
for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard,&darwinEvents[i]); for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard,&darwinEvents[i]);

View File

@ -52,6 +52,8 @@
#include "quartzKeyboard.h" #include "quartzKeyboard.h"
#include "quartzAudio.h" #include "quartzAudio.h"
#include "threadSafety.h"
#ifdef NDEBUG #ifdef NDEBUG
#undef NDEBUG #undef NDEBUG
#include <assert.h> #include <assert.h>
@ -59,6 +61,7 @@
#else #else
#include <assert.h> #include <assert.h>
#endif #endif
#include <pthread.h>
#include "xkbsrv.h" #include "xkbsrv.h"
#include "exevents.h" #include "exevents.h"
@ -304,6 +307,7 @@ const static struct {
}; };
darwinKeyboardInfo keyInfo; darwinKeyboardInfo keyInfo;
pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER;
static void DarwinChangeKeyboardControl( DeviceIntPtr device, KeybdCtrl *ctrl ) static void DarwinChangeKeyboardControl( DeviceIntPtr device, KeybdCtrl *ctrl )
{ {
@ -411,11 +415,7 @@ static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) {
* it to an equivalent X keyboard map and modifier map. * it to an equivalent X keyboard map and modifier map.
*/ */
static void DarwinLoadKeyboardMapping(KeySymsRec *keySyms) { static void DarwinLoadKeyboardMapping(KeySymsRec *keySyms) {
memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); pthread_mutex_lock(&keyInfo_mutex);
if (!QuartzReadSystemKeymap(&keyInfo)) {
FatalError("Could not build a valid keymap.");
}
DarwinBuildModifierMaps(&keyInfo); DarwinBuildModifierMaps(&keyInfo);
@ -423,6 +423,8 @@ static void DarwinLoadKeyboardMapping(KeySymsRec *keySyms) {
keySyms->mapWidth = GLYPHS_PER_KEY; keySyms->mapWidth = GLYPHS_PER_KEY;
keySyms->minKeyCode = MIN_KEYCODE; keySyms->minKeyCode = MIN_KEYCODE;
keySyms->maxKeyCode = MAX_KEYCODE; keySyms->maxKeyCode = MAX_KEYCODE;
pthread_mutex_unlock(&keyInfo_mutex);
} }
void QuartzXkbUpdate(DeviceIntPtr pDev) { void QuartzXkbUpdate(DeviceIntPtr pDev) {
@ -450,27 +452,27 @@ void DarwinKeyboardInit(DeviceIntPtr pDev) {
assert( darwinParamConnect = NXOpenEventStatus() ); assert( darwinParamConnect = NXOpenEventStatus() );
DarwinLoadKeyboardMapping(&keySyms); DarwinLoadKeyboardMapping(&keySyms);
/* Initialize the seed, so we don't reload the keymap unnecessarily
(and possibly overwrite xinitrc changes) */
QuartzSystemKeymapSeed();
#ifdef XQUARTZ_USE_XKB #ifdef XQUARTZ_USE_XKB
XkbComponentNamesRec names; XkbComponentNamesRec names;
bzero(&names, sizeof(names)); bzero(&names, sizeof(names));
/* We need to really have rules... or something... */ /* We need to really have rules... or something... */
XkbSetRulesDflts("base", "pc105", "us", NULL, NULL); XkbSetRulesDflts("base", "pc105", "us", NULL, NULL);
pthread_mutex_lock(&keyInfo_mutex);
assert(XkbInitKeyboardDeviceStruct(pDev, &names, &keySyms, keyInfo.modMap, assert(XkbInitKeyboardDeviceStruct(pDev, &names, &keySyms, keyInfo.modMap,
QuartzBell, DarwinChangeKeyboardControl)); QuartzBell, DarwinChangeKeyboardControl));
assert(SetKeySymsMap(&pDev->key->curKeySyms, &keySyms)); assert(SetKeySymsMap(&pDev->key->curKeySyms, &keySyms));
assert(keyInfo.modMap!=NULL); assert(keyInfo.modMap!=NULL);
assert(pDev->key->modifierMap!=NULL); assert(pDev->key->modifierMap!=NULL);
memcpy(pDev->key->modifierMap, keyInfo.modMap, sizeof(keyInfo.modMap)); memcpy(pDev->key->modifierMap, keyInfo.modMap, sizeof(keyInfo.modMap));
pthread_mutex_unlock(&keyInfo_mutex);
QuartzXkbUpdate(pDev); QuartzXkbUpdate(pDev);
#else #else
pthread_mutex_lock(&keyInfo_mutex);
assert( InitKeyboardDeviceStruct( (DevicePtr)pDev, &keySyms, assert( InitKeyboardDeviceStruct( (DevicePtr)pDev, &keySyms,
keyInfo.modMap, QuartzBell, keyInfo.modMap, QuartzBell,
DarwinChangeKeyboardControl )); DarwinChangeKeyboardControl ));
pthread_mutex_unlock(&keyInfo_mutex);
SwitchCoreKeyboard(pDev); SwitchCoreKeyboard(pDev);
#endif #endif
} }
@ -493,10 +495,13 @@ void DarwinKeyboardReloadHandler(int screenNum, xEventPtr xe, DeviceIntPtr pDev,
xfree(pDev->key); xfree(pDev->key);
} }
pthread_mutex_lock(&keyInfo_mutex);
if (!InitKeyClassDeviceStruct(pDev, &keySyms, keyInfo.modMap)) { if (!InitKeyClassDeviceStruct(pDev, &keySyms, keyInfo.modMap)) {
DEBUG_LOG("InitKeyClassDeviceStruct failed\n"); DEBUG_LOG("InitKeyClassDeviceStruct failed\n");
pthread_mutex_unlock(&keyInfo_mutex);
return; return;
} }
pthread_mutex_unlock(&keyInfo_mutex);
SendMappingNotify(MappingKeyboard, MIN_KEYCODE, NUM_KEYCODES, 0); SendMappingNotify(MappingKeyboard, MIN_KEYCODE, NUM_KEYCODES, 0);
SendMappingNotify(MappingModifier, 0, 0, 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. * Returns 0 if key+side is not a known modifier.
*/ */
int DarwinModifierNXKeyToNXKeycode(int key, int side) { 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 DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) {
int key, side; int key, side;
pthread_mutex_lock(&keyInfo_mutex);
keycode += MIN_KEYCODE; keycode += MIN_KEYCODE;
// search modifierKeycodes for this keycode+side // search modifierKeycodes for this keycode+side
for (key = 0; key < NX_NUMMODIFIERS; key++) { 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 (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; if (outSide) *outSide = side;
pthread_mutex_unlock(&keyInfo_mutex);
return key; return key;
} }
@ -666,39 +682,6 @@ Bool LegalModifier(unsigned int key, DeviceIntPtr pDev)
return 1; 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) { static inline UniChar macroman2ucs(unsigned char c) {
/* Precalculated table mapping MacRoman-128 to Unicode. Generated /* Precalculated table mapping MacRoman-128 to Unicode. Generated
by creating single element CFStringRefs then extracting the by creating single element CFStringRefs then extracting the

View File

@ -32,6 +32,8 @@
#include "X11/keysym.h" #include "X11/keysym.h"
#include "inputstr.h" #include "inputstr.h"
#include <pthread.h>
// Each key can generate 4 glyphs. They are, in order: // Each key can generate 4 glyphs. They are, in order:
// unshifted, shifted, modeswitch unshifted, modeswitch shifted // unshifted, shifted, modeswitch unshifted, modeswitch shifted
#define GLYPHS_PER_KEY 4 #define GLYPHS_PER_KEY 4
@ -47,10 +49,10 @@ typedef struct darwinKeyboardInfo_struct {
/* These functions need to be implemented by Xquartz, XDarwin, etc. */ /* These functions need to be implemented by Xquartz, XDarwin, etc. */
Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info); Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info);
unsigned int QuartzSystemKeymapSeed(void);
/* Provided for darwinEvents.c */ /* Provided for darwinEvents.c */
extern darwinKeyboardInfo keyInfo; extern darwinKeyboardInfo keyInfo;
extern pthread_mutex_t keyInfo_mutex;
void DarwinKeyboardReloadHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, int nevents); void DarwinKeyboardReloadHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, int nevents);
void DarwinKeyboardInit(DeviceIntPtr pDev); void DarwinKeyboardInit(DeviceIntPtr pDev);
int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide); int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide);