Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions rivet/runtime/windows/src/features/address_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ struct Bar {
refresh_inline: bool,
/// The caret the input method's windows were last placed at, in client pixels.
placed: Option<[i32; 4]>,
/// The bar's place, left, top and width in DIPs, when it was last drawn.
drawn_at: Option<[f32; 3]>,
}

thread_local! {
Expand Down Expand Up @@ -312,6 +314,7 @@ fn with_bar<R>(window: HWND, work: impl FnOnce(&mut Bar) -> R) -> R {
refresh_step: None,
refresh_inline: false,
placed: None,
drawn_at: None,
});
work(bar)
})
Expand Down Expand Up @@ -607,6 +610,7 @@ pub(crate) unsafe fn view(window: HWND) -> Option<View> {
if bar.field.as_ref().is_some_and(|field| field.take_changed()) {
bar.generation += 1;
}
bar.drawn_at = Some([x, y, width]);
View {
dev,
url: url.clone(),
Expand Down Expand Up @@ -696,11 +700,21 @@ pub(crate) unsafe fn with_field_pixels<R>(
/// takes the clicks of its controls wherever the browser would put its own title bar.
pub(crate) unsafe fn part_at(window: HWND, point: POINT) -> Option<Part> {
let [x, y, width] = place(window)?;
// The bar takes clicks where it is now. When it was drawn elsewhere, as when the browser moved
// its panel without a repaint after, it is drawn again here before the click can come.
if !busy() && needs_redraw_at(with_bar(window, |bar| bar.drawn_at), [x, y, width]) {
crate::frame::request_bar_paint(window);
}
let f = factor(window);
let (px, py) = (point.x as f32 / f - x, point.y as f32 / f - y);
part_in(width, in_pane(window), dev_reserve(window), px, py)
}

/// Whether a bar drawn at `drawn` must be drawn again to show at `now`, its place for clicks.
pub(crate) fn needs_redraw_at(drawn: Option<[f32; 3]>, now: [f32; 3]) -> bool {
drawn.is_some_and(|drawn| drawn != now)
}

/// The control of a bar `width` DIPs wide at `px`, `py` DIPs from its top left corner, from the
/// same places the bar is painted at.
pub(crate) fn part_in(width: f32, pane: bool, reserve: f32, px: f32, py: f32) -> Option<Part> {
Expand Down Expand Up @@ -1771,6 +1785,18 @@ mod tests {
assert!(!needs_query(true, "exa", "exa", "mple.com"));
}

#[test]
fn fr12_a_bar_drawn_where_it_no_longer_takes_clicks_is_drawn_again() {
// Shown beside the appbar, then folded: the panel moved left and grew.
let shown = [276.0, 8.0, 1156.0];
let folded = [8.0, 8.0, 1424.0];
assert!(needs_redraw_at(Some(shown), folded));
assert!(needs_redraw_at(Some(folded), shown));
assert!(!needs_redraw_at(Some(folded), folded));
// A bar never drawn yet is drawn with the window's first paint.
assert!(!needs_redraw_at(None, folded));
}

#[test]
fn nfr2_a_key_that_shows_nothing_new_draws_nothing() {
let before = Shown {
Expand Down
9 changes: 9 additions & 0 deletions rivet/runtime/windows/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2147,6 +2147,8 @@ unsafe fn toggle_appbar(window: HWND) {
SLIDE.with(|slides| slides.borrow_mut().remove(&(window as isize)));
KillTimer(window, PEEK_TIMER);
relayout(window);
// The panel moves with the appbar, and the top bar with it.
request_bar_paint(window);
}

/// Shows or puts away the floating appbar of a hidden one, sliding it.
Expand Down Expand Up @@ -3469,6 +3471,13 @@ fn panel_moved(window: HWND) {

const BAR_MOVED_MESSAGE: &str = "Rivet.BarMoved";

/// Asks for the top bar to be painted again after the message being handled.
pub(crate) fn request_bar_paint(window: HWND) {
unsafe {
PostMessageW(window, bar_moved_message(), 0, 0);
}
}

fn bar_moved_message() -> u32 {
unsafe { RegisterWindowMessageW(wide(BAR_MOVED_MESSAGE).as_ptr()) }
}
Expand Down
Loading