mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-17 17:26:09 +03:00
Imgui (#20)
* vendor/cimgui * Add a "dev mode" window which for now is just imgui demo
This commit is contained in:

committed by
GitHub

parent
ddfb1dec4b
commit
f29393bca6
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -28,3 +28,6 @@
|
|||||||
[submodule "vendor/zig-libxml2"]
|
[submodule "vendor/zig-libxml2"]
|
||||||
path = vendor/zig-libxml2
|
path = vendor/zig-libxml2
|
||||||
url = https://github.com/mitchellh/zig-libxml2.git
|
url = https://github.com/mitchellh/zig-libxml2.git
|
||||||
|
[submodule "vendor/cimgui"]
|
||||||
|
path = vendor/cimgui
|
||||||
|
url = https://github.com/cimgui/cimgui.git
|
||||||
|
13
build.zig
13
build.zig
@ -6,6 +6,7 @@ const glfw = @import("vendor/mach/libs/glfw/build.zig");
|
|||||||
const fontconfig = @import("pkg/fontconfig/build.zig");
|
const fontconfig = @import("pkg/fontconfig/build.zig");
|
||||||
const freetype = @import("pkg/freetype/build.zig");
|
const freetype = @import("pkg/freetype/build.zig");
|
||||||
const harfbuzz = @import("pkg/harfbuzz/build.zig");
|
const harfbuzz = @import("pkg/harfbuzz/build.zig");
|
||||||
|
const imgui = @import("pkg/imgui/build.zig");
|
||||||
const libxml2 = @import("vendor/zig-libxml2/libxml2.zig");
|
const libxml2 = @import("vendor/zig-libxml2/libxml2.zig");
|
||||||
const libuv = @import("pkg/libuv/build.zig");
|
const libuv = @import("pkg/libuv/build.zig");
|
||||||
const libpng = @import("pkg/libpng/build.zig");
|
const libpng = @import("pkg/libpng/build.zig");
|
||||||
@ -189,6 +190,7 @@ fn addDeps(
|
|||||||
if (enable_fontconfig) step.addPackage(fontconfig.pkg);
|
if (enable_fontconfig) step.addPackage(fontconfig.pkg);
|
||||||
step.addPackage(freetype.pkg);
|
step.addPackage(freetype.pkg);
|
||||||
step.addPackage(harfbuzz.pkg);
|
step.addPackage(harfbuzz.pkg);
|
||||||
|
step.addPackage(imgui.pkg);
|
||||||
step.addPackage(glfw.pkg);
|
step.addPackage(glfw.pkg);
|
||||||
step.addPackage(libuv.pkg);
|
step.addPackage(libuv.pkg);
|
||||||
step.addPackage(utf8proc.pkg);
|
step.addPackage(utf8proc.pkg);
|
||||||
@ -214,10 +216,15 @@ fn addDeps(
|
|||||||
_ = try utf8proc.link(b, step);
|
_ = try utf8proc.link(b, step);
|
||||||
|
|
||||||
// Glfw
|
// Glfw
|
||||||
try glfw.link(b, step, .{
|
const glfw_opts: glfw.Options = .{ .metal = false, .opengl = false };
|
||||||
.metal = false,
|
try glfw.link(b, step, glfw_opts);
|
||||||
.opengl = false, // Found at runtime
|
|
||||||
|
// Imgui
|
||||||
|
const imgui_backends = [_][]const u8{ "glfw", "opengl3" };
|
||||||
|
const imgui_step = try imgui.link(b, step, .{
|
||||||
|
.backends = &imgui_backends,
|
||||||
});
|
});
|
||||||
|
try glfw.link(b, imgui_step, glfw_opts);
|
||||||
|
|
||||||
// Dynamic link
|
// Dynamic link
|
||||||
if (!static) {
|
if (!static) {
|
||||||
|
93
pkg/imgui/build.zig
Normal file
93
pkg/imgui/build.zig
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
/// Directories with our includes.
|
||||||
|
const root = thisDir() ++ "../../../vendor/cimgui/";
|
||||||
|
pub const include_paths = [_][]const u8{
|
||||||
|
root,
|
||||||
|
root ++ "imgui",
|
||||||
|
root ++ "imgui/backends",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const pkg = std.build.Pkg{
|
||||||
|
.name = "imgui",
|
||||||
|
.source = .{ .path = thisDir() ++ "/main.zig" },
|
||||||
|
};
|
||||||
|
|
||||||
|
fn thisDir() []const u8 {
|
||||||
|
return std.fs.path.dirname(@src().file) orelse ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Options = struct {
|
||||||
|
backends: ?[]const []const u8 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn link(
|
||||||
|
b: *std.build.Builder,
|
||||||
|
step: *std.build.LibExeObjStep,
|
||||||
|
opt: Options,
|
||||||
|
) !*std.build.LibExeObjStep {
|
||||||
|
const lib = try buildImgui(b, step, opt);
|
||||||
|
step.linkLibrary(lib);
|
||||||
|
inline for (include_paths) |path| step.addIncludePath(path);
|
||||||
|
return lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buildImgui(
|
||||||
|
b: *std.build.Builder,
|
||||||
|
step: *std.build.LibExeObjStep,
|
||||||
|
opt: Options,
|
||||||
|
) !*std.build.LibExeObjStep {
|
||||||
|
const target = step.target;
|
||||||
|
const lib = b.addStaticLibrary("imgui", null);
|
||||||
|
lib.setTarget(step.target);
|
||||||
|
lib.setBuildMode(step.build_mode);
|
||||||
|
|
||||||
|
// Include
|
||||||
|
inline for (include_paths) |path| lib.addIncludePath(path);
|
||||||
|
|
||||||
|
// Link
|
||||||
|
lib.linkLibC();
|
||||||
|
|
||||||
|
// Compile
|
||||||
|
var flags = std.ArrayList([]const u8).init(b.allocator);
|
||||||
|
defer flags.deinit();
|
||||||
|
try flags.appendSlice(&.{
|
||||||
|
"-DIMGUI_DISABLE_OBSOLETE_FUNCTIONS=1",
|
||||||
|
|
||||||
|
//"-fno-sanitize=undefined",
|
||||||
|
});
|
||||||
|
switch (target.getOsTag()) {
|
||||||
|
.windows => try flags.appendSlice(&.{
|
||||||
|
"-DIMGUI_IMPL_API=extern\t\"C\"\t__declspec(dllexport)",
|
||||||
|
}),
|
||||||
|
else => try flags.appendSlice(&.{
|
||||||
|
"-DIMGUI_IMPL_API=extern\t\"C\"\t",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// C files
|
||||||
|
lib.addCSourceFiles(srcs, flags.items);
|
||||||
|
if (opt.backends) |backends| {
|
||||||
|
for (backends) |backend| {
|
||||||
|
var buf: [4096]u8 = undefined;
|
||||||
|
const path = try std.fmt.bufPrint(
|
||||||
|
&buf,
|
||||||
|
"{s}imgui/backends/imgui_impl_{s}.cpp",
|
||||||
|
.{ root, backend },
|
||||||
|
);
|
||||||
|
|
||||||
|
lib.addCSourceFile(path, flags.items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
const srcs = &.{
|
||||||
|
root ++ "cimgui.cpp",
|
||||||
|
root ++ "imgui/imgui.cpp",
|
||||||
|
root ++ "imgui/imgui_demo.cpp",
|
||||||
|
root ++ "imgui/imgui_draw.cpp",
|
||||||
|
root ++ "imgui/imgui_tables.cpp",
|
||||||
|
root ++ "imgui/imgui_widgets.cpp",
|
||||||
|
};
|
4
pkg/imgui/c.zig
Normal file
4
pkg/imgui/c.zig
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub usingnamespace @cImport({
|
||||||
|
@cDefine("CIMGUI_DEFINE_ENUMS_AND_STRUCTS", "");
|
||||||
|
@cInclude("cimgui.h");
|
||||||
|
});
|
28
pkg/imgui/context.zig
Normal file
28
pkg/imgui/context.zig
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
pub const Context = opaque {
|
||||||
|
pub fn create() Allocator.Error!*Context {
|
||||||
|
return @ptrCast(
|
||||||
|
?*Context,
|
||||||
|
c.igCreateContext(null),
|
||||||
|
) orelse Allocator.Error.OutOfMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroy(self: *Context) void {
|
||||||
|
c.igDestroyContext(self.cval());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn cval(self: *Context) *c.ImGuiContext {
|
||||||
|
return @ptrCast(
|
||||||
|
*c.ImGuiContext,
|
||||||
|
@alignCast(@alignOf(c.ImGuiContext), self),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test {
|
||||||
|
var ctx = try Context.create();
|
||||||
|
defer ctx.destroy();
|
||||||
|
}
|
20
pkg/imgui/core.zig
Normal file
20
pkg/imgui/core.zig
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
const imgui = @import("main.zig");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
pub fn newFrame() void {
|
||||||
|
c.igNewFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn endFrame() void {
|
||||||
|
c.igEndFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render() void {
|
||||||
|
c.igRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn showDemoWindow(open: ?*bool) void {
|
||||||
|
c.igShowDemoWindow(@ptrCast([*c]bool, if (open) |v| v else null));
|
||||||
|
}
|
20
pkg/imgui/draw_data.zig
Normal file
20
pkg/imgui/draw_data.zig
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
const imgui = @import("main.zig");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
pub const DrawData = opaque {
|
||||||
|
pub fn get() Allocator.Error!*DrawData {
|
||||||
|
return @ptrCast(
|
||||||
|
?*DrawData,
|
||||||
|
c.igGetDrawData(),
|
||||||
|
) orelse Allocator.Error.OutOfMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn cval(self: *DrawData) *c.ImGuiDrawData {
|
||||||
|
return @ptrCast(
|
||||||
|
*c.ImGuiDrawData,
|
||||||
|
@alignCast(@alignOf(c.ImGuiDrawData), self),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
28
pkg/imgui/impl_glfw.zig
Normal file
28
pkg/imgui/impl_glfw.zig
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
const imgui = @import("main.zig");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
pub const ImplGlfw = struct {
|
||||||
|
pub const GLFWWindow = opaque {};
|
||||||
|
|
||||||
|
pub fn initForOpenGL(win: *GLFWWindow, install_callbacks: bool) bool {
|
||||||
|
// https://github.com/ocornut/imgui/issues/5785
|
||||||
|
defer _ = glfwGetError(null);
|
||||||
|
|
||||||
|
return ImGui_ImplGlfw_InitForOpenGL(win, install_callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shutdown() void {
|
||||||
|
return ImGui_ImplGlfw_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn newFrame() void {
|
||||||
|
return ImGui_ImplGlfw_NewFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "c" fn glfwGetError(?*const anyopaque) c_int;
|
||||||
|
extern "c" fn ImGui_ImplGlfw_InitForOpenGL(*GLFWWindow, bool) bool;
|
||||||
|
extern "c" fn ImGui_ImplGlfw_Shutdown() void;
|
||||||
|
extern "c" fn ImGui_ImplGlfw_NewFrame() void;
|
||||||
|
};
|
30
pkg/imgui/impl_opengl3.zig
Normal file
30
pkg/imgui/impl_opengl3.zig
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
const imgui = @import("main.zig");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
pub const ImplOpenGL3 = struct {
|
||||||
|
pub fn init(glsl_version: ?[:0]const u8) bool {
|
||||||
|
return ImGui_ImplOpenGL3_Init(
|
||||||
|
if (glsl_version) |s| s.ptr else null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shutdown() void {
|
||||||
|
return ImGui_ImplOpenGL3_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn newFrame() void {
|
||||||
|
return ImGui_ImplOpenGL3_NewFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn renderDrawData(data: *imgui.DrawData) void {
|
||||||
|
ImGui_ImplOpenGL3_RenderDrawData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "c" fn glfwGetError(?*const anyopaque) c_int;
|
||||||
|
extern "c" fn ImGui_ImplOpenGL3_Init([*c]const u8) bool;
|
||||||
|
extern "c" fn ImGui_ImplOpenGL3_Shutdown() void;
|
||||||
|
extern "c" fn ImGui_ImplOpenGL3_NewFrame() void;
|
||||||
|
extern "c" fn ImGui_ImplOpenGL3_RenderDrawData(*imgui.DrawData) void;
|
||||||
|
};
|
26
pkg/imgui/io.zig
Normal file
26
pkg/imgui/io.zig
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
const imgui = @import("main.zig");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
pub const IO = opaque {
|
||||||
|
pub fn get() Allocator.Error!*IO {
|
||||||
|
return @ptrCast(
|
||||||
|
?*IO,
|
||||||
|
c.igGetIO(),
|
||||||
|
) orelse Allocator.Error.OutOfMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn cval(self: *IO) *c.ImGuiIO {
|
||||||
|
return @ptrCast(
|
||||||
|
*c.ImGuiIO,
|
||||||
|
@alignCast(@alignOf(c.ImGuiIO), self),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test {
|
||||||
|
const ctx = try imgui.Context.create();
|
||||||
|
defer ctx.destroy();
|
||||||
|
_ = try IO.get();
|
||||||
|
}
|
13
pkg/imgui/main.zig
Normal file
13
pkg/imgui/main.zig
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
pub const c = @import("c.zig");
|
||||||
|
pub usingnamespace @import("context.zig");
|
||||||
|
pub usingnamespace @import("core.zig");
|
||||||
|
pub usingnamespace @import("draw_data.zig");
|
||||||
|
pub usingnamespace @import("io.zig");
|
||||||
|
pub usingnamespace @import("style.zig");
|
||||||
|
|
||||||
|
pub usingnamespace @import("impl_glfw.zig");
|
||||||
|
pub usingnamespace @import("impl_opengl3.zig");
|
||||||
|
|
||||||
|
test {
|
||||||
|
@import("std").testing.refAllDecls(@This());
|
||||||
|
}
|
35
pkg/imgui/style.zig
Normal file
35
pkg/imgui/style.zig
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
pub const Style = opaque {
|
||||||
|
pub fn get() Allocator.Error!*Style {
|
||||||
|
return @ptrCast(
|
||||||
|
?*Style,
|
||||||
|
c.igGetStyle(),
|
||||||
|
) orelse Allocator.Error.OutOfMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn colorsDark(self: *Style) void {
|
||||||
|
c.igStyleColorsDark(self.cval());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn colorsLight(self: *Style) void {
|
||||||
|
c.igStyleColorsLight(self.cval());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn colorsClassic(self: *Style) void {
|
||||||
|
c.igStyleColorsClassic(self.cval());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scaleAllSizes(self: *Style, factor: f32) void {
|
||||||
|
c.ImGuiStyle_ScaleAllSizes(self.cval(), factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn cval(self: *Style) *c.ImGuiStyle {
|
||||||
|
return @ptrCast(
|
||||||
|
*c.ImGuiStyle,
|
||||||
|
@alignCast(@alignOf(c.ImGuiStyle), self),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
38
src/DevMode.zig
Normal file
38
src/DevMode.zig
Normal 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();
|
||||||
|
}
|
@ -12,6 +12,7 @@ const Allocator = std.mem.Allocator;
|
|||||||
const Grid = @import("Grid.zig");
|
const Grid = @import("Grid.zig");
|
||||||
const glfw = @import("glfw");
|
const glfw = @import("glfw");
|
||||||
const gl = @import("opengl.zig");
|
const gl = @import("opengl.zig");
|
||||||
|
const imgui = @import("imgui");
|
||||||
const libuv = @import("libuv");
|
const libuv = @import("libuv");
|
||||||
const Pty = @import("Pty.zig");
|
const Pty = @import("Pty.zig");
|
||||||
const font = @import("font/main.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 terminal = @import("terminal/main.zig");
|
||||||
const Config = @import("config.zig").Config;
|
const Config = @import("config.zig").Config;
|
||||||
const input = @import("input.zig");
|
const input = @import("input.zig");
|
||||||
|
const DevMode = @import("DevMode.zig");
|
||||||
|
|
||||||
const RenderTimer = max_timer.MaxTimer(renderTimerCallback);
|
const RenderTimer = max_timer.MaxTimer(renderTimerCallback);
|
||||||
|
|
||||||
@ -45,6 +47,9 @@ window: glfw.Window,
|
|||||||
/// The glfw mouse cursor handle.
|
/// The glfw mouse cursor handle.
|
||||||
cursor: glfw.Cursor,
|
cursor: glfw.Cursor,
|
||||||
|
|
||||||
|
/// Imgui context
|
||||||
|
imgui_ctx: if (DevMode.enabled) *imgui.Context else void,
|
||||||
|
|
||||||
/// Whether the window is currently focused
|
/// Whether the window is currently focused
|
||||||
focused: bool,
|
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_g = @intToFloat(f32, config.background.g) / 255.0,
|
||||||
.bg_b = @intToFloat(f32, config.background.b) / 255.0,
|
.bg_b = @intToFloat(f32, config.background.b) / 255.0,
|
||||||
.bg_a = 1.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
|
// Setup our callbacks and user data
|
||||||
window.setUserPointer(self);
|
window.setUserPointer(self);
|
||||||
@ -499,10 +507,37 @@ pub fn create(alloc: Allocator, loop: libuv.Loop, config: *const Config) !*Windo
|
|||||||
@intCast(i32, window_size.height),
|
@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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *Window) void {
|
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
|
// Deinitialize the pty. This closes the pty handles. This should
|
||||||
// cause a close in the our subprocess so just wait for that.
|
// cause a close in the our subprocess so just wait for that.
|
||||||
self.pty.deinit();
|
self.pty.deinit();
|
||||||
@ -747,6 +782,7 @@ fn keyCallback(
|
|||||||
.F10 => .f10,
|
.F10 => .f10,
|
||||||
.F11 => .f11,
|
.F11 => .f11,
|
||||||
.F12 => .f12,
|
.F12 => .f12,
|
||||||
|
.grave_accent => .grave_accent,
|
||||||
else => .invalid,
|
else => .invalid,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -795,6 +831,11 @@ fn keyCallback(
|
|||||||
log.err("error queueing write in keyCallback err={}", .{err});
|
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
|
// Bindings always result in us ignoring the char if printable
|
||||||
@ -1109,6 +1150,13 @@ fn mouseButtonCallback(
|
|||||||
|
|
||||||
const win = window.getUserPointer(Window) orelse return;
|
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
|
// Convert glfw button to input button
|
||||||
const button: input.MouseButton = switch (glfw_button) {
|
const button: input.MouseButton = switch (glfw_button) {
|
||||||
.left => .left,
|
.left => .left,
|
||||||
@ -1186,6 +1234,13 @@ fn cursorPosCallback(
|
|||||||
|
|
||||||
const win = window.getUserPointer(Window) orelse return;
|
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
|
// Do a mouse report
|
||||||
if (win.terminal.modes.mouse_event != .none) {
|
if (win.terminal.modes.mouse_event != .none) {
|
||||||
// We use the first mouse button we find pressed in order to report
|
// We use the first mouse button we find pressed in order to report
|
||||||
@ -1525,6 +1580,12 @@ fn renderTimerCallback(t: *libuv.Timer) void {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (DevMode.enabled and DevMode.instance.visible) {
|
||||||
|
DevMode.instance.update();
|
||||||
|
const data = DevMode.instance.render() catch unreachable;
|
||||||
|
imgui.ImplOpenGL3.renderDrawData(data);
|
||||||
|
}
|
||||||
|
|
||||||
// Swap
|
// Swap
|
||||||
win.window.swapBuffers() catch |err| {
|
win.window.swapBuffers() catch |err| {
|
||||||
log.err("error swapping buffers: {}", .{err});
|
log.err("error swapping buffers: {}", .{err});
|
||||||
|
@ -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 = .f11 }, .{ .csi = "23~" });
|
||||||
try result.keybind.set.put(alloc, .{ .key = .f12 }, .{ .csi = "24~" });
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +140,9 @@ pub const Action = union(enum) {
|
|||||||
/// Copy and paste.
|
/// Copy and paste.
|
||||||
copy_to_clipboard: Void,
|
copy_to_clipboard: Void,
|
||||||
paste_from_clipboard: Void,
|
paste_from_clipboard: Void,
|
||||||
|
|
||||||
|
/// Dev mode
|
||||||
|
toggle_dev_mode: Void,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Trigger is the associated key state that can trigger an action.
|
/// Trigger is the associated key state that can trigger an action.
|
||||||
|
@ -49,6 +49,9 @@ pub const Key = enum {
|
|||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
|
|
||||||
|
// other
|
||||||
|
grave_accent, // `
|
||||||
|
|
||||||
// control
|
// control
|
||||||
up,
|
up,
|
||||||
down,
|
down,
|
||||||
|
1
vendor/cimgui
vendored
Submodule
1
vendor/cimgui
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 9ce2c32dada1e1fcb90f2c9bab2568895db719f5
|
Reference in New Issue
Block a user