diff --git a/glfw/src/Cursor.zig b/glfw/src/Cursor.zig index 95dac3a1..85850e6c 100644 --- a/glfw/src/Cursor.zig +++ b/glfw/src/Cursor.zig @@ -14,7 +14,9 @@ const Cursor = @This(); ptr: *c.GLFWcursor, -// Standard system cursor shapes. +/// Standard system cursor shapes. +/// +/// These are the standard cursor shapes that can be requested from the platform (window system). pub const Shape = enum(i32) { /// The regular arrow cursor shape. arrow = c.GLFW_ARROW_CURSOR, @@ -22,17 +24,68 @@ pub const Shape = enum(i32) { /// The text input I-beam cursor shape. ibeam = c.GLFW_IBEAM_CURSOR, - /// The crosshair shape. + /// The crosshair cursor shape. crosshair = c.GLFW_CROSSHAIR_CURSOR, - /// The hand shape. - hand = c.GLFW_HAND_CURSOR, + /// The pointing hand cursor shape. + /// + /// NOTE: This supersedes the old `hand` enum. + pointing_hand = c.GLFW_POINTING_HAND_CURSOR, - /// The horizontal resize arrow shape. - hresize = c.GLFW_HRESIZE_CURSOR, + /// The horizontal resize/move arrow shape. + /// + /// The horizontal resize/move arrow shape. This is usually a horizontal double-headed arrow. + // + // NOTE: This supersedes the old `hresize` enum. + resize_ew = c.GLFW_RESIZE_EW_CURSOR, - /// The vertical resize arrow shape. - vresize = c.GLFW_VRESIZE_CURSOR, + /// The vertical resize/move arrow shape. + /// + /// The vertical resize/move shape. This is usually a vertical double-headed arrow. + /// + /// NOTE: This supersedes the old `vresize` enum. + resize_ns = c.GLFW_RESIZE_NS_CURSOR, + + /// The top-left to bottom-right diagonal resize/move arrow shape. + /// + /// The top-left to bottom-right diagonal resize/move shape. This is usually a diagonal + /// double-headed arrow. + /// + /// macos: This shape is provided by a private system API and may fail CursorUnavailable in the + /// future. + /// + /// x11: This shape is provided by a newer standard not supported by all cursor themes. + /// + /// wayland: This shape is provided by a newer standard not supported by all cursor themes. + resize_nwse = c.GLFW_RESIZE_NWSE_CURSOR, + + /// The top-right to bottom-left diagonal resize/move arrow shape. + /// + /// The top-right to bottom-left diagonal resize/move shape. This is usually a diagonal + /// double-headed arrow. + /// + /// macos: This shape is provided by a private system API and may fail with CursorUnavailable + /// in the future. + /// + /// x11: This shape is provided by a newer standard not supported by all cursor themes. + /// + /// wayland: This shape is provided by a newer standard not supported by all cursor themes. + resize_nesw = c.GLFW_RESIZE_NESW_CURSOR, + + /// The omni-directional resize/move cursor shape. + /// + /// The omni-directional resize cursor/move shape. This is usually either a combined horizontal + /// and vertical double-headed arrow or a grabbing hand. + resize_all = c.GLFW_RESIZE_ALL_CURSOR, + + /// The operation-not-allowed shape. + /// + /// The operation-not-allowed shape. This is usually a circle with a diagonal line through it. + /// + /// x11: This shape is provided by a newer standard not supported by all cursor themes. + /// + /// wayland: This shape is provided by a newer standard not supported by all cursor themes. + not_allowed = c.GLFW_NOT_ALLOWED_CURSOR, }; /// Creates a custom cursor. @@ -53,20 +106,19 @@ pub const Shape = enum(i32) { /// @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. /// @return The handle of the created cursor. /// -/// Possible errors include glfw.Error.NotInitialized and glfw.Error.PlatformError. -/// /// @pointer_lifetime The specified image data is copied before this function returns. /// /// @thread_safety This function must only be called from the main thread. /// /// see also: cursor_object, glfw.Cursor.destroy, glfw.Cursor.createStandard -pub inline fn create(image: Image, xhot: i32, yhot: i32) error{PlatformError}!Cursor { +pub inline fn create(image: Image, xhot: i32, yhot: i32) error{ PlatformError, InvalidValue }!Cursor { internal_debug.assertInitialized(); const img = image.toC(); if (c.glfwCreateCursor(&img, @intCast(c_int, xhot), @intCast(c_int, yhot))) |cursor| return Cursor{ .ptr = cursor }; getError() catch |err| return switch (err) { Error.NotInitialized => unreachable, Error.PlatformError => |e| e, + Error.InvalidValue => |e| e, else => unreachable, }; // `glfwCreateCursor` returns `null` only for errors @@ -75,19 +127,41 @@ pub inline fn create(image: Image, xhot: i32, yhot: i32) error{PlatformError}!Cu /// Creates a cursor with a standard shape. /// -/// Returns a cursor with a standard shape (see shapes), that can be set for a window with glfw.Window.setCursor. +/// Returns a cursor with a standard shape, that can be set for a window with glfw.Window.setCursor. +/// The images for these cursors come from the system cursor theme and their exact appearance will +/// vary between platforms. /// -/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum and glfw.Error.PlatformError. +/// Most of these shapes are guaranteed to exist on every supported platform but a few may not be +/// present. See the table below for details. /// -/// @thread_safety This function must only be called from the main thread. +/// | Cursor shape | Windows | macOS | X11 | Wayland | +/// |------------------|---------|-----------------|-------------------|-------------------| +/// | `.arrow` | Yes | Yes | Yes | Yes | +/// | `.ibeam` | Yes | Yes | Yes | Yes | +/// | `.crosshair` | Yes | Yes | Yes | Yes | +/// | `.pointing_hand` | Yes | Yes | Yes | Yes | +/// | `.resize_ew` | Yes | Yes | Yes | Yes | +/// | `.resize_ns` | Yes | Yes | Yes | Yes | +/// | `.resize_nwse` | Yes | Yes1 | Maybe2 | Maybe2 | +/// | `.resize_nesw` | Yes | Yes1 | Maybe2 | Maybe2 | +/// | `.resize_all` | Yes | Yes | Yes | Yes | +/// | `.not_allowed` | Yes | Yes | Maybe2 | Maybe2 | +/// +/// 1. This uses a private system API and may fail in the future. +/// 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 +/// +/// thread_safety: This function must only be called from the main thread. /// /// see also: cursor_object, glfwCreateCursor -pub inline fn createStandard(shape: Shape) error{PlatformError}!Cursor { +pub inline fn createStandard(shape: Shape) error{ PlatformError, CursorUnavailable }!Cursor { internal_debug.assertInitialized(); if (c.glfwCreateStandardCursor(@intCast(c_int, @enumToInt(shape)))) |cursor| return Cursor{ .ptr = cursor }; getError() catch |err| return switch (err) { Error.NotInitialized => unreachable, Error.InvalidEnum => unreachable, + Error.CursorUnavailable => |e| e, Error.PlatformError => |e| e, else => unreachable, };