glfw: rework error handling system to prevent footguns
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
a9e9ac0955
commit
e9ba368443
12 changed files with 1136 additions and 1531 deletions
|
@ -106,23 +106,19 @@ pub const Shape = enum(i32) {
|
||||||
/// @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot.
|
/// @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot.
|
||||||
/// @return The handle of the created cursor.
|
/// @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.
|
/// @pointer_lifetime The specified image data is copied before this function returns.
|
||||||
///
|
///
|
||||||
/// @thread_safety This function must only be called from the main thread.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: cursor_object, glfw.Cursor.destroy, glfw.Cursor.createStandard
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
const img = image.toC();
|
const img = image.toC();
|
||||||
if (c.glfwCreateCursor(&img, @intCast(c_int, xhot), @intCast(c_int, yhot))) |cursor| return Cursor{ .ptr = cursor };
|
if (c.glfwCreateCursor(&img, @intCast(c_int, xhot), @intCast(c_int, yhot))) |cursor| return Cursor{ .ptr = cursor };
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.PlatformError => |e| e,
|
|
||||||
Error.InvalidValue => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwCreateCursor` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a cursor with a standard shape.
|
/// 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.
|
/// 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
|
/// 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.
|
/// thread_safety: This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: cursor_object, glfwCreateCursor
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
if (c.glfwCreateStandardCursor(@intCast(c_int, @enumToInt(shape)))) |cursor| return Cursor{ .ptr = cursor };
|
if (c.glfwCreateStandardCursor(@intCast(c_int, @enumToInt(shape)))) |cursor| return Cursor{ .ptr = cursor };
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.InvalidEnum => unreachable,
|
|
||||||
Error.CursorUnavailable => |e| e,
|
|
||||||
Error.PlatformError => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwCreateStandardCursor` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Destroys a cursor.
|
/// 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
|
/// 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.
|
/// 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.
|
/// @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 {
|
pub inline fn destroy(self: Cursor) void {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
c.glfwDestroyCursor(self.ptr);
|
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" {
|
test "create" {
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const image = try Image.init(allocator, 32, 32, 32 * 32 * 4);
|
const image = try Image.init(allocator, 32, 32, 32 * 32 * 4);
|
||||||
defer image.deinit(allocator);
|
defer image.deinit(allocator);
|
||||||
|
|
||||||
const cursor = glfw.Cursor.create(image, 0, 0) catch |err| {
|
const cursor = glfw.Cursor.create(image, 0, 0);
|
||||||
std.debug.print("failed to create cursor, custom cursors not supported? error={}\n", .{err});
|
if (cursor) |cur| cur.destroy();
|
||||||
return;
|
|
||||||
};
|
|
||||||
cursor.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "createStandard" {
|
test "createStandard" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const cursor = glfw.Cursor.createStandard(.ibeam) catch |err| {
|
const cursor = glfw.Cursor.createStandard(.ibeam);
|
||||||
std.debug.print("failed to create cursor, custom cursors not supported? error={}\n", .{err});
|
if (cursor) |cur| cur.destroy();
|
||||||
return;
|
|
||||||
};
|
|
||||||
cursor.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
215
src/Joystick.zig
215
src/Joystick.zig
|
@ -80,20 +80,14 @@ const GamepadState = extern struct {
|
||||||
///
|
///
|
||||||
/// @return `true` if the joystick is present, or `false` otherwise.
|
/// @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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: joystick
|
/// see also: joystick
|
||||||
pub inline fn present(self: Joystick) error{PlatformError}!bool {
|
pub inline fn present(self: Joystick) bool {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const is_present = c.glfwJoystickPresent(@enumToInt(self.jid));
|
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;
|
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.
|
/// @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
|
/// @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
|
/// 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
|
/// see also: joystick_axis
|
||||||
/// Replaces `glfwGetJoystickPos`.
|
/// Replaces `glfwGetJoystickPos`.
|
||||||
pub inline fn getAxes(self: Joystick) error{PlatformError}!?[]const f32 {
|
pub inline fn getAxes(self: Joystick) ?[]const f32 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
var count: c_int = undefined;
|
var count: c_int = undefined;
|
||||||
const axes = c.glfwGetJoystickAxes(@enumToInt(self.jid), &count);
|
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;
|
if (axes == null) return null;
|
||||||
return axes[0..@intCast(u32, count)];
|
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.
|
/// @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
|
/// @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.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: joystick_button
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
var count: c_int = undefined;
|
var count: c_int = undefined;
|
||||||
const buttons = c.glfwGetJoystickButtons(@enumToInt(self.jid), &count);
|
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;
|
if (buttons == null) return null;
|
||||||
return buttons[0..@intCast(u32, count)];
|
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.
|
/// @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
|
/// @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
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: joystick_hat
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
var count: c_int = undefined;
|
var count: c_int = undefined;
|
||||||
const hats = c.glfwGetJoystickHats(@enumToInt(self.jid), &count);
|
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;
|
if (hats == null) return null;
|
||||||
const slice = hats[0..@intCast(u32, count)];
|
const slice = hats[0..@intCast(u32, count)];
|
||||||
return @ptrCast(*const []const Hat, &slice).*;
|
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
|
/// @return The UTF-8 encoded name of the joystick, or null if the joystick is not present or an
|
||||||
/// error occurred.
|
/// 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
|
/// @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.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: joystick_name
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
const name_opt = c.glfwGetJoystickName(@enumToInt(self.jid));
|
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|
|
return if (name_opt) |name|
|
||||||
std.mem.span(@ptrCast([*:0]const u8, name))
|
std.mem.span(@ptrCast([*:0]const u8, name))
|
||||||
else
|
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.
|
/// @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
|
/// @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.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: gamepad
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
const guid_opt = c.glfwGetJoystickGUID(@enumToInt(self.jid));
|
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|
|
return if (guid_opt) |guid|
|
||||||
std.mem.span(@ptrCast([*:0]const u8, guid))
|
std.mem.span(@ptrCast([*:0]const u8, guid))
|
||||||
else
|
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 {
|
pub inline fn setUserPointer(self: Joystick, comptime T: type, pointer: *T) void {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
c.glfwSetJoystickUserPointer(@enumToInt(self.jid), @ptrCast(*anyopaque, pointer));
|
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.
|
/// 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 {
|
pub inline fn getUserPointer(self: Joystick, comptime PointerType: type) ?PointerType {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const ptr = c.glfwGetJoystickUserPointer(@enumToInt(self.jid));
|
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));
|
if (ptr) |p| return @ptrCast(PointerType, @alignCast(@alignOf(std.meta.Child(PointerType)), p));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -366,8 +327,6 @@ pub const Event = enum(c_int) {
|
||||||
/// @callback_param `event` One of `.connected` or `.disconnected`. Future releases may add
|
/// @callback_param `event` One of `.connected` or `.disconnected`. Future releases may add
|
||||||
/// more events.
|
/// more events.
|
||||||
///
|
///
|
||||||
/// Possible errors include glfw.Error.NotInitialized.
|
|
||||||
///
|
|
||||||
/// @thread_safety This function must only be called from the main thread.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: joystick_event
|
/// see also: joystick_event
|
||||||
|
@ -388,11 +347,6 @@ pub inline fn setCallback(comptime callback: ?fn (joystick: Joystick, event: Eve
|
||||||
} else {
|
} else {
|
||||||
if (c.glfwSetJoystickCallback(null) != null) return;
|
if (c.glfwSetJoystickCallback(null) != null) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the specified SDL_GameControllerDB gamepad mappings.
|
/// 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.
|
/// @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.
|
/// @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
|
/// @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();
|
internal_debug.assertInitialized();
|
||||||
if (c.glfwUpdateGamepadMappings(gamepad_mappings) == c.GLFW_TRUE) return;
|
return c.glfwUpdateGamepadMappings(gamepad_mappings) == c.GLFW_TRUE;
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the specified joystick has a gamepad mapping.
|
/// 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.
|
/// @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.
|
/// @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 {
|
pub inline fn isGamepad(self: Joystick) bool {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const is_gamepad = c.glfwJoystickIsGamepad(@enumToInt(self.jid));
|
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;
|
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
|
/// @return The UTF-8 encoded name of the gamepad, or null if the joystick is not present or does
|
||||||
/// not have a mapping.
|
/// 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
|
/// @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
|
/// 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 {
|
pub inline fn getGamepadName(self: Joystick) ?[:0]const u8 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const name_opt = c.glfwGetGamepadName(@enumToInt(self.jid));
|
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|
|
return if (name_opt) |name|
|
||||||
std.mem.span(@ptrCast([*:0]const u8, name))
|
std.mem.span(@ptrCast([*:0]const u8, name))
|
||||||
else
|
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
|
/// @return the gamepad input state if successful, or null if no joystick is connected or it has no
|
||||||
/// gamepad mapping.
|
/// 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.
|
/// @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();
|
internal_debug.assertInitialized();
|
||||||
var state: GamepadState = undefined;
|
var state: GamepadState = undefined;
|
||||||
const success = c.glfwGetGamepadState(@enumToInt(self.jid), @ptrCast(*c.GLFWgamepadstate, &state));
|
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;
|
return if (success == c.GLFW_TRUE) state else null;
|
||||||
}
|
}
|
||||||
|
|
||||||
test "present" {
|
test "present" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
_ = joystick.present();
|
||||||
_ = joystick.present() catch |err| std.debug.print("failed to detect joystick, joysticks not supported? error={}\n", .{err});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getAxes" {
|
test "getAxes" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
_ = joystick.getAxes();
|
||||||
_ = joystick.getAxes() catch |err| std.debug.print("failed to get joystick axes, joysticks not supported? error={}\n", .{err});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getButtons" {
|
test "getButtons" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
_ = joystick.getButtons();
|
||||||
_ = joystick.getButtons() catch |err| std.debug.print("failed to get joystick buttons, joysticks not supported? error={}\n", .{err});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getHats" {
|
test "getHats" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
|
||||||
_ = joystick.getHats() catch |err| std.debug.print("failed to get joystick hats, joysticks not supported? error={}\n", .{err});
|
if (joystick.getHats()) |hats| {
|
||||||
const hats = std.mem.zeroes(Hat);
|
for (hats) |hat| {
|
||||||
if (hats.down and hats.up) {
|
if (hat.down and hat.up) {
|
||||||
// down-up!
|
// down-up!
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getName" {
|
test "getName" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
_ = joystick.getName();
|
||||||
_ = joystick.getName() catch |err| std.debug.print("failed to get joystick name, joysticks not supported? error={}\n", .{err});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getGUID" {
|
test "getGUID" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
_ = joystick.getGUID();
|
||||||
_ = joystick.getGUID() catch |err| std.debug.print("failed to get joystick GUID, joysticks not supported? error={}\n", .{err});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "setUserPointer_syntax" {
|
test "setUserPointer_syntax" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
@ -607,7 +566,11 @@ test "setUserPointer_syntax" {
|
||||||
|
|
||||||
test "getUserPointer_syntax" {
|
test "getUserPointer_syntax" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
@ -619,7 +582,11 @@ test "getUserPointer_syntax" {
|
||||||
|
|
||||||
test "setCallback" {
|
test "setCallback" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
glfw.Joystick.setCallback((struct {
|
glfw.Joystick.setCallback((struct {
|
||||||
|
@ -637,7 +604,11 @@ test "updateGamepadMappings_syntax" {
|
||||||
|
|
||||||
test "isGamepad" {
|
test "isGamepad" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
@ -646,7 +617,11 @@ test "isGamepad" {
|
||||||
|
|
||||||
test "getGamepadName" {
|
test "getGamepadName" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
@ -655,7 +630,11 @@ test "getGamepadName" {
|
||||||
|
|
||||||
test "getGamepadState" {
|
test "getGamepadState" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const joystick = glfw.Joystick{ .jid = .one };
|
const joystick = glfw.Joystick{ .jid = .one };
|
||||||
|
|
230
src/Monitor.zig
230
src/Monitor.zig
|
@ -27,21 +27,16 @@ const Pos = struct {
|
||||||
|
|
||||||
/// Returns the position of the monitor's viewport on the virtual screen.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: monitor_properties
|
/// see also: monitor_properties
|
||||||
pub inline fn getPos(self: Monitor) error{PlatformError}!Pos {
|
pub inline fn getPos(self: Monitor) Pos {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
var xpos: c_int = 0;
|
var xpos: c_int = 0;
|
||||||
var ypos: c_int = 0;
|
var ypos: c_int = 0;
|
||||||
c.glfwGetMonitorPos(self.handle, &xpos, &ypos);
|
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) };
|
return Pos{ .x = @intCast(u32, xpos), .y = @intCast(u32, ypos) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,23 +55,19 @@ const Workarea = struct {
|
||||||
|
|
||||||
/// Retrieves the work area of the monitor.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: monitor_workarea
|
/// see also: monitor_workarea
|
||||||
pub inline fn getWorkarea(self: Monitor) error{PlatformError}!Workarea {
|
pub inline fn getWorkarea(self: Monitor) Workarea {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
var xpos: c_int = 0;
|
var xpos: c_int = 0;
|
||||||
var ypos: c_int = 0;
|
var ypos: c_int = 0;
|
||||||
var width: c_int = 0;
|
var width: c_int = 0;
|
||||||
var height: c_int = 0;
|
var height: c_int = 0;
|
||||||
c.glfwGetMonitorWorkarea(self.handle, &xpos, &ypos, &width, &height);
|
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) };
|
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)
|
/// [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data)
|
||||||
/// data is incorrect or because the driver does not report it accurately.
|
/// 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
|
/// 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
|
/// 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.
|
/// @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 width_mm: c_int = 0;
|
||||||
var height_mm: c_int = 0;
|
var height_mm: c_int = 0;
|
||||||
c.glfwGetMonitorPhysicalSize(self.handle, &width_mm, &height_mm);
|
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) };
|
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.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: monitor_scale, glfw.Window.getContentScale
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
var x_scale: f32 = 0;
|
var x_scale: f32 = 0;
|
||||||
var y_scale: f32 = 0;
|
var y_scale: f32 = 0;
|
||||||
c.glfwGetMonitorContentScale(self.handle, &x_scale, &y_scale);
|
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) };
|
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
|
/// name typically reflects the make and model of the monitor and is not guaranteed to be unique
|
||||||
/// among the connected monitors.
|
/// 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
|
/// @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.
|
/// 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 {
|
pub inline fn getName(self: Monitor) [*:0]const u8 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (c.glfwGetMonitorName(self.handle)) |name| return @ptrCast([*:0]const u8, name);
|
if (c.glfwGetMonitorName(self.handle)) |name| return @ptrCast([*:0]const u8, name);
|
||||||
getError() catch |err| return switch (err) {
|
// `glfwGetMonitorName` returns `null` only for errors, but the only error is unreachable
|
||||||
Error.NotInitialized => unreachable,
|
// (NotInitialized)
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetMonitorName` returns `null` only for errors
|
|
||||||
unreachable;
|
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
|
/// This function may be called from the monitor callback, even for a monitor that is being
|
||||||
/// disconnected.
|
/// disconnected.
|
||||||
///
|
///
|
||||||
/// Possible errors include glfw.Error.NotInitialized.
|
|
||||||
///
|
|
||||||
/// @thread_safety This function may be called from any thread. Access is not synchronized.
|
/// @thread_safety This function may be called from any thread. Access is not synchronized.
|
||||||
///
|
///
|
||||||
/// see also: monitor_userptr, glfw.Monitor.getUserPointer
|
/// see also: monitor_userptr, glfw.Monitor.getUserPointer
|
||||||
pub inline fn setUserPointer(self: Monitor, comptime T: type, ptr: *T) void {
|
pub inline fn setUserPointer(self: Monitor, comptime T: type, ptr: *T) void {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
c.glfwSetMonitorUserPointer(self.handle, ptr);
|
c.glfwSetMonitorUserPointer(self.handle, ptr);
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the user pointer of the specified monitor.
|
/// 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
|
/// This function may be called from the monitor callback, even for a monitor that is being
|
||||||
/// disconnected.
|
/// disconnected.
|
||||||
///
|
///
|
||||||
/// Possible errors include glfw.Error.NotInitialized.
|
|
||||||
///
|
|
||||||
/// @thread_safety This function may be called from any thread. Access is not synchronized.
|
/// @thread_safety This function may be called from any thread. Access is not synchronized.
|
||||||
///
|
///
|
||||||
/// see also: monitor_userptr, glfw.Monitor.setUserPointer
|
/// see also: monitor_userptr, glfw.Monitor.setUserPointer
|
||||||
pub inline fn getUserPointer(self: Monitor, comptime T: type) ?*T {
|
pub inline fn getUserPointer(self: Monitor, comptime T: type) ?*T {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const ptr = c.glfwGetMonitorUserPointer(self.handle);
|
const ptr = c.glfwGetMonitorUserPointer(self.handle);
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
if (ptr == null) return null;
|
if (ptr == null) return null;
|
||||||
return @ptrCast(*T, @alignCast(@alignOf(T), ptr.?));
|
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
|
/// then by resolution area (the product of width and height), then resolution width and finally
|
||||||
/// by refresh rate.
|
/// 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.
|
/// The returned slice memory is owned by the caller.
|
||||||
///
|
///
|
||||||
/// @thread_safety This function must only be called from the main thread.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: monitor_modes, glfw.Monitor.getVideoMode
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
var count: c_int = 0;
|
var count: c_int = 0;
|
||||||
if (c.glfwGetVideoModes(self.handle, &count)) |modes| {
|
if (c.glfwGetVideoModes(self.handle, &count)) |modes| {
|
||||||
|
@ -243,13 +209,7 @@ pub inline fn getVideoModes(self: Monitor, allocator: mem.Allocator) (mem.Alloca
|
||||||
}
|
}
|
||||||
return slice;
|
return slice;
|
||||||
}
|
}
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.PlatformError => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetVideoModes` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the current mode of the specified monitor.
|
/// 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
|
/// full screen window for that monitor, the return value will depend on whether that window is
|
||||||
/// iconified.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: monitor_modes, glfw.Monitor.getVideoModes
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
if (c.glfwGetVideoMode(self.handle)) |mode| return VideoMode{ .handle = mode.* };
|
if (c.glfwGetVideoMode(self.handle)) |mode| return VideoMode{ .handle = mode.* };
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.PlatformError => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetVideoMode` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a gamma ramp and sets it for the specified monitor.
|
/// 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.
|
/// 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
|
/// wayland: Gamma handling is a privileged protocol, this function will thus never be implemented
|
||||||
/// and emits glfw.Error.PlatformError.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: monitor_gamma
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
|
|
||||||
std.debug.assert(!std.math.isNan(gamma));
|
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);
|
std.debug.assert(gamma <= std.math.f32_max);
|
||||||
|
|
||||||
c.glfwSetGamma(self.handle, gamma);
|
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.
|
/// Returns the current gamma ramp for the specified monitor.
|
||||||
///
|
///
|
||||||
/// This function returns the current gamma ramp of 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
|
/// wayland: Gamma handling is a privileged protocol, this function will thus never be implemented
|
||||||
/// and returns glfw.Error.PlatformError.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: monitor_gamma
|
/// see also: monitor_gamma
|
||||||
pub inline fn getGammaRamp(self: Monitor) error{ PlatformError, FeatureUnavailable }!GammaRamp {
|
pub inline fn getGammaRamp(self: Monitor) ?GammaRamp {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (c.glfwGetGammaRamp(self.handle)) |ramp| return GammaRamp.fromC(ramp.*);
|
if (c.glfwGetGammaRamp(self.handle)) |ramp| return GammaRamp.fromC(ramp.*);
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.PlatformError, Error.FeatureUnavailable => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetGammaRamp` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the current gamma ramp for the specified monitor.
|
/// 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.
|
/// 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
|
/// 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.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: monitor_gamma
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
c.glfwSetGammaRamp(self.handle, &ramp.toC());
|
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.
|
/// Returns the currently connected monitors.
|
||||||
|
@ -395,11 +334,8 @@ pub inline fn getAll(allocator: mem.Allocator) mem.Allocator.Error![]Monitor {
|
||||||
}
|
}
|
||||||
return slice;
|
return slice;
|
||||||
}
|
}
|
||||||
getError() catch |err| return switch (err) {
|
// `glfwGetMonitors` returning null can be either an error or no monitors, but the only error is
|
||||||
Error.NotInitialized => unreachable,
|
// unreachable (NotInitialized)
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetMonitors` returning null can be either an error or no monitors
|
|
||||||
return &[_]Monitor{};
|
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
|
/// This function returns the primary monitor. This is usually the monitor where elements like
|
||||||
/// the task bar or global menu bar are located.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: monitor_monitors, glfw.monitors.getAll
|
/// see also: monitor_monitors, glfw.monitors.getAll
|
||||||
pub inline fn getPrimary() ?Monitor {
|
pub inline fn getPrimary() ?Monitor {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (c.glfwGetPrimaryMonitor()) |handle| return Monitor{ .handle = handle };
|
if (c.glfwGetPrimaryMonitor()) |handle| return Monitor{ .handle = handle };
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
return null;
|
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.
|
/// `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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: monitor_event
|
/// see also: monitor_event
|
||||||
|
@ -470,16 +398,15 @@ pub inline fn setCallback(comptime callback: ?fn (monitor: Monitor, event: Event
|
||||||
} else {
|
} else {
|
||||||
if (c.glfwSetMonitorCallback(null) != null) return;
|
if (c.glfwSetMonitorCallback(null) != null) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getAll" {
|
test "getAll" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
|
@ -489,7 +416,11 @@ test "getAll" {
|
||||||
|
|
||||||
test "getPrimary" {
|
test "getPrimary" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
_ = getPrimary();
|
_ = getPrimary();
|
||||||
|
@ -497,29 +428,41 @@ test "getPrimary" {
|
||||||
|
|
||||||
test "getPos" {
|
test "getPos" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const monitor = getPrimary();
|
const monitor = getPrimary();
|
||||||
if (monitor) |m| {
|
if (monitor) |m| {
|
||||||
_ = try m.getPos();
|
_ = m.getPos();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getWorkarea" {
|
test "getWorkarea" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const monitor = getPrimary();
|
const monitor = getPrimary();
|
||||||
if (monitor) |m| {
|
if (monitor) |m| {
|
||||||
_ = try m.getWorkarea();
|
_ = m.getWorkarea();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getPhysicalSize" {
|
test "getPhysicalSize" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const monitor = getPrimary();
|
const monitor = getPrimary();
|
||||||
|
@ -530,18 +473,26 @@ test "getPhysicalSize" {
|
||||||
|
|
||||||
test "getContentScale" {
|
test "getContentScale" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const monitor = getPrimary();
|
const monitor = getPrimary();
|
||||||
if (monitor) |m| {
|
if (monitor) |m| {
|
||||||
_ = try m.getContentScale();
|
_ = m.getContentScale();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getName" {
|
test "getName" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const monitor = getPrimary();
|
const monitor = getPrimary();
|
||||||
|
@ -552,7 +503,11 @@ test "getName" {
|
||||||
|
|
||||||
test "userPointer" {
|
test "userPointer" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const monitor = getPrimary();
|
const monitor = getPrimary();
|
||||||
|
@ -568,7 +523,11 @@ test "userPointer" {
|
||||||
|
|
||||||
test "setCallback" {
|
test "setCallback" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
setCallback(struct {
|
setCallback(struct {
|
||||||
|
@ -581,46 +540,57 @@ test "setCallback" {
|
||||||
|
|
||||||
test "getVideoModes" {
|
test "getVideoModes" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const monitor = getPrimary();
|
const monitor = getPrimary();
|
||||||
if (monitor) |m| {
|
if (monitor) |m| {
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
const modes = try m.getVideoModes(allocator);
|
const modes_maybe = try m.getVideoModes(allocator);
|
||||||
|
if (modes_maybe) |modes| {
|
||||||
defer allocator.free(modes);
|
defer allocator.free(modes);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getVideoMode" {
|
test "getVideoMode" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const monitor = getPrimary();
|
const monitor = getPrimary();
|
||||||
if (monitor) |m| {
|
if (monitor) |m| {
|
||||||
_ = try m.getVideoMode();
|
_ = m.getVideoMode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "set_getGammaRamp" {
|
test "set_getGammaRamp" {
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const monitor = getPrimary();
|
const monitor = getPrimary();
|
||||||
if (monitor) |m| {
|
if (monitor) |m| {
|
||||||
const ramp = m.getGammaRamp() catch |err| {
|
if (m.getGammaRamp()) |ramp| {
|
||||||
std.debug.print("can't get window position, wayland maybe? error={}\n", .{err});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set it to the exact same value; if we do otherwise an our tests fail it wouldn't call
|
// 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.
|
// terminate and our made-up gamma ramp would get stuck.
|
||||||
try m.setGammaRamp(ramp);
|
m.setGammaRamp(ramp);
|
||||||
|
|
||||||
// technically not needed here / noop because GLFW owns this gamma ramp.
|
// technically not needed here / noop because GLFW owns this gamma ramp.
|
||||||
defer ramp.deinit(allocator);
|
defer ramp.deinit(allocator);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
1471
src/Window.zig
1471
src/Window.zig
File diff suppressed because it is too large
Load diff
|
@ -12,21 +12,16 @@ const internal_debug = @import("internal_debug.zig");
|
||||||
///
|
///
|
||||||
/// @param[in] string A UTF-8 encoded string.
|
/// @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.
|
/// @pointer_lifetime The specified string is copied before this function returns.
|
||||||
///
|
///
|
||||||
/// @thread_safety This function must only be called from the main thread.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: clipboard, glfwGetClipboardString
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
c.glfwSetClipboardString(null, value);
|
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.
|
/// 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.
|
/// @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
|
/// @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
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: clipboard, glfwSetClipboardString
|
/// see also: clipboard, glfwSetClipboardString
|
||||||
pub inline fn getClipboardString() error{ FormatUnavailable, PlatformError }![:0]const u8 {
|
pub inline fn getClipboardString() ?[:0]const u8 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (c.glfwGetClipboardString(null)) |c_str| return std.mem.span(@ptrCast([*:0]const u8, c_str));
|
if (c.glfwGetClipboardString(null)) |c_str| return std.mem.span(@ptrCast([*:0]const u8, c_str));
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.FormatUnavailable, Error.PlatformError => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetClipboardString` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "setClipboardString" {
|
test "setClipboardString" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
try glfw.setClipboardString("hello mach");
|
glfw.setClipboardString("hello mach");
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getClipboardString" {
|
test "getClipboardString" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
_ = glfw.getClipboardString() catch |err| std.debug.print("can't get clipboard, not supported by OS? error={}\n", .{err});
|
_ = glfw.getClipboardString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,6 +190,13 @@ pub inline fn getError() Error!void {
|
||||||
return convertError(c.glfwGetError(null));
|
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.
|
/// 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
|
/// This function returns a UTF-8 encoded human-readable description of the last error that occured
|
||||||
|
|
42
src/key.zig
42
src/key.zig
|
@ -204,7 +204,8 @@ pub const Key = enum(c_int) {
|
||||||
/// @param[in] scancode The scancode of the key to query.
|
/// @param[in] scancode The scancode of the key to query.
|
||||||
/// @return The UTF-8 encoded, layout-specific name of the key, or null.
|
/// @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.
|
/// 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.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: input_key_name
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
const name_opt = cc.glfwGetKeyName(@enumToInt(self), @intCast(c_int, scancode));
|
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|
|
return if (name_opt) |name|
|
||||||
std.mem.span(@ptrCast([*:0]const u8, name))
|
std.mem.span(@ptrCast([*:0]const u8, name))
|
||||||
else
|
else
|
||||||
|
@ -237,36 +233,36 @@ pub const Key = enum(c_int) {
|
||||||
/// @param[in] key Any named key (see keys).
|
/// @param[in] key Any named key (see keys).
|
||||||
/// @return The platform-specific scancode for the key.
|
/// @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.
|
/// @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();
|
internal_debug.assertInitialized();
|
||||||
const scancode = cc.glfwGetKeyScancode(@enumToInt(self));
|
return 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;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
test "getName" {
|
test "getName" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
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" {
|
test "getScancode" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
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();
|
||||||
}
|
}
|
||||||
|
|
135
src/main.zig
135
src/main.zig
|
@ -12,7 +12,9 @@ pub const dont_care = c.GLFW_DONT_CARE;
|
||||||
/// may be useful.
|
/// may be useful.
|
||||||
pub const errors = @import("errors.zig");
|
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 setErrorCallback = errors.setErrorCallback;
|
||||||
pub const Error = errors.Error;
|
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
|
/// current environment if that category is still "C". This is because the "C" locale breaks
|
||||||
/// Unicode text input.
|
/// 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.
|
/// @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.toggleInitialized();
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
errdefer {
|
errdefer {
|
||||||
|
@ -100,12 +105,7 @@ pub inline fn init(hints: InitHints) error{ PlatformUnavailable, PlatformError }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.glfwInit() == c.GLFW_TRUE) return;
|
return c.glfwInit() == c.GLFW_TRUE;
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.PlatformUnavailable => |e| e,
|
|
||||||
Error.PlatformError => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement custom allocator support
|
// TODO: implement custom allocator support
|
||||||
|
@ -161,10 +161,6 @@ pub inline fn terminate() void {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
internal_debug.toggleInitialized();
|
internal_debug.toggleInitialized();
|
||||||
c.glfwTerminate();
|
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
|
/// 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))),
|
.Bool => c.glfwInitHint(@enumToInt(hint), @intCast(c_int, @boolToInt(value))),
|
||||||
else => @compileError("expected a int or bool, got " ++ @typeName(@TypeOf(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.
|
/// 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.
|
/// thread_safety: This function may be called from any thread.
|
||||||
pub fn getPlatform() PlatformType {
|
pub fn getPlatform() PlatformType {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const platform = @intToEnum(PlatformType, c.glfwGetPlatform());
|
return @intToEnum(PlatformType, c.glfwGetPlatform());
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
return platform;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the library includes support for the specified platform.
|
/// 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.
|
/// thread_safety: This function may be called from any thread.
|
||||||
pub fn platformSupported(platform: PlatformType) bool {
|
pub fn platformSupported(platform: PlatformType) bool {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const is_supported = c.glfwPlatformSupported(@enumToInt(platform));
|
return c.glfwPlatformSupported(@enumToInt(platform)) == c.GLFW_TRUE;
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.InvalidEnum => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
return is_supported == c.GLFW_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Processes all pending events.
|
/// Processes all pending events.
|
||||||
|
@ -365,21 +346,16 @@ pub fn platformSupported(platform: PlatformType) bool {
|
||||||
///
|
///
|
||||||
/// Event processing is not required for joystick input to work.
|
/// 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.
|
/// @reentrancy This function must not be called from a callback.
|
||||||
///
|
///
|
||||||
/// @thread_safety This function must only be called from the main thread.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: events, glfw.waitEvents, glfw.waitEventsTimeout
|
/// see also: events, glfw.waitEvents, glfw.waitEventsTimeout
|
||||||
pub inline fn pollEvents() error{PlatformError}!void {
|
pub inline fn pollEvents() void {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
c.glfwPollEvents();
|
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.
|
/// 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.
|
/// 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.
|
/// @reentrancy This function must not be called from a callback.
|
||||||
///
|
///
|
||||||
/// @thread_safety This function must only be called from the main thread.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: events, glfw.pollEvents, glfw.waitEventsTimeout
|
/// see also: events, glfw.pollEvents, glfw.waitEventsTimeout
|
||||||
pub inline fn waitEvents() error{PlatformError}!void {
|
pub inline fn waitEvents() void {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
c.glfwWaitEvents();
|
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.
|
/// 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.
|
/// @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.
|
/// @reentrancy This function must not be called from a callback.
|
||||||
///
|
///
|
||||||
/// @thread_safety This function must only be called from the main thread.
|
/// @thread_safety This function must only be called from the main thread.
|
||||||
///
|
///
|
||||||
/// see also: events, glfw.pollEvents, glfw.waitEvents
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
std.debug.assert(!std.math.isNan(timeout));
|
std.debug.assert(!std.math.isNan(timeout));
|
||||||
std.debug.assert(timeout >= 0);
|
std.debug.assert(timeout >= 0);
|
||||||
std.debug.assert(timeout <= std.math.f64_max);
|
std.debug.assert(timeout <= std.math.f64_max);
|
||||||
c.glfwWaitEventsTimeout(timeout);
|
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.
|
/// 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
|
/// This function posts an empty event from the current thread to the event queue, causing
|
||||||
/// glfw.waitEvents or glfw.waitEventsTimeout to return.
|
/// 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.
|
/// @thread_safety This function may be called from any thread.
|
||||||
///
|
///
|
||||||
/// see also: events, glfw.waitEvents, glfw.waitEventsTimeout
|
/// see also: events, glfw.waitEvents, glfw.waitEventsTimeout
|
||||||
pub inline fn postEmptyEvent() error{PlatformError}!void {
|
pub inline fn postEmptyEvent() void {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
c.glfwPostEmptyEvent();
|
c.glfwPostEmptyEvent();
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.PlatformError => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether raw mouse motion is supported.
|
/// 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
|
/// see also: raw_mouse_motion, glfw.setInputMode
|
||||||
pub inline fn rawMouseMotionSupported() bool {
|
pub inline fn rawMouseMotionSupported() bool {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const supported = c.glfwRawMouseMotionSupported();
|
return c.glfwRawMouseMotionSupported() == c.GLFW_TRUE;
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
return supported == c.GLFW_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn basicTest() !void {
|
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();
|
defer terminate();
|
||||||
|
|
||||||
const window = Window.create(640, 480, "GLFW example", null, null, .{}) catch |err| {
|
const window = Window.create(640, 480, "GLFW example", null, null, .{}) orelse {
|
||||||
// return without fail, because most of our CI environments are headless / we cannot open
|
std.log.err("failed to create window: {?s}", .{getErrorString()});
|
||||||
// windows on them.
|
std.process.exit(0); // note: we don't exit(1) here because our CI can't open windows
|
||||||
std.debug.print("note: failed to create window: {}\n", .{err});
|
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
defer window.destroy();
|
defer window.destroy();
|
||||||
|
|
||||||
|
@ -545,34 +502,54 @@ test "getVersionString" {
|
||||||
}
|
}
|
||||||
|
|
||||||
test "pollEvents" {
|
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();
|
defer terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
test "pollEvents" {
|
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();
|
defer terminate();
|
||||||
|
|
||||||
try pollEvents();
|
pollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
test "waitEventsTimeout" {
|
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();
|
defer terminate();
|
||||||
|
|
||||||
try waitEventsTimeout(0.25);
|
waitEventsTimeout(0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "postEmptyEvent_and_waitEvents" {
|
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();
|
defer terminate();
|
||||||
|
|
||||||
try postEmptyEvent();
|
postEmptyEvent();
|
||||||
try waitEvents();
|
waitEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
test "rawMouseMotionSupported" {
|
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();
|
defer terminate();
|
||||||
|
|
||||||
_ = rawMouseMotionSupported();
|
_ = rawMouseMotionSupported();
|
||||||
|
|
229
src/native.zig
229
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
|
/// return: The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`) of the
|
||||||
/// specified monitor.
|
/// specified monitor.
|
||||||
///
|
///
|
||||||
/// Possible errors include glfw.Error.NotInitalized.
|
|
||||||
///
|
|
||||||
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getWin32Adapter(monitor: Monitor) [*:0]const u8 {
|
pub fn getWin32Adapter(monitor: Monitor) [*:0]const u8 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetWin32Adapter(@ptrCast(*native.GLFWmonitor, monitor.handle))) |adapter| return adapter;
|
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
|
// `glfwGetWin32Adapter` returns `null` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,17 +75,12 @@ pub fn Native(comptime options: BackendOptions) type {
|
||||||
/// return: The UTF-8 encoded display device name (for example `\\.\DISPLAY1\Monitor0`)
|
/// return: The UTF-8 encoded display device name (for example `\\.\DISPLAY1\Monitor0`)
|
||||||
/// of the specified monitor.
|
/// of the specified monitor.
|
||||||
///
|
///
|
||||||
/// Possible errors include glfw.Error.NotInitalized.
|
|
||||||
///
|
|
||||||
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getWin32Monitor(monitor: Monitor) [*:0]const u8 {
|
pub fn getWin32Monitor(monitor: Monitor) [*:0]const u8 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetWin32Monitor(@ptrCast(*native.GLFWmonitor, monitor.handle))) |mon| return mon;
|
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
|
// `glfwGetWin32Monitor` returns `null` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,18 +94,13 @@ pub fn Native(comptime options: BackendOptions) type {
|
||||||
/// ```
|
/// ```
|
||||||
/// This DC is private and does not need to be released.
|
/// 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.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getWin32Window(window: Window) std.os.windows.HWND {
|
pub fn getWin32Window(window: Window) std.os.windows.HWND {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetWin32Window(@ptrCast(*native.GLFWwindow, window.handle))) |win|
|
if (native.glfwGetWin32Window(@ptrCast(*native.GLFWwindow, window.handle))) |win|
|
||||||
return @ptrCast(std.os.windows.HWND, 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
|
// `glfwGetWin32Window` returns `null` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,261 +114,181 @@ pub fn Native(comptime options: BackendOptions) type {
|
||||||
/// ```
|
/// ```
|
||||||
/// This DC is private and does not need to be released.
|
/// 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.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetWGLContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return context;
|
if (native.glfwGetWGLContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return context;
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.NoWindowContext => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetWGLContext` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `CGDirectDisplayID` of the specified monitor.
|
/// 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.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getCocoaMonitor(monitor: Monitor) u32 {
|
pub fn getCocoaMonitor(monitor: Monitor) u32 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const mon = native.glfwGetCocoaMonitor(@ptrCast(*native.GLFWmonitor, monitor.handle));
|
const mon = native.glfwGetCocoaMonitor(@ptrCast(*native.GLFWmonitor, monitor.handle));
|
||||||
if (mon != native.kCGNullDirectDisplay) return mon;
|
if (mon != native.kCGNullDirectDisplay) return mon;
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetCocoaMonitor` returns `kCGNullDirectDisplay` only for errors
|
// `glfwGetCocoaMonitor` returns `kCGNullDirectDisplay` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `NSWindow` of the specified window.
|
/// 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.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getCocoaWindow(window: Window) ?*anyopaque {
|
pub fn getCocoaWindow(window: Window) ?*anyopaque {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const win = native.glfwGetCocoaWindow(@ptrCast(*native.GLFWwindow, window.handle));
|
return native.glfwGetCocoaWindow(@ptrCast(*native.GLFWwindow, window.handle));
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
return win;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `NSWindow` of the specified window.
|
/// 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.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
const context = native.glfwGetNSGLContext(@ptrCast(*native.GLFWwindow, window.handle));
|
return native.glfwGetNSGLContext(@ptrCast(*native.GLFWwindow, window.handle));
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.NoWindowContext => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
return context;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `Display` used by GLFW.
|
/// 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.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getX11Display() *anyopaque {
|
pub fn getX11Display() *anyopaque {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetX11Display()) |display| return @ptrCast(*anyopaque, display);
|
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
|
// `glfwGetX11Display` returns `null` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `RRCrtc` of the specified monitor.
|
/// 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.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getX11Adapter(monitor: Monitor) u32 {
|
pub fn getX11Adapter(monitor: Monitor) u32 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const adapter = native.glfwGetX11Adapter(@ptrCast(*native.GLFWMonitor, monitor.handle));
|
const adapter = native.glfwGetX11Adapter(@ptrCast(*native.GLFWMonitor, monitor.handle));
|
||||||
if (adapter != 0) return adapter;
|
if (adapter != 0) return adapter;
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetX11Adapter` returns `0` only for errors
|
// `glfwGetX11Adapter` returns `0` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `RROutput` of the specified monitor.
|
/// 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.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getX11Monitor(monitor: Monitor) u32 {
|
pub fn getX11Monitor(monitor: Monitor) u32 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const mon = native.glfwGetX11Monitor(@ptrCast(*native.GLFWmonitor, monitor.handle));
|
const mon = native.glfwGetX11Monitor(@ptrCast(*native.GLFWmonitor, monitor.handle));
|
||||||
if (mon != 0) return mon;
|
if (mon != 0) return mon;
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetX11Monitor` returns `0` only for errors
|
// `glfwGetX11Monitor` returns `0` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `Window` of the specified window.
|
/// 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.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getX11Window(window: Window) u32 {
|
pub fn getX11Window(window: Window) u32 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const win = native.glfwGetX11Window(@ptrCast(*native.GLFWwindow, window.handle));
|
const win = native.glfwGetX11Window(@ptrCast(*native.GLFWwindow, window.handle));
|
||||||
if (win != 0) return @intCast(u32, win);
|
if (win != 0) return @intCast(u32, win);
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetX11Window` returns `0` only for errors
|
// `glfwGetX11Window` returns `0` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the current primary selection to the specified string.
|
/// 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.
|
/// The specified string is copied before this function returns.
|
||||||
///
|
///
|
||||||
/// thread_safety: This function must only be called from the main thread.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
native.glfwSetX11SelectionString(string);
|
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.
|
/// 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
|
/// 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
|
/// yourself. It is valid until the next call to getX11SelectionString or
|
||||||
/// setX11SelectionString, or until the library is terminated.
|
/// setX11SelectionString, or until the library is terminated.
|
||||||
///
|
///
|
||||||
/// thread_safety: This function must only be called from the main thread.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetX11SelectionString()) |str| return str;
|
if (native.glfwGetX11SelectionString()) |str| return str;
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.FormatUnavailable => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetX11SelectionString` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `GLXContext` of the specified window.
|
/// 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.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetGLXContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return @ptrCast(*anyopaque, context);
|
if (native.glfwGetGLXContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return @ptrCast(*anyopaque, context);
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.NoWindowContext => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetGLXContext` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `GLXWindow` of the specified window.
|
/// 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.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
const win = native.glfwGetGLXWindow(@ptrCast(*native.GLFWwindow, window.handle));
|
const win = native.glfwGetGLXWindow(@ptrCast(*native.GLFWwindow, window.handle));
|
||||||
if (win != 0) return @ptrCast(*anyopaque, win);
|
if (win != 0) return @ptrCast(*anyopaque, win);
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.NoWindowContext => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetGLXWindow` returns `0` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `*wl_display` used by GLFW.
|
/// 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.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getWaylandDisplay() *anyopaque {
|
pub fn getWaylandDisplay() *anyopaque {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetWaylandDisplay()) |display| return @ptrCast(*anyopaque, display);
|
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
|
// `glfwGetWaylandDisplay` returns `null` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `*wl_output` of the specified monitor.
|
/// 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.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getWaylandMonitor(monitor: Monitor) *anyopaque {
|
pub fn getWaylandMonitor(monitor: Monitor) *anyopaque {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetWaylandMonitor(@ptrCast(*native.GLFWmonitor, monitor.handle))) |mon| return @ptrCast(*anyopaque, mon);
|
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
|
// `glfwGetWaylandMonitor` returns `null` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `*wl_surface` of the specified window.
|
/// 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.
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
||||||
pub fn getWaylandWindow(window: Window) *anyopaque {
|
pub fn getWaylandWindow(window: Window) *anyopaque {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetWaylandWindow(@ptrCast(*native.GLFWwindow, window.handle))) |win| return @ptrCast(*anyopaque, win);
|
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
|
// `glfwGetWaylandWindow` returns `null` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `EGLDisplay` used by GLFW.
|
/// 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`
|
/// remark: Because EGL is initialized on demand, this function will return `EGL_NO_DISPLAY`
|
||||||
/// until the first context has been created via EGL.
|
/// until the first context has been created via EGL.
|
||||||
///
|
///
|
||||||
|
@ -392,30 +297,22 @@ pub fn Native(comptime options: BackendOptions) type {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const display = native.glfwGetEGLDisplay();
|
const display = native.glfwGetEGLDisplay();
|
||||||
if (display != native.EGL_NO_DISPLAY) return @ptrCast(*anyopaque, display);
|
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
|
// `glfwGetEGLDisplay` returns `EGL_NO_DISPLAY` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `EGLContext` of the specified window.
|
/// 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.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
const context = native.glfwGetEGLContext(@ptrCast(*native.GLFWwindow, window.handle));
|
const context = native.glfwGetEGLContext(@ptrCast(*native.GLFWwindow, window.handle));
|
||||||
if (context != native.EGL_NO_CONTEXT) return @ptrCast(*anyopaque, context);
|
if (context != native.EGL_NO_CONTEXT) return @ptrCast(*anyopaque, context);
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.NoWindowContext => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetEGLContext` returns `EGL_NO_CONTEXT` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `EGLSurface` of the specified window.
|
/// 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.
|
/// Possible errors include glfw.Error.NotInitalized and glfw.Error.NoWindowContext.
|
||||||
///
|
///
|
||||||
/// thread_safety This function may be called from any thread. Access is not synchronized.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
const surface = native.glfwGetEGLSurface(@ptrCast(*native.GLFWwindow, window.handle));
|
const surface = native.glfwGetEGLSurface(@ptrCast(*native.GLFWwindow, window.handle));
|
||||||
if (surface != native.EGL_NO_SURFACE) return @ptrCast(*anyopaque, surface);
|
if (surface != native.EGL_NO_SURFACE) return @ptrCast(*anyopaque, surface);
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.NoWindowContext => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetEGLSurface` returns `EGL_NO_SURFACE` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const OSMesaColorBuffer = struct {
|
pub const OSMesaColorBuffer = struct {
|
||||||
|
@ -445,11 +336,11 @@ pub fn Native(comptime options: BackendOptions) type {
|
||||||
|
|
||||||
/// Retrieves the color buffer associated with the specified window.
|
/// Retrieves the color buffer associated with the specified window.
|
||||||
///
|
///
|
||||||
/// Possible errors include glfw.Error.NotInitalized, glfw.Error.NoWindowContext
|
/// Possible errors include glfw.Error.NoWindowContext and glfw.Error.PlatformError.
|
||||||
/// 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.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
var buf: OSMesaColorBuffer = undefined;
|
var buf: OSMesaColorBuffer = undefined;
|
||||||
if (native.glfwGetOSMesaColorBuffer(
|
if (native.glfwGetOSMesaColorBuffer(
|
||||||
|
@ -459,13 +350,7 @@ pub fn Native(comptime options: BackendOptions) type {
|
||||||
&buf.format,
|
&buf.format,
|
||||||
&buf.buffer,
|
&buf.buffer,
|
||||||
) == native.GLFW_TRUE) return buf;
|
) == native.GLFW_TRUE) return buf;
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.PlatformError, Error.NoWindowContext => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetOSMesaColorBuffer` returns `GLFW_FALSE` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const OSMesaDepthBuffer = struct {
|
pub const OSMesaDepthBuffer = struct {
|
||||||
|
@ -477,11 +362,11 @@ pub fn Native(comptime options: BackendOptions) type {
|
||||||
|
|
||||||
/// Retrieves the depth buffer associated with the specified window.
|
/// Retrieves the depth buffer associated with the specified window.
|
||||||
///
|
///
|
||||||
/// Possible errors include glfw.Error.NotInitalized, glfw.Error.NoWindowContext
|
/// Possible errors include glfw.Error.NoWindowContext and glfw.Error.PlatformError.
|
||||||
/// 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.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
var buf: OSMesaDepthBuffer = undefined;
|
var buf: OSMesaDepthBuffer = undefined;
|
||||||
if (native.glfwGetOSMesaDepthBuffer(
|
if (native.glfwGetOSMesaDepthBuffer(
|
||||||
|
@ -491,30 +376,18 @@ pub fn Native(comptime options: BackendOptions) type {
|
||||||
&buf.bytes_per_value,
|
&buf.bytes_per_value,
|
||||||
&buf.buffer,
|
&buf.buffer,
|
||||||
) == native.GLFW_TRUE) return buf;
|
) == native.GLFW_TRUE) return buf;
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.PlatformError, Error.NoWindowContext => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetOSMesaDepthBuffer` returns `GLFW_FALSE` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the 'OSMesaContext' of the specified window.
|
/// 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.
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
if (native.glfwGetOSMesaContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return @ptrCast(*anyopaque, context);
|
if (native.glfwGetOSMesaContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return @ptrCast(*anyopaque, context);
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.NoWindowContext => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetOSMesaContext` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
112
src/opengl.zig
112
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
|
/// @param[in] window The window whose context to make current, or null to
|
||||||
/// detach the current context.
|
/// 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.
|
/// @thread_safety This function may be called from any thread.
|
||||||
///
|
///
|
||||||
/// see also: context_current, glfwGetCurrentContext
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
if (window) |w| c.glfwMakeContextCurrent(w.handle) else c.glfwMakeContextCurrent(null);
|
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.
|
/// 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.
|
/// 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.
|
/// @thread_safety This function may be called from any thread.
|
||||||
///
|
///
|
||||||
/// see also: context_current, glfwMakeContextCurrent
|
/// see also: context_current, glfwMakeContextCurrent
|
||||||
pub inline fn getCurrentContext() ?Window {
|
pub inline fn getCurrentContext() ?Window {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (c.glfwGetCurrentContext()) |handle| return Window.from(handle);
|
if (c.glfwGetCurrentContext()) |handle| return Window.from(handle);
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
return null;
|
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
|
/// @param[in] interval The minimum number of screen updates to wait for until the buffers are
|
||||||
/// swapped by glfw.swapBuffers.
|
/// 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
|
/// 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
|
/// 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.
|
/// @thread_safety This function may be called from any thread.
|
||||||
///
|
///
|
||||||
/// see also: buffer_swap, glfwSwapBuffers
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
c.glfwSwapInterval(@intCast(c_int, interval));
|
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.
|
/// 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.
|
/// @param[in] extension The ASCII encoded name of the extension.
|
||||||
/// @return `true` if the extension is available, or `false` otherwise.
|
/// @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.
|
/// and glfw.Error.PlatformError.
|
||||||
///
|
///
|
||||||
/// @thread_safety This function may be called from any thread.
|
/// @thread_safety This function may be called from any thread.
|
||||||
///
|
///
|
||||||
/// see also: context_glext, glfw.getProcAddress
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
|
|
||||||
std.debug.assert(extension.len != 0);
|
std.debug.assert(extension.len != 0);
|
||||||
std.debug.assert(extension[0] != 0);
|
std.debug.assert(extension[0] != 0);
|
||||||
|
|
||||||
const supported = c.glfwExtensionSupported(extension.ptr);
|
return c.glfwExtensionSupported(extension.ptr) == c.GLFW_TRUE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const builtin = @import("builtin");
|
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 {
|
pub fn getProcAddress(proc_name: [*:0]const u8) callconv(.C) ?GLProc {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (c.glfwGetProcAddress(proc_name)) |proc_address| return proc_address;
|
if (c.glfwGetProcAddress(proc_name)) |proc_address| return proc_address;
|
||||||
getError() catch |err| @panic(@errorName(err));
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
test "makeContextCurrent" {
|
test "makeContextCurrent" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| {
|
const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) orelse {
|
||||||
// return without fail, because most of our CI environments are headless / we cannot open
|
std.log.err("failed to create window: {?s}", .{glfw.getErrorString()});
|
||||||
// windows on them.
|
std.process.exit(1);
|
||||||
std.debug.print("note: failed to create window: {}\n", .{err});
|
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
defer window.destroy();
|
defer window.destroy();
|
||||||
|
|
||||||
try glfw.makeContextCurrent(window);
|
glfw.makeContextCurrent(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getCurrentContext" {
|
test "getCurrentContext" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const current_context = glfw.getCurrentContext();
|
const current_context = glfw.getCurrentContext();
|
||||||
|
@ -220,51 +202,57 @@ test "getCurrentContext" {
|
||||||
|
|
||||||
test "swapInterval" {
|
test "swapInterval" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| {
|
const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) orelse {
|
||||||
// return without fail, because most of our CI environments are headless / we cannot open
|
std.log.err("failed to create window: {?s}", .{glfw.getErrorString()});
|
||||||
// windows on them.
|
std.process.exit(1);
|
||||||
std.debug.print("note: failed to create window: {}\n", .{err});
|
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
defer window.destroy();
|
defer window.destroy();
|
||||||
|
|
||||||
try glfw.makeContextCurrent(window);
|
glfw.makeContextCurrent(window);
|
||||||
glfw.swapInterval(1) catch |err| std.debug.print("failed to set swap interval, error={}\n", .{err});
|
glfw.swapInterval(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getProcAddress" {
|
test "getProcAddress" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| {
|
const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) orelse {
|
||||||
// return without fail, because most of our CI environments are headless / we cannot open
|
std.log.err("failed to create window: {?s}", .{glfw.getErrorString()});
|
||||||
// windows on them.
|
std.process.exit(1);
|
||||||
std.debug.print("note: failed to create window: {}\n", .{err});
|
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
defer window.destroy();
|
defer window.destroy();
|
||||||
|
|
||||||
try glfw.makeContextCurrent(window);
|
glfw.makeContextCurrent(window);
|
||||||
_ = glfw.getProcAddress("foobar");
|
_ = glfw.getProcAddress("foobar");
|
||||||
}
|
}
|
||||||
|
|
||||||
test "extensionSupported" {
|
test "extensionSupported" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) catch |err| {
|
const window = Window.create(640, 480, "Hello, Zig!", null, null, .{}) orelse {
|
||||||
// return without fail, because most of our CI environments are headless / we cannot open
|
std.log.err("failed to create window: {?s}", .{glfw.getErrorString()});
|
||||||
// windows on them.
|
std.process.exit(1);
|
||||||
std.debug.print("note: failed to create window: {}\n", .{err});
|
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
defer window.destroy();
|
defer window.destroy();
|
||||||
|
|
||||||
try glfw.makeContextCurrent(window);
|
glfw.makeContextCurrent(window);
|
||||||
_ = glfw.extensionSupported("foobar") catch |err| std.debug.print("failed to check if extension supported, error={}\n", .{err});
|
_ = glfw.extensionSupported("foobar");
|
||||||
}
|
}
|
||||||
|
|
46
src/time.zig
46
src/time.zig
|
@ -31,11 +31,8 @@ pub inline fn getTime() f64 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const time = c.glfwGetTime();
|
const time = c.glfwGetTime();
|
||||||
if (time != 0) return time;
|
if (time != 0) return time;
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetTime` returns `0` only for errors
|
// `glfwGetTime` returns `0` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +46,7 @@ pub inline fn getTime() f64 {
|
||||||
///
|
///
|
||||||
/// @param[in] time The new value, in seconds.
|
/// @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
|
/// 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.
|
/// 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);
|
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.
|
/// Returns the current value of the raw timer.
|
||||||
|
@ -91,11 +83,8 @@ pub inline fn getTimerValue() u64 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const value = c.glfwGetTimerValue();
|
const value = c.glfwGetTimerValue();
|
||||||
if (value != 0) return value;
|
if (value != 0) return value;
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetTimerValue` returns `0` only for errors
|
// `glfwGetTimerValue` returns `0` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,17 +101,18 @@ pub inline fn getTimerFrequency() u64 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const frequency = c.glfwGetTimerFrequency();
|
const frequency = c.glfwGetTimerFrequency();
|
||||||
if (frequency != 0) return frequency;
|
if (frequency != 0) return frequency;
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetTimerFrequency` returns `0` only for errors
|
// `glfwGetTimerFrequency` returns `0` only for errors
|
||||||
|
// but the only potential error is unreachable (NotInitialized)
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getTime" {
|
test "getTime" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
_ = getTime();
|
_ = getTime();
|
||||||
|
@ -130,7 +120,11 @@ test "getTime" {
|
||||||
|
|
||||||
test "setTime" {
|
test "setTime" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
_ = glfw.setTime(1234);
|
_ = glfw.setTime(1234);
|
||||||
|
@ -138,7 +132,11 @@ test "setTime" {
|
||||||
|
|
||||||
test "getTimerValue" {
|
test "getTimerValue" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
_ = glfw.getTimerValue();
|
_ = glfw.getTimerValue();
|
||||||
|
@ -146,7 +144,11 @@ test "getTimerValue" {
|
||||||
|
|
||||||
test "getTimerFrequency" {
|
test "getTimerFrequency" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
_ = glfw.getTimerFrequency();
|
_ = glfw.getTimerFrequency();
|
||||||
|
|
|
@ -49,13 +49,10 @@ pub const VKGetInstanceProcAddr = *const fn (vk_instance: c.VkInstance, name: [*
|
||||||
///
|
///
|
||||||
/// @return `true` if Vulkan is minimally available, or `false` otherwise.
|
/// @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.
|
/// @thread_safety This function may be called from any thread.
|
||||||
pub inline fn vulkanSupported() bool {
|
pub inline fn vulkanSupported() bool {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const supported = c.glfwVulkanSupported();
|
const supported = c.glfwVulkanSupported();
|
||||||
getError() catch unreachable; // Only error 'GLFW_NOT_INITIALIZED' is impossible
|
|
||||||
return supported == c.GLFW_TRUE;
|
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,
|
/// 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.
|
/// 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
|
/// 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
|
/// 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.
|
/// @thread_safety This function may be called from any thread.
|
||||||
///
|
///
|
||||||
/// see also: vulkan_ext, glfwCreateWindowSurface
|
/// see also: vulkan_ext, glfwCreateWindowSurface
|
||||||
pub inline fn getRequiredInstanceExtensions() error{APIUnavailable}![][*:0]const u8 {
|
pub inline fn getRequiredInstanceExtensions() ?[][*:0]const u8 {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
var count: u32 = 0;
|
var count: u32 = 0;
|
||||||
if (c.glfwGetRequiredInstanceExtensions(&count)) |extensions| return @ptrCast([*][*:0]const u8, extensions)[0..count];
|
if (c.glfwGetRequiredInstanceExtensions(&count)) |extensions| return @ptrCast([*][*:0]const u8, extensions)[0..count];
|
||||||
getError() catch |err| return switch (err) {
|
return null;
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.APIUnavailable => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
// `glfwGetRequiredInstanceExtensions` returns `null` only for errors
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vulkan API function pointer type.
|
/// 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 {
|
pub fn getInstanceProcAddress(vk_instance: ?*anyopaque, proc_name: [*:0]const u8) callconv(.C) ?VKProc {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
if (c.glfwGetInstanceProcAddress(if (vk_instance) |v| @ptrCast(c.VkInstance, v) else null, proc_name)) |proc_address| return proc_address;
|
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;
|
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.
|
/// @param[in] queuefamily The index of the queue family to query.
|
||||||
/// @return `true` if the queue family supports presentation, or `false` otherwise.
|
/// @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
|
/// 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.
|
/// '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_instance: *anyopaque,
|
||||||
vk_physical_device: *anyopaque,
|
vk_physical_device: *anyopaque,
|
||||||
queue_family: u32,
|
queue_family: u32,
|
||||||
) error{ APIUnavailable, PlatformError }!bool {
|
) bool {
|
||||||
internal_debug.assertInitialized();
|
internal_debug.assertInitialized();
|
||||||
const v = c.glfwGetPhysicalDevicePresentationSupport(
|
return c.glfwGetPhysicalDevicePresentationSupport(
|
||||||
@ptrCast(c.VkInstance, vk_instance),
|
@ptrCast(c.VkInstance, vk_instance),
|
||||||
@ptrCast(c.VkPhysicalDevice, vk_physical_device),
|
@ptrCast(c.VkPhysicalDevice, vk_physical_device),
|
||||||
queue_family,
|
queue_family,
|
||||||
);
|
) == c.GLFW_TRUE;
|
||||||
getError() catch |err| return switch (err) {
|
|
||||||
Error.NotInitialized => unreachable,
|
|
||||||
Error.APIUnavailable, Error.PlatformError => |e| e,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
return v == c.GLFW_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a Vulkan surface for the specified window.
|
/// 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
|
/// @return `VkResult` type, `VK_SUCCESS` if successful, or a Vulkan error code if an
|
||||||
/// error occurred.
|
/// 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
|
/// 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
|
/// 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.
|
/// Vulkan objects, see the Vulkan specification.
|
||||||
///
|
///
|
||||||
/// see also: vulkan_surface, glfw.getRequiredInstanceExtensions
|
/// 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();
|
internal_debug.assertInitialized();
|
||||||
// zig-vulkan uses enums to represent opaque pointers:
|
// zig-vulkan uses enums to represent opaque pointers:
|
||||||
// pub const Instance = enum(usize) { null_handle = 0, _ };
|
// 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),
|
else => @ptrCast(c.VkInstance, vk_instance),
|
||||||
};
|
};
|
||||||
|
|
||||||
const v = c.glfwCreateWindowSurface(
|
return c.glfwCreateWindowSurface(
|
||||||
instance,
|
instance,
|
||||||
window.handle,
|
window.handle,
|
||||||
if (vk_allocation_callbacks == null) null else @ptrCast(*const c.VkAllocationCallbacks, @alignCast(@alignOf(c.VkAllocationCallbacks), vk_allocation_callbacks)),
|
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)),
|
@ptrCast(*c.VkSurfaceKHR, @alignCast(@alignOf(c.VkSurfaceKHR), vk_surface_khr)),
|
||||||
);
|
) == c.VK_SUCCESS;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "vulkanSupported" {
|
test "vulkanSupported" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
_ = glfw.vulkanSupported();
|
_ = glfw.vulkanSupported();
|
||||||
|
@ -277,15 +259,23 @@ test "vulkanSupported" {
|
||||||
|
|
||||||
test "getRequiredInstanceExtensions" {
|
test "getRequiredInstanceExtensions" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
_ = glfw.getRequiredInstanceExtensions() catch |err| std.debug.print("failed to get vulkan instance extensions, error={}\n", .{err});
|
_ = glfw.getRequiredInstanceExtensions();
|
||||||
}
|
}
|
||||||
|
|
||||||
test "getInstanceProcAddress" {
|
test "getInstanceProcAddress" {
|
||||||
const glfw = @import("main.zig");
|
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();
|
defer glfw.terminate();
|
||||||
|
|
||||||
// syntax check only, we don't have a real vulkan instance and so this function would panic.
|
// syntax check only, we don't have a real vulkan instance and so this function would panic.
|
||||||
|
|
Loading…
Add table
Reference in a new issue