diff --git a/src/inspector/Inspector.zig b/src/inspector/Inspector.zig index 9142f7bc8..cb7739cfe 100644 --- a/src/inspector/Inspector.zig +++ b/src/inspector/Inspector.zig @@ -956,37 +956,7 @@ fn renderKeyboardWindow(self: *Inspector) void { ); if (!ev.imgui_state.selected) continue; - - _ = cimgui.c.igBeginTable( - "##event", - 2, - cimgui.c.ImGuiTableFlags_None, - .{ .x = 0, .y = 0 }, - 0, - ); - defer cimgui.c.igEndTable(); - - { - cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); - _ = cimgui.c.igTableSetColumnIndex(0); - cimgui.c.igText("Action"); - _ = cimgui.c.igTableSetColumnIndex(1); - cimgui.c.igText("%s", @tagName(ev.event.action).ptr); - } - { - cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); - _ = cimgui.c.igTableSetColumnIndex(0); - cimgui.c.igText("Key"); - _ = cimgui.c.igTableSetColumnIndex(1); - cimgui.c.igText("%s", @tagName(ev.event.key).ptr); - } - { - cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); - _ = cimgui.c.igTableSetColumnIndex(0); - cimgui.c.igText("Physical Key"); - _ = cimgui.c.igTableSetColumnIndex(1); - cimgui.c.igText("%s", @tagName(ev.event.physical_key).ptr); - } + ev.render(); } } // table } diff --git a/src/inspector/key.zig b/src/inspector/key.zig index 97596bddb..0a44e2c9d 100644 --- a/src/inspector/key.zig +++ b/src/inspector/key.zig @@ -2,6 +2,7 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const input = @import("../input.zig"); const CircBuf = @import("../circ_buf.zig").CircBuf; +const cimgui = @import("cimgui"); /// Circular buffer of key events. pub const EventRing = CircBuf(Event, undefined); @@ -53,10 +54,167 @@ pub const Event = struct { if (self.event.mods.super) try writer.writeAll("Super+"); try writer.writeAll(@tagName(self.event.key)); + // Deadkey + if (self.event.composing) try writer.writeAll(" (composing)"); + // Null-terminator try writer.writeByte(0); return buf[0..(buf_stream.getWritten().len - 1) :0]; } + + /// Render this event in the inspector GUI. + pub fn render(self: *const Event) void { + _ = cimgui.c.igBeginTable( + "##event", + 2, + cimgui.c.ImGuiTableFlags_None, + .{ .x = 0, .y = 0 }, + 0, + ); + defer cimgui.c.igEndTable(); + + if (self.binding) |binding| { + cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); + _ = cimgui.c.igTableSetColumnIndex(0); + cimgui.c.igText("Triggered Binding"); + _ = cimgui.c.igTableSetColumnIndex(1); + cimgui.c.igText("%s", @tagName(binding).ptr); + } + + pty: { + cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); + _ = cimgui.c.igTableSetColumnIndex(0); + cimgui.c.igText("Encoding to Pty"); + _ = cimgui.c.igTableSetColumnIndex(1); + if (self.pty.len == 0) { + cimgui.c.igTextDisabled("(no data)"); + break :pty; + } + + self.renderPty() catch { + cimgui.c.igTextDisabled("(error rendering pty data)"); + break :pty; + }; + } + + { + cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); + _ = cimgui.c.igTableSetColumnIndex(0); + cimgui.c.igText("Action"); + _ = cimgui.c.igTableSetColumnIndex(1); + cimgui.c.igText("%s", @tagName(self.event.action).ptr); + } + { + cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); + _ = cimgui.c.igTableSetColumnIndex(0); + cimgui.c.igText("Key"); + _ = cimgui.c.igTableSetColumnIndex(1); + cimgui.c.igText("%s", @tagName(self.event.key).ptr); + } + if (self.event.physical_key != self.event.key) { + cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); + _ = cimgui.c.igTableSetColumnIndex(0); + cimgui.c.igText("Physical Key"); + _ = cimgui.c.igTableSetColumnIndex(1); + cimgui.c.igText("%s", @tagName(self.event.physical_key).ptr); + } + if (!self.event.mods.empty()) { + cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); + _ = cimgui.c.igTableSetColumnIndex(0); + cimgui.c.igText("Mods"); + _ = cimgui.c.igTableSetColumnIndex(1); + if (self.event.mods.shift) cimgui.c.igText("shift "); + if (self.event.mods.ctrl) cimgui.c.igText("ctrl "); + if (self.event.mods.alt) cimgui.c.igText("alt "); + if (self.event.mods.super) cimgui.c.igText("super "); + } + if (self.event.composing) { + cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); + _ = cimgui.c.igTableSetColumnIndex(0); + cimgui.c.igText("Composing"); + _ = cimgui.c.igTableSetColumnIndex(1); + cimgui.c.igText("true"); + } + utf8: { + cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0); + _ = cimgui.c.igTableSetColumnIndex(0); + cimgui.c.igText("UTF-8"); + _ = cimgui.c.igTableSetColumnIndex(1); + if (self.event.utf8.len == 0) { + cimgui.c.igTextDisabled("(empty)"); + break :utf8; + } + + self.renderUtf8(self.event.utf8) catch { + cimgui.c.igTextDisabled("(error rendering utf-8)"); + break :utf8; + }; + } + } + + fn renderUtf8(self: *const Event, utf8: []const u8) !void { + _ = self; + + // Format the codepoint sequence + var buf: [1024]u8 = undefined; + var buf_stream = std.io.fixedBufferStream(&buf); + const writer = buf_stream.writer(); + if (std.unicode.Utf8View.init(utf8)) |view| { + var it = view.iterator(); + while (it.nextCodepoint()) |cp| { + try writer.print("U+{X} ", .{cp}); + } + } else |_| { + try writer.writeAll("(invalid utf-8)"); + } + try writer.writeByte(0); + + // Render as a textbox + _ = cimgui.c.igInputText( + "##utf8", + &buf, + buf_stream.getWritten().len - 1, + cimgui.c.ImGuiInputTextFlags_ReadOnly, + null, + null, + ); + } + + fn renderPty(self: *const Event) !void { + // Format the codepoint sequence + var buf: [1024]u8 = undefined; + var buf_stream = std.io.fixedBufferStream(&buf); + const writer = buf_stream.writer(); + + for (self.pty) |byte| { + // Print ESC special because its so common + if (byte == 0x1B) { + try writer.writeAll("ESC "); + continue; + } + + // Print ASCII as-is + if (byte > 0x20 and byte < 0x7F) { + try writer.writeByte(byte); + continue; + } + + // Everything else as a hex byte + try writer.print("0x{X} ", .{byte}); + } + + try writer.writeByte(0); + + // Render as a textbox + _ = cimgui.c.igInputText( + "##pty", + &buf, + buf_stream.getWritten().len - 1, + cimgui.c.ImGuiInputTextFlags_ReadOnly, + null, + null, + ); + } }; test "event string" {