summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/gui.zig37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/gui/gui.zig b/src/gui/gui.zig
index 1a1b1f99..9748d4c0 100644
--- a/src/gui/gui.zig
+++ b/src/gui/gui.zig
@@ -5525,7 +5525,13 @@ fn renderFrame(
const track_index = groupAt(&groups, layer.viewport.x, layer.viewport.y);
// A notice floats over the panes, moving with its own.
const group_index = if (layer.kind == .notice) noticeGroup(&groups, layer) else track_index;
+ const start = cell_next[group_index];
emitTagLayer(g, instances, &cell_next[group_index], layer, win_w, win_h, groups.items[track_index].track, page, cursors_shown, false);
+ // A notice dropping past its row (a flavour's overshoot) stays
+ // inside its pane's body.
+ if (layer.kind == .notice and layer.slide > 0) if (bodyBottom(surface, layer.id, layout)) |bottom| {
+ for (instances[start..cell_next[group_index]]) |*instance| clipInstance(instance, .{ -1e9, -1e9, 1e9, bottom }, win_w, win_h);
+ };
}
for (groups.items[1..][0..groups.tracks], 1..) |group, index| {
const track = group.track.?;
@@ -5894,6 +5900,14 @@ test "the layer cover is the per-cell layer scan, over a core's layouts and rand
}
}
+/// The bottom of pane `owner`'s body, in window pixels.
+fn bodyBottom(surface: *const pardes.Surface, owner: u16, layout: CellLayout) ?f32 {
+ for (surface.regionList()) |region| {
+ if (region.kind == .body and region.owner == owner) return @as(f32, @floatFromInt(region.rect.y + region.rect.h)) * layout.h;
+ }
+ return null;
+}
+
fn tagLayerCellCount(g: *const Gui, layer: *const pardes.Layer) u32 {
const pixels = @as(u32, layer.viewport.w) * g.cell_w;
return @min(layer.cols, (pixels + g.tagline_width - 1) / g.tagline_width);
@@ -6306,6 +6320,29 @@ test "every pixel of a grip column is band, button or ring, and the button sits
pane.file.?.revision = pane.file.?.saved_revision;
}
+test "a rising pane past its mark stays inside its box" {
+ // Bouncy, a vertical rise at its highest overshoot: drawn past its box,
+ // clipped to it.
+ var g: Gui = undefined;
+ g.cell_w = 10;
+ g.cell_h = 20;
+ var track: pardes.animation.Track = .{ .serial = 3, .phase = .opening, .effect = .vertical, .motion = @intFromEnum(pardes.animation.Motion.Flavour.bouncy) + 1, .frame_count = 20, .from = .{ .x = 0, .y = 10, .w = 40, .h = 10 }, .to = .{ .x = 0, .y = 0, .w = 40, .h = 10 } };
+ var peak: u16 = 0;
+ var highest: f32 = 1e9;
+ while (track.frame < track.frames()) : (track.frame += 1) {
+ if (track.presented().y < highest) {
+ highest = track.presented().y;
+ peak = track.frame;
+ }
+ }
+ track.frame = peak;
+ try std.testing.expect(track.presented().y < 0);
+ var instance: CellInstance = std.mem.zeroes(CellInstance);
+ setTransitionFields(&instance, track, fixedCellLayout(&g), 800, 480, 0);
+ try std.testing.expectEqual(@as(f32, 0), instance.clip_y0);
+ try std.testing.expectEqual(@as(f32, 200), instance.clip_y1);
+}
+
test "small tagline fonts leave no background gutters between adjacent tags" {
const chrome: pardes.Chrome = .{};
var g: Gui = undefined;