From 9c1ee09e483c632e04611f3c7c779ee906069341 Mon Sep 17 00:00:00 2001 From: Bryan Lee <38807139+liby@users.noreply.github.com> Date: Fri, 17 Jan 2025 10:58:51 +0800 Subject: [PATCH] Add `toggle_background_opacity` action for macOS --- include/ghostty.h | 1 + macos/Sources/Ghostty/Ghostty.App.swift | 23 ++++++++++++++- macos/Sources/Ghostty/Package.swift | 3 ++ .../Sources/Ghostty/SurfaceView_AppKit.swift | 29 +++++++++++++++++++ src/Surface.zig | 6 ++++ src/apprt/action.zig | 4 +++ src/apprt/glfw.zig | 1 + src/input/Binding.zig | 4 +++ 8 files changed, 70 insertions(+), 1 deletion(-) diff --git a/include/ghostty.h b/include/ghostty.h index 18c547910..2519f41bd 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -591,6 +591,7 @@ typedef enum { GHOSTTY_ACTION_TOGGLE_FULLSCREEN, GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW, GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS, + GHOSTTY_ACTION_TOGGLE_BACKGROUND_OPACITY, GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL, GHOSTTY_ACTION_TOGGLE_COMMAND_PALETTE, GHOSTTY_ACTION_TOGGLE_VISIBILITY, diff --git a/macos/Sources/Ghostty/Ghostty.App.swift b/macos/Sources/Ghostty/Ghostty.App.swift index 65e91ce83..fb26e487b 100644 --- a/macos/Sources/Ghostty/Ghostty.App.swift +++ b/macos/Sources/Ghostty/Ghostty.App.swift @@ -550,6 +550,9 @@ extension Ghostty { case GHOSTTY_ACTION_RING_BELL: ringBell(app, target: target) + case GHOSTTY_ACTION_TOGGLE_BACKGROUND_OPACITY: + toggleBackgroundOpacity(app, target: target) + case GHOSTTY_ACTION_CLOSE_ALL_WINDOWS: fallthrough case GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW: @@ -1071,7 +1074,7 @@ extension Ghostty { guard let surface = target.target.surface else { return } guard let surfaceView = self.surfaceView(from: surface) else { return } guard let window = surfaceView.window as? TerminalWindow else { return } - + switch (mode) { case .on: window.level = .floating @@ -1509,6 +1512,24 @@ extension Ghostty { } } + private static func toggleBackgroundOpacity(_ app: ghostty_app_t, target: ghostty_target_s) { + switch (target.tag) { + case GHOSTTY_TARGET_APP: + Ghostty.logger.warning("toggle_background_opacity does nothing with an app target") + return + + case GHOSTTY_TARGET_SURFACE: + guard let surface = target.target.surface, + let surfaceView = self.surfaceView(from: surface) else { return } + NotificationCenter.default.post( + name: .ghosttyBackgroundOpacityDidToggle, + object: surfaceView + ) + + default: + assertionFailure() + } + } // MARK: User Notifications diff --git a/macos/Sources/Ghostty/Package.swift b/macos/Sources/Ghostty/Package.swift index 30d5573df..14e4e26ae 100644 --- a/macos/Sources/Ghostty/Package.swift +++ b/macos/Sources/Ghostty/Package.swift @@ -263,6 +263,9 @@ extension Notification.Name { static let ghosttyColorDidChange = Notification.Name("com.mitchellh.ghostty.ghosttyColorDidChange") static let GhosttyColorChangeKey = ghosttyColorDidChange.rawValue + /// Background opacity toggle event + static let ghosttyBackgroundOpacityDidToggle = Notification.Name("com.mitchellh.ghostty.backgroundOpacityDidToggle") + /// Goto tab. Has tab index in the userinfo. static let ghosttyMoveTab = Notification.Name("com.mitchellh.ghostty.moveTab") static let GhosttyMoveTabKey = ghosttyMoveTab.rawValue diff --git a/macos/Sources/Ghostty/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/SurfaceView_AppKit.swift index 921c32c8b..6beeb624f 100644 --- a/macos/Sources/Ghostty/SurfaceView_AppKit.swift +++ b/macos/Sources/Ghostty/SurfaceView_AppKit.swift @@ -203,6 +203,11 @@ extension Ghostty { selector: #selector(windowDidChangeScreen), name: NSWindow.didChangeScreenNotification, object: nil) + center.addObserver( + self, + selector: #selector(ghosttyBackgroundOpacityDidToggle), + name: .ghosttyBackgroundOpacityDidToggle, + object: self) // Listen for local events that we need to know of outside of // single surface handlers. @@ -591,6 +596,30 @@ extension Ghostty { } } + @objc private func ghosttyBackgroundOpacityDidToggle() { + guard self.derivedConfig.backgroundOpacity < 1 else { return } + + // Toggle the window's background opacity + if let window = self.window as? TerminalWindow { + let newOpaque = !window.isOpaque + window.isOpaque = newOpaque + + // Update the window background color based on opacity state + if newOpaque { + window.backgroundColor = NSColor(self.derivedConfig.backgroundColor) + } else { + // Use a very small alpha component to match Terminal.app's look + window.backgroundColor = .white.withAlphaComponent(0.001) + // Apply background blur + if let app = (NSApplication.shared.delegate as? AppDelegate)?.ghostty.app { + ghostty_set_window_background_blur(app, Unmanaged.passUnretained(window).toOpaque()) + } + } + } else { + Ghostty.logger.warning("toggle background opacity: no terminal window found") + } + } + // MARK: - NSView override func becomeFirstResponder() -> Bool { diff --git a/src/Surface.zig b/src/Surface.zig index 0d4c9d984..2e1285472 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -4291,6 +4291,12 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool {}, ), + .toggle_background_opacity => return try self.rt_app.performAction( + .{ .surface = self }, + .toggle_background_opacity, + {}, + ), + .toggle_tab_overview => return try self.rt_app.performAction( .{ .surface = self }, .toggle_tab_overview, diff --git a/src/apprt/action.zig b/src/apprt/action.zig index 4be296f09..40e68ca8f 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -104,6 +104,9 @@ pub const Action = union(Key) { /// Toggle whether window directions are shown. toggle_window_decorations, + /// Toggle the background opacity of the target terminal. + toggle_background_opacity, + /// Toggle the quick terminal in or out. toggle_quick_terminal, @@ -267,6 +270,7 @@ pub const Action = union(Key) { toggle_fullscreen, toggle_tab_overview, toggle_window_decorations, + toggle_background_opacity, toggle_quick_terminal, toggle_command_palette, toggle_visibility, diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index 9d1c8a6b5..95c06546a 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -227,6 +227,7 @@ pub const App = struct { .close_tab, .toggle_tab_overview, .toggle_window_decorations, + .toggle_background_opacity, .toggle_quick_terminal, .toggle_command_palette, .toggle_visibility, diff --git a/src/input/Binding.zig b/src/input/Binding.zig index 6583e1462..550341c2e 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -439,6 +439,9 @@ pub const Action = union(enum) { /// This only works on macOS. toggle_window_float_on_top, + /// Toggle background opacity of window. + toggle_background_opacity: void, + /// Toggle secure input mode on or off. This is used to prevent apps /// that monitor input from seeing what you type. This is useful for /// entering passwords or other sensitive information. @@ -830,6 +833,7 @@ pub const Action = union(enum) { .toggle_fullscreen, .toggle_window_decorations, .toggle_window_float_on_top, + .toggle_background_opacity, .toggle_secure_input, .toggle_command_palette, .reset_window_size,