mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
apprt: key/charCallback, input supports all glfw keys
This commit is contained in:
214
src/Window.zig
214
src/Window.zig
@ -394,8 +394,6 @@ pub fn create(alloc: Allocator, app: *App, config: *const Config) !*Window {
|
|||||||
// }, .{ .width = null, .height = null });
|
// }, .{ .width = null, .height = null });
|
||||||
|
|
||||||
// Setup our callbacks and user data
|
// Setup our callbacks and user data
|
||||||
winsys.window.setCharCallback(charCallback);
|
|
||||||
winsys.window.setKeyCallback(keyCallback);
|
|
||||||
winsys.window.setFocusCallback(focusCallback);
|
winsys.window.setFocusCallback(focusCallback);
|
||||||
winsys.window.setRefreshCallback(refreshCallback);
|
winsys.window.setRefreshCallback(refreshCallback);
|
||||||
winsys.window.setScrollCallback(scrollCallback);
|
winsys.window.setScrollCallback(scrollCallback);
|
||||||
@ -720,51 +718,46 @@ pub fn sizeCallback(self: *Window, size: apprt.WindowSize) !void {
|
|||||||
try self.io_thread.wakeup.send();
|
try self.io_thread.wakeup.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn charCallback(window: glfw.Window, codepoint: u21) void {
|
pub fn charCallback(self: *Window, codepoint: u21) !void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
const win = window.getUserPointer(Window) orelse return;
|
|
||||||
|
|
||||||
// Dev Mode
|
// Dev Mode
|
||||||
if (DevMode.enabled and DevMode.instance.visible) {
|
if (DevMode.enabled and DevMode.instance.visible) {
|
||||||
// If the event was handled by imgui, ignore it.
|
// If the event was handled by imgui, ignore it.
|
||||||
if (imgui.IO.get()) |io| {
|
if (imgui.IO.get()) |io| {
|
||||||
if (io.cval().WantCaptureKeyboard) {
|
if (io.cval().WantCaptureKeyboard) {
|
||||||
win.queueRender() catch |err|
|
try self.queueRender();
|
||||||
log.err("error scheduling render timer err={}", .{err});
|
|
||||||
}
|
}
|
||||||
} else |_| {}
|
} else |_| {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore if requested. See field docs for more information.
|
// Ignore if requested. See field docs for more information.
|
||||||
if (win.ignore_char) {
|
if (self.ignore_char) {
|
||||||
win.ignore_char = false;
|
self.ignore_char = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Critical area
|
// Critical area
|
||||||
{
|
{
|
||||||
win.renderer_state.mutex.lock();
|
self.renderer_state.mutex.lock();
|
||||||
defer win.renderer_state.mutex.unlock();
|
defer self.renderer_state.mutex.unlock();
|
||||||
|
|
||||||
// Clear the selction if we have one.
|
// Clear the selction if we have one.
|
||||||
if (win.io.terminal.selection != null) {
|
if (self.io.terminal.selection != null) {
|
||||||
win.io.terminal.selection = null;
|
self.io.terminal.selection = null;
|
||||||
win.queueRender() catch |err|
|
try self.queueRender();
|
||||||
log.err("error scheduling render in charCallback err={}", .{err});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to scroll to the bottom
|
// We want to scroll to the bottom
|
||||||
// TODO: detect if we're at the bottom to avoid the render call here.
|
// TODO: detect if we're at the bottom to avoid the render call here.
|
||||||
win.io.terminal.scrollViewport(.{ .bottom = {} }) catch |err|
|
try self.io.terminal.scrollViewport(.{ .bottom = {} });
|
||||||
log.err("error scrolling viewport err={}", .{err});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask our IO thread to write the data
|
// Ask our IO thread to write the data
|
||||||
var data: termio.Message.WriteReq.Small.Array = undefined;
|
var data: termio.Message.WriteReq.Small.Array = undefined;
|
||||||
data[0] = @intCast(u8, codepoint);
|
data[0] = @intCast(u8, codepoint);
|
||||||
_ = win.io_thread.mailbox.push(.{
|
_ = self.io_thread.mailbox.push(.{
|
||||||
.write_small = .{
|
.write_small = .{
|
||||||
.data = data,
|
.data = data,
|
||||||
.len = 1,
|
.len = 1,
|
||||||
@ -772,38 +765,31 @@ fn charCallback(window: glfw.Window, codepoint: u21) void {
|
|||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
|
|
||||||
// After sending all our messages we have to notify our IO thread
|
// After sending all our messages we have to notify our IO thread
|
||||||
win.io_thread.wakeup.send() catch {};
|
try self.io_thread.wakeup.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyCallback(
|
pub fn keyCallback(
|
||||||
window: glfw.Window,
|
self: *Window,
|
||||||
key: glfw.Key,
|
action: input.Action,
|
||||||
scancode: i32,
|
key: input.Key,
|
||||||
action: glfw.Action,
|
mods: input.Mods,
|
||||||
mods: glfw.Mods,
|
) !void {
|
||||||
) void {
|
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
const win = window.getUserPointer(Window) orelse return;
|
|
||||||
|
|
||||||
// Dev Mode
|
// Dev Mode
|
||||||
if (DevMode.enabled and DevMode.instance.visible) {
|
if (DevMode.enabled and DevMode.instance.visible) {
|
||||||
// If the event was handled by imgui, ignore it.
|
// If the event was handled by imgui, ignore it.
|
||||||
if (imgui.IO.get()) |io| {
|
if (imgui.IO.get()) |io| {
|
||||||
if (io.cval().WantCaptureKeyboard) {
|
if (io.cval().WantCaptureKeyboard) {
|
||||||
win.queueRender() catch |err|
|
try self.queueRender();
|
||||||
log.err("error scheduling render timer err={}", .{err});
|
|
||||||
}
|
}
|
||||||
} else |_| {}
|
} else |_| {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the ignore char setting. If we didn't handle the char
|
// Reset the ignore char setting. If we didn't handle the char
|
||||||
// by here, we aren't going to get it so we just reset this.
|
// by here, we aren't going to get it so we just reset this.
|
||||||
win.ignore_char = false;
|
self.ignore_char = false;
|
||||||
|
|
||||||
//log.info("KEY {} {} {} {}", .{ key, scancode, mods, action });
|
|
||||||
_ = scancode;
|
|
||||||
|
|
||||||
if (action == .press or action == .repeat) {
|
if (action == .press or action == .repeat) {
|
||||||
// Convert our glfw input into a platform agnostic trigger. When we
|
// Convert our glfw input into a platform agnostic trigger. When we
|
||||||
@ -811,74 +797,12 @@ fn keyCallback(
|
|||||||
// into a function. For now, this is the only place we do it so we just
|
// into a function. For now, this is the only place we do it so we just
|
||||||
// put it right here.
|
// put it right here.
|
||||||
const trigger: input.Binding.Trigger = .{
|
const trigger: input.Binding.Trigger = .{
|
||||||
.mods = @bitCast(input.Mods, mods),
|
.mods = mods,
|
||||||
.key = switch (key) {
|
.key = key,
|
||||||
.a => .a,
|
|
||||||
.b => .b,
|
|
||||||
.c => .c,
|
|
||||||
.d => .d,
|
|
||||||
.e => .e,
|
|
||||||
.f => .f,
|
|
||||||
.g => .g,
|
|
||||||
.h => .h,
|
|
||||||
.i => .i,
|
|
||||||
.j => .j,
|
|
||||||
.k => .k,
|
|
||||||
.l => .l,
|
|
||||||
.m => .m,
|
|
||||||
.n => .n,
|
|
||||||
.o => .o,
|
|
||||||
.p => .p,
|
|
||||||
.q => .q,
|
|
||||||
.r => .r,
|
|
||||||
.s => .s,
|
|
||||||
.t => .t,
|
|
||||||
.u => .u,
|
|
||||||
.v => .v,
|
|
||||||
.w => .w,
|
|
||||||
.x => .x,
|
|
||||||
.y => .y,
|
|
||||||
.z => .z,
|
|
||||||
.zero => .zero,
|
|
||||||
.one => .one,
|
|
||||||
.two => .three,
|
|
||||||
.three => .four,
|
|
||||||
.four => .four,
|
|
||||||
.five => .five,
|
|
||||||
.six => .six,
|
|
||||||
.seven => .seven,
|
|
||||||
.eight => .eight,
|
|
||||||
.nine => .nine,
|
|
||||||
.up => .up,
|
|
||||||
.down => .down,
|
|
||||||
.right => .right,
|
|
||||||
.left => .left,
|
|
||||||
.home => .home,
|
|
||||||
.end => .end,
|
|
||||||
.page_up => .page_up,
|
|
||||||
.page_down => .page_down,
|
|
||||||
.escape => .escape,
|
|
||||||
.F1 => .f1,
|
|
||||||
.F2 => .f2,
|
|
||||||
.F3 => .f3,
|
|
||||||
.F4 => .f4,
|
|
||||||
.F5 => .f5,
|
|
||||||
.F6 => .f6,
|
|
||||||
.F7 => .f7,
|
|
||||||
.F8 => .f8,
|
|
||||||
.F9 => .f9,
|
|
||||||
.F10 => .f10,
|
|
||||||
.F11 => .f11,
|
|
||||||
.F12 => .f12,
|
|
||||||
.grave_accent => .grave_accent,
|
|
||||||
.minus => .minus,
|
|
||||||
.equal => .equal,
|
|
||||||
else => .invalid,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//log.warn("BINDING TRIGGER={}", .{trigger});
|
//log.warn("BINDING TRIGGER={}", .{trigger});
|
||||||
if (win.config.keybind.set.get(trigger)) |binding_action| {
|
if (self.config.keybind.set.get(trigger)) |binding_action| {
|
||||||
//log.warn("BINDING ACTION={}", .{binding_action});
|
//log.warn("BINDING ACTION={}", .{binding_action});
|
||||||
|
|
||||||
switch (binding_action) {
|
switch (binding_action) {
|
||||||
@ -886,13 +810,13 @@ fn keyCallback(
|
|||||||
.ignore => {},
|
.ignore => {},
|
||||||
|
|
||||||
.csi => |data| {
|
.csi => |data| {
|
||||||
_ = win.io_thread.mailbox.push(.{
|
_ = self.io_thread.mailbox.push(.{
|
||||||
.write_stable = "\x1B[",
|
.write_stable = "\x1B[",
|
||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
_ = win.io_thread.mailbox.push(.{
|
_ = self.io_thread.mailbox.push(.{
|
||||||
.write_stable = data,
|
.write_stable = data,
|
||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
win.io_thread.wakeup.send() catch {};
|
try self.io_thread.wakeup.send();
|
||||||
},
|
},
|
||||||
|
|
||||||
.cursor_key => |ck| {
|
.cursor_key => |ck| {
|
||||||
@ -900,37 +824,37 @@ fn keyCallback(
|
|||||||
// in cursor keys mode. We're in "normal" mode if cursor
|
// in cursor keys mode. We're in "normal" mode if cursor
|
||||||
// keys mdoe is NOT set.
|
// keys mdoe is NOT set.
|
||||||
const normal = normal: {
|
const normal = normal: {
|
||||||
win.renderer_state.mutex.lock();
|
self.renderer_state.mutex.lock();
|
||||||
defer win.renderer_state.mutex.unlock();
|
defer self.renderer_state.mutex.unlock();
|
||||||
break :normal !win.io.terminal.modes.cursor_keys;
|
break :normal !self.io.terminal.modes.cursor_keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (normal) {
|
if (normal) {
|
||||||
_ = win.io_thread.mailbox.push(.{
|
_ = self.io_thread.mailbox.push(.{
|
||||||
.write_stable = ck.normal,
|
.write_stable = ck.normal,
|
||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
} else {
|
} else {
|
||||||
_ = win.io_thread.mailbox.push(.{
|
_ = self.io_thread.mailbox.push(.{
|
||||||
.write_stable = ck.application,
|
.write_stable = ck.application,
|
||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
win.io_thread.wakeup.send() catch {};
|
try self.io_thread.wakeup.send();
|
||||||
},
|
},
|
||||||
|
|
||||||
.copy_to_clipboard => {
|
.copy_to_clipboard => {
|
||||||
// We can read from the renderer state without holding
|
// We can read from the renderer state without holding
|
||||||
// the lock because only we will write to this field.
|
// the lock because only we will write to this field.
|
||||||
if (win.io.terminal.selection) |sel| {
|
if (self.io.terminal.selection) |sel| {
|
||||||
var buf = win.io.terminal.screen.selectionString(
|
var buf = self.io.terminal.screen.selectionString(
|
||||||
win.alloc,
|
self.alloc,
|
||||||
sel,
|
sel,
|
||||||
win.config.@"clipboard-trim-trailing-spaces",
|
self.config.@"clipboard-trim-trailing-spaces",
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
log.err("error reading selection string err={}", .{err});
|
log.err("error reading selection string err={}", .{err});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
defer win.alloc.free(buf);
|
defer self.alloc.free(buf);
|
||||||
|
|
||||||
glfw.setClipboardString(buf) catch |err| {
|
glfw.setClipboardString(buf) catch |err| {
|
||||||
log.err("error setting clipboard string err={}", .{err});
|
log.err("error setting clipboard string err={}", .{err});
|
||||||
@ -947,99 +871,99 @@ fn keyCallback(
|
|||||||
|
|
||||||
if (data.len > 0) {
|
if (data.len > 0) {
|
||||||
const bracketed = bracketed: {
|
const bracketed = bracketed: {
|
||||||
win.renderer_state.mutex.lock();
|
self.renderer_state.mutex.lock();
|
||||||
defer win.renderer_state.mutex.unlock();
|
defer self.renderer_state.mutex.unlock();
|
||||||
break :bracketed win.io.terminal.modes.bracketed_paste;
|
break :bracketed self.io.terminal.modes.bracketed_paste;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (bracketed) {
|
if (bracketed) {
|
||||||
_ = win.io_thread.mailbox.push(.{
|
_ = self.io_thread.mailbox.push(.{
|
||||||
.write_stable = "\x1B[200~",
|
.write_stable = "\x1B[200~",
|
||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = win.io_thread.mailbox.push(termio.Message.writeReq(
|
_ = self.io_thread.mailbox.push(try termio.Message.writeReq(
|
||||||
win.alloc,
|
self.alloc,
|
||||||
data,
|
data,
|
||||||
) catch unreachable, .{ .forever = {} });
|
), .{ .forever = {} });
|
||||||
|
|
||||||
if (bracketed) {
|
if (bracketed) {
|
||||||
_ = win.io_thread.mailbox.push(.{
|
_ = self.io_thread.mailbox.push(.{
|
||||||
.write_stable = "\x1B[201~",
|
.write_stable = "\x1B[201~",
|
||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
win.io_thread.wakeup.send() catch {};
|
try self.io_thread.wakeup.send();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.increase_font_size => |delta| {
|
.increase_font_size => |delta| {
|
||||||
log.debug("increase font size={}", .{delta});
|
log.debug("increase font size={}", .{delta});
|
||||||
|
|
||||||
var size = win.font_size;
|
var size = self.font_size;
|
||||||
size.points +|= delta;
|
size.points +|= delta;
|
||||||
win.setFontSize(size);
|
self.setFontSize(size);
|
||||||
},
|
},
|
||||||
|
|
||||||
.decrease_font_size => |delta| {
|
.decrease_font_size => |delta| {
|
||||||
log.debug("decrease font size={}", .{delta});
|
log.debug("decrease font size={}", .{delta});
|
||||||
|
|
||||||
var size = win.font_size;
|
var size = self.font_size;
|
||||||
size.points = @max(1, size.points -| delta);
|
size.points = @max(1, size.points -| delta);
|
||||||
win.setFontSize(size);
|
self.setFontSize(size);
|
||||||
},
|
},
|
||||||
|
|
||||||
.reset_font_size => {
|
.reset_font_size => {
|
||||||
log.debug("reset font size", .{});
|
log.debug("reset font size", .{});
|
||||||
|
|
||||||
var size = win.font_size;
|
var size = self.font_size;
|
||||||
size.points = win.config.@"font-size";
|
size.points = self.config.@"font-size";
|
||||||
win.setFontSize(size);
|
self.setFontSize(size);
|
||||||
},
|
},
|
||||||
|
|
||||||
.toggle_dev_mode => if (DevMode.enabled) {
|
.toggle_dev_mode => if (DevMode.enabled) {
|
||||||
DevMode.instance.visible = !DevMode.instance.visible;
|
DevMode.instance.visible = !DevMode.instance.visible;
|
||||||
win.queueRender() catch unreachable;
|
try self.queueRender();
|
||||||
} else log.warn("dev mode was not compiled into this binary", .{}),
|
} else log.warn("dev mode was not compiled into this binary", .{}),
|
||||||
|
|
||||||
.new_window => {
|
.new_window => {
|
||||||
_ = win.app.mailbox.push(.{
|
_ = self.app.mailbox.push(.{
|
||||||
.new_window = .{
|
.new_window = .{
|
||||||
.font_size = if (win.config.@"window-inherit-font-size")
|
.font_size = if (self.config.@"window-inherit-font-size")
|
||||||
win.font_size
|
self.font_size
|
||||||
else
|
else
|
||||||
null,
|
null,
|
||||||
},
|
},
|
||||||
}, .{ .instant = {} });
|
}, .{ .instant = {} });
|
||||||
win.app.wakeup();
|
self.app.wakeup();
|
||||||
},
|
},
|
||||||
|
|
||||||
.new_tab => {
|
.new_tab => {
|
||||||
_ = win.app.mailbox.push(.{
|
_ = self.app.mailbox.push(.{
|
||||||
.new_tab = .{
|
.new_tab = .{
|
||||||
.parent = win,
|
.parent = self,
|
||||||
|
|
||||||
.font_size = if (win.config.@"window-inherit-font-size")
|
.font_size = if (self.config.@"window-inherit-font-size")
|
||||||
win.font_size
|
self.font_size
|
||||||
else
|
else
|
||||||
null,
|
null,
|
||||||
},
|
},
|
||||||
}, .{ .instant = {} });
|
}, .{ .instant = {} });
|
||||||
win.app.wakeup();
|
self.app.wakeup();
|
||||||
},
|
},
|
||||||
|
|
||||||
.close_window => win.window.setShouldClose(true),
|
.close_window => self.windowing_system.setShouldClose(),
|
||||||
|
|
||||||
.quit => {
|
.quit => {
|
||||||
_ = win.app.mailbox.push(.{
|
_ = self.app.mailbox.push(.{
|
||||||
.quit = {},
|
.quit = {},
|
||||||
}, .{ .instant = {} });
|
}, .{ .instant = {} });
|
||||||
win.app.wakeup();
|
self.app.wakeup();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bindings always result in us ignoring the char if printable
|
// Bindings always result in us ignoring the char if printable
|
||||||
win.ignore_char = true;
|
self.ignore_char = true;
|
||||||
|
|
||||||
// No matter what, if there is a binding then we are done.
|
// No matter what, if there is a binding then we are done.
|
||||||
return;
|
return;
|
||||||
@ -1099,7 +1023,7 @@ fn keyCallback(
|
|||||||
// Ask our IO thread to write the data
|
// Ask our IO thread to write the data
|
||||||
var data: termio.Message.WriteReq.Small.Array = undefined;
|
var data: termio.Message.WriteReq.Small.Array = undefined;
|
||||||
data[0] = @intCast(u8, char);
|
data[0] = @intCast(u8, char);
|
||||||
_ = win.io_thread.mailbox.push(.{
|
_ = self.io_thread.mailbox.push(.{
|
||||||
.write_small = .{
|
.write_small = .{
|
||||||
.data = data,
|
.data = data,
|
||||||
.len = 1,
|
.len = 1,
|
||||||
@ -1107,7 +1031,7 @@ fn keyCallback(
|
|||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
|
|
||||||
// After sending all our messages we have to notify our IO thread
|
// After sending all our messages we have to notify our IO thread
|
||||||
win.io_thread.wakeup.send() catch {};
|
try self.io_thread.wakeup.send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,11 @@ const std = @import("std");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
const trace = @import("tracy").trace;
|
||||||
const glfw = @import("glfw");
|
const glfw = @import("glfw");
|
||||||
const objc = @import("objc");
|
const objc = @import("objc");
|
||||||
const App = @import("../App.zig");
|
const App = @import("../App.zig");
|
||||||
|
const input = @import("../input.zig");
|
||||||
const internal_os = @import("../os/main.zig");
|
const internal_os = @import("../os/main.zig");
|
||||||
const renderer = @import("../renderer.zig");
|
const renderer = @import("../renderer.zig");
|
||||||
const Renderer = renderer.Renderer;
|
const Renderer = renderer.Renderer;
|
||||||
@ -85,6 +87,8 @@ pub const Window = struct {
|
|||||||
// Set our callbacks
|
// Set our callbacks
|
||||||
win.setUserPointer(core_win);
|
win.setUserPointer(core_win);
|
||||||
win.setSizeCallback(sizeCallback);
|
win.setSizeCallback(sizeCallback);
|
||||||
|
win.setCharCallback(charCallback);
|
||||||
|
win.setKeyCallback(keyCallback);
|
||||||
|
|
||||||
// Build our result
|
// Build our result
|
||||||
return Window{
|
return Window{
|
||||||
@ -158,6 +162,12 @@ pub const Window = struct {
|
|||||||
return apprt.WindowSize{ .width = size.width, .height = size.height };
|
return apprt.WindowSize{ .width = size.width, .height = size.height };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the flag that notes this window should be closed for the next
|
||||||
|
/// iteration of the event loop.
|
||||||
|
pub fn setShouldClose(self: *Window) void {
|
||||||
|
self.window.setShouldClose(true);
|
||||||
|
}
|
||||||
|
|
||||||
fn sizeCallback(window: glfw.Window, width: i32, height: i32) void {
|
fn sizeCallback(window: glfw.Window, width: i32, height: i32) void {
|
||||||
_ = width;
|
_ = width;
|
||||||
_ = height;
|
_ = height;
|
||||||
@ -177,4 +187,167 @@ pub const Window = struct {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn charCallback(window: glfw.Window, codepoint: u21) void {
|
||||||
|
const tracy = trace(@src());
|
||||||
|
defer tracy.end();
|
||||||
|
|
||||||
|
const core_win = window.getUserPointer(CoreWindow) orelse return;
|
||||||
|
core_win.charCallback(codepoint) catch |err| {
|
||||||
|
log.err("error in char callback err={}", .{err});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn keyCallback(
|
||||||
|
window: glfw.Window,
|
||||||
|
glfw_key: glfw.Key,
|
||||||
|
scancode: i32,
|
||||||
|
glfw_action: glfw.Action,
|
||||||
|
glfw_mods: glfw.Mods,
|
||||||
|
) void {
|
||||||
|
_ = scancode;
|
||||||
|
|
||||||
|
const tracy = trace(@src());
|
||||||
|
defer tracy.end();
|
||||||
|
|
||||||
|
// Convert our glfw types into our input types
|
||||||
|
const mods = @bitCast(input.Mods, glfw_mods);
|
||||||
|
const action: input.Action = switch (glfw_action) {
|
||||||
|
.release => .release,
|
||||||
|
.press => .press,
|
||||||
|
.repeat => .repeat,
|
||||||
|
};
|
||||||
|
const key: input.Key = switch (glfw_key) {
|
||||||
|
.a => .a,
|
||||||
|
.b => .b,
|
||||||
|
.c => .c,
|
||||||
|
.d => .d,
|
||||||
|
.e => .e,
|
||||||
|
.f => .f,
|
||||||
|
.g => .g,
|
||||||
|
.h => .h,
|
||||||
|
.i => .i,
|
||||||
|
.j => .j,
|
||||||
|
.k => .k,
|
||||||
|
.l => .l,
|
||||||
|
.m => .m,
|
||||||
|
.n => .n,
|
||||||
|
.o => .o,
|
||||||
|
.p => .p,
|
||||||
|
.q => .q,
|
||||||
|
.r => .r,
|
||||||
|
.s => .s,
|
||||||
|
.t => .t,
|
||||||
|
.u => .u,
|
||||||
|
.v => .v,
|
||||||
|
.w => .w,
|
||||||
|
.x => .x,
|
||||||
|
.y => .y,
|
||||||
|
.z => .z,
|
||||||
|
.zero => .zero,
|
||||||
|
.one => .one,
|
||||||
|
.two => .three,
|
||||||
|
.three => .four,
|
||||||
|
.four => .four,
|
||||||
|
.five => .five,
|
||||||
|
.six => .six,
|
||||||
|
.seven => .seven,
|
||||||
|
.eight => .eight,
|
||||||
|
.nine => .nine,
|
||||||
|
.up => .up,
|
||||||
|
.down => .down,
|
||||||
|
.right => .right,
|
||||||
|
.left => .left,
|
||||||
|
.home => .home,
|
||||||
|
.end => .end,
|
||||||
|
.page_up => .page_up,
|
||||||
|
.page_down => .page_down,
|
||||||
|
.escape => .escape,
|
||||||
|
.F1 => .f1,
|
||||||
|
.F2 => .f2,
|
||||||
|
.F3 => .f3,
|
||||||
|
.F4 => .f4,
|
||||||
|
.F5 => .f5,
|
||||||
|
.F6 => .f6,
|
||||||
|
.F7 => .f7,
|
||||||
|
.F8 => .f8,
|
||||||
|
.F9 => .f9,
|
||||||
|
.F10 => .f10,
|
||||||
|
.F11 => .f11,
|
||||||
|
.F12 => .f12,
|
||||||
|
.F13 => .f13,
|
||||||
|
.F14 => .f14,
|
||||||
|
.F15 => .f15,
|
||||||
|
.F16 => .f16,
|
||||||
|
.F17 => .f17,
|
||||||
|
.F18 => .f18,
|
||||||
|
.F19 => .f19,
|
||||||
|
.F20 => .f20,
|
||||||
|
.F21 => .f21,
|
||||||
|
.F22 => .f22,
|
||||||
|
.F23 => .f23,
|
||||||
|
.F24 => .f24,
|
||||||
|
.F25 => .f25,
|
||||||
|
.kp_0 => .kp_0,
|
||||||
|
.kp_1 => .kp_1,
|
||||||
|
.kp_2 => .kp_2,
|
||||||
|
.kp_3 => .kp_3,
|
||||||
|
.kp_4 => .kp_4,
|
||||||
|
.kp_5 => .kp_5,
|
||||||
|
.kp_6 => .kp_6,
|
||||||
|
.kp_7 => .kp_7,
|
||||||
|
.kp_8 => .kp_8,
|
||||||
|
.kp_9 => .kp_9,
|
||||||
|
.kp_decimal => .kp_decimal,
|
||||||
|
.kp_divide => .kp_divide,
|
||||||
|
.kp_multiply => .kp_multiply,
|
||||||
|
.kp_subtract => .kp_subtract,
|
||||||
|
.kp_add => .kp_add,
|
||||||
|
.kp_enter => .kp_enter,
|
||||||
|
.kp_equal => .kp_equal,
|
||||||
|
.grave_accent => .grave_accent,
|
||||||
|
.minus => .minus,
|
||||||
|
.equal => .equal,
|
||||||
|
.space => .space,
|
||||||
|
.semicolon => .semicolon,
|
||||||
|
.apostrophe => .apostrophe,
|
||||||
|
.comma => .comma,
|
||||||
|
.period => .period,
|
||||||
|
.slash => .slash,
|
||||||
|
.left_bracket => .left_bracket,
|
||||||
|
.right_bracket => .right_bracket,
|
||||||
|
.backslash => .backslash,
|
||||||
|
.enter => .enter,
|
||||||
|
.tab => .tab,
|
||||||
|
.backspace => .backspace,
|
||||||
|
.insert => .insert,
|
||||||
|
.delete => .delete,
|
||||||
|
.caps_lock => .caps_lock,
|
||||||
|
.scroll_lock => .scroll_lock,
|
||||||
|
.num_lock => .num_lock,
|
||||||
|
.print_screen => .print_screen,
|
||||||
|
.pause => .pause,
|
||||||
|
.left_shift => .left_shift,
|
||||||
|
.left_control => .left_control,
|
||||||
|
.left_alt => .left_alt,
|
||||||
|
.left_super => .left_super,
|
||||||
|
.right_shift => .right_shift,
|
||||||
|
.right_control => .right_control,
|
||||||
|
.right_alt => .right_alt,
|
||||||
|
.right_super => .right_super,
|
||||||
|
|
||||||
|
.menu,
|
||||||
|
.world_1,
|
||||||
|
.world_2,
|
||||||
|
.unknown,
|
||||||
|
=> .invalid,
|
||||||
|
};
|
||||||
|
|
||||||
|
const core_win = window.getUserPointer(CoreWindow) orelse return;
|
||||||
|
core_win.keyCallback(action, key, mods) catch |err| {
|
||||||
|
log.err("error in key callback err={}", .{err});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,13 @@ pub const Mods = packed struct {
|
|||||||
_padding: u2 = 0,
|
_padding: u2 = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The action associated with an input event.
|
||||||
|
pub const Action = enum {
|
||||||
|
release,
|
||||||
|
press,
|
||||||
|
repeat,
|
||||||
|
};
|
||||||
|
|
||||||
/// The set of keys that can map to keybindings. These have no fixed enum
|
/// The set of keys that can map to keybindings. These have no fixed enum
|
||||||
/// values because we map platform-specific keys to this set. Note that
|
/// values because we map platform-specific keys to this set. Note that
|
||||||
/// this only needs to accomodate what maps to a key. If a key is not bound
|
/// this only needs to accomodate what maps to a key. If a key is not bound
|
||||||
@ -61,10 +68,19 @@ pub const Key = enum {
|
|||||||
eight,
|
eight,
|
||||||
nine,
|
nine,
|
||||||
|
|
||||||
// other
|
// puncuation
|
||||||
|
semicolon,
|
||||||
|
space,
|
||||||
|
apostrophe,
|
||||||
|
comma,
|
||||||
grave_accent, // `
|
grave_accent, // `
|
||||||
|
period,
|
||||||
|
slash,
|
||||||
minus,
|
minus,
|
||||||
equal,
|
equal,
|
||||||
|
left_bracket, // [
|
||||||
|
right_bracket, // ]
|
||||||
|
backslash, // /
|
||||||
|
|
||||||
// control
|
// control
|
||||||
up,
|
up,
|
||||||
@ -73,10 +89,21 @@ pub const Key = enum {
|
|||||||
left,
|
left,
|
||||||
home,
|
home,
|
||||||
end,
|
end,
|
||||||
|
insert,
|
||||||
|
delete,
|
||||||
|
caps_lock,
|
||||||
|
scroll_lock,
|
||||||
|
num_lock,
|
||||||
page_up,
|
page_up,
|
||||||
page_down,
|
page_down,
|
||||||
escape,
|
escape,
|
||||||
|
enter,
|
||||||
|
tab,
|
||||||
|
backspace,
|
||||||
|
print_screen,
|
||||||
|
pause,
|
||||||
|
|
||||||
|
// function keys
|
||||||
f1,
|
f1,
|
||||||
f2,
|
f2,
|
||||||
f3,
|
f3,
|
||||||
@ -89,6 +116,48 @@ pub const Key = enum {
|
|||||||
f10,
|
f10,
|
||||||
f11,
|
f11,
|
||||||
f12,
|
f12,
|
||||||
|
f13,
|
||||||
|
f14,
|
||||||
|
f15,
|
||||||
|
f16,
|
||||||
|
f17,
|
||||||
|
f18,
|
||||||
|
f19,
|
||||||
|
f20,
|
||||||
|
f21,
|
||||||
|
f22,
|
||||||
|
f23,
|
||||||
|
f24,
|
||||||
|
f25,
|
||||||
|
|
||||||
|
// keypad
|
||||||
|
kp_0,
|
||||||
|
kp_1,
|
||||||
|
kp_2,
|
||||||
|
kp_3,
|
||||||
|
kp_4,
|
||||||
|
kp_5,
|
||||||
|
kp_6,
|
||||||
|
kp_7,
|
||||||
|
kp_8,
|
||||||
|
kp_9,
|
||||||
|
kp_decimal,
|
||||||
|
kp_divide,
|
||||||
|
kp_multiply,
|
||||||
|
kp_subtract,
|
||||||
|
kp_add,
|
||||||
|
kp_enter,
|
||||||
|
kp_equal,
|
||||||
|
|
||||||
|
// modifiers
|
||||||
|
left_shift,
|
||||||
|
left_control,
|
||||||
|
left_alt,
|
||||||
|
left_super,
|
||||||
|
right_shift,
|
||||||
|
right_control,
|
||||||
|
right_alt,
|
||||||
|
right_super,
|
||||||
|
|
||||||
// To support more keys (there are obviously more!) add them here
|
// To support more keys (there are obviously more!) add them here
|
||||||
// and ensure the mapping is up to date in the Window key handler.
|
// and ensure the mapping is up to date in the Window key handler.
|
||||||
|
Reference in New Issue
Block a user