mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-13 19:15:48 +00:00
inspector: renderer panel
This commit is contained in:
@@ -65,6 +65,12 @@ pub fn deinit(self: *Inspector, alloc: Allocator) void {
|
||||
self.gui.deinit(alloc);
|
||||
}
|
||||
|
||||
/// Returns the renderer info panel. This is a convenience function
|
||||
/// to access and find this state to read and modify.
|
||||
pub fn rendererInfo(self: *Inspector) *widgets.renderer.Info {
|
||||
return &self.gui.renderer_info;
|
||||
}
|
||||
|
||||
/// Record a keyboard event.
|
||||
pub fn recordKeyEvent(
|
||||
self: *Inspector,
|
||||
|
||||
@@ -3,6 +3,7 @@ const cimgui = @import("dcimgui");
|
||||
pub const page = @import("widgets/page.zig");
|
||||
pub const pagelist = @import("widgets/pagelist.zig");
|
||||
pub const key = @import("widgets/key.zig");
|
||||
pub const renderer = @import("widgets/renderer.zig");
|
||||
pub const screen = @import("widgets/screen.zig");
|
||||
pub const style = @import("widgets/style.zig");
|
||||
pub const surface = @import("widgets/surface.zig");
|
||||
|
||||
71
src/inspector/widgets/renderer.zig
Normal file
71
src/inspector/widgets/renderer.zig
Normal file
@@ -0,0 +1,71 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const cimgui = @import("dcimgui");
|
||||
const widgets = @import("../widgets.zig");
|
||||
const renderer = @import("../../renderer.zig");
|
||||
|
||||
const log = std.log.scoped(.inspector_renderer);
|
||||
|
||||
/// Renderer information inspector widget.
|
||||
pub const Info = struct {
|
||||
features: std.AutoArrayHashMapUnmanaged(
|
||||
std.meta.Tag(renderer.Overlay.Feature),
|
||||
renderer.Overlay.Feature,
|
||||
),
|
||||
|
||||
pub const empty: Info = .{
|
||||
.features = .empty,
|
||||
};
|
||||
|
||||
pub fn deinit(self: *Info, alloc: Allocator) void {
|
||||
self.features.deinit(alloc);
|
||||
}
|
||||
|
||||
/// Grab the features into a new allocated slice. This is used by
|
||||
pub fn overlayFeatures(
|
||||
self: *const Info,
|
||||
alloc: Allocator,
|
||||
) Allocator.Error![]renderer.Overlay.Feature {
|
||||
// The features from our internal state.
|
||||
const features = self.features.values();
|
||||
|
||||
// For now we do a dumb copy since the features have no managed
|
||||
// memory.
|
||||
const result = try alloc.dupe(
|
||||
renderer.Overlay.Feature,
|
||||
features,
|
||||
);
|
||||
errdefer alloc.free(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Draw the renderer info window.
|
||||
pub fn draw(
|
||||
self: *Info,
|
||||
alloc: Allocator,
|
||||
open: bool,
|
||||
) void {
|
||||
if (!open) return;
|
||||
|
||||
cimgui.c.ImGui_SeparatorText("Overlays");
|
||||
|
||||
// Hyperlinks
|
||||
{
|
||||
var hyperlinks: bool = self.features.contains(.highlight_hyperlinks);
|
||||
_ = cimgui.c.ImGui_Checkbox("Overlay Hyperlinks", &hyperlinks);
|
||||
cimgui.c.ImGui_SameLine();
|
||||
widgets.helpMarker("When enabled, highlights OSC8 hyperlinks.");
|
||||
|
||||
if (!hyperlinks) {
|
||||
_ = self.features.swapRemove(.highlight_hyperlinks);
|
||||
} else {
|
||||
self.features.put(
|
||||
alloc,
|
||||
.highlight_hyperlinks,
|
||||
.highlight_hyperlinks,
|
||||
) catch log.warn("error enabling hyperlink overlay feature", .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -16,6 +16,7 @@ const window_keyboard = "Keyboard";
|
||||
const window_terminal = "Terminal";
|
||||
const window_surface = "Surface";
|
||||
const window_termio = "Terminal IO";
|
||||
const window_renderer = "Renderer";
|
||||
|
||||
pub const Inspector = struct {
|
||||
/// Internal GUI state
|
||||
@@ -23,6 +24,7 @@ pub const Inspector = struct {
|
||||
key_stream: widgets.key.Stream,
|
||||
terminal_info: widgets.terminal.Info,
|
||||
vt_stream: widgets.termio.Stream,
|
||||
renderer_info: widgets.renderer.Info,
|
||||
|
||||
pub fn init(alloc: Allocator) !Inspector {
|
||||
return .{
|
||||
@@ -30,12 +32,14 @@ pub const Inspector = struct {
|
||||
.key_stream = try .init(alloc),
|
||||
.terminal_info = .empty,
|
||||
.vt_stream = try .init(alloc),
|
||||
.renderer_info = .empty,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Inspector, alloc: Allocator) void {
|
||||
self.key_stream.deinit(alloc);
|
||||
self.vt_stream.deinit(alloc);
|
||||
self.renderer_info.deinit(alloc);
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
@@ -116,6 +120,20 @@ pub const Inspector = struct {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Renderer info window
|
||||
{
|
||||
const open = cimgui.c.ImGui_Begin(
|
||||
window_renderer,
|
||||
null,
|
||||
cimgui.c.ImGuiWindowFlags_NoFocusOnAppearing,
|
||||
);
|
||||
defer cimgui.c.ImGui_End();
|
||||
self.renderer_info.draw(
|
||||
surface.alloc,
|
||||
open,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (first_render) {
|
||||
@@ -157,6 +175,7 @@ pub const Inspector = struct {
|
||||
cimgui.ImGui_DockBuilderDockWindow(window_surface, dock_id_main);
|
||||
cimgui.ImGui_DockBuilderDockWindow(window_keyboard, dock_id_main);
|
||||
cimgui.ImGui_DockBuilderDockWindow(window_termio, dock_id_main);
|
||||
cimgui.ImGui_DockBuilderDockWindow(window_renderer, dock_id_main);
|
||||
cimgui.ImGui_DockBuilderDockWindow(window_imgui_demo, dock_id_main);
|
||||
cimgui.ImGui_DockBuilderFinish(dockspace_id);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ pub const Metal = @import("renderer/Metal.zig");
|
||||
pub const OpenGL = @import("renderer/OpenGL.zig");
|
||||
pub const WebGL = @import("renderer/WebGL.zig");
|
||||
pub const Options = @import("renderer/Options.zig");
|
||||
pub const Overlay = @import("renderer/Overlay.zig");
|
||||
pub const Thread = @import("renderer/Thread.zig");
|
||||
pub const State = @import("renderer/State.zig");
|
||||
pub const CursorStyle = cursor.Style;
|
||||
|
||||
@@ -225,13 +225,6 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
/// Our overlay state, if any.
|
||||
overlay: ?Overlay = null,
|
||||
|
||||
// Right now, the debug overlay is turned on and configured by
|
||||
// modifying these and recompiling. In the future, we will expose
|
||||
// all of this at runtime via the inspector.
|
||||
const overlay_features: []const Overlay.Feature = &.{
|
||||
//.highlight_hyperlinks,
|
||||
};
|
||||
|
||||
const HighlightTag = enum(u8) {
|
||||
search_match,
|
||||
search_match_selected,
|
||||
@@ -1152,6 +1145,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
mouse: renderer.State.Mouse,
|
||||
preedit: ?renderer.State.Preedit,
|
||||
scrollbar: terminal.Scrollbar,
|
||||
overlay_features: []const Overlay.Feature,
|
||||
};
|
||||
|
||||
// Update all our data as tightly as possible within the mutex.
|
||||
@@ -1231,11 +1225,20 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
};
|
||||
};
|
||||
|
||||
const overlay_features: []const Overlay.Feature = overlay: {
|
||||
const insp = state.inspector orelse break :overlay &.{};
|
||||
const renderer_info = insp.rendererInfo();
|
||||
break :overlay renderer_info.overlayFeatures(
|
||||
arena_alloc,
|
||||
) catch &.{};
|
||||
};
|
||||
|
||||
break :critical .{
|
||||
.links = links,
|
||||
.mouse = state.mouse,
|
||||
.preedit = preedit,
|
||||
.scrollbar = scrollbar,
|
||||
.overlay_features = overlay_features,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1306,7 +1309,9 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
|
||||
// Rebuild the overlay image if we have one. We can do this
|
||||
// outside of any critical areas.
|
||||
self.rebuildOverlay() catch |err| {
|
||||
self.rebuildOverlay(
|
||||
critical.overlay_features,
|
||||
) catch |err| {
|
||||
log.warn(
|
||||
"error rebuilding overlay surface err={}",
|
||||
.{err},
|
||||
@@ -2241,7 +2246,10 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
|
||||
/// Build the overlay as configured. Returns null if there is no
|
||||
/// overlay currently configured.
|
||||
fn rebuildOverlay(self: *Self) Overlay.InitError!void {
|
||||
fn rebuildOverlay(
|
||||
self: *Self,
|
||||
features: []const Overlay.Feature,
|
||||
) Overlay.InitError!void {
|
||||
// const start = std.time.Instant.now() catch unreachable;
|
||||
// const start_micro = std.time.microTimestamp();
|
||||
// defer {
|
||||
@@ -2256,7 +2264,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
|
||||
// If we have no features enabled, don't build an overlay.
|
||||
// If we had a previous overlay, deallocate it.
|
||||
if (overlay_features.len == 0) {
|
||||
if (features.len == 0) {
|
||||
if (self.overlay) |*old| {
|
||||
old.deinit(alloc);
|
||||
self.overlay = null;
|
||||
@@ -2277,7 +2285,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
overlay.applyFeatures(
|
||||
alloc,
|
||||
&self.terminal_state,
|
||||
overlay_features,
|
||||
features,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user