timeline: keep scrolled content out of the track-headers column

- The ruler's canvas does not self-clip in gpui, so scrolled tick labels
  painted over the header spacer/column; the ruler strip now has
  overflow_hidden.
- The playhead was a row-level absolute child painted after the headers,
  so it drew over them when scrolled off the left edge; it now lives
  inside the clip area (clipped by the area's left edge) and still
  paints above the clips.
This commit is contained in:
2026-08-25 02:51:42 +08:00
parent 7497035c12
commit 30aa052ca6
+21 -11
View File
@@ -993,6 +993,12 @@ impl<D: TimelineDataSource> Render for TimelineView<D> {
div()
.flex_1()
.h_full()
// Clip the ruler at the clip area's left edge: the canvas
// paints translated ticks/labels when scrolled, and gpui's
// canvas does not self-clip — without this the labels
// paint over the track-headers column (the headers must
// occlude the timeline, not the other way round).
.overflow_hidden()
.id("timeline-ruler")
.on_mouse_down(
MouseButton::Left,
@@ -1496,15 +1502,20 @@ impl<D: TimelineDataSource> Render for TimelineView<D> {
}))
// The clip-move ghost overlays the rows (an absolute child of the
// clip area; an empty div when no clip drag is active).
.child(clip_ghost_element);
let playhead = div()
.absolute()
.left(px(HEADER_WIDTH + playhead_x))
.top(px(0.))
.bottom(px(0.))
.w(px(1.))
.child(PlayheadElement::new(px(0.), playhead_color()));
.child(clip_ghost_element)
// The playhead lives INSIDE the clip area (clip-area-local x): it
// is clipped by the area's left edge when scrolled off-screen
// instead of painting over the track-headers column, and stays on
// top of the clips.
.child(
div()
.absolute()
.left(px(playhead_x))
.top(px(0.))
.bottom(px(0.))
.w(px(1.))
.child(PlayheadElement::new(px(0.), playhead_color())),
);
div().size_full().flex().flex_col().child(ruler).child(
div()
@@ -1513,8 +1524,7 @@ impl<D: TimelineDataSource> Render for TimelineView<D> {
.flex_1()
.relative()
.child(headers)
.child(clip_area)
.child(playhead),
.child(clip_area),
)
}
}