PopupWindow: fix absolute-position property within a PopupWindow

We were actually skipping two element (the popup and the popup parent)
Also this broke the positioning of sub-popup.

The "fix" is to not get a parent for popup window.
This will also have the side effect of fixing the focus issue
This commit is contained in:
Olivier Goffart 2024-12-06 10:18:48 +01:00
parent 9b9a34561d
commit 34152611b3
3 changed files with 71 additions and 8 deletions

View file

@ -99,8 +99,12 @@ Currently the `z` value is a compile time constant and cannot be changed at runt
</SlintProperty>
### absolute-position
<SlintProperty propName="absolute-position" typeName="struct" structName="Point" >
The position of the element within the contained window.
<SlintProperty propName="absolute-position" typeName="struct" structName="Point" propertyVisibility="out">
Represents a point specifying an absolute position within a window or popup window.
It defines coordinates (x,y) relative to the enclosing Window or PopupWindow, but the reference frame is unspecified
(could be screen, window, or popup coordinates).
This property is only absolute within the enclosing Window or PopupWindow.
</SlintProperty>
@ -172,9 +176,9 @@ These properties are valid on all visible items and can be used to specify const
### cache-rendering-hint
<SlintProperty typeName="bool" propName="cache-rendering-hint" default="false" >
When set to `true`, this provides a hint to the renderer to cache the contents of the element
and all the children into an intermediate cached layer. For complex sub-trees that rarely
change this may speed up the rendering, at the expense of increased memory consumption. Not
When set to `true`, this provides a hint to the renderer to cache the contents of the element
and all the children into an intermediate cached layer. For complex sub-trees that rarely
change this may speed up the rendering, at the expense of increased memory consumption. Not
all rendering backends support this, so this is merely a hint.
</SlintProperty>

View file

@ -299,6 +299,8 @@ impl ItemRc {
}
/// Return the parent Item in the item tree.
///
/// If the item is a the root on its Window or PopupWindow, then the parent is None.
pub fn parent_item(&self) -> Option<ItemRc> {
let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
let item_tree = crate::item_tree::ItemTreeNodeArray::new(&comp_ref_pin);
@ -309,8 +311,19 @@ impl ItemRc {
let mut r = ItemWeak::default();
comp_ref_pin.as_ref().parent_node(&mut r);
// parent_node returns the repeater node, go up one more level!
r.upgrade()?.parent_item()
let parent = r.upgrade()?;
let comp_ref_pin = vtable::VRc::borrow_pin(&parent.item_tree);
let item_tree_array = crate::item_tree::ItemTreeNodeArray::new(&comp_ref_pin);
if let Some(ItemTreeNode::DynamicTree { parent_index, .. }) =
item_tree_array.get(parent.index())
{
// parent_node returns the repeater node, go up one more level!
Some(ItemRc::new(parent.item_tree.clone(), *parent_index))
} else {
// the Item was most likely a PopupWindow and we don't want to return the item for the purpose of this call
// (eg, focus/geometry/...)
None
}
}
/// Returns true if this item is visible from the root of the item tree. Note that this will return

View file

@ -24,6 +24,12 @@ export component TestCase {
height: 500phx;
property <bool> simple-inner-ok: simple-inner.absolute-position.x == 40phx && simple-inner.absolute-position.y == 60phx;
out property <string> inner-popup;
// The absolute-position is only absolute within the popup.
// If we changed the behavior to be relative within the window, then we'd need to uncomment the commented numbers
out property <string> inner-popup-expected: "x=" + (/*10+100+0+8*/-5+200) + " y=" + (/*20+0+50+7*/-5-200);
Rectangle {
x: 10phx;
y: 20phx;
@ -32,6 +38,45 @@ export component TestCase {
x: 30phx;
y: 40phx;
}
init => {debug(hl.preferred-height) }
hl := HorizontalLayout {
if true:Rectangle {
preferred-height: 200phx;
Rectangle {
x: 100phx;
init => {
popup.show();
}
Rectangle {
y: 50phx;
popup := PopupWindow {
x: 8phx;
y: 7phx;
Rectangle {
x: -5phx;
y: -5phx;
init => { debug(vl.preferred-height) }
vl:=VerticalLayout {
if true: Rectangle {
Rectangle {
x: 200phx;
y: -200phx;
Rectangle {
init => {
inner-popup = "x=" + (self.absolute-position.x/1px) + " y=" + (self.absolute-position.y/1px);
}
}
}
}
}
}
}
}
}
}
}
}
empty1 := Rectangle {
Rectangle {
@ -41,7 +86,8 @@ export component TestCase {
}
}
xxx := Issue3148 { width: 50%; }
out property <bool> test: simple-inner-ok && xxx.result == 42px && empty1.absolute-position == empty2.absolute-position;
out property <bool> test: simple-inner-ok && xxx.result == 42px && empty1.absolute-position == empty2.absolute-position
&& inner-popup == inner-popup-expected;
out property <Point> coords <=> simple-inner.absolute-position;
}