inspector: track mouse state

This commit is contained in:
Mitchell Hashimoto
2023-10-22 18:02:20 -07:00
parent e40cfc791d
commit bc398327f2
2 changed files with 152 additions and 4 deletions

View File

@ -7,6 +7,7 @@ const std = @import("std");
const builtin = @import("builtin");
const cimgui = @import("cimgui");
const Surface = @import("Surface.zig");
const input = @import("input.zig");
const terminal = @import("terminal/main.zig");
/// The window names. These are used with docking so we need to have access.
@ -22,10 +23,22 @@ surface: *Surface,
/// is used to set up the initial window positions.
first_render: bool = true,
/// Window show states
show_modes_window: bool = true,
show_screen_window: bool = true,
show_size_window: bool = true,
/// Mouse state that we track in addition to normal mouse states that
/// Ghostty always knows about.
mouse: struct {
/// Last hovered x/y
last_xpos: f64 = 0,
last_ypos: f64 = 0,
/// Last hovered screen point
last_point: terminal.point.ScreenPoint = .{},
} = .{},
/// Setup the ImGui state. This requires an ImGui context to be set.
pub fn setup() void {
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
@ -440,7 +453,7 @@ fn renderSizeWindow(self: *Inspector) void {
{
_ = cimgui.c.igTableSetColumnIndex(1);
cimgui.c.igText(
"%d x %d",
"%dpx x %dpx",
self.surface.screen_size.width,
self.surface.screen_size.height,
);
@ -457,7 +470,7 @@ fn renderSizeWindow(self: *Inspector) void {
{
_ = cimgui.c.igTableSetColumnIndex(1);
cimgui.c.igText(
"%d x %d",
"%dc x %dr",
self.surface.grid_size.columns,
self.surface.grid_size.rows,
);
@ -474,7 +487,7 @@ fn renderSizeWindow(self: *Inspector) void {
{
_ = cimgui.c.igTableSetColumnIndex(1);
cimgui.c.igText(
"%d x %d",
"%dpx x %dpx",
self.surface.cell_size.width,
self.surface.cell_size.height,
);
@ -491,7 +504,7 @@ fn renderSizeWindow(self: *Inspector) void {
{
_ = cimgui.c.igTableSetColumnIndex(1);
cimgui.c.igText(
"T=%d B=%d L=%d R=%d",
"T=%d B=%d L=%d R=%d px",
self.surface.padding.top,
self.surface.padding.bottom,
self.surface.padding.left,
@ -543,4 +556,125 @@ fn renderSizeWindow(self: *Inspector) void {
}
}
}
cimgui.c.igSeparatorText("Mouse");
{
_ = cimgui.c.igBeginTable(
"table_mouse",
2,
cimgui.c.ImGuiTableFlags_None,
.{ .x = 0, .y = 0 },
0,
);
defer cimgui.c.igEndTable();
const mouse = &self.surface.mouse;
const t = self.surface.renderer_state.terminal;
{
const hover_point = self.mouse.last_point.toViewport(&t.screen);
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
{
_ = cimgui.c.igTableSetColumnIndex(0);
cimgui.c.igText("Hover Grid");
}
{
_ = cimgui.c.igTableSetColumnIndex(1);
cimgui.c.igText(
"row=%d, col=%d",
hover_point.y,
hover_point.x,
);
}
}
{
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
{
_ = cimgui.c.igTableSetColumnIndex(0);
cimgui.c.igText("Hover Point");
}
{
_ = cimgui.c.igTableSetColumnIndex(1);
cimgui.c.igText(
"(%dpx, %dpx)",
@as(u32, @intFromFloat(self.mouse.last_xpos)),
@as(u32, @intFromFloat(self.mouse.last_ypos)),
);
}
}
const any_click = for (mouse.click_state) |state| {
if (state == .press) break true;
} else false;
click: {
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
{
_ = cimgui.c.igTableSetColumnIndex(0);
cimgui.c.igText("Click State");
}
{
_ = cimgui.c.igTableSetColumnIndex(1);
if (!any_click) {
cimgui.c.igText("none");
break :click;
}
for (mouse.click_state, 0..) |state, i| {
if (state != .press) continue;
const button: input.MouseButton = @enumFromInt(i);
cimgui.c.igSameLine(0, 0);
cimgui.c.igText("%s", (switch (button) {
.unknown => "?",
.left => "L",
.middle => "M",
.right => "R",
.four => "{4}",
.five => "{5}",
.six => "{6}",
.seven => "{7}",
.eight => "{8}",
.nine => "{9}",
.ten => "{10}",
.eleven => "{11}",
}).ptr);
}
}
}
{
const left_click_point = mouse.left_click_point.toViewport(&t.screen);
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
{
_ = cimgui.c.igTableSetColumnIndex(0);
cimgui.c.igText("Click Grid");
}
{
_ = cimgui.c.igTableSetColumnIndex(1);
cimgui.c.igText(
"row=%d, col=%d",
left_click_point.y,
left_click_point.x,
);
}
}
{
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
{
_ = cimgui.c.igTableSetColumnIndex(0);
cimgui.c.igText("Click Point");
}
{
_ = cimgui.c.igTableSetColumnIndex(1);
cimgui.c.igText(
"(%dpx, %dpx)",
@as(u32, @intFromFloat(mouse.left_click_xpos)),
@as(u32, @intFromFloat(mouse.left_click_ypos)),
);
}
}
}
}

View File

@ -1615,6 +1615,9 @@ pub fn mouseButtonCallback(
self.mouse.click_state[@intCast(@intFromEnum(button))] = action;
self.mouse.mods = @bitCast(mods);
// If we have an inspector, we always queue a render
if (self.inspector != null) try self.queueRender();
// Always show the mouse again if it is hidden
if (self.mouse.hidden) self.showMouse();
@ -1788,6 +1791,17 @@ pub fn cursorPosCallback(
self.renderer_state.mutex.lock();
defer self.renderer_state.mutex.unlock();
// If we have an inspector, we need to always record position information
if (self.inspector) |insp| {
insp.mouse.last_xpos = pos.x;
insp.mouse.last_ypos = pos.y;
const point = self.posToViewport(pos.x, pos.y);
insp.mouse.last_point = point.toScreen(&self.io.terminal.screen);
try self.queueRender();
}
// Do a mouse report
if (self.io.terminal.flags.mouse_event != .none) report: {
// Shift overrides mouse "grabbing" in the window, taken from Kitty.