`getError()` now returns a struct `Error` containing `error_code` and
`description`. Rationale: retrieving the error code with the previous
implementation of `getError()` caused `getErrorString()` to return
null (the reverse is also true). The new implementation allows both
values to be retrieved at once.
The previous `getError()` function has been renamed to
`getErrorCode()` to reflect the fact that it returns a simple Zig
error rather than the `Error` struct. The error set returned by
`getErrorCode()` is now named `ErrorCode` rather than `Error`.
The behavior of the `getError()` family of functions clearing the
stored error is unchanged. However, since all code that used
`defer glfw.getError() catch {}` to explicitly clear errors had to be
refactored, a new `glfw.clearError()` function that returns void is
now available to make this operation more explicit.
Additionally, `mustGetError()` is now `mustGetErrorCode()`, and new
functions `mustGetError()` and `mustGetErrorString()` have been added
which wrap `getError()` and `getErrorString()` but panic if no error
is actually available.
Tests and API documentation had to be refactored across all of
`mach/glfw`. This commit also takes the opportunity to skip tests
involving window creation on CI so that other tests may still execute
normally.
391 lines
17 KiB
Zig
391 lines
17 KiB
Zig
//! Native access functions
|
|
const std = @import("std");
|
|
|
|
const Window = @import("Window.zig");
|
|
const Monitor = @import("Monitor.zig");
|
|
|
|
const internal_debug = @import("internal_debug.zig");
|
|
|
|
pub const BackendOptions = struct {
|
|
win32: bool = false,
|
|
wgl: bool = false,
|
|
cocoa: bool = false,
|
|
nsgl: bool = false,
|
|
x11: bool = false,
|
|
glx: bool = false,
|
|
wayland: bool = false,
|
|
egl: bool = false,
|
|
osmesa: bool = false,
|
|
};
|
|
|
|
/// This function returns a type which allows provides an interface to access
|
|
/// the native handles based on backends selected.
|
|
///
|
|
/// The available window API options are:
|
|
/// * win32
|
|
/// * cocoa
|
|
/// * x11
|
|
/// * wayland
|
|
///
|
|
/// The available context API options are:
|
|
///
|
|
/// * wgl
|
|
/// * nsgl
|
|
/// * glx
|
|
/// * egl
|
|
/// * osmesa
|
|
///
|
|
/// The chosen backends must match those the library was compiled for. Failure to do so
|
|
/// will cause a link-time error.
|
|
pub fn Native(comptime options: BackendOptions) type {
|
|
const native = @cImport({
|
|
@cDefine("GLFW_INCLUDE_VULKAN", "1");
|
|
@cInclude("GLFW/glfw3.h");
|
|
if (options.win32) @cDefine("GLFW_EXPOSE_NATIVE_WIN32", "1");
|
|
if (options.wgl) @cDefine("GLFW_EXPOSE_NATIVE_WGL", "1");
|
|
if (options.cocoa) @cDefine("GLFW_EXPOSE_NATIVE_COCOA", "1");
|
|
if (options.nsgl) @cDefine("GLFW_EXPOSE_NATIVE_NGSL", "1");
|
|
if (options.x11) @cDefine("GLFW_EXPOSE_NATIVE_X11", "1");
|
|
if (options.glx) @cDefine("GLFW_EXPOSE_NATIVE_GLX", "1");
|
|
if (options.wayland) @cDefine("GLFW_EXPOSE_NATIVE_WAYLAND", "1");
|
|
if (options.egl) @cDefine("GLFW_EXPOSE_NATIVE_EGL", "1");
|
|
if (options.osmesa) @cDefine("GLFW_EXPOSE_NATIVE_OSMESA", "1");
|
|
@cInclude("GLFW/glfw3native.h");
|
|
});
|
|
|
|
return struct {
|
|
/// Returns the adapter device name of the specified monitor.
|
|
///
|
|
/// return: The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`) of the
|
|
/// specified monitor.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getWin32Adapter(monitor: Monitor) [*:0]const u8 {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetWin32Adapter(@ptrCast(*native.GLFWmonitor, monitor.handle))) |adapter| return adapter;
|
|
// `glfwGetWin32Adapter` returns `null` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the display device name of the specified monitor.
|
|
///
|
|
/// return: The UTF-8 encoded display device name (for example `\\.\DISPLAY1\Monitor0`)
|
|
/// of the specified monitor.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getWin32Monitor(monitor: Monitor) [*:0]const u8 {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetWin32Monitor(@ptrCast(*native.GLFWmonitor, monitor.handle))) |mon| return mon;
|
|
// `glfwGetWin32Monitor` returns `null` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the `HWND` of the specified window.
|
|
///
|
|
/// The `HDC` associated with the window can be queried with the
|
|
/// [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc)
|
|
/// function.
|
|
/// ```
|
|
/// const dc = std.os.windows.user32.GetDC(native.getWin32Window(window));
|
|
/// ```
|
|
/// This DC is private and does not need to be released.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getWin32Window(window: Window) std.os.windows.HWND {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetWin32Window(@ptrCast(*native.GLFWwindow, window.handle))) |win|
|
|
return @ptrCast(std.os.windows.HWND, win);
|
|
// `glfwGetWin32Window` returns `null` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the `HGLRC` of the specified window.
|
|
///
|
|
/// The `HDC` associated with the window can be queried with the
|
|
/// [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc)
|
|
/// function.
|
|
/// ```
|
|
/// const dc = std.os.windows.user32.GetDC(native.getWin32Window(window));
|
|
/// ```
|
|
/// This DC is private and does not need to be released.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.NoWindowContext
|
|
/// null is returned in the event of an error.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getWGLContext(window: Window) ?std.os.windows.HGLRC {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetWGLContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return context;
|
|
return null;
|
|
}
|
|
|
|
/// Returns the `CGDirectDisplayID` of the specified monitor.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getCocoaMonitor(monitor: Monitor) u32 {
|
|
internal_debug.assertInitialized();
|
|
const mon = native.glfwGetCocoaMonitor(@ptrCast(*native.GLFWmonitor, monitor.handle));
|
|
if (mon != native.kCGNullDirectDisplay) return mon;
|
|
// `glfwGetCocoaMonitor` returns `kCGNullDirectDisplay` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the `NSWindow` of the specified window.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getCocoaWindow(window: Window) ?*anyopaque {
|
|
internal_debug.assertInitialized();
|
|
return native.glfwGetCocoaWindow(@ptrCast(*native.GLFWwindow, window.handle));
|
|
}
|
|
|
|
/// Returns the `NSWindow` of the specified window.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.NoWindowContext.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getNSGLContext(window: Window) u32 {
|
|
internal_debug.assertInitialized();
|
|
return native.glfwGetNSGLContext(@ptrCast(*native.GLFWwindow, window.handle));
|
|
}
|
|
|
|
/// Returns the `Display` used by GLFW.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getX11Display() *anyopaque {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetX11Display()) |display| return @ptrCast(*anyopaque, display);
|
|
// `glfwGetX11Display` returns `null` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the `RRCrtc` of the specified monitor.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getX11Adapter(monitor: Monitor) u32 {
|
|
internal_debug.assertInitialized();
|
|
const adapter = native.glfwGetX11Adapter(@ptrCast(*native.GLFWMonitor, monitor.handle));
|
|
if (adapter != 0) return adapter;
|
|
// `glfwGetX11Adapter` returns `0` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the `RROutput` of the specified monitor.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getX11Monitor(monitor: Monitor) u32 {
|
|
internal_debug.assertInitialized();
|
|
const mon = native.glfwGetX11Monitor(@ptrCast(*native.GLFWmonitor, monitor.handle));
|
|
if (mon != 0) return mon;
|
|
// `glfwGetX11Monitor` returns `0` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the `Window` of the specified window.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getX11Window(window: Window) u32 {
|
|
internal_debug.assertInitialized();
|
|
const win = native.glfwGetX11Window(@ptrCast(*native.GLFWwindow, window.handle));
|
|
if (win != 0) return @intCast(u32, win);
|
|
// `glfwGetX11Window` returns `0` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Sets the current primary selection to the specified string.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.PlatformError.
|
|
///
|
|
/// The specified string is copied before this function returns.
|
|
///
|
|
/// thread_safety: This function must only be called from the main thread.
|
|
pub fn setX11SelectionString(string: [*:0]const u8) void {
|
|
internal_debug.assertInitialized();
|
|
native.glfwSetX11SelectionString(string);
|
|
}
|
|
|
|
/// Returns the contents of the current primary selection as a string.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.PlatformError.
|
|
/// Returns null in the event of an error.
|
|
///
|
|
/// The returned string is allocated and freed by GLFW. You should not free it
|
|
/// yourself. It is valid until the next call to getX11SelectionString or
|
|
/// setX11SelectionString, or until the library is terminated.
|
|
///
|
|
/// thread_safety: This function must only be called from the main thread.
|
|
pub fn getX11SelectionString() ?[*:0]const u8 {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetX11SelectionString()) |str| return str;
|
|
return null;
|
|
}
|
|
|
|
/// Returns the `GLXContext` of the specified window.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.NoWindowContext.
|
|
/// Returns null in the event of an error.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getGLXContext(window: Window) ?*anyopaque {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetGLXContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return @ptrCast(*anyopaque, context);
|
|
return null;
|
|
}
|
|
|
|
/// Returns the `GLXWindow` of the specified window.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.NoWindowContext.
|
|
/// Returns null in the event of an error.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getGLXWindow(window: Window) ?*anyopaque {
|
|
internal_debug.assertInitialized();
|
|
const win = native.glfwGetGLXWindow(@ptrCast(*native.GLFWwindow, window.handle));
|
|
if (win != 0) return @ptrCast(*anyopaque, win);
|
|
return null;
|
|
}
|
|
|
|
/// Returns the `*wl_display` used by GLFW.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getWaylandDisplay() *anyopaque {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetWaylandDisplay()) |display| return @ptrCast(*anyopaque, display);
|
|
// `glfwGetWaylandDisplay` returns `null` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the `*wl_output` of the specified monitor.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getWaylandMonitor(monitor: Monitor) *anyopaque {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetWaylandMonitor(@ptrCast(*native.GLFWmonitor, monitor.handle))) |mon| return @ptrCast(*anyopaque, mon);
|
|
// `glfwGetWaylandMonitor` returns `null` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the `*wl_surface` of the specified window.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getWaylandWindow(window: Window) *anyopaque {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetWaylandWindow(@ptrCast(*native.GLFWwindow, window.handle))) |win| return @ptrCast(*anyopaque, win);
|
|
// `glfwGetWaylandWindow` returns `null` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the `EGLDisplay` used by GLFW.
|
|
///
|
|
/// remark: Because EGL is initialized on demand, this function will return `EGL_NO_DISPLAY`
|
|
/// until the first context has been created via EGL.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getEGLDisplay() *anyopaque {
|
|
internal_debug.assertInitialized();
|
|
const display = native.glfwGetEGLDisplay();
|
|
if (display != native.EGL_NO_DISPLAY) return @ptrCast(*anyopaque, display);
|
|
// `glfwGetEGLDisplay` returns `EGL_NO_DISPLAY` only for errors
|
|
// but the only potential error is unreachable (NotInitialized)
|
|
unreachable;
|
|
}
|
|
|
|
/// Returns the `EGLContext` of the specified window.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.NoWindowContext.
|
|
/// Returns null in the event of an error.
|
|
///
|
|
/// thread_safety This function may be called from any thread. Access is not synchronized.
|
|
pub fn getEGLContext(window: Window) ?*anyopaque {
|
|
internal_debug.assertInitialized();
|
|
const context = native.glfwGetEGLContext(@ptrCast(*native.GLFWwindow, window.handle));
|
|
if (context != native.EGL_NO_CONTEXT) return @ptrCast(*anyopaque, context);
|
|
return null;
|
|
}
|
|
|
|
/// Returns the `EGLSurface` of the specified window.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.NotInitalized and glfw.ErrorCode.NoWindowContext.
|
|
///
|
|
/// thread_safety This function may be called from any thread. Access is not synchronized.
|
|
pub fn getEGLSurface(window: Window) ?*anyopaque {
|
|
internal_debug.assertInitialized();
|
|
const surface = native.glfwGetEGLSurface(@ptrCast(*native.GLFWwindow, window.handle));
|
|
if (surface != native.EGL_NO_SURFACE) return @ptrCast(*anyopaque, surface);
|
|
return null;
|
|
}
|
|
|
|
pub const OSMesaColorBuffer = struct {
|
|
width: c_int,
|
|
height: c_int,
|
|
format: c_int,
|
|
buffer: *anyopaque,
|
|
};
|
|
|
|
/// Retrieves the color buffer associated with the specified window.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.NoWindowContext and glfw.ErrorCode.PlatformError.
|
|
/// Returns null in the event of an error.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getOSMesaColorBuffer(window: Window) ?OSMesaColorBuffer {
|
|
internal_debug.assertInitialized();
|
|
var buf: OSMesaColorBuffer = undefined;
|
|
if (native.glfwGetOSMesaColorBuffer(
|
|
@ptrCast(*native.GLFWwindow, window.handle),
|
|
&buf.width,
|
|
&buf.height,
|
|
&buf.format,
|
|
&buf.buffer,
|
|
) == native.GLFW_TRUE) return buf;
|
|
return null;
|
|
}
|
|
|
|
pub const OSMesaDepthBuffer = struct {
|
|
width: c_int,
|
|
height: c_int,
|
|
bytes_per_value: c_int,
|
|
buffer: *anyopaque,
|
|
};
|
|
|
|
/// Retrieves the depth buffer associated with the specified window.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.NoWindowContext and glfw.ErrorCode.PlatformError.
|
|
/// Returns null in the event of an error.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getOSMesaDepthBuffer(window: Window) ?OSMesaDepthBuffer {
|
|
internal_debug.assertInitialized();
|
|
var buf: OSMesaDepthBuffer = undefined;
|
|
if (native.glfwGetOSMesaDepthBuffer(
|
|
@ptrCast(*native.GLFWwindow, window.handle),
|
|
&buf.width,
|
|
&buf.height,
|
|
&buf.bytes_per_value,
|
|
&buf.buffer,
|
|
) == native.GLFW_TRUE) return buf;
|
|
return null;
|
|
}
|
|
|
|
/// Returns the 'OSMesaContext' of the specified window.
|
|
///
|
|
/// Possible errors include glfw.ErrorCode.NoWindowContext.
|
|
///
|
|
/// thread_safety: This function may be called from any thread. Access is not synchronized.
|
|
pub fn getOSMesaContext(window: Window) ?*anyopaque {
|
|
internal_debug.assertInitialized();
|
|
if (native.glfwGetOSMesaContext(@ptrCast(*native.GLFWwindow, window.handle))) |context| return @ptrCast(*anyopaque, context);
|
|
return null;
|
|
}
|
|
};
|
|
}
|