From 32f38b97d544eb2fd9a568e94e37830106417b51 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Tue, 24 May 2016 21:33:15 +0200 Subject: [PATCH] Fix OS X key names not following layout --- src/cocoa_init.m | 83 +++++++++++++++++++++++++++++++++++++------- src/cocoa_platform.h | 3 ++ 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/src/cocoa_init.m b/src/cocoa_init.m index a2337414..1ee60fd1 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -200,6 +200,37 @@ static void createKeyTables(void) } } +// Retrieve Unicode data for the current keyboard layout +// +static GLFWbool updateUnicodeDataNS(void) +{ + if (_glfw.ns.inputSource) + { + CFRelease(_glfw.ns.inputSource); + _glfw.ns.inputSource = NULL; + _glfw.ns.unicodeData = nil; + } + + _glfw.ns.inputSource = TISCopyCurrentKeyboardLayoutInputSource(); + if (!_glfw.ns.inputSource) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: Failed to retrieve keyboard layout input source"); + return GLFW_FALSE; + } + + _glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource, + kTISPropertyUnicodeKeyLayoutData); + if (!_glfw.ns.unicodeData) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: Failed to retrieve keyboard layout Unicode data"); + return GLFW_FALSE; + } + + return GLFW_TRUE; +} + // Load HIToolbox.framework and the TIS symbols we need from it // This works only because Cocoa has already loaded it properly // @@ -216,6 +247,9 @@ static GLFWbool initializeTIS(void) CFStringRef* kPropertyUnicodeKeyLayoutData = CFBundleGetDataPointerForName(_glfw.ns.tis.bundle, CFSTR("kTISPropertyUnicodeKeyLayoutData")); + CFStringRef* kNotifySelectedKeyboardInputSourceChanged = + CFBundleGetDataPointerForName(_glfw.ns.tis.bundle, + CFSTR("kTISNotifySelectedKeyboardInputSourceChanged")); _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource = CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle, CFSTR("TISCopyCurrentKeyboardLayoutInputSource")); @@ -227,6 +261,7 @@ static GLFWbool initializeTIS(void) CFSTR("LMGetKbdType")); if (!kPropertyUnicodeKeyLayoutData || + !kNotifySelectedKeyboardInputSourceChanged || !TISCopyCurrentKeyboardLayoutInputSource || !TISGetInputSourceProperty || !LMGetKbdType) @@ -236,22 +271,26 @@ static GLFWbool initializeTIS(void) return GLFW_FALSE; } - _glfw.ns.tis.kPropertyUnicodeKeyLayoutData = *kPropertyUnicodeKeyLayoutData; + _glfw.ns.tis.kPropertyUnicodeKeyLayoutData = + *kPropertyUnicodeKeyLayoutData; + _glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged = + *kNotifySelectedKeyboardInputSourceChanged; - // TODO: Catch kTISNotifySelectedKeyboardInputSourceChanged and update - - _glfw.ns.inputSource = TISCopyCurrentKeyboardLayoutInputSource(); - if (!_glfw.ns.inputSource) - return GLFW_FALSE; - - _glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource, - kTISPropertyUnicodeKeyLayoutData); - if (!_glfw.ns.unicodeData) - return GLFW_FALSE; - - return GLFW_TRUE; + return updateUnicodeDataNS(); } +@interface GLFWLayoutListener : NSObject +@end + +@implementation GLFWLayoutListener + +- (void)selectedKeyboardInputSourceChanged:(NSObject* )object +{ + updateUnicodeDataNS(); +} + +@end + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// @@ -261,6 +300,13 @@ int _glfwPlatformInit(void) { _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init]; + _glfw.ns.listener = [[GLFWLayoutListener alloc] init]; + [[NSDistributedNotificationCenter defaultCenter] + addObserver:_glfw.ns.listener + selector:@selector(selectedKeyboardInputSourceChanged:) + name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged + object:nil]; + #if defined(_GLFW_USE_CHDIR) changeToResourcesDirectory(); #endif @@ -294,6 +340,7 @@ void _glfwPlatformTerminate(void) { CFRelease(_glfw.ns.inputSource); _glfw.ns.inputSource = NULL; + _glfw.ns.unicodeData = nil; } if (_glfw.ns.eventSource) @@ -309,6 +356,16 @@ void _glfwPlatformTerminate(void) _glfw.ns.delegate = nil; } + if (_glfw.ns.listener) + { + [[NSDistributedNotificationCenter defaultCenter] + removeObserver:_glfw.ns.listener + name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged + object:nil]; + [_glfw.ns.listener release]; + _glfw.ns.listener = nil; + } + [_glfw.ns.cursor release]; _glfw.ns.cursor = nil; diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 134c423c..780af401 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -58,6 +58,7 @@ typedef void* id; // HIToolbox.framework pointer typedefs #define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData +#define kTISNotifySelectedKeyboardInputSourceChanged _glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void); #define TISCopyCurrentKeyboardLayoutInputSource _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource typedef void* (*PFN_TISGetInputSourceProperty)(TISInputSourceRef,CFStringRef); @@ -92,6 +93,7 @@ typedef struct _GLFWlibraryNS id cursor; TISInputSourceRef inputSource; id unicodeData; + id listener; char keyName[64]; short int publicKeys[256]; @@ -104,6 +106,7 @@ typedef struct _GLFWlibraryNS PFN_TISGetInputSourceProperty GetInputSourceProperty; PFN_LMGetKbdType GetKbdType; CFStringRef kPropertyUnicodeKeyLayoutData; + CFStringRef kNotifySelectedKeyboardInputSourceChanged; } tis; } _GLFWlibraryNS;