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;
- (OSX_BOOL) x_active;
@end
extern X11Application *X11App;

View File

@ -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:
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);
case NSKeyDown: case NSKeyUp:
/* 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 */
}
}

View File

@ -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]);

View File

@ -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

View File

@ -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);