glfw: use comptime magic to remove InternalUserPointer and associated overhead

This commit is contained in:
Lee Cannon 2022-02-09 23:03:35 +00:00 committed by Stephen Gutekanst
parent 8d2a4cd8d2
commit 6f32a338c0
5 changed files with 330 additions and 262 deletions

View file

@ -352,12 +352,6 @@ pub const Event = enum(c_int) {
disconnected = c.GLFW_DISCONNECTED,
};
var _callback: ?fn (joystick: Joystick, event: Event) void = null;
fn callbackWrapper(jid: c_int, event: c_int) callconv(.C) void {
_callback.?(Joystick{ .jid = @intToEnum(Joystick.Id, jid) }, @intToEnum(Event, event));
}
/// Sets the joystick configuration callback.
///
/// This function sets the joystick configuration callback, or removes the currently set callback.
@ -379,10 +373,24 @@ fn callbackWrapper(jid: c_int, event: c_int) callconv(.C) void {
/// @thread_safety This function must only be called from the main thread.
///
/// see also: joystick_event
pub inline fn setCallback(callback: ?fn (joystick: Joystick, event: Event) void) void {
pub inline fn setCallback(comptime callback: ?fn (joystick: Joystick, event: Event) void) void {
internal_debug.assertInitialized();
_callback = callback;
_ = if (_callback != null) c.glfwSetJoystickCallback(callbackWrapper) else c.glfwSetJoystickCallback(null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn joystickCallbackWrapper(jid: c_int, event: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
Joystick{ .jid = @intToEnum(Joystick.Id, jid) },
@intToEnum(Event, event),
});
}
};
if (c.glfwSetJoystickCallback(CWrapper.joystickCallbackWrapper) != null) return;
} else {
if (c.glfwSetJoystickCallback(null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,

View file

@ -422,9 +422,6 @@ pub inline fn getPrimary() ?Monitor {
return null;
}
var callback_fn_ptr: ?usize = null;
var callback_data_ptr: ?usize = undefined;
/// Describes an event relating to a monitor.
pub const Event = enum(c_int) {
/// The device was connected.
@ -455,27 +452,24 @@ pub const Event = enum(c_int) {
/// @thread_safety This function must only be called from the main thread.
///
/// see also: monitor_event
pub inline fn setCallback(comptime Data: type, data: *Data, f: ?*const fn (monitor: Monitor, event: Event, data: *Data) void) void {
pub inline fn setCallback(comptime callback: ?fn (monitor: Monitor, event: Event) void) void {
internal_debug.assertInitialized();
if (f) |new_callback| {
callback_fn_ptr = @ptrToInt(new_callback);
callback_data_ptr = @ptrToInt(data);
const NewCallback = @TypeOf(new_callback);
_ = c.glfwSetMonitorCallback((struct {
fn callbackC(monitor: ?*c.GLFWmonitor, event: c_int) callconv(.C) void {
const callback = @intToPtr(NewCallback, callback_fn_ptr.?);
callback.*(
if (callback) |user_callback| {
const CWrapper = struct {
pub fn monitorCallbackWrapper(monitor: ?*c.GLFWmonitor, event: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
Monitor{ .handle = monitor.? },
@intToEnum(Event, event),
@intToPtr(*Data, callback_data_ptr.?),
);
});
}
}).callbackC);
};
if (c.glfwSetMonitorCallback(CWrapper.monitorCallbackWrapper) != null) return;
} else {
_ = c.glfwSetMonitorCallback(null);
callback_fn_ptr = null;
callback_data_ptr = null;
if (c.glfwSetMonitorCallback(null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
@ -576,14 +570,12 @@ test "setCallback" {
try glfw.init(.{});
defer glfw.terminate();
var custom_data: u32 = 5;
setCallback(u32, &custom_data, &(struct {
fn callback(monitor: Monitor, event: Event, data: *u32) void {
setCallback(struct {
fn callback(monitor: Monitor, event: Event) void {
_ = monitor;
_ = event;
_ = data;
}
}).callback);
}.callback);
}
test "getVideoModes" {

View file

@ -23,49 +23,10 @@ const Window = @This();
handle: *c.GLFWwindow,
/// Returns a Zig GLFW window from an underlying C GLFW window handle.
///
/// Note that the Zig GLFW library stores a custom user pointer in order to make callbacks nicer,
/// see glfw.Window.InternalUserPointer.
pub inline fn from(handle: *c.GLFWwindow) mem.Allocator.Error!Window {
internal_debug.assertInitialized();
const ptr = c.glfwGetWindowUserPointer(handle);
if (ptr == null) {
const internal = try std.heap.c_allocator.create(InternalUserPointer);
c.glfwSetWindowUserPointer(handle, @ptrCast(*anyopaque, internal));
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
pub inline fn from(handle: *c.GLFWwindow) Window {
return Window{ .handle = handle };
}
/// The actual type which is stored by the Zig GLFW library in glfwSetWindowUserPointer.
///
/// This is used to internally carry function callbacks with nicer Zig interfaces.
pub const InternalUserPointer = struct {
/// The actual user pointer that the user of the library wished to set via setUserPointer.
user_pointer: ?*anyopaque,
// Callbacks to be invoked by wrapper functions.
setPosCallback: ?fn (window: Window, xpos: i32, ypos: i32) void,
setSizeCallback: ?fn (window: Window, width: i32, height: i32) void,
setCloseCallback: ?fn (window: Window) void,
setRefreshCallback: ?fn (window: Window) void,
setFocusCallback: ?fn (window: Window, focused: bool) void,
setIconifyCallback: ?fn (window: Window, iconified: bool) void,
setMaximizeCallback: ?fn (window: Window, maximized: bool) void,
setFramebufferSizeCallback: ?fn (window: Window, width: u32, height: u32) void,
setContentScaleCallback: ?fn (window: Window, xscale: f32, yscale: f32) void,
setKeyCallback: ?fn (window: Window, key: Key, scancode: i32, action: Action, mods: Mods) void,
setCharCallback: ?fn (window: Window, codepoint: u21) void,
setMouseButtonCallback: ?fn (window: Window, button: MouseButton, action: Action, mods: Mods) void,
setCursorPosCallback: ?fn (window: Window, xpos: f64, ypos: f64) void,
setCursorEnterCallback: ?fn (window: Window, entered: bool) void,
setScrollCallback: ?fn (window: Window, xoffset: f64, yoffset: f64) void,
setDropCallback: ?fn (window: Window, paths: [][*:0]const u8) void,
};
/// Resets all window hints to their default values.
///
/// This function resets all window hints to their default values.
@ -418,7 +379,7 @@ pub inline fn create(
monitor: ?Monitor,
share: ?Window,
hints: Hints,
) (mem.Allocator.Error || error{ APIUnavailable, VersionUnavailable, FormatUnavailable, PlatformError })!Window {
) error{ APIUnavailable, VersionUnavailable, FormatUnavailable, PlatformError }!Window {
internal_debug.assertInitialized();
const ignore_hints_struct = if (comptime @import("builtin").is_test) testing_ignore_window_hints_struct else false;
if (!ignore_hints_struct) hints.set();
@ -468,9 +429,7 @@ var testing_ignore_window_hints_struct = if (@import("builtin").is_test) false e
/// see also: window_creation, glfw.Window.create
pub inline fn destroy(self: Window) void {
internal_debug.assertInitialized();
const internal = self.getInternal();
c.glfwDestroyWindow(self.handle);
std.heap.c_allocator.destroy(internal);
// Technically, glfwDestroyWindow could produce errors including glfw.Error.NotInitialized and
// glfw.Error.PlatformError. But how would anybody handle them? By creating a new window to
@ -1353,13 +1312,6 @@ pub inline fn setAttrib(self: Window, attrib: Attrib, value: bool) error{Platfor
};
}
pub inline fn getInternal(self: Window) *InternalUserPointer {
internal_debug.assertInitialized();
const ptr = c.glfwGetWindowUserPointer(self.handle);
if (ptr) |p| return @ptrCast(*InternalUserPointer, @alignCast(@alignOf(*InternalUserPointer), p));
@panic("expected GLFW window user pointer to be *glfw.Window.InternalUserPointer, found null");
}
/// Sets the user pointer of the specified window.
///
/// This function sets the user-defined pointer of the specified window. The current value is
@ -1370,8 +1322,11 @@ pub inline fn getInternal(self: Window) *InternalUserPointer {
/// see also: window_userptr, glfw.Window.getUserPointer
pub inline fn setUserPointer(self: Window, pointer: ?*anyopaque) void {
internal_debug.assertInitialized();
const internal = self.getInternal();
internal.user_pointer = pointer;
c.glfwSetWindowUserPointer(self.handle, pointer);
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
/// Returns the user pointer of the specified window.
@ -1384,18 +1339,14 @@ pub inline fn setUserPointer(self: Window, pointer: ?*anyopaque) void {
/// see also: window_userptr, glfw.Window.setUserPointer
pub inline fn getUserPointer(self: Window, comptime T: type) ?*T {
internal_debug.assertInitialized();
const internal = self.getInternal();
if (internal.user_pointer) |p| return @ptrCast(?*T, @alignCast(@alignOf(T), p));
if (c.glfwGetWindowUserPointer(self.handle)) |user_pointer| return @ptrCast(?*T, @alignCast(@alignOf(T), user_pointer));
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
return null;
}
fn setPosCallbackWrapper(handle: ?*c.GLFWwindow, xpos: c_int, ypos: c_int) callconv(.C) void {
internal_debug.assertInitialized();
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setPosCallback.?(window, @intCast(i32, xpos), @intCast(i32, ypos));
}
/// Sets the position callback for the specified window.
///
/// This function sets the position callback of the specified window, which is called when the
@ -1416,24 +1367,31 @@ fn setPosCallbackWrapper(handle: ?*c.GLFWwindow, xpos: c_int, ypos: c_int) callc
/// @thread_safety This function must only be called from the main thread.
///
/// see also: window_pos
pub inline fn setPosCallback(self: Window, callback: ?fn (window: Window, xpos: i32, ypos: i32) void) void {
pub inline fn setPosCallback(self: Window, comptime callback: ?fn (window: Window, xpos: i32, ypos: i32) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setPosCallback = callback;
_ = c.glfwSetWindowPosCallback(self.handle, if (callback != null) setPosCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn posCallbackWrapper(handle: ?*c.GLFWwindow, xpos: c_int, ypos: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
@intCast(i32, xpos),
@intCast(i32, ypos),
});
}
};
if (c.glfwSetWindowPosCallback(self.handle, CWrapper.posCallbackWrapper) != null) return;
} else {
if (c.glfwSetWindowPosCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setSizeCallbackWrapper(handle: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
internal_debug.assertInitialized();
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setSizeCallback.?(window, @intCast(i32, width), @intCast(i32, height));
}
/// Sets the size callback for the specified window.
///
/// This function sets the size callback of the specified window, which is called when the window
@ -1447,24 +1405,31 @@ fn setSizeCallbackWrapper(handle: ?*c.GLFWwindow, width: c_int, height: c_int) c
/// @thread_safety This function must only be called from the main thread.
///
/// see also: window_size
pub inline fn setSizeCallback(self: Window, callback: ?fn (window: Window, width: i32, height: i32) void) void {
pub inline fn setSizeCallback(self: Window, comptime callback: ?fn (window: Window, width: i32, height: i32) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setSizeCallback = callback;
_ = c.glfwSetWindowSizeCallback(self.handle, if (callback != null) setSizeCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn sizeCallbackWrapper(handle: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
@intCast(i32, width),
@intCast(i32, height),
});
}
};
if (c.glfwSetWindowSizeCallback(self.handle, CWrapper.sizeCallbackWrapper) != null) return;
} else {
if (c.glfwSetWindowSizeCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setCloseCallbackWrapper(handle: ?*c.GLFWwindow) callconv(.C) void {
internal_debug.assertInitialized();
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setCloseCallback.?(window);
}
/// Sets the close callback for the specified window.
///
/// This function sets the close callback of the specified window, which is called when the user
@ -1486,23 +1451,29 @@ fn setCloseCallbackWrapper(handle: ?*c.GLFWwindow) callconv(.C) void {
/// @thread_safety This function must only be called from the main thread.
///
/// see also: window_close
pub inline fn setCloseCallback(self: Window, callback: ?fn (window: Window) void) void {
pub inline fn setCloseCallback(self: Window, comptime callback: ?fn (window: Window) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setCloseCallback = callback;
_ = c.glfwSetWindowCloseCallback(self.handle, if (callback != null) setCloseCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn closeCallbackWrapper(handle: ?*c.GLFWwindow) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
});
}
};
if (c.glfwSetWindowCloseCallback(self.handle, CWrapper.closeCallbackWrapper) != null) return;
} else {
if (c.glfwSetWindowCloseCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setRefreshCallbackWrapper(handle: ?*c.GLFWwindow) callconv(.C) void {
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setRefreshCallback.?(window);
}
/// Sets the refresh callback for the specified window.
///
/// This function sets the refresh callback of the specified window, which is
@ -1522,24 +1493,29 @@ fn setRefreshCallbackWrapper(handle: ?*c.GLFWwindow) callconv(.C) void {
/// @thread_safety This function must only be called from the main thread.
///
/// see also: window_refresh
pub inline fn setRefreshCallback(self: Window, callback: ?fn (window: Window) void) void {
pub inline fn setRefreshCallback(self: Window, comptime callback: ?fn (window: Window) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setRefreshCallback = callback;
_ = c.glfwSetWindowRefreshCallback(self.handle, if (callback != null) setRefreshCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn refreshCallbackWrapper(handle: ?*c.GLFWwindow) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
});
}
};
if (c.glfwSetWindowRefreshCallback(self.handle, CWrapper.refreshCallbackWrapper) != null) return;
} else {
if (c.glfwSetWindowRefreshCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setFocusCallbackWrapper(handle: ?*c.GLFWwindow, focused: c_int) callconv(.C) void {
internal_debug.assertInitialized();
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setFocusCallback.?(window, if (focused == c.GLFW_TRUE) true else false);
}
/// Sets the focus callback for the specified window.
///
/// This function sets the focus callback of the specified window, which is
@ -1560,24 +1536,30 @@ fn setFocusCallbackWrapper(handle: ?*c.GLFWwindow, focused: c_int) callconv(.C)
/// @thread_safety This function must only be called from the main thread.
///
/// see also: window_focus
pub inline fn setFocusCallback(self: Window, callback: ?fn (window: Window, focused: bool) void) void {
pub inline fn setFocusCallback(self: Window, comptime callback: ?fn (window: Window, focused: bool) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setFocusCallback = callback;
_ = c.glfwSetWindowFocusCallback(self.handle, if (callback != null) setFocusCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn focusCallbackWrapper(handle: ?*c.GLFWwindow, focused: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
focused == c.GLFW_TRUE,
});
}
};
if (c.glfwSetWindowFocusCallback(self.handle, CWrapper.focusCallbackWrapper) != null) return;
} else {
if (c.glfwSetWindowFocusCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setIconifyCallbackWrapper(handle: ?*c.GLFWwindow, iconified: c_int) callconv(.C) void {
internal_debug.assertInitialized();
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setIconifyCallback.?(window, if (iconified == c.GLFW_TRUE) true else false);
}
/// Sets the iconify callback for the specified window.
///
/// This function sets the iconification callback of the specified window, which
@ -1596,24 +1578,30 @@ fn setIconifyCallbackWrapper(handle: ?*c.GLFWwindow, iconified: c_int) callconv(
/// @thread_safety This function must only be called from the main thread.
///
/// see also: window_iconify
pub inline fn setIconifyCallback(self: Window, callback: ?fn (window: Window, iconified: bool) void) void {
pub inline fn setIconifyCallback(self: Window, comptime callback: ?fn (window: Window, iconified: bool) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setIconifyCallback = callback;
_ = c.glfwSetWindowIconifyCallback(self.handle, if (callback != null) setIconifyCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn iconifyCallbackWrapper(handle: ?*c.GLFWwindow, iconified: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
iconified == c.GLFW_TRUE,
});
}
};
if (c.glfwSetWindowIconifyCallback(self.handle, CWrapper.iconifyCallbackWrapper) != null) return;
} else {
if (c.glfwSetWindowIconifyCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setMaximizeCallbackWrapper(handle: ?*c.GLFWwindow, maximized: c_int) callconv(.C) void {
internal_debug.assertInitialized();
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setMaximizeCallback.?(window, if (maximized == c.GLFW_TRUE) true else false);
}
/// Sets the maximize callback for the specified window.
///
/// This function sets the maximization callback of the specified window, which
@ -1630,24 +1618,30 @@ fn setMaximizeCallbackWrapper(handle: ?*c.GLFWwindow, maximized: c_int) callconv
///
/// see also: window_maximize
// GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun callback);
pub inline fn setMaximizeCallback(self: Window, callback: ?fn (window: Window, maximized: bool) void) void {
pub inline fn setMaximizeCallback(self: Window, comptime callback: ?fn (window: Window, maximized: bool) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setMaximizeCallback = callback;
_ = c.glfwSetWindowMaximizeCallback(self.handle, if (callback != null) setMaximizeCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn maximizeCallbackWrapper(handle: ?*c.GLFWwindow, maximized: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
maximized == c.GLFW_TRUE,
});
}
};
if (c.glfwSetWindowMaximizeCallback(self.handle, CWrapper.maximizeCallbackWrapper) != null) return;
} else {
if (c.glfwSetWindowMaximizeCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setFramebufferSizeCallbackWrapper(handle: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
internal_debug.assertInitialized();
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setFramebufferSizeCallback.?(window, @intCast(u32, width), @intCast(u32, height));
}
/// Sets the framebuffer resize callback for the specified window.
///
/// This function sets the framebuffer resize callback of the specified window,
@ -1664,24 +1658,31 @@ fn setFramebufferSizeCallbackWrapper(handle: ?*c.GLFWwindow, width: c_int, heigh
/// @thread_safety This function must only be called from the main thread.
///
/// see also: window_fbsize
pub inline fn setFramebufferSizeCallback(self: Window, callback: ?fn (window: Window, width: u32, height: u32) void) void {
pub inline fn setFramebufferSizeCallback(self: Window, comptime callback: ?fn (window: Window, width: u32, height: u32) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setFramebufferSizeCallback = callback;
_ = c.glfwSetFramebufferSizeCallback(self.handle, if (callback != null) setFramebufferSizeCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn framebufferSizeCallbackWrapper(handle: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
@intCast(u32, width),
@intCast(u32, height),
});
}
};
if (c.glfwSetFramebufferSizeCallback(self.handle, CWrapper.framebufferSizeCallbackWrapper) != null) return;
} else {
if (c.glfwSetFramebufferSizeCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setContentScaleCallbackWrapper(handle: ?*c.GLFWwindow, xscale: f32, yscale: f32) callconv(.C) void {
internal_debug.assertInitialized();
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setContentScaleCallback.?(window, xscale, yscale);
}
/// Sets the window content scale callback for the specified window.
///
/// This function sets the window content scale callback of the specified window,
@ -1698,11 +1699,25 @@ fn setContentScaleCallbackWrapper(handle: ?*c.GLFWwindow, xscale: f32, yscale: f
/// @thread_safety This function must only be called from the main thread.
///
/// see also: window_scale, glfw.Window.getContentScale
pub inline fn setContentScaleCallback(self: Window, callback: ?fn (window: Window, xscale: f32, yscale: f32) void) void {
pub inline fn setContentScaleCallback(self: Window, comptime callback: ?fn (window: Window, xscale: f32, yscale: f32) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setContentScaleCallback = callback;
_ = c.glfwSetWindowContentScaleCallback(self.handle, if (callback != null) setContentScaleCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn windowScaleCallbackWrapper(handle: ?*c.GLFWwindow, xscale: f32, yscale: f32) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
xscale,
yscale,
});
}
};
if (c.glfwSetWindowContentScaleCallback(self.handle, CWrapper.windowScaleCallbackWrapper) != null) return;
} else {
if (c.glfwSetWindowContentScaleCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
@ -2044,12 +2059,6 @@ pub inline fn setCursor(self: Window, cursor: Cursor) error{PlatformError}!void
};
}
fn setKeyCallbackWrapper(handle: ?*c.GLFWwindow, key: c_int, scancode: c_int, action: c_int, mods: c_int) callconv(.C) void {
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setKeyCallback.?(window, @intToEnum(Key, key), @intCast(i32, scancode), @intToEnum(Action, action), Mods.fromInt(mods));
}
/// Sets the key callback.
///
/// This function sets the key callback of the specified window, which is called when a key is
@ -2084,23 +2093,33 @@ fn setKeyCallbackWrapper(handle: ?*c.GLFWwindow, key: c_int, scancode: c_int, ac
/// @thread_safety This function must only be called from the main thread.
///
/// see also: input_key
pub inline fn setKeyCallback(self: Window, callback: ?fn (window: Window, key: Key, scancode: i32, action: Action, mods: Mods) void) void {
pub inline fn setKeyCallback(self: Window, comptime callback: ?fn (window: Window, key: Key, scancode: i32, action: Action, mods: Mods) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setKeyCallback = callback;
_ = c.glfwSetKeyCallback(self.handle, if (callback != null) setKeyCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn keyCallbackWrapper(handle: ?*c.GLFWwindow, key: c_int, scancode: c_int, action: c_int, mods: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
@intToEnum(Key, key),
@intCast(i32, scancode),
@intToEnum(Action, action),
Mods.fromInt(mods),
});
}
};
if (c.glfwSetKeyCallback(self.handle, CWrapper.keyCallbackWrapper) != null) return;
} else {
if (c.glfwSetKeyCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setCharCallbackWrapper(handle: ?*c.GLFWwindow, codepoint: c_uint) callconv(.C) void {
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setCharCallback.?(window, @intCast(u21, codepoint));
}
/// Sets the Unicode character callback.
///
/// This function sets the character callback of the specified window, which is called when a
@ -2125,23 +2144,30 @@ fn setCharCallbackWrapper(handle: ?*c.GLFWwindow, codepoint: c_uint) callconv(.C
/// @thread_safety This function must only be called from the main thread.
///
/// see also: input_char
pub inline fn setCharCallback(self: Window, callback: ?fn (window: Window, codepoint: u21) void) void {
pub inline fn setCharCallback(self: Window, comptime callback: ?fn (window: Window, codepoint: u21) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setCharCallback = callback;
_ = c.glfwSetCharCallback(self.handle, if (callback != null) setCharCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn charCallbackWrapper(handle: ?*c.GLFWwindow, codepoint: c_uint) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
@intCast(u21, codepoint),
});
}
};
if (c.glfwSetCharCallback(self.handle, CWrapper.charCallbackWrapper) != null) return;
} else {
if (c.glfwSetCharCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setMouseButtonCallbackWrapper(handle: ?*c.GLFWwindow, button: c_int, action: c_int, mods: c_int) callconv(.C) void {
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setMouseButtonCallback.?(window, @intToEnum(MouseButton, button), @intToEnum(Action, action), Mods.fromInt(mods));
}
/// Sets the mouse button callback.
///
/// This function sets the mouse button callback of the specified window, which is called when a
@ -2164,23 +2190,32 @@ fn setMouseButtonCallbackWrapper(handle: ?*c.GLFWwindow, button: c_int, action:
/// @thread_safety This function must only be called from the main thread.
///
/// see also: input_mouse_button
pub inline fn setMouseButtonCallback(self: Window, callback: ?fn (window: Window, button: MouseButton, action: Action, mods: Mods) void) void {
pub inline fn setMouseButtonCallback(self: Window, comptime callback: ?fn (window: Window, button: MouseButton, action: Action, mods: Mods) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setMouseButtonCallback = callback;
_ = c.glfwSetMouseButtonCallback(self.handle, if (callback != null) setMouseButtonCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn mouseButtonCallbackWrapper(handle: ?*c.GLFWwindow, button: c_int, action: c_int, mods: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
@intToEnum(MouseButton, button),
@intToEnum(Action, action),
Mods.fromInt(mods),
});
}
};
if (c.glfwSetMouseButtonCallback(self.handle, CWrapper.mouseButtonCallbackWrapper) != null) return;
} else {
if (c.glfwSetMouseButtonCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setCursorPosCallbackWrapper(handle: ?*c.GLFWwindow, xpos: f64, ypos: f64) callconv(.C) void {
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setCursorPosCallback.?(window, xpos, ypos);
}
/// Sets the cursor position callback.
///
/// This function sets the cursor position callback of the specified window, which is called when
@ -2198,23 +2233,31 @@ fn setCursorPosCallbackWrapper(handle: ?*c.GLFWwindow, xpos: f64, ypos: f64) cal
/// @thread_safety This function must only be called from the main thread.
///
/// see also: cursor_pos
pub inline fn setCursorPosCallback(self: Window, callback: ?fn (window: Window, xpos: f64, ypos: f64) void) void {
pub inline fn setCursorPosCallback(self: Window, comptime callback: ?fn (window: Window, xpos: f64, ypos: f64) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setCursorPosCallback = callback;
_ = c.glfwSetCursorPosCallback(self.handle, if (callback != null) setCursorPosCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn cursorPosCallbackWrapper(handle: ?*c.GLFWwindow, xpos: f64, ypos: f64) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
xpos,
ypos,
});
}
};
if (c.glfwSetCursorPosCallback(self.handle, CWrapper.cursorPosCallbackWrapper) != null) return;
} else {
if (c.glfwSetCursorPosCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setCursorEnterCallbackWrapper(handle: ?*c.GLFWwindow, entered: c_int) callconv(.C) void {
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setCursorEnterCallback.?(window, entered == c.GLFW_TRUE);
}
/// Sets the cursor enter/leave callback.
///
/// This function sets the cursor boundary crossing callback of the specified window, which is
@ -2229,23 +2272,30 @@ fn setCursorEnterCallbackWrapper(handle: ?*c.GLFWwindow, entered: c_int) callcon
/// @thread_safety This function must only be called from the main thread.
///
/// see also: cursor_enter
pub inline fn setCursorEnterCallback(self: Window, callback: ?fn (window: Window, entered: bool) void) void {
pub inline fn setCursorEnterCallback(self: Window, comptime callback: ?fn (window: Window, entered: bool) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setCursorEnterCallback = callback;
_ = c.glfwSetCursorEnterCallback(self.handle, if (callback != null) setCursorEnterCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn cursorEnterCallbackWrapper(handle: ?*c.GLFWwindow, entered: c_int) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
entered == c.GLFW_TRUE,
});
}
};
if (c.glfwSetCursorEnterCallback(self.handle, CWrapper.cursorEnterCallbackWrapper) != null) return;
} else {
if (c.glfwSetCursorEnterCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setScrollCallbackWrapper(handle: ?*c.GLFWwindow, xoffset: f64, yoffset: f64) callconv(.C) void {
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setScrollCallback.?(window, xoffset, yoffset);
}
/// Sets the scroll callback.
///
/// This function sets the scroll callback of the specified window, which is called when a scrolling
@ -2264,23 +2314,31 @@ fn setScrollCallbackWrapper(handle: ?*c.GLFWwindow, xoffset: f64, yoffset: f64)
/// @thread_safety This function must only be called from the main thread.
///
/// see also: scrolling
pub inline fn setScrollCallback(self: Window, callback: ?fn (window: Window, xoffset: f64, yoffset: f64) void) void {
pub inline fn setScrollCallback(self: Window, comptime callback: ?fn (window: Window, xoffset: f64, yoffset: f64) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setScrollCallback = callback;
_ = c.glfwSetScrollCallback(self.handle, if (callback != null) setScrollCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn scrollCallbackWrapper(handle: ?*c.GLFWwindow, xoffset: f64, yoffset: f64) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
xoffset,
yoffset,
});
}
};
if (c.glfwSetScrollCallback(self.handle, CWrapper.scrollCallbackWrapper) != null) return;
} else {
if (c.glfwSetScrollCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
};
}
fn setDropCallbackWrapper(handle: ?*c.GLFWwindow, path_count: c_int, paths: [*c][*c]const u8) callconv(.C) void {
const window = from(handle.?) catch unreachable;
const internal = window.getInternal();
internal.setDropCallback.?(window, @ptrCast([*][*:0]const u8, paths)[0..@intCast(u32, path_count)]);
}
/// Sets the path drop callback.
///
/// This function sets the path drop callback of the specified window, which is called when one or
@ -2306,11 +2364,24 @@ fn setDropCallbackWrapper(handle: ?*c.GLFWwindow, path_count: c_int, paths: [*c]
/// @thread_safety This function must only be called from the main thread.
///
/// see also: path_drop
pub inline fn setDropCallback(self: Window, callback: ?fn (window: Window, paths: [][*:0]const u8) void) void {
pub inline fn setDropCallback(self: Window, comptime callback: ?fn (window: Window, paths: [][*:0]const u8) void) void {
internal_debug.assertInitialized();
var internal = self.getInternal();
internal.setDropCallback = callback;
_ = c.glfwSetDropCallback(self.handle, if (callback != null) setDropCallbackWrapper else null);
if (callback) |user_callback| {
const CWrapper = struct {
pub fn dropCallbackWrapper(handle: ?*c.GLFWwindow, path_count: c_int, paths: [*c][*c]const u8) callconv(.C) void {
@call(.{ .modifier = .always_inline }, user_callback, .{
from(handle.?),
@ptrCast([*][*:0]const u8, paths)[0..@intCast(u32, path_count)],
});
}
};
if (c.glfwSetDropCallback(self.handle, CWrapper.dropCallbackWrapper) != null) return;
} else {
if (c.glfwSetDropCallback(self.handle, null) != null) return;
}
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,

View file

@ -161,7 +161,7 @@ pub inline fn getError() Error!void {
pub fn setErrorCallback(comptime callback: ?fn (error_code: Error, description: [:0]const u8) void) void {
if (callback) |user_callback| {
const CWrapper = struct {
pub fn c_wrapper(err_int: c_int, c_description: [*c]const u8) callconv(.C) void {
pub fn errorCallbackWrapper(err_int: c_int, c_description: [*c]const u8) callconv(.C) void {
if (convertError(err_int)) |_| {
// This means the error was `GLFW_NO_ERROR`
return;
@ -171,7 +171,7 @@ pub fn setErrorCallback(comptime callback: ?fn (error_code: Error, description:
}
};
_ = c.glfwSetErrorCallback(CWrapper.c_wrapper);
_ = c.glfwSetErrorCallback(CWrapper.errorCallbackWrapper);
return;
}

View file

@ -53,9 +53,9 @@ pub inline fn makeContextCurrent(window: ?Window) error{ NoWindowContext, Platfo
/// @thread_safety This function may be called from any thread.
///
/// see also: context_current, glfwMakeContextCurrent
pub inline fn getCurrentContext() std.mem.Allocator.Error!?Window {
pub inline fn getCurrentContext() ?Window {
internal_debug.assertInitialized();
if (c.glfwGetCurrentContext()) |handle| return try Window.from(handle);
if (c.glfwGetCurrentContext()) |handle| return Window.from(handle);
getError() catch |err| return switch (err) {
Error.NotInitialized => unreachable,
else => unreachable,
@ -213,10 +213,7 @@ test "getCurrentContext" {
try glfw.init(.{});
defer glfw.terminate();
const current_context = glfw.getCurrentContext() catch |err| {
std.debug.print("can't get current context, error={}\n", .{err});
return;
};
const current_context = glfw.getCurrentContext();
std.debug.assert(current_context == null);
}