summaryrefslogtreecommitdiff
path: root/src/draw.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/draw.zig')
-rw-r--r--src/draw.zig47
1 files changed, 39 insertions, 8 deletions
diff --git a/src/draw.zig b/src/draw.zig
index 4242a6e7..3798bf59 100644
--- a/src/draw.zig
+++ b/src/draw.zig
@@ -163,10 +163,6 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface {
// the pointer per-text (the macOS I-beam) read this as "target" and
// afford it the arrow instead.
if (p.look_hover_preview != null) s.pointer_shape = .target;
- // Stale hover bits must not survive into a frame whose pointer has
- // moved on: the ordinary content paint does not clear fields it
- // never set.
- for (s.cells) |*c| c.hover = false;
for (&s.body_layers) |*layer| layer.rows = 0;
for (&s.tag_layers) |*layer| layer.rows = 0;
s.nimages = 0;
@@ -661,10 +657,11 @@ fn renderHeaderLayer(p: *Pardes, arena: std.mem.Allocator, layer: *pardes.Layer,
var surface: Surface = .{ .cols = columns, .rows = 1, .cells = layer.cells[index * columns ..][0..columns] };
surface.fill(0, 0, columns, 1, .{ .bg = .{ .rgb = bg }, .font_role = .tagline });
_ = surface.print(0, 0, columns, shown[panes.File.rawAtDisplay(shown, scroll)..], .{ .fg = .{ .rgb = fg }, .bg = .{ .rgb = bg }, .font_role = .tagline });
- // The word under the pointer: on a header even while it is edited,
- // but not on a notice (a message is not a command line), nor on a
- // column a carried column's pointer is aiming at a place over.
- const hovered = p.pointer_inside and kind != .notice and !(kind == .column and p.drag == .column_move);
+ // The word under the pointer, a Look or Exec target: on a header even
+ // while it is edited, on a notice, and on the grid's copy of either
+ // (joined from this); not on a column a carried column's pointer is
+ // aiming at a place over.
+ const hovered = p.pointer_inside and !(kind == .column and p.drag == .column_move);
if (hovered) {
const tag_hit = p.pointer_tag_hit;
const col: ?usize = if (tag_hit) |pointer|
@@ -1033,6 +1030,40 @@ test "place puts every part where the painters and layers put it, in every layou
}
}
+test "the word under the pointer on a notice is lit in its layer and in the grid's copy" {
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 41, .rows = 12 });
+ defer p.deinit();
+ _ = try p.setTestFile("text\n");
+ var arena: std.heap.ArenaAllocator = .init(std.testing.allocator);
+ defer arena.deinit();
+ try std.testing.expect(p.executeBuiltinLine(p.active, "Msg Look here"));
+ p.sync();
+ var s = try p.render(arena.allocator());
+ const notice = for (s.regionList()) |region| {
+ if (region.kind == .notice) break region;
+ } else return error.TestExpectedNotice;
+ const row = s.cells[@as(usize, notice.rect.y) * s.cols ..][0..s.cols];
+ // "here", the chip's last word, before its blank edge.
+ const here = notice.rect.x + notice.rect.w - 5;
+ try std.testing.expectEqualStrings("h", row[here].grapheme());
+ p.pointer_inside = true;
+ p.hover_col = here + 1;
+ p.hover_row = notice.rect.y;
+ _ = arena.reset(.retain_capacity);
+ s = try p.render(arena.allocator());
+ const lit = s.cells[@as(usize, notice.rect.y) * s.cols ..][0..s.cols];
+ const sel: Color = .{ .rgb = p.theme().sel_bg };
+ for (lit[here..][0..4]) |cell| try std.testing.expectEqual(sel, cell.style.bg);
+ try std.testing.expect(!std.meta.eql(sel, lit[here - 2].style.bg));
+ const layer = for (s.tagLayers()) |*layer| {
+ if (layer.rows != 0 and layer.kind == .notice) break layer;
+ } else return error.TestExpectedNotice;
+ const lit_in_layer = for (layer.cells) |cell| {
+ if (std.meta.eql(sel, cell.style.bg)) break true;
+ } else false;
+ try std.testing.expect(lit_in_layer);
+}
+
test "a wide glyph cut by a tag's or a notice's edge is joined into the grid as blank, never half drawn" {
const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 41, .rows = 12 });
defer p.deinit();