1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

[macOS] Move keyboard layout related code to base display server.

This commit is contained in:
Pāvels Nadtočajevs
2025-06-24 10:45:19 +03:00
parent 88b9932ce1
commit 350b1936ee
4 changed files with 175 additions and 167 deletions

View File

@@ -188,14 +188,6 @@ private:
bool drop_events = false;
bool in_dispatch_input_event = false;
struct LayoutInfo {
String name;
String code;
};
mutable Vector<LayoutInfo> 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<InputEvent> &p_event);
void _push_input(const Ref<InputEvent> &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;

View File

@@ -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<Image> &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();

View File

@@ -44,11 +44,22 @@ class DisplayServerMacOSBase : public DisplayServer {
id tts = nullptr;
struct LayoutInfo {
String name;
String code;
};
mutable Vector<LayoutInfo> 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<Dictionary> tts_get_voices() const override;
@@ -66,4 +86,5 @@ public:
virtual void tts_stop() override;
DisplayServerMacOSBase();
~DisplayServerMacOSBase();
};

View File

@@ -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 <Carbon/Carbon.h>
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);
}