iced icon indicating copy to clipboard operation
iced copied to clipboard

Integration Example uses wrong viewport size for one frame after window resize.

Open pimpale opened this issue 10 months ago • 0 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues.

Is this issue related to iced?

  • [X] My hardware is compatible and my graphics drivers are up-to-date.

What happened?

In the integration example, the first frame after every window resize still uses the old viewport size to layout the UI. This is especially noticeable if you use a tiling window manager. The UI fixes itself after you interact with the window, by hovering the mouse or interacting with it. Below, I've included some screenshots displaying the bug.

After resizing window: Screenshot from 2023-08-18 17-18-34

After interacting with the window: Screenshot from 2023-08-18 17-17-29

What is the expected behavior?

I expected the UI to render using the correct new window size.

Cause of the bug:

The code to handle window events marks that a resize is necessary after a window resizes. However, it does not change the viewport variable yet.

match event {
    WindowEvent::CursorMoved { position, .. } => {
        cursor_position = Some(position);
    }
    WindowEvent::ModifiersChanged(new_modifiers) => {
        modifiers = new_modifiers;
    }
    WindowEvent::Resized(_) => {
        resized = true;
    }
    WindowEvent::CloseRequested => {
        *control_flow = ControlFlow::Exit;
    }
    _ => {}
}
// Map window event to iced event
if let Some(event) = iced_winit::conversion::window_event(
    &event,
    window.scale_factor(),
    modifiers,
) {
    state.queue_event(event);
}

After this, the control flow then goes to the Event::MainEventsCleared branch of the event loop. Here, we use the un-updated version of viewport to build the UI:

Event::MainEventsCleared => {
    // If there are events pending
    if !state.is_queue_empty() {
        // We update iced
        let _ = state.update(
            viewport.logical_size(),
            cursor_position
                .map(|p| {
                    conversion::cursor_position(
                        p,
                        viewport.scale_factor(),
                    )
                })
                .map(mouse::Cursor::Available)
                .unwrap_or(mouse::Cursor::Unavailable),
            &mut renderer,
            &Theme::Dark,
            &renderer::Style {
                text_color: Color::WHITE,
            },
            &mut clipboard,
            &mut debug,
        );

        // and request a redraw
        window.request_redraw();
    }
}

After this, we go to the Event::RedrawRequested branch of the event loop. Here, viewport is finally updated. However, we should be updating it earlier so that the UI update has access to the correct bounds.

Solution:

I believe this problem would be solved by adding the following line here:

viewport = Viewport::with_physical_size(
    Size::new(size.width, size.height),
    window.scale_factor(),
);

Version

master

Operating System

Linux

Do you have any log output?

No response

pimpale avatar Aug 19 '23 00:08 pimpale