mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 00:36:07 +03:00
inspector: track mouse state
This commit is contained in:
@ -7,6 +7,7 @@ const std = @import("std");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const cimgui = @import("cimgui");
|
const cimgui = @import("cimgui");
|
||||||
const Surface = @import("Surface.zig");
|
const Surface = @import("Surface.zig");
|
||||||
|
const input = @import("input.zig");
|
||||||
const terminal = @import("terminal/main.zig");
|
const terminal = @import("terminal/main.zig");
|
||||||
|
|
||||||
/// The window names. These are used with docking so we need to have access.
|
/// 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.
|
/// is used to set up the initial window positions.
|
||||||
first_render: bool = true,
|
first_render: bool = true,
|
||||||
|
|
||||||
|
/// Window show states
|
||||||
show_modes_window: bool = true,
|
show_modes_window: bool = true,
|
||||||
show_screen_window: bool = true,
|
show_screen_window: bool = true,
|
||||||
show_size_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.
|
/// Setup the ImGui state. This requires an ImGui context to be set.
|
||||||
pub fn setup() void {
|
pub fn setup() void {
|
||||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||||
@ -440,7 +453,7 @@ fn renderSizeWindow(self: *Inspector) void {
|
|||||||
{
|
{
|
||||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||||
cimgui.c.igText(
|
cimgui.c.igText(
|
||||||
"%d x %d",
|
"%dpx x %dpx",
|
||||||
self.surface.screen_size.width,
|
self.surface.screen_size.width,
|
||||||
self.surface.screen_size.height,
|
self.surface.screen_size.height,
|
||||||
);
|
);
|
||||||
@ -457,7 +470,7 @@ fn renderSizeWindow(self: *Inspector) void {
|
|||||||
{
|
{
|
||||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||||
cimgui.c.igText(
|
cimgui.c.igText(
|
||||||
"%d x %d",
|
"%dc x %dr",
|
||||||
self.surface.grid_size.columns,
|
self.surface.grid_size.columns,
|
||||||
self.surface.grid_size.rows,
|
self.surface.grid_size.rows,
|
||||||
);
|
);
|
||||||
@ -474,7 +487,7 @@ fn renderSizeWindow(self: *Inspector) void {
|
|||||||
{
|
{
|
||||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||||
cimgui.c.igText(
|
cimgui.c.igText(
|
||||||
"%d x %d",
|
"%dpx x %dpx",
|
||||||
self.surface.cell_size.width,
|
self.surface.cell_size.width,
|
||||||
self.surface.cell_size.height,
|
self.surface.cell_size.height,
|
||||||
);
|
);
|
||||||
@ -491,7 +504,7 @@ fn renderSizeWindow(self: *Inspector) void {
|
|||||||
{
|
{
|
||||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||||
cimgui.c.igText(
|
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.top,
|
||||||
self.surface.padding.bottom,
|
self.surface.padding.bottom,
|
||||||
self.surface.padding.left,
|
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)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1615,6 +1615,9 @@ pub fn mouseButtonCallback(
|
|||||||
self.mouse.click_state[@intCast(@intFromEnum(button))] = action;
|
self.mouse.click_state[@intCast(@intFromEnum(button))] = action;
|
||||||
self.mouse.mods = @bitCast(mods);
|
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
|
// Always show the mouse again if it is hidden
|
||||||
if (self.mouse.hidden) self.showMouse();
|
if (self.mouse.hidden) self.showMouse();
|
||||||
|
|
||||||
@ -1788,6 +1791,17 @@ pub fn cursorPosCallback(
|
|||||||
self.renderer_state.mutex.lock();
|
self.renderer_state.mutex.lock();
|
||||||
defer self.renderer_state.mutex.unlock();
|
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
|
// Do a mouse report
|
||||||
if (self.io.terminal.flags.mouse_event != .none) report: {
|
if (self.io.terminal.flags.mouse_event != .none) report: {
|
||||||
// Shift overrides mouse "grabbing" in the window, taken from Kitty.
|
// Shift overrides mouse "grabbing" in the window, taken from Kitty.
|
||||||
|
Reference in New Issue
Block a user