summaryrefslogtreecommitdiff
path: root/src/pardes.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/pardes.zig')
-rw-r--r--src/pardes.zig41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/pardes.zig b/src/pardes.zig
index b16d39b7..402b3cd8 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -3482,6 +3482,9 @@ pub const Mouse = struct {
col: u16,
row: u16,
ctrl: bool = false,
+ shift: bool = false,
+ /// Alt, which xterm's mouse reports call meta.
+ alt: bool = false,
body_hit: ?BodyHit = null,
tag_hit: ?TagHit = null,
/// A pixel frontend's press on the rule it draws at the top of this row,
@@ -3575,6 +3578,8 @@ pub const Event = union(enum) {
/// The host pointer left the drawable area. Unlike an out-of-range motion,
/// this must not clamp onto and preview the final grid cell.
pointer_leave,
+ /// The window gained (true) or lost the host's keyboard focus.
+ focus: bool,
tick,
};
@@ -4346,6 +4351,13 @@ pub const Pardes = struct {
unattended: bool = false,
haptic: HapticSlot = if (platform == .macos) .none else {},
drag: mouse.Drag = .none,
+ /// A press a terminal's program took (mouse.programMouse): its drags
+ /// and release are the program's too, wherever the pointer goes.
+ mouse_grab: ?mouse.Grab = null,
+ /// Whether the host window has the keyboard (Event.focus), and the pane
+ /// whose program was last told it has it (reportFocus).
+ window_focused: bool = true,
+ focus_told: ?struct { id: usize, serial: u32 } = null,
hover_col: u16 = 0,
hover_row: u16 = 0,
pointer_raw_col: u16 = 0,
@@ -4361,6 +4373,10 @@ pub const Pardes = struct {
chord_hold: bool = false,
/// The look just run found nothing (look.zig missed).
look_missed: bool = false,
+ /// The diff line a right click just expanded to, by row: a look at its
+ /// text goes to the place that row names, not the first equal line
+ /// (look.zig diffLook).
+ diff_look: ?struct { serial: u32, row: usize } = null,
look_hover_wait: ?look.LookHoverWait = null,
/// The place a look-hover last found nothing to open: the pointer
/// resting there does not ask again every frame (look.noteLookHover).
@@ -4502,6 +4518,9 @@ pub const Pardes = struct {
/// the terminal motion surface, memoized against the pane it was built
/// for — see panes.terminal.RowsCache for the lifetime rule
shell_rows: panes.terminal.RowsCache = .{},
+ /// Finished command panes' output, and whether it is a diff
+ /// (File.DiffOutput).
+ diff_output: panes.File.DiffOutput = .{},
/// The message row's entry points, called from everywhere as
/// `p.setMessage(...)`; they live with the rest of it in Messages.zig.
@@ -4752,6 +4771,7 @@ pub const Pardes = struct {
p.locations_cache.deinit(p.tree_sitter_gpa);
p.fs.deinit(gpa);
p.shell_rows.reset(gpa);
+ p.diff_output.reset(gpa);
p.scratch.deinit();
p.frame_arena.deinit();
gpa.free(p.surface.cells);
@@ -5039,6 +5059,25 @@ pub const Pardes = struct {
}
/// The column the keyboard is in: its tag's, or its pane's.
+ /// DECSET 1004: a program that asked is told `CSI I` when its pane
+ /// takes the keyboard (the active pane, its body, the window focused)
+ /// and `CSI O` when it gives it up, to another pane, a tag or header,
+ /// or another window.
+ fn reportFocus(p: *Pardes) void {
+ const want: @FieldType(Pardes, "focus_told") = blk: {
+ if (!p.window_focused or p.header_focus) break :blk null;
+ const pane = p.panes[p.active] orelse break :blk null;
+ if (pane.focus != .body) break :blk null;
+ break :blk .{ .id = p.active, .serial = pane.serial };
+ };
+ if (std.meta.eql(want, p.focus_told)) return;
+ if (p.focus_told) |old| if (p.panes[old.id]) |pane| {
+ if (pane.serial == old.serial and panes.terminal.reportsFocus(pane)) p.emitWrite(old.id, "\x1b[O");
+ };
+ if (want) |new| if (panes.terminal.reportsFocus(p.panes[new.id].?)) p.emitWrite(new.id, "\x1b[I");
+ p.focus_told = want;
+ }
+
pub fn noteTyped(p: *Pardes) void {
if (p.header_focus) {
if (p.header_column) |c| p.setActiveColumn(c);
@@ -5699,6 +5738,7 @@ pub const Pardes = struct {
}
pub fn update(p: *Pardes, ev: Event) void {
+ defer p.reportFocus();
// A tick with nothing animating is the one event that cannot change
// the screen.
p.needs_frame = p.needs_frame or ev != .tick;
@@ -5831,6 +5871,7 @@ pub const Pardes = struct {
.command => |line| _ = p.executeBuiltinLine(p.active, line),
.pinch => |scale| p.ov_pinch_scale = scale,
.touch_scroll => |delta| p.ov_touch_scroll_delta = delta,
+ .focus => |focused| p.window_focused = focused,
.pointer_leave => {
p.pointer_inside = false;
p.pointer_body_hit = null;