mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Replace uiless_pass flag with Context::is_visible
egui now derives "no ui is shown this pass" from the `minimized` / `occluded` flags the integrations already report in `ViewportInfo`, instead of a new `RawInput` flag that they had to set separately. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -268,14 +268,10 @@ impl EpiIntegration {
|
|||||||
app: &mut dyn epi::App,
|
app: &mut dyn epi::App,
|
||||||
viewport_ui_cb: Option<&DeferredViewportUiCallback>,
|
viewport_ui_cb: Option<&DeferredViewportUiCallback>,
|
||||||
mut raw_input: egui::RawInput,
|
mut raw_input: egui::RawInput,
|
||||||
show_ui: bool,
|
is_visible: bool,
|
||||||
) -> egui::FullOutput {
|
) -> egui::FullOutput {
|
||||||
raw_input.time = Some(self.beginning.elapsed().as_secs_f64());
|
raw_input.time = Some(self.beginning.elapsed().as_secs_f64());
|
||||||
|
|
||||||
// We still run a pass while hidden so that app logic keeps ticking,
|
|
||||||
// but we tell egui to skip all book-keeping that assumes ui was shown:
|
|
||||||
raw_input.uiless_pass = !show_ui;
|
|
||||||
|
|
||||||
let close_requested = raw_input.viewport().close_requested();
|
let close_requested = raw_input.viewport().close_requested();
|
||||||
|
|
||||||
app.raw_input_hook(&self.egui_ctx, &mut raw_input);
|
app.raw_input_hook(&self.egui_ctx, &mut raw_input);
|
||||||
@@ -283,7 +279,7 @@ impl EpiIntegration {
|
|||||||
let full_output = self.egui_ctx.run_ui(raw_input, |ui| {
|
let full_output = self.egui_ctx.run_ui(raw_input, |ui| {
|
||||||
if let Some(viewport_ui_cb) = viewport_ui_cb {
|
if let Some(viewport_ui_cb) = viewport_ui_cb {
|
||||||
// Child viewport
|
// Child viewport
|
||||||
if show_ui {
|
if is_visible {
|
||||||
profiling::scope!("viewport_callback");
|
profiling::scope!("viewport_callback");
|
||||||
viewport_ui_cb(ui);
|
viewport_ui_cb(ui);
|
||||||
}
|
}
|
||||||
@@ -293,7 +289,7 @@ impl EpiIntegration {
|
|||||||
app.logic(ui.ctx(), &mut self.frame);
|
app.logic(ui.ctx(), &mut self.frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
if show_ui {
|
if is_visible {
|
||||||
{
|
{
|
||||||
profiling::scope!("App::ui");
|
profiling::scope!("App::ui");
|
||||||
app.ui(ui, &mut self.frame);
|
app.ui(ui, &mut self.frame);
|
||||||
|
|||||||
@@ -280,10 +280,6 @@ impl AppRunner {
|
|||||||
.and_then(|v| v.visible())
|
.and_then(|v| v.visible())
|
||||||
.unwrap_or(true);
|
.unwrap_or(true);
|
||||||
|
|
||||||
// We still run a pass while hidden so that app logic keeps ticking,
|
|
||||||
// but we tell egui to skip all book-keeping that assumes ui was shown:
|
|
||||||
raw_input.uiless_pass = !is_visible;
|
|
||||||
|
|
||||||
let full_output = self.egui_ctx.run_ui(raw_input, |ui| {
|
let full_output = self.egui_ctx.run_ui(raw_input, |ui| {
|
||||||
self.app.logic(ui.ctx(), &mut self.frame);
|
self.app.logic(ui.ctx(), &mut self.frame);
|
||||||
|
|
||||||
|
|||||||
@@ -457,9 +457,10 @@ impl ContextImpl {
|
|||||||
|
|
||||||
let viewport = self.viewports.entry(self.viewport_id()).or_default();
|
let viewport = self.viewports.entry(self.viewport_id()).or_default();
|
||||||
|
|
||||||
// If no ui will be shown this pass we skip all book-keeping that assumes ui was shown.
|
// If the window is minimized or occluded, the integration may still run passes
|
||||||
// See `RawInput::uiless_pass`.
|
// to keep app logic ticking, but without showing any ui.
|
||||||
let uiless_pass = new_raw_input.uiless_pass;
|
// We then skip all book-keeping that assumes ui was shown.
|
||||||
|
let is_visible = new_raw_input.viewport().visible().unwrap_or(true);
|
||||||
|
|
||||||
self.memory.begin_pass(&new_raw_input, &all_viewport_ids);
|
self.memory.begin_pass(&new_raw_input, &all_viewport_ids);
|
||||||
|
|
||||||
@@ -475,7 +476,7 @@ impl ContextImpl {
|
|||||||
|
|
||||||
viewport.this_pass.begin_pass();
|
viewport.this_pass.begin_pass();
|
||||||
|
|
||||||
if !uiless_pass {
|
if is_visible {
|
||||||
// Areas that are not interactable are click-through: skip them in the hit-test.
|
// Areas that are not interactable are click-through: skip them in the hit-test.
|
||||||
let mut layers: Vec<LayerId> = viewport
|
let mut layers: Vec<LayerId> = viewport
|
||||||
.prev_pass
|
.prev_pass
|
||||||
@@ -520,7 +521,7 @@ impl ContextImpl {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.is_accesskit_enabled && !uiless_pass {
|
if self.is_accesskit_enabled && is_visible {
|
||||||
profiling::scope!("accesskit");
|
profiling::scope!("accesskit");
|
||||||
use crate::pass_state::AccessKitPassState;
|
use crate::pass_state::AccessKitPassState;
|
||||||
let id = crate::accesskit_root_id();
|
let id = crate::accesskit_root_id();
|
||||||
@@ -811,15 +812,15 @@ impl Context {
|
|||||||
);
|
);
|
||||||
|
|
||||||
{
|
{
|
||||||
// Plugins may show ui, so don't run them when no ui should be shown.
|
// Plugins may show ui, so don't run them when nothing is shown.
|
||||||
// See `RawInput::uiless_pass`.
|
// See [`Context::is_visible`].
|
||||||
let show_ui = !ctx.is_uiless_pass();
|
let is_visible = ctx.is_visible();
|
||||||
|
|
||||||
if show_ui {
|
if is_visible {
|
||||||
plugins.on_begin_pass(&mut root_ui);
|
plugins.on_begin_pass(&mut root_ui);
|
||||||
}
|
}
|
||||||
run_ui(&mut root_ui);
|
run_ui(&mut root_ui);
|
||||||
if show_ui {
|
if is_visible {
|
||||||
plugins.on_end_pass(&mut root_ui);
|
plugins.on_end_pass(&mut root_ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -835,7 +836,7 @@ impl Context {
|
|||||||
fn run_dyn(&self, mut new_input: RawInput, run_ui: &mut dyn FnMut(&Self)) -> FullOutput {
|
fn run_dyn(&self, mut new_input: RawInput, run_ui: &mut dyn FnMut(&Self)) -> FullOutput {
|
||||||
profiling::function_scope!();
|
profiling::function_scope!();
|
||||||
let viewport_id = new_input.viewport_id;
|
let viewport_id = new_input.viewport_id;
|
||||||
let uiless_pass = new_input.uiless_pass;
|
let is_visible = new_input.viewport().visible().unwrap_or(true);
|
||||||
let max_passes = self.write(|ctx| ctx.memory.options.max_passes.get());
|
let max_passes = self.write(|ctx| ctx.memory.options.max_passes.get());
|
||||||
|
|
||||||
let mut output = FullOutput::default();
|
let mut output = FullOutput::default();
|
||||||
@@ -895,8 +896,9 @@ impl Context {
|
|||||||
} else {
|
} else {
|
||||||
viewport.num_multipass_in_row = 0;
|
viewport.num_multipass_in_row = 0;
|
||||||
}
|
}
|
||||||
if !uiless_pass {
|
if is_visible {
|
||||||
// A uiless pass is not a frame: nothing was shown. See `RawInput::uiless_pass`.
|
// A pass without any ui is not a frame: nothing was shown.
|
||||||
|
// See [`Context::is_visible`].
|
||||||
viewport.repaint.cumulative_frame_nr += 1;
|
viewport.repaint.cumulative_frame_nr += 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1734,15 +1736,22 @@ impl Context {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this a pass where no ui will be shown?
|
/// Is the current viewport visible, i.e. neither minimized nor occluded?
|
||||||
///
|
///
|
||||||
/// This is `true` when the integration runs a pass only to keep app logic ticking,
|
/// When this is `false`, the integration may still run passes so that app logic keeps
|
||||||
/// e.g. because the window is minimized or occluded.
|
/// ticking (e.g. so the app can send a [`crate::ViewportCommand`] to show itself again),
|
||||||
/// Don't show any ui while this is `true`.
|
/// but nothing is painted, and no ui should be shown.
|
||||||
///
|
///
|
||||||
/// See [`RawInput::uiless_pass`].
|
/// egui also skips all book-keeping that assumes ui was shown, so that widgets don't
|
||||||
pub fn is_uiless_pass(&self) -> bool {
|
/// think they were hidden and replay their appear-animations, popups don't close,
|
||||||
self.input(|i| i.raw.uiless_pass)
|
/// focus isn't lost, and so on.
|
||||||
|
///
|
||||||
|
/// Defaults to `true` if the integration doesn't report
|
||||||
|
/// [`ViewportInfo::minimized`] and [`ViewportInfo::occluded`].
|
||||||
|
///
|
||||||
|
/// See [`ViewportInfo::visible`].
|
||||||
|
pub fn is_visible(&self) -> bool {
|
||||||
|
self.input(|i| i.viewport().visible().unwrap_or(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The total number of completed passes (usually there is one pass per rendered frame).
|
/// The total number of completed passes (usually there is one pass per rendered frame).
|
||||||
@@ -2429,7 +2438,7 @@ impl Context {
|
|||||||
self.sync_window_theme();
|
self.sync_window_theme();
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
if !self.is_uiless_pass() {
|
if self.is_visible() {
|
||||||
self.debug_painting();
|
self.debug_painting();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2641,11 +2650,12 @@ impl ContextImpl {
|
|||||||
let viewport = self.viewports.entry(ended_viewport_id).or_default();
|
let viewport = self.viewports.entry(ended_viewport_id).or_default();
|
||||||
let pixels_per_point = viewport.input.pixels_per_point;
|
let pixels_per_point = viewport.input.pixels_per_point;
|
||||||
|
|
||||||
// If no ui was shown this pass we skip all book-keeping that assumes ui was shown.
|
// If nothing was shown this pass we skip all book-keeping that assumes ui was shown.
|
||||||
let uiless_pass = viewport.input.raw.uiless_pass;
|
// See [`Context::is_visible`].
|
||||||
|
let is_visible = viewport.input.viewport().visible().unwrap_or(true);
|
||||||
|
|
||||||
if !uiless_pass {
|
if is_visible {
|
||||||
// A uiless pass uses no images and no widget ids,
|
// A pass without any ui uses no images and no widget ids,
|
||||||
// so garbage-collecting based on it would throw away things we still need.
|
// so garbage-collecting based on it would throw away things we still need.
|
||||||
self.loaders.end_pass(viewport.repaint.cumulative_pass_nr);
|
self.loaders.end_pass(viewport.repaint.cumulative_pass_nr);
|
||||||
|
|
||||||
@@ -2704,7 +2714,7 @@ impl ContextImpl {
|
|||||||
|
|
||||||
let mut repaint_needed = false;
|
let mut repaint_needed = false;
|
||||||
|
|
||||||
if self.memory.options.repaint_on_widget_change && !uiless_pass {
|
if self.memory.options.repaint_on_widget_change && is_visible {
|
||||||
profiling::scope!("compare-widget-rects");
|
profiling::scope!("compare-widget-rects");
|
||||||
#[allow(clippy::allow_attributes, clippy::collapsible_if)] // false positive on wasm
|
#[allow(clippy::allow_attributes, clippy::collapsible_if)] // false positive on wasm
|
||||||
if viewport.prev_pass.widgets != viewport.this_pass.widgets {
|
if viewport.prev_pass.widgets != viewport.this_pass.widgets {
|
||||||
@@ -2725,7 +2735,7 @@ impl ContextImpl {
|
|||||||
shapes
|
shapes
|
||||||
};
|
};
|
||||||
|
|
||||||
if !uiless_pass {
|
if is_visible {
|
||||||
// Keep `prev_pass` from the last pass that actually showed ui,
|
// Keep `prev_pass` from the last pass that actually showed ui,
|
||||||
// so widgets are still found by the next hit-test and interaction.
|
// so widgets are still found by the next hit-test and interaction.
|
||||||
std::mem::swap(&mut viewport.prev_pass, &mut viewport.this_pass);
|
std::mem::swap(&mut viewport.prev_pass, &mut viewport.this_pass);
|
||||||
@@ -2758,10 +2768,10 @@ impl ContextImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let is_our_child = parent == ended_viewport_id && id != ViewportId::ROOT;
|
let is_our_child = parent == ended_viewport_id && id != ViewportId::ROOT;
|
||||||
if is_our_child && !uiless_pass {
|
if is_our_child && is_visible {
|
||||||
// A uiless pass never calls `Context::show_viewport_deferred`,
|
// A pass without any ui never calls `Context::show_viewport_deferred`,
|
||||||
// so we must not read `used` from it: that would close all our child
|
// so we must not read `used` from it: that would close all our child
|
||||||
// viewports, only for them to pop back up on the next normal pass.
|
// viewports, only for them to pop back up on the next visible pass.
|
||||||
if !viewport.used {
|
if !viewport.used {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"Removing viewport {:?} ({:?}): it was never used this pass",
|
"Removing viewport {:?} ({:?}): it was never used this pass",
|
||||||
|
|||||||
@@ -89,20 +89,6 @@ pub struct RawInput {
|
|||||||
///
|
///
|
||||||
/// `None` means "don't know".
|
/// `None` means "don't know".
|
||||||
pub system_theme: Option<Theme>,
|
pub system_theme: Option<Theme>,
|
||||||
|
|
||||||
/// Set this if no ui will be shown during this pass.
|
|
||||||
///
|
|
||||||
/// An integration sets this when the window is hidden, minimized, or occluded,
|
|
||||||
/// but it still wants to run a pass so that background logic keeps ticking
|
|
||||||
/// (e.g. so the app can send a [`crate::ViewportCommand`] to show itself again).
|
|
||||||
///
|
|
||||||
/// egui then skips all the book-keeping that assumes ui was shown, so that
|
|
||||||
/// widgets don't think they were hidden and replay their appear-animations,
|
|
||||||
/// popups don't close, focus isn't lost, and so on.
|
|
||||||
/// See <https://github.com/emilk/egui/issues/8266>.
|
|
||||||
///
|
|
||||||
/// If you set this, you must not show any ui during the pass.
|
|
||||||
pub uiless_pass: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RawInput {
|
impl Default for RawInput {
|
||||||
@@ -120,7 +106,6 @@ impl Default for RawInput {
|
|||||||
focused: true, // integrations opt into global focus tracking
|
focused: true, // integrations opt into global focus tracking
|
||||||
system_theme: None,
|
system_theme: None,
|
||||||
safe_area_insets: Default::default(),
|
safe_area_insets: Default::default(),
|
||||||
uiless_pass: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,7 +139,6 @@ impl RawInput {
|
|||||||
dropped_files: std::mem::take(&mut self.dropped_files),
|
dropped_files: std::mem::take(&mut self.dropped_files),
|
||||||
focused: self.focused,
|
focused: self.focused,
|
||||||
system_theme: self.system_theme,
|
system_theme: self.system_theme,
|
||||||
uiless_pass: self.uiless_pass,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +157,6 @@ impl RawInput {
|
|||||||
focused,
|
focused,
|
||||||
system_theme,
|
system_theme,
|
||||||
safe_area_insets: safe_area,
|
safe_area_insets: safe_area,
|
||||||
uiless_pass,
|
|
||||||
} = newer;
|
} = newer;
|
||||||
|
|
||||||
self.viewport_id = viewport_ids;
|
self.viewport_id = viewport_ids;
|
||||||
@@ -188,7 +171,6 @@ impl RawInput {
|
|||||||
self.focused = focused;
|
self.focused = focused;
|
||||||
self.system_theme = system_theme;
|
self.system_theme = system_theme;
|
||||||
self.safe_area_insets = safe_area;
|
self.safe_area_insets = safe_area;
|
||||||
self.uiless_pass = uiless_pass;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +189,6 @@ impl RawInput {
|
|||||||
focused,
|
focused,
|
||||||
system_theme,
|
system_theme,
|
||||||
safe_area_insets: safe_area,
|
safe_area_insets: safe_area,
|
||||||
uiless_pass,
|
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
ui.label(format!("Active viewport: {viewport_id:?}"));
|
ui.label(format!("Active viewport: {viewport_id:?}"));
|
||||||
@@ -237,7 +218,6 @@ impl RawInput {
|
|||||||
ui.label(format!("focused: {focused}"));
|
ui.label(format!("focused: {focused}"));
|
||||||
ui.label(format!("system_theme: {system_theme:?}"));
|
ui.label(format!("system_theme: {system_theme:?}"));
|
||||||
ui.label(format!("safe_area: {safe_area:?}"));
|
ui.label(format!("safe_area: {safe_area:?}"));
|
||||||
ui.label(format!("uiless_pass: {uiless_pass}"));
|
|
||||||
ui.scope(|ui| {
|
ui.scope(|ui| {
|
||||||
ui.set_min_height(150.0);
|
ui.set_min_height(150.0);
|
||||||
ui.label(format!("events: {events:#?}"))
|
ui.label(format!("events: {events:#?}"))
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ impl ViewportInfo {
|
|||||||
/// A window is not visible if it is minimized or occluded.
|
/// A window is not visible if it is minimized or occluded.
|
||||||
/// When not visible, the UI is not painted and rendering is skipped,
|
/// When not visible, the UI is not painted and rendering is skipped,
|
||||||
/// but application logic may still be executed by some integrations.
|
/// but application logic may still be executed by some integrations.
|
||||||
|
///
|
||||||
|
/// See also [`crate::Context::is_visible`].
|
||||||
pub fn visible(&self) -> Option<bool> {
|
pub fn visible(&self) -> Option<bool> {
|
||||||
match (self.minimized, self.occluded) {
|
match (self.minimized, self.occluded) {
|
||||||
(Some(true), _) | (_, Some(true)) => Some(false),
|
(Some(true), _) | (_, Some(true)) => Some(false),
|
||||||
|
|||||||
@@ -797,9 +797,9 @@ impl Memory {
|
|||||||
|
|
||||||
self.options.begin_pass(new_raw_input);
|
self.options.begin_pass(new_raw_input);
|
||||||
|
|
||||||
if !new_raw_input.uiless_pass {
|
if new_raw_input.viewport().visible().unwrap_or(true) {
|
||||||
// No widget will ask for focus during a uiless pass,
|
// When nothing is shown, no widget will ask for focus,
|
||||||
// so leave the focus state alone.
|
// so leave the focus state alone. See [`crate::Context::is_visible`].
|
||||||
self.focus
|
self.focus
|
||||||
.entry(self.viewport_id)
|
.entry(self.viewport_id)
|
||||||
.or_default()
|
.or_default()
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ impl<'a, State> Harness<'a, State> {
|
|||||||
fn _step(&mut self, sizing_pass: bool) {
|
fn _step(&mut self, sizing_pass: bool) {
|
||||||
self.input.predicted_dt = self.step_dt;
|
self.input.predicted_dt = self.step_dt;
|
||||||
|
|
||||||
let uiless_pass = self.input.uiless_pass;
|
let is_visible = self.input.viewport().visible().unwrap_or(true);
|
||||||
|
|
||||||
let mut output = self.ctx.run_ui(self.input.take(), |ui| {
|
let mut output = self.ctx.run_ui(self.input.take(), |ui| {
|
||||||
self.response = self.app.run(ui, &mut self.state, sizing_pass);
|
self.response = self.app.run(ui, &mut self.state, sizing_pass);
|
||||||
@@ -267,9 +267,9 @@ impl<'a, State> Harness<'a, State> {
|
|||||||
if let Some(accesskit_update) = output.platform_output.accesskit_update.take() {
|
if let Some(accesskit_update) = output.platform_output.accesskit_update.take() {
|
||||||
self.kittest.update(accesskit_update);
|
self.kittest.update(accesskit_update);
|
||||||
} else {
|
} else {
|
||||||
// A uiless pass shows no ui, so there is no accessibility tree to update.
|
// An occluded/minimized viewport shows no ui, so there is no accessibility tree
|
||||||
// Keep the tree from the last pass that did show ui.
|
// to update. Keep the tree from the last visible pass.
|
||||||
assert!(uiless_pass, "AccessKit was disabled");
|
assert!(!is_visible, "AccessKit was disabled");
|
||||||
}
|
}
|
||||||
self.renderer.handle_delta(&mut output.textures_delta);
|
self.renderer.handle_delta(&mut output.textures_delta);
|
||||||
self.output = output;
|
self.output = output;
|
||||||
|
|||||||
@@ -560,14 +560,14 @@ fn tooltip_should_hand_over_to_neighboring_widget() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An integration runs a pass with [`egui::RawInput::uiless_pass`] set when its window is
|
/// When a window is minimized or occluded, an integration may keep running passes so that
|
||||||
/// hidden, minimized, or occluded, so that app logic keeps ticking without showing any ui.
|
/// app logic keeps ticking, but without showing any ui. See [`egui::Context::is_visible`].
|
||||||
///
|
///
|
||||||
/// Such a pass must leave all ui state alone. Otherwise areas think they were hidden and
|
/// Such a pass must leave all ui state alone. Otherwise areas think they were hidden and
|
||||||
/// replay their fade-in, popups close, focus is lost, and child viewports pop back up.
|
/// replay their fade-in, popups close, focus is lost, and child viewports pop back up.
|
||||||
/// See <https://github.com/emilk/egui/issues/8266>.
|
/// See <https://github.com/emilk/egui/issues/8266>.
|
||||||
#[test]
|
#[test]
|
||||||
fn uiless_pass_should_not_disturb_ui_state() {
|
fn occluded_pass_should_not_disturb_ui_state() {
|
||||||
const MENU: &str = "My menu";
|
const MENU: &str = "My menu";
|
||||||
const MENU_ITEM: &str = "Button in my menu";
|
const MENU_ITEM: &str = "Button in my menu";
|
||||||
const FOCUSED_BUTTON: &str = "Click me";
|
const FOCUSED_BUTTON: &str = "Click me";
|
||||||
@@ -582,8 +582,8 @@ fn uiless_pass_should_not_disturb_ui_state() {
|
|||||||
// A backend that can open real windows, like eframe:
|
// A backend that can open real windows, like eframe:
|
||||||
ui.ctx().set_embed_viewports(false);
|
ui.ctx().set_embed_viewports(false);
|
||||||
|
|
||||||
if ui.ctx().is_uiless_pass() {
|
if !ui.ctx().is_visible() {
|
||||||
// The integration shows no ui and viewports during a uiless pass.
|
// The integration shows no ui and no viewports while occluded.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,17 +633,22 @@ fn uiless_pass_should_not_disturb_ui_state() {
|
|||||||
|
|
||||||
assert_state(&harness);
|
assert_state(&harness);
|
||||||
|
|
||||||
|
let set_occluded = |harness: &mut Harness<'_>, occluded: bool| {
|
||||||
|
let input = harness.input_mut();
|
||||||
|
let viewport_id = input.viewport_id;
|
||||||
|
input.viewports.entry(viewport_id).or_default().occluded = Some(occluded);
|
||||||
|
};
|
||||||
|
|
||||||
// The window is now occluded, so the integration runs passes without any ui.
|
// The window is now occluded, so the integration runs passes without any ui.
|
||||||
// egui keeps the accessibility tree from the last pass that did show ui,
|
// egui keeps the accessibility tree from the last visible pass, so we can still query it.
|
||||||
// so we can still query it.
|
set_occluded(&mut harness, true);
|
||||||
harness.input_mut().uiless_pass = true;
|
|
||||||
harness.step();
|
harness.step();
|
||||||
harness.step();
|
harness.step();
|
||||||
|
|
||||||
assert_state(&harness);
|
assert_state(&harness);
|
||||||
|
|
||||||
// The window is visible again, and everything should be where we left it:
|
// The window is visible again, and everything should be where we left it:
|
||||||
harness.input_mut().uiless_pass = false;
|
set_occluded(&mut harness, false);
|
||||||
harness.run();
|
harness.run();
|
||||||
|
|
||||||
assert_state(&harness);
|
assert_state(&harness);
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ impl eframe::App for App {
|
|||||||
|
|
||||||
fn viewport_info(ctx: &egui::Context) -> String {
|
fn viewport_info(ctx: &egui::Context) -> String {
|
||||||
ctx.input(|i| {
|
ctx.input(|i| {
|
||||||
use std::fmt::Write as _;
|
|
||||||
let ViewportInfo {
|
let ViewportInfo {
|
||||||
minimized,
|
minimized,
|
||||||
focused,
|
focused,
|
||||||
@@ -57,12 +56,10 @@ fn viewport_info(ctx: &egui::Context) -> String {
|
|||||||
];
|
];
|
||||||
for (name, value) in flags {
|
for (name, value) in flags {
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
|
use std::fmt::Write as _;
|
||||||
write!(s, " {name}={value}").ok();
|
write!(s, " {name}={value}").ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(s, " uiless_pass={}", i.raw.uiless_pass).ok();
|
|
||||||
|
|
||||||
s
|
s
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user