1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00

Fix Context::is_pointer_over_egui and Context::egui_wants_pointer_input (#8081)

* Closes https://github.com/emilk/egui/issues/8041

These functions were broken when using the new `run_ui`.
This commit is contained in:
Emil Ernerfeldt
2026-04-08 09:52:28 +02:00
committed by GitHub
parent 1fdc5c0775
commit b117a1ac19
4 changed files with 83 additions and 18 deletions

View File

@@ -793,7 +793,7 @@ impl Context {
let plugins = self.read(|ctx| ctx.plugins.ordered_plugins());
#[expect(deprecated)]
self.run(new_input, |ctx| {
let mut top_ui = Ui::new(
let mut root_ui = Ui::new(
ctx.clone(),
Id::new((ctx.viewport_id(), "__top_ui")),
UiBuilder::new()
@@ -802,14 +802,15 @@ impl Context {
);
{
plugins.on_begin_pass(&mut top_ui);
run_ui(&mut top_ui);
plugins.on_end_pass(&mut top_ui);
plugins.on_begin_pass(&mut root_ui);
run_ui(&mut root_ui);
plugins.on_end_pass(&mut root_ui);
}
// Inform ctx about what we actually used, so we can shrink the native window to fit.
// TODO(emilk): make better use of this somehow
ctx.pass_state_mut(|state| state.allocate_central_panel(top_ui.min_rect()));
ctx.pass_state_mut(|state| {
state.root_ui_available_rect = Some(root_ui.available_rect_before_wrap());
state.root_ui_min_rect = Some(root_ui.min_rect());
});
})
}
@@ -2853,13 +2854,21 @@ impl Context {
/// How much space is still available after panels have been added.
#[deprecated = "Use content_rect (or viewport_rect) instead"]
pub fn available_rect(&self) -> Rect {
#[expect(deprecated)] // legacy
self.pass_state(|s| s.available_rect()).round_ui()
}
/// How much space is used by windows and the top-level [`Ui`].
pub fn globally_used_rect(&self) -> Rect {
self.write(|ctx| {
let mut used = ctx.viewport().this_pass.used_by_panels;
let viewport = ctx.viewport();
let root_ui_min_rect =
(viewport.this_pass.root_ui_min_rect).or(viewport.prev_pass.root_ui_min_rect);
let mut used = root_ui_min_rect.unwrap_or_else(|| {
#[expect(deprecated)] // legacy
ctx.viewport().this_pass.used_by_panels
});
for (_id, window) in ctx.memory.areas().visible_windows() {
used |= window.rect();
}
@@ -2886,19 +2895,28 @@ impl Context {
/// Is the pointer (mouse/touch) over any egui area?
pub fn is_pointer_over_egui(&self) -> bool {
let pointer_pos = self.input(|i| i.pointer.interact_pos());
if let Some(pointer_pos) = pointer_pos {
if let Some(layer) = self.layer_id_at(pointer_pos) {
let Some(pointer_pos) = pointer_pos else {
return false;
};
let Some(layer) = self.layer_id_at(pointer_pos) else {
return false;
};
if layer.order == Order::Background {
let root_ui_available_rect = self
.pass_state(|state| state.root_ui_available_rect)
.or_else(|| self.prev_pass_state(|state| state.root_ui_available_rect));
if let Some(root_ui_available_rect) = root_ui_available_rect {
// Modern `run_ui` code
!root_ui_available_rect.contains(pointer_pos)
} else {
// Legacy code
#[expect(deprecated)]
!self.pass_state(|state| state.unused_rect.contains(pointer_pos))
}
} else {
true
}
} else {
false
}
} else {
false
}
}
/// Is the pointer (mouse/touch) over any egui area?

View File

@@ -1,3 +1,5 @@
#![expect(deprecated)] // TODO(emilk): Remove legacy panels
use ahash::HashMap;
use crate::{Align, Id, IdMap, LayerId, Rangef, Rect, Vec2, WidgetRects, id::IdSet, style};
@@ -199,15 +201,28 @@ pub struct PassState {
pub tooltips: TooltipPassState,
/// What the root UI had available at the end of the previous pass.
///
/// Only set if [`crate::Context::run_ui`] has been called.
pub root_ui_available_rect: Option<Rect>,
/// What the root UI had used at the end of the previous pass.
///
/// Only set if [`crate::Context::run_ui`] has been called.
pub root_ui_min_rect: Option<Rect>,
/// Starts off as the `screen_rect`, shrinks as panels are added.
/// The [`crate::CentralPanel`] does not change this.
#[deprecated = "Only used by legacy Context-Panels"]
pub available_rect: Rect,
/// Starts off as the `screen_rect`, shrinks as panels are added.
/// The [`crate::CentralPanel`] retracts from this.
#[deprecated = "Only used by legacy Context-Panels"]
pub unused_rect: Rect,
/// How much space is used by panels.
#[deprecated = "Only used by legacy Context-Panels"]
pub used_by_panels: Rect,
/// The current scroll area should scroll to this range (horizontal, vertical).
@@ -240,6 +255,8 @@ impl Default for PassState {
widgets: Default::default(),
layers: Default::default(),
tooltips: Default::default(),
root_ui_available_rect: None,
root_ui_min_rect: None,
available_rect: Rect::NAN,
unused_rect: Rect::NAN,
used_by_panels: Rect::NAN,
@@ -262,6 +279,8 @@ impl PassState {
widgets,
tooltips,
layers,
root_ui_available_rect,
root_ui_min_rect,
available_rect,
unused_rect,
used_by_panels,
@@ -278,6 +297,8 @@ impl PassState {
widgets.clear();
tooltips.clear();
layers.clear();
*root_ui_available_rect = None;
*root_ui_min_rect = None;
*available_rect = content_rect;
*unused_rect = content_rect;
*used_by_panels = Rect::NOTHING;
@@ -295,6 +316,7 @@ impl PassState {
}
/// How much space is still available after panels has been added.
#[deprecated = "Only used by legacy Context-Panels"]
pub(crate) fn available_rect(&self) -> Rect {
debug_assert!(
self.available_rect.is_finite(),
@@ -304,6 +326,7 @@ impl PassState {
}
/// Shrink `available_rect`.
#[deprecated = "Only used by legacy Context-Panels"]
pub(crate) fn allocate_left_panel(&mut self, panel_rect: Rect) {
debug_assert!(
panel_rect.min.distance(self.available_rect.min) < 0.1,
@@ -315,6 +338,7 @@ impl PassState {
}
/// Shrink `available_rect`.
#[deprecated = "Only used by legacy Context-Panels"]
pub(crate) fn allocate_right_panel(&mut self, panel_rect: Rect) {
debug_assert!(
panel_rect.max.distance(self.available_rect.max) < 0.1,
@@ -326,6 +350,7 @@ impl PassState {
}
/// Shrink `available_rect`.
#[deprecated = "Only used by legacy Context-Panels"]
pub(crate) fn allocate_top_panel(&mut self, panel_rect: Rect) {
debug_assert!(
panel_rect.min.distance(self.available_rect.min) < 0.1,
@@ -337,6 +362,7 @@ impl PassState {
}
/// Shrink `available_rect`.
#[deprecated = "Only used by legacy Context-Panels"]
pub(crate) fn allocate_bottom_panel(&mut self, panel_rect: Rect) {
debug_assert!(
panel_rect.max.distance(self.available_rect.max) < 0.1,
@@ -347,6 +373,7 @@ impl PassState {
self.used_by_panels |= panel_rect;
}
#[deprecated = "Only used by legacy Context-Panels"]
pub(crate) fn allocate_central_panel(&mut self, panel_rect: Rect) {
// Note: we do not shrink `available_rect`, because
// we allow windows to cover the CentralPanel.

View File

@@ -13,7 +13,8 @@ workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
eframe = { workspace = true, features = [
eframe = { workspace = true, default_features = false, features = [
"glow",
"default",
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
] }

View File

@@ -30,6 +30,10 @@ struct MyTestApp {}
impl eframe::App for MyTestApp {
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
egui::Panel::top("top").show_inside(ui, |ui| {
ui.label("This is a test of painting directly with glow.");
});
use glow::HasContext as _;
let gl = frame.gl().unwrap();
@@ -43,6 +47,21 @@ impl eframe::App for MyTestApp {
egui::Window::new("Floating Window").show(ui.ctx(), |ui| {
ui.label("The background should be purple.");
ui.label(format!(
"is_pointer_over_egui: {}",
ui.is_pointer_over_egui()
));
ui.label(format!(
"egui_wants_pointer_input: {}",
ui.egui_wants_pointer_input()
));
ui.label(format!(
"egui_is_using_pointer: {}",
ui.egui_is_using_pointer()
));
if let Some(pos) = ui.pointer_latest_pos() {
ui.label(format!("layer_id_at: {:?}", ui.layer_id_at(pos)));
}
});
}
}