* vendor/cimgui

* Add a "dev mode" window which for now is just imgui demo
This commit is contained in:
Mitchell Hashimoto
2022-10-16 16:20:08 -07:00
committed by GitHub
parent ddfb1dec4b
commit f29393bca6
18 changed files with 423 additions and 3 deletions

38
src/DevMode.zig Normal file
View File

@@ -0,0 +1,38 @@
//! This file implements the "dev mode" interface for the terminal. This
//! includes state managements and rendering.
const DevMode = @This();
const imgui = @import("imgui");
/// If this is false, the rest of the terminal will be compiled without
/// dev mode support at all.
pub const enabled = true;
/// The global DevMode instance that can be used app-wide. Assume all functions
/// are NOT thread-safe unless otherwise noted.
pub var instance: DevMode = .{};
/// Whether to show the dev mode UI currently.
visible: bool = false,
/// Update the state associated with the dev mode. This should generally
/// only be called paired with a render since it otherwise wastes CPU
/// cycles.
pub fn update(self: DevMode) void {
_ = self;
imgui.ImplOpenGL3.newFrame();
imgui.ImplGlfw.newFrame();
imgui.newFrame();
// Just demo for now
imgui.showDemoWindow(null);
}
/// Render the scene and return the draw data. The caller must be imgui-aware
/// in order to render the draw data. This lets this file be renderer/backend
/// agnostic.
pub fn render(self: DevMode) !*imgui.DrawData {
_ = self;
imgui.render();
return try imgui.DrawData.get();
}

View File

@@ -12,6 +12,7 @@ const Allocator = std.mem.Allocator;
const Grid = @import("Grid.zig");
const glfw = @import("glfw");
const gl = @import("opengl.zig");
const imgui = @import("imgui");
const libuv = @import("libuv");
const Pty = @import("Pty.zig");
const font = @import("font/main.zig");
@@ -22,6 +23,7 @@ const max_timer = @import("max_timer.zig");
const terminal = @import("terminal/main.zig");
const Config = @import("config.zig").Config;
const input = @import("input.zig");
const DevMode = @import("DevMode.zig");
const RenderTimer = max_timer.MaxTimer(renderTimerCallback);
@@ -45,6 +47,9 @@ window: glfw.Window,
/// The glfw mouse cursor handle.
cursor: glfw.Cursor,
/// Imgui context
imgui_ctx: if (DevMode.enabled) *imgui.Context else void,
/// Whether the window is currently focused
focused: bool,
@@ -475,7 +480,10 @@ pub fn create(alloc: Allocator, loop: libuv.Loop, config: *const Config) !*Windo
.bg_g = @intToFloat(f32, config.background.g) / 255.0,
.bg_b = @intToFloat(f32, config.background.b) / 255.0,
.bg_a = 1.0,
.imgui_ctx = if (!DevMode.enabled) void else try imgui.Context.create(),
};
errdefer if (DevMode.enabled) self.imgui_ctx.destroy();
// Setup our callbacks and user data
window.setUserPointer(self);
@@ -499,10 +507,37 @@ pub fn create(alloc: Allocator, loop: libuv.Loop, config: *const Config) !*Windo
@intCast(i32, window_size.height),
);
// Load imgui. This must be done LAST because it has to be done after
// all our GLFW setup is complete.
if (DevMode.enabled) {
const io = try imgui.IO.get();
io.cval().IniFilename = "ghostty_dev_mode.ini";
// On Mac imgui handles scaling automatically just fine. On Linux
// and other platforms we need to apply a scaling factor.
if (builtin.os.tag != .macos) io.cval().FontGlobalScale = content_scale.x_scale;
const style = try imgui.Style.get();
style.colorsDark();
assert(imgui.ImplGlfw.initForOpenGL(
@ptrCast(*imgui.ImplGlfw.GLFWWindow, window.handle),
true,
));
assert(imgui.ImplOpenGL3.init("#version 330 core"));
}
return self;
}
pub fn destroy(self: *Window) void {
if (DevMode.enabled) {
// Uninitialize imgui
imgui.ImplOpenGL3.shutdown();
imgui.ImplGlfw.shutdown();
self.imgui_ctx.destroy();
}
// Deinitialize the pty. This closes the pty handles. This should
// cause a close in the our subprocess so just wait for that.
self.pty.deinit();
@@ -747,6 +782,7 @@ fn keyCallback(
.F10 => .f10,
.F11 => .f11,
.F12 => .f12,
.grave_accent => .grave_accent,
else => .invalid,
},
};
@@ -795,6 +831,11 @@ fn keyCallback(
log.err("error queueing write in keyCallback err={}", .{err});
}
},
.toggle_dev_mode => if (DevMode.enabled) {
DevMode.instance.visible = !DevMode.instance.visible;
win.render_timer.schedule() catch unreachable;
} else log.warn("dev mode was not compiled into this binary", .{}),
}
// Bindings always result in us ignoring the char if printable
@@ -1109,6 +1150,13 @@ fn mouseButtonCallback(
const win = window.getUserPointer(Window) orelse return;
// If our dev mode window is visible then we always schedule a render on
// cursor move because the cursor might touch our windows.
if (DevMode.enabled and DevMode.instance.visible) {
win.render_timer.schedule() catch |err|
log.err("error scheduling render timer in cursorPosCallback err={}", .{err});
}
// Convert glfw button to input button
const button: input.MouseButton = switch (glfw_button) {
.left => .left,
@@ -1186,6 +1234,13 @@ fn cursorPosCallback(
const win = window.getUserPointer(Window) orelse return;
// If our dev mode window is visible then we always schedule a render on
// cursor move because the cursor might touch our windows.
if (DevMode.enabled and DevMode.instance.visible) {
win.render_timer.schedule() catch |err|
log.err("error scheduling render timer in cursorPosCallback err={}", .{err});
}
// Do a mouse report
if (win.terminal.modes.mouse_event != .none) {
// We use the first mouse button we find pressed in order to report
@@ -1525,6 +1580,12 @@ fn renderTimerCallback(t: *libuv.Timer) void {
return;
};
if (DevMode.enabled and DevMode.instance.visible) {
DevMode.instance.update();
const data = DevMode.instance.render() catch unreachable;
imgui.ImplOpenGL3.renderDrawData(data);
}
// Swap
win.window.swapBuffers() catch |err| {
log.err("error swapping buffers: {}", .{err});

View File

@@ -120,6 +120,13 @@ pub const Config = struct {
try result.keybind.set.put(alloc, .{ .key = .f11 }, .{ .csi = "23~" });
try result.keybind.set.put(alloc, .{ .key = .f12 }, .{ .csi = "24~" });
// Dev Mode
try result.keybind.set.put(
alloc,
.{ .key = .grave_accent, .mods = .{ .shift = true, .super = true } },
.{ .toggle_dev_mode = 0 },
);
return result;
}

View File

@@ -140,6 +140,9 @@ pub const Action = union(enum) {
/// Copy and paste.
copy_to_clipboard: Void,
paste_from_clipboard: Void,
/// Dev mode
toggle_dev_mode: Void,
};
/// Trigger is the associated key state that can trigger an action.

View File

@@ -49,6 +49,9 @@ pub const Key = enum {
y,
z,
// other
grave_accent, // `
// control
up,
down,