mach: mouse cursor support (#352)

adds mouse cursor support for standard cursors

Co-authored-by: Stephen Gutekanst <stephen.gutekanst@gmail.com>
This commit is contained in:
David Vanderson 2022-06-16 00:53:55 -04:00 committed by GitHub
parent f5affbe7ae
commit 43bff35d2c
Failed to generate hash of commit
5 changed files with 87 additions and 0 deletions

View file

@ -87,6 +87,10 @@ pub fn getWindowSize(engine: *Engine) structs.Size {
return engine.internal.getWindowSize(); return engine.internal.getWindowSize();
} }
pub fn setMouseCursor(engine: *Engine, cursor: enums.MouseCursor) !void {
try engine.internal.setMouseCursor(cursor);
}
pub fn hasEvent(engine: *Engine) bool { pub fn hasEvent(engine: *Engine) bool {
return engine.internal.hasEvent(); return engine.internal.hasEvent();
} }

View file

@ -20,6 +20,19 @@ pub const VSyncMode = enum {
triple, triple,
}; };
pub const MouseCursor = enum {
arrow,
ibeam,
crosshair,
pointing_hand,
resize_ew,
resize_ns,
resize_nwse,
resize_nesw,
resize_all,
not_allowed,
};
pub const MouseButton = enum { pub const MouseButton = enum {
left, left,
right, right,

View file

@ -294,6 +294,24 @@ const mach = {
window.dispatchEvent(new Event("mach-close")); window.dispatchEvent(new Event("mach-close"));
}, },
machSetMouseCursor(cursor_ptr, len) {
let mach_name = mach.getString(cursor_ptr, len);
if (mach_name === 'arrow') document.body.style.cursor = 'default';
else if (mach_name === 'ibeam') document.body.style.cursor = 'text';
else if (mach_name === 'crosshair') document.body.style.cursor = 'crosshair';
else if (mach_name === 'pointing_hand') document.body.style.cursor = 'pointer';
else if (mach_name === 'resize_ew') document.body.style.cursor = 'ew-resize';
else if (mach_name === 'resize_ns') document.body.style.cursor = 'ns-resize';
else if (mach_name === 'resize_nwse') document.body.style.cursor = 'nwse-resize';
else if (mach_name === 'resize_nesw') document.body.style.cursor = 'nesw-resize';
else if (mach_name === 'resize_all') document.body.style.cursor = 'move';
else if (mach_name === 'not_allowed') document.body.style.cursor = 'not-allowed';
else {
console.log("machSetMouseCursor failed for " + mach_name);
}
},
machSetWaitEvent(timeout) { machSetWaitEvent(timeout) {
mach.wait_event_timeout = timeout; mach.wait_event_timeout = timeout;
}, },

View file

@ -20,6 +20,10 @@ pub const Platform = struct {
last_position: glfw.Window.Pos, last_position: glfw.Window.Pos,
wait_event_timeout: f64 = 0.0, wait_event_timeout: f64 = 0.0,
cursors: [@typeInfo(enums.MouseCursor).Enum.fields.len]?glfw.Cursor = undefined,
cursors_tried: [@typeInfo(enums.MouseCursor).Enum.fields.len]bool =
[_]bool{false} ** @typeInfo(enums.MouseCursor).Enum.fields.len,
native_instance: gpu.NativeInstance, native_instance: gpu.NativeInstance,
const EventQueue = std.TailQueue(structs.Event); const EventQueue = std.TailQueue(structs.Event);
@ -184,6 +188,14 @@ pub const Platform = struct {
}; };
} }
pub fn deinit(platform: *Platform) void {
for (platform.cursors) |glfw_cursor| {
if (glfw_cursor) |cur| {
cur.destroy();
}
}
}
fn pushEvent(platform: *Platform, event: structs.Event) void { fn pushEvent(platform: *Platform, event: structs.Event) void {
const node = platform.allocator.create(EventNode) catch unreachable; const node = platform.allocator.create(EventNode) catch unreachable;
node.* = .{ .data = event }; node.* = .{ .data = event };
@ -318,6 +330,39 @@ pub const Platform = struct {
return platform.last_window_size; return platform.last_window_size;
} }
pub fn setMouseCursor(platform: *Platform, cursor: enums.MouseCursor) !void {
// Try to create glfw standard cursor, but could fail. In the future
// we hope to provide custom backup images for these.
// See https://github.com/hexops/mach/pull/352 for more info
const enum_int = @enumToInt(cursor);
const tried = platform.cursors_tried[enum_int];
if (!tried) {
platform.cursors_tried[enum_int] = true;
platform.cursors[enum_int] = switch (cursor) {
.arrow => glfw.Cursor.createStandard(.arrow) catch null,
.ibeam => glfw.Cursor.createStandard(.ibeam) catch null,
.crosshair => glfw.Cursor.createStandard(.crosshair) catch null,
.pointing_hand => glfw.Cursor.createStandard(.pointing_hand) catch null,
.resize_ew => glfw.Cursor.createStandard(.resize_ew) catch null,
.resize_ns => glfw.Cursor.createStandard(.resize_ns) catch null,
.resize_nwse => glfw.Cursor.createStandard(.resize_nwse) catch null,
.resize_nesw => glfw.Cursor.createStandard(.resize_nesw) catch null,
.resize_all => glfw.Cursor.createStandard(.resize_all) catch null,
.not_allowed => glfw.Cursor.createStandard(.not_allowed) catch null,
};
}
if (platform.cursors[enum_int]) |cur| {
try platform.window.setCursor(cur);
} else {
// TODO: In the future we shouldn't hit this because we'll provide backup
// custom cursors.
// See https://github.com/hexops/mach/pull/352 for more info
std.debug.print("mach: setMouseCursor: {s} not yet supported\n", .{cursor});
}
}
pub fn hasEvent(platform: *Platform) bool { pub fn hasEvent(platform: *Platform) bool {
return platform.events.first != null; return platform.events.first != null;
} }
@ -496,6 +541,7 @@ pub fn main() !void {
const allocator = gpa.allocator(); const allocator = gpa.allocator();
var engine = try Engine.init(allocator); var engine = try Engine.init(allocator);
defer engine.internal.deinit();
var app: App = undefined; var app: App = undefined;
try app.init(&engine); try app.init(&engine);

View file

@ -14,6 +14,7 @@ const js = struct {
extern fn machCanvasGetWindowHeight(canvas: CanvasId) u32; extern fn machCanvasGetWindowHeight(canvas: CanvasId) u32;
extern fn machCanvasGetFramebufferWidth(canvas: CanvasId) u32; extern fn machCanvasGetFramebufferWidth(canvas: CanvasId) u32;
extern fn machCanvasGetFramebufferHeight(canvas: CanvasId) u32; extern fn machCanvasGetFramebufferHeight(canvas: CanvasId) u32;
extern fn machSetMouseCursor(cursor_name: [*]const u8, len: u32) void;
extern fn machEmitCloseEvent() void; extern fn machEmitCloseEvent() void;
extern fn machSetWaitEvent(timeout: f64) void; extern fn machSetWaitEvent(timeout: f64) void;
extern fn machHasEvent() bool; extern fn machHasEvent() bool;
@ -84,6 +85,11 @@ pub const Platform = struct {
return platform.last_window_size; return platform.last_window_size;
} }
pub fn setMouseCursor(_: *Platform, cursor: enums.MouseCursor) !void {
const cursor_name = @tagName(cursor);
js.machSetMouseCursor(cursor_name.ptr, cursor_name.len);
}
fn pollChanges(platform: *Platform) void { fn pollChanges(platform: *Platform) void {
const change_type = js.machChangeShift(); const change_type = js.machChangeShift();