mach: flesh out mach.Event (#377)

* Flesh out mach.Event
This commit is contained in:
Jamie Brandon 2022-07-01 16:47:06 -07:00 committed by GitHub
parent da046f340d
commit 5bb740f89e
Failed to generate hash of commit
4 changed files with 218 additions and 66 deletions

View file

@ -196,27 +196,39 @@ const mach = {
canvas.addEventListener("contextmenu", (ev) => ev.preventDefault()); canvas.addEventListener("contextmenu", (ev) => ev.preventDefault());
canvas.addEventListener("keydown", (ev) => { canvas.addEventListener("keydown", (ev) => {
if (ev.repeat) {
mach.events.push(...[2, convertKeyCode(ev.code)]);
} else {
mach.events.push(...[1, convertKeyCode(ev.code)]); mach.events.push(...[1, convertKeyCode(ev.code)]);
}
}); });
canvas.addEventListener("keyup", (ev) => { canvas.addEventListener("keyup", (ev) => {
mach.events.push(...[2, convertKeyCode(ev.code)]); mach.events.push(...[3, convertKeyCode(ev.code)]);
}); });
canvas.addEventListener("mousemove", (ev) => { canvas.addEventListener("mousemove", (ev) => {
mach.events.push(...[3, ev.clientX, ev.clientY]); mach.events.push(...[4, ev.clientX, ev.clientY]);
}); });
canvas.addEventListener("mousedown", (ev) => { canvas.addEventListener("mousedown", (ev) => {
mach.events.push(...[4, ev.button]);
});
canvas.addEventListener("mouseup", (ev) => {
mach.events.push(...[5, ev.button]); mach.events.push(...[5, ev.button]);
}); });
canvas.addEventListener("mouseup", (ev) => {
mach.events.push(...[6, ev.button]);
});
canvas.addEventListener("wheel", (ev) => { canvas.addEventListener("wheel", (ev) => {
mach.events.push(...[6, ev.deltaX, ev.deltaY]); mach.events.push(...[7, ev.deltaX, ev.deltaY]);
});
canvas.addEventListener("focus", (ev) => {
mach.events.push(...[8]);
});
canvas.addEventListener("blur", (ev) => {
mach.events.push(...[9]);
}); });
canvas.addEventListener("mach-canvas-resize", (ev) => { canvas.addEventListener("mach-canvas-resize", (ev) => {

View file

@ -29,6 +29,8 @@ pub const Platform = struct {
native_instance: gpu.NativeInstance, native_instance: gpu.NativeInstance,
last_cursor_position: structs.WindowPos,
const EventQueue = std.TailQueue(structs.Event); const EventQueue = std.TailQueue(structs.Event);
const EventNode = EventQueue.Node; const EventNode = EventQueue.Node;
@ -180,6 +182,8 @@ pub const Platform = struct {
engine.current_desc = descriptor; engine.current_desc = descriptor;
engine.target_desc = descriptor; engine.target_desc = descriptor;
const cursor_pos = try window.getCursorPos();
return Platform{ return Platform{
.window = window, .window = window,
.backend_type = backend_type, .backend_type = backend_type,
@ -187,6 +191,10 @@ pub const Platform = struct {
.last_window_size = .{ .width = window_size.width, .height = window_size.height }, .last_window_size = .{ .width = window_size.width, .height = window_size.height },
.last_framebuffer_size = .{ .width = framebuffer_size.width, .height = framebuffer_size.height }, .last_framebuffer_size = .{ .width = framebuffer_size.width, .height = framebuffer_size.height },
.last_position = try window.getPos(), .last_position = try window.getPos(),
.last_cursor_position = .{
.x = cursor_pos.xpos,
.y = cursor_pos.ypos,
},
.native_instance = native_instance, .native_instance = native_instance,
}; };
} }
@ -210,37 +218,48 @@ pub const Platform = struct {
platform.window.setUserPointer(&platform.user_ptr); platform.window.setUserPointer(&platform.user_ptr);
const callback = struct { const key_callback = struct {
fn callback(window: glfw.Window, key: glfw.Key, scancode: i32, action: glfw.Action, mods: glfw.Mods) void { fn callback(window: glfw.Window, key: glfw.Key, scancode: i32, action: glfw.Action, mods: glfw.Mods) void {
const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform; const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform;
const key_event = structs.KeyEvent{
.key = toMachKey(key),
.mods = toMachMods(mods),
};
switch (action) { switch (action) {
.press => pf.pushEvent(.{ .press => pf.pushEvent(.{ .key_press = key_event }),
.key_press = .{ .repeat => pf.pushEvent(.{ .key_repeat = key_event }),
.key = toMachKey(key), .release => pf.pushEvent(.{ .key_release = key_event }),
},
}),
.release => pf.pushEvent(.{
.key_release = .{
.key = toMachKey(key),
},
}),
else => {},
} }
_ = scancode; _ = scancode;
_ = mods;
} }
}.callback; }.callback;
platform.window.setKeyCallback(callback); platform.window.setKeyCallback(key_callback);
const char_callback = struct {
fn callback(window: glfw.Window, codepoint: u21) void {
const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform;
pf.pushEvent(.{
.char_input = .{
.codepoint = codepoint,
},
});
}
}.callback;
platform.window.setCharCallback(char_callback);
const mouse_motion_callback = struct { const mouse_motion_callback = struct {
fn callback(window: glfw.Window, xpos: f64, ypos: f64) void { fn callback(window: glfw.Window, xpos: f64, ypos: f64) void {
const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform; const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform;
pf.pushEvent(.{ pf.last_cursor_position = .{
.mouse_motion = .{
.x = xpos, .x = xpos,
.y = ypos, .y = ypos,
};
pf.pushEvent(.{
.mouse_motion = .{
.pos = .{
.x = xpos,
.y = ypos,
},
}, },
}); });
} }
@ -250,17 +269,15 @@ pub const Platform = struct {
const mouse_button_callback = struct { const mouse_button_callback = struct {
fn callback(window: glfw.Window, button: glfw.mouse_button.MouseButton, action: glfw.Action, mods: glfw.Mods) void { fn callback(window: glfw.Window, button: glfw.mouse_button.MouseButton, action: glfw.Action, mods: glfw.Mods) void {
const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform; const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform;
const mouse_button_event = structs.MouseButtonEvent{
.button = toMachButton(button),
.pos = pf.last_cursor_position,
.mods = toMachMods(mods),
};
switch (action) { switch (action) {
.press => pf.pushEvent(.{ .press => pf.pushEvent(.{ .mouse_press = mouse_button_event }),
.mouse_press = .{
.button = toMachButton(button),
},
}),
.release => pf.pushEvent(.{ .release => pf.pushEvent(.{
.mouse_release = .{ .mouse_release = mouse_button_event,
.button = toMachButton(button),
},
}), }),
else => {}, else => {},
} }
@ -283,6 +300,22 @@ pub const Platform = struct {
}.callback; }.callback;
platform.window.setScrollCallback(scroll_callback); platform.window.setScrollCallback(scroll_callback);
const focus_callback = struct {
fn callback(window: glfw.Window, focused: bool) void {
const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform;
pf.pushEvent(if (focused) .focus_gained else .focus_lost);
}
}.callback;
platform.window.setFocusCallback(focus_callback);
const close_callback = struct {
fn callback(window: glfw.Window) void {
const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform;
pf.pushEvent(.closed);
}
}.callback;
platform.window.setCloseCallback(close_callback);
const size_callback = struct { const size_callback = struct {
fn callback(window: glfw.Window, width: i32, height: i32) void { fn callback(window: glfw.Window, width: i32, height: i32) void {
const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform; const pf = (window.getUserPointer(UserPtr) orelse unreachable).platform;
@ -526,6 +559,17 @@ pub const Platform = struct {
}; };
} }
fn toMachMods(mods: glfw.Mods) structs.KeyMods {
return .{
.shift = mods.shift,
.control = mods.control,
.alt = mods.alt,
.super = mods.super,
.caps_lock = mods.caps_lock,
.num_lock = mods.num_lock,
};
}
/// Default GLFW error handling callback /// Default GLFW error handling callback
fn errorCallback(error_code: glfw.Error, description: [:0]const u8) void { fn errorCallback(error_code: glfw.Error, description: [:0]const u8) void {
std.debug.print("glfw: {}: {s}\n", .{ error_code, description }); std.debug.print("glfw: {}: {s}\n", .{ error_code, description });

View file

@ -38,6 +38,9 @@ pub const Platform = struct {
last_window_size: structs.Size, last_window_size: structs.Size,
last_framebuffer_size: structs.Size, last_framebuffer_size: structs.Size,
last_cursor_position: structs.WindowPos,
last_key_mods: structs.KeyMods,
pub fn init(allocator: std.mem.Allocator, eng: *Engine) !Platform { pub fn init(allocator: std.mem.Allocator, eng: *Engine) !Platform {
var selector = [1]u8{0} ** 15; var selector = [1]u8{0} ** 15;
const id = js.machCanvasInit(&selector[0]); const id = js.machCanvasInit(&selector[0]);
@ -53,6 +56,20 @@ pub const Platform = struct {
.width = js.machCanvasGetFramebufferWidth(id), .width = js.machCanvasGetFramebufferWidth(id),
.height = js.machCanvasGetFramebufferHeight(id), .height = js.machCanvasGetFramebufferHeight(id),
}, },
// TODO initialize these properly
.last_cursor_position = .{
.x = 0,
.y = 0,
},
.last_key_mods = .{
.shift = false,
.control = false,
.alt = false,
.super = false,
.caps_lock = false,
.num_lock = false,
},
}; };
try platform.setOptions(eng.options); try platform.setOptions(eng.options);
@ -117,38 +134,93 @@ pub const Platform = struct {
return js.machHasEvent(); return js.machHasEvent();
} }
pub fn pollEvent(_: *Platform) ?structs.Event { pub fn pollEvent(platform: *Platform) ?structs.Event {
const event_type = js.machEventShift(); const event_type = js.machEventShift();
return switch (event_type) { return switch (event_type) {
1, 2 => key_down: {
const key = @intToEnum(enums.Key, js.machEventShift());
switch (key) {
.left_shift, .right_shift => platform.last_key_mods.shift = true,
.left_control, .right_control => platform.last_key_mods.control = true,
.left_alt, .right_alt => platform.last_key_mods.alt = true,
.left_super, .right_super => platform.last_key_mods.super = true,
.caps_lock => platform.last_key_mods.caps_lock = true,
.num_lock => platform.last_key_mods.num_lock = true,
else => {},
}
break :key_down switch (event_type) {
1 => structs.Event{ 1 => structs.Event{
.key_press = .{ .key = @intToEnum(enums.Key, js.machEventShift()) }, .key_press = .{
.key = key,
.mods = platform.last_key_mods,
},
}, },
2 => structs.Event{ 2 => structs.Event{
.key_release = .{ .key = @intToEnum(enums.Key, js.machEventShift()) }, .key_repeat = .{
.key = key,
.mods = platform.last_key_mods,
}, },
3 => structs.Event{ },
else => unreachable,
};
},
3 => key_release: {
const key = @intToEnum(enums.Key, js.machEventShift());
switch (key) {
.left_shift, .right_shift => platform.last_key_mods.shift = false,
.left_control, .right_control => platform.last_key_mods.control = false,
.left_alt, .right_alt => platform.last_key_mods.alt = false,
.left_super, .right_super => platform.last_key_mods.super = false,
.caps_lock => platform.last_key_mods.caps_lock = false,
.num_lock => platform.last_key_mods.num_lock = false,
else => {},
}
break :key_release structs.Event{
.key_release = .{
.key = key,
.mods = platform.last_key_mods,
},
};
},
4 => mouse_motion: {
const x = @intToFloat(f64, js.machEventShift());
const y = @intToFloat(f64, js.machEventShift());
platform.last_cursor_position = .{
.x = x,
.y = y,
};
break :mouse_motion structs.Event{
.mouse_motion = .{ .mouse_motion = .{
.x = @intToFloat(f64, js.machEventShift()), .pos = .{
.y = @intToFloat(f64, js.machEventShift()), .x = x,
.y = y,
}, },
}, },
4 => structs.Event{ };
.mouse_press = .{
.button = toMachButton(js.machEventShift()),
},
}, },
5 => structs.Event{ 5 => structs.Event{
.mouse_release = .{ .mouse_press = .{
.button = toMachButton(js.machEventShift()), .button = toMachButton(js.machEventShift()),
.pos = platform.last_cursor_position,
.mods = platform.last_key_mods,
}, },
}, },
6 => structs.Event{ 6 => structs.Event{
.mouse_release = .{
.button = toMachButton(js.machEventShift()),
.pos = platform.last_cursor_position,
.mods = platform.last_key_mods,
},
},
7 => structs.Event{
.mouse_scroll = .{ .mouse_scroll = .{
.xoffset = @floatCast(f32, sign(js.machEventShiftFloat())), .xoffset = @floatCast(f32, sign(js.machEventShiftFloat())),
.yoffset = @floatCast(f32, sign(js.machEventShiftFloat())), .yoffset = @floatCast(f32, sign(js.machEventShiftFloat())),
}, },
}, },
8 => structs.Event.focus_gained,
9 => structs.Event.focus_lost,
else => null, else => null,
}; };
} }

View file

@ -48,25 +48,49 @@ pub const Options = struct {
}; };
pub const Event = union(enum) { pub const Event = union(enum) {
key_press: struct { key_press: KeyEvent,
key: enums.Key, key_repeat: KeyEvent,
}, key_release: KeyEvent,
key_release: struct { char_input: struct {
key: enums.Key, codepoint: u21,
}, },
mouse_motion: struct { mouse_motion: struct {
// These are in window coordinates (not framebuffer coords) pos: WindowPos,
x: f64,
y: f64,
},
mouse_press: struct {
button: enums.MouseButton,
},
mouse_release: struct {
button: enums.MouseButton,
}, },
mouse_press: MouseButtonEvent,
mouse_release: MouseButtonEvent,
mouse_scroll: struct { mouse_scroll: struct {
xoffset: f32, xoffset: f32,
yoffset: f32, yoffset: f32,
}, },
focus_gained,
focus_lost,
closed,
};
pub const KeyEvent = struct {
key: enums.Key,
mods: KeyMods,
};
pub const MouseButtonEvent = struct {
button: enums.MouseButton,
pos: WindowPos,
mods: KeyMods,
};
pub const KeyMods = packed struct {
shift: bool,
control: bool,
alt: bool,
super: bool,
caps_lock: bool,
num_lock: bool,
_reserved: u2 = 0,
};
pub const WindowPos = struct {
// These are in window coordinates (not framebuffer coords)
x: f64,
y: f64,
}; };