XQuartz: Fixed threading issue with TSM.
(cherry picked from commit 93ab4e0071670bb80bfa1170dd97ed9d6d51c67a)
This commit is contained in:
parent
ee87c9b024
commit
12a59c44cb
|
@ -56,7 +56,6 @@
|
|||
- (void) prefs_synchronize;
|
||||
|
||||
- (OSX_BOOL) x_active;
|
||||
|
||||
@end
|
||||
|
||||
extern X11Application *X11App;
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue