Some improvements to Window visibility

- From C++, always call the Window::show() and hide() function instead
   of going through set_visible directly as it doesn't set the size of
   the WindowItem
 - show() should also call resize on the renderer
 - remove the is_visible in the WindowAdapterInternal as it is no longer
   needed
This commit is contained in:
Olivier Goffart 2023-08-30 09:32:14 +02:00 committed by Olivier Goffart
parent 1721b2d1be
commit fde561a56a
8 changed files with 30 additions and 45 deletions

View file

@ -492,7 +492,7 @@ declare_types! {
let this = cx.this();
let window = cx.borrow(&this, |x| x.0.as_ref().cloned());
let window_adapter = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
window_adapter.set_visible(true).unwrap();
window_adapter.window().show().unwrap();
Ok(JsUndefined::new().as_value(&mut cx))
}
@ -500,7 +500,7 @@ declare_types! {
let this = cx.this();
let window = cx.borrow(&this, |x| x.0.as_ref().cloned());
let window_adapter = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
window_adapter.set_visible(false).unwrap();
window_adapter.window().hide().unwrap();
Ok(JsUndefined::new().as_value(&mut cx))
}

View file

@ -1802,13 +1802,6 @@ impl WindowAdapterInternal for QtWindow {
});
ds.as_ref().get()
}
fn is_visible(&self) -> bool {
let widget_ptr = self.widget_ptr();
cpp! {unsafe [widget_ptr as "QWidget*"] -> bool as "bool" {
return widget_ptr->isVisible();
}}
}
}
impl i_slint_core::renderer::RendererSealed for QtWindow {

View file

@ -28,8 +28,7 @@ impl i_slint_core::platform::Platform for TestingBackend {
) -> Result<Rc<dyn WindowAdapter>, i_slint_core::platform::PlatformError> {
Ok(Rc::new_cyclic(|self_weak| TestingWindow {
window: i_slint_core::api::Window::new(self_weak.clone() as _),
shown: false.into(),
size: Default::default(),
size: PhysicalSize::new(600, 800).into(),
ime_requests: Default::default(),
}))
}
@ -78,7 +77,6 @@ impl i_slint_core::platform::Platform for TestingBackend {
pub struct TestingWindow {
window: i_slint_core::api::Window,
shown: core::cell::Cell<bool>,
size: core::cell::Cell<PhysicalSize>,
pub ime_requests: RefCell<Vec<InputMethodRequest>>,
}
@ -88,10 +86,6 @@ impl WindowAdapterInternal for TestingWindow {
self
}
fn is_visible(&self) -> bool {
self.shown.get()
}
fn input_method_request(&self, request: i_slint_core::window::InputMethodRequest) {
self.ime_requests.borrow_mut().push(request)
}
@ -102,11 +96,6 @@ impl WindowAdapter for TestingWindow {
&self.window
}
fn set_visible(&self, visible: bool) -> Result<(), PlatformError> {
self.shown.set(visible);
Ok(())
}
fn size(&self) -> PhysicalSize {
self.size.get()
}

View file

@ -662,10 +662,6 @@ impl WindowAdapterInternal for WinitWindowAdapter {
.get()
}
fn is_visible(&self) -> bool {
self.winit_window().is_visible().unwrap_or(true)
}
#[cfg(enable_accesskit)]
fn handle_focus_change(&self, _old: Option<ItemRc>, _new: Option<ItemRc>) {
self.accesskit_adapter.handle_focus_item_change();

View file

@ -524,11 +524,7 @@ impl Window {
/// Returns the visibility state of the window. This function can return false even if you previously called show()
/// on it, for example if the user minimized the window.
pub fn is_visible(&self) -> bool {
self.0
.window_adapter()
.internal(crate::InternalToken)
.map(|w| w.is_visible())
.unwrap_or(false)
self.0.is_visible()
}
}

View file

@ -200,12 +200,6 @@ pub trait WindowAdapterInternal {
fn dark_color_scheme(&self) -> bool {
false
}
/// Get the visibility of the window
// todo: replace with WindowEvent::VisibilityChanged and require backend to dispatch event
fn is_visible(&self) -> bool {
false
}
}
/// This is the parameter from [`WindowAdapterInternal::input_method_request()`] which lets the editable text input field
@ -349,7 +343,8 @@ struct WindowPinnedFields {
pub struct WindowInner {
window_adapter_weak: Weak<dyn WindowAdapter>,
component: RefCell<ComponentWeak>,
strong_component_ref: RefCell<Option<ComponentRc>>, // When the window is visible, keep a strong reference
/// When the window is visible, keep a strong reference
strong_component_ref: RefCell<Option<ComponentRc>>,
mouse_input_state: Cell<MouseInputState>,
pub(crate) modifiers: Cell<InternalKeyboardModifierState>,
@ -782,10 +777,9 @@ impl WindowInner {
self.window_adapter().set_visible(true)?;
// Make sure that the window's inner size is in sync with the root window item's
// width/height.
self.set_window_item_geometry(
self.window_adapter().size().to_logical(self.scale_factor()).to_euclid(),
);
let size = self.window_adapter().size();
self.set_window_item_geometry(size.to_logical(self.scale_factor()).to_euclid());
self.window_adapter().renderer().resize(size).unwrap();
Ok(())
}
@ -919,6 +913,11 @@ impl WindowInner {
self.pinned_fields.text_input_focused.set(value)
}
/// Returns true if the window is visible
pub fn is_visible(&self) -> bool {
self.strong_component_ref.borrow().is_some()
}
/// Returns the window item that is the first item in the component.
pub fn window_item(&self) -> Option<VRcMapped<ComponentVTable, crate::items::WindowItem>> {
self.try_component().and_then(|component_rc| {
@ -1025,14 +1024,14 @@ pub mod ffi {
pub unsafe extern "C" fn slint_windowrc_show(handle: *const WindowAdapterRcOpaque) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.set_visible(true).unwrap();
window_adapter.window().show().unwrap();
}
/// Spins an event loop and renders the items of the provided component in this window.
#[no_mangle]
pub unsafe extern "C" fn slint_windowrc_hide(handle: *const WindowAdapterRcOpaque) {
let window_adapter = &*(handle as *const Rc<dyn WindowAdapter>);
window_adapter.set_visible(false).unwrap();
window_adapter.window().hide().unwrap();
}
/// Returns the visibility state of the window. This function can return false even if you previously called show()
@ -1042,7 +1041,7 @@ pub mod ffi {
handle: *const WindowAdapterRcOpaque,
) -> bool {
let window = &*(handle as *const Rc<dyn WindowAdapter>);
window.internal(crate::InternalToken).map_or(false, |w| w.is_visible())
window.window().is_visible()
}
/// Returns the window scale factor.

View file

@ -561,7 +561,10 @@ pub extern "C" fn slint_interpreter_component_instance_show(
) {
generativity::make_guard!(guard);
let comp = inst.unerase(guard);
comp.borrow_instance().window_adapter().set_visible(is_visible).unwrap();
match is_visible {
true => comp.borrow_instance().window_adapter().window().show().unwrap(),
false => comp.borrow_instance().window_adapter().window().hide().unwrap(),
}
}
/// Return a window for the component

View file

@ -169,6 +169,7 @@ Hello := Rectangle {
property <string> arrow_down_commands: "M21.8,311.1l84.2-82.1c15.7-15.2,41-15.2,56.7,0l341.1,304.1l333.7-297.5c15.5-15.2,41-15.2,56.6,0l84.3,82.1c15.6,15.2,15.6,40,0,55.2L531.7,771c-15.7,15.3-41,15.3-56.7,0l-6.9-6.7L21.8,366.3C6.1,351,6.1,326.3,21.8,311.1z";
property <string> funky_shape_commands: "M 100 300 Q 150 50 250 150 C 250 300 300 300 300 450 A 50 50 0 1 0 450 450 L 550 300";
property <length> width2 <=> root.width;
}
/*
@ -177,8 +178,12 @@ Hello := Rectangle {
auto handle = Hello::create();
const Hello &instance = *handle;
assert(!instance.window().is_visible());
assert_eq(instance.get_width2(), 0); //Before it is shown, no size is set
instance.window().show();
assert(instance.window().is_visible());
assert(instance.get_width2() > 0); // default size from the backend
instance.window().set_size(slint::LogicalSize({123., 456.}));
assert_eq(instance.get_width2(), 123.);
instance.window().hide();
assert(!instance.window().is_visible());
```
@ -187,8 +192,12 @@ assert(!instance.window().is_visible());
```rust
let instance = Hello::new().unwrap();
assert!(!instance.window().is_visible());
assert_eq!(instance.get_width2(), 0.);
instance.window().show().unwrap();
assert!(instance.window().is_visible());
assert!(instance.get_width2() > 0.); // default size from the backend
instance.window().set_size(slint::LogicalSize::new(123., 456.));
assert_eq!(instance.get_width2(), 123.);
instance.window().hide().unwrap();
assert!(!instance.window().is_visible());
```