diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index 3f4d34c2325..a6f4f36c89e 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -188,14 +188,6 @@ private: bool drop_events = false; bool in_dispatch_input_event = false; - struct LayoutInfo { - String name; - String code; - }; - mutable Vector kbd_layouts; - mutable int current_layout = 0; - mutable bool keyboard_layout_dirty = true; - WindowID window_mouseover_id = INVALID_WINDOW_ID; WindowID last_focused_window = INVALID_WINDOW_ID; WindowID window_id_counter = MAIN_WINDOW_ID; @@ -242,8 +234,6 @@ private: void _dispatch_input_event(const Ref &p_event); void _push_input(const Ref &p_event); void _process_key_events(); - void _update_keyboard_layouts() const; - static void _keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info); static NSCursor *_cursor_from_selector(SEL p_selector, SEL p_fallback = nil); @@ -454,15 +444,6 @@ public: virtual Error request_close_embedded_process(OS::ProcessID p_pid) override; virtual Error remove_embedded_process(OS::ProcessID p_pid) override; - virtual int keyboard_get_layout_count() const override; - virtual int keyboard_get_current_layout() const override; - virtual void keyboard_set_current_layout(int p_index) override; - virtual String keyboard_get_layout_language(int p_index) const override; - virtual String keyboard_get_layout_name(int p_index) const override; - virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override; - virtual Key keyboard_get_label_from_physical(Key p_keycode) const override; - virtual void show_emoji_and_symbol_picker() const override; - void _process_events(bool p_pump); virtual void process_events() override; virtual void force_process_and_drop_events() override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index cf526209697..966bc0d396a 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -543,58 +543,6 @@ void DisplayServerMacOS::_process_key_events() { key_event_pos = 0; } -void DisplayServerMacOS::_update_keyboard_layouts() const { - kbd_layouts.clear(); - current_layout = 0; - - TISInputSourceRef cur_source = TISCopyCurrentKeyboardInputSource(); - NSString *cur_name = (__bridge NSString *)TISGetInputSourceProperty(cur_source, kTISPropertyLocalizedName); - CFRelease(cur_source); - - // Enum IME layouts. - NSDictionary *filter_ime = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardInputMode }; - NSArray *list_ime = (__bridge NSArray *)TISCreateInputSourceList((__bridge CFDictionaryRef)filter_ime, false); - for (NSUInteger i = 0; i < [list_ime count]; i++) { - LayoutInfo ly; - NSString *name = (__bridge NSString *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyLocalizedName); - ly.name.append_utf8([name UTF8String]); - - NSArray *langs = (__bridge NSArray *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyInputSourceLanguages); - ly.code.append_utf8([(NSString *)[langs objectAtIndex:0] UTF8String]); - kbd_layouts.push_back(ly); - - if ([name isEqualToString:cur_name]) { - current_layout = kbd_layouts.size() - 1; - } - } - - // Enum plain keyboard layouts. - NSDictionary *filter_kbd = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardLayout }; - NSArray *list_kbd = (__bridge NSArray *)TISCreateInputSourceList((__bridge CFDictionaryRef)filter_kbd, false); - for (NSUInteger i = 0; i < [list_kbd count]; i++) { - LayoutInfo ly; - NSString *name = (__bridge NSString *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyLocalizedName); - ly.name.append_utf8([name UTF8String]); - - NSArray *langs = (__bridge NSArray *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyInputSourceLanguages); - ly.code.append_utf8([(NSString *)[langs objectAtIndex:0] UTF8String]); - kbd_layouts.push_back(ly); - - if ([name isEqualToString:cur_name]) { - current_layout = kbd_layouts.size() - 1; - } - } - - keyboard_layout_dirty = false; -} - -void DisplayServerMacOS::_keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) { - DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); - if (ds) { - ds->keyboard_layout_dirty = true; - } -} - NSImage *DisplayServerMacOS::_convert_to_nsimg(Ref &p_image) const { p_image->convert(Image::FORMAT_RGBA8); NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc] @@ -3289,95 +3237,6 @@ Error DisplayServerMacOS::remove_embedded_process(OS::ProcessID p_pid) { return OK; } -int DisplayServerMacOS::keyboard_get_layout_count() const { - if (keyboard_layout_dirty) { - _update_keyboard_layouts(); - } - return kbd_layouts.size(); -} - -void DisplayServerMacOS::keyboard_set_current_layout(int p_index) { - if (keyboard_layout_dirty) { - _update_keyboard_layouts(); - } - - ERR_FAIL_INDEX(p_index, kbd_layouts.size()); - - NSString *cur_name = [NSString stringWithUTF8String:kbd_layouts[p_index].name.utf8().get_data()]; - - NSDictionary *filter_kbd = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardLayout }; - NSArray *list_kbd = (__bridge NSArray *)TISCreateInputSourceList((__bridge CFDictionaryRef)filter_kbd, false); - for (NSUInteger i = 0; i < [list_kbd count]; i++) { - NSString *name = (__bridge NSString *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyLocalizedName); - if ([name isEqualToString:cur_name]) { - TISSelectInputSource((__bridge TISInputSourceRef)[list_kbd objectAtIndex:i]); - break; - } - } - - NSDictionary *filter_ime = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardInputMode }; - NSArray *list_ime = (__bridge NSArray *)TISCreateInputSourceList((__bridge CFDictionaryRef)filter_ime, false); - for (NSUInteger i = 0; i < [list_ime count]; i++) { - NSString *name = (__bridge NSString *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyLocalizedName); - if ([name isEqualToString:cur_name]) { - TISSelectInputSource((__bridge TISInputSourceRef)[list_ime objectAtIndex:i]); - break; - } - } -} - -int DisplayServerMacOS::keyboard_get_current_layout() const { - if (keyboard_layout_dirty) { - _update_keyboard_layouts(); - } - - return current_layout; -} - -String DisplayServerMacOS::keyboard_get_layout_language(int p_index) const { - if (keyboard_layout_dirty) { - _update_keyboard_layouts(); - } - - ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), ""); - return kbd_layouts[p_index].code; -} - -String DisplayServerMacOS::keyboard_get_layout_name(int p_index) const { - if (keyboard_layout_dirty) { - _update_keyboard_layouts(); - } - - ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), ""); - return kbd_layouts[p_index].name; -} - -Key DisplayServerMacOS::keyboard_get_keycode_from_physical(Key p_keycode) const { - if (p_keycode == Key::PAUSE || p_keycode == Key::NONE) { - return p_keycode; - } - - Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK; - Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK; - unsigned int macos_keycode = KeyMappingMacOS::unmap_key(keycode_no_mod); - return (Key)(KeyMappingMacOS::remap_key(macos_keycode, 0, false) | modifiers); -} - -Key DisplayServerMacOS::keyboard_get_label_from_physical(Key p_keycode) const { - if (p_keycode == Key::PAUSE || p_keycode == Key::NONE) { - return p_keycode; - } - - Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK; - Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK; - unsigned int macos_keycode = KeyMappingMacOS::unmap_key(keycode_no_mod); - return (Key)(KeyMappingMacOS::remap_key(macos_keycode, 0, true) | modifiers); -} - -void DisplayServerMacOS::show_emoji_and_symbol_picker() const { - [[NSApplication sharedApplication] orderFrontCharacterPalette:nil]; -} - void DisplayServerMacOS::process_events() { _process_events(true); } @@ -3880,12 +3739,6 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM display_max_scale = std::fmax(display_max_scale, screen_get_scale(i)); } - // Register to be notified on keyboard layout changes. - CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), - nullptr, _keyboard_layout_changed, - kTISNotifySelectedKeyboardInputSourceChanged, nullptr, - CFNotificationSuspensionBehaviorDeliverImmediately); - // Register to be notified on displays arrangement changes. CGDisplayRegisterReconfigurationCallback(_displays_arrangement_changed, nullptr); @@ -4169,7 +4022,6 @@ DisplayServerMacOS::~DisplayServerMacOS() { memdelete(accessibility_driver); } #endif - CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), nullptr, kTISNotifySelectedKeyboardInputSourceChanged, nullptr); CGDisplayRemoveReconfigurationCallback(_displays_arrangement_changed, nullptr); cursors_cache.clear(); diff --git a/platform/macos/display_server_macos_base.h b/platform/macos/display_server_macos_base.h index d66e341d620..4a532e9647f 100644 --- a/platform/macos/display_server_macos_base.h +++ b/platform/macos/display_server_macos_base.h @@ -44,11 +44,22 @@ class DisplayServerMacOSBase : public DisplayServer { id tts = nullptr; + struct LayoutInfo { + String name; + String code; + }; + mutable Vector kbd_layouts; + mutable int current_layout = 0; + mutable bool keyboard_layout_dirty = true; + protected: _THREAD_SAFE_CLASS_ void initialize_tts() const; + void _update_keyboard_layouts() const; + static void _keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info); + public: virtual void clipboard_set(const String &p_text) override; virtual String clipboard_get() const override; @@ -56,6 +67,15 @@ public: virtual bool clipboard_has() const override; virtual bool clipboard_has_image() const override; + virtual int keyboard_get_layout_count() const override; + virtual int keyboard_get_current_layout() const override; + virtual void keyboard_set_current_layout(int p_index) override; + virtual String keyboard_get_layout_language(int p_index) const override; + virtual String keyboard_get_layout_name(int p_index) const override; + virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override; + virtual Key keyboard_get_label_from_physical(Key p_keycode) const override; + virtual void show_emoji_and_symbol_picker() const override; + virtual bool tts_is_speaking() const override; virtual bool tts_is_paused() const override; virtual TypedArray tts_get_voices() const override; @@ -66,4 +86,5 @@ public: virtual void tts_stop() override; DisplayServerMacOSBase(); + ~DisplayServerMacOSBase(); }; diff --git a/platform/macos/display_server_macos_base.mm b/platform/macos/display_server_macos_base.mm index 64c4d976d65..ba15250beee 100644 --- a/platform/macos/display_server_macos_base.mm +++ b/platform/macos/display_server_macos_base.mm @@ -29,11 +29,14 @@ /**************************************************************************/ #import "display_server_macos_base.h" +#import "key_mapping_macos.h" #import "tts_macos.h" #include "core/config/project_settings.h" #include "drivers/png/png_driver_common.h" +#import + void DisplayServerMacOSBase::clipboard_set(const String &p_text) { _THREAD_SAFE_METHOD_ @@ -157,10 +160,161 @@ void DisplayServerMacOSBase::tts_stop() { [tts stopSpeaking]; } +void DisplayServerMacOSBase::_update_keyboard_layouts() const { + kbd_layouts.clear(); + current_layout = 0; + + TISInputSourceRef cur_source = TISCopyCurrentKeyboardInputSource(); + NSString *cur_name = (__bridge NSString *)TISGetInputSourceProperty(cur_source, kTISPropertyLocalizedName); + CFRelease(cur_source); + + // Enum IME layouts. + NSDictionary *filter_ime = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardInputMode }; + NSArray *list_ime = (__bridge NSArray *)TISCreateInputSourceList((__bridge CFDictionaryRef)filter_ime, false); + for (NSUInteger i = 0; i < [list_ime count]; i++) { + LayoutInfo ly; + NSString *name = (__bridge NSString *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyLocalizedName); + ly.name.append_utf8([name UTF8String]); + + NSArray *langs = (__bridge NSArray *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyInputSourceLanguages); + ly.code.append_utf8([(NSString *)[langs objectAtIndex:0] UTF8String]); + kbd_layouts.push_back(ly); + + if ([name isEqualToString:cur_name]) { + current_layout = kbd_layouts.size() - 1; + } + } + + // Enum plain keyboard layouts. + NSDictionary *filter_kbd = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardLayout }; + NSArray *list_kbd = (__bridge NSArray *)TISCreateInputSourceList((__bridge CFDictionaryRef)filter_kbd, false); + for (NSUInteger i = 0; i < [list_kbd count]; i++) { + LayoutInfo ly; + NSString *name = (__bridge NSString *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyLocalizedName); + ly.name.append_utf8([name UTF8String]); + + NSArray *langs = (__bridge NSArray *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyInputSourceLanguages); + ly.code.append_utf8([(NSString *)[langs objectAtIndex:0] UTF8String]); + kbd_layouts.push_back(ly); + + if ([name isEqualToString:cur_name]) { + current_layout = kbd_layouts.size() - 1; + } + } + + keyboard_layout_dirty = false; +} + +void DisplayServerMacOSBase::_keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) { + DisplayServerMacOSBase *ds = (DisplayServerMacOSBase *)DisplayServer::get_singleton(); + if (ds) { + ds->keyboard_layout_dirty = true; + } +} + +int DisplayServerMacOSBase::keyboard_get_layout_count() const { + if (keyboard_layout_dirty) { + _update_keyboard_layouts(); + } + return kbd_layouts.size(); +} + +void DisplayServerMacOSBase::keyboard_set_current_layout(int p_index) { + if (keyboard_layout_dirty) { + _update_keyboard_layouts(); + } + + ERR_FAIL_INDEX(p_index, kbd_layouts.size()); + + NSString *cur_name = [NSString stringWithUTF8String:kbd_layouts[p_index].name.utf8().get_data()]; + + NSDictionary *filter_kbd = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardLayout }; + NSArray *list_kbd = (__bridge NSArray *)TISCreateInputSourceList((__bridge CFDictionaryRef)filter_kbd, false); + for (NSUInteger i = 0; i < [list_kbd count]; i++) { + NSString *name = (__bridge NSString *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyLocalizedName); + if ([name isEqualToString:cur_name]) { + TISSelectInputSource((__bridge TISInputSourceRef)[list_kbd objectAtIndex:i]); + break; + } + } + + NSDictionary *filter_ime = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardInputMode }; + NSArray *list_ime = (__bridge NSArray *)TISCreateInputSourceList((__bridge CFDictionaryRef)filter_ime, false); + for (NSUInteger i = 0; i < [list_ime count]; i++) { + NSString *name = (__bridge NSString *)TISGetInputSourceProperty((__bridge TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyLocalizedName); + if ([name isEqualToString:cur_name]) { + TISSelectInputSource((__bridge TISInputSourceRef)[list_ime objectAtIndex:i]); + break; + } + } +} + +int DisplayServerMacOSBase::keyboard_get_current_layout() const { + if (keyboard_layout_dirty) { + _update_keyboard_layouts(); + } + + return current_layout; +} + +String DisplayServerMacOSBase::keyboard_get_layout_language(int p_index) const { + if (keyboard_layout_dirty) { + _update_keyboard_layouts(); + } + + ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), ""); + return kbd_layouts[p_index].code; +} + +String DisplayServerMacOSBase::keyboard_get_layout_name(int p_index) const { + if (keyboard_layout_dirty) { + _update_keyboard_layouts(); + } + + ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), ""); + return kbd_layouts[p_index].name; +} + +Key DisplayServerMacOSBase::keyboard_get_keycode_from_physical(Key p_keycode) const { + if (p_keycode == Key::PAUSE || p_keycode == Key::NONE) { + return p_keycode; + } + + Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK; + Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK; + unsigned int macos_keycode = KeyMappingMacOS::unmap_key(keycode_no_mod); + return (Key)(KeyMappingMacOS::remap_key(macos_keycode, 0, false) | modifiers); +} + +Key DisplayServerMacOSBase::keyboard_get_label_from_physical(Key p_keycode) const { + if (p_keycode == Key::PAUSE || p_keycode == Key::NONE) { + return p_keycode; + } + + Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK; + Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK; + unsigned int macos_keycode = KeyMappingMacOS::unmap_key(keycode_no_mod); + return (Key)(KeyMappingMacOS::remap_key(macos_keycode, 0, true) | modifiers); +} + +void DisplayServerMacOSBase::show_emoji_and_symbol_picker() const { + [[NSApplication sharedApplication] orderFrontCharacterPalette:nil]; +} + DisplayServerMacOSBase::DisplayServerMacOSBase() { // Init TTS bool tts_enabled = GLOBAL_GET("audio/general/text_to_speech"); if (tts_enabled) { initialize_tts(); } + + // Register to be notified on keyboard layout changes. + CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), + nullptr, _keyboard_layout_changed, + kTISNotifySelectedKeyboardInputSourceChanged, nullptr, + CFNotificationSuspensionBehaviorDeliverImmediately); +} + +DisplayServerMacOSBase::~DisplayServerMacOSBase() { + CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), nullptr, kTISNotifySelectedKeyboardInputSourceChanged, nullptr); }