From fbe2b7c2677fbb5af88d9cd6387d1bcf71628435 Mon Sep 17 00:00:00 2001 From: Raiden1411 <67233402+Raiden1411@users.noreply.github.com> Date: Tue, 7 Nov 2023 17:58:00 +0000 Subject: [PATCH 1/4] feat: fullscreen and toggleFullscreen support --- src/apprt/glfw.zig | 59 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index 41bfae892..33010b618 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -144,6 +144,38 @@ pub const App = struct { return &self.config; } + /// Toggle the window to fullscreen mode. + pub fn toggleFullscreen(self: *App, surface: *Surface) void { + _ = self; + const win = surface.window; + + if (!surface.isFullscreen()) { + const monitor = win.getMonitor() orelse monitor: { + log.warn("window had null monitor, getting primary monitor", .{}); + break :monitor glfw.Monitor.getPrimary() orelse { + log.warn("window could not get any monitor. Will not perform action", .{}); + return; + }; + }; + const position = win.getPos(); + const size = surface.getSize() catch { + log.warn("Failed to get window size. Will not perform fullscreen action", .{}); + return; + }; + + surface.window_dimensions = .{ + .width = size.width, + .height = size.height, + .position_x = position.x, + .position_y = position.y, + }; + + win.setMonitor(monitor, 0, 0, surface.window_dimensions.width, surface.window_dimensions.height, 0); + } else { + win.setMonitor(null, @as(i32, @intCast(surface.window_dimensions.position_x)), @as(i32, @intCast(surface.window_dimensions.position_y)), surface.window_dimensions.width, surface.window_dimensions.height, 0); + } + } + /// Create a new window for the app. pub fn newWindow(self: *App, parent_: ?*CoreSurface) !void { _ = try self.newSurface(parent_); @@ -267,6 +299,15 @@ pub const App = struct { }; }; +/// These are used to keep track of the original monitor values so that we can safely +/// toggle on and off of fullscreen. +const MonitorDimensions = struct { + width: u32, + height: u32, + position_x: i64, + position_y: i64, +}; + /// Surface represents the drawable surface for glfw. In glfw, a surface /// is always a window because that is the only abstraction that glfw exposes. /// @@ -297,17 +338,21 @@ pub const Surface = struct { /// (GLFW guarantees that charCallback is called after keyCallback). key_event: ?input.KeyEvent = null, + window_dimensions: MonitorDimensions, + pub const Options = struct {}; /// Initialize the surface into the given self pointer. This gives a /// stable pointer to the destination that can be used for callbacks. pub fn init(self: *Surface, app: *App) !void { + const fullscreen = if (app.config.fullscreen) glfw.Monitor.getPrimary().? else null; + // Create our window const win = glfw.Window.create( 640, 480, "ghostty", - null, + fullscreen, null, Renderer.glfwWindowHints(&app.config), ) orelse return glfw.mustGetErrorCode(); @@ -320,8 +365,8 @@ pub const Surface = struct { log.warn("window had null monitor, getting primary monitor", .{}); break :monitor glfw.Monitor.getPrimary().?; }; - const physical_size = monitor.getPhysicalSize(); const video_mode = monitor.getVideoMode() orelse return glfw.mustGetErrorCode(); + const physical_size = monitor.getPhysicalSize(); const physical_x_dpi = @as(f32, @floatFromInt(video_mode.getWidth())) / (@as(f32, @floatFromInt(physical_size.width_mm)) / 25.4); const physical_y_dpi = @as(f32, @floatFromInt(video_mode.getHeight())) / (@as(f32, @floatFromInt(physical_size.height_mm)) / 25.4); log.debug("physical dpi x={} y={}", .{ @@ -361,6 +406,7 @@ pub const Surface = struct { .window = win, .cursor = null, .core_surface = undefined, + .window_dimensions = undefined, }; errdefer self.* = undefined; @@ -447,6 +493,15 @@ pub const Surface = struct { try self.app.newTab(&self.core_surface); } + /// Checks if the glfw window is in fullscreen. + pub fn isFullscreen(self: *Surface) bool { + return self.window.getMonitor() != null; + } + + pub fn toggleFullscreen(self: *Surface, _: Config.NonNativeFullscreen) void { + self.app.toggleFullscreen(self); + } + /// Close this surface. pub fn close(self: *Surface, processActive: bool) void { _ = processActive; From b9ad49acc3dd1e698ace23311b996920c3cc7607 Mon Sep 17 00:00:00 2001 From: Raiden1411 <67233402+Raiden1411@users.noreply.github.com> Date: Tue, 7 Nov 2023 18:07:22 +0000 Subject: [PATCH 2/4] chore: add video mode --- src/apprt/glfw.zig | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index 33010b618..c7bbd9e76 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -153,13 +153,18 @@ pub const App = struct { const monitor = win.getMonitor() orelse monitor: { log.warn("window had null monitor, getting primary monitor", .{}); break :monitor glfw.Monitor.getPrimary() orelse { - log.warn("window could not get any monitor. Will not perform action", .{}); + log.warn("window could not get any monitor. will not perform action", .{}); return; }; }; + const video_mode = monitor.getVideoMode() orelse { + log.warn("failed to get video mode. will not perform action", .{}); + return; + }; + const position = win.getPos(); const size = surface.getSize() catch { - log.warn("Failed to get window size. Will not perform fullscreen action", .{}); + log.warn("failed to get window size. will not perform fullscreen action", .{}); return; }; @@ -170,7 +175,7 @@ pub const App = struct { .position_y = position.y, }; - win.setMonitor(monitor, 0, 0, surface.window_dimensions.width, surface.window_dimensions.height, 0); + win.setMonitor(monitor, 0, 0, video_mode.getWidth(), video_mode.getHeight(), 0); } else { win.setMonitor(null, @as(i32, @intCast(surface.window_dimensions.position_x)), @as(i32, @intCast(surface.window_dimensions.position_y)), surface.window_dimensions.width, surface.window_dimensions.height, 0); } From b0f6b1e2c937585afbd662bba15d9f3ba1863d28 Mon Sep 17 00:00:00 2001 From: Raiden1411 <67233402+Raiden1411@users.noreply.github.com> Date: Tue, 7 Nov 2023 19:24:02 +0000 Subject: [PATCH 3/4] re-add dimensions --- src/apprt/glfw.zig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index c7bbd9e76..c1b2c1879 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -405,13 +405,17 @@ pub const Surface = struct { win.setMouseButtonCallback(mouseButtonCallback); win.setDropCallback(dropCallback); + const pos = win.getPos(); + const size = win.getFramebufferSize(); + + const dimensions = .{ .width = size.width, .height = size.height, .position_x = pos.x, .position_y = pos.y }; // Build our result self.* = .{ .app = app, .window = win, .cursor = null, .core_surface = undefined, - .window_dimensions = undefined, + .window_dimensions = dimensions, }; errdefer self.* = undefined; From 126f02187ac176e0d4b1d26b1dc2d8f6a5f3efbb Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 9 Nov 2023 15:00:16 -0800 Subject: [PATCH 4/4] apprt/glfw: minor stylistic things --- src/apprt/glfw.zig | 92 +++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index c1b2c1879..7dadcab55 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -149,36 +149,45 @@ pub const App = struct { _ = self; const win = surface.window; - if (!surface.isFullscreen()) { - const monitor = win.getMonitor() orelse monitor: { - log.warn("window had null monitor, getting primary monitor", .{}); - break :monitor glfw.Monitor.getPrimary() orelse { - log.warn("window could not get any monitor. will not perform action", .{}); - return; - }; - }; - const video_mode = monitor.getVideoMode() orelse { - log.warn("failed to get video mode. will not perform action", .{}); - return; - }; - - const position = win.getPos(); - const size = surface.getSize() catch { - log.warn("failed to get window size. will not perform fullscreen action", .{}); - return; - }; - - surface.window_dimensions = .{ - .width = size.width, - .height = size.height, - .position_x = position.x, - .position_y = position.y, - }; - - win.setMonitor(monitor, 0, 0, video_mode.getWidth(), video_mode.getHeight(), 0); - } else { - win.setMonitor(null, @as(i32, @intCast(surface.window_dimensions.position_x)), @as(i32, @intCast(surface.window_dimensions.position_y)), surface.window_dimensions.width, surface.window_dimensions.height, 0); + if (surface.isFullscreen()) { + win.setMonitor( + null, + @intCast(surface.monitor_dims.position_x), + @intCast(surface.monitor_dims.position_y), + surface.monitor_dims.width, + surface.monitor_dims.height, + 0, + ); + return; } + + const monitor = win.getMonitor() orelse monitor: { + log.warn("window had null monitor, getting primary monitor", .{}); + break :monitor glfw.Monitor.getPrimary() orelse { + log.warn("window could not get any monitor. will not perform action", .{}); + return; + }; + }; + + const video_mode = monitor.getVideoMode() orelse { + log.warn("failed to get video mode. will not perform action", .{}); + return; + }; + + const position = win.getPos(); + const size = surface.getSize() catch { + log.warn("failed to get window size. will not perform fullscreen action", .{}); + return; + }; + + surface.monitor_dims = .{ + .width = size.width, + .height = size.height, + .position_x = position.x, + .position_y = position.y, + }; + + win.setMonitor(monitor, 0, 0, video_mode.getWidth(), video_mode.getHeight(), 0); } /// Create a new window for the app. @@ -304,8 +313,8 @@ pub const App = struct { }; }; -/// These are used to keep track of the original monitor values so that we can safely -/// toggle on and off of fullscreen. +/// These are used to keep track of the original monitor values so that we can +/// safely toggle on and off of fullscreen. const MonitorDimensions = struct { width: u32, height: u32, @@ -343,21 +352,21 @@ pub const Surface = struct { /// (GLFW guarantees that charCallback is called after keyCallback). key_event: ?input.KeyEvent = null, - window_dimensions: MonitorDimensions, + /// The monitor dimensions so we can toggle fullscreen on and off. + monitor_dims: MonitorDimensions, pub const Options = struct {}; /// Initialize the surface into the given self pointer. This gives a /// stable pointer to the destination that can be used for callbacks. pub fn init(self: *Surface, app: *App) !void { - const fullscreen = if (app.config.fullscreen) glfw.Monitor.getPrimary().? else null; // Create our window const win = glfw.Window.create( 640, 480, "ghostty", - fullscreen, + if (app.config.fullscreen) glfw.Monitor.getPrimary() else null, null, Renderer.glfwWindowHints(&app.config), ) orelse return glfw.mustGetErrorCode(); @@ -405,17 +414,24 @@ pub const Surface = struct { win.setMouseButtonCallback(mouseButtonCallback); win.setDropCallback(dropCallback); - const pos = win.getPos(); - const size = win.getFramebufferSize(); + const dimensions: MonitorDimensions = dimensions: { + const pos = win.getPos(); + const size = win.getFramebufferSize(); + break :dimensions .{ + .width = size.width, + .height = size.height, + .position_x = pos.x, + .position_y = pos.y, + }; + }; - const dimensions = .{ .width = size.width, .height = size.height, .position_x = pos.x, .position_y = pos.y }; // Build our result self.* = .{ .app = app, .window = win, .cursor = null, .core_surface = undefined, - .window_dimensions = dimensions, + .monitor_dims = dimensions, }; errdefer self.* = undefined;