macos: detect keyboard layout change and reload the keymap

This commit is contained in:
Mitchell Hashimoto
2023-08-09 19:42:13 -07:00
parent 3d23f26326
commit 57a527b0c9
3 changed files with 41 additions and 0 deletions

View File

@ -283,6 +283,7 @@ ghostty_app_t ghostty_app_new(const ghostty_runtime_config_s *, ghostty_config_t
void ghostty_app_free(ghostty_app_t);
bool ghostty_app_tick(ghostty_app_t);
void *ghostty_app_userdata(ghostty_app_t);
void ghostty_app_keyboard_changed(ghostty_app_t);
ghostty_surface_t ghostty_surface_new(ghostty_app_t, ghostty_surface_config_s*);
void ghostty_surface_free(ghostty_surface_t);

View File

@ -75,6 +75,13 @@ extension Ghostty {
}
self.app = app
// Subscribe to notifications for keyboard layout change so that we can update Ghostty.
NotificationCenter.default.addObserver(
self,
selector: #selector(self.keyboardSelectionDidChange(notification:)),
name: NSTextInputContext.keyboardSelectionDidChangeNotification,
object: nil)
self.readiness = .ready
}
@ -82,6 +89,12 @@ extension Ghostty {
// This will force the didSet callbacks to run which free.
self.app = nil
self.config = nil
// Remove our observer
NotificationCenter.default.removeObserver(
self,
name: NSTextInputContext.keyboardSelectionDidChangeNotification,
object: nil)
}
/// Initializes a new configuration and loads all the values.
@ -132,6 +145,13 @@ extension Ghostty {
ghostty_surface_split_focus(surface, direction.toNative())
}
// Called when the selected keyboard changes. We have to notify Ghostty so that
// it can reload the keyboard mapping for input.
@objc private func keyboardSelectionDidChange(notification: NSNotification) {
guard let app = self.app else { return }
ghostty_app_keyboard_changed(app)
}
// MARK: Ghostty Callbacks
static func newSplit(_ userdata: UnsafeMutableRawPointer?, direction: ghostty_split_direction_e) {

View File

@ -92,6 +92,17 @@ pub const App = struct {
self.keymap.deinit();
}
/// This should be called whenever the keyboard layout was changed.
pub fn reloadKeymap(self: *App) !void {
// Reload the keymap
try self.keymap.reload();
// Clear the dead key state since we changed the keymap, any
// dead key state is just forgotten. i.e. if you type ' on us-intl
// and then switch to us and type a, you'll get a rather than á.
self.keymap_state = .{};
}
pub fn reloadConfig(self: *App) !?*const Config {
// Reload
if (self.opts.reload_config(self.opts.userdata)) |new| {
@ -475,6 +486,15 @@ pub const CAPI = struct {
core_app.destroy();
}
/// Notify the app that the keyboard was changed. This causes the
/// keyboard layout to be reloaded from the OS.
export fn ghostty_app_keyboard_changed(v: *App) void {
v.reloadKeymap() catch |err| {
log.err("error reloading keyboard map err={}", .{err});
return;
};
}
/// Create a new surface as part of an app.
export fn ghostty_surface_new(
app: *App,