refactor: track virtual offset in the layout

This commit is contained in:
Ashley Wulber 2025-03-20 10:10:02 -04:00 committed by Michael Murphy
parent 91eae67dd5
commit a3525ef56e
9 changed files with 200 additions and 78 deletions

2
iced

@ -1 +1 @@
Subproject commit 69da0abad9b708f4191ac5c7a9fdc0b733c4ad2d Subproject commit 07f666981d2d90cf7978f3fd90c0a9dfe22e1f0e

View file

@ -140,7 +140,11 @@ where
operation.container(Some(&self.id), layout.bounds(), &mut |operation| { operation.container(Some(&self.id), layout.bounds(), &mut |operation| {
self.content.as_widget().operate( self.content.as_widget().operate(
&mut tree.children[0], &mut tree.children[0],
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
operation, operation,
); );
@ -171,7 +175,11 @@ where
self.content.as_widget_mut().on_event( self.content.as_widget_mut().on_event(
&mut tree.children[0], &mut tree.children[0],
event.clone(), event.clone(),
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
@ -191,7 +199,7 @@ where
let content_layout = layout.children().next().unwrap(); let content_layout = layout.children().next().unwrap();
self.content.as_widget().mouse_interaction( self.content.as_widget().mouse_interaction(
&tree.children[0], &tree.children[0],
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
cursor_position, cursor_position,
viewport, viewport,
renderer, renderer,
@ -214,7 +222,7 @@ where
renderer, renderer,
theme, theme,
renderer_style, renderer_style,
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
cursor_position, cursor_position,
viewport, viewport,
); );
@ -229,7 +237,11 @@ where
) -> Option<overlay::Element<'b, Message, Theme, Renderer>> { ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
self.content.as_widget_mut().overlay( self.content.as_widget_mut().overlay(
&mut tree.children[0], &mut tree.children[0],
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
translation, translation,
) )
@ -245,7 +257,7 @@ where
let content_layout = layout.children().next().unwrap(); let content_layout = layout.children().next().unwrap();
self.content.as_widget().drag_destinations( self.content.as_widget().drag_destinations(
&state.children[0], &state.children[0],
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
dnd_rectangles, dnd_rectangles,
); );
@ -269,7 +281,11 @@ where
) -> iced_accessibility::A11yTree { ) -> iced_accessibility::A11yTree {
let c_layout = layout.children().next().unwrap(); let c_layout = layout.children().next().unwrap();
let c_state = &state.children[0]; let c_state = &state.children[0];
self.content.as_widget().a11y_nodes(c_layout, c_state, p) self.content.as_widget().a11y_nodes(
c_layout.with_virtual_offset(layout.virtual_offset()),
c_state,
p,
)
} }
} }

View file

@ -271,7 +271,11 @@ impl<'a, Message: 'a + Clone> Widget<Message, crate::Theme, crate::Renderer>
operation.container(None, layout.bounds(), &mut |operation| { operation.container(None, layout.bounds(), &mut |operation| {
self.content.as_widget().operate( self.content.as_widget().operate(
&mut tree.children[0], &mut tree.children[0],
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
operation, operation,
); );
@ -315,7 +319,11 @@ impl<'a, Message: 'a + Clone> Widget<Message, crate::Theme, crate::Renderer>
if self.content.as_widget_mut().on_event( if self.content.as_widget_mut().on_event(
&mut tree.children[0], &mut tree.children[0],
event.clone(), event.clone(),
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
cursor, cursor,
renderer, renderer,
clipboard, clipboard,
@ -416,7 +424,7 @@ impl<'a, Message: 'a + Clone> Widget<Message, crate::Theme, crate::Renderer>
text_color, text_color,
scale_factor: renderer_style.scale_factor, scale_factor: renderer_style.scale_factor,
}, },
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
cursor, cursor,
&viewport.intersection(&bounds).unwrap_or_default(), &viewport.intersection(&bounds).unwrap_or_default(),
); );
@ -533,7 +541,11 @@ impl<'a, Message: 'a + Clone> Widget<Message, crate::Theme, crate::Renderer>
_viewport: &Rectangle, _viewport: &Rectangle,
_renderer: &crate::Renderer, _renderer: &crate::Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
mouse_interaction(layout, cursor, self.on_press.is_some()) mouse_interaction(
layout.with_virtual_offset(layout.virtual_offset()),
cursor,
self.on_press.is_some(),
)
} }
fn overlay<'b>( fn overlay<'b>(
@ -548,7 +560,11 @@ impl<'a, Message: 'a + Clone> Widget<Message, crate::Theme, crate::Renderer>
translation.y += position.y; translation.y += position.y;
self.content.as_widget_mut().overlay( self.content.as_widget_mut().overlay(
&mut tree.children[0], &mut tree.children[0],
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
translation, translation,
) )
@ -614,9 +630,11 @@ impl<'a, Message: 'a + Clone> Widget<Message, crate::Theme, crate::Renderer>
node.set_default_action_verb(DefaultActionVerb::Click); node.set_default_action_verb(DefaultActionVerb::Click);
if let Some(child_tree) = child_tree.map(|child_tree| { if let Some(child_tree) = child_tree.map(|child_tree| {
self.content self.content.as_widget().a11y_nodes(
.as_widget() child_layout.with_virtual_offset(layout.virtual_offset()),
.a11y_nodes(child_layout, child_tree, p) child_tree,
p,
)
}) { }) {
A11yTree::node_with_child_tree(A11yNode::new(node, self.id.clone()), child_tree) A11yTree::node_with_child_tree(A11yNode::new(node, self.id.clone()), child_tree)
} else { } else {

View file

@ -535,6 +535,8 @@ pub fn update<
let state = state.clone(); let state = state.clone();
let on_close = surface::action::destroy_popup(id); let on_close = surface::action::destroy_popup(id);
let on_surface_action_clone = on_surface_action.clone(); let on_surface_action_clone = on_surface_action.clone();
let translation = layout.virtual_offset();
dbg!(translation);
let get_popup_action = surface::action::simple_popup::< let get_popup_action = surface::action::simple_popup::<
AppMessage, AppMessage,
Box< Box<
@ -556,7 +558,7 @@ pub fn update<
anchor: cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Anchor::BottomLeft, anchor: cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Anchor::BottomLeft,
gravity: cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Gravity::BottomRight, gravity: cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Gravity::BottomRight,
reactive: true, reactive: true,
offset: (-padding.left as i32, 0), offset: ((-padding.left - translation.x) as i32, -translation.y as i32),
constraint_adjustment: 9, constraint_adjustment: 9,
..Default::default() ..Default::default()
}, },

View file

@ -137,10 +137,13 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, Renderer> for FlexR
.iter() .iter()
.zip(&mut tree.children) .zip(&mut tree.children)
.zip(layout.children()) .zip(layout.children())
.for_each(|((child, state), layout)| { .for_each(|((child, state), c_layout)| {
child child.as_widget().operate(
.as_widget() state,
.operate(state, layout, renderer, operation); c_layout.with_virtual_offset(layout.virtual_offset()),
renderer,
operation,
);
}); });
}); });
} }
@ -160,11 +163,11 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, Renderer> for FlexR
.iter_mut() .iter_mut()
.zip(&mut tree.children) .zip(&mut tree.children)
.zip(layout.children()) .zip(layout.children())
.map(|((child, state), layout)| { .map(|((child, state), c_layout)| {
child.as_widget_mut().on_event( child.as_widget_mut().on_event(
state, state,
event.clone(), event.clone(),
layout, c_layout.with_virtual_offset(layout.virtual_offset()),
cursor, cursor,
renderer, renderer,
clipboard, clipboard,
@ -187,10 +190,14 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, Renderer> for FlexR
.iter() .iter()
.zip(&tree.children) .zip(&tree.children)
.zip(layout.children()) .zip(layout.children())
.map(|((child, state), layout)| { .map(|((child, state), c_layout)| {
child child.as_widget().mouse_interaction(
.as_widget() state,
.mouse_interaction(state, layout, cursor, viewport, renderer) c_layout.with_virtual_offset(layout.virtual_offset()),
cursor,
viewport,
renderer,
)
}) })
.max() .max()
.unwrap_or_default() .unwrap_or_default()
@ -206,15 +213,21 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, Renderer> for FlexR
cursor: mouse::Cursor, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
for ((child, state), layout) in self for ((child, state), c_layout) in self
.children .children
.iter() .iter()
.zip(&tree.children) .zip(&tree.children)
.zip(layout.children()) .zip(layout.children())
{ {
child child.as_widget().draw(
.as_widget() state,
.draw(state, renderer, theme, style, layout, cursor, viewport); renderer,
theme,
style,
c_layout.with_virtual_offset(layout.virtual_offset()),
cursor,
viewport,
);
} }
} }

View file

@ -166,10 +166,13 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, Renderer> for Grid<
.iter() .iter()
.zip(&mut tree.children) .zip(&mut tree.children)
.zip(layout.children()) .zip(layout.children())
.for_each(|((child, state), layout)| { .for_each(|((child, state), c_layout)| {
child child.as_widget().operate(
.as_widget() state,
.operate(state, layout, renderer, operation); c_layout.with_virtual_offset(layout.virtual_offset()),
renderer,
operation,
);
}); });
}); });
} }
@ -189,11 +192,11 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, Renderer> for Grid<
.iter_mut() .iter_mut()
.zip(&mut tree.children) .zip(&mut tree.children)
.zip(layout.children()) .zip(layout.children())
.map(|((child, state), layout)| { .map(|((child, state), c_layout)| {
child.as_widget_mut().on_event( child.as_widget_mut().on_event(
state, state,
event.clone(), event.clone(),
layout, c_layout.with_virtual_offset(layout.virtual_offset()),
cursor, cursor,
renderer, renderer,
clipboard, clipboard,
@ -216,10 +219,14 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, Renderer> for Grid<
.iter() .iter()
.zip(&tree.children) .zip(&tree.children)
.zip(layout.children()) .zip(layout.children())
.map(|((child, state), layout)| { .map(|((child, state), c_layout)| {
child child.as_widget().mouse_interaction(
.as_widget() state,
.mouse_interaction(state, layout, cursor, viewport, renderer) c_layout.with_virtual_offset(layout.virtual_offset()),
cursor,
viewport,
renderer,
)
}) })
.max() .max()
.unwrap_or_default() .unwrap_or_default()
@ -235,15 +242,21 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, Renderer> for Grid<
cursor: mouse::Cursor, cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
for ((child, state), layout) in self for ((child, state), c_layout) in self
.children .children
.iter() .iter()
.zip(&tree.children) .zip(&tree.children)
.zip(layout.children()) .zip(layout.children())
{ {
child child.as_widget().draw(
.as_widget() state,
.draw(state, renderer, theme, style, layout, cursor, viewport); renderer,
theme,
style,
c_layout.with_virtual_offset(layout.virtual_offset()),
cursor,
viewport,
);
} }
} }
@ -271,7 +284,13 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, Renderer> for Grid<
.iter() .iter()
.zip(layout.children()) .zip(layout.children())
.zip(state.children.iter()) .zip(state.children.iter())
.map(|((c, c_layout), state)| c.as_widget().a11y_nodes(c_layout, state, p)), .map(|((c, c_layout), state)| {
c.as_widget().a11y_nodes(
c_layout.with_virtual_offset(layout.virtual_offset()),
state,
p,
)
}),
) )
} }
@ -282,14 +301,18 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, Renderer> for Grid<
renderer: &Renderer, renderer: &Renderer,
dnd_rectangles: &mut iced_core::clipboard::DndDestinationRectangles, dnd_rectangles: &mut iced_core::clipboard::DndDestinationRectangles,
) { ) {
for ((e, layout), state) in self for ((e, c_layout), state) in self
.children .children
.iter() .iter()
.zip(layout.children()) .zip(layout.children())
.zip(state.children.iter()) .zip(state.children.iter())
{ {
e.as_widget() e.as_widget().drag_destinations(
.drag_destinations(state, layout, renderer, dnd_rectangles); state,
c_layout.with_virtual_offset(layout.virtual_offset()),
renderer,
dnd_rectangles,
);
} }
} }
} }

View file

@ -88,7 +88,11 @@ where
operation.container(Some(&self.id), layout.bounds(), &mut |operation| { operation.container(Some(&self.id), layout.bounds(), &mut |operation| {
self.content.as_widget().operate( self.content.as_widget().operate(
&mut tree.children[0], &mut tree.children[0],
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
operation, operation,
); );
@ -109,7 +113,11 @@ where
self.content.as_widget_mut().on_event( self.content.as_widget_mut().on_event(
&mut tree.children[0], &mut tree.children[0],
event.clone(), event.clone(),
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
@ -129,7 +137,7 @@ where
let content_layout = layout.children().next().unwrap(); let content_layout = layout.children().next().unwrap();
self.content.as_widget().mouse_interaction( self.content.as_widget().mouse_interaction(
&tree.children[0], &tree.children[0],
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
cursor_position, cursor_position,
viewport, viewport,
renderer, renderer,
@ -152,7 +160,7 @@ where
renderer, renderer,
theme, theme,
renderer_style, renderer_style,
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
cursor_position, cursor_position,
viewport, viewport,
); );
@ -167,7 +175,11 @@ where
) -> Option<overlay::Element<'b, Message, Theme, Renderer>> { ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
self.content.as_widget_mut().overlay( self.content.as_widget_mut().overlay(
&mut tree.children[0], &mut tree.children[0],
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
translation, translation,
) )
@ -183,7 +195,7 @@ where
let content_layout = layout.children().next().unwrap(); let content_layout = layout.children().next().unwrap();
self.content.as_widget().drag_destinations( self.content.as_widget().drag_destinations(
&state.children[0], &state.children[0],
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
dnd_rectangles, dnd_rectangles,
); );
@ -207,7 +219,11 @@ where
) -> iced_accessibility::A11yTree { ) -> iced_accessibility::A11yTree {
let c_layout = layout.children().next().unwrap(); let c_layout = layout.children().next().unwrap();
let c_state = &state.children[0]; let c_state = &state.children[0];
self.content.as_widget().a11y_nodes(c_layout, c_state, p) self.content.as_widget().a11y_nodes(
c_layout.with_virtual_offset(layout.virtual_offset()),
c_state,
p,
)
} }
} }

View file

@ -131,7 +131,11 @@ where
operation.container(Some(&self.id), layout.bounds(), &mut |operation| { operation.container(Some(&self.id), layout.bounds(), &mut |operation| {
self.content.as_widget().operate( self.content.as_widget().operate(
&mut tree.children[0], &mut tree.children[0],
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
operation, operation,
); );
@ -165,7 +169,11 @@ where
self.content.as_widget_mut().on_event( self.content.as_widget_mut().on_event(
&mut tree.children[0], &mut tree.children[0],
event.clone(), event.clone(),
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
@ -185,7 +193,7 @@ where
let content_layout = layout.children().next().unwrap(); let content_layout = layout.children().next().unwrap();
self.content.as_widget().mouse_interaction( self.content.as_widget().mouse_interaction(
&tree.children[0], &tree.children[0],
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
cursor_position, cursor_position,
viewport, viewport,
renderer, renderer,
@ -208,7 +216,7 @@ where
renderer, renderer,
theme, theme,
renderer_style, renderer_style,
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
cursor_position, cursor_position,
viewport, viewport,
); );
@ -223,7 +231,11 @@ where
) -> Option<overlay::Element<'b, Message, Theme, Renderer>> { ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
self.content.as_widget_mut().overlay( self.content.as_widget_mut().overlay(
&mut tree.children[0], &mut tree.children[0],
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
translation, translation,
) )
@ -239,7 +251,7 @@ where
let content_layout = layout.children().next().unwrap(); let content_layout = layout.children().next().unwrap();
self.content.as_widget().drag_destinations( self.content.as_widget().drag_destinations(
&state.children[0], &state.children[0],
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
dnd_rectangles, dnd_rectangles,
); );
@ -263,7 +275,11 @@ where
) -> iced_accessibility::A11yTree { ) -> iced_accessibility::A11yTree {
let c_layout = layout.children().next().unwrap(); let c_layout = layout.children().next().unwrap();
let c_state = &state.children[0]; let c_state = &state.children[0];
self.content.as_widget().a11y_nodes(c_layout, c_state, p) self.content.as_widget().a11y_nodes(
c_layout.with_virtual_offset(layout.virtual_offset()),
c_state,
p,
)
} }
} }

View file

@ -240,7 +240,11 @@ impl<'a, Message: 'static + Clone, TopLevelMessage: 'static + Clone>
operation.container(None, layout.bounds(), &mut |operation| { operation.container(None, layout.bounds(), &mut |operation| {
self.content.as_widget().operate( self.content.as_widget().operate(
&mut tree.children[0], &mut tree.children[0],
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
operation, operation,
); );
@ -271,16 +275,22 @@ impl<'a, Message: 'static + Clone, TopLevelMessage: 'static + Clone>
&self.on_surface_action, &self.on_surface_action,
|| tree.state.downcast_mut::<State>(), || tree.state.downcast_mut::<State>(),
); );
status.merge(self.content.as_widget_mut().on_event( status.merge(
&mut tree.children[0], self.content.as_widget_mut().on_event(
event, &mut tree.children[0],
layout.children().next().unwrap(), event,
cursor, layout
renderer, .children()
clipboard, .next()
shell, .unwrap()
viewport, .with_virtual_offset(layout.virtual_offset()),
)) cursor,
renderer,
clipboard,
shell,
viewport,
),
)
} }
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
@ -321,7 +331,7 @@ impl<'a, Message: 'static + Clone, TopLevelMessage: 'static + Clone>
text_color: styling.text_color, text_color: styling.text_color,
scale_factor: renderer_style.scale_factor, scale_factor: renderer_style.scale_factor,
}, },
content_layout, content_layout.with_virtual_offset(layout.virtual_offset()),
cursor, cursor,
&viewport.intersection(&bounds).unwrap_or_default(), &viewport.intersection(&bounds).unwrap_or_default(),
); );
@ -339,7 +349,7 @@ impl<'a, Message: 'static + Clone, TopLevelMessage: 'static + Clone>
) -> mouse::Interaction { ) -> mouse::Interaction {
self.content.as_widget().mouse_interaction( self.content.as_widget().mouse_interaction(
&tree.children[0], &tree.children[0],
layout, layout.children().next().unwrap(),
cursor, cursor,
viewport, viewport,
renderer, renderer,
@ -358,7 +368,11 @@ impl<'a, Message: 'static + Clone, TopLevelMessage: 'static + Clone>
translation.y += position.y; translation.y += position.y;
self.content.as_widget_mut().overlay( self.content.as_widget_mut().overlay(
&mut tree.children[0], &mut tree.children[0],
layout.children().next().unwrap(), layout
.children()
.next()
.unwrap()
.with_virtual_offset(layout.virtual_offset()),
renderer, renderer,
translation, translation,
) )
@ -374,7 +388,11 @@ impl<'a, Message: 'static + Clone, TopLevelMessage: 'static + Clone>
) -> iced_accessibility::A11yTree { ) -> iced_accessibility::A11yTree {
let c_layout = layout.children().next().unwrap(); let c_layout = layout.children().next().unwrap();
self.content.as_widget().a11y_nodes(c_layout, state, p) self.content.as_widget().a11y_nodes(
c_layout.with_virtual_offset(layout.virtual_offset()),
state,
p,
)
} }
fn id(&self) -> Option<Id> { fn id(&self) -> Option<Id> {