mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 14:49:06 -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:
@@ -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,18 +2895,27 @@ 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) {
|
||||
if layer.order == Order::Background {
|
||||
!self.pass_state(|state| state.unused_rect.contains(pointer_pos))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
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 {
|
||||
false
|
||||
// Legacy code
|
||||
#[expect(deprecated)]
|
||||
!self.pass_state(|state| state.unused_rect.contains(pointer_pos))
|
||||
}
|
||||
} else {
|
||||
false
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
] }
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user