mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-17 04:52:47 +00:00
inspector: starting screen
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
const cimgui = @import("dcimgui");
|
||||
|
||||
pub const screen = @import("widgets/screen.zig");
|
||||
pub const surface = @import("widgets/surface.zig");
|
||||
pub const terminal = @import("widgets/terminal.zig");
|
||||
|
||||
|
||||
120
src/inspector/widgets/screen.zig
Normal file
120
src/inspector/widgets/screen.zig
Normal file
@@ -0,0 +1,120 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const assert = @import("../../quirks.zig").inlineAssert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const cimgui = @import("dcimgui");
|
||||
const widgets = @import("../widgets.zig");
|
||||
const terminal = @import("../../terminal/main.zig");
|
||||
|
||||
/// Screen information inspector widget.
|
||||
pub const Info = struct {
|
||||
pub const empty: Info = .{};
|
||||
|
||||
/// Draw the screen info contents.
|
||||
pub fn draw(self: *Info, open: bool, data: struct {
|
||||
/// The screen that we're inspecting.
|
||||
screen: *const terminal.Screen,
|
||||
|
||||
/// Which screen key we're viewing.
|
||||
key: terminal.ScreenSet.Key,
|
||||
|
||||
/// Which screen is active (primary or alternate).
|
||||
active_key: terminal.ScreenSet.Key,
|
||||
|
||||
/// Whether xterm modify other keys mode 2 is enabled.
|
||||
modify_other_keys_2: bool,
|
||||
|
||||
/// Color palette for cursor color resolution.
|
||||
color_palette: *const terminal.color.DynamicPalette,
|
||||
}) void {
|
||||
_ = self;
|
||||
const screen = data.screen;
|
||||
|
||||
// The remainder is the open state
|
||||
if (!open) return;
|
||||
|
||||
// Show warning if viewing an inactive screen
|
||||
if (data.key != data.active_key) {
|
||||
cimgui.c.ImGui_TextColored(
|
||||
.{ .x = 1.0, .y = 0.8, .z = 0.0, .w = 1.0 },
|
||||
"⚠ Viewing inactive screen",
|
||||
);
|
||||
cimgui.c.ImGui_Separator();
|
||||
}
|
||||
|
||||
if (cimgui.c.ImGui_CollapsingHeader(
|
||||
"Keyboard",
|
||||
cimgui.c.ImGuiTreeNodeFlags_None,
|
||||
)) keyboardTable(
|
||||
screen,
|
||||
data.modify_other_keys_2,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/// Render keyboard information with a table.
|
||||
fn keyboardTable(
|
||||
screen: *const terminal.Screen,
|
||||
modify_other_keys_2: bool,
|
||||
) void {
|
||||
if (!cimgui.c.ImGui_BeginTable(
|
||||
"table_keyboard",
|
||||
2,
|
||||
cimgui.c.ImGuiTableFlags_None,
|
||||
)) return;
|
||||
defer cimgui.c.ImGui_EndTable();
|
||||
|
||||
const kitty_flags = screen.kitty_keyboard.current();
|
||||
|
||||
{
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Mode");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
const mode = if (kitty_flags.int() != 0) "kitty" else "legacy";
|
||||
cimgui.c.ImGui_Text("%s", mode.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (kitty_flags.int() != 0) {
|
||||
const Flags = @TypeOf(kitty_flags);
|
||||
inline for (@typeInfo(Flags).@"struct".fields) |field| {
|
||||
{
|
||||
const value = @field(kitty_flags, field.name);
|
||||
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
const field_name = std.fmt.comptimePrint("{s}", .{field.name});
|
||||
cimgui.c.ImGui_Text("%s", field_name.ptr);
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text(
|
||||
"%s",
|
||||
if (value) "true".ptr else "false".ptr,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
{
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Xterm modify keys");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text(
|
||||
"%s",
|
||||
if (modify_other_keys_2) "true".ptr else "false".ptr,
|
||||
);
|
||||
}
|
||||
}
|
||||
} // keyboard mode info
|
||||
|
||||
}
|
||||
@@ -20,6 +20,9 @@ pub const Info = struct {
|
||||
color_header: widgets.DetachableHeader,
|
||||
modes_header: widgets.DetachableHeader,
|
||||
|
||||
/// Screen detail windows for each screen key.
|
||||
screens: ScreenMap,
|
||||
|
||||
pub const empty: Info = .{
|
||||
.show_palette = false,
|
||||
.misc_header = .{},
|
||||
@@ -27,6 +30,7 @@ pub const Info = struct {
|
||||
.mouse_header = .{},
|
||||
.color_header = .{},
|
||||
.modes_header = .{},
|
||||
.screens = .{},
|
||||
};
|
||||
|
||||
/// Draw the terminal info window.
|
||||
@@ -72,19 +76,59 @@ pub const Info = struct {
|
||||
palette("palette", &t.colors.palette.current);
|
||||
}
|
||||
}
|
||||
|
||||
// Screen pop-out windows
|
||||
var it = self.screens.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const screen = t.screens.get(entry.key) orelse {
|
||||
// Could happen if we opened up a window for a screen
|
||||
// and that screen was subsequently deinitialized. In
|
||||
// this case, hide the window.
|
||||
self.screens.remove(entry.key);
|
||||
continue;
|
||||
};
|
||||
|
||||
var title_buf: [128]u8 = undefined;
|
||||
const title = std.fmt.bufPrintZ(
|
||||
&title_buf,
|
||||
"Screen: {t}",
|
||||
.{entry.key},
|
||||
) catch "Screen";
|
||||
|
||||
// Setup our next window so it has some size to it.
|
||||
const viewport = cimgui.c.ImGui_GetMainViewport();
|
||||
cimgui.c.ImGui_SetNextWindowSize(
|
||||
.{
|
||||
.x = @min(400, viewport.*.Size.x),
|
||||
.y = @min(300, viewport.*.Size.y),
|
||||
},
|
||||
cimgui.c.ImGuiCond_FirstUseEver,
|
||||
);
|
||||
|
||||
var screen_open: bool = true;
|
||||
defer cimgui.c.ImGui_End();
|
||||
const screen_draw = cimgui.c.ImGui_Begin(
|
||||
title,
|
||||
&screen_open,
|
||||
cimgui.c.ImGuiWindowFlags_NoFocusOnAppearing,
|
||||
);
|
||||
entry.value.draw(screen_draw, .{
|
||||
.screen = screen,
|
||||
.key = entry.key,
|
||||
.active_key = t.screens.active_key,
|
||||
.modify_other_keys_2 = t.flags.modify_other_keys_2,
|
||||
.color_palette = &t.colors.palette,
|
||||
});
|
||||
|
||||
// If the window was closed, remove it from our map so future
|
||||
// renders don't draw it.
|
||||
if (!screen_open) self.screens.remove(entry.key);
|
||||
}
|
||||
}
|
||||
|
||||
fn drawOpen(self: *Info, t: *Terminal) void {
|
||||
{
|
||||
widgets.helpMarker(
|
||||
"This window displays the internal state of the terminal. " ++
|
||||
"The terminal state is global to this terminal. Some state " ++
|
||||
"is specific to the active screen or other subsystems. Values " ++
|
||||
"here reflect the running state and will update as the terminal " ++
|
||||
"application modifies them via escape sequences or shell integration. " ++
|
||||
"Some can be modified directly for debugging purposes.",
|
||||
);
|
||||
}
|
||||
// Show our screens up top.
|
||||
screensTable(t, &self.screens);
|
||||
|
||||
if (self.misc_header.header("Misc")) miscTable(t);
|
||||
if (self.layout_header.header("Layout")) layoutTable(t);
|
||||
@@ -94,6 +138,98 @@ pub const Info = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const ScreenMap = std.EnumMap(
|
||||
terminal.ScreenSet.Key,
|
||||
widgets.screen.Info,
|
||||
);
|
||||
|
||||
/// Render the table of possible screens with various actions.
|
||||
fn screensTable(
|
||||
t: *Terminal,
|
||||
map: *ScreenMap,
|
||||
) void {
|
||||
if (!cimgui.c.ImGui_BeginTable(
|
||||
"screens",
|
||||
3,
|
||||
cimgui.c.ImGuiTableFlags_Borders |
|
||||
cimgui.c.ImGuiTableFlags_RowBg |
|
||||
cimgui.c.ImGuiTableFlags_SizingFixedFit,
|
||||
)) return;
|
||||
defer cimgui.c.ImGui_EndTable();
|
||||
|
||||
cimgui.c.ImGui_TableSetupColumn("Screen", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
|
||||
cimgui.c.ImGui_TableSetupColumn("Status", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
|
||||
cimgui.c.ImGui_TableSetupColumn("", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
|
||||
|
||||
// Custom header row to include help marker before "Screen"
|
||||
{
|
||||
cimgui.c.ImGui_TableNextRowEx(cimgui.c.ImGuiTableRowFlags_Headers, 0.0);
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_PushStyleVarImVec2(cimgui.c.ImGuiStyleVar_FramePadding, .{ .x = 0, .y = 0 });
|
||||
widgets.helpMarker(
|
||||
"A terminal can have multiple screens, only one of which is active at " ++
|
||||
"a time. Each screen has its own grid, contents, and other state. " ++
|
||||
"This section allows you to inspect the different screens managed by " ++
|
||||
"the terminal.",
|
||||
);
|
||||
cimgui.c.ImGui_PopStyleVar();
|
||||
cimgui.c.ImGui_SameLineEx(0.0, cimgui.c.ImGui_GetStyle().*.ItemInnerSpacing.x);
|
||||
cimgui.c.ImGui_TableHeader("Screen");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_TableHeader("Status");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
|
||||
cimgui.c.ImGui_TableHeader("");
|
||||
}
|
||||
}
|
||||
|
||||
for (std.meta.tags(terminal.ScreenSet.Key)) |key| {
|
||||
const is_initialized = t.screens.get(key) != null;
|
||||
const is_active = t.screens.active_key == key;
|
||||
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("%s", @tagName(key).ptr);
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
if (is_active) {
|
||||
cimgui.c.ImGui_TextColored(
|
||||
.{ .x = 0.4, .y = 1.0, .z = 0.4, .w = 1.0 },
|
||||
"active",
|
||||
);
|
||||
} else if (is_initialized) {
|
||||
cimgui.c.ImGui_TextColored(
|
||||
.{ .x = 0.6, .y = 0.6, .z = 0.6, .w = 1.0 },
|
||||
"initialized",
|
||||
);
|
||||
} else {
|
||||
cimgui.c.ImGui_TextColored(
|
||||
.{ .x = 0.4, .y = 0.4, .z = 0.4, .w = 1.0 },
|
||||
"(not initialized)",
|
||||
);
|
||||
}
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
|
||||
cimgui.c.ImGui_PushIDInt(@intFromEnum(key));
|
||||
defer cimgui.c.ImGui_PopID();
|
||||
cimgui.c.ImGui_BeginDisabled(!is_initialized);
|
||||
defer cimgui.c.ImGui_EndDisabled();
|
||||
if (cimgui.c.ImGui_Button("View")) {
|
||||
if (!map.contains(key)) {
|
||||
map.put(key, .empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Table of miscellaneous terminal information.
|
||||
fn miscTable(t: *Terminal) void {
|
||||
_ = cimgui.c.ImGui_BeginTable(
|
||||
|
||||
Reference in New Issue
Block a user