slint-ui / slint

Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
https://slint.dev
Other
17.58k stars 604 forks source link

Infinitely growing layout #2902

Open tp971 opened 1 year ago

tp971 commented 1 year ago

The following code produces an infinitely growing window:

fn main() {
    MainWindow::new().unwrap().run().unwrap();
}

slint::slint! {
    import { HorizontalBox, VerticalBox } from "std-widgets.slint";

    export component MainWindow inherits Window {
        HorizontalBox {
            VerticalBox {
                width: parent.width;
                height: parent.height;
                Text {
                    text: "Test";
                }
            }
        }
    }
}

(the exact behaviour differs between backends, sometimes it doesn't grow or randomly stops growing)

I guess the expected behaviour here is to detect a binding loop?

ogoffart commented 1 year ago

I can reroduce the problem: With Qt: the layout grows With winit: the size is fixed.

We could try to detect that as a binding loop. The question is how. Should we make a link between the width/height of a window and the preferred/minimum/maximum size? that may break existing application, maybe just a warning?

ogoffart commented 1 year ago

(This was also tracked in https://github.com/slint-ui/slint/issues/257 , but i closed it in favor of this one)

almindor commented 1 year ago

This seems similar to what I'm getting with this UI:

import { Button } from "std-widgets.slint";

export component MainWindow inherits Window {
    VerticalLayout {
        width: parent.width;
        height: parent.height;

        Button { 
            text: "Button";
        }

        Rectangle {
            width: parent.width;
            height: parent.height; // this is the problem
        }
    }
}

This produces a black-out window that starts normal but blacks out eventually (on wayland/sway linux).

qarmin commented 9 months ago

Now with slint lsp (nightly 1.4.1)

    import { HorizontalBox, VerticalBox } from "std-widgets.slint";

    export component MainWindow inherits Window {
        HorizontalBox {
            VerticalBox {
                width: parent.width;
                height: parent.height;
                Text {
                    text: "Test";
                }
            }
        }
    }

I have such panic

thread 'main' panicked at /home/runner/work/slint/slint/internal/core/properties.rs:486:9:
Recursion detected
stack backtrace:
   0: rust_begin_unwind
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/std/src/panicking.rs:645:5
   1: core::panicking::panic_fmt
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/panicking.rs:72:14
   2: i_slint_core::properties::Property<T>::get
   3: <field_offset::FieldOffset<Item,i_slint_core::properties::Property<T>,field_offset::AllowPin> as i_slint_core::rtti::PropertyInfo<Item,Value>>::get
   4: slint_interpreter::eval::load_property_helper
   5: slint_interpreter::eval_layout::get_layout_info
   6: slint_interpreter::dynamic_item_tree::layout_info
   7: slint_interpreter::dynamic_item_tree::COMPONENT_BOX_VT::layout_info
   8: core::ops::function::FnOnce::call_once
   9: i_slint_core::properties::alloc_binding_holder::evaluate
  10: i_slint_core::properties::Property<T>::get
  11: core::ops::function::FnOnce::call_once
  12: i_slint_core::properties::alloc_binding_holder::evaluate
  13: i_slint_core::properties::Property<T>::get
  14: i_slint_core::properties::alloc_binding_holder::evaluate
  15: i_slint_core::properties::Property<T>::get
  16: <i_slint_core::rtti::MaybeAnimatedPropertyInfoWrapper<Item,i_slint_core::properties::Property<T>> as i_slint_core::rtti::PropertyInfo<Item,Value>>::get
  17: <&dyn i_slint_core::rtti::PropertyInfo<Item,slint_interpreter::api::Value> as slint_interpreter::eval::ErasedPropertyInfo>::get
  18: slint_interpreter::eval::load_property_helper
  19: slint_interpreter::eval::eval_expression
  20: slint_interpreter::dynamic_item_tree::make_binding_eval_closure::{{closure}}
  21: i_slint_core::properties::alloc_binding_holder::evaluate
  22: i_slint_core::properties::Property<T>::get
  23: <i_slint_core::rtti::MaybeAnimatedPropertyInfoWrapper<Item,i_slint_core::properties::Property<T>> as i_slint_core::rtti::PropertyInfo<Item,Value>>::get
  24: slint_interpreter::eval::load_property_helper
  25: slint_interpreter::eval::eval_expression
  26: slint_interpreter::dynamic_item_tree::make_binding_eval_closure::{{closure}}
  27: i_slint_core::properties::alloc_binding_holder::evaluate
  28: i_slint_core::properties::Property<T>::get
  29: <i_slint_core::rtti::MaybeAnimatedPropertyInfoWrapper<Item,i_slint_core::properties::Property<T>> as i_slint_core::rtti::PropertyInfo<Item,Value>>::get
  30: slint_interpreter::eval::load_property_helper
  31: slint_interpreter::eval_layout::compute_layout_info::{{closure}}
  32: slint_interpreter::eval_layout::fill_layout_info_constraints
  33: slint_interpreter::eval_layout::compute_layout_info
  34: slint_interpreter::dynamic_item_tree::make_binding_eval_closure::{{closure}}
  35: i_slint_core::properties::alloc_binding_holder::evaluate
  36: i_slint_core::properties::Property<T>::get
  37: <field_offset::FieldOffset<Item,i_slint_core::properties::Property<T>,field_offset::AllowPin> as i_slint_core::rtti::PropertyInfo<Item,Value>>::get
  38: slint_interpreter::eval::load_property_helper
  39: slint_interpreter::eval::eval_expression
  40: slint_interpreter::eval::eval_expression
  41: slint_interpreter::dynamic_item_tree::make_binding_eval_closure::{{closure}}
  42: i_slint_core::properties::alloc_binding_holder::evaluate
  43: i_slint_core::properties::Property<T>::get
  44: <field_offset::FieldOffset<Item,i_slint_core::properties::Property<T>,field_offset::AllowPin> as i_slint_core::rtti::PropertyInfo<Item,Value>>::get
  45: slint_interpreter::eval::load_property_helper
  46: slint_interpreter::eval_layout::get_layout_info
  47: slint_interpreter::dynamic_item_tree::layout_info
  48: slint_interpreter::dynamic_item_tree::COMPONENT_BOX_VT::layout_info
  49: core::ops::function::FnOnce::call_once
  50: i_slint_core::properties::alloc_binding_holder::evaluate
  51: i_slint_core::properties::Property<T>::get
  52: core::ops::function::FnOnce::call_once
  53: i_slint_core::properties::alloc_binding_holder::evaluate
  54: i_slint_core::properties::Property<T>::get
  55: core::ops::function::FnOnce::call_once
  56: i_slint_core::properties::alloc_binding_holder::evaluate
  57: i_slint_core::properties::Property<T>::get
  58: <slint_lsp::preview::ui::slint_generatedPreviewUi::InnerPreviewUi as const_field_offset::PinnedDrop>::drop::VT::layout_info
  59: <i_slint_backend_winit::winitwindowadapter::WinitWindowAdapter as i_slint_core::window::WindowAdapter>::update_window_properties
  60: i_slint_core::window::WindowInner::update_window_properties
  61: <slint_lsp::preview::ui::slint_generatedPreviewUi::PreviewUi as i_slint_core::api::ComponentHandle>::show
  62: slint_lsp::preview::load_preview::{{closure}}::{{closure}}
  63: core::ops::function::FnOnce::call_once{{vtable.shim}}
  64: i_slint_backend_winit::event_loop::EventLoopState::process_event
  65: i_slint_backend_winit::event_loop::EventLoopState::run
  66: <i_slint_backend_winit::Backend as i_slint_core::platform::Platform>::run_event_loop
  67: slint_lsp::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.