core: add borderless window fullscreen support
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
cf1e870688
commit
f57073f02f
3 changed files with 67 additions and 18 deletions
|
|
@ -373,9 +373,21 @@ pub const KeyMods = packed struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DisplayMode = enum {
|
pub const DisplayMode = enum {
|
||||||
|
/// Windowed mode.
|
||||||
windowed,
|
windowed,
|
||||||
|
|
||||||
|
/// Fullscreen mode, using this option may change the display's video mode.
|
||||||
fullscreen,
|
fullscreen,
|
||||||
// TODO: fullscreen_windowed,
|
|
||||||
|
/// Borderless fullscreen window.
|
||||||
|
///
|
||||||
|
/// Beware that true .fullscreen is also a hint to the OS that is used in various contexts, e.g.
|
||||||
|
///
|
||||||
|
/// * macOS: Moving to a virtual space dedicated to fullscreen windows as the user expects
|
||||||
|
/// * macOS: .borderless windows cannot prevent the system menu bar from being displayed
|
||||||
|
///
|
||||||
|
/// Always allow users to choose their preferred display mode.
|
||||||
|
borderless,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CursorMode = enum {
|
pub const CursorMode = enum {
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ last_size: glfw.Window.Size,
|
||||||
last_pos: glfw.Window.Pos,
|
last_pos: glfw.Window.Pos,
|
||||||
size_limit: SizeLimit,
|
size_limit: SizeLimit,
|
||||||
frame_buffer_resized: bool,
|
frame_buffer_resized: bool,
|
||||||
|
display_mode: DisplayMode,
|
||||||
|
border: bool,
|
||||||
|
|
||||||
current_cursor: CursorShape,
|
current_cursor: CursorShape,
|
||||||
cursors: [@typeInfo(CursorShape).Enum.fields.len]?glfw.Cursor,
|
cursors: [@typeInfo(CursorShape).Enum.fields.len]?glfw.Cursor,
|
||||||
|
|
@ -191,6 +193,8 @@ pub fn init(core: *Core, allocator: std.mem.Allocator, options: Options) !void {
|
||||||
.max = .{ .width = null, .height = null },
|
.max = .{ .width = null, .height = null },
|
||||||
},
|
},
|
||||||
.frame_buffer_resized = false,
|
.frame_buffer_resized = false,
|
||||||
|
.display_mode = .windowed,
|
||||||
|
.border = true,
|
||||||
|
|
||||||
.current_cursor = .arrow,
|
.current_cursor = .arrow,
|
||||||
.cursors = std.mem.zeroes([@typeInfo(CursorShape).Enum.fields.len]?glfw.Cursor),
|
.cursors = std.mem.zeroes([@typeInfo(CursorShape).Enum.fields.len]?glfw.Cursor),
|
||||||
|
|
@ -391,10 +395,12 @@ pub fn setTitle(self: *Core, title: [:0]const u8) void {
|
||||||
self.window.setTitle(title);
|
self.window.setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setDisplayMode(self: *Core, mode: DisplayMode, monitor_index: ?usize) !void {
|
pub fn setDisplayMode(self: *Core, mode: DisplayMode, monitor_index: ?usize) void {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
.windowed => {
|
.windowed => {
|
||||||
try self.window.setMonitor(
|
self.window.setAttrib(.decorated, self.border);
|
||||||
|
self.window.setAttrib(.floating, false);
|
||||||
|
self.window.setMonitor(
|
||||||
null,
|
null,
|
||||||
@intCast(i32, self.last_pos.x),
|
@intCast(i32, self.last_pos.x),
|
||||||
@intCast(i32, self.last_pos.y),
|
@intCast(i32, self.last_pos.y),
|
||||||
|
|
@ -404,41 +410,68 @@ pub fn setDisplayMode(self: *Core, mode: DisplayMode, monitor_index: ?usize) !vo
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
.fullscreen => {
|
.fullscreen => {
|
||||||
if (try self.displayMode() == .windowed) {
|
if (self.display_mode == .windowed) {
|
||||||
self.last_size = try self.window.getSize();
|
self.last_size = self.window.getSize();
|
||||||
self.last_pos = try self.window.getPos();
|
self.last_pos = self.window.getPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
const monitor = blk: {
|
const monitor = blk: {
|
||||||
if (monitor_index) |i| {
|
if (monitor_index) |i| {
|
||||||
const monitor_list = try glfw.Monitor.getAll(self.allocator);
|
// TODO(core): handle OOM via error flag
|
||||||
|
const monitor_list = glfw.Monitor.getAll(self.allocator) catch unreachable;
|
||||||
defer self.allocator.free(monitor_list);
|
defer self.allocator.free(monitor_list);
|
||||||
break :blk monitor_list[i];
|
break :blk monitor_list[i];
|
||||||
}
|
}
|
||||||
break :blk glfw.Monitor.getPrimary();
|
break :blk glfw.Monitor.getPrimary();
|
||||||
};
|
};
|
||||||
|
if (monitor) |m| {
|
||||||
|
const video_mode = m.getVideoMode();
|
||||||
|
if (video_mode) |v| {
|
||||||
|
self.window.setMonitor(m, 0, 0, v.getWidth(), v.getHeight(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.borderless => {
|
||||||
|
if (self.display_mode == .windowed) {
|
||||||
|
self.last_size = self.window.getSize();
|
||||||
|
self.last_pos = self.window.getPos();
|
||||||
|
}
|
||||||
|
|
||||||
const video_mode = try monitor.?.getVideoMode();
|
const monitor = blk: {
|
||||||
try self.window.setMonitor(monitor, 0, 0, video_mode.getWidth(), video_mode.getHeight(), null);
|
if (monitor_index) |i| {
|
||||||
|
// TODO(core): handle OOM via error flag
|
||||||
|
const monitor_list = glfw.Monitor.getAll(self.allocator) catch unreachable;
|
||||||
|
defer self.allocator.free(monitor_list);
|
||||||
|
break :blk monitor_list[i];
|
||||||
|
}
|
||||||
|
break :blk glfw.Monitor.getPrimary();
|
||||||
|
};
|
||||||
|
if (monitor) |m| {
|
||||||
|
const video_mode = m.getVideoMode();
|
||||||
|
if (video_mode) |v| {
|
||||||
|
self.window.setAttrib(.decorated, false);
|
||||||
|
self.window.setAttrib(.floating, true);
|
||||||
|
self.window.setMonitor(null, 0, 0, v.getWidth(), v.getHeight(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
self.display_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn displayMode(self: *Core) DisplayMode {
|
pub fn displayMode(self: *Core) DisplayMode {
|
||||||
if (self.window.getMonitor()) |_| {
|
return self.display_mode;
|
||||||
return .fullscreen;
|
|
||||||
} else {
|
|
||||||
return .windowed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setBorder(self: *Core, value: bool) void {
|
pub fn setBorder(self: *Core, value: bool) void {
|
||||||
self.window.setAttrib(.decorated, value);
|
if (self.border != value) {
|
||||||
|
self.border = value;
|
||||||
|
if (self.display_mode != .borderless) self.window.setAttrib(.decorated, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn border(self: *Core) !bool {
|
pub fn border(self: *Core) bool {
|
||||||
const decorated = try self.window.getAttrib(.decorated);
|
return self.border;
|
||||||
return decorated == 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setHeadless(self: *Core, value: bool) void {
|
pub fn setHeadless(self: *Core, value: bool) void {
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,10 @@ pub fn setTitle(self: *Core, title: [:0]const u8) void {
|
||||||
|
|
||||||
pub fn setDisplayMode(self: *Core, mode: DisplayMode, monitor: ?usize) void {
|
pub fn setDisplayMode(self: *Core, mode: DisplayMode, monitor: ?usize) void {
|
||||||
_ = monitor;
|
_ = monitor;
|
||||||
|
if (mode == .borderless) {
|
||||||
|
// borderless fullscreen window has no meaning in web
|
||||||
|
mode = .fullscreen;
|
||||||
|
}
|
||||||
js.machCanvasSetDisplayMode(self.id, @enumToInt(mode));
|
js.machCanvasSetDisplayMode(self.id, @enumToInt(mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue