diff --git a/libs/glfw/src/Cursor.zig b/libs/glfw/src/Cursor.zig index 85850e6c..c0f1c898 100644 --- a/libs/glfw/src/Cursor.zig +++ b/libs/glfw/src/Cursor.zig @@ -106,23 +106,19 @@ pub const Shape = enum(i32) { /// @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. /// @return The handle of the created cursor. /// +/// Possible errors include glfw.Error.PlatformError and glfw.Error.InvalidValue +/// null is returned in the event of an error. +/// /// @pointer_lifetime The specified image data is copied before this function returns. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: cursor_object, glfw.Cursor.destroy, glfw.Cursor.createStandard -pub inline fn create(image: Image, xhot: i32, yhot: i32) error{ PlatformError, InvalidValue }!Cursor { +pub inline fn create(image: Image, xhot: i32, yhot: i32) ?Cursor { internal_debug.assertInitialized(); const img = image.toC(); if (c.glfwCreateCursor(&img, @intCast(c_int, xhot), @intCast(c_int, yhot))) |cursor| return Cursor{ .ptr = cursor }; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - Error.InvalidValue => |e| e, - else => unreachable, - }; - // `glfwCreateCursor` returns `null` only for errors - unreachable; + return null; } /// Creates a cursor with a standard shape. @@ -151,22 +147,16 @@ pub inline fn create(image: Image, xhot: i32, yhot: i32) error{ PlatformError, I /// 2. This uses a newer standard that not all cursor themes support. /// /// If the requested shape is not available, this function emits a CursorUnavailable error +/// Possible errors include glfw.Error.PlatformError and glfw.Error.CursorUnavailable. +/// null is returned in the event of an error. /// /// thread_safety: This function must only be called from the main thread. /// /// see also: cursor_object, glfwCreateCursor -pub inline fn createStandard(shape: Shape) error{ PlatformError, CursorUnavailable }!Cursor { +pub inline fn createStandard(shape: Shape) ?Cursor { internal_debug.assertInitialized(); if (c.glfwCreateStandardCursor(@intCast(c_int, @enumToInt(shape)))) |cursor| return Cursor{ .ptr = cursor }; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.CursorUnavailable => |e| e, - Error.PlatformError => |e| e, - else => unreachable, - }; - // `glfwCreateStandardCursor` returns `null` only for errors - unreachable; + return null; } /// Destroys a cursor. @@ -177,7 +167,7 @@ pub inline fn createStandard(shape: Shape) error{ PlatformError, CursorUnavailab /// If the specified cursor is current for any window, that window will be reverted to the default /// cursor. This does not affect the cursor mode. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// @reentrancy This function must not be called from a callback. /// @@ -187,37 +177,35 @@ pub inline fn createStandard(shape: Shape) error{ PlatformError, CursorUnavailab pub inline fn destroy(self: Cursor) void { internal_debug.assertInitialized(); c.glfwDestroyCursor(self.ptr); - getError() catch |err| return switch (err) { - Error.PlatformError => std.log.err("mach/glfw: unable to destroy Cursor: {}\n", .{err}), - else => unreachable, - }; } test "create" { const allocator = testing.allocator; const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const image = try Image.init(allocator, 32, 32, 32 * 32 * 4); defer image.deinit(allocator); - const cursor = glfw.Cursor.create(image, 0, 0) catch |err| { - std.debug.print("failed to create cursor, custom cursors not supported? error={}\n", .{err}); - return; - }; - cursor.destroy(); + const cursor = glfw.Cursor.create(image, 0, 0); + if (cursor) |cur| cur.destroy(); } test "createStandard" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const cursor = glfw.Cursor.createStandard(.ibeam) catch |err| { - std.debug.print("failed to create cursor, custom cursors not supported? error={}\n", .{err}); - return; - }; - cursor.destroy(); + const cursor = glfw.Cursor.createStandard(.ibeam); + if (cursor) |cur| cur.destroy(); } diff --git a/libs/glfw/src/Joystick.zig b/libs/glfw/src/Joystick.zig index ff8fd8a2..54f62372 100644 --- a/libs/glfw/src/Joystick.zig +++ b/libs/glfw/src/Joystick.zig @@ -80,20 +80,14 @@ const GamepadState = extern struct { /// /// @return `true` if the joystick is present, or `false` otherwise. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidEnum and glfw.Error.PlatformError. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: joystick -pub inline fn present(self: Joystick) error{PlatformError}!bool { +pub inline fn present(self: Joystick) bool { internal_debug.assertInitialized(); const is_present = c.glfwJoystickPresent(@enumToInt(self.jid)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return is_present == c.GLFW_TRUE; } @@ -107,7 +101,8 @@ pub inline fn present(self: Joystick) error{PlatformError}!bool { /// /// @return An array of axis values, or null if the joystick is not present. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// null is additionally returned in the event of an error. /// /// @pointer_lifetime The returned array is allocated and freed by GLFW. You should not free it /// yourself. It is valid until the specified joystick is disconnected or the library is @@ -117,16 +112,10 @@ pub inline fn present(self: Joystick) error{PlatformError}!bool { /// /// see also: joystick_axis /// Replaces `glfwGetJoystickPos`. -pub inline fn getAxes(self: Joystick) error{PlatformError}!?[]const f32 { +pub inline fn getAxes(self: Joystick) ?[]const f32 { internal_debug.assertInitialized(); var count: c_int = undefined; const axes = c.glfwGetJoystickAxes(@enumToInt(self.jid), &count); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; if (axes == null) return null; return axes[0..@intCast(u32, count)]; } @@ -147,7 +136,8 @@ pub inline fn getAxes(self: Joystick) error{PlatformError}!?[]const f32 { /// /// @return An array of button states, or null if the joystick is not present. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// null is additionally returned in the event of an error. /// /// @pointer_lifetime The returned array is allocated and freed by GLFW. You should not free it /// yourself. It is valid until the specified joystick is disconnected or the library is terminated. @@ -155,16 +145,10 @@ pub inline fn getAxes(self: Joystick) error{PlatformError}!?[]const f32 { /// @thread_safety This function must only be called from the main thread. /// /// see also: joystick_button -pub inline fn getButtons(self: Joystick) error{PlatformError}!?[]const u8 { +pub inline fn getButtons(self: Joystick) ?[]const u8 { internal_debug.assertInitialized(); var count: c_int = undefined; const buttons = c.glfwGetJoystickButtons(@enumToInt(self.jid), &count); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; if (buttons == null) return null; return buttons[0..@intCast(u32, count)]; } @@ -200,7 +184,8 @@ pub inline fn getButtons(self: Joystick) error{PlatformError}!?[]const u8 { /// /// @return An array of hat states, or null if the joystick is not present. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// null is additionally returned in the event of an error. /// /// @pointer_lifetime The returned array is allocated and freed by GLFW. You should not free it /// yourself. It is valid until the specified joystick is disconnected, this function is called @@ -209,16 +194,10 @@ pub inline fn getButtons(self: Joystick) error{PlatformError}!?[]const u8 { /// @thread_safety This function must only be called from the main thread. /// /// see also: joystick_hat -pub inline fn getHats(self: Joystick) error{PlatformError}!?[]const Hat { +pub inline fn getHats(self: Joystick) ?[]const Hat { internal_debug.assertInitialized(); var count: c_int = undefined; const hats = c.glfwGetJoystickHats(@enumToInt(self.jid), &count); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; if (hats == null) return null; const slice = hats[0..@intCast(u32, count)]; return @ptrCast(*const []const Hat, &slice).*; @@ -235,7 +214,8 @@ pub inline fn getHats(self: Joystick) error{PlatformError}!?[]const Hat { /// @return The UTF-8 encoded name of the joystick, or null if the joystick is not present or an /// error occurred. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// null is additionally returned in the event of an error. /// /// @pointer_lifetime The returned string is allocated and freed by GLFW. You should not free it /// yourself. It is valid until the specified joystick is disconnected or the library is terminated. @@ -243,15 +223,9 @@ pub inline fn getHats(self: Joystick) error{PlatformError}!?[]const Hat { /// @thread_safety This function must only be called from the main thread. /// /// see also: joystick_name -pub inline fn getName(self: Joystick) error{PlatformError}!?[:0]const u8 { +pub inline fn getName(self: Joystick) ?[:0]const u8 { internal_debug.assertInitialized(); const name_opt = c.glfwGetJoystickName(@enumToInt(self.jid)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return if (name_opt) |name| std.mem.span(@ptrCast([*:0]const u8, name)) else @@ -277,7 +251,8 @@ pub inline fn getName(self: Joystick) error{PlatformError}!?[:0]const u8 { /// /// @return The UTF-8 encoded GUID of the joystick, or null if the joystick is not present. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// null is additionally returned in the event of an error. /// /// @pointer_lifetime The returned string is allocated and freed by GLFW. You should not free it /// yourself. It is valid until the specified joystick is disconnected or the library is terminated. @@ -285,15 +260,9 @@ pub inline fn getName(self: Joystick) error{PlatformError}!?[:0]const u8 { /// @thread_safety This function must only be called from the main thread. /// /// see also: gamepad -pub inline fn getGUID(self: Joystick) error{PlatformError}!?[:0]const u8 { +pub inline fn getGUID(self: Joystick) ?[:0]const u8 { internal_debug.assertInitialized(); const guid_opt = c.glfwGetJoystickGUID(@enumToInt(self.jid)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return if (guid_opt) |guid| std.mem.span(@ptrCast([*:0]const u8, guid)) else @@ -313,10 +282,6 @@ pub inline fn getGUID(self: Joystick) error{PlatformError}!?[:0]const u8 { pub inline fn setUserPointer(self: Joystick, comptime T: type, pointer: *T) void { internal_debug.assertInitialized(); c.glfwSetJoystickUserPointer(@enumToInt(self.jid), @ptrCast(*anyopaque, pointer)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Returns the user pointer of the specified joystick. @@ -333,10 +298,6 @@ pub inline fn setUserPointer(self: Joystick, comptime T: type, pointer: *T) void pub inline fn getUserPointer(self: Joystick, comptime PointerType: type) ?PointerType { internal_debug.assertInitialized(); const ptr = c.glfwGetJoystickUserPointer(@enumToInt(self.jid)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; if (ptr) |p| return @ptrCast(PointerType, @alignCast(@alignOf(std.meta.Child(PointerType)), p)); return null; } @@ -366,8 +327,6 @@ pub const Event = enum(c_int) { /// @callback_param `event` One of `.connected` or `.disconnected`. Future releases may add /// more events. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @thread_safety This function must only be called from the main thread. /// /// see also: joystick_event @@ -388,11 +347,6 @@ pub inline fn setCallback(comptime callback: ?fn (joystick: Joystick, event: Eve } else { if (c.glfwSetJoystickCallback(null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Adds the specified SDL_GameControllerDB gamepad mappings. @@ -410,7 +364,8 @@ pub inline fn setCallback(comptime callback: ?fn (joystick: Joystick, event: Eve /// /// @param[in] string The string containing the gamepad mappings. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.InvalidValue. +/// Possible errors include glfw.Error.InvalidValue. +/// Returns a boolean indicating success. /// /// @thread_safety This function must only be called from the main thread. /// @@ -418,18 +373,9 @@ pub inline fn setCallback(comptime callback: ?fn (joystick: Joystick, event: Eve /// /// /// @ingroup input -pub inline fn updateGamepadMappings(gamepad_mappings: [*:0]const u8) error{InvalidValue}!void { +pub inline fn updateGamepadMappings(gamepad_mappings: [*:0]const u8) bool { internal_debug.assertInitialized(); - if (c.glfwUpdateGamepadMappings(gamepad_mappings) == c.GLFW_TRUE) return; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - // TODO: Maybe return as 'ParseError' here? - // TODO: Look into upstream proposal for GLFW to publicize - // their Gamepad mappings parsing functions/interface - // for a better error message in debug. - Error.InvalidValue => |e| e, - else => unreachable, - }; + return c.glfwUpdateGamepadMappings(gamepad_mappings) == c.GLFW_TRUE; } /// Returns whether the specified joystick has a gamepad mapping. @@ -442,7 +388,8 @@ pub inline fn updateGamepadMappings(gamepad_mappings: [*:0]const u8) error{Inval /// /// @return `true` if a joystick is both present and has a gamepad mapping, or `false` otherwise. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.InvalidEnum. +/// Possible errors include glfw.Error.InvalidEnum. +/// Additionally returns false in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// @@ -450,11 +397,6 @@ pub inline fn updateGamepadMappings(gamepad_mappings: [*:0]const u8) error{Inval pub inline fn isGamepad(self: Joystick) bool { internal_debug.assertInitialized(); const is_gamepad = c.glfwJoystickIsGamepad(@enumToInt(self.jid)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - else => unreachable, - }; return is_gamepad == c.GLFW_TRUE; } @@ -470,7 +412,8 @@ pub inline fn isGamepad(self: Joystick) bool { /// @return The UTF-8 encoded name of the gamepad, or null if the joystick is not present or does /// not have a mapping. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.InvalidEnum. +/// Possible errors include glfw.Error.InvalidEnum. +/// Additionally returns null in the event of an error. /// /// @pointer_lifetime The returned string is allocated and freed by GLFW. You should not free it /// yourself. It is valid until the specified joystick is disconnected, the gamepad mappings are @@ -482,11 +425,6 @@ pub inline fn isGamepad(self: Joystick) bool { pub inline fn getGamepadName(self: Joystick) ?[:0]const u8 { internal_debug.assertInitialized(); const name_opt = c.glfwGetGamepadName(@enumToInt(self.jid)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidValue => unreachable, - else => unreachable, - }; return if (name_opt) |name| std.mem.span(@ptrCast([*:0]const u8, name)) else @@ -512,7 +450,8 @@ pub inline fn getGamepadName(self: Joystick) ?[:0]const u8 { /// @return the gamepad input state if successful, or null if no joystick is connected or it has no /// gamepad mapping. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.InvalidEnum. +/// Possible errors include glfw.Error.InvalidEnum. +/// Returns null in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// @@ -521,81 +460,101 @@ pub inline fn getGamepadState(self: Joystick) ?GamepadState { internal_debug.assertInitialized(); var state: GamepadState = undefined; const success = c.glfwGetGamepadState(@enumToInt(self.jid), @ptrCast(*c.GLFWgamepadstate, &state)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - else => unreachable, - }; return if (success == c.GLFW_TRUE) state else null; } test "present" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; - - _ = joystick.present() catch |err| std.debug.print("failed to detect joystick, joysticks not supported? error={}\n", .{err}); + _ = joystick.present(); } test "getAxes" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; - - _ = joystick.getAxes() catch |err| std.debug.print("failed to get joystick axes, joysticks not supported? error={}\n", .{err}); + _ = joystick.getAxes(); } test "getButtons" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; - - _ = joystick.getButtons() catch |err| std.debug.print("failed to get joystick buttons, joysticks not supported? error={}\n", .{err}); + _ = joystick.getButtons(); } test "getHats" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; - _ = joystick.getHats() catch |err| std.debug.print("failed to get joystick hats, joysticks not supported? error={}\n", .{err}); - const hats = std.mem.zeroes(Hat); - if (hats.down and hats.up) { - // down-up! + if (joystick.getHats()) |hats| { + for (hats) |hat| { + if (hat.down and hat.up) { + // down-up! + } + } } } test "getName" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; - - _ = joystick.getName() catch |err| std.debug.print("failed to get joystick name, joysticks not supported? error={}\n", .{err}); + _ = joystick.getName(); } test "getGUID" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; - - _ = joystick.getGUID() catch |err| std.debug.print("failed to get joystick GUID, joysticks not supported? error={}\n", .{err}); + _ = joystick.getGUID(); } test "setUserPointer_syntax" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; @@ -607,7 +566,11 @@ test "setUserPointer_syntax" { test "getUserPointer_syntax" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; @@ -619,7 +582,11 @@ test "getUserPointer_syntax" { test "setCallback" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); glfw.Joystick.setCallback((struct { @@ -637,7 +604,11 @@ test "updateGamepadMappings_syntax" { test "isGamepad" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; @@ -646,7 +617,11 @@ test "isGamepad" { test "getGamepadName" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; @@ -655,7 +630,11 @@ test "getGamepadName" { test "getGamepadState" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const joystick = glfw.Joystick{ .jid = .one }; diff --git a/libs/glfw/src/Monitor.zig b/libs/glfw/src/Monitor.zig index df0d448b..a950c461 100644 --- a/libs/glfw/src/Monitor.zig +++ b/libs/glfw/src/Monitor.zig @@ -27,21 +27,16 @@ const Pos = struct { /// Returns the position of the monitor's viewport on the virtual screen. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: monitor_properties -pub inline fn getPos(self: Monitor) error{PlatformError}!Pos { +pub inline fn getPos(self: Monitor) Pos { internal_debug.assertInitialized(); var xpos: c_int = 0; var ypos: c_int = 0; c.glfwGetMonitorPos(self.handle, &xpos, &ypos); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return Pos{ .x = @intCast(u32, xpos), .y = @intCast(u32, ypos) }; } @@ -60,23 +55,19 @@ const Workarea = struct { /// Retrieves the work area of the monitor. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// A zero value is returned in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: monitor_workarea -pub inline fn getWorkarea(self: Monitor) error{PlatformError}!Workarea { +pub inline fn getWorkarea(self: Monitor) Workarea { internal_debug.assertInitialized(); var xpos: c_int = 0; var ypos: c_int = 0; var width: c_int = 0; var height: c_int = 0; c.glfwGetMonitorWorkarea(self.handle, &xpos, &ypos, &width, &height); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return Workarea{ .x = @intCast(u32, xpos), .y = @intCast(u32, ypos), .width = @intCast(u32, width), .height = @intCast(u32, height) }; } @@ -92,9 +83,6 @@ const PhysicalSize = struct { /// [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data) /// data is incorrect or because the driver does not report it accurately. /// -/// Possible errors include glfw.Error.NotInitialized. -/// -/// /// win32: On Windows 8 and earlier the physical size is calculated from /// the current resolution and system DPI instead of querying the monitor EDID data /// @thread_safety This function must only be called from the main thread. @@ -105,10 +93,6 @@ pub inline fn getPhysicalSize(self: Monitor) PhysicalSize { var width_mm: c_int = 0; var height_mm: c_int = 0; c.glfwGetMonitorPhysicalSize(self.handle, &width_mm, &height_mm); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; return PhysicalSize{ .width_mm = @intCast(u32, width_mm), .height_mm = @intCast(u32, height_mm) }; } @@ -130,21 +114,17 @@ const ContentScale = struct { /// Returns the content scale for the monitor. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// A zero value is returned in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: monitor_scale, glfw.Window.getContentScale -pub inline fn getContentScale(self: Monitor) error{PlatformError}!ContentScale { +pub inline fn getContentScale(self: Monitor) ContentScale { internal_debug.assertInitialized(); var x_scale: f32 = 0; var y_scale: f32 = 0; c.glfwGetMonitorContentScale(self.handle, &x_scale, &y_scale); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return ContentScale{ .x_scale = @floatCast(f32, x_scale), .y_scale = @floatCast(f32, y_scale) }; } @@ -154,8 +134,6 @@ pub inline fn getContentScale(self: Monitor) error{PlatformError}!ContentScale { /// name typically reflects the make and model of the monitor and is not guaranteed to be unique /// among the connected monitors. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @pointer_lifetime The returned string is allocated and freed by GLFW. You should not free it /// yourself. It is valid until the specified monitor is disconnected or the library is terminated. /// @@ -165,11 +143,8 @@ pub inline fn getContentScale(self: Monitor) error{PlatformError}!ContentScale { pub inline fn getName(self: Monitor) [*:0]const u8 { internal_debug.assertInitialized(); if (c.glfwGetMonitorName(self.handle)) |name| return @ptrCast([*:0]const u8, name); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; - // `glfwGetMonitorName` returns `null` only for errors + // `glfwGetMonitorName` returns `null` only for errors, but the only error is unreachable + // (NotInitialized) unreachable; } @@ -181,18 +156,12 @@ pub inline fn getName(self: Monitor) [*:0]const u8 { /// This function may be called from the monitor callback, even for a monitor that is being /// disconnected. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @thread_safety This function may be called from any thread. Access is not synchronized. /// /// see also: monitor_userptr, glfw.Monitor.getUserPointer pub inline fn setUserPointer(self: Monitor, comptime T: type, ptr: *T) void { internal_debug.assertInitialized(); c.glfwSetMonitorUserPointer(self.handle, ptr); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Returns the user pointer of the specified monitor. @@ -202,18 +171,12 @@ pub inline fn setUserPointer(self: Monitor, comptime T: type, ptr: *T) void { /// This function may be called from the monitor callback, even for a monitor that is being /// disconnected. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @thread_safety This function may be called from any thread. Access is not synchronized. /// /// see also: monitor_userptr, glfw.Monitor.setUserPointer pub inline fn getUserPointer(self: Monitor, comptime T: type) ?*T { internal_debug.assertInitialized(); const ptr = c.glfwGetMonitorUserPointer(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; if (ptr == null) return null; return @ptrCast(*T, @alignCast(@alignOf(T), ptr.?)); } @@ -225,14 +188,17 @@ pub inline fn getUserPointer(self: Monitor, comptime T: type) ?*T { /// then by resolution area (the product of width and height), then resolution width and finally /// by refresh rate. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// Returns null in the event of an error. /// /// The returned slice memory is owned by the caller. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: monitor_modes, glfw.Monitor.getVideoMode -pub inline fn getVideoModes(self: Monitor, allocator: mem.Allocator) (mem.Allocator.Error || error{PlatformError})![]VideoMode { +// +/// TODO(glfw): rewrite this to not require any allocation. +pub inline fn getVideoModes(self: Monitor, allocator: mem.Allocator) mem.Allocator.Error!?[]VideoMode { internal_debug.assertInitialized(); var count: c_int = 0; if (c.glfwGetVideoModes(self.handle, &count)) |modes| { @@ -243,13 +209,7 @@ pub inline fn getVideoModes(self: Monitor, allocator: mem.Allocator) (mem.Alloca } return slice; } - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; - // `glfwGetVideoModes` returns `null` only for errors - unreachable; + return null; } /// Returns the current mode of the specified monitor. @@ -258,21 +218,16 @@ pub inline fn getVideoModes(self: Monitor, allocator: mem.Allocator) (mem.Alloca /// full screen window for that monitor, the return value will depend on whether that window is /// iconified. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// Additionally returns null in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: monitor_modes, glfw.Monitor.getVideoModes -pub inline fn getVideoMode(self: Monitor) error{PlatformError}!VideoMode { +pub inline fn getVideoMode(self: Monitor) ?VideoMode { internal_debug.assertInitialized(); if (c.glfwGetVideoMode(self.handle)) |mode| return VideoMode{ .handle = mode.* }; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; - // `glfwGetVideoMode` returns `null` only for errors - unreachable; + return null; } /// Generates a gamma ramp and sets it for the specified monitor. @@ -286,7 +241,7 @@ pub inline fn getVideoMode(self: Monitor) error{PlatformError}!VideoMode { /// /// For gamma correct rendering with OpenGL or OpenGL ES, see the glfw.srgb_capable hint. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidValue and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidValue and glfw.Error.PlatformError. /// /// wayland: Gamma handling is a privileged protocol, this function will thus never be implemented /// and emits glfw.Error.PlatformError. @@ -294,7 +249,7 @@ pub inline fn getVideoMode(self: Monitor) error{PlatformError}!VideoMode { /// @thread_safety This function must only be called from the main thread. /// /// see also: monitor_gamma -pub inline fn setGamma(self: Monitor, gamma: f32) error{PlatformError}!void { +pub inline fn setGamma(self: Monitor, gamma: f32) void { internal_debug.assertInitialized(); std.debug.assert(!std.math.isNan(gamma)); @@ -302,19 +257,14 @@ pub inline fn setGamma(self: Monitor, gamma: f32) error{PlatformError}!void { std.debug.assert(gamma <= std.math.f32_max); c.glfwSetGamma(self.handle, gamma); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidValue => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Returns the current gamma ramp for the specified monitor. /// /// This function returns the current gamma ramp of the specified monitor. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// Additionally returns null in the event of an error. /// /// wayland: Gamma handling is a privileged protocol, this function will thus never be implemented /// and returns glfw.Error.PlatformError. @@ -326,16 +276,10 @@ pub inline fn setGamma(self: Monitor, gamma: f32) error{PlatformError}!void { /// @thread_safety This function must only be called from the main thread. /// /// see also: monitor_gamma -pub inline fn getGammaRamp(self: Monitor) error{ PlatformError, FeatureUnavailable }!GammaRamp { +pub inline fn getGammaRamp(self: Monitor) ?GammaRamp { internal_debug.assertInitialized(); if (c.glfwGetGammaRamp(self.handle)) |ramp| return GammaRamp.fromC(ramp.*); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError, Error.FeatureUnavailable => |e| e, - else => unreachable, - }; - // `glfwGetGammaRamp` returns `null` only for errors - unreachable; + return null; } /// Sets the current gamma ramp for the specified monitor. @@ -350,7 +294,7 @@ pub inline fn getGammaRamp(self: Monitor) error{ PlatformError, FeatureUnavailab /// /// For gamma correct rendering with OpenGL or OpenGL ES, see the glfw.srgb_capable hint. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// The size of the specified gamma ramp should match the size of the current ramp for that /// monitor. On win32, the gamma ramp size must be 256. @@ -363,14 +307,9 @@ pub inline fn getGammaRamp(self: Monitor) error{ PlatformError, FeatureUnavailab /// @thread_safety This function must only be called from the main thread. /// /// see also: monitor_gamma -pub inline fn setGammaRamp(self: Monitor, ramp: GammaRamp) error{PlatformError}!void { +pub inline fn setGammaRamp(self: Monitor, ramp: GammaRamp) void { internal_debug.assertInitialized(); c.glfwSetGammaRamp(self.handle, &ramp.toC()); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Returns the currently connected monitors. @@ -395,11 +334,8 @@ pub inline fn getAll(allocator: mem.Allocator) mem.Allocator.Error![]Monitor { } return slice; } - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; - // `glfwGetMonitors` returning null can be either an error or no monitors + // `glfwGetMonitors` returning null can be either an error or no monitors, but the only error is + // unreachable (NotInitialized) return &[_]Monitor{}; } @@ -408,18 +344,12 @@ pub inline fn getAll(allocator: mem.Allocator) mem.Allocator.Error![]Monitor { /// This function returns the primary monitor. This is usually the monitor where elements like /// the task bar or global menu bar are located. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @thread_safety This function must only be called from the main thread. /// /// see also: monitor_monitors, glfw.monitors.getAll pub inline fn getPrimary() ?Monitor { internal_debug.assertInitialized(); if (c.glfwGetPrimaryMonitor()) |handle| return Monitor{ .handle = handle }; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; return null; } @@ -448,8 +378,6 @@ pub const Event = enum(c_int) { /// /// `event` may be one of .connected or .disconnected. More events may be added in the future. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @thread_safety This function must only be called from the main thread. /// /// see also: monitor_event @@ -470,16 +398,15 @@ pub inline fn setCallback(comptime callback: ?fn (monitor: Monitor, event: Event } else { if (c.glfwSetMonitorCallback(null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } test "getAll" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const allocator = testing.allocator; @@ -489,7 +416,11 @@ test "getAll" { test "getPrimary" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); _ = getPrimary(); @@ -497,29 +428,41 @@ test "getPrimary" { test "getPos" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const monitor = getPrimary(); if (monitor) |m| { - _ = try m.getPos(); + _ = m.getPos(); } } test "getWorkarea" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const monitor = getPrimary(); if (monitor) |m| { - _ = try m.getWorkarea(); + _ = m.getWorkarea(); } } test "getPhysicalSize" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const monitor = getPrimary(); @@ -530,18 +473,26 @@ test "getPhysicalSize" { test "getContentScale" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const monitor = getPrimary(); if (monitor) |m| { - _ = try m.getContentScale(); + _ = m.getContentScale(); } } test "getName" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const monitor = getPrimary(); @@ -552,7 +503,11 @@ test "getName" { test "userPointer" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const monitor = getPrimary(); @@ -568,7 +523,11 @@ test "userPointer" { test "setCallback" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); setCallback(struct { @@ -581,46 +540,57 @@ test "setCallback" { test "getVideoModes" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const monitor = getPrimary(); if (monitor) |m| { const allocator = testing.allocator; - const modes = try m.getVideoModes(allocator); - defer allocator.free(modes); + const modes_maybe = try m.getVideoModes(allocator); + if (modes_maybe) |modes| { + defer allocator.free(modes); + } } } test "getVideoMode" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const monitor = getPrimary(); if (monitor) |m| { - _ = try m.getVideoMode(); + _ = m.getVideoMode(); } } test "set_getGammaRamp" { const allocator = testing.allocator; const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const monitor = getPrimary(); if (monitor) |m| { - const ramp = m.getGammaRamp() catch |err| { - std.debug.print("can't get window position, wayland maybe? error={}\n", .{err}); - return; - }; + if (m.getGammaRamp()) |ramp| { + // Set it to the exact same value; if we do otherwise an our tests fail it wouldn't call + // terminate and our made-up gamma ramp would get stuck. + m.setGammaRamp(ramp); - // Set it to the exact same value; if we do otherwise an our tests fail it wouldn't call - // terminate and our made-up gamma ramp would get stuck. - try m.setGammaRamp(ramp); - - // technically not needed here / noop because GLFW owns this gamma ramp. - defer ramp.deinit(allocator); + // technically not needed here / noop because GLFW owns this gamma ramp. + defer ramp.deinit(allocator); + } } } diff --git a/libs/glfw/src/Window.zig b/libs/glfw/src/Window.zig index fa11bd84..54d1e838 100644 --- a/libs/glfw/src/Window.zig +++ b/libs/glfw/src/Window.zig @@ -31,18 +31,12 @@ pub inline fn from(handle: *anyopaque) Window { /// /// This function resets all window hints to their default values. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_hints, glfw.Window.hint, glfw.Window.hintString pub inline fn defaultHints() void { internal_debug.assertInitialized(); c.glfwDefaultWindowHints(); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Window hints @@ -255,12 +249,6 @@ pub const Hints = struct { else => unreachable, } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - else => unreachable, - }; } } }; @@ -307,9 +295,10 @@ pub const Hints = struct { /// The swap interval is not set during window creation and the initial value may vary depending on /// driver settings and defaults. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum, glfw.Error.InvalidValue, +/// Possible errors include glfw.Error.InvalidEnum, glfw.Error.InvalidValue, /// glfw.Error.APIUnavailable, glfw.Error.VersionUnavailable, glfw.Error.FormatUnavailable and /// glfw.Error.PlatformError. +/// Returns null in the event of an error. /// /// Parameters are as follows: /// @@ -385,7 +374,7 @@ pub inline fn create( monitor: ?Monitor, share: ?Window, hints: Hints, -) error{ APIUnavailable, VersionUnavailable, FormatUnavailable, PlatformError }!Window { +) ?Window { internal_debug.assertInitialized(); const ignore_hints_struct = if (comptime @import("builtin").is_test) testing_ignore_window_hints_struct else false; if (!ignore_hints_struct) hints.set(); @@ -397,21 +386,7 @@ pub inline fn create( if (monitor) |m| m.handle else null, if (share) |w| w.handle else null, )) |handle| return from(handle); - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.InvalidValue => unreachable, - Error.APIUnavailable, - Error.PlatformError, - Error.VersionUnavailable, - Error.FormatUnavailable, - => |e| e, - - else => unreachable, - }; - // `glfwCreateWindow` returns `null` only for errors - unreachable; + return null; } var testing_ignore_window_hints_struct = if (@import("builtin").is_test) false else @as(void, {}); @@ -427,6 +402,8 @@ var testing_ignore_window_hints_struct = if (@import("builtin").is_test) false e /// note: The context of the specified window must not be current on any other thread when this /// function is called. /// +/// Possible errors include glfw.Error.PlatformError. +/// /// @reentrancy This function must not be called from a callback. /// /// @thread_safety This function must only be called from the main thread. @@ -435,17 +412,6 @@ var testing_ignore_window_hints_struct = if (@import("builtin").is_test) false e pub inline fn destroy(self: Window) void { internal_debug.assertInitialized(); c.glfwDestroyWindow(self.handle); - - // Technically, glfwDestroyWindow could produce errors including glfw.Error.NotInitialized and - // glfw.Error.PlatformError. But how would anybody handle them? By creating a new window to - // warn the user? That seems user-hostile. Also, `defer try window.destroy()` isn't possible in - // Zig, so by returning an error we'd make it harder to destroy the window properly. So we differ - // from GLFW here: we discard any potential error from this operation. - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => std.log.debug("{}: was unable to destroy Window.\n", .{err}), - else => unreachable, - }; } /// Checks the close flag of the specified window. @@ -457,12 +423,7 @@ pub inline fn destroy(self: Window) void { /// see also: window_close pub inline fn shouldClose(self: Window) bool { internal_debug.assertInitialized(); - const flag = c.glfwWindowShouldClose(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; - return flag == c.GLFW_TRUE; + return c.glfwWindowShouldClose(self.handle) == c.GLFW_TRUE; } /// Sets the close flag of the specified window. @@ -470,8 +431,6 @@ pub inline fn shouldClose(self: Window) bool { /// This function sets the value of the close flag of the specified window. This can be used to /// override the user's attempt to close the window, or to signal that it should be closed. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @thread_safety This function may be called from any thread. Access is not /// synchronized. /// @@ -480,31 +439,22 @@ pub inline fn setShouldClose(self: Window, value: bool) void { internal_debug.assertInitialized(); const boolean = if (value) c.GLFW_TRUE else c.GLFW_FALSE; c.glfwSetWindowShouldClose(self.handle, boolean); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the UTF-8 encoded title of the specified window. /// /// This function sets the window title, encoded as UTF-8, of the specified window. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// macos: The window title will not be updated until the next time you process events. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_title -pub inline fn setTitle(self: Window, title: [*:0]const u8) error{PlatformError}!void { +pub inline fn setTitle(self: Window, title: [*:0]const u8) void { internal_debug.assertInitialized(); c.glfwSetWindowTitle(self.handle, title); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Sets the icon for the specified window. @@ -530,10 +480,12 @@ pub inline fn setTitle(self: Window, title: [*:0]const u8) error{PlatformError}! /// wayland: There is no existing protocol to change an icon, the window will thus inherit the one /// defined in the application's desktop file. This function will emit glfw.Error.FeatureUnavailable. /// +/// Possible errors include glfw.Error.InvalidValue, glfw.Error.FeatureUnavailable +/// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_icon -pub inline fn setIcon(self: Window, allocator: mem.Allocator, images: ?[]Image) (mem.Allocator.Error || error{ InvalidValue, FeatureUnavailable })!void { +pub inline fn setIcon(self: Window, allocator: mem.Allocator, images: ?[]Image) mem.Allocator.Error!void { internal_debug.assertInitialized(); if (images) |im| { const tmp = try allocator.alloc(c.GLFWimage, im.len); @@ -541,12 +493,6 @@ pub inline fn setIcon(self: Window, allocator: mem.Allocator, images: ?[]Image) for (im) |img, index| tmp[index] = img.toC(); c.glfwSetWindowIcon(self.handle, @intCast(c_int, im.len), &tmp[0]); } else c.glfwSetWindowIcon(self.handle, 0, null); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidValue => |e| e, - Error.FeatureUnavailable => |e| e, - else => unreachable, - }; } pub const Pos = struct { @@ -559,7 +505,8 @@ pub const Pos = struct { /// This function retrieves the position, in screen coordinates, of the upper-left corner of the /// content area of the specified window. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.FeatureUnavailable. +/// Possible errors include glfw.Error.FeatureUnavailable. +/// Additionally returns a zero value in the event of an error. /// /// wayland: There is no way for an application to retrieve the global position of its windows, /// this function will always emit glfw.Error.FeatureUnavailable. @@ -567,16 +514,11 @@ pub const Pos = struct { /// @thread_safety This function must only be called from the main thread. /// /// see also: window_pos glfw.Window.setPos -pub inline fn getPos(self: Window) error{FeatureUnavailable}!Pos { +pub inline fn getPos(self: Window) Pos { internal_debug.assertInitialized(); var x: c_int = 0; var y: c_int = 0; c.glfwGetWindowPos(self.handle, &x, &y); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.FeatureUnavailable => |e| e, - else => unreachable, - }; return Pos{ .x = @intCast(i64, x), .y = @intCast(i64, y) }; } @@ -592,7 +534,7 @@ pub inline fn getPos(self: Window) error{FeatureUnavailable}!Pos { /// The window manager may put limits on what positions are allowed. GLFW cannot and should not /// override these limits. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.FeatureUnavailable. +/// Possible errors include glfw.Error.FeatureUnavailable. /// /// wayland: There is no way for an application to set the global position of its windows, this /// function will always emit glfw.Error.FeatureUnavailable. @@ -600,14 +542,9 @@ pub inline fn getPos(self: Window) error{FeatureUnavailable}!Pos { /// @thread_safety This function must only be called from the main thread. /// /// see also: window_pos, glfw.Window.getPos -pub inline fn setPos(self: Window, pos: Pos) error{FeatureUnavailable}!void { +pub inline fn setPos(self: Window, pos: Pos) void { internal_debug.assertInitialized(); c.glfwSetWindowPos(self.handle, @intCast(c_int, pos.x), @intCast(c_int, pos.y)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.FeatureUnavailable => |e| e, - else => unreachable, - }; } pub const Size = struct { @@ -621,21 +558,17 @@ pub const Size = struct { /// window. If you wish to retrieve the size of the framebuffer of the window in pixels, see /// glfw.Window.getFramebufferSize. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// Additionally returns a zero value in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_size, glfw.Window.setSize -pub inline fn getSize(self: Window) error{PlatformError}!Size { +pub inline fn getSize(self: Window) Size { internal_debug.assertInitialized(); var width: c_int = 0; var height: c_int = 0; c.glfwGetWindowSize(self.handle, &width, &height); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return Size{ .width = @intCast(u32, width), .height = @intCast(u32, height) }; } @@ -653,7 +586,7 @@ pub inline fn getSize(self: Window) error{PlatformError}!Size { /// The window manager may put limits on what sizes are allowed. GLFW cannot and should not /// override these limits. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// wayland: A full screen window will not attempt to change the mode, no matter what the requested /// size. @@ -661,14 +594,9 @@ pub inline fn getSize(self: Window) error{PlatformError}!Size { /// @thread_safety This function must only be called from the main thread. /// /// see also: window_size, glfw.Window.getSize, glfw.Window.SetMonitor -pub inline fn setSize(self: Window, size: Size) error{PlatformError}!void { +pub inline fn setSize(self: Window, size: Size) void { internal_debug.assertInitialized(); c.glfwSetWindowSize(self.handle, @intCast(c_int, size.width), @intCast(c_int, size.height)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// A size with option width/height, used to represent e.g. constraints on a windows size while @@ -689,7 +617,7 @@ pub const SizeOptional = struct { /// The maximum dimensions must be greater than or equal to the minimum dimensions. glfw.dont_care /// may be used for any width/height parameter. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidValue and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidValue and glfw.Error.PlatformError. /// /// If you set size limits and an aspect ratio that conflict, the results are undefined. /// @@ -699,7 +627,7 @@ pub const SizeOptional = struct { /// @thread_safety This function must only be called from the main thread. /// /// see also: window_sizelimits, glfw.Window.setAspectRatio -pub inline fn setSizeLimits(self: Window, min: SizeOptional, max: SizeOptional) error{PlatformError}!void { +pub inline fn setSizeLimits(self: Window, min: SizeOptional, max: SizeOptional) void { internal_debug.assertInitialized(); if (min.width != null and max.width != null) { @@ -716,12 +644,6 @@ pub inline fn setSizeLimits(self: Window, min: SizeOptional, max: SizeOptional) if (max.width) |max_width| @intCast(c_int, max_width) else glfw.dont_care, if (max.height) |max_height| @intCast(c_int, max_height) else glfw.dont_care, ); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidValue => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Sets the aspect ratio of the specified window. @@ -739,8 +661,7 @@ pub inline fn setSizeLimits(self: Window, min: SizeOptional, max: SizeOptional) /// The aspect ratio is applied immediately to a windowed mode window and may cause it to be /// resized. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidValue and -/// glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidValue and glfw.Error.PlatformError. /// /// If you set size limits and an aspect ratio that conflict, the results are undefined. /// @@ -752,7 +673,7 @@ pub inline fn setSizeLimits(self: Window, min: SizeOptional, max: SizeOptional) /// see also: window_sizelimits, glfw.Window.setSizeLimits /// /// WARNING: on wayland it will return Error.FeatureUnimplemented -pub inline fn setAspectRatio(self: Window, numerator: ?u32, denominator: ?u32) error{ PlatformError, FeatureUnimplemented }!void { +pub inline fn setAspectRatio(self: Window, numerator: ?u32, denominator: ?u32) void { internal_debug.assertInitialized(); if (numerator != null and denominator != null) { @@ -765,12 +686,6 @@ pub inline fn setAspectRatio(self: Window, numerator: ?u32, denominator: ?u32) e if (numerator) |numerator_unwrapped| @intCast(c_int, numerator_unwrapped) else glfw.dont_care, if (denominator) |denominator_unwrapped| @intCast(c_int, denominator_unwrapped) else glfw.dont_care, ); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidValue => unreachable, - Error.PlatformError, Error.FeatureUnimplemented => |e| e, - else => unreachable, - }; } /// Retrieves the size of the framebuffer of the specified window. @@ -778,21 +693,17 @@ pub inline fn setAspectRatio(self: Window, numerator: ?u32, denominator: ?u32) e /// This function retrieves the size, in pixels, of the framebuffer of the specified window. If you /// wish to retrieve the size of the window in screen coordinates, see @ref glfwGetWindowSize. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// Additionally returns a zero value in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_fbsize, glfwWindow.setFramebufferSizeCallback -pub inline fn getFramebufferSize(self: Window) error{PlatformError}!Size { +pub inline fn getFramebufferSize(self: Window) Size { internal_debug.assertInitialized(); var width: c_int = 0; var height: c_int = 0; c.glfwGetFramebufferSize(self.handle, &width, &height); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return Size{ .width = @intCast(u32, width), .height = @intCast(u32, height) }; } @@ -812,23 +723,19 @@ pub const FrameSize = struct { /// Because this function retrieves the size of each window frame edge and not the offset along a /// particular coordinate axis, the retrieved values will always be zero or positive. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// Additionally returns a zero value in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_size -pub inline fn getFrameSize(self: Window) error{PlatformError}!FrameSize { +pub inline fn getFrameSize(self: Window) FrameSize { internal_debug.assertInitialized(); var left: c_int = 0; var top: c_int = 0; var right: c_int = 0; var bottom: c_int = 0; c.glfwGetWindowFrameSize(self.handle, &left, &top, &right, &bottom); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return FrameSize{ .left = @intCast(u32, left), .top = @intCast(u32, top), @@ -854,21 +761,17 @@ pub const ContentScale = struct { /// On platforms where each monitors can have its own content scale, the window content scale will /// depend on which monitor the system considers the window to be on. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// Additionally returns a zero value in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_scale, glfwSetWindowContentScaleCallback, glfwGetMonitorContentScale -pub inline fn getContentScale(self: Window) error{PlatformError}!ContentScale { +pub inline fn getContentScale(self: Window) ContentScale { internal_debug.assertInitialized(); var x_scale: f32 = 0; var y_scale: f32 = 0; c.glfwGetWindowContentScale(self.handle, &x_scale, &y_scale); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return ContentScale{ .x_scale = x_scale, .y_scale = y_scale }; } @@ -882,19 +785,15 @@ pub inline fn getContentScale(self: Window) error{PlatformError}!ContentScale { /// /// The initial opacity value for newly created windows is one. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// Additionally returns a zero value in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_transparency, glfw.Window.setOpacity -pub inline fn getOpacity(self: Window) error{PlatformError}!f32 { +pub inline fn getOpacity(self: Window) f32 { internal_debug.assertInitialized(); const opacity = c.glfwGetWindowOpacity(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return opacity; } @@ -913,15 +812,9 @@ pub inline fn getOpacity(self: Window) error{PlatformError}!f32 { /// @thread_safety This function must only be called from the main thread. /// /// see also: window_transparency, glfw.Window.getOpacity -pub inline fn setOpacity(self: Window, opacity: f32) error{ PlatformError, FeatureUnavailable }!void { +pub inline fn setOpacity(self: Window, opacity: f32) void { internal_debug.assertInitialized(); c.glfwSetWindowOpacity(self.handle, opacity); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - Error.FeatureUnavailable => |e| e, - else => unreachable, - }; } /// Iconifies the specified window. @@ -932,7 +825,7 @@ pub inline fn setOpacity(self: Window, opacity: f32) error{ PlatformError, Featu /// If the specified window is a full screen window, the original monitor resolution is restored /// until the window is restored. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// wayland: Once a window is iconified, glfw.Window.restorebe able to restore it. This is a design /// decision of the xdg-shell protocol. @@ -940,14 +833,9 @@ pub inline fn setOpacity(self: Window, opacity: f32) error{ PlatformError, Featu /// @thread_safety This function must only be called from the main thread. /// /// see also: window_iconify, glfw.Window.restore, glfw.Window.maximize -pub inline fn iconify(self: Window) error{PlatformError}!void { +pub inline fn iconify(self: Window) void { internal_debug.assertInitialized(); c.glfwIconifyWindow(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Restores the specified window. @@ -958,19 +846,14 @@ pub inline fn iconify(self: Window) error{PlatformError}!void { /// If the specified window is a full screen window, the resolution chosen for the window is /// restored on the selected monitor. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_iconify, glfw.Window.iconify, glfw.Window.maximize -pub inline fn restore(self: Window) error{PlatformError}!void { +pub inline fn restore(self: Window) void { internal_debug.assertInitialized(); c.glfwRestoreWindow(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Maximizes the specified window. @@ -980,19 +863,14 @@ pub inline fn restore(self: Window) error{PlatformError}!void { /// /// If the specified window is a full screen window, this function does nothing. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_iconify, glfw.Window.iconify, glfw.Window.restore -pub inline fn maximize(self: Window) error{PlatformError}!void { +pub inline fn maximize(self: Window) void { internal_debug.assertInitialized(); c.glfwMaximizeWindow(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Makes the specified window visible. @@ -1013,14 +891,9 @@ pub inline fn maximize(self: Window) error{PlatformError}!void { /// see also: window_hide, glfw.Window.hide /// /// WARNING: on wayland it will return Error.FeatureUnavailable -pub inline fn show(self: Window) error{ PlatformError, FeatureUnavailable }!void { +pub inline fn show(self: Window) void { internal_debug.assertInitialized(); c.glfwShowWindow(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError, Error.FeatureUnavailable => |e| e, - else => unreachable, - }; } /// Hides the specified window. @@ -1028,19 +901,14 @@ pub inline fn show(self: Window) error{ PlatformError, FeatureUnavailable }!void /// This function hides the specified window if it was previously visible. If the window is already /// hidden or is in full screen mode, this function does nothing. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_hide, glfw.Window.show -pub inline fn hide(self: Window) error{PlatformError}!void { +pub inline fn hide(self: Window) void { internal_debug.assertInitialized(); c.glfwHideWindow(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Brings the specified window to front and sets input focus. @@ -1064,15 +932,9 @@ pub inline fn hide(self: Window) error{PlatformError}!void { /// @thread_safety This function must only be called from the main thread. /// /// see also: window_focus, window_attention -pub inline fn focus(self: Window) error{ PlatformError, FeatureUnavailable }!void { +pub inline fn focus(self: Window) void { internal_debug.assertInitialized(); c.glfwFocusWindow(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - Error.FeatureUnavailable => |e| e, - else => unreachable, - }; } /// Requests user attention to the specified window. @@ -1082,7 +944,7 @@ pub inline fn focus(self: Window) error{ PlatformError, FeatureUnavailable }!voi /// /// Once the user has given attention, usually by focusing the window or application, the system will end the request automatically. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// macos: Attention is requested to the application as a whole, not the /// specific window. @@ -1092,14 +954,9 @@ pub inline fn focus(self: Window) error{ PlatformError, FeatureUnavailable }!voi /// see also: window_attention /// /// WARNING: on wayland it will return Error.FeatureUnimplemented -pub inline fn requestAttention(self: Window) error{ PlatformError, FeatureUnimplemented }!void { +pub inline fn requestAttention(self: Window) void { internal_debug.assertInitialized(); c.glfwRequestWindowAttention(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError, Error.FeatureUnimplemented => |e| e, - else => unreachable, - }; } /// Swaps the front and back buffers of the specified window. @@ -1116,21 +973,16 @@ pub inline fn requestAttention(self: Window) error{ PlatformError, FeatureUnimpl /// /// @param[in] window The window whose buffers to swap. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.NoWindowContext and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.NoWindowContext and glfw.Error.PlatformError. /// /// __EGL:__ The context of the specified window must be current on the calling thread. /// /// @thread_safety This function may be called from any thread. /// /// see also: buffer_swap, glfwSwapInterval -pub inline fn swapBuffers(self: Window) error{ NoWindowContext, PlatformError }!void { +pub inline fn swapBuffers(self: Window) void { internal_debug.assertInitialized(); c.glfwSwapBuffers(self.handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.NoWindowContext, Error.PlatformError => |e| e, - else => unreachable, - }; } /// Returns the monitor that the window uses for full screen mode. @@ -1139,18 +991,12 @@ pub inline fn swapBuffers(self: Window) error{ NoWindowContext, PlatformError }! /// /// @return The monitor, or null if the window is in windowed mode. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @thread_safety This function must only be called from the main thread. /// /// see also: window_monitor, glfw.Window.setMonitor pub inline fn getMonitor(self: Window) ?Monitor { internal_debug.assertInitialized(); if (c.glfwGetWindowMonitor(self.handle)) |monitor| return Monitor{ .handle = monitor }; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; return null; } @@ -1181,7 +1027,7 @@ pub inline fn getMonitor(self: Window) ?Monitor { /// @param[in] height The desired height, in screen coordinates, of the content area or video mode. /// @param[in] refreshRate The desired refresh rate, in Hz, of the video mode, or `glfw.dont_care`. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// The OpenGL or OpenGL ES context will not be destroyed or otherwise affected by any resizing or /// mode switching, although you may need to update your viewport if the framebuffer size has @@ -1196,7 +1042,7 @@ pub inline fn getMonitor(self: Window) ?Monitor { /// @thread_safety This function must only be called from the main thread. /// /// see also: window_monitor, window_full_screen, glfw.Window.getMonitor, glfw.Window.setSize -pub inline fn setMonitor(self: Window, monitor: ?Monitor, xpos: i32, ypos: i32, width: u32, height: u32, refresh_rate: ?u32) error{PlatformError}!void { +pub inline fn setMonitor(self: Window, monitor: ?Monitor, xpos: i32, ypos: i32, width: u32, height: u32, refresh_rate: ?u32) void { internal_debug.assertInitialized(); c.glfwSetWindowMonitor( self.handle, @@ -1207,11 +1053,6 @@ pub inline fn setMonitor(self: Window, monitor: ?Monitor, xpos: i32, ypos: i32, @intCast(c_int, height), if (refresh_rate) |refresh_rate_unwrapped| @intCast(c_int, refresh_rate_unwrapped) else glfw.dont_care, ); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Window attributes @@ -1253,7 +1094,8 @@ pub const Attrib = enum(c_int) { /// @param[in] attrib The window attribute (see window_attribs) whose value to return. /// @return The value of the attribute, or zero if an error occurred. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// Additionally returns a zero value in the event of an error. /// /// Framebuffer related hints are not window attributes. See window_attribs_fb for more information. /// @@ -1264,18 +1106,9 @@ pub const Attrib = enum(c_int) { /// @thread_safety This function must only be called from the main thread. /// /// see also: window_attribs, glfw.Window.setAttrib -pub inline fn getAttrib(self: Window, attrib: Attrib) error{PlatformError}!i32 { +pub inline fn getAttrib(self: Window, attrib: Attrib) i32 { internal_debug.assertInitialized(); - const v = c.glfwGetWindowAttrib(self.handle, @enumToInt(attrib)); - if (v != 0) return v; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; - // this is not unreachable as `0` is a valid value - return v; + return c.glfwGetWindowAttrib(self.handle, @enumToInt(attrib)); } /// Sets an attribute of the specified window. @@ -1293,7 +1126,7 @@ pub inline fn getAttrib(self: Window, attrib: Attrib) error{PlatformError}!i32 { /// /// @param[in] attrib A supported window attribute. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum, glfw.Error.InvalidValue and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidEnum, glfw.Error.InvalidValue and glfw.Error.PlatformError. /// /// Calling glfw.Window.getAttrib will always return the latest /// value, even if that value is ignored by the current mode of the window. @@ -1302,7 +1135,7 @@ pub inline fn getAttrib(self: Window, attrib: Attrib) error{PlatformError}!i32 { /// /// see also: window_attribs, glfw.Window.getAttrib /// -pub inline fn setAttrib(self: Window, attrib: Attrib, value: bool) error{PlatformError}!void { +pub inline fn setAttrib(self: Window, attrib: Attrib, value: bool) void { internal_debug.assertInitialized(); std.debug.assert(switch (attrib) { .decorated, @@ -1316,13 +1149,6 @@ pub inline fn setAttrib(self: Window, attrib: Attrib, value: bool) error{Platfor else => false, }); c.glfwSetWindowAttrib(self.handle, @enumToInt(attrib), if (value) c.GLFW_TRUE else c.GLFW_FALSE); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.InvalidValue => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Sets the user pointer of the specified window. @@ -1336,10 +1162,6 @@ pub inline fn setAttrib(self: Window, attrib: Attrib, value: bool) error{Platfor pub inline fn setUserPointer(self: Window, pointer: ?*anyopaque) void { internal_debug.assertInitialized(); c.glfwSetWindowUserPointer(self.handle, pointer); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Returns the user pointer of the specified window. @@ -1353,10 +1175,6 @@ pub inline fn setUserPointer(self: Window, pointer: ?*anyopaque) void { pub inline fn getUserPointer(self: Window, comptime T: type) ?*T { internal_debug.assertInitialized(); if (c.glfwGetWindowUserPointer(self.handle)) |user_pointer| return @ptrCast(?*T, @alignCast(@alignOf(T), user_pointer)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; return null; } @@ -1398,11 +1216,6 @@ pub inline fn setPosCallback(self: Window, comptime callback: ?fn (window: Windo } else { if (c.glfwSetWindowPosCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the size callback for the specified window. @@ -1436,11 +1249,6 @@ pub inline fn setSizeCallback(self: Window, comptime callback: ?fn (window: Wind } else { if (c.glfwSetWindowSizeCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the close callback for the specified window. @@ -1480,11 +1288,6 @@ pub inline fn setCloseCallback(self: Window, comptime callback: ?fn (window: Win } else { if (c.glfwSetWindowCloseCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the refresh callback for the specified window. @@ -1522,11 +1325,6 @@ pub inline fn setRefreshCallback(self: Window, comptime callback: ?fn (window: W } else { if (c.glfwSetWindowRefreshCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the focus callback for the specified window. @@ -1566,11 +1364,6 @@ pub inline fn setFocusCallback(self: Window, comptime callback: ?fn (window: Win } else { if (c.glfwSetWindowFocusCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the iconify callback for the specified window. @@ -1605,11 +1398,6 @@ pub inline fn setIconifyCallback(self: Window, comptime callback: ?fn (window: W } else { if (c.glfwSetWindowIconifyCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the maximize callback for the specified window. @@ -1645,11 +1433,6 @@ pub inline fn setMaximizeCallback(self: Window, comptime callback: ?fn (window: } else { if (c.glfwSetWindowMaximizeCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the framebuffer resize callback for the specified window. @@ -1686,11 +1469,6 @@ pub inline fn setFramebufferSizeCallback(self: Window, comptime callback: ?fn (w } else { if (c.glfwSetFramebufferSizeCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the window content scale callback for the specified window. @@ -1727,11 +1505,6 @@ pub inline fn setContentScaleCallback(self: Window, comptime callback: ?fn (wind } else { if (c.glfwSetWindowContentScaleCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } pub const InputMode = enum(c_int) { @@ -1757,7 +1530,7 @@ pub const InputModeCursor = enum(c_int) { }; /// Sets the input mode of the cursor, whether it should behave normally, be hidden, or grabbed. -pub inline fn setInputModeCursor(self: Window, value: InputModeCursor) error{ PlatformError, FeatureUnavailable }!void { +pub inline fn setInputModeCursor(self: Window, value: InputModeCursor) void { return self.setInputMode(InputMode.cursor, value); } @@ -1771,7 +1544,7 @@ pub inline fn getInputModeCursor(self: Window) InputModeCursor { /// /// This is useful when you are only interested in whether keys have been pressed but not when or /// in which order. -pub inline fn setInputModeStickyKeys(self: Window, enabled: bool) error{ PlatformError, FeatureUnavailable }!void { +pub inline fn setInputModeStickyKeys(self: Window, enabled: bool) void { return self.setInputMode(InputMode.sticky_keys, enabled); } @@ -1786,7 +1559,7 @@ pub inline fn getInputModeStickyKeys(self: Window) bool { /// /// This is useful when you are only interested in whether buttons have been pressed but not when /// or in which order. -pub inline fn setInputModeStickyMouseButtons(self: Window, enabled: bool) error{ PlatformError, FeatureUnavailable }!void { +pub inline fn setInputModeStickyMouseButtons(self: Window, enabled: bool) void { return self.setInputMode(InputMode.sticky_mouse_buttons, enabled); } @@ -1798,7 +1571,7 @@ pub inline fn getInputModeStickyMouseButtons(self: Window) bool { /// Sets the input mode of locking key modifiers, if enabled callbacks that receive modifier bits /// will also have the glfw.mod.caps_lock bit set when the event was generated with Caps Lock on, /// and the glfw.mod.num_lock bit when Num Lock was on. -pub inline fn setInputModeLockKeyMods(self: Window, enabled: bool) error{ PlatformError, FeatureUnavailable }!void { +pub inline fn setInputModeLockKeyMods(self: Window, enabled: bool) void { return self.setInputMode(InputMode.lock_key_mods, enabled); } @@ -1813,7 +1586,7 @@ pub inline fn getInputModeLockKeyMods(self: Window) bool { /// /// If raw motion is not supported, attempting to set this will emit glfw.Error.FeatureUnavailable. Call /// glfw.rawMouseMotionSupported to check for support. -pub inline fn setInputModeRawMouseMotion(self: Window, enabled: bool) error{ PlatformError, FeatureUnavailable }!void { +pub inline fn setInputModeRawMouseMotion(self: Window, enabled: bool) void { return self.setInputMode(InputMode.raw_mouse_motion, enabled); } @@ -1845,13 +1618,6 @@ pub inline fn getInputModeRawMouseMotion(self: Window) bool { pub inline fn getInputMode(self: Window, mode: InputMode) i32 { internal_debug.assertInitialized(); const value = c.glfwGetInputMode(self.handle, @enumToInt(mode)); - - getError() catch |err| return switch (err) { - Error.InvalidEnum => unreachable, - Error.NotInitialized => unreachable, - else => unreachable, - }; - return @intCast(i32, value); } @@ -1872,7 +1638,7 @@ pub inline fn getInputMode(self: Window, mode: InputMode) i32 { /// @thread_safety This function must only be called from the main thread. /// /// see also: glfw.Window.getInputMode -pub inline fn setInputMode(self: Window, mode: InputMode, value: anytype) error{ PlatformError, FeatureUnavailable }!void { +pub inline fn setInputMode(self: Window, mode: InputMode, value: anytype) void { internal_debug.assertInitialized(); const T = @TypeOf(value); std.debug.assert(switch (mode) { @@ -1893,13 +1659,6 @@ pub inline fn setInputMode(self: Window, mode: InputMode, value: anytype) error{ else => @boolToInt(value), }; c.glfwSetInputMode(self.handle, @enumToInt(mode), int_value); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.PlatformError => |e| e, - Error.FeatureUnavailable => |e| e, - else => unreachable, - }; } /// Returns the last reported press state of a keyboard key for the specified window. @@ -1923,19 +1682,12 @@ pub inline fn setInputMode(self: Window, mode: InputMode, value: anytype) error{ /// @param[in] key The desired keyboard key (see keys). `glfw.key.unknown` is not a valid key for /// this function. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.InvalidEnum. -/// /// @thread_safety This function must only be called from the main thread. /// /// see also: input_key pub inline fn getKey(self: Window, key: Key) Action { internal_debug.assertInitialized(); const state = c.glfwGetKey(self.handle, @enumToInt(key)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - else => unreachable, - }; return @intToEnum(Action, state); } @@ -1950,7 +1702,7 @@ pub inline fn getKey(self: Window, key: Key) Action { /// @param[in] button The desired mouse button. /// @return One of `true` (if pressed) or `false` (if released) /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.InvalidEnum. +/// Possible errors include glfw.Error.InvalidEnum. /// /// @thread_safety This function must only be called from the main thread. /// @@ -1958,11 +1710,6 @@ pub inline fn getKey(self: Window, key: Key) Action { pub inline fn getMouseButton(self: Window, button: MouseButton) Action { internal_debug.assertInitialized(); const state = c.glfwGetMouseButton(self.handle, @enumToInt(button)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - else => unreachable, - }; return @intToEnum(Action, state); } @@ -1991,20 +1738,16 @@ pub const CursorPos = struct { /// @param[out] ypos Where to store the cursor y-coordinate, relative to the to top edge of the /// content area, or null. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. +/// Additionally returns a zero value in the event of an error. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: cursor_pos, glfw.Window.setCursorPos -pub inline fn getCursorPos(self: Window) error{PlatformError}!CursorPos { +pub inline fn getCursorPos(self: Window) CursorPos { internal_debug.assertInitialized(); var pos: CursorPos = undefined; c.glfwGetCursorPos(self.handle, &pos.xpos, &pos.ypos); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return pos; } @@ -2025,7 +1768,7 @@ pub inline fn getCursorPos(self: Window) error{PlatformError}!CursorPos { /// @param[in] xpos The desired x-coordinate, relative to the left edge of the content area. /// @param[in] ypos The desired y-coordinate, relative to the top edge of the content area. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// wayland: This function will only work when the cursor mode is `glfw.cursor_disabled`, otherwise /// it will do nothing. @@ -2033,14 +1776,9 @@ pub inline fn getCursorPos(self: Window) error{PlatformError}!CursorPos { /// @thread_safety This function must only be called from the main thread. /// /// see also: cursor_pos, glfw.Window.getCursorPos -pub inline fn setCursorPos(self: Window, xpos: f64, ypos: f64) error{PlatformError}!void { +pub inline fn setCursorPos(self: Window, xpos: f64, ypos: f64) void { internal_debug.assertInitialized(); c.glfwSetCursorPos(self.handle, xpos, ypos); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Sets the cursor for the window. @@ -2053,19 +1791,14 @@ pub inline fn setCursorPos(self: Window, xpos: f64, ypos: f64) error{PlatformErr /// /// @param[in] cursor The cursor to set, or null to switch back to the default arrow cursor. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: cursor_object -pub inline fn setCursor(self: Window, cursor: ?Cursor) error{PlatformError}!void { +pub inline fn setCursor(self: Window, cursor: ?Cursor) void { internal_debug.assertInitialized(); c.glfwSetCursor(self.handle, if (cursor) |cs| cs.ptr else null); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Sets the key callback. @@ -2122,11 +1855,6 @@ pub inline fn setKeyCallback(self: Window, comptime callback: ?fn (window: Windo } else { if (c.glfwSetKeyCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the Unicode character callback. @@ -2170,11 +1898,6 @@ pub inline fn setCharCallback(self: Window, comptime callback: ?fn (window: Wind } else { if (c.glfwSetCharCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the mouse button callback. @@ -2218,11 +1941,6 @@ pub inline fn setMouseButtonCallback(self: Window, comptime callback: ?fn (windo } else { if (c.glfwSetMouseButtonCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the cursor position callback. @@ -2260,11 +1978,6 @@ pub inline fn setCursorPosCallback(self: Window, comptime callback: ?fn (window: } else { if (c.glfwSetCursorPosCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the cursor enter/leave callback. @@ -2298,11 +2011,6 @@ pub inline fn setCursorEnterCallback(self: Window, comptime callback: ?fn (windo } else { if (c.glfwSetCursorEnterCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the scroll callback. @@ -2341,11 +2049,6 @@ pub inline fn setScrollCallback(self: Window, comptime callback: ?fn (window: Wi } else { if (c.glfwSetScrollCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// Sets the path drop callback. @@ -2366,8 +2069,6 @@ pub inline fn setScrollCallback(self: Window, comptime callback: ?fn (window: Wi /// @callback_pointer_lifetime The path array and its strings are valid until the callback function /// returns. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// wayland: File drop is currently unimplemented. /// /// @thread_safety This function must only be called from the main thread. @@ -2390,11 +2091,6 @@ pub inline fn setDropCallback(self: Window, comptime callback: ?fn (window: Wind } else { if (c.glfwSetDropCallback(self.handle, null) != null) return; } - - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; } /// For testing purposes only; see glfw.Window.Hints and glfw.Window.create for the public API. @@ -2410,7 +2106,7 @@ pub inline fn setDropCallback(self: Window, comptime callback: ?fn (window: Wind /// Some hints are platform specific. These may be set on any platform but they will only affect /// their specific platform. Other platforms will ignore them. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.InvalidEnum. +/// Possible errors include glfw.Error.InvalidEnum. /// /// @pointer_lifetime in the event that value is of a str type, the specified string is copied before this function returns. /// @@ -2457,22 +2153,25 @@ inline fn hint(h: Hint, value: anytype) void { @compileError("expected a int, bool, enum, array, or pointer, got " ++ @typeName(value_type)); }, } - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - else => unreachable, - }; } test "defaultHints" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); defaultHints(); } test "hint comptime int" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); hint(.focused, 1); @@ -2480,7 +2179,11 @@ test "hint comptime int" { } test "hint int" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); var focused: i32 = 1; @@ -2490,7 +2193,11 @@ test "hint int" { } test "hint bool" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); hint(.focused, true); @@ -2498,7 +2205,11 @@ test "hint bool" { } test "hint enum(u1)" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const MyEnum = enum(u1) { @@ -2511,7 +2222,11 @@ test "hint enum(u1)" { } test "hint enum(i32)" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const MyEnum = enum(i32) { @@ -2524,7 +2239,11 @@ test "hint enum(i32)" { } test "hint array str" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const str_arr = [_]u8{ 'm', 'y', 'c', 'l', 'a', 's', 's' }; @@ -2534,64 +2253,76 @@ test "hint array str" { } test "hint pointer str" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); hint(.x11_class_name, "myclass"); } test "createWindow" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); } test "setShouldClose" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; window.setShouldClose(true); defer window.destroy(); } test "setTitle" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - try window.setTitle("Updated title!"); + window.setTitle("Updated title!"); } test "setIcon" { const allocator = testing.allocator; - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -2609,293 +2340,331 @@ test "setIcon" { icon.pixels[(x * y * 4) + 3] = 255; // alpha } } - window.setIcon(allocator, &[_]Image{icon}) catch |err| std.debug.print("can't set window icon, wayland maybe? error={}\n", .{err}); + try window.setIcon(allocator, &[_]Image{icon}); icon.deinit(allocator); // glfw copies it. } test "getPos" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.getPos() catch |err| std.debug.print("can't get window position, wayland maybe? error={}\n", .{err}); + _ = window.getPos(); } test "setPos" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.setPos(.{ .x = 0, .y = 0 }) catch |err| std.debug.print("can't set window position, wayland maybe? error={}\n", .{err}); + _ = window.setPos(.{ .x = 0, .y = 0 }); } test "getSize" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = try window.getSize(); + _ = window.getSize(); } test "setSize" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = try window.setSize(.{ .width = 640, .height = 480 }); + _ = window.setSize(.{ .width = 640, .height = 480 }); } test "setSizeLimits" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - try window.setSizeLimits( + window.setSizeLimits( .{ .width = 720, .height = 480 }, .{ .width = 1080, .height = 1920 }, ); } test "setAspectRatio" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - window.setAspectRatio(4, 3) catch |err| std.debug.print("can't modify aspect ratio, wayland maybe? error={}\n", .{err}); + window.setAspectRatio(4, 3); } test "getFramebufferSize" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = try window.getFramebufferSize(); + _ = window.getFramebufferSize(); } test "getFrameSize" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = try window.getFrameSize(); + _ = window.getFrameSize(); } test "getContentScale" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = try window.getContentScale(); + _ = window.getContentScale(); } test "getOpacity" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = try window.getOpacity(); + _ = window.getOpacity(); } test "iconify" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.iconify() catch |err| std.debug.print("can't iconify window, wayland maybe? error={}\n", .{err}); + _ = window.iconify(); } test "restore" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.restore() catch |err| std.debug.print("can't restore window, not supported by OS maybe? error={}\n", .{err}); + _ = window.restore(); } test "maximize" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.maximize() catch |err| std.debug.print("can't maximize window, not supported by OS maybe? error={}\n", .{err}); + _ = window.maximize(); } test "show" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.show() catch |err| std.debug.print("can't show window, not supported by OS maybe? error={}\n", .{err}); + _ = window.show(); } test "hide" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.hide() catch |err| std.debug.print("can't hide window, not supported by OS maybe? error={}\n", .{err}); + _ = window.hide(); } test "focus" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.focus() catch |err| std.debug.print("can't focus window, wayland maybe? error={}\n", .{err}); + _ = window.focus(); } test "requestAttention" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.requestAttention() catch |err| std.debug.print("can't request attention for window, not supported by OS maybe? error={}\n", .{err}); + _ = window.requestAttention(); } test "swapBuffers" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.swapBuffers() catch |err| std.debug.print("can't swap buffers, wayland maybe? error={}\n", .{err}); + _ = window.swapBuffers(); } test "getMonitor" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -2903,59 +2672,67 @@ test "getMonitor" { } test "setMonitor" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - window.setMonitor(null, 10, 10, 640, 480, 60) catch |err| std.debug.print("can't set monitor, not supported by OS maybe? error={}\n", .{err}); + window.setMonitor(null, 10, 10, 640, 480, 60); } test "getAttrib" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.getAttrib(.focused) catch |err| std.debug.print("can't check if window is focused, not supported by OS maybe? error={}\n", .{err}); + _ = window.getAttrib(.focused); } test "setAttrib" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - window.setAttrib(.decorated, false) catch |err| std.debug.print("can't remove window decorations, not supported by OS maybe? error={}\n", .{err}); + window.setAttrib(.decorated, false); } test "setUserPointer" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -2966,14 +2743,16 @@ test "setUserPointer" { } test "getUserPointer" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -2986,14 +2765,16 @@ test "getUserPointer" { } test "setPosCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3007,14 +2788,16 @@ test "setPosCallback" { } test "setSizeCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3028,14 +2811,16 @@ test "setSizeCallback" { } test "setCloseCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3047,14 +2832,16 @@ test "setCloseCallback" { } test "setRefreshCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3066,14 +2853,16 @@ test "setRefreshCallback" { } test "setFocusCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3086,14 +2875,16 @@ test "setFocusCallback" { } test "setIconifyCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3106,14 +2897,16 @@ test "setIconifyCallback" { } test "setMaximizeCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3126,14 +2919,16 @@ test "setMaximizeCallback" { } test "setFramebufferSizeCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3147,14 +2942,16 @@ test "setFramebufferSizeCallback" { } test "setContentScaleCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3168,14 +2965,16 @@ test "setContentScaleCallback" { } test "setDropCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3188,14 +2987,16 @@ test "setDropCallback" { } test "getInputModeCursor" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3203,29 +3004,33 @@ test "getInputModeCursor" { } test "setInputModeCursor" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - window.setInputModeCursor(.hidden) catch |err| std.debug.print("failed to set input mode, not supported? error={}\n", .{err}); + window.setInputModeCursor(.hidden); } test "getInputModeStickyKeys" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3233,29 +3038,33 @@ test "getInputModeStickyKeys" { } test "setInputModeStickyKeys" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - window.setInputModeStickyKeys(false) catch |err| std.debug.print("failed to set input mode, not supported? error={}\n", .{err}); + window.setInputModeStickyKeys(false); } test "getInputModeStickyMouseButtons" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3263,29 +3072,33 @@ test "getInputModeStickyMouseButtons" { } test "setInputModeStickyMouseButtons" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - window.setInputModeStickyMouseButtons(false) catch |err| std.debug.print("failed to set input mode, not supported? error={}\n", .{err}); + window.setInputModeStickyMouseButtons(false); } test "getInputModeLockKeyMods" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3293,29 +3106,33 @@ test "getInputModeLockKeyMods" { } test "setInputModeLockKeyMods" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - window.setInputModeLockKeyMods(false) catch |err| std.debug.print("failed to set input mode, not supported? error={}\n", .{err}); + window.setInputModeLockKeyMods(false); } test "getInputModeRawMouseMotion" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3323,29 +3140,33 @@ test "getInputModeRawMouseMotion" { } test "setInputModeRawMouseMotion" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - window.setInputModeRawMouseMotion(false) catch |err| std.debug.print("failed to set input mode, not supported? error={}\n", .{err}); + window.setInputModeRawMouseMotion(false); } test "getInputMode" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3353,33 +3174,37 @@ test "getInputMode" { } test "setInputMode" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); // Boolean values. - window.setInputMode(glfw.Window.InputMode.sticky_mouse_buttons, true) catch |err| std.debug.print("failed to set input mode, not supported? error={}\n", .{err}); + window.setInputMode(glfw.Window.InputMode.sticky_mouse_buttons, true); // Integer values. - window.setInputMode(glfw.Window.InputMode.cursor, glfw.Window.InputModeCursor.hidden) catch |err| std.debug.print("failed to set input mode, not supported? error={}\n", .{err}); + window.setInputMode(glfw.Window.InputMode.cursor, glfw.Window.InputModeCursor.hidden); } test "getKey" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3387,14 +3212,16 @@ test "getKey" { } test "getMouseButton" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3402,65 +3229,71 @@ test "getMouseButton" { } test "getCursorPos" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - _ = window.getCursorPos() catch |err| std.debug.print("failed to get cursor pos, not supported? error={}\n", .{err}); + _ = window.getCursorPos(); } test "setCursorPos" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - window.setCursorPos(0, 0) catch |err| std.debug.print("failed to set cursor pos, not supported? error={}\n", .{err}); + window.setCursorPos(0, 0); } test "setCursor" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); - const cursor = glfw.Cursor.createStandard(.ibeam) catch |err| { - std.debug.print("failed to create cursor, custom cursors not supported? error={}\n", .{err}); - return; - }; - defer cursor.destroy(); - - window.setCursor(cursor) catch |err| std.debug.print("failed to set cursor, custom cursors not supported? error={}\n", .{err}); + const cursor = glfw.Cursor.createStandard(.ibeam); + if (cursor) |cur| { + window.setCursor(cur); + defer cur.destroy(); + } } test "setKeyCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3476,14 +3309,16 @@ test "setKeyCallback" { } test "setCharCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3496,14 +3331,16 @@ test "setCharCallback" { } test "setMouseButtonCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3518,14 +3355,16 @@ test "setMouseButtonCallback" { } test "setCursorPosCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3539,14 +3378,16 @@ test "setCursorPosCallback" { } test "setCursorEnterCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3559,14 +3400,16 @@ test "setCursorEnterCallback" { } test "setScrollCallback" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -3580,24 +3423,24 @@ test "setScrollCallback" { } test "hint-attribute default value parity" { - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); testing_ignore_window_hints_struct = true; - const window_a = Window.create(640, 480, "Hello, Zig!", null, null, undefined) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window_a: {}\n", .{err}); - return; + const window_a = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window_a: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window_a.destroy(); testing_ignore_window_hints_struct = false; - const window_b = Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window_b: {}\n", .{err}); - return; + const window_b = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window_b: {?s}", .{glfw.getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window_b.destroy(); @@ -3626,14 +3469,8 @@ test "hint-attribute default value parity" { .opengl_forward_compat, .opengl_profile, => { - const expected = window_a.getAttrib(attrib_tag) catch |err| { - std.debug.print("Failed to get attribute '{}' value from window_a with error '{}'.\n", .{ attrib_tag, err }); - return; - }; - const actual = window_b.getAttrib(attrib_tag) catch |err| { - std.debug.print("Failed to get attribute '{}' value from window_b with error '{}'.\n", .{ attrib_tag, err }); - return; - }; + const expected = window_a.getAttrib(attrib_tag); + const actual = window_b.getAttrib(attrib_tag); testing.expectEqual(expected, actual) catch |err| { std.debug.print("On attribute '{}'.\n", .{hint_tag}); diff --git a/libs/glfw/src/clipboard.zig b/libs/glfw/src/clipboard.zig index 9c7c0560..6c2866e1 100644 --- a/libs/glfw/src/clipboard.zig +++ b/libs/glfw/src/clipboard.zig @@ -12,21 +12,16 @@ const internal_debug = @import("internal_debug.zig"); /// /// @param[in] string A UTF-8 encoded string. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// @pointer_lifetime The specified string is copied before this function returns. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: clipboard, glfwGetClipboardString -pub inline fn setClipboardString(value: [*:0]const u8) error{PlatformError}!void { +pub inline fn setClipboardString(value: [*:0]const u8) void { internal_debug.assertInitialized(); c.glfwSetClipboardString(null, value); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Returns the contents of the clipboard as a string. @@ -37,7 +32,8 @@ pub inline fn setClipboardString(value: [*:0]const u8) error{PlatformError}!void /// /// @return The contents of the clipboard as a UTF-8 encoded string. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.FormatUnavailable and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.FormatUnavailable and glfw.Error.PlatformError. +/// null is returned in the event of an error. /// /// @pointer_lifetime The returned string is allocated and freed by GLFW. You should not free it /// yourself. It is valid until the next call to glfw.getClipboardString or glfw.setClipboardString @@ -46,30 +42,32 @@ pub inline fn setClipboardString(value: [*:0]const u8) error{PlatformError}!void /// @thread_safety This function must only be called from the main thread. /// /// see also: clipboard, glfwSetClipboardString -pub inline fn getClipboardString() error{ FormatUnavailable, PlatformError }![:0]const u8 { +pub inline fn getClipboardString() ?[:0]const u8 { internal_debug.assertInitialized(); if (c.glfwGetClipboardString(null)) |c_str| return std.mem.span(@ptrCast([*:0]const u8, c_str)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.FormatUnavailable, Error.PlatformError => |e| e, - else => unreachable, - }; - // `glfwGetClipboardString` returns `null` only for errors - unreachable; + return null; } test "setClipboardString" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - try glfw.setClipboardString("hello mach"); + glfw.setClipboardString("hello mach"); } test "getClipboardString" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - _ = glfw.getClipboardString() catch |err| std.debug.print("can't get clipboard, not supported by OS? error={}\n", .{err}); + _ = glfw.getClipboardString(); } diff --git a/libs/glfw/src/errors.zig b/libs/glfw/src/errors.zig index 2bdcd35e..cc8447ab 100644 --- a/libs/glfw/src/errors.zig +++ b/libs/glfw/src/errors.zig @@ -190,6 +190,13 @@ pub inline fn getError() Error!void { return convertError(c.glfwGetError(null)); } +/// Returns and clears the last error for the calling thread. If no error is present, this function +/// panics. +pub inline fn mustGetError() Error { + try getError(); + @panic("glfw: mustGetError called but no error is present"); +} + /// Returns and clears the last error description for the calling thread. /// /// This function returns a UTF-8 encoded human-readable description of the last error that occured diff --git a/libs/glfw/src/key.zig b/libs/glfw/src/key.zig index d274378b..c15dab2f 100644 --- a/libs/glfw/src/key.zig +++ b/libs/glfw/src/key.zig @@ -204,7 +204,8 @@ pub const Key = enum(c_int) { /// @param[in] scancode The scancode of the key to query. /// @return The UTF-8 encoded, layout-specific name of the key, or null. /// - /// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. + /// Possible errors include glfw.Error.PlatformError. + /// Also returns null in the event of an error. /// /// The contents of the returned string may change when a keyboard layout change event is received. /// @@ -214,14 +215,9 @@ pub const Key = enum(c_int) { /// @thread_safety This function must only be called from the main thread. /// /// see also: input_key_name - pub inline fn getName(self: Key, scancode: i32) error{PlatformError}!?[:0]const u8 { + pub inline fn getName(self: Key, scancode: i32) ?[:0]const u8 { internal_debug.assertInitialized(); const name_opt = cc.glfwGetKeyName(@enumToInt(self), @intCast(c_int, scancode)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; return if (name_opt) |name| std.mem.span(@ptrCast([*:0]const u8, name)) else @@ -237,36 +233,36 @@ pub const Key = enum(c_int) { /// @param[in] key Any named key (see keys). /// @return The platform-specific scancode for the key. /// - /// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum and glfw.Error.PlatformError. + /// Possible errors include glfw.Error.InvalidEnum and glfw.Error.PlatformError. + /// Additionally returns -1 in the event of an error. /// /// @thread_safety This function may be called from any thread. - pub inline fn getScancode(self: Key) error{PlatformError}!i32 { + pub inline fn getScancode(self: Key) i32 { internal_debug.assertInitialized(); - const scancode = cc.glfwGetKeyScancode(@enumToInt(self)); - if (scancode != -1) return scancode; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidEnum => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; - // `glfwGetKeyScancode` returns `-1` only for errors - unreachable; + return cc.glfwGetKeyScancode(@enumToInt(self)); } }; test "getName" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - _ = glfw.Key.a.getName(0) catch |err| std.debug.print("failed to get key name, not supported? error={}\n", .{err}); + _ = glfw.Key.a.getName(0); } test "getScancode" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - _ = glfw.Key.a.getScancode() catch |err| std.debug.print("failed to get key scancode, not supported? error={}\n", .{err}); + _ = glfw.Key.a.getScancode(); } diff --git a/libs/glfw/src/main.zig b/libs/glfw/src/main.zig index b242ed9e..b6c14767 100644 --- a/libs/glfw/src/main.zig +++ b/libs/glfw/src/main.zig @@ -12,7 +12,9 @@ pub const dont_care = c.GLFW_DONT_CARE; /// may be useful. pub const errors = @import("errors.zig"); -const getError = errors.getError; +pub const getError = errors.getError; +pub const mustGetError = errors.mustGetError; +pub const getErrorString = errors.getErrorString; pub const setErrorCallback = errors.setErrorCallback; pub const Error = errors.Error; @@ -81,8 +83,11 @@ pub fn assumeInitialized() void { /// current environment if that category is still "C". This is because the "C" locale breaks /// Unicode text input. /// +/// Possible errors include glfw.Error.PlatformUnavailable, glfw.Error.PlatformError. +/// Returns a bool indicating success. +/// /// @thread_safety This function must only be called from the main thread. -pub inline fn init(hints: InitHints) error{ PlatformUnavailable, PlatformError }!void { +pub inline fn init(hints: InitHints) bool { internal_debug.toggleInitialized(); internal_debug.assertInitialized(); errdefer { @@ -100,12 +105,7 @@ pub inline fn init(hints: InitHints) error{ PlatformUnavailable, PlatformError } } } - if (c.glfwInit() == c.GLFW_TRUE) return; - getError() catch |err| return switch (err) { - Error.PlatformUnavailable => |e| e, - Error.PlatformError => |e| e, - else => unreachable, - }; + return c.glfwInit() == c.GLFW_TRUE; } // TODO: implement custom allocator support @@ -161,10 +161,6 @@ pub inline fn terminate() void { internal_debug.assertInitialized(); internal_debug.toggleInitialized(); c.glfwTerminate(); - getError() catch |err| return switch (err) { - Error.PlatformError => std.log.err("mach/glfw: Failed to terminate GLFW: {}", .{err}), - else => unreachable, - }; } /// Initialization hints for passing into glfw.init @@ -280,11 +276,6 @@ fn initHint(hint: InitHint, value: anytype) void { .Bool => c.glfwInitHint(@enumToInt(hint), @intCast(c_int, @boolToInt(value))), else => @compileError("expected a int or bool, got " ++ @typeName(@TypeOf(value))), } - getError() catch |err| return switch (err) { - Error.InvalidEnum => unreachable, - Error.InvalidValue => unreachable, - else => unreachable, - }; } /// Returns a string describing the compile-time configuration. @@ -320,12 +311,7 @@ pub inline fn getVersionString() [:0]const u8 { /// thread_safety: This function may be called from any thread. pub fn getPlatform() PlatformType { internal_debug.assertInitialized(); - const platform = @intToEnum(PlatformType, c.glfwGetPlatform()); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; - return platform; + return @intToEnum(PlatformType, c.glfwGetPlatform()); } /// Returns whether the library includes support for the specified platform. @@ -339,12 +325,7 @@ pub fn getPlatform() PlatformType { /// thread_safety: This function may be called from any thread. pub fn platformSupported(platform: PlatformType) bool { internal_debug.assertInitialized(); - const is_supported = c.glfwPlatformSupported(@enumToInt(platform)); - getError() catch |err| return switch (err) { - Error.InvalidEnum => unreachable, - else => unreachable, - }; - return is_supported == c.GLFW_TRUE; + return c.glfwPlatformSupported(@enumToInt(platform)) == c.GLFW_TRUE; } /// Processes all pending events. @@ -365,21 +346,16 @@ pub fn platformSupported(platform: PlatformType) bool { /// /// Event processing is not required for joystick input to work. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// @reentrancy This function must not be called from a callback. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: events, glfw.waitEvents, glfw.waitEventsTimeout -pub inline fn pollEvents() error{PlatformError}!void { +pub inline fn pollEvents() void { internal_debug.assertInitialized(); c.glfwPollEvents(); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Waits until events are queued and processes them. @@ -405,21 +381,16 @@ pub inline fn pollEvents() error{PlatformError}!void { /// /// Event processing is not required for joystick input to work. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// @reentrancy This function must not be called from a callback. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: events, glfw.pollEvents, glfw.waitEventsTimeout -pub inline fn waitEvents() error{PlatformError}!void { +pub inline fn waitEvents() void { internal_debug.assertInitialized(); c.glfwWaitEvents(); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Waits with timeout until events are queued and processes them. @@ -449,25 +420,19 @@ pub inline fn waitEvents() error{PlatformError}!void { /// /// @param[in] timeout The maximum amount of time, in seconds, to wait. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidValue and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.InvalidValue and glfw.Error.PlatformError. /// /// @reentrancy This function must not be called from a callback. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: events, glfw.pollEvents, glfw.waitEvents -pub inline fn waitEventsTimeout(timeout: f64) error{PlatformError}!void { +pub inline fn waitEventsTimeout(timeout: f64) void { internal_debug.assertInitialized(); std.debug.assert(!std.math.isNan(timeout)); std.debug.assert(timeout >= 0); std.debug.assert(timeout <= std.math.f64_max); c.glfwWaitEventsTimeout(timeout); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidValue => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Posts an empty event to the event queue. @@ -475,19 +440,14 @@ pub inline fn waitEventsTimeout(timeout: f64) error{PlatformError}!void { /// This function posts an empty event from the current thread to the event queue, causing /// glfw.waitEvents or glfw.waitEventsTimeout to return. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.PlatformError. /// /// @thread_safety This function may be called from any thread. /// /// see also: events, glfw.waitEvents, glfw.waitEventsTimeout -pub inline fn postEmptyEvent() error{PlatformError}!void { +pub inline fn postEmptyEvent() void { internal_debug.assertInitialized(); c.glfwPostEmptyEvent(); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Returns whether raw mouse motion is supported. @@ -509,23 +469,20 @@ pub inline fn postEmptyEvent() error{PlatformError}!void { /// see also: raw_mouse_motion, glfw.setInputMode pub inline fn rawMouseMotionSupported() bool { internal_debug.assertInitialized(); - const supported = c.glfwRawMouseMotionSupported(); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; - return supported == c.GLFW_TRUE; + return c.glfwRawMouseMotionSupported() == c.GLFW_TRUE; } pub fn basicTest() !void { - try init(.{}); + defer getError() catch {}; // clear any error we generate + if (!init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{getErrorString()}); + std.process.exit(1); + } defer terminate(); - const window = Window.create(640, 480, "GLFW example", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{getErrorString()}); + std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows }; defer window.destroy(); @@ -545,34 +502,54 @@ test "getVersionString" { } test "pollEvents" { - try init(.{ .cocoa_chdir_resources = true }); + init(.{ .cocoa_chdir_resources = true }); + if (getErrorString()) |err| { + std.log.err("failed to initialize GLFW: {?s}", .{err}); + std.process.exit(1); + } defer terminate(); } test "pollEvents" { - try init(.{}); + defer getError() catch {}; // clear any error we generate + if (!init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{getErrorString()}); + std.process.exit(1); + } defer terminate(); - try pollEvents(); + pollEvents(); } test "waitEventsTimeout" { - try init(.{}); + defer getError() catch {}; // clear any error we generate + if (!init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{getErrorString()}); + std.process.exit(1); + } defer terminate(); - try waitEventsTimeout(0.25); + waitEventsTimeout(0.25); } test "postEmptyEvent_and_waitEvents" { - try init(.{}); + defer getError() catch {}; // clear any error we generate + if (!init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{getErrorString()}); + std.process.exit(1); + } defer terminate(); - try postEmptyEvent(); - try waitEvents(); + postEmptyEvent(); + waitEvents(); } test "rawMouseMotionSupported" { - try init(.{}); + defer getError() catch {}; // clear any error we generate + if (!init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{getErrorString()}); + std.process.exit(1); + } defer terminate(); _ = rawMouseMotionSupported(); diff --git a/libs/glfw/src/native.zig b/libs/glfw/src/native.zig index a2efb9fd..cc7c4489 100644 --- a/libs/glfw/src/native.zig +++ b/libs/glfw/src/native.zig @@ -61,17 +61,12 @@ pub fn Native(comptime options: BackendOptions) type { /// return: The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`) of the /// specified monitor. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getWin32Adapter(monitor: Monitor) [*:0]const u8 { internal_debug.assertInitialized(); if (native.glfwGetWin32Adapter(@ptrCast(*native.GLFWmonitor, monitor.handle))) |adapter| return adapter; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetWin32Adapter` returns `null` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } @@ -80,17 +75,12 @@ pub fn Native(comptime options: BackendOptions) type { /// return: The UTF-8 encoded display device name (for example `\\.\DISPLAY1\Monitor0`) /// of the specified monitor. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getWin32Monitor(monitor: Monitor) [*:0]const u8 { internal_debug.assertInitialized(); if (native.glfwGetWin32Monitor(@ptrCast(*native.GLFWmonitor, monitor.handle))) |mon| return mon; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetWin32Monitor` returns `null` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } @@ -104,18 +94,13 @@ pub fn Native(comptime options: BackendOptions) type { /// ``` /// This DC is private and does not need to be released. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getWin32Window(window: Window) std.os.windows.HWND { internal_debug.assertInitialized(); if (native.glfwGetWin32Window(@ptrCast(*native.GLFWwindow, window.handle))) |win| return @ptrCast(std.os.windows.HWND, win); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetWin32Window` returns `null` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } @@ -129,261 +114,181 @@ pub fn Native(comptime options: BackendOptions) type { /// ``` /// This DC is private and does not need to be released. /// - /// Possible errors include glfw.Error.NotInitalized. + /// Possible errors include glfw.Error.NoWindowContext + /// null is returned in the event of an error. /// /// thread_safety: This function may be called from any thread. Access is not synchronized. - pub fn getWGLContext(window: Window) error{NoWindowContext}!std.os.windows.HGLRC { + pub fn getWGLContext(window: Window) ?std.os.windows.HGLRC { internal_debug.assertInitialized(); if (native.glfwGetWGLContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return context; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.NoWindowContext => |e| e, - else => unreachable, - }; - // `glfwGetWGLContext` returns `null` only for errors - unreachable; + return null; } /// Returns the `CGDirectDisplayID` of the specified monitor. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getCocoaMonitor(monitor: Monitor) u32 { internal_debug.assertInitialized(); const mon = native.glfwGetCocoaMonitor(@ptrCast(*native.GLFWmonitor, monitor.handle)); if (mon != native.kCGNullDirectDisplay) return mon; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetCocoaMonitor` returns `kCGNullDirectDisplay` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } /// Returns the `NSWindow` of the specified window. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getCocoaWindow(window: Window) ?*anyopaque { internal_debug.assertInitialized(); - const win = native.glfwGetCocoaWindow(@ptrCast(*native.GLFWwindow, window.handle)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; - return win; + return native.glfwGetCocoaWindow(@ptrCast(*native.GLFWwindow, window.handle)); } /// Returns the `NSWindow` of the specified window. /// - /// Possible errors include glfw.Error.NotInitialized, glfw.Error.NoWindowContext. + /// Possible errors include glfw.Error.NoWindowContext. /// /// thread_safety: This function may be called from any thread. Access is not synchronized. - pub fn getNSGLContext(window: Window) error{NoWindowContext}!u32 { + pub fn getNSGLContext(window: Window) u32 { internal_debug.assertInitialized(); - const context = native.glfwGetNSGLContext(@ptrCast(*native.GLFWwindow, window.handle)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.NoWindowContext => |e| e, - else => unreachable, - }; - return context; + return native.glfwGetNSGLContext(@ptrCast(*native.GLFWwindow, window.handle)); } /// Returns the `Display` used by GLFW. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getX11Display() *anyopaque { internal_debug.assertInitialized(); if (native.glfwGetX11Display()) |display| return @ptrCast(*anyopaque, display); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetX11Display` returns `null` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } /// Returns the `RRCrtc` of the specified monitor. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getX11Adapter(monitor: Monitor) u32 { internal_debug.assertInitialized(); const adapter = native.glfwGetX11Adapter(@ptrCast(*native.GLFWMonitor, monitor.handle)); if (adapter != 0) return adapter; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetX11Adapter` returns `0` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } /// Returns the `RROutput` of the specified monitor. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getX11Monitor(monitor: Monitor) u32 { internal_debug.assertInitialized(); const mon = native.glfwGetX11Monitor(@ptrCast(*native.GLFWmonitor, monitor.handle)); if (mon != 0) return mon; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetX11Monitor` returns `0` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } /// Returns the `Window` of the specified window. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getX11Window(window: Window) u32 { internal_debug.assertInitialized(); const win = native.glfwGetX11Window(@ptrCast(*native.GLFWwindow, window.handle)); if (win != 0) return @intCast(u32, win); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetX11Window` returns `0` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } /// Sets the current primary selection to the specified string. /// - /// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. + /// Possible errors include glfw.Error.PlatformError. /// /// The specified string is copied before this function returns. /// /// thread_safety: This function must only be called from the main thread. - pub fn setX11SelectionString(string: [*:0]const u8) error{PlatformError}!void { + pub fn setX11SelectionString(string: [*:0]const u8) void { internal_debug.assertInitialized(); native.glfwSetX11SelectionString(string); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError => |e| e, - else => unreachable, - }; } /// Returns the contents of the current primary selection as a string. /// - /// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. + /// Possible errors include glfw.Error.PlatformError. + /// Returns null in the event of an error. /// /// The returned string is allocated and freed by GLFW. You should not free it /// yourself. It is valid until the next call to getX11SelectionString or /// setX11SelectionString, or until the library is terminated. /// /// thread_safety: This function must only be called from the main thread. - pub fn getX11SelectionString() error{FormatUnavailable}![*:0]const u8 { + pub fn getX11SelectionString() ?[*:0]const u8 { internal_debug.assertInitialized(); if (native.glfwGetX11SelectionString()) |str| return str; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.FormatUnavailable => |e| e, - else => unreachable, - }; - // `glfwGetX11SelectionString` returns `null` only for errors - unreachable; + return null; } /// Returns the `GLXContext` of the specified window. /// - /// Possible errors include glfw.Error.NoWindowContext and glfw.Error.NotInitialized. + /// Possible errors include glfw.Error.NoWindowContext. + /// Returns null in the event of an error. /// /// thread_safety: This function may be called from any thread. Access is not synchronized. - pub fn getGLXContext(window: Window) error{NoWindowContext}!*anyopaque { + pub fn getGLXContext(window: Window) ?*anyopaque { internal_debug.assertInitialized(); if (native.glfwGetGLXContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return @ptrCast(*anyopaque, context); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.NoWindowContext => |e| e, - else => unreachable, - }; - // `glfwGetGLXContext` returns `null` only for errors - unreachable; + return null; } /// Returns the `GLXWindow` of the specified window. /// - /// Possible errors include glfw.Error.NoWindowContext and glfw.Error.NotInitialized. + /// Possible errors include glfw.Error.NoWindowContext. + /// Returns null in the event of an error. /// /// thread_safety: This function may be called from any thread. Access is not synchronized. - pub fn getGLXWindow(window: Window) error{NoWindowContext}!*anyopaque { + pub fn getGLXWindow(window: Window) ?*anyopaque { internal_debug.assertInitialized(); const win = native.glfwGetGLXWindow(@ptrCast(*native.GLFWwindow, window.handle)); if (win != 0) return @ptrCast(*anyopaque, win); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.NoWindowContext => |e| e, - else => unreachable, - }; - // `glfwGetGLXWindow` returns `0` only for errors - unreachable; + return null; } /// Returns the `*wl_display` used by GLFW. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getWaylandDisplay() *anyopaque { internal_debug.assertInitialized(); if (native.glfwGetWaylandDisplay()) |display| return @ptrCast(*anyopaque, display); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetWaylandDisplay` returns `null` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } /// Returns the `*wl_output` of the specified monitor. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getWaylandMonitor(monitor: Monitor) *anyopaque { internal_debug.assertInitialized(); if (native.glfwGetWaylandMonitor(@ptrCast(*native.GLFWmonitor, monitor.handle))) |mon| return @ptrCast(*anyopaque, mon); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetWaylandMonitor` returns `null` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } /// Returns the `*wl_surface` of the specified window. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// thread_safety: This function may be called from any thread. Access is not synchronized. pub fn getWaylandWindow(window: Window) *anyopaque { internal_debug.assertInitialized(); if (native.glfwGetWaylandWindow(@ptrCast(*native.GLFWwindow, window.handle))) |win| return @ptrCast(*anyopaque, win); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetWaylandWindow` returns `null` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } /// Returns the `EGLDisplay` used by GLFW. /// - /// Possible errors include glfw.Error.NotInitalized. - /// /// remark: Because EGL is initialized on demand, this function will return `EGL_NO_DISPLAY` /// until the first context has been created via EGL. /// @@ -392,30 +297,22 @@ pub fn Native(comptime options: BackendOptions) type { internal_debug.assertInitialized(); const display = native.glfwGetEGLDisplay(); if (display != native.EGL_NO_DISPLAY) return @ptrCast(*anyopaque, display); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetEGLDisplay` returns `EGL_NO_DISPLAY` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } /// Returns the `EGLContext` of the specified window. /// - /// Possible errors include glfw.Error.NotInitalized and glfw.Error.NoWindowContext. + /// Possible errors include glfw.Error.NoWindowContext. + /// Returns null in the event of an error. /// /// thread_safety This function may be called from any thread. Access is not synchronized. - pub fn getEGLContext(window: Window) error{NoWindowContext}!*anyopaque { + pub fn getEGLContext(window: Window) ?*anyopaque { internal_debug.assertInitialized(); const context = native.glfwGetEGLContext(@ptrCast(*native.GLFWwindow, window.handle)); if (context != native.EGL_NO_CONTEXT) return @ptrCast(*anyopaque, context); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.NoWindowContext => |e| e, - else => unreachable, - }; - // `glfwGetEGLContext` returns `EGL_NO_CONTEXT` only for errors - unreachable; + return null; } /// Returns the `EGLSurface` of the specified window. @@ -423,17 +320,11 @@ pub fn Native(comptime options: BackendOptions) type { /// Possible errors include glfw.Error.NotInitalized and glfw.Error.NoWindowContext. /// /// thread_safety This function may be called from any thread. Access is not synchronized. - pub fn getEGLSurface(window: Window) error{NoWindowContext}!*anyopaque { + pub fn getEGLSurface(window: Window) ?*anyopaque { internal_debug.assertInitialized(); const surface = native.glfwGetEGLSurface(@ptrCast(*native.GLFWwindow, window.handle)); if (surface != native.EGL_NO_SURFACE) return @ptrCast(*anyopaque, surface); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.NoWindowContext => |e| e, - else => unreachable, - }; - // `glfwGetEGLSurface` returns `EGL_NO_SURFACE` only for errors - unreachable; + return null; } pub const OSMesaColorBuffer = struct { @@ -445,11 +336,11 @@ pub fn Native(comptime options: BackendOptions) type { /// Retrieves the color buffer associated with the specified window. /// - /// Possible errors include glfw.Error.NotInitalized, glfw.Error.NoWindowContext - /// and glfw.Error.PlatformError. + /// Possible errors include glfw.Error.NoWindowContext and glfw.Error.PlatformError. + /// Returns null in the event of an error. /// /// thread_safety: This function may be called from any thread. Access is not synchronized. - pub fn getOSMesaColorBuffer(window: Window) error{ PlatformError, NoWindowContext }!OSMesaColorBuffer { + pub fn getOSMesaColorBuffer(window: Window) ?OSMesaColorBuffer { internal_debug.assertInitialized(); var buf: OSMesaColorBuffer = undefined; if (native.glfwGetOSMesaColorBuffer( @@ -459,13 +350,7 @@ pub fn Native(comptime options: BackendOptions) type { &buf.format, &buf.buffer, ) == native.GLFW_TRUE) return buf; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError, Error.NoWindowContext => |e| e, - else => unreachable, - }; - // `glfwGetOSMesaColorBuffer` returns `GLFW_FALSE` only for errors - unreachable; + return null; } pub const OSMesaDepthBuffer = struct { @@ -477,11 +362,11 @@ pub fn Native(comptime options: BackendOptions) type { /// Retrieves the depth buffer associated with the specified window. /// - /// Possible errors include glfw.Error.NotInitalized, glfw.Error.NoWindowContext - /// and glfw.Error.PlatformError. + /// Possible errors include glfw.Error.NoWindowContext and glfw.Error.PlatformError. + /// Returns null in the event of an error. /// /// thread_safety: This function may be called from any thread. Access is not synchronized. - pub fn getOSMesaDepthBuffer(window: Window) error{ PlatformError, NoWindowContext }!OSMesaDepthBuffer { + pub fn getOSMesaDepthBuffer(window: Window) ?OSMesaDepthBuffer { internal_debug.assertInitialized(); var buf: OSMesaDepthBuffer = undefined; if (native.glfwGetOSMesaDepthBuffer( @@ -491,30 +376,18 @@ pub fn Native(comptime options: BackendOptions) type { &buf.bytes_per_value, &buf.buffer, ) == native.GLFW_TRUE) return buf; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.PlatformError, Error.NoWindowContext => |e| e, - else => unreachable, - }; - // `glfwGetOSMesaDepthBuffer` returns `GLFW_FALSE` only for errors - unreachable; + return null; } /// Returns the 'OSMesaContext' of the specified window. /// - /// Possible errors include glfw.Error.NotInitalized and glfw.Error.NoWindowContext. + /// Possible errors include glfw.Error.NoWindowContext. /// /// thread_safety: This function may be called from any thread. Access is not synchronized. - pub fn getOSMesaContext(window: Window) error{NoWindowContext}!*anyopaque { + pub fn getOSMesaContext(window: Window) ?*anyopaque { internal_debug.assertInitialized(); if (native.glfwGetOSMesaContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return @ptrCast(*anyopaque, context); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.NoWindowContext => |e| e, - else => unreachable, - }; - // `glfwGetOSMesaContext` returns `null` only for errors - unreachable; + return null; } }; } diff --git a/libs/glfw/src/opengl.zig b/libs/glfw/src/opengl.zig index bddaa1c7..5ceacf9d 100644 --- a/libs/glfw/src/opengl.zig +++ b/libs/glfw/src/opengl.zig @@ -26,19 +26,14 @@ const internal_debug = @import("internal_debug.zig"); /// @param[in] window The window whose context to make current, or null to /// detach the current context. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.NoWindowContext and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.NoWindowContext and glfw.Error.PlatformError. /// /// @thread_safety This function may be called from any thread. /// /// see also: context_current, glfwGetCurrentContext -pub inline fn makeContextCurrent(window: ?Window) error{ NoWindowContext, PlatformError }!void { +pub inline fn makeContextCurrent(window: ?Window) void { internal_debug.assertInitialized(); if (window) |w| c.glfwMakeContextCurrent(w.handle) else c.glfwMakeContextCurrent(null); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.NoWindowContext, Error.PlatformError => |e| e, - else => unreachable, - }; } /// Returns the window whose context is current on the calling thread. @@ -48,18 +43,12 @@ pub inline fn makeContextCurrent(window: ?Window) error{ NoWindowContext, Platfo /// /// Returns he window whose context is current, or null if no window's context is current. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @thread_safety This function may be called from any thread. /// /// see also: context_current, glfwMakeContextCurrent pub inline fn getCurrentContext() ?Window { internal_debug.assertInitialized(); if (c.glfwGetCurrentContext()) |handle| return Window.from(handle); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; return null; } @@ -83,7 +72,7 @@ pub inline fn getCurrentContext() ?Window { /// @param[in] interval The minimum number of screen updates to wait for until the buffers are /// swapped by glfw.swapBuffers. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.NoCurrentContext and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.NoCurrentContext and glfw.Error.PlatformError. /// /// This function is not called during context creation, leaving the swap interval set to whatever /// is the default for that API. This is done because some swap interval extensions used by @@ -96,14 +85,9 @@ pub inline fn getCurrentContext() ?Window { /// @thread_safety This function may be called from any thread. /// /// see also: buffer_swap, glfwSwapBuffers -pub inline fn swapInterval(interval: i32) error{ NoCurrentContext, PlatformError }!void { +pub inline fn swapInterval(interval: i32) void { internal_debug.assertInitialized(); c.glfwSwapInterval(@intCast(c_int, interval)); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.NoCurrentContext, Error.PlatformError => |e| e, - else => unreachable, - }; } /// Returns whether the specified extension is available. @@ -125,26 +109,19 @@ pub inline fn swapInterval(interval: i32) error{ NoCurrentContext, PlatformError /// @param[in] extension The ASCII encoded name of the extension. /// @return `true` if the extension is available, or `false` otherwise. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.NoCurrentContext, glfw.Error.InvalidValue +/// Possible errors include glfw.Error.NoCurrentContext, glfw.Error.InvalidValue /// and glfw.Error.PlatformError. /// /// @thread_safety This function may be called from any thread. /// /// see also: context_glext, glfw.getProcAddress -pub inline fn extensionSupported(extension: [:0]const u8) error{ NoCurrentContext, PlatformError }!bool { +pub inline fn extensionSupported(extension: [:0]const u8) bool { internal_debug.assertInitialized(); std.debug.assert(extension.len != 0); std.debug.assert(extension[0] != 0); - const supported = c.glfwExtensionSupported(extension.ptr); - getError() catch |err| return switch (err) { - Error.NoCurrentContext, Error.PlatformError => |e| e, - Error.NotInitialized => unreachable, - Error.InvalidValue => unreachable, - else => unreachable, - }; - return supported == c.GLFW_TRUE; + return c.glfwExtensionSupported(extension.ptr) == c.GLFW_TRUE; } const builtin = @import("builtin"); @@ -189,29 +166,34 @@ pub const GLProc = *const fn () callconv(.C) void; pub fn getProcAddress(proc_name: [*:0]const u8) callconv(.C) ?GLProc { internal_debug.assertInitialized(); if (c.glfwGetProcAddress(proc_name)) |proc_address| return proc_address; - getError() catch |err| @panic(@errorName(err)); return null; } test "makeContextCurrent" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); }; defer window.destroy(); - try glfw.makeContextCurrent(window); + glfw.makeContextCurrent(window); } test "getCurrentContext" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); const current_context = glfw.getCurrentContext(); @@ -220,51 +202,57 @@ test "getCurrentContext" { test "swapInterval" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); }; defer window.destroy(); - try glfw.makeContextCurrent(window); - glfw.swapInterval(1) catch |err| std.debug.print("failed to set swap interval, error={}\n", .{err}); + glfw.makeContextCurrent(window); + glfw.swapInterval(1); } test "getProcAddress" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); }; defer window.destroy(); - try glfw.makeContextCurrent(window); + glfw.makeContextCurrent(window); _ = glfw.getProcAddress("foobar"); } test "extensionSupported" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| { - // return without fail, because most of our CI environments are headless / we cannot open - // windows on them. - std.debug.print("note: failed to create window: {}\n", .{err}); - return; + const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) orelse { + std.log.err("failed to create window: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); }; defer window.destroy(); - try glfw.makeContextCurrent(window); - _ = glfw.extensionSupported("foobar") catch |err| std.debug.print("failed to check if extension supported, error={}\n", .{err}); + glfw.makeContextCurrent(window); + _ = glfw.extensionSupported("foobar"); } diff --git a/libs/glfw/src/time.zig b/libs/glfw/src/time.zig index 27e81f72..68f7c86e 100644 --- a/libs/glfw/src/time.zig +++ b/libs/glfw/src/time.zig @@ -31,11 +31,8 @@ pub inline fn getTime() f64 { internal_debug.assertInitialized(); const time = c.glfwGetTime(); if (time != 0) return time; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetTime` returns `0` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } @@ -49,7 +46,7 @@ pub inline fn getTime() f64 { /// /// @param[in] time The new value, in seconds. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.InvalidValue. +/// Possible errors include glfw.Error.InvalidValue. /// /// The upper limit of GLFW time is calculated as `floor((2^64 - 1) / 10^9)` and is due to /// implementations storing nanoseconds in 64 bits. The limit may be increased in the future. @@ -70,11 +67,6 @@ pub inline fn setTime(time: f64) void { }); c.glfwSetTime(time); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidValue => unreachable, - else => unreachable, - }; } /// Returns the current value of the raw timer. @@ -91,11 +83,8 @@ pub inline fn getTimerValue() u64 { internal_debug.assertInitialized(); const value = c.glfwGetTimerValue(); if (value != 0) return value; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetTimerValue` returns `0` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } @@ -112,17 +101,18 @@ pub inline fn getTimerFrequency() u64 { internal_debug.assertInitialized(); const frequency = c.glfwGetTimerFrequency(); if (frequency != 0) return frequency; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - else => unreachable, - }; // `glfwGetTimerFrequency` returns `0` only for errors + // but the only potential error is unreachable (NotInitialized) unreachable; } test "getTime" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); _ = getTime(); @@ -130,7 +120,11 @@ test "getTime" { test "setTime" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); _ = glfw.setTime(1234); @@ -138,7 +132,11 @@ test "setTime" { test "getTimerValue" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); _ = glfw.getTimerValue(); @@ -146,7 +144,11 @@ test "getTimerValue" { test "getTimerFrequency" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); _ = glfw.getTimerFrequency(); diff --git a/libs/glfw/src/vulkan.zig b/libs/glfw/src/vulkan.zig index f9836149..61f3c5ac 100644 --- a/libs/glfw/src/vulkan.zig +++ b/libs/glfw/src/vulkan.zig @@ -49,13 +49,10 @@ pub const VKGetInstanceProcAddr = *const fn (vk_instance: c.VkInstance, name: [* /// /// @return `true` if Vulkan is minimally available, or `false` otherwise. /// -/// Possible errors include glfw.Error.NotInitialized. -/// /// @thread_safety This function may be called from any thread. pub inline fn vulkanSupported() bool { internal_debug.assertInitialized(); const supported = c.glfwVulkanSupported(); - getError() catch unreachable; // Only error 'GLFW_NOT_INITIALIZED' is impossible return supported == c.GLFW_TRUE; } @@ -73,7 +70,8 @@ pub inline fn vulkanSupported() bool { /// If Vulkan is available but no set of extensions allowing window surface creation was found, /// this function returns null. You may still use Vulkan for off-screen rendering and compute work. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.APIUnavailable. +/// Possible errors include glfw.Error.APIUnavailable. +/// Returns null in the event of an error. /// /// Additional extensions may be required by future versions of GLFW. You should check if any /// extensions you wish to enable are already in the returned array, as it is an error to specify @@ -85,17 +83,11 @@ pub inline fn vulkanSupported() bool { /// @thread_safety This function may be called from any thread. /// /// see also: vulkan_ext, glfwCreateWindowSurface -pub inline fn getRequiredInstanceExtensions() error{APIUnavailable}![][*:0]const u8 { +pub inline fn getRequiredInstanceExtensions() ?[][*:0]const u8 { internal_debug.assertInitialized(); var count: u32 = 0; if (c.glfwGetRequiredInstanceExtensions(&count)) |extensions| return @ptrCast([*][*:0]const u8, extensions)[0..count]; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.APIUnavailable => |e| e, - else => unreachable, - }; - // `glfwGetRequiredInstanceExtensions` returns `null` only for errors - unreachable; + return null; } /// Vulkan API function pointer type. @@ -139,7 +131,6 @@ pub const VKProc = *const fn () callconv(.C) void; pub fn getInstanceProcAddress(vk_instance: ?*anyopaque, proc_name: [*:0]const u8) callconv(.C) ?VKProc { internal_debug.assertInitialized(); if (c.glfwGetInstanceProcAddress(if (vk_instance) |v| @ptrCast(c.VkInstance, v) else null, proc_name)) |proc_address| return proc_address; - getError() catch |err| @panic(@errorName(err)); return null; } @@ -159,7 +150,8 @@ pub fn getInstanceProcAddress(vk_instance: ?*anyopaque, proc_name: [*:0]const u8 /// @param[in] queuefamily The index of the queue family to query. /// @return `true` if the queue family supports presentation, or `false` otherwise. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.APIUnavailable and glfw.Error.PlatformError. +/// Possible errors include glfw.Error.APIUnavailable and glfw.Error.PlatformError. +/// Returns false in the event of an error. /// /// macos: This function currently always returns `true`, as the `VK_MVK_macos_surface` and /// 'VK_EXT_metal_surface' extension does not provide a `vkGetPhysicalDevice*PresentationSupport` type function. @@ -172,19 +164,13 @@ pub inline fn getPhysicalDevicePresentationSupport( vk_instance: *anyopaque, vk_physical_device: *anyopaque, queue_family: u32, -) error{ APIUnavailable, PlatformError }!bool { +) bool { internal_debug.assertInitialized(); - const v = c.glfwGetPhysicalDevicePresentationSupport( + return c.glfwGetPhysicalDevicePresentationSupport( @ptrCast(c.VkInstance, vk_instance), @ptrCast(c.VkPhysicalDevice, vk_physical_device), queue_family, - ); - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.APIUnavailable, Error.PlatformError => |e| e, - else => unreachable, - }; - return v == c.GLFW_TRUE; + ) == c.GLFW_TRUE; } /// Creates a Vulkan surface for the specified window. @@ -217,7 +203,8 @@ pub inline fn getPhysicalDevicePresentationSupport( /// @return `VkResult` type, `VK_SUCCESS` if successful, or a Vulkan error code if an /// error occurred. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.APIUnavailable, glfw.Error.PlatformError and glfw.Error.InvalidValue +/// Possible errors include glfw.Error.APIUnavailable, glfw.Error.PlatformError and glfw.Error.InvalidValue +/// Returns a bool indicating success. /// /// If an error occurs before the creation call is made, GLFW returns the Vulkan error code most /// appropriate for the error. Appropriate use of glfw.vulkanSupported and glfw.getRequiredInstanceExtensions @@ -241,7 +228,7 @@ pub inline fn getPhysicalDevicePresentationSupport( /// Vulkan objects, see the Vulkan specification. /// /// see also: vulkan_surface, glfw.getRequiredInstanceExtensions -pub inline fn createWindowSurface(vk_instance: anytype, window: Window, vk_allocation_callbacks: anytype, vk_surface_khr: anytype) error{ APIUnavailable, PlatformError }!i32 { +pub inline fn createWindowSurface(vk_instance: anytype, window: Window, vk_allocation_callbacks: anytype, vk_surface_khr: anytype) i32 { internal_debug.assertInitialized(); // zig-vulkan uses enums to represent opaque pointers: // pub const Instance = enum(usize) { null_handle = 0, _ }; @@ -250,26 +237,21 @@ pub inline fn createWindowSurface(vk_instance: anytype, window: Window, vk_alloc else => @ptrCast(c.VkInstance, vk_instance), }; - const v = c.glfwCreateWindowSurface( + return c.glfwCreateWindowSurface( instance, window.handle, if (vk_allocation_callbacks == null) null else @ptrCast(*const c.VkAllocationCallbacks, @alignCast(@alignOf(c.VkAllocationCallbacks), vk_allocation_callbacks)), @ptrCast(*c.VkSurfaceKHR, @alignCast(@alignOf(c.VkSurfaceKHR), vk_surface_khr)), - ); - if (v == c.VK_SUCCESS) return v; - getError() catch |err| return switch (err) { - Error.NotInitialized => unreachable, - Error.InvalidValue => @panic("Attempted to use window with client api to create vulkan surface."), - Error.APIUnavailable, Error.PlatformError => |e| e, - else => unreachable, - }; - // `glfwCreateWindowSurface` returns `!VK_SUCCESS` only for errors - unreachable; + ) == c.VK_SUCCESS; } test "vulkanSupported" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); _ = glfw.vulkanSupported(); @@ -277,15 +259,23 @@ test "vulkanSupported" { test "getRequiredInstanceExtensions" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); - _ = glfw.getRequiredInstanceExtensions() catch |err| std.debug.print("failed to get vulkan instance extensions, error={}\n", .{err}); + _ = glfw.getRequiredInstanceExtensions(); } test "getInstanceProcAddress" { const glfw = @import("main.zig"); - try glfw.init(.{}); + defer glfw.getError() catch {}; // clear any error we generate + if (!glfw.init(.{})) { + std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()}); + std.process.exit(1); + } defer glfw.terminate(); // syntax check only, we don't have a real vulkan instance and so this function would panic.