linebender / xilem

An experimental Rust native UI framework
Apache License 2.0
3.7k stars 115 forks source link

Calculator example: jumpy relayout and panic when changing window size on macOS #455

Open kud1ing opened 3 months ago

kud1ing commented 3 months ago

Changing the window height leads to jumpy relayouting. This does not happen with changing the window width.

Changing window width and height eventually leads to a panic.

thread 'main' panicked at masonry/src/contexts.rs:746:13:
Error in #87: trying to call 'child_baseline_offset' with child 'Flex' #86 before computing its layout
stack backtrace:
   0: rust_begin_unwind
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/std/src/panicking.rs:652:5
   1: core::panicking::panic_fmt
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/panicking.rs:72:14
   2: masonry::contexts::LayoutCtx::assert_layout_done
             at ./src/util.rs:27:13
   3: masonry::contexts::LayoutCtx::child_baseline_offset
             at ./src/contexts.rs:853:9
   4: <masonry::widget::flex::Flex as masonry::widget::widget::Widget>::layout
             at ./src/widget/flex.rs:769:43
   5: <alloc::boxed::Box<dyn masonry::widget::widget::Widget> as masonry::widget::widget::Widget>::layout
             at ./src/widget/widget.rs:294:9
   6: masonry::widget::widget_pod::WidgetPod<W>::layout_inner
             at ./src/widget/widget_pod.rs:885:13
   7: masonry::widget::widget_pod::WidgetPod<W>::layout::{{closure}}
             at ./src/widget/widget_pod.rs:832:33
   8: masonry::widget::widget_pod::WidgetPod<W>::call_widget_method_with_checks
             at ./src/widget/widget_pod.rs:212:29
   9: masonry::widget::widget_pod::WidgetPod<W>::layout
             at ./src/widget/widget_pod.rs:823:9
  10: <masonry::widget::root_widget::RootWidget<W> as masonry::widget::widget::Widget>::layout
             at ./src/widget/root_widget.rs:60:20
  11: <alloc::boxed::Box<dyn masonry::widget::widget::Widget> as masonry::widget::widget::Widget>::layout
             at ./src/widget/widget.rs:294:9
  12: <alloc::boxed::Box<dyn masonry::widget::widget::Widget> as masonry::widget::widget::Widget>::layout
             at ./src/widget/widget.rs:294:9
  13: masonry::widget::widget_pod::WidgetPod<W>::layout_inner
             at ./src/widget/widget_pod.rs:885:13
  14: masonry::widget::widget_pod::WidgetPod<W>::layout::{{closure}}
             at ./src/widget/widget_pod.rs:832:33
  15: masonry::widget::widget_pod::WidgetPod<W>::call_widget_method_with_checks
             at ./src/widget/widget_pod.rs:212:29
  16: masonry::widget::widget_pod::WidgetPod<W>::layout
             at ./src/widget/widget_pod.rs:823:9
  17: masonry::render_root::RenderRoot::root_layout
             at ./src/render_root.rs:548:13
  18: masonry::render_root::RenderRoot::redraw
             at ./src/render_root.rs:202:13
  19: masonry::event_loop_runner::MasonryState::handle_window_event
             at ./src/event_loop_runner.rs:416:44
  20: <masonry::event_loop_runner::MainState as winit::application::ApplicationHandler<masonry::event_loop_runner::MasonryUserEvent>>::window_event
             at ./src/event_loop_runner.rs:162:9
  21: winit::event_loop::dispatch_event_for_app
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/event_loop.rs:631:52
  22: winit::event_loop::EventLoop<T>::run_app::{{closure}}
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/event_loop.rs:265:49
  23: winit::platform_impl::macos::event_loop::map_user_event::{{closure}}
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/event_loop.rs:163:22
  24: <alloc::boxed::Box<F,A> as core::ops::function::FnMut<Args>>::call_mut
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/alloc/src/boxed.rs:2070:9
  25: winit::platform_impl::macos::event_handler::EventHandler::handle_event
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/event_handler.rs:125:17
  26: winit::platform_impl::macos::app_state::ApplicationDelegate::handle_event
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/app_state.rs:303:9
  27: winit::platform_impl::macos::app_state::ApplicationDelegate::cleared
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/app_state.rs:365:13
  28: winit::platform_impl::macos::observer::control_flow_end_handler::{{closure}}
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/observer.rs:84:21
  29: winit::platform_impl::macos::observer::control_flow_handler::{{closure}}
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/observer.rs:46:9
  30: std::panicking::try::do_call
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/std/src/panicking.rs:559:40
  31: ___rust_try
  32: std::panicking::try
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/std/src/panicking.rs:523:19
  33: std::panic::catch_unwind
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/std/src/panic.rs:149:14
  34: winit::platform_impl::macos::event_loop::stop_app_on_panic
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/event_loop.rs:424:11
  35: winit::platform_impl::macos::observer::control_flow_handler
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/observer.rs:44:5
  36: winit::platform_impl::macos::observer::control_flow_end_handler
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/observer.rs:79:9
  37: <unknown>
  38: <unknown>
  39: <unknown>
  40: <unknown>
  41: <unknown>
  42: <unknown>
  43: <unknown>
  44: <unknown>
  45: <unknown>
  46: <unknown>
  47: <unknown>
  48: <unknown>
  49: <unknown>
  50: <unknown>
  51: <unknown>
  52: <unknown>
  53: <unknown>
  54: <(A,) as objc2::encode::EncodeArguments>::__invoke
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/encode.rs:437:26
  55: objc2::runtime::message_receiver::msg_send_primitive::send_super
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/runtime/message_receiver.rs:193:18
  56: objc2::runtime::message_receiver::MessageReceiver::send_super_message
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/runtime/message_receiver.rs:477:33
  57: objc2::__macro_helpers::msg_send::MsgSend::send_super_message
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/__macro_helpers/msg_send.rs:53:13
  58: objc2::__macro_helpers::msg_send::MsgSend::send_super_message_static
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/__macro_helpers/msg_send.rs:71:18
  59: winit::platform_impl::macos::app::WinitApplication::send_event
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/app.rs:42:26
  60: <unknown>
  61: <unknown>
  62: <() as objc2::encode::EncodeArguments>::__invoke
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/encode.rs:437:26
  63: objc2::runtime::message_receiver::msg_send_primitive::send
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/runtime/message_receiver.rs:173:18
  64: objc2::runtime::message_receiver::MessageReceiver::send_message
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/runtime/message_receiver.rs:433:38
  65: objc2::__macro_helpers::msg_send::MsgSend::send_message
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/__macro_helpers/msg_send.rs:27:31
  66: objc2_app_kit::generated::__NSApplication::NSApplication::run
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/macros/extern_methods.rs:247:14
  67: winit::platform_impl::macos::event_loop::EventLoop<T>::run_on_demand::{{closure}}::{{closure}}
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/event_loop.rs:295:26
  68: objc2::rc::autorelease::autoreleasepool
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/rc/autorelease.rs:438:15
  69: winit::platform_impl::macos::event_loop::EventLoop<T>::run_on_demand::{{closure}}
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/event_loop.rs:281:13
  70: winit::platform_impl::macos::event_handler::EventHandler::set
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/event_handler.rs:98:9
  71: winit::platform_impl::macos::app_state::ApplicationDelegate::set_event_handler
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/app_state.rs:172:9
  72: winit::platform_impl::macos::event_loop::EventLoop<T>::run_on_demand
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/event_loop.rs:280:9
  73: winit::platform_impl::macos::event_loop::EventLoop<T>::run
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/platform_impl/macos/event_loop.rs:267:9
  74: winit::event_loop::EventLoop<T>::run_app
             at .cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.4/src/event_loop.rs:265:9
  75: masonry::event_loop_runner::run_with
             at ./src/event_loop_runner.rs:144:5
  76: masonry::event_loop_runner::run
             at ./src/event_loop_runner.rs:117:5
  77: calc::main
             at ./examples/calc.rs:387:5
  78: core::ops::function::FnOnce::call_once
             at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
17:50:35.582Z ERROR tried to run event handler, but no handler was set
kud1ing commented 3 months ago

This panic was in debug mode. In release mode there are lots of errors/warnings instead:

17:57:28.473Z ERROR layout: Error in #87: trying to call 'child_baseline_offset' with child 'Flex' #52 before computing its layout
17:57:28.473Z ERROR layout: Error in #87: trying to call 'child_size' with child 'Flex' #52 before computing its layout
17:57:28.473Z ERROR layout: Error in #87: trying to call 'place_child' with child 'Flex' #52 before computing its layout
17:57:28.474Z ERROR layout: Error in #88: trying to call 'place_child' with child 'Flex' #87 before computing its layout
17:57:28.474Z ERROR Error in #88: trying to call 'place_child' with child 'RootWidget' #88 before computing its layout
17:57:28.474Z  WARN Widget requested layout during layout pass
17:57:28.580Z ERROR layout: Error in #87: trying to call 'child_baseline_offset' with child 'Flex' #52 before computing its layout
17:57:28.580Z ERROR layout: Error in #87: trying to call 'child_size' with child 'Flex' #52 before computing its layout
17:57:28.580Z ERROR layout: Error in #87: trying to call 'place_child' with child 'Flex' #52 before computing its layout
17:57:28.580Z ERROR layout: Error in #88: trying to call 'place_child' with child 'Flex' #87 before computing its layout
17:57:28.580Z ERROR Error in #88: trying to call 'place_child' with child 'RootWidget' #88 before computing its layout
17:57:28.580Z  WARN Widget requested layout during layout pass
17:57:29.789Z ERROR layout: Error in #87: trying to call 'child_baseline_offset' with child 'Flex' #52 before computing its layout
17:57:29.789Z ERROR layout: Error in #87: trying to call 'child_size' with child 'Flex' #52 before computing its layout
17:57:29.789Z ERROR layout: Error in #87: trying to call 'place_child' with child 'Flex' #52 before computing its layout
17:57:29.789Z ERROR layout: Error in #88: trying to call 'place_child' with child 'Flex' #87 before computing its layout
17:57:29.789Z ERROR Error in #88: trying to call 'place_child' with child 'RootWidget' #88 before computing its layout
jaredoconnell commented 3 months ago

For me, just hovering over buttons is enough to trigger a crash from this.

Error in #87: trying to call 'child_baseline_offset' with child 'Flex' #69 before computing its layout
DJMcNab commented 3 months ago

Thanks for the reports. Are you resizing using a keyboard shortcut rather than the by dragging with the mouse? I can reproduce in that case. I don't know why there should be a settling process in the flex implementation; there might be a caching issue?

The panic @jaredoconnell is related to the hot state. This should be resolved when we implement https://github.com/linebender/rfcs/pull/7, and isn't really possible to fix before then without changing the behaviour of the buttons to not have a border.

This occurs because in calc the buttons add a border/change the border colour when they are hovered over, which requests a layout. And this hot state can be updated in layout, especially if widgets moved around during it.

kud1ing commented 3 months ago

Thank you for your reply.

Are you resizing using a keyboard shortcut rather than the by dragging with the mouse?

I was using the mouse at the window borders/corner to trigger the panic. It's reproducible best when run in debug mode and resizing both window width and height. Sometimes it didn't occur but reappeared after restarting the calc example. Could be a race condition or even undefined behaviour.

The jumpy relayouting when resizing the window height is always reproducible.

DJMcNab commented 3 months ago

Right. I guess your desktop environment is bringing the mouse inside the window as you drag it. I think the crash is the same issue @jaredoconnell is reporting.

Can you provide a video showing the jumpy resizing you're seeing - the effect seemed very subtle to me, and I couldn't notice it just using the mouse.

kud1ing commented 3 months ago

https://github.com/user-attachments/assets/731106e7-2e83-49b8-98d0-390052e378ef

kud1ing commented 3 months ago

In the last few seconds you can see another subtlety: the hovering marker of the button changes.

kud1ing commented 3 months ago

I've first come across the vertical jumpiness/jitteryness with https://github.com/veniamin-ilmer/minesweeper_xilem. But now i suppose it's a problem with the fundamental layouting.