Merge pull request #172 from mitchellh/mrn/toggle-fullscreen

Toggle fullscreen on super/ctrl+return, only macOS for now
This commit is contained in:
Mitchell Hashimoto
2023-07-02 12:00:55 -07:00
committed by GitHub
8 changed files with 56 additions and 1 deletions

View File

@ -239,6 +239,7 @@ typedef void (*ghostty_runtime_new_split_cb)(void *, ghostty_split_direction_e);
typedef void (*ghostty_runtime_close_surface_cb)(void *, bool);
typedef void (*ghostty_runtime_focus_split_cb)(void *, ghostty_split_focus_direction_e);
typedef void (*ghostty_runtime_goto_tab_cb)(void *, int32_t);
typedef void (*ghostty_runtime_toggle_fullscreen_cb)(void *);
typedef struct {
void *userdata;
@ -251,6 +252,7 @@ typedef struct {
ghostty_runtime_close_surface_cb close_surface_cb;
ghostty_runtime_focus_split_cb focus_split_cb;
ghostty_runtime_goto_tab_cb goto_tab_cb;
ghostty_runtime_toggle_fullscreen_cb toggle_fullscreen_cb;
} ghostty_runtime_config_s;
//-------------------------------------------------------------------

View File

@ -28,6 +28,7 @@ struct ContentView: View {
case .ready:
let center = NotificationCenter.default
let gotoTab = center.publisher(for: Ghostty.Notification.ghosttyGotoTab)
let toggleFullscreen = center.publisher(for: Ghostty.Notification.ghosttyToggleFullscreen)
let confirmQuitting = Binding<Bool>(get: {
self.appDelegate.confirmQuit && (self.window?.isKeyWindow ?? false)
@ -39,6 +40,7 @@ struct ContentView: View {
.ghosttyApp(ghostty.app!)
.background(WindowAccessor(window: $window))
.onReceive(gotoTab) { onGotoTab(notification: $0) }
.onReceive(toggleFullscreen) { onToggleFullscreen(notification: $0) }
.confirmationDialog(
"Quit Ghostty?",
isPresented: confirmQuitting) {
@ -84,4 +86,14 @@ struct ContentView: View {
let targetWindow = tabbedWindows[adjustedIndex]
targetWindow.makeKeyAndOrderFront(nil)
}
private func onToggleFullscreen(notification: SwiftUI.Notification) {
// Just like in `onGotoTab`, we might receive this multiple times. But
// it's fine, because `toggleFullscreen` should only apply to the
// currently focused window.
guard let window = self.window else { return }
guard window.isKeyWindow else { return }
window.toggleFullScreen(nil)
}
}

View File

@ -62,7 +62,8 @@ extension Ghostty {
new_split_cb: { userdata, direction in AppState.newSplit(userdata, direction: direction) },
close_surface_cb: { userdata, processAlive in AppState.closeSurface(userdata, processAlive: processAlive) },
focus_split_cb: { userdata, direction in AppState.focusSplit(userdata, direction: direction) },
goto_tab_cb: { userdata, n in AppState.gotoTab(userdata, n: n) }
goto_tab_cb: { userdata, n in AppState.gotoTab(userdata, n: n) },
toggle_fullscreen_cb: { userdata in AppState.toggleFullscreen(userdata) }
)
// Create the ghostty app.
@ -218,6 +219,15 @@ extension Ghostty {
}
}
static func toggleFullscreen(_ userdata: UnsafeMutableRawPointer?) {
guard let surface = self.surfaceUserdata(from: userdata) else { return }
NotificationCenter.default.post(
name: Notification.ghosttyToggleFullscreen,
object: surface,
userInfo: [:]
)
}
/// Returns the GhosttyState from the given userdata value.
static private func appState(fromSurface userdata: UnsafeMutableRawPointer?) -> AppState? {
let surfaceView = Unmanaged<SurfaceView>.fromOpaque(userdata!).takeUnretainedValue()

View File

@ -78,6 +78,9 @@ extension Ghostty.Notification {
/// Goto tab. Has tab index in the userinfo.
static let ghosttyGotoTab = Notification.Name("com.mitchellh.ghostty.gotoTab")
static let GotoTabKey = ghosttyGotoTab.rawValue
/// Toggle fullscreen of current window
static let ghosttyToggleFullscreen = Notification.Name("com.mitchellh.ghostty.toggleFullscreen")
}
// Make the input enum hashable.

View File

@ -1135,6 +1135,12 @@ pub fn keyCallback(
} else log.warn("runtime doesn't implement gotoSplit", .{});
},
.toggle_fullscreen => {
if (@hasDecl(apprt.Surface, "toggleFullscreen")) {
self.rt_surface.toggleFullscreen();
} else log.warn("runtime doesn't implement toggleFullscreen", .{});
},
.close_surface => self.close(),
.close_window => {

View File

@ -64,6 +64,9 @@ pub const App = struct {
/// Goto tab
goto_tab: ?*const fn (SurfaceUD, usize) callconv(.C) void = null,
/// Toggle fullscreen for current window.
toggle_fullscreen: ?*const fn (SurfaceUD) callconv(.C) void = null,
};
core_app: *CoreApp,
@ -371,6 +374,15 @@ pub const Surface = struct {
func(self.opts.userdata, n);
}
pub fn toggleFullscreen(self: *Surface) void {
const func = self.app.opts.toggle_fullscreen orelse {
log.info("runtime embedder does not toggle_fullscreen", .{});
return;
};
func(self.opts.userdata);
}
/// The cursor position from the host directly is in screen coordinates but
/// all our interface works in pixels.
fn cursorPosToPixels(self: *const Surface, pos: apprt.CursorPos) !apprt.CursorPos {

View File

@ -441,6 +441,13 @@ pub const Config = struct {
}
}
// Toggle fullscreen
try result.keybind.set.put(
alloc,
.{ .key = .enter, .mods = ctrlOrSuper(.{}) },
.{ .toggle_fullscreen = {} },
);
// Mac-specific keyboard bindings.
if (comptime builtin.target.isDarwin()) {
try result.keybind.set.put(

View File

@ -207,6 +207,9 @@ pub const Action = union(enum) {
/// Close the window, regardless of how many tabs or splits there may be.
close_window: void,
/// Toggle fullscreen mode of window.
toggle_fullscreen: void,
/// Quit ghostty
quit: void,