Fix: Menu popups and tooltips don't respect layer transforms (#4708)

The menu buttons, combo box menus, and tooltips don't take layer
transforms into account when placing their popups, resulting in popups
being placed in the wrong location.

This PR makes the popups take layer transforms into account,
transforming the positions before displaying them on screen. I
implemented this fix for menu buttons, combo boxes, and tooltips; let me
know if there's anything I missed.
Scaling of the popups is purposefully ignored for now. Personally, I
think popup scaling isn't necessary but if it is required I can
implement it (also it would require doing more invasive things to the
code and I want to keep this as simple as possible.)

Before the fix: (with a modified version of the "Pan Zoom" web demo)
<video
src=https://github.com/emilk/egui/assets/104604363/a2d79757-c410-4815-8159-b64d6bd668ee>

After:
<video
src=https://github.com/emilk/egui/assets/104604363/48f8b1d1-d30f-44bf-961f-f10b85964a92>

The frame delay seems to be unavoidable unless we can move the popups
_after_ the layer transform is set (or apply the transforms to the popup
during painting). I think this would be better implemented once the
menu/popup/tooltip unification is done (#4669).
This commit is contained in:
Colin Cai 2024-06-26 02:11:31 -04:00 committed by GitHub
parent 10571e9da5
commit d30f79db60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 22 additions and 2 deletions

View File

@ -302,10 +302,16 @@ pub fn popup_above_or_below_widget<R>(
add_contents: impl FnOnce(&mut Ui) -> R,
) -> Option<R> {
if parent_ui.memory(|mem| mem.is_popup_open(popup_id)) {
let (pos, pivot) = match above_or_below {
let (mut pos, pivot) = match above_or_below {
AboveOrBelow::Above => (widget_response.rect.left_top(), Align2::LEFT_BOTTOM),
AboveOrBelow::Below => (widget_response.rect.left_bottom(), Align2::LEFT_TOP),
};
if let Some(transform) = parent_ui
.ctx()
.memory(|m| m.layer_transforms.get(&parent_ui.layer_id()).copied())
{
pos = transform * pos;
}
let frame = Frame::popup(parent_ui.style());
let frame_margin = frame.total_margin();

View File

@ -363,6 +363,13 @@ impl MenuRoot {
}
}
if let Some(transform) = button
.ctx
.memory(|m| m.layer_transforms.get(&button.layer_id).copied())
{
pos = transform * pos;
}
return MenuResponse::Create(pos, id);
} else if button
.ctx

View File

@ -562,7 +562,14 @@ impl Response {
///
/// This can be used to give attention to a widget during a tutorial.
pub fn show_tooltip_ui(&self, add_contents: impl FnOnce(&mut Ui)) {
crate::containers::show_tooltip_for(&self.ctx, self.id, &self.rect, add_contents);
let mut rect = self.rect;
if let Some(transform) = self
.ctx
.memory(|m| m.layer_transforms.get(&self.layer_id).copied())
{
rect = transform * rect;
}
crate::containers::show_tooltip_for(&self.ctx, self.id, &rect, add_contents);
}
/// Always show this tooltip, even if disabled and the user isn't hovering it.