diff --git a/macos/Sources/AppDelegate.swift b/macos/Sources/AppDelegate.swift index 7a5b41b30..3f81349bc 100644 --- a/macos/Sources/AppDelegate.swift +++ b/macos/Sources/AppDelegate.swift @@ -15,6 +15,7 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp @Published var confirmQuit: Bool = false /// Various menu items so that we can programmatically sync the keyboard shortcut with the Ghostty config. + @IBOutlet private var menuReloadConfig: NSMenuItem? @IBOutlet private var menuQuit: NSMenuItem? @IBOutlet private var menuNewWindow: NSMenuItem? @@ -127,6 +128,7 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp private func syncMenuShortcuts() { guard ghostty.config != nil else { return } + syncMenuShortcut(action: "reload_config", menuItem: self.menuReloadConfig) syncMenuShortcut(action: "quit", menuItem: self.menuQuit) syncMenuShortcut(action: "new_window", menuItem: self.menuNewWindow) @@ -186,6 +188,7 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp // If we have configuration errors, we need to show them. let c = ConfigurationErrorsController.sharedInstance c.model.errors = state.configErrors() + Self.logger.warning("TEST did reload, count=\(c.model.errors.count)") if (c.model.errors.count > 0) { c.showWindow(self) } } @@ -202,6 +205,10 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp //MARK: - IB Actions + @IBAction func reloadConfig(_ sender: Any?) { + ghostty.reloadConfig() + } + @IBAction func newWindow(_ sender: Any?) { windowManager.newWindow() diff --git a/macos/Sources/Ghostty/AppState.swift b/macos/Sources/Ghostty/AppState.swift index 9870fbcd6..20a815ebc 100644 --- a/macos/Sources/Ghostty/AppState.swift +++ b/macos/Sources/Ghostty/AppState.swift @@ -171,6 +171,22 @@ extension Ghostty { NSApplication.shared.terminate(nil) } + func reloadConfig() { + guard let newConfig = Self.reloadConfig() else { + AppDelegate.logger.warning("failed to reload configuration") + return + } + + // Assign the new config. This will automatically free the old config. + // It is safe to free the old config from within this function call. + config = newConfig + + // If we have a delegate, notify. + if let delegate = delegate { + delegate.configDidReload(self) + } + } + /// Request that the given surface is closed. This will trigger the full normal surface close event /// cycle which will call our close surface callback. func requestClose(surface: ghostty_surface_t) { @@ -286,22 +302,9 @@ extension Ghostty { } static func reloadConfig(_ userdata: UnsafeMutableRawPointer?) -> ghostty_config_t? { - guard let newConfig = AppState.reloadConfig() else { - AppDelegate.logger.warning("failed to reload configuration") - return nil - } - - // Assign the new config. This will automatically free the old config. - // It is safe to free the old config from within this function call. let state = Unmanaged.fromOpaque(userdata!).takeUnretainedValue() - state.config = newConfig - - // If we have a delegate, notify. - if let delegate = state.delegate { - delegate.configDidReload(state) - } - - return newConfig + state.reloadConfig() + return state.config } static func wakeup(_ userdata: UnsafeMutableRawPointer?) { diff --git a/macos/Sources/MainMenu.xib b/macos/Sources/MainMenu.xib index a65d314f2..7166541e7 100644 --- a/macos/Sources/MainMenu.xib +++ b/macos/Sources/MainMenu.xib @@ -23,6 +23,7 @@ + @@ -47,6 +48,12 @@ + + + + + + diff --git a/src/config/Config.zig b/src/config/Config.zig index 5ca6b27cd..e5b1dddcf 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -588,6 +588,11 @@ pub fn default(alloc_gpa: Allocator) Allocator.Error!Config { .{ .key = .q, .mods = .{ .super = true } }, .{ .quit = {} }, ); + try result.keybind.set.put( + alloc, + .{ .key = .comma, .mods = .{ .super = true, .shift = true } }, + .{ .reload_config = {} }, + ); try result.keybind.set.put( alloc,