egui/
context.rs

1#![warn(missing_docs)] // Let's keep `Context` well-documented.
2
3use std::{borrow::Cow, cell::RefCell, panic::Location, sync::Arc, time::Duration};
4
5use emath::GuiRounding as _;
6use epaint::{
7    ClippedPrimitive, ClippedShape, Color32, ImageData, Pos2, Rect, StrokeKind,
8    TessellationOptions, TextureId, Vec2,
9    emath::{self, TSTransform},
10    mutex::RwLock,
11    stats::PaintStats,
12    tessellator,
13    text::{FontInsert, FontPriority, Fonts, FontsView},
14    vec2,
15};
16
17use crate::{
18    Align2, CursorIcon, DeferredViewportUiCallback, FontDefinitions, Grid, Id, ImmediateViewport,
19    ImmediateViewportRendererCallback, Key, KeyboardShortcut, Label, LayerId, Memory,
20    ModifierNames, Modifiers, NumExt as _, Order, Painter, RawInput, Response, RichText,
21    SafeAreaInsets, ScrollArea, Sense, Style, TextStyle, TextureHandle, TextureOptions, Ui,
22    ViewportBuilder, ViewportCommand, ViewportId, ViewportIdMap, ViewportIdPair, ViewportIdSet,
23    ViewportOutput, Widget as _, WidgetRect, WidgetText,
24    animation_manager::AnimationManager,
25    containers::{self, area::AreaState},
26    data::output::PlatformOutput,
27    epaint,
28    hit_test::WidgetHits,
29    input_state::{InputState, MultiTouchInfo, PointerEvent, SurrenderFocusOn},
30    interaction::InteractionSnapshot,
31    layers::GraphicLayers,
32    load::{self, Bytes, Loaders, SizedTexture},
33    memory::{Options, Theme},
34    os::OperatingSystem,
35    output::FullOutput,
36    pass_state::PassState,
37    plugin,
38    plugin::TypedPluginHandle,
39    resize, response, scroll_area,
40    util::IdTypeMap,
41    viewport::ViewportClass,
42};
43
44#[cfg(feature = "accesskit")]
45use crate::IdMap;
46
47/// Information given to the backend about when it is time to repaint the ui.
48///
49/// This is given in the callback set by [`Context::set_request_repaint_callback`].
50#[derive(Clone, Copy, Debug)]
51pub struct RequestRepaintInfo {
52    /// This is used to specify what viewport that should repaint.
53    pub viewport_id: ViewportId,
54
55    /// Repaint after this duration. If zero, repaint as soon as possible.
56    pub delay: Duration,
57
58    /// The number of fully completed passes, of the entire lifetime of the [`Context`].
59    ///
60    /// This can be compared to [`Context::cumulative_pass_nr`] to see if we we still
61    /// need another repaint (ui pass / frame), or if one has already happened.
62    pub current_cumulative_pass_nr: u64,
63}
64
65// ----------------------------------------------------------------------------
66
67thread_local! {
68    static IMMEDIATE_VIEWPORT_RENDERER: RefCell<Option<Box<ImmediateViewportRendererCallback>>> = Default::default();
69}
70
71// ----------------------------------------------------------------------------
72
73struct WrappedTextureManager(Arc<RwLock<epaint::TextureManager>>);
74
75impl Default for WrappedTextureManager {
76    fn default() -> Self {
77        let mut tex_mngr = epaint::textures::TextureManager::default();
78
79        // Will be filled in later
80        let font_id = tex_mngr.alloc(
81            "egui_font_texture".into(),
82            epaint::ColorImage::filled([0, 0], Color32::TRANSPARENT).into(),
83            Default::default(),
84        );
85        assert_eq!(
86            font_id,
87            TextureId::default(),
88            "font id should be equal to TextureId::default(), but was {font_id:?}",
89        );
90
91        Self(Arc::new(RwLock::new(tex_mngr)))
92    }
93}
94
95// ----------------------------------------------------------------------------
96
97/// Repaint-logic
98impl ContextImpl {
99    /// This is where we update the repaint logic.
100    fn begin_pass_repaint_logic(&mut self, viewport_id: ViewportId) {
101        let viewport = self.viewports.entry(viewport_id).or_default();
102
103        std::mem::swap(
104            &mut viewport.repaint.prev_causes,
105            &mut viewport.repaint.causes,
106        );
107        viewport.repaint.causes.clear();
108
109        viewport.repaint.prev_pass_paint_delay = viewport.repaint.repaint_delay;
110
111        if viewport.repaint.outstanding == 0 {
112            // We are repainting now, so we can wait a while for the next repaint.
113            viewport.repaint.repaint_delay = Duration::MAX;
114        } else {
115            viewport.repaint.repaint_delay = Duration::ZERO;
116            viewport.repaint.outstanding -= 1;
117            if let Some(callback) = &self.request_repaint_callback {
118                (callback)(RequestRepaintInfo {
119                    viewport_id,
120                    delay: Duration::ZERO,
121                    current_cumulative_pass_nr: viewport.repaint.cumulative_pass_nr,
122                });
123            }
124        }
125    }
126
127    fn request_repaint(&mut self, viewport_id: ViewportId, cause: RepaintCause) {
128        self.request_repaint_after(Duration::ZERO, viewport_id, cause);
129    }
130
131    fn request_repaint_after(
132        &mut self,
133        mut delay: Duration,
134        viewport_id: ViewportId,
135        cause: RepaintCause,
136    ) {
137        let viewport = self.viewports.entry(viewport_id).or_default();
138
139        if delay == Duration::ZERO {
140            // Each request results in two repaints, just to give some things time to settle.
141            // This solves some corner-cases of missing repaints on frame-delayed responses.
142            viewport.repaint.outstanding = 1;
143        } else {
144            // For non-zero delays, we only repaint once, because
145            // otherwise we would just schedule an immediate repaint _now_,
146            // which would then clear the delay and repaint again.
147            // Hovering a tooltip is a good example of a case where we want to repaint after a delay.
148        }
149
150        if let Ok(predicted_frame_time) = Duration::try_from_secs_f32(viewport.input.predicted_dt) {
151            // Make it less likely we over-shoot the target:
152            delay = delay.saturating_sub(predicted_frame_time);
153        }
154
155        viewport.repaint.causes.push(cause);
156
157        // We save some CPU time by only calling the callback if we need to.
158        // If the new delay is greater or equal to the previous lowest,
159        // it means we have already called the callback, and don't need to do it again.
160        if delay < viewport.repaint.repaint_delay {
161            viewport.repaint.repaint_delay = delay;
162
163            if let Some(callback) = &self.request_repaint_callback {
164                (callback)(RequestRepaintInfo {
165                    viewport_id,
166                    delay,
167                    current_cumulative_pass_nr: viewport.repaint.cumulative_pass_nr,
168                });
169            }
170        }
171    }
172
173    #[must_use]
174    fn requested_immediate_repaint_prev_pass(&self, viewport_id: &ViewportId) -> bool {
175        self.viewports
176            .get(viewport_id)
177            .is_some_and(|v| v.repaint.requested_immediate_repaint_prev_pass())
178    }
179
180    #[must_use]
181    fn has_requested_repaint(&self, viewport_id: &ViewportId) -> bool {
182        self.viewports
183            .get(viewport_id)
184            .is_some_and(|v| 0 < v.repaint.outstanding || v.repaint.repaint_delay < Duration::MAX)
185    }
186}
187
188// ----------------------------------------------------------------------------
189
190/// State stored per viewport.
191///
192/// Mostly for internal use.
193/// Things here may move and change without warning.
194#[derive(Default)]
195pub struct ViewportState {
196    /// The type of viewport.
197    ///
198    /// This will never be [`ViewportClass::Embedded`],
199    /// since those don't result in real viewports.
200    pub class: ViewportClass,
201
202    /// The latest delta
203    pub builder: ViewportBuilder,
204
205    /// The user-code that shows the GUI, used for deferred viewports.
206    ///
207    /// `None` for immediate viewports.
208    pub viewport_ui_cb: Option<Arc<DeferredViewportUiCallback>>,
209
210    pub input: InputState,
211
212    /// State that is collected during a pass and then cleared.
213    pub this_pass: PassState,
214
215    /// The final [`PassState`] from last pass.
216    ///
217    /// Only read from.
218    pub prev_pass: PassState,
219
220    /// Has this viewport been updated this pass?
221    pub used: bool,
222
223    /// State related to repaint scheduling.
224    repaint: ViewportRepaintInfo,
225
226    // ----------------------
227    // Updated at the start of the pass:
228    //
229    /// Which widgets are under the pointer?
230    pub hits: WidgetHits,
231
232    /// What widgets are being interacted with this pass?
233    ///
234    /// Based on the widgets from last pass, and input in this pass.
235    pub interact_widgets: InteractionSnapshot,
236
237    // ----------------------
238    // The output of a pass:
239    //
240    pub graphics: GraphicLayers,
241    // Most of the things in `PlatformOutput` are not actually viewport dependent.
242    pub output: PlatformOutput,
243    pub commands: Vec<ViewportCommand>,
244
245    // ----------------------
246    // Cross-frame statistics:
247    pub num_multipass_in_row: usize,
248}
249
250/// What called [`Context::request_repaint`] or [`Context::request_discard`]?
251#[derive(Clone, PartialEq, Eq, Hash)]
252pub struct RepaintCause {
253    /// What file had the call that requested the repaint?
254    pub file: &'static str,
255
256    /// What line number of the call that requested the repaint?
257    pub line: u32,
258
259    /// Explicit reason; human readable.
260    pub reason: Cow<'static, str>,
261}
262
263impl std::fmt::Debug for RepaintCause {
264    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
265        write!(f, "{}:{} {}", self.file, self.line, self.reason)
266    }
267}
268
269impl std::fmt::Display for RepaintCause {
270    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271        write!(f, "{}:{} {}", self.file, self.line, self.reason)
272    }
273}
274
275impl RepaintCause {
276    /// Capture the file and line number of the call site.
277    #[expect(clippy::new_without_default)]
278    #[track_caller]
279    pub fn new() -> Self {
280        let caller = Location::caller();
281        Self {
282            file: caller.file(),
283            line: caller.line(),
284            reason: "".into(),
285        }
286    }
287
288    /// Capture the file and line number of the call site,
289    /// as well as add a reason.
290    #[track_caller]
291    pub fn new_reason(reason: impl Into<Cow<'static, str>>) -> Self {
292        let caller = Location::caller();
293        Self {
294            file: caller.file(),
295            line: caller.line(),
296            reason: reason.into(),
297        }
298    }
299}
300
301/// Per-viewport state related to repaint scheduling.
302struct ViewportRepaintInfo {
303    /// Monotonically increasing counter.
304    ///
305    /// Incremented at the end of [`Context::run`].
306    /// This can be smaller than [`Self::cumulative_pass_nr`],
307    /// but never larger.
308    cumulative_frame_nr: u64,
309
310    /// Monotonically increasing counter, counting the number of passes.
311    /// This can be larger than [`Self::cumulative_frame_nr`],
312    /// but never smaller.
313    cumulative_pass_nr: u64,
314
315    /// The duration which the backend will poll for new events
316    /// before forcing another egui update, even if there's no new events.
317    ///
318    /// Also used to suppress multiple calls to the repaint callback during the same pass.
319    ///
320    /// This is also returned in [`crate::ViewportOutput`].
321    repaint_delay: Duration,
322
323    /// While positive, keep requesting repaints. Decrement at the start of each pass.
324    outstanding: u8,
325
326    /// What caused repaints during this pass?
327    causes: Vec<RepaintCause>,
328
329    /// What triggered a repaint the previous pass?
330    /// (i.e: why are we updating now?)
331    prev_causes: Vec<RepaintCause>,
332
333    /// What was the output of `repaint_delay` on the previous pass?
334    ///
335    /// If this was zero, we are repainting as quickly as possible
336    /// (as far as we know).
337    prev_pass_paint_delay: Duration,
338}
339
340impl Default for ViewportRepaintInfo {
341    fn default() -> Self {
342        Self {
343            cumulative_frame_nr: 0,
344            cumulative_pass_nr: 0,
345
346            // We haven't scheduled a repaint yet.
347            repaint_delay: Duration::MAX,
348
349            // Let's run a couple of frames at the start, because why not.
350            outstanding: 1,
351
352            causes: Default::default(),
353            prev_causes: Default::default(),
354
355            prev_pass_paint_delay: Duration::MAX,
356        }
357    }
358}
359
360impl ViewportRepaintInfo {
361    pub fn requested_immediate_repaint_prev_pass(&self) -> bool {
362        self.prev_pass_paint_delay == Duration::ZERO
363    }
364}
365
366// ----------------------------------------------------------------------------
367
368#[derive(Default)]
369struct ContextImpl {
370    fonts: Option<Fonts>,
371    font_definitions: FontDefinitions,
372
373    memory: Memory,
374    animation_manager: AnimationManager,
375
376    plugins: plugin::Plugins,
377    safe_area: SafeAreaInsets,
378
379    /// All viewports share the same texture manager and texture namespace.
380    ///
381    /// In all viewports, [`TextureId::default`] is special, and points to the font atlas.
382    /// The font-atlas texture _may_ be different across viewports, as they may have different
383    /// `pixels_per_point`, so we do special book-keeping for that.
384    /// See <https://github.com/emilk/egui/issues/3664>.
385    tex_manager: WrappedTextureManager,
386
387    /// Set during the pass, becomes active at the start of the next pass.
388    new_zoom_factor: Option<f32>,
389
390    os: OperatingSystem,
391
392    /// How deeply nested are we?
393    viewport_stack: Vec<ViewportIdPair>,
394
395    /// What is the last viewport rendered?
396    last_viewport: ViewportId,
397
398    paint_stats: PaintStats,
399
400    request_repaint_callback: Option<Box<dyn Fn(RequestRepaintInfo) + Send + Sync>>,
401
402    viewport_parents: ViewportIdMap<ViewportId>,
403    viewports: ViewportIdMap<ViewportState>,
404
405    embed_viewports: bool,
406
407    #[cfg(feature = "accesskit")]
408    is_accesskit_enabled: bool,
409
410    loaders: Arc<Loaders>,
411}
412
413impl ContextImpl {
414    fn begin_pass(&mut self, mut new_raw_input: RawInput) {
415        let viewport_id = new_raw_input.viewport_id;
416        let parent_id = new_raw_input
417            .viewports
418            .get(&viewport_id)
419            .and_then(|v| v.parent)
420            .unwrap_or_default();
421        let ids = ViewportIdPair::from_self_and_parent(viewport_id, parent_id);
422
423        if let Some(safe_area) = new_raw_input.safe_area_insets {
424            self.safe_area = safe_area;
425        }
426
427        let is_outermost_viewport = self.viewport_stack.is_empty(); // not necessarily root, just outermost immediate viewport
428        self.viewport_stack.push(ids);
429
430        self.begin_pass_repaint_logic(viewport_id);
431
432        let viewport = self.viewports.entry(viewport_id).or_default();
433
434        if is_outermost_viewport && let Some(new_zoom_factor) = self.new_zoom_factor.take() {
435            let ratio = self.memory.options.zoom_factor / new_zoom_factor;
436            self.memory.options.zoom_factor = new_zoom_factor;
437
438            let input = &viewport.input;
439            // This is a bit hacky, but is required to avoid jitter:
440            let mut rect = input.content_rect();
441            rect.min = (ratio * rect.min.to_vec2()).to_pos2();
442            rect.max = (ratio * rect.max.to_vec2()).to_pos2();
443            new_raw_input.screen_rect = Some(rect);
444            // We should really scale everything else in the input too,
445            // but the `screen_rect` is the most important part.
446        }
447        let native_pixels_per_point = new_raw_input
448            .viewport()
449            .native_pixels_per_point
450            .unwrap_or(1.0);
451        let pixels_per_point = self.memory.options.zoom_factor * native_pixels_per_point;
452
453        let all_viewport_ids: ViewportIdSet = self.all_viewport_ids();
454
455        let viewport = self.viewports.entry(self.viewport_id()).or_default();
456
457        self.memory.begin_pass(&new_raw_input, &all_viewport_ids);
458
459        viewport.input = std::mem::take(&mut viewport.input).begin_pass(
460            new_raw_input,
461            viewport.repaint.requested_immediate_repaint_prev_pass(),
462            pixels_per_point,
463            self.memory.options.input_options,
464        );
465        let repaint_after = viewport.input.wants_repaint_after();
466
467        let content_rect = viewport.input.content_rect();
468
469        viewport.this_pass.begin_pass(content_rect);
470
471        {
472            let mut layers: Vec<LayerId> = viewport.prev_pass.widgets.layer_ids().collect();
473            layers.sort_by(|&a, &b| self.memory.areas().compare_order(a, b));
474
475            viewport.hits = if let Some(pos) = viewport.input.pointer.interact_pos() {
476                let interact_radius = self.memory.options.style().interaction.interact_radius;
477
478                crate::hit_test::hit_test(
479                    &viewport.prev_pass.widgets,
480                    &layers,
481                    &self.memory.to_global,
482                    pos,
483                    interact_radius,
484                )
485            } else {
486                WidgetHits::default()
487            };
488
489            viewport.interact_widgets = crate::interaction::interact(
490                &viewport.interact_widgets,
491                &viewport.prev_pass.widgets,
492                &viewport.hits,
493                &viewport.input,
494                self.memory.interaction_mut(),
495            );
496        }
497
498        // Ensure we register the background area so panels and background ui can catch clicks:
499        self.memory.areas_mut().set_state(
500            LayerId::background(),
501            AreaState {
502                pivot_pos: Some(content_rect.left_top()),
503                pivot: Align2::LEFT_TOP,
504                size: Some(content_rect.size()),
505                interactable: true,
506                last_became_visible_at: None,
507            },
508        );
509
510        #[cfg(feature = "accesskit")]
511        if self.is_accesskit_enabled {
512            profiling::scope!("accesskit");
513            use crate::pass_state::AccessKitPassState;
514            let id = crate::accesskit_root_id();
515            let mut root_node = accesskit::Node::new(accesskit::Role::Window);
516            let pixels_per_point = viewport.input.pixels_per_point();
517            root_node.set_transform(accesskit::Affine::scale(pixels_per_point.into()));
518            let mut nodes = IdMap::default();
519            nodes.insert(id, root_node);
520            viewport.this_pass.accesskit_state = Some(AccessKitPassState {
521                nodes,
522                parent_map: IdMap::default(),
523            });
524        }
525
526        self.update_fonts_mut();
527
528        if let Some(delay) = repaint_after {
529            self.request_repaint_after(delay, viewport_id, RepaintCause::new());
530        }
531    }
532
533    /// Load fonts unless already loaded.
534    fn update_fonts_mut(&mut self) {
535        profiling::function_scope!();
536        let input = &self.viewport().input;
537        let max_texture_side = input.max_texture_side;
538
539        if let Some(font_definitions) = self.memory.new_font_definitions.take() {
540            // New font definition loaded, so we need to reload all fonts.
541            self.fonts = None;
542            self.font_definitions = font_definitions;
543
544            log::trace!("Loading new font definitions");
545        }
546
547        if !self.memory.add_fonts.is_empty() {
548            let fonts = self.memory.add_fonts.drain(..);
549            for font in fonts {
550                self.fonts = None; // recreate all the fonts
551                for family in font.families {
552                    let fam = self
553                        .font_definitions
554                        .families
555                        .entry(family.family)
556                        .or_default();
557                    match family.priority {
558                        FontPriority::Highest => fam.insert(0, font.name.clone()),
559                        FontPriority::Lowest => fam.push(font.name.clone()),
560                    }
561                }
562                self.font_definitions
563                    .font_data
564                    .insert(font.name, Arc::new(font.data));
565            }
566
567            log::trace!("Adding new fonts");
568        }
569
570        let text_alpha_from_coverage = self.memory.options.style().visuals.text_alpha_from_coverage;
571
572        let mut is_new = false;
573
574        let fonts = self.fonts.get_or_insert_with(|| {
575            log::trace!("Creating new Fonts");
576
577            is_new = true;
578            profiling::scope!("Fonts::new");
579            Fonts::new(
580                max_texture_side,
581                text_alpha_from_coverage,
582                self.font_definitions.clone(),
583            )
584        });
585
586        {
587            profiling::scope!("Fonts::begin_pass");
588            fonts.begin_pass(max_texture_side, text_alpha_from_coverage);
589        }
590    }
591
592    #[cfg(feature = "accesskit")]
593    fn accesskit_node_builder(&mut self, id: Id) -> &mut accesskit::Node {
594        let state = self.viewport().this_pass.accesskit_state.as_mut().unwrap();
595        let builders = &mut state.nodes;
596        if let std::collections::hash_map::Entry::Vacant(entry) = builders.entry(id) {
597            entry.insert(Default::default());
598
599            /// Find the first ancestor that already has an accesskit node.
600            fn find_accesskit_parent(
601                parent_map: &IdMap<Id>,
602                node_map: &IdMap<accesskit::Node>,
603                id: Id,
604            ) -> Option<Id> {
605                if let Some(parent_id) = parent_map.get(&id) {
606                    if node_map.contains_key(parent_id) {
607                        Some(*parent_id)
608                    } else {
609                        find_accesskit_parent(parent_map, node_map, *parent_id)
610                    }
611                } else {
612                    None
613                }
614            }
615
616            let parent_id = find_accesskit_parent(&state.parent_map, builders, id)
617                .unwrap_or(crate::accesskit_root_id());
618
619            let parent_builder = builders.get_mut(&parent_id).unwrap();
620            parent_builder.push_child(id.accesskit_id());
621        }
622        builders.get_mut(&id).unwrap()
623    }
624
625    fn pixels_per_point(&mut self) -> f32 {
626        self.viewport().input.pixels_per_point
627    }
628
629    /// Return the `ViewportId` of the current viewport.
630    ///
631    /// For the root viewport this will return [`ViewportId::ROOT`].
632    pub(crate) fn viewport_id(&self) -> ViewportId {
633        self.viewport_stack.last().copied().unwrap_or_default().this
634    }
635
636    /// Return the `ViewportId` of his parent.
637    ///
638    /// For the root viewport this will return [`ViewportId::ROOT`].
639    pub(crate) fn parent_viewport_id(&self) -> ViewportId {
640        let viewport_id = self.viewport_id();
641        *self
642            .viewport_parents
643            .get(&viewport_id)
644            .unwrap_or(&ViewportId::ROOT)
645    }
646
647    fn all_viewport_ids(&self) -> ViewportIdSet {
648        self.viewports
649            .keys()
650            .copied()
651            .chain([ViewportId::ROOT])
652            .collect()
653    }
654
655    /// The current active viewport
656    pub(crate) fn viewport(&mut self) -> &mut ViewportState {
657        self.viewports.entry(self.viewport_id()).or_default()
658    }
659
660    fn viewport_for(&mut self, viewport_id: ViewportId) -> &mut ViewportState {
661        self.viewports.entry(viewport_id).or_default()
662    }
663}
664
665// ----------------------------------------------------------------------------
666
667/// Your handle to egui.
668///
669/// This is the first thing you need when working with egui.
670/// Contains the [`InputState`], [`Memory`], [`PlatformOutput`], and more.
671///
672/// [`Context`] is cheap to clone, and any clones refers to the same mutable data
673/// ([`Context`] uses refcounting internally).
674///
675/// ## Locking
676/// All methods are marked `&self`; [`Context`] has interior mutability protected by an [`RwLock`].
677///
678/// To access parts of a `Context` you need to use some of the helper functions that take closures:
679///
680/// ```
681/// # let ctx = egui::Context::default();
682/// if ctx.input(|i| i.key_pressed(egui::Key::A)) {
683///     ctx.copy_text("Hello!".to_owned());
684/// }
685/// ```
686///
687/// Within such a closure you may NOT recursively lock the same [`Context`], as that can lead to a deadlock.
688/// Therefore it is important that any lock of [`Context`] is short-lived.
689///
690/// These are effectively transactional accesses.
691///
692/// [`Ui`] has many of the same accessor functions, and the same applies there.
693///
694/// ## Example:
695///
696/// ``` no_run
697/// # fn handle_platform_output(_: egui::PlatformOutput) {}
698/// # fn paint(textures_delta: egui::TexturesDelta, _: Vec<egui::ClippedPrimitive>) {}
699/// let mut ctx = egui::Context::default();
700///
701/// // Game loop:
702/// loop {
703///     let raw_input = egui::RawInput::default();
704///     let full_output = ctx.run(raw_input, |ctx| {
705///         egui::CentralPanel::default().show(&ctx, |ui| {
706///             ui.label("Hello world!");
707///             if ui.button("Click me").clicked() {
708///                 // take some action here
709///             }
710///         });
711///     });
712///     handle_platform_output(full_output.platform_output);
713///     let clipped_primitives = ctx.tessellate(full_output.shapes, full_output.pixels_per_point);
714///     paint(full_output.textures_delta, clipped_primitives);
715/// }
716/// ```
717#[derive(Clone)]
718pub struct Context(Arc<RwLock<ContextImpl>>);
719
720impl std::fmt::Debug for Context {
721    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
722        f.debug_struct("Context").finish_non_exhaustive()
723    }
724}
725
726impl std::cmp::PartialEq for Context {
727    fn eq(&self, other: &Self) -> bool {
728        Arc::ptr_eq(&self.0, &other.0)
729    }
730}
731
732impl Default for Context {
733    fn default() -> Self {
734        let ctx_impl = ContextImpl {
735            embed_viewports: true,
736            viewports: std::iter::once((ViewportId::ROOT, ViewportState::default())).collect(),
737            ..Default::default()
738        };
739        let ctx = Self(Arc::new(RwLock::new(ctx_impl)));
740
741        ctx.add_plugin(plugin::CallbackPlugin::default());
742
743        // Register built-in plugins:
744        ctx.add_plugin(crate::debug_text::DebugTextPlugin::default());
745        ctx.add_plugin(crate::text_selection::LabelSelectionState::default());
746        ctx.add_plugin(crate::DragAndDrop::default());
747
748        ctx
749    }
750}
751
752impl Context {
753    /// Do read-only (shared access) transaction on Context
754    fn read<R>(&self, reader: impl FnOnce(&ContextImpl) -> R) -> R {
755        reader(&self.0.read())
756    }
757
758    /// Do read-write (exclusive access) transaction on Context
759    fn write<R>(&self, writer: impl FnOnce(&mut ContextImpl) -> R) -> R {
760        writer(&mut self.0.write())
761    }
762
763    /// Run the ui code for one frame.
764    ///
765    /// At most [`Options::max_passes`] calls will be issued to `run_ui`,
766    /// and only on the rare occasion that [`Context::request_discard`] is called.
767    /// Usually, it `run_ui` will only be called once.
768    ///
769    /// Put your widgets into a [`crate::SidePanel`], [`crate::TopBottomPanel`], [`crate::CentralPanel`], [`crate::Window`] or [`crate::Area`].
770    ///
771    /// Instead of calling `run`, you can alternatively use [`Self::begin_pass`] and [`Context::end_pass`].
772    ///
773    /// ```
774    /// // One egui context that you keep reusing:
775    /// let mut ctx = egui::Context::default();
776    ///
777    /// // Each frame:
778    /// let input = egui::RawInput::default();
779    /// let full_output = ctx.run(input, |ctx| {
780    ///     egui::CentralPanel::default().show(&ctx, |ui| {
781    ///         ui.label("Hello egui!");
782    ///     });
783    /// });
784    /// // handle full_output
785    /// ```
786    #[must_use]
787    pub fn run(&self, mut new_input: RawInput, mut run_ui: impl FnMut(&Self)) -> FullOutput {
788        profiling::function_scope!();
789        let viewport_id = new_input.viewport_id;
790        let max_passes = self.write(|ctx| ctx.memory.options.max_passes.get());
791
792        let mut output = FullOutput::default();
793        debug_assert_eq!(
794            output.platform_output.num_completed_passes, 0,
795            "output must be fresh, but had {} passes",
796            output.platform_output.num_completed_passes
797        );
798
799        loop {
800            profiling::scope!(
801                "pass",
802                output
803                    .platform_output
804                    .num_completed_passes
805                    .to_string()
806                    .as_str()
807            );
808
809            // We must move the `num_passes` (back) to the viewport output so that [`Self::will_discard`]
810            // has access to the latest pass count.
811            self.write(|ctx| {
812                let viewport = ctx.viewport_for(viewport_id);
813                viewport.output.num_completed_passes =
814                    std::mem::take(&mut output.platform_output.num_completed_passes);
815                output.platform_output.request_discard_reasons.clear();
816            });
817
818            self.begin_pass(new_input.take());
819            run_ui(self);
820            output.append(self.end_pass());
821            debug_assert!(
822                0 < output.platform_output.num_completed_passes,
823                "Completed passes was lower than 0, was {}",
824                output.platform_output.num_completed_passes
825            );
826
827            if !output.platform_output.requested_discard() {
828                break; // no need for another pass
829            }
830
831            if max_passes <= output.platform_output.num_completed_passes {
832                log::debug!(
833                    "Ignoring call request_discard, because max_passes={max_passes}. Requested from {:?}",
834                    output.platform_output.request_discard_reasons
835                );
836
837                break;
838            }
839        }
840
841        self.write(|ctx| {
842            let did_multipass = 1 < output.platform_output.num_completed_passes;
843            let viewport = ctx.viewport_for(viewport_id);
844            if did_multipass {
845                viewport.num_multipass_in_row += 1;
846            } else {
847                viewport.num_multipass_in_row = 0;
848            }
849            viewport.repaint.cumulative_frame_nr += 1;
850        });
851
852        output
853    }
854
855    /// An alternative to calling [`Self::run`].
856    ///
857    /// It is usually better to use [`Self::run`], because
858    /// `run` supports multi-pass layout using [`Self::request_discard`].
859    ///
860    /// ```
861    /// // One egui context that you keep reusing:
862    /// let mut ctx = egui::Context::default();
863    ///
864    /// // Each frame:
865    /// let input = egui::RawInput::default();
866    /// ctx.begin_pass(input);
867    ///
868    /// egui::CentralPanel::default().show(&ctx, |ui| {
869    ///     ui.label("Hello egui!");
870    /// });
871    ///
872    /// let full_output = ctx.end_pass();
873    /// // handle full_output
874    /// ```
875    pub fn begin_pass(&self, mut new_input: RawInput) {
876        profiling::function_scope!();
877
878        let plugins = self.read(|ctx| ctx.plugins.ordered_plugins());
879        plugins.on_input(&mut new_input);
880
881        self.write(|ctx| ctx.begin_pass(new_input));
882
883        // Plugins run just after the pass starts:
884        plugins.on_begin_pass(self);
885    }
886
887    /// See [`Self::begin_pass`].
888    #[deprecated = "Renamed begin_pass"]
889    pub fn begin_frame(&self, new_input: RawInput) {
890        self.begin_pass(new_input);
891    }
892}
893
894/// ## Borrows parts of [`Context`]
895/// These functions all lock the [`Context`].
896/// Please see the documentation of [`Context`] for how locking works!
897impl Context {
898    /// Read-only access to [`InputState`].
899    ///
900    /// Note that this locks the [`Context`].
901    ///
902    /// ```
903    /// # let mut ctx = egui::Context::default();
904    /// ctx.input(|i| {
905    ///     // ⚠️ Using `ctx` (even from other `Arc` reference) again here will lead to a deadlock!
906    /// });
907    ///
908    /// if let Some(pos) = ctx.input(|i| i.pointer.hover_pos()) {
909    ///     // This is fine!
910    /// }
911    /// ```
912    #[inline]
913    pub fn input<R>(&self, reader: impl FnOnce(&InputState) -> R) -> R {
914        self.write(move |ctx| reader(&ctx.viewport().input))
915    }
916
917    /// This will create a `InputState::default()` if there is no input state for that viewport
918    #[inline]
919    pub fn input_for<R>(&self, id: ViewportId, reader: impl FnOnce(&InputState) -> R) -> R {
920        self.write(move |ctx| reader(&ctx.viewport_for(id).input))
921    }
922
923    /// Read-write access to [`InputState`].
924    #[inline]
925    pub fn input_mut<R>(&self, writer: impl FnOnce(&mut InputState) -> R) -> R {
926        self.input_mut_for(self.viewport_id(), writer)
927    }
928
929    /// This will create a `InputState::default()` if there is no input state for that viewport
930    #[inline]
931    pub fn input_mut_for<R>(&self, id: ViewportId, writer: impl FnOnce(&mut InputState) -> R) -> R {
932        self.write(move |ctx| writer(&mut ctx.viewport_for(id).input))
933    }
934
935    /// Read-only access to [`Memory`].
936    #[inline]
937    pub fn memory<R>(&self, reader: impl FnOnce(&Memory) -> R) -> R {
938        self.read(move |ctx| reader(&ctx.memory))
939    }
940
941    /// Read-write access to [`Memory`].
942    #[inline]
943    pub fn memory_mut<R>(&self, writer: impl FnOnce(&mut Memory) -> R) -> R {
944        self.write(move |ctx| writer(&mut ctx.memory))
945    }
946
947    /// Read-only access to [`IdTypeMap`], which stores superficial widget state.
948    #[inline]
949    pub fn data<R>(&self, reader: impl FnOnce(&IdTypeMap) -> R) -> R {
950        self.read(move |ctx| reader(&ctx.memory.data))
951    }
952
953    /// Read-write access to [`IdTypeMap`], which stores superficial widget state.
954    #[inline]
955    pub fn data_mut<R>(&self, writer: impl FnOnce(&mut IdTypeMap) -> R) -> R {
956        self.write(move |ctx| writer(&mut ctx.memory.data))
957    }
958
959    /// Read-write access to [`GraphicLayers`], where painted [`crate::Shape`]s are written to.
960    #[inline]
961    pub fn graphics_mut<R>(&self, writer: impl FnOnce(&mut GraphicLayers) -> R) -> R {
962        self.write(move |ctx| writer(&mut ctx.viewport().graphics))
963    }
964
965    /// Read-only access to [`GraphicLayers`], where painted [`crate::Shape`]s are written to.
966    #[inline]
967    pub fn graphics<R>(&self, reader: impl FnOnce(&GraphicLayers) -> R) -> R {
968        self.write(move |ctx| reader(&ctx.viewport().graphics))
969    }
970
971    /// Read-only access to [`PlatformOutput`].
972    ///
973    /// This is what egui outputs each pass and frame.
974    ///
975    /// ```
976    /// # let mut ctx = egui::Context::default();
977    /// ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Progress);
978    /// ```
979    #[inline]
980    pub fn output<R>(&self, reader: impl FnOnce(&PlatformOutput) -> R) -> R {
981        self.write(move |ctx| reader(&ctx.viewport().output))
982    }
983
984    /// Read-write access to [`PlatformOutput`].
985    #[inline]
986    pub fn output_mut<R>(&self, writer: impl FnOnce(&mut PlatformOutput) -> R) -> R {
987        self.write(move |ctx| writer(&mut ctx.viewport().output))
988    }
989
990    /// Read-only access to [`PassState`].
991    ///
992    /// This is only valid during the call to [`Self::run`] (between [`Self::begin_pass`] and [`Self::end_pass`]).
993    #[inline]
994    pub(crate) fn pass_state<R>(&self, reader: impl FnOnce(&PassState) -> R) -> R {
995        self.write(move |ctx| reader(&ctx.viewport().this_pass))
996    }
997
998    /// Read-write access to [`PassState`].
999    ///
1000    /// This is only valid during the call to [`Self::run`] (between [`Self::begin_pass`] and [`Self::end_pass`]).
1001    #[inline]
1002    pub(crate) fn pass_state_mut<R>(&self, writer: impl FnOnce(&mut PassState) -> R) -> R {
1003        self.write(move |ctx| writer(&mut ctx.viewport().this_pass))
1004    }
1005
1006    /// Read-only access to the [`PassState`] from the previous pass.
1007    ///
1008    /// This is swapped at the end of each pass.
1009    #[inline]
1010    pub(crate) fn prev_pass_state<R>(&self, reader: impl FnOnce(&PassState) -> R) -> R {
1011        self.write(move |ctx| reader(&ctx.viewport().prev_pass))
1012    }
1013
1014    /// Read-only access to [`Fonts`].
1015    ///
1016    /// Not valid until first call to [`Context::run()`].
1017    /// That's because since we don't know the proper `pixels_per_point` until then.
1018    #[inline]
1019    pub fn fonts<R>(&self, reader: impl FnOnce(&FontsView<'_>) -> R) -> R {
1020        self.write(move |ctx| {
1021            let pixels_per_point = ctx.pixels_per_point();
1022            reader(
1023                &ctx.fonts
1024                    .as_mut()
1025                    .expect("No fonts available until first call to Context::run()")
1026                    .with_pixels_per_point(pixels_per_point),
1027            )
1028        })
1029    }
1030
1031    /// Read-write access to [`Fonts`].
1032    ///
1033    /// Not valid until first call to [`Context::run()`].
1034    /// That's because since we don't know the proper `pixels_per_point` until then.
1035    #[inline]
1036    pub fn fonts_mut<R>(&self, reader: impl FnOnce(&mut FontsView<'_>) -> R) -> R {
1037        self.write(move |ctx| {
1038            let pixels_per_point = ctx.pixels_per_point();
1039            reader(
1040                &mut ctx
1041                    .fonts
1042                    .as_mut()
1043                    .expect("No fonts available until first call to Context::run()")
1044                    .with_pixels_per_point(pixels_per_point),
1045            )
1046        })
1047    }
1048
1049    /// Read-only access to [`Options`].
1050    #[inline]
1051    pub fn options<R>(&self, reader: impl FnOnce(&Options) -> R) -> R {
1052        self.read(move |ctx| reader(&ctx.memory.options))
1053    }
1054
1055    /// Read-write access to [`Options`].
1056    #[inline]
1057    pub fn options_mut<R>(&self, writer: impl FnOnce(&mut Options) -> R) -> R {
1058        self.write(move |ctx| writer(&mut ctx.memory.options))
1059    }
1060
1061    /// Read-only access to [`TessellationOptions`].
1062    #[inline]
1063    pub fn tessellation_options<R>(&self, reader: impl FnOnce(&TessellationOptions) -> R) -> R {
1064        self.read(move |ctx| reader(&ctx.memory.options.tessellation_options))
1065    }
1066
1067    /// Read-write access to [`TessellationOptions`].
1068    #[inline]
1069    pub fn tessellation_options_mut<R>(
1070        &self,
1071        writer: impl FnOnce(&mut TessellationOptions) -> R,
1072    ) -> R {
1073        self.write(move |ctx| writer(&mut ctx.memory.options.tessellation_options))
1074    }
1075
1076    /// If the given [`Id`] has been used previously the same pass at different position,
1077    /// then an error will be printed on screen.
1078    ///
1079    /// This function is already called for all widgets that do any interaction,
1080    /// but you can call this from widgets that store state but that does not interact.
1081    ///
1082    /// The given [`Rect`] should be approximately where the widget will be.
1083    /// The most important thing is that [`Rect::min`] is approximately correct,
1084    /// because that's where the warning will be painted. If you don't know what size to pick, just pick [`Vec2::ZERO`].
1085    pub fn check_for_id_clash(&self, id: Id, new_rect: Rect, what: &str) {
1086        let prev_rect = self.pass_state_mut(move |state| state.used_ids.insert(id, new_rect));
1087
1088        if !self.options(|opt| opt.warn_on_id_clash) {
1089            return;
1090        }
1091
1092        let Some(prev_rect) = prev_rect else { return };
1093
1094        // It is ok to reuse the same ID for e.g. a frame around a widget,
1095        // or to check for interaction with the same widget twice:
1096        let is_same_rect = prev_rect.expand(0.1).contains_rect(new_rect)
1097            || new_rect.expand(0.1).contains_rect(prev_rect);
1098        if is_same_rect {
1099            return;
1100        }
1101
1102        let show_error = |widget_rect: Rect, text: String| {
1103            let content_rect = self.content_rect();
1104
1105            let text = format!("🔥 {text}");
1106            let color = self.style().visuals.error_fg_color;
1107            let painter = self.debug_painter();
1108            painter.rect_stroke(widget_rect, 0.0, (1.0, color), StrokeKind::Outside);
1109
1110            let below = widget_rect.bottom() + 32.0 < content_rect.bottom();
1111
1112            let text_rect = if below {
1113                painter.debug_text(
1114                    widget_rect.left_bottom() + vec2(0.0, 2.0),
1115                    Align2::LEFT_TOP,
1116                    color,
1117                    text,
1118                )
1119            } else {
1120                painter.debug_text(
1121                    widget_rect.left_top() - vec2(0.0, 2.0),
1122                    Align2::LEFT_BOTTOM,
1123                    color,
1124                    text,
1125                )
1126            };
1127
1128            if let Some(pointer_pos) = self.pointer_hover_pos()
1129                && text_rect.contains(pointer_pos)
1130            {
1131                let tooltip_pos = if below {
1132                    text_rect.left_bottom() + vec2(2.0, 4.0)
1133                } else {
1134                    text_rect.left_top() + vec2(2.0, -4.0)
1135                };
1136
1137                painter.error(
1138                        tooltip_pos,
1139                        format!("Widget is {} this text.\n\n\
1140                             ID clashes happens when things like Windows or CollapsingHeaders share names,\n\
1141                             or when things like Plot and Grid:s aren't given unique id_salt:s.\n\n\
1142                             Sometimes the solution is to use ui.push_id.",
1143                                if below { "above" } else { "below" }),
1144                    );
1145            }
1146        };
1147
1148        let id_str = id.short_debug_format();
1149
1150        if prev_rect.min.distance(new_rect.min) < 4.0 {
1151            show_error(new_rect, format!("Double use of {what} ID {id_str}"));
1152        } else {
1153            show_error(prev_rect, format!("First use of {what} ID {id_str}"));
1154            show_error(new_rect, format!("Second use of {what} ID {id_str}"));
1155        }
1156    }
1157
1158    // ---------------------------------------------------------------------
1159
1160    /// Create a widget and check for interaction.
1161    ///
1162    /// If this is not called, the widget doesn't exist.
1163    ///
1164    /// You should use [`Ui::interact`] instead.
1165    ///
1166    /// If the widget already exists, its state (sense, Rect, etc) will be updated.
1167    ///
1168    /// `allow_focus` should usually be true, unless you call this function multiple times with the
1169    /// same widget, then `allow_focus` should only be true once (like in [`Ui::new`] (true) and [`Ui::remember_min_rect`] (false)).
1170    pub(crate) fn create_widget(&self, w: WidgetRect, allow_focus: bool) -> Response {
1171        let interested_in_focus = w.enabled
1172            && w.sense.is_focusable()
1173            && self.memory(|mem| mem.allows_interaction(w.layer_id));
1174
1175        // Remember this widget
1176        self.write(|ctx| {
1177            let viewport = ctx.viewport();
1178
1179            // We add all widgets here, even non-interactive ones,
1180            // because we need this list not only for checking for blocking widgets,
1181            // but also to know when we have reached the widget we are checking for cover.
1182            viewport.this_pass.widgets.insert(w.layer_id, w);
1183
1184            if allow_focus && interested_in_focus {
1185                ctx.memory.interested_in_focus(w.id, w.layer_id);
1186            }
1187        });
1188
1189        if allow_focus && !interested_in_focus {
1190            // Not interested or allowed input:
1191            self.memory_mut(|mem| mem.surrender_focus(w.id));
1192        }
1193
1194        if w.sense.interactive() || w.sense.is_focusable() {
1195            self.check_for_id_clash(w.id, w.rect, "widget");
1196        }
1197
1198        #[allow(clippy::let_and_return, clippy::allow_attributes)]
1199        let res = self.get_response(w);
1200
1201        #[cfg(debug_assertions)]
1202        if res.contains_pointer() {
1203            let plugins = self.read(|ctx| ctx.plugins.ordered_plugins());
1204            plugins.on_widget_under_pointer(self, &w);
1205        }
1206
1207        #[cfg(feature = "accesskit")]
1208        if allow_focus && w.sense.is_focusable() {
1209            // Make sure anything that can receive focus has an AccessKit node.
1210            // TODO(mwcampbell): For nodes that are filled from widget info,
1211            // some information is written to the node twice.
1212            self.accesskit_node_builder(w.id, |builder| res.fill_accesskit_node_common(builder));
1213        }
1214
1215        #[cfg(feature = "accesskit")]
1216        self.write(|ctx| {
1217            use crate::{Align, pass_state::ScrollTarget, style::ScrollAnimation};
1218            let viewport = ctx.viewport_for(ctx.viewport_id());
1219
1220            viewport
1221                .input
1222                .consume_accesskit_action_requests(res.id, |request| {
1223                    // TODO(lucasmerlin): Correctly handle the scroll unit:
1224                    // https://github.com/AccessKit/accesskit/blob/e639c0e0d8ccbfd9dff302d972fa06f9766d608e/common/src/lib.rs#L2621
1225                    const DISTANCE: f32 = 100.0;
1226
1227                    match &request.action {
1228                        accesskit::Action::ScrollIntoView => {
1229                            viewport.this_pass.scroll_target = [
1230                                Some(ScrollTarget::new(
1231                                    res.rect.x_range(),
1232                                    Some(Align::Center),
1233                                    ScrollAnimation::none(),
1234                                )),
1235                                Some(ScrollTarget::new(
1236                                    res.rect.y_range(),
1237                                    Some(Align::Center),
1238                                    ScrollAnimation::none(),
1239                                )),
1240                            ];
1241                        }
1242                        accesskit::Action::ScrollDown => {
1243                            viewport.this_pass.scroll_delta.0 += DISTANCE * Vec2::UP;
1244                        }
1245                        accesskit::Action::ScrollUp => {
1246                            viewport.this_pass.scroll_delta.0 += DISTANCE * Vec2::DOWN;
1247                        }
1248                        accesskit::Action::ScrollLeft => {
1249                            viewport.this_pass.scroll_delta.0 += DISTANCE * Vec2::LEFT;
1250                        }
1251                        accesskit::Action::ScrollRight => {
1252                            viewport.this_pass.scroll_delta.0 += DISTANCE * Vec2::RIGHT;
1253                        }
1254                        _ => return false,
1255                    }
1256                    true
1257                });
1258        });
1259
1260        res
1261    }
1262
1263    /// Read the response of some widget, which may be called _before_ creating the widget (!).
1264    ///
1265    /// This is because widget interaction happens at the start of the pass, using the widget rects from the previous pass.
1266    ///
1267    /// If the widget was not visible the previous pass (or this pass), this will return `None`.
1268    ///
1269    /// If you try to read a [`Ui`]'s response, while still inside, this will return the [`Rect`] from the previous frame.
1270    pub fn read_response(&self, id: Id) -> Option<Response> {
1271        self.write(|ctx| {
1272            let viewport = ctx.viewport();
1273            let widget_rect = viewport
1274                .this_pass
1275                .widgets
1276                .get(id)
1277                .or_else(|| viewport.prev_pass.widgets.get(id))
1278                .copied();
1279            widget_rect.map(|mut rect| {
1280                // If the Rect is invalid the Ui hasn't registered its final Rect yet.
1281                // We return the Rect from last frame instead.
1282                if !(rect.rect.is_positive() && rect.rect.is_finite())
1283                    && let Some(prev_rect) = viewport.prev_pass.widgets.get(id)
1284                {
1285                    rect.rect = prev_rect.rect;
1286                }
1287                rect
1288            })
1289        })
1290        .map(|widget_rect| self.get_response(widget_rect))
1291    }
1292
1293    /// Do all interaction for an existing widget, without (re-)registering it.
1294    pub(crate) fn get_response(&self, widget_rect: WidgetRect) -> Response {
1295        use response::Flags;
1296
1297        let WidgetRect {
1298            id,
1299            layer_id,
1300            rect,
1301            interact_rect,
1302            sense,
1303            enabled,
1304        } = widget_rect;
1305
1306        // previous pass + "highlight next pass" == "highlight this pass"
1307        let highlighted = self.prev_pass_state(|fs| fs.highlight_next_pass.contains(&id));
1308
1309        let mut res = Response {
1310            ctx: self.clone(),
1311            layer_id,
1312            id,
1313            rect,
1314            interact_rect,
1315            sense,
1316            flags: Flags::empty(),
1317            interact_pointer_pos: None,
1318            intrinsic_size: None,
1319        };
1320
1321        res.flags.set(Flags::ENABLED, enabled);
1322        res.flags.set(Flags::HIGHLIGHTED, highlighted);
1323
1324        self.write(|ctx| {
1325            let viewport = ctx.viewports.entry(ctx.viewport_id()).or_default();
1326
1327            res.flags.set(
1328                Flags::CONTAINS_POINTER,
1329                viewport.interact_widgets.contains_pointer.contains(&id),
1330            );
1331
1332            let input = &viewport.input;
1333            let memory = &mut ctx.memory;
1334
1335            if enabled
1336                && sense.senses_click()
1337                && memory.has_focus(id)
1338                && (input.key_pressed(Key::Space) || input.key_pressed(Key::Enter))
1339            {
1340                // Space/enter works like a primary click for e.g. selected buttons
1341                res.flags.set(Flags::FAKE_PRIMARY_CLICKED, true);
1342            }
1343
1344            #[cfg(feature = "accesskit")]
1345            if enabled
1346                && sense.senses_click()
1347                && input.has_accesskit_action_request(id, accesskit::Action::Click)
1348            {
1349                res.flags.set(Flags::FAKE_PRIMARY_CLICKED, true);
1350            }
1351
1352            if enabled && sense.senses_click() && Some(id) == viewport.interact_widgets.long_touched
1353            {
1354                res.flags.set(Flags::LONG_TOUCHED, true);
1355            }
1356
1357            let interaction = memory.interaction();
1358
1359            res.flags.set(
1360                Flags::IS_POINTER_BUTTON_DOWN_ON,
1361                interaction.potential_click_id == Some(id)
1362                    || interaction.potential_drag_id == Some(id),
1363            );
1364
1365            if res.enabled() {
1366                res.flags.set(
1367                    Flags::HOVERED,
1368                    viewport.interact_widgets.hovered.contains(&id),
1369                );
1370                res.flags.set(
1371                    Flags::DRAGGED,
1372                    Some(id) == viewport.interact_widgets.dragged,
1373                );
1374                res.flags.set(
1375                    Flags::DRAG_STARTED,
1376                    Some(id) == viewport.interact_widgets.drag_started,
1377                );
1378                res.flags.set(
1379                    Flags::DRAG_STOPPED,
1380                    Some(id) == viewport.interact_widgets.drag_stopped,
1381                );
1382            }
1383
1384            let clicked = Some(id) == viewport.interact_widgets.clicked;
1385            let mut any_press = false;
1386
1387            for pointer_event in &input.pointer.pointer_events {
1388                match pointer_event {
1389                    PointerEvent::Moved(_) => {}
1390                    PointerEvent::Pressed { .. } => {
1391                        any_press = true;
1392                    }
1393                    PointerEvent::Released { click, .. } => {
1394                        if enabled && sense.senses_click() && clicked && click.is_some() {
1395                            res.flags.set(Flags::CLICKED, true);
1396                        }
1397
1398                        res.flags.set(Flags::IS_POINTER_BUTTON_DOWN_ON, false);
1399                        res.flags.set(Flags::DRAGGED, false);
1400                    }
1401                }
1402            }
1403
1404            // is_pointer_button_down_on is false when released, but we want interact_pointer_pos
1405            // to still work.
1406            let is_interacted_with = res.is_pointer_button_down_on()
1407                || res.long_touched()
1408                || clicked
1409                || res.drag_stopped();
1410            if is_interacted_with {
1411                res.interact_pointer_pos = input.pointer.interact_pos();
1412                if let (Some(to_global), Some(pos)) = (
1413                    memory.to_global.get(&res.layer_id),
1414                    &mut res.interact_pointer_pos,
1415                ) {
1416                    *pos = to_global.inverse() * *pos;
1417                }
1418            }
1419
1420            if input.pointer.any_down() && !is_interacted_with {
1421                // We don't hover widgets while interacting with *other* widgets:
1422                res.flags.set(Flags::HOVERED, false);
1423            }
1424
1425            let should_surrender_focus = match memory.options.input_options.surrender_focus_on {
1426                SurrenderFocusOn::Presses => any_press,
1427                SurrenderFocusOn::Clicks => input.pointer.any_click(),
1428                SurrenderFocusOn::Never => false,
1429            };
1430
1431            let pointer_clicked_elsewhere = should_surrender_focus && !res.hovered();
1432            if pointer_clicked_elsewhere && memory.has_focus(id) {
1433                memory.surrender_focus(id);
1434            }
1435        });
1436
1437        res
1438    }
1439
1440    /// This is called by [`Response::widget_info`], but can also be called directly.
1441    ///
1442    /// With some debug flags it will store the widget info in [`crate::WidgetRects`] for later display.
1443    #[inline]
1444    pub fn register_widget_info(&self, id: Id, make_info: impl Fn() -> crate::WidgetInfo) {
1445        #[cfg(debug_assertions)]
1446        self.write(|ctx| {
1447            if ctx.memory.options.style().debug.show_interactive_widgets {
1448                ctx.viewport().this_pass.widgets.set_info(id, make_info());
1449            }
1450        });
1451
1452        #[cfg(not(debug_assertions))]
1453        {
1454            _ = (self, id, make_info);
1455        }
1456    }
1457
1458    /// Get a full-screen painter for a new or existing layer
1459    pub fn layer_painter(&self, layer_id: LayerId) -> Painter {
1460        let content_rect = self.content_rect();
1461        Painter::new(self.clone(), layer_id, content_rect)
1462    }
1463
1464    /// Paint on top of everything else
1465    pub fn debug_painter(&self) -> Painter {
1466        Self::layer_painter(self, LayerId::debug())
1467    }
1468
1469    /// Print this text next to the cursor at the end of the pass.
1470    ///
1471    /// If you call this multiple times, the text will be appended.
1472    ///
1473    /// This only works if compiled with `debug_assertions`.
1474    ///
1475    /// ```
1476    /// # let ctx = egui::Context::default();
1477    /// # let state = true;
1478    /// ctx.debug_text(format!("State: {state:?}"));
1479    /// ```
1480    ///
1481    /// This is just a convenience for calling [`crate::debug_text::print`].
1482    #[track_caller]
1483    pub fn debug_text(&self, text: impl Into<WidgetText>) {
1484        crate::debug_text::print(self, text);
1485    }
1486
1487    /// What operating system are we running on?
1488    ///
1489    /// When compiling natively, this is
1490    /// figured out from the `target_os`.
1491    ///
1492    /// For web, this can be figured out from the user-agent,
1493    /// and is done so by [`eframe`](https://github.com/emilk/egui/tree/main/crates/eframe).
1494    pub fn os(&self) -> OperatingSystem {
1495        self.read(|ctx| ctx.os)
1496    }
1497
1498    /// Set the operating system we are running on.
1499    ///
1500    /// If you are writing wasm-based integration for egui you
1501    /// may want to set this based on e.g. the user-agent.
1502    pub fn set_os(&self, os: OperatingSystem) {
1503        self.write(|ctx| ctx.os = os);
1504    }
1505
1506    /// Set the cursor icon.
1507    ///
1508    /// Equivalent to:
1509    /// ```
1510    /// # let ctx = egui::Context::default();
1511    /// ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::PointingHand);
1512    /// ```
1513    pub fn set_cursor_icon(&self, cursor_icon: CursorIcon) {
1514        self.output_mut(|o| o.cursor_icon = cursor_icon);
1515    }
1516
1517    /// Add a command to [`PlatformOutput::commands`],
1518    /// for the integration to execute at the end of the frame.
1519    pub fn send_cmd(&self, cmd: crate::OutputCommand) {
1520        self.output_mut(|o| o.commands.push(cmd));
1521    }
1522
1523    /// Open an URL in a browser.
1524    ///
1525    /// Equivalent to:
1526    /// ```
1527    /// # let ctx = egui::Context::default();
1528    /// # let open_url = egui::OpenUrl::same_tab("http://www.example.com");
1529    /// ctx.send_cmd(egui::OutputCommand::OpenUrl(open_url));
1530    /// ```
1531    pub fn open_url(&self, open_url: crate::OpenUrl) {
1532        self.send_cmd(crate::OutputCommand::OpenUrl(open_url));
1533    }
1534
1535    /// Copy the given text to the system clipboard.
1536    ///
1537    /// Note that in web applications, the clipboard is only accessible in secure contexts (e.g.,
1538    /// HTTPS or localhost). If this method is used outside of a secure context, it will log an
1539    /// error and do nothing. See <https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts>.
1540    pub fn copy_text(&self, text: String) {
1541        self.send_cmd(crate::OutputCommand::CopyText(text));
1542    }
1543
1544    /// Copy the given image to the system clipboard.
1545    ///
1546    /// Note that in web applications, the clipboard is only accessible in secure contexts (e.g.,
1547    /// HTTPS or localhost). If this method is used outside of a secure context, it will log an
1548    /// error and do nothing. See <https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts>.
1549    pub fn copy_image(&self, image: crate::ColorImage) {
1550        self.send_cmd(crate::OutputCommand::CopyImage(image));
1551    }
1552
1553    fn can_show_modifier_symbols(&self) -> bool {
1554        let ModifierNames {
1555            alt,
1556            ctrl,
1557            shift,
1558            mac_cmd,
1559            ..
1560        } = ModifierNames::SYMBOLS;
1561
1562        let font_id = TextStyle::Body.resolve(&self.style());
1563        self.fonts_mut(|f| {
1564            let mut font = f.fonts.font(&font_id.family);
1565            font.has_glyphs(alt)
1566                && font.has_glyphs(ctrl)
1567                && font.has_glyphs(shift)
1568                && font.has_glyphs(mac_cmd)
1569        })
1570    }
1571
1572    /// Format the given modifiers in a human-readable way (e.g. `Ctrl+Shift+X`).
1573    pub fn format_modifiers(&self, modifiers: Modifiers) -> String {
1574        let os = self.os();
1575
1576        let is_mac = os.is_mac();
1577
1578        if is_mac && self.can_show_modifier_symbols() {
1579            ModifierNames::SYMBOLS.format(&modifiers, is_mac)
1580        } else {
1581            ModifierNames::NAMES.format(&modifiers, is_mac)
1582        }
1583    }
1584
1585    /// Format the given shortcut in a human-readable way (e.g. `Ctrl+Shift+X`).
1586    ///
1587    /// Can be used to get the text for [`crate::Button::shortcut_text`].
1588    pub fn format_shortcut(&self, shortcut: &KeyboardShortcut) -> String {
1589        let os = self.os();
1590
1591        let is_mac = os.is_mac();
1592
1593        if is_mac && self.can_show_modifier_symbols() {
1594            shortcut.format(&ModifierNames::SYMBOLS, is_mac)
1595        } else {
1596            shortcut.format(&ModifierNames::NAMES, is_mac)
1597        }
1598    }
1599
1600    /// The total number of completed frames.
1601    ///
1602    /// Starts at zero, and is incremented once at the end of each call to [`Self::run`].
1603    ///
1604    /// This is always smaller or equal to [`Self::cumulative_pass_nr`].
1605    pub fn cumulative_frame_nr(&self) -> u64 {
1606        self.cumulative_frame_nr_for(self.viewport_id())
1607    }
1608
1609    /// The total number of completed frames.
1610    ///
1611    /// Starts at zero, and is incremented once at the end of each call to [`Self::run`].
1612    ///
1613    /// This is always smaller or equal to [`Self::cumulative_pass_nr_for`].
1614    pub fn cumulative_frame_nr_for(&self, id: ViewportId) -> u64 {
1615        self.read(|ctx| {
1616            ctx.viewports
1617                .get(&id)
1618                .map(|v| v.repaint.cumulative_frame_nr)
1619                .unwrap_or_else(|| {
1620                    if cfg!(debug_assertions) {
1621                        panic!("cumulative_frame_nr_for failed to find the viewport {id:?}");
1622                    } else {
1623                        0
1624                    }
1625                })
1626        })
1627    }
1628
1629    /// The total number of completed passes (usually there is one pass per rendered frame).
1630    ///
1631    /// Starts at zero, and is incremented for each completed pass inside of [`Self::run`] (usually once).
1632    ///
1633    /// If you instead want to know which pass index this is within the current frame,
1634    /// use [`Self::current_pass_index`].
1635    pub fn cumulative_pass_nr(&self) -> u64 {
1636        self.cumulative_pass_nr_for(self.viewport_id())
1637    }
1638
1639    /// The total number of completed passes (usually there is one pass per rendered frame).
1640    ///
1641    /// Starts at zero, and is incremented for each completed pass inside of [`Self::run`] (usually once).
1642    pub fn cumulative_pass_nr_for(&self, id: ViewportId) -> u64 {
1643        self.read(|ctx| {
1644            ctx.viewports
1645                .get(&id)
1646                .map_or(0, |v| v.repaint.cumulative_pass_nr)
1647        })
1648    }
1649
1650    /// The index of the current pass in the current frame, starting at zero.
1651    ///
1652    /// Usually this is zero, but if something called [`Self::request_discard`] to do multi-pass layout,
1653    /// then this will be incremented for each pass.
1654    ///
1655    /// This just reads the value of [`PlatformOutput::num_completed_passes`].
1656    ///
1657    /// To know the total number of passes ever completed, use [`Self::cumulative_pass_nr`].
1658    pub fn current_pass_index(&self) -> usize {
1659        self.output(|o| o.num_completed_passes)
1660    }
1661
1662    /// Call this if there is need to repaint the UI, i.e. if you are showing an animation.
1663    ///
1664    /// If this is called at least once in a frame, then there will be another frame right after this.
1665    /// Call as many times as you wish, only one repaint will be issued.
1666    ///
1667    /// To request repaint with a delay, use [`Self::request_repaint_after`].
1668    ///
1669    /// If called from outside the UI thread, the UI thread will wake up and run,
1670    /// provided the egui integration has set that up via [`Self::set_request_repaint_callback`]
1671    /// (this will work on `eframe`).
1672    ///
1673    /// This will repaint the current viewport.
1674    #[track_caller]
1675    pub fn request_repaint(&self) {
1676        self.request_repaint_of(self.viewport_id());
1677    }
1678
1679    /// Call this if there is need to repaint the UI, i.e. if you are showing an animation.
1680    ///
1681    /// If this is called at least once in a frame, then there will be another frame right after this.
1682    /// Call as many times as you wish, only one repaint will be issued.
1683    ///
1684    /// To request repaint with a delay, use [`Self::request_repaint_after_for`].
1685    ///
1686    /// If called from outside the UI thread, the UI thread will wake up and run,
1687    /// provided the egui integration has set that up via [`Self::set_request_repaint_callback`]
1688    /// (this will work on `eframe`).
1689    ///
1690    /// This will repaint the specified viewport.
1691    #[track_caller]
1692    pub fn request_repaint_of(&self, id: ViewportId) {
1693        let cause = RepaintCause::new();
1694        self.write(|ctx| ctx.request_repaint(id, cause));
1695    }
1696
1697    /// Request repaint after at most the specified duration elapses.
1698    ///
1699    /// The backend can chose to repaint sooner, for instance if some other code called
1700    /// this method with a lower duration, or if new events arrived.
1701    ///
1702    /// The function can be multiple times, but only the *smallest* duration will be considered.
1703    /// So, if the function is called two times with `1 second` and `2 seconds`, egui will repaint
1704    /// after `1 second`
1705    ///
1706    /// This is primarily useful for applications who would like to save battery by avoiding wasted
1707    /// redraws when the app is not in focus. But sometimes the GUI of the app might become stale
1708    /// and outdated if it is not updated for too long.
1709    ///
1710    /// Let's say, something like a stopwatch widget that displays the time in seconds. You would waste
1711    /// resources repainting multiple times within the same second (when you have no input),
1712    /// just calculate the difference of duration between current time and next second change,
1713    /// and call this function, to make sure that you are displaying the latest updated time, but
1714    /// not wasting resources on needless repaints within the same second.
1715    ///
1716    /// ### Quirk:
1717    /// Duration begins at the next frame. Let's say for example that it's a very inefficient app
1718    /// and takes 500 milliseconds per frame at 2 fps. The widget / user might want a repaint in
1719    /// next 500 milliseconds. Now, app takes 1000 ms per frame (1 fps) because the backend event
1720    /// timeout takes 500 milliseconds AFTER the vsync swap buffer.
1721    /// So, it's not that we are requesting repaint within X duration. We are rather timing out
1722    /// during app idle time where we are not receiving any new input events.
1723    ///
1724    /// This repaints the current viewport.
1725    #[track_caller]
1726    pub fn request_repaint_after(&self, duration: Duration) {
1727        self.request_repaint_after_for(duration, self.viewport_id());
1728    }
1729
1730    /// Repaint after this many seconds.
1731    ///
1732    /// See [`Self::request_repaint_after`] for details.
1733    #[track_caller]
1734    pub fn request_repaint_after_secs(&self, seconds: f32) {
1735        if let Ok(duration) = std::time::Duration::try_from_secs_f32(seconds) {
1736            self.request_repaint_after(duration);
1737        }
1738    }
1739
1740    /// Request repaint after at most the specified duration elapses.
1741    ///
1742    /// The backend can chose to repaint sooner, for instance if some other code called
1743    /// this method with a lower duration, or if new events arrived.
1744    ///
1745    /// The function can be multiple times, but only the *smallest* duration will be considered.
1746    /// So, if the function is called two times with `1 second` and `2 seconds`, egui will repaint
1747    /// after `1 second`
1748    ///
1749    /// This is primarily useful for applications who would like to save battery by avoiding wasted
1750    /// redraws when the app is not in focus. But sometimes the GUI of the app might become stale
1751    /// and outdated if it is not updated for too long.
1752    ///
1753    /// Let's say, something like a stopwatch widget that displays the time in seconds. You would waste
1754    /// resources repainting multiple times within the same second (when you have no input),
1755    /// just calculate the difference of duration between current time and next second change,
1756    /// and call this function, to make sure that you are displaying the latest updated time, but
1757    /// not wasting resources on needless repaints within the same second.
1758    ///
1759    /// ### Quirk:
1760    /// Duration begins at the next frame. Let's say for example that it's a very inefficient app
1761    /// and takes 500 milliseconds per frame at 2 fps. The widget / user might want a repaint in
1762    /// next 500 milliseconds. Now, app takes 1000 ms per frame (1 fps) because the backend event
1763    /// timeout takes 500 milliseconds AFTER the vsync swap buffer.
1764    /// So, it's not that we are requesting repaint within X duration. We are rather timing out
1765    /// during app idle time where we are not receiving any new input events.
1766    ///
1767    /// This repaints the specified viewport.
1768    #[track_caller]
1769    pub fn request_repaint_after_for(&self, duration: Duration, id: ViewportId) {
1770        let cause = RepaintCause::new();
1771        self.write(|ctx| ctx.request_repaint_after(duration, id, cause));
1772    }
1773
1774    /// Was a repaint requested last pass for the current viewport?
1775    #[must_use]
1776    pub fn requested_repaint_last_pass(&self) -> bool {
1777        self.requested_repaint_last_pass_for(&self.viewport_id())
1778    }
1779
1780    /// Was a repaint requested last pass for the given viewport?
1781    #[must_use]
1782    pub fn requested_repaint_last_pass_for(&self, viewport_id: &ViewportId) -> bool {
1783        self.read(|ctx| ctx.requested_immediate_repaint_prev_pass(viewport_id))
1784    }
1785
1786    /// Has a repaint been requested for the current viewport?
1787    #[must_use]
1788    pub fn has_requested_repaint(&self) -> bool {
1789        self.has_requested_repaint_for(&self.viewport_id())
1790    }
1791
1792    /// Has a repaint been requested for the given viewport?
1793    #[must_use]
1794    pub fn has_requested_repaint_for(&self, viewport_id: &ViewportId) -> bool {
1795        self.read(|ctx| ctx.has_requested_repaint(viewport_id))
1796    }
1797
1798    /// Why are we repainting?
1799    ///
1800    /// This can be helpful in debugging why egui is constantly repainting.
1801    pub fn repaint_causes(&self) -> Vec<RepaintCause> {
1802        self.read(|ctx| {
1803            ctx.viewports
1804                .get(&ctx.viewport_id())
1805                .map(|v| v.repaint.prev_causes.clone())
1806        })
1807        .unwrap_or_default()
1808    }
1809
1810    /// For integrations: this callback will be called when an egui user calls [`Self::request_repaint`] or [`Self::request_repaint_after`].
1811    ///
1812    /// This lets you wake up a sleeping UI thread.
1813    ///
1814    /// Note that only one callback can be set. Any new call overrides the previous callback.
1815    pub fn set_request_repaint_callback(
1816        &self,
1817        callback: impl Fn(RequestRepaintInfo) + Send + Sync + 'static,
1818    ) {
1819        let callback = Box::new(callback);
1820        self.write(|ctx| ctx.request_repaint_callback = Some(callback));
1821    }
1822
1823    /// Request to discard the visual output of this pass,
1824    /// and to immediately do another one.
1825    ///
1826    /// This can be called to cover up visual glitches during a "sizing pass".
1827    /// For instance, when a [`crate::Grid`] is first shown we don't yet know the
1828    /// width and heights of its columns and rows. egui will do a best guess,
1829    /// but it will likely be wrong. Next pass it can read the sizes from the previous
1830    /// pass, and from there on the widths will be stable.
1831    /// This means the first pass will look glitchy, and ideally should not be shown to the user.
1832    /// So [`crate::Grid`] calls [`Self::request_discard`] to cover up this glitches.
1833    ///
1834    /// There is a limit to how many passes egui will perform, set by [`Options::max_passes`] (default=2).
1835    /// Therefore, the request might be declined.
1836    ///
1837    /// You can check if the current pass will be discarded with [`Self::will_discard`].
1838    ///
1839    /// You should be very conservative with when you call [`Self::request_discard`],
1840    /// as it will cause an extra ui pass, potentially leading to extra CPU use and frame judder.
1841    ///
1842    /// The given reason should be a human-readable string that explains why `request_discard`
1843    /// was called. This will be shown in certain debug situations, to help you figure out
1844    /// why a pass was discarded.
1845    #[track_caller]
1846    pub fn request_discard(&self, reason: impl Into<Cow<'static, str>>) {
1847        let cause = RepaintCause::new_reason(reason);
1848        self.output_mut(|o| o.request_discard_reasons.push(cause));
1849
1850        log::trace!(
1851            "request_discard: {}",
1852            if self.will_discard() {
1853                "allowed"
1854            } else {
1855                "denied"
1856            }
1857        );
1858    }
1859
1860    /// Will the visual output of this pass be discarded?
1861    ///
1862    /// If true, you can early-out from expensive graphics operations.
1863    ///
1864    /// See [`Self::request_discard`] for more.
1865    pub fn will_discard(&self) -> bool {
1866        self.write(|ctx| {
1867            let vp = ctx.viewport();
1868            // NOTE: `num_passes` is incremented
1869            vp.output.requested_discard()
1870                && vp.output.num_completed_passes + 1 < ctx.memory.options.max_passes.get()
1871        })
1872    }
1873}
1874
1875/// Callbacks
1876impl Context {
1877    /// Call the given callback at the start of each pass of each viewport.
1878    ///
1879    /// This is a convenience wrapper around [`Self::add_plugin`].
1880    pub fn on_begin_pass(&self, debug_name: &'static str, cb: plugin::ContextCallback) {
1881        self.with_plugin(|p: &mut crate::plugin::CallbackPlugin| {
1882            p.on_begin_plugins.push((debug_name, cb));
1883        });
1884    }
1885
1886    /// Call the given callback at the end of each pass of each viewport.
1887    ///
1888    /// This is a convenience wrapper around [`Self::add_plugin`].
1889    pub fn on_end_pass(&self, debug_name: &'static str, cb: plugin::ContextCallback) {
1890        self.with_plugin(|p: &mut crate::plugin::CallbackPlugin| {
1891            p.on_end_plugins.push((debug_name, cb));
1892        });
1893    }
1894
1895    /// Register a [`Plugin`](plugin::Plugin)
1896    ///
1897    /// Plugins are called in the order they are added.
1898    ///
1899    /// A plugin of the same type can only be added once (further calls with the same type will be ignored).
1900    /// This way it's convenient to add plugins in `eframe::run_simple_native`.
1901    pub fn add_plugin(&self, plugin: impl plugin::Plugin + 'static) {
1902        let handle = plugin::PluginHandle::new(plugin);
1903
1904        let added = self.write(|ctx| ctx.plugins.add(handle.clone()));
1905
1906        if added {
1907            handle.lock().dyn_plugin_mut().setup(self);
1908        }
1909    }
1910
1911    /// Call the provided closure with the plugin of type `T`, if it was registered.
1912    ///
1913    /// Returns `None` if the plugin was not registered.
1914    pub fn with_plugin<T: plugin::Plugin + 'static, R>(
1915        &self,
1916        f: impl FnOnce(&mut T) -> R,
1917    ) -> Option<R> {
1918        let plugin = self.read(|ctx| ctx.plugins.get(std::any::TypeId::of::<T>()));
1919        plugin.map(|plugin| f(plugin.lock().typed_plugin_mut()))
1920    }
1921
1922    /// Get a handle to the plugin of type `T`.
1923    ///
1924    /// ## Panics
1925    /// If the plugin of type `T` was not registered, this will panic.
1926    pub fn plugin<T: plugin::Plugin>(&self) -> TypedPluginHandle<T> {
1927        if let Some(plugin) = self.plugin_opt() {
1928            plugin
1929        } else {
1930            panic!("Plugin of type {:?} not found", std::any::type_name::<T>());
1931        }
1932    }
1933
1934    /// Get a handle to the plugin of type `T`, if it was registered.
1935    pub fn plugin_opt<T: plugin::Plugin>(&self) -> Option<TypedPluginHandle<T>> {
1936        let plugin = self.read(|ctx| ctx.plugins.get(std::any::TypeId::of::<T>()));
1937        plugin.map(TypedPluginHandle::new)
1938    }
1939
1940    /// Get a handle to the plugin of type `T`, or insert its default.
1941    pub fn plugin_or_default<T: plugin::Plugin + Default>(&self) -> TypedPluginHandle<T> {
1942        if let Some(plugin) = self.plugin_opt() {
1943            plugin
1944        } else {
1945            let default_plugin = T::default();
1946            self.add_plugin(default_plugin);
1947            self.plugin()
1948        }
1949    }
1950}
1951
1952impl Context {
1953    /// Tell `egui` which fonts to use.
1954    ///
1955    /// The default `egui` fonts only support latin and cyrillic alphabets,
1956    /// but you can call this to install additional fonts that support e.g. korean characters.
1957    ///
1958    /// The new fonts will become active at the start of the next pass.
1959    /// This will overwrite the existing fonts.
1960    pub fn set_fonts(&self, font_definitions: FontDefinitions) {
1961        profiling::function_scope!();
1962
1963        let mut update_fonts = true;
1964
1965        self.read(|ctx| {
1966            if let Some(current_fonts) = ctx.fonts.as_ref() {
1967                // NOTE: this comparison is expensive since it checks TTF data for equality
1968                if current_fonts.definitions() == &font_definitions {
1969                    update_fonts = false; // no need to update
1970                }
1971            }
1972        });
1973
1974        if update_fonts {
1975            self.memory_mut(|mem| mem.new_font_definitions = Some(font_definitions));
1976        }
1977    }
1978
1979    /// Tell `egui` which fonts to use.
1980    ///
1981    /// The default `egui` fonts only support latin and cyrillic alphabets,
1982    /// but you can call this to install additional fonts that support e.g. korean characters.
1983    ///
1984    /// The new font will become active at the start of the next pass.
1985    /// This will keep the existing fonts.
1986    pub fn add_font(&self, new_font: FontInsert) {
1987        profiling::function_scope!();
1988
1989        let mut update_fonts = true;
1990
1991        self.read(|ctx| {
1992            if let Some(current_fonts) = ctx.fonts.as_ref()
1993                && current_fonts
1994                    .definitions()
1995                    .font_data
1996                    .contains_key(&new_font.name)
1997            {
1998                update_fonts = false; // no need to update
1999            }
2000        });
2001
2002        if update_fonts {
2003            self.memory_mut(|mem| mem.add_fonts.push(new_font));
2004        }
2005    }
2006
2007    /// Does the OS use dark or light mode?
2008    /// This is used when the theme preference is set to [`crate::ThemePreference::System`].
2009    pub fn system_theme(&self) -> Option<Theme> {
2010        self.memory(|mem| mem.options.system_theme)
2011    }
2012
2013    /// The [`Theme`] used to select the appropriate [`Style`] (dark or light)
2014    /// used by all subsequent windows, panels etc.
2015    pub fn theme(&self) -> Theme {
2016        self.options(|opt| opt.theme())
2017    }
2018
2019    /// The [`Theme`] used to select between dark and light [`Self::style`]
2020    /// as the active style used by all subsequent windows, panels etc.
2021    ///
2022    /// Example:
2023    /// ```
2024    /// # let mut ctx = egui::Context::default();
2025    /// ctx.set_theme(egui::Theme::Light); // Switch to light mode
2026    /// ```
2027    pub fn set_theme(&self, theme_preference: impl Into<crate::ThemePreference>) {
2028        self.options_mut(|opt| opt.theme_preference = theme_preference.into());
2029    }
2030
2031    /// The currently active [`Style`] used by all subsequent windows, panels etc.
2032    pub fn style(&self) -> Arc<Style> {
2033        self.options(|opt| opt.style().clone())
2034    }
2035
2036    /// Mutate the currently active [`Style`] used by all subsequent windows, panels etc.
2037    /// Use [`Self::all_styles_mut`] to mutate both dark and light mode styles.
2038    ///
2039    /// Example:
2040    /// ```
2041    /// # let mut ctx = egui::Context::default();
2042    /// ctx.style_mut(|style| {
2043    ///     style.spacing.item_spacing = egui::vec2(10.0, 20.0);
2044    /// });
2045    /// ```
2046    pub fn style_mut(&self, mutate_style: impl FnOnce(&mut Style)) {
2047        self.options_mut(|opt| mutate_style(Arc::make_mut(opt.style_mut())));
2048    }
2049
2050    /// The currently active [`Style`] used by all new windows, panels etc.
2051    ///
2052    /// Use [`Self::all_styles_mut`] to mutate both dark and light mode styles.
2053    ///
2054    /// You can also change this using [`Self::style_mut`].
2055    ///
2056    /// You can use [`Ui::style_mut`] to change the style of a single [`Ui`].
2057    pub fn set_style(&self, style: impl Into<Arc<Style>>) {
2058        self.options_mut(|opt| *opt.style_mut() = style.into());
2059    }
2060
2061    /// Mutate the [`Style`]s used by all subsequent windows, panels etc. in both dark and light mode.
2062    ///
2063    /// Example:
2064    /// ```
2065    /// # let mut ctx = egui::Context::default();
2066    /// ctx.all_styles_mut(|style| {
2067    ///     style.spacing.item_spacing = egui::vec2(10.0, 20.0);
2068    /// });
2069    /// ```
2070    pub fn all_styles_mut(&self, mut mutate_style: impl FnMut(&mut Style)) {
2071        self.options_mut(|opt| {
2072            mutate_style(Arc::make_mut(&mut opt.dark_style));
2073            mutate_style(Arc::make_mut(&mut opt.light_style));
2074        });
2075    }
2076
2077    /// The [`Style`] used by all subsequent windows, panels etc.
2078    pub fn style_of(&self, theme: Theme) -> Arc<Style> {
2079        self.options(|opt| match theme {
2080            Theme::Dark => opt.dark_style.clone(),
2081            Theme::Light => opt.light_style.clone(),
2082        })
2083    }
2084
2085    /// Mutate the [`Style`] used by all subsequent windows, panels etc.
2086    ///
2087    /// Example:
2088    /// ```
2089    /// # let mut ctx = egui::Context::default();
2090    /// ctx.style_mut_of(egui::Theme::Dark, |style| {
2091    ///     style.spacing.item_spacing = egui::vec2(10.0, 20.0);
2092    /// });
2093    /// ```
2094    pub fn style_mut_of(&self, theme: Theme, mutate_style: impl FnOnce(&mut Style)) {
2095        self.options_mut(|opt| match theme {
2096            Theme::Dark => mutate_style(Arc::make_mut(&mut opt.dark_style)),
2097            Theme::Light => mutate_style(Arc::make_mut(&mut opt.light_style)),
2098        });
2099    }
2100
2101    /// The [`Style`] used by all new windows, panels etc.
2102    /// Use [`Self::set_theme`] to choose between dark and light mode.
2103    ///
2104    /// You can also change this using [`Self::style_mut_of`].
2105    ///
2106    /// You can use [`Ui::style_mut`] to change the style of a single [`Ui`].
2107    pub fn set_style_of(&self, theme: Theme, style: impl Into<Arc<Style>>) {
2108        let style = style.into();
2109        self.options_mut(|opt| match theme {
2110            Theme::Dark => opt.dark_style = style,
2111            Theme::Light => opt.light_style = style,
2112        });
2113    }
2114
2115    /// The [`crate::Visuals`] used by all subsequent windows, panels etc.
2116    ///
2117    /// You can also use [`Ui::visuals_mut`] to change the visuals of a single [`Ui`].
2118    ///
2119    /// Example:
2120    /// ```
2121    /// # let mut ctx = egui::Context::default();
2122    /// ctx.set_visuals_of(egui::Theme::Dark, egui::Visuals { panel_fill: egui::Color32::RED, ..Default::default() });
2123    /// ```
2124    pub fn set_visuals_of(&self, theme: Theme, visuals: crate::Visuals) {
2125        self.style_mut_of(theme, |style| style.visuals = visuals);
2126    }
2127
2128    /// The [`crate::Visuals`] used by all subsequent windows, panels etc.
2129    ///
2130    /// You can also use [`Ui::visuals_mut`] to change the visuals of a single [`Ui`].
2131    ///
2132    /// Example:
2133    /// ```
2134    /// # let mut ctx = egui::Context::default();
2135    /// ctx.set_visuals(egui::Visuals { panel_fill: egui::Color32::RED, ..Default::default() });
2136    /// ```
2137    pub fn set_visuals(&self, visuals: crate::Visuals) {
2138        self.style_mut_of(self.theme(), |style| style.visuals = visuals);
2139    }
2140
2141    /// The number of physical pixels for each logical point.
2142    ///
2143    /// This is calculated as [`Self::zoom_factor`] * [`Self::native_pixels_per_point`]
2144    #[inline(always)]
2145    pub fn pixels_per_point(&self) -> f32 {
2146        self.input(|i| i.pixels_per_point)
2147    }
2148
2149    /// Set the number of physical pixels for each logical point.
2150    /// Will become active at the start of the next pass.
2151    ///
2152    /// This will actually translate to a call to [`Self::set_zoom_factor`].
2153    pub fn set_pixels_per_point(&self, pixels_per_point: f32) {
2154        if pixels_per_point != self.pixels_per_point() {
2155            self.set_zoom_factor(pixels_per_point / self.native_pixels_per_point().unwrap_or(1.0));
2156        }
2157    }
2158
2159    /// The number of physical pixels for each logical point on this monitor.
2160    ///
2161    /// This is given as input to egui via [`crate::ViewportInfo::native_pixels_per_point`]
2162    /// and cannot be changed.
2163    #[inline(always)]
2164    pub fn native_pixels_per_point(&self) -> Option<f32> {
2165        self.input(|i| i.viewport().native_pixels_per_point)
2166    }
2167
2168    /// Global zoom factor of the UI.
2169    ///
2170    /// This is used to calculate the `pixels_per_point`
2171    /// for the UI as `pixels_per_point = zoom_factor * native_pixels_per_point`.
2172    ///
2173    /// The default is 1.0.
2174    /// Make larger to make everything larger.
2175    #[inline(always)]
2176    pub fn zoom_factor(&self) -> f32 {
2177        self.options(|o| o.zoom_factor)
2178    }
2179
2180    /// Sets zoom factor of the UI.
2181    /// Will become active at the start of the next pass.
2182    ///
2183    /// Note that calling this will not update [`Self::zoom_factor`] until the end of the pass.
2184    ///
2185    /// This is used to calculate the `pixels_per_point`
2186    /// for the UI as `pixels_per_point = zoom_fator * native_pixels_per_point`.
2187    ///
2188    /// The default is 1.0.
2189    /// Make larger to make everything larger.
2190    ///
2191    /// It is better to call this than modifying
2192    /// [`Options::zoom_factor`].
2193    #[inline(always)]
2194    pub fn set_zoom_factor(&self, zoom_factor: f32) {
2195        let cause = RepaintCause::new();
2196        self.write(|ctx| {
2197            if ctx.memory.options.zoom_factor != zoom_factor {
2198                ctx.new_zoom_factor = Some(zoom_factor);
2199                #[expect(clippy::iter_over_hash_type)]
2200                for viewport_id in ctx.all_viewport_ids() {
2201                    ctx.request_repaint(viewport_id, cause.clone());
2202                }
2203            }
2204        });
2205    }
2206
2207    /// Allocate a texture.
2208    ///
2209    /// This is for advanced users.
2210    /// Most users should use [`crate::Ui::image`] or [`Self::try_load_texture`]
2211    /// instead.
2212    ///
2213    /// In order to display an image you must convert it to a texture using this function.
2214    /// The function will hand over the image data to the egui backend, which will
2215    /// upload it to the GPU.
2216    ///
2217    /// ⚠️ Make sure to only call this ONCE for each image, i.e. NOT in your main GUI code.
2218    /// The call is NOT immediate safe.
2219    ///
2220    /// The given name can be useful for later debugging, and will be visible if you call [`Self::texture_ui`].
2221    ///
2222    /// For how to load an image, see [`crate::ImageData`] and [`crate::ColorImage::from_rgba_unmultiplied`].
2223    ///
2224    /// ```
2225    /// struct MyImage {
2226    ///     texture: Option<egui::TextureHandle>,
2227    /// }
2228    ///
2229    /// impl MyImage {
2230    ///     fn ui(&mut self, ui: &mut egui::Ui) {
2231    ///         let texture: &egui::TextureHandle = self.texture.get_or_insert_with(|| {
2232    ///             // Load the texture only once.
2233    ///             ui.ctx().load_texture(
2234    ///                 "my-image",
2235    ///                 egui::ColorImage::example(),
2236    ///                 Default::default()
2237    ///             )
2238    ///         });
2239    ///
2240    ///         // Show the image:
2241    ///         ui.image((texture.id(), texture.size_vec2()));
2242    ///     }
2243    /// }
2244    /// ```
2245    ///
2246    /// See also [`crate::ImageData`], [`crate::Ui::image`] and [`crate::Image`].
2247    pub fn load_texture(
2248        &self,
2249        name: impl Into<String>,
2250        image: impl Into<ImageData>,
2251        options: TextureOptions,
2252    ) -> TextureHandle {
2253        let name = name.into();
2254        let image = image.into();
2255        let max_texture_side = self.input(|i| i.max_texture_side);
2256        debug_assert!(
2257            image.width() <= max_texture_side && image.height() <= max_texture_side,
2258            "Texture {:?} has size {}x{}, but the maximum texture side is {}",
2259            name,
2260            image.width(),
2261            image.height(),
2262            max_texture_side
2263        );
2264        let tex_mngr = self.tex_manager();
2265        let tex_id = tex_mngr.write().alloc(name, image, options);
2266        TextureHandle::new(tex_mngr, tex_id)
2267    }
2268
2269    /// Low-level texture manager.
2270    ///
2271    /// In general it is easier to use [`Self::load_texture`] and [`TextureHandle`].
2272    ///
2273    /// You can show stats about the allocated textures using [`Self::texture_ui`].
2274    pub fn tex_manager(&self) -> Arc<RwLock<epaint::textures::TextureManager>> {
2275        self.read(|ctx| ctx.tex_manager.0.clone())
2276    }
2277
2278    // ---------------------------------------------------------------------
2279
2280    /// Constrain the position of a window/area so it fits within the provided boundary.
2281    pub(crate) fn constrain_window_rect_to_area(window: Rect, area: Rect) -> Rect {
2282        let mut pos = window.min;
2283
2284        // Constrain to screen, unless window is too large to fit:
2285        let margin_x = (window.width() - area.width()).at_least(0.0);
2286        let margin_y = (window.height() - area.height()).at_least(0.0);
2287
2288        pos.x = pos.x.at_most(area.right() + margin_x - window.width()); // move left if needed
2289        pos.x = pos.x.at_least(area.left() - margin_x); // move right if needed
2290        pos.y = pos.y.at_most(area.bottom() + margin_y - window.height()); // move right if needed
2291        pos.y = pos.y.at_least(area.top() - margin_y); // move down if needed
2292
2293        Rect::from_min_size(pos, window.size()).round_ui()
2294    }
2295}
2296
2297impl Context {
2298    /// Call at the end of each frame if you called [`Context::begin_pass`].
2299    #[must_use]
2300    pub fn end_pass(&self) -> FullOutput {
2301        profiling::function_scope!();
2302
2303        if self.options(|o| o.zoom_with_keyboard) {
2304            crate::gui_zoom::zoom_with_keyboard(self);
2305        }
2306
2307        // Plugins run just before the pass ends.
2308        let plugins = self.read(|ctx| ctx.plugins.ordered_plugins());
2309        plugins.on_end_pass(self);
2310
2311        #[cfg(debug_assertions)]
2312        self.debug_painting();
2313
2314        let mut output = self.write(|ctx| ctx.end_pass());
2315        plugins.on_output(&mut output);
2316        output
2317    }
2318
2319    /// Call at the end of each frame if you called [`Context::begin_pass`].
2320    #[must_use]
2321    #[deprecated = "Renamed end_pass"]
2322    pub fn end_frame(&self) -> FullOutput {
2323        self.end_pass()
2324    }
2325
2326    /// Called at the end of the pass.
2327    #[cfg(debug_assertions)]
2328    fn debug_painting(&self) {
2329        #![expect(clippy::iter_over_hash_type)] // ok to be sloppy in debug painting
2330
2331        let paint_widget = |widget: &WidgetRect, text: &str, color: Color32| {
2332            let rect = widget.interact_rect;
2333            if rect.is_positive() {
2334                let painter = Painter::new(self.clone(), widget.layer_id, Rect::EVERYTHING);
2335                painter.debug_rect(rect, color, text);
2336            }
2337        };
2338
2339        let paint_widget_id = |id: Id, text: &str, color: Color32| {
2340            if let Some(widget) =
2341                self.write(|ctx| ctx.viewport().this_pass.widgets.get(id).copied())
2342            {
2343                paint_widget(&widget, text, color);
2344            }
2345        };
2346
2347        if self.style().debug.show_interactive_widgets {
2348            // Show all interactive widgets:
2349            let rects = self.write(|ctx| ctx.viewport().this_pass.widgets.clone());
2350            for (layer_id, rects) in rects.layers() {
2351                let painter = Painter::new(self.clone(), *layer_id, Rect::EVERYTHING);
2352                for rect in rects {
2353                    if rect.sense.interactive() {
2354                        let (color, text) = if rect.sense.senses_click() && rect.sense.senses_drag()
2355                        {
2356                            (Color32::from_rgb(0x88, 0, 0x88), "click+drag")
2357                        } else if rect.sense.senses_click() {
2358                            (Color32::from_rgb(0x88, 0, 0), "click")
2359                        } else if rect.sense.senses_drag() {
2360                            (Color32::from_rgb(0, 0, 0x88), "drag")
2361                        } else {
2362                            // unreachable since we only show interactive
2363                            (Color32::from_rgb(0, 0, 0x88), "hover")
2364                        };
2365                        painter.debug_rect(rect.interact_rect, color, text);
2366                    }
2367                }
2368            }
2369
2370            // Show the ones actually interacted with:
2371            {
2372                let interact_widgets = self.write(|ctx| ctx.viewport().interact_widgets.clone());
2373                let InteractionSnapshot {
2374                    clicked,
2375                    long_touched: _,
2376                    drag_started: _,
2377                    dragged,
2378                    drag_stopped: _,
2379                    contains_pointer,
2380                    hovered,
2381                } = interact_widgets;
2382
2383                if true {
2384                    for &id in &contains_pointer {
2385                        paint_widget_id(id, "contains_pointer", Color32::BLUE);
2386                    }
2387
2388                    let widget_rects = self.write(|w| w.viewport().this_pass.widgets.clone());
2389
2390                    let mut contains_pointer: Vec<Id> = contains_pointer.iter().copied().collect();
2391                    contains_pointer.sort_by_key(|&id| {
2392                        widget_rects
2393                            .order(id)
2394                            .map(|(layer_id, order_in_layer)| (layer_id.order, order_in_layer))
2395                    });
2396
2397                    let mut debug_text = "Widgets in order:\n".to_owned();
2398                    for id in contains_pointer {
2399                        let mut widget_text = format!("{id:?}");
2400                        if let Some(rect) = widget_rects.get(id) {
2401                            widget_text +=
2402                                &format!(" {:?} {:?} {:?}", rect.layer_id, rect.rect, rect.sense);
2403                        }
2404                        if let Some(info) = widget_rects.info(id) {
2405                            widget_text += &format!(" {info:?}");
2406                        }
2407                        debug_text += &format!("{widget_text}\n");
2408                    }
2409                    self.debug_text(debug_text);
2410                }
2411                if true {
2412                    for widget in hovered {
2413                        paint_widget_id(widget, "hovered", Color32::WHITE);
2414                    }
2415                }
2416                if let Some(widget) = clicked {
2417                    paint_widget_id(widget, "clicked", Color32::RED);
2418                }
2419                if let Some(widget) = dragged {
2420                    paint_widget_id(widget, "dragged", Color32::GREEN);
2421                }
2422            }
2423        }
2424
2425        if self.style().debug.show_widget_hits {
2426            let hits = self.write(|ctx| ctx.viewport().hits.clone());
2427            let WidgetHits {
2428                close,
2429                contains_pointer,
2430                click,
2431                drag,
2432            } = hits;
2433
2434            if false {
2435                for widget in &close {
2436                    paint_widget(widget, "close", Color32::from_gray(70));
2437                }
2438            }
2439            if true {
2440                for widget in &contains_pointer {
2441                    paint_widget(widget, "contains_pointer", Color32::BLUE);
2442                }
2443            }
2444            if let Some(widget) = &click {
2445                paint_widget(widget, "click", Color32::RED);
2446            }
2447            if let Some(widget) = &drag {
2448                paint_widget(widget, "drag", Color32::GREEN);
2449            }
2450        }
2451
2452        if let Some(debug_rect) = self.pass_state_mut(|fs| fs.debug_rect.take()) {
2453            debug_rect.paint(&self.debug_painter());
2454        }
2455
2456        let num_multipass_in_row = self.viewport(|vp| vp.num_multipass_in_row);
2457        if 3 <= num_multipass_in_row {
2458            // If you see this message, it means we've been paying the cost of multi-pass for multiple frames in a row.
2459            // This is likely a bug. `request_discard` should only be called in rare situations, when some layout changes.
2460
2461            let mut warning = format!(
2462                "egui PERF WARNING: request_discard has been called {num_multipass_in_row} frames in a row"
2463            );
2464            self.viewport(|vp| {
2465                for reason in &vp.output.request_discard_reasons {
2466                    warning += &format!("\n  {reason}");
2467                }
2468            });
2469
2470            self.debug_painter()
2471                .debug_text(Pos2::ZERO, Align2::LEFT_TOP, Color32::RED, warning);
2472        }
2473    }
2474}
2475
2476impl ContextImpl {
2477    fn end_pass(&mut self) -> FullOutput {
2478        let ended_viewport_id = self.viewport_id();
2479        let viewport = self.viewports.entry(ended_viewport_id).or_default();
2480        let pixels_per_point = viewport.input.pixels_per_point;
2481
2482        self.loaders.end_pass(viewport.repaint.cumulative_pass_nr);
2483
2484        viewport.repaint.cumulative_pass_nr += 1;
2485
2486        self.memory.end_pass(&viewport.this_pass.used_ids);
2487
2488        if let Some(fonts) = self.fonts.as_mut() {
2489            let tex_mngr = &mut self.tex_manager.0.write();
2490            if let Some(font_image_delta) = fonts.font_image_delta() {
2491                // A partial font atlas update, e.g. a new glyph has been entered.
2492                tex_mngr.set(TextureId::default(), font_image_delta);
2493            }
2494        }
2495
2496        // Inform the backend of all textures that have been updated (including font atlas).
2497        let textures_delta = self.tex_manager.0.write().take_delta();
2498
2499        let mut platform_output: PlatformOutput = std::mem::take(&mut viewport.output);
2500
2501        #[cfg(feature = "accesskit")]
2502        {
2503            profiling::scope!("accesskit");
2504            let state = viewport.this_pass.accesskit_state.take();
2505            if let Some(state) = state {
2506                let root_id = crate::accesskit_root_id().accesskit_id();
2507                let nodes = {
2508                    state
2509                        .nodes
2510                        .into_iter()
2511                        .map(|(id, node)| (id.accesskit_id(), node))
2512                        .collect()
2513                };
2514                let focus_id = self
2515                    .memory
2516                    .focused()
2517                    .map_or(root_id, |id| id.accesskit_id());
2518                platform_output.accesskit_update = Some(accesskit::TreeUpdate {
2519                    nodes,
2520                    tree: Some(accesskit::Tree::new(root_id)),
2521                    tree_id: accesskit::TreeId::ROOT,
2522                    focus: focus_id,
2523                });
2524            }
2525        }
2526
2527        let shapes = viewport
2528            .graphics
2529            .drain(self.memory.areas().order(), &self.memory.to_global);
2530
2531        let mut repaint_needed = false;
2532
2533        if self.memory.options.repaint_on_widget_change {
2534            profiling::scope!("compare-widget-rects");
2535            #[allow(clippy::allow_attributes, clippy::collapsible_if)] // false positive on wasm
2536            if viewport.prev_pass.widgets != viewport.this_pass.widgets {
2537                repaint_needed = true; // Some widget has moved
2538            }
2539        }
2540
2541        std::mem::swap(&mut viewport.prev_pass, &mut viewport.this_pass);
2542
2543        if repaint_needed {
2544            self.request_repaint(ended_viewport_id, RepaintCause::new());
2545        }
2546        //  -------------------
2547
2548        let all_viewport_ids = self.all_viewport_ids();
2549
2550        self.last_viewport = ended_viewport_id;
2551
2552        self.viewports.retain(|&id, viewport| {
2553            if id == ViewportId::ROOT {
2554                return true; // never remove the root
2555            }
2556
2557            let parent = *self.viewport_parents.entry(id).or_default();
2558
2559            if !all_viewport_ids.contains(&parent) {
2560                log::debug!(
2561                    "Removing viewport {:?} ({:?}): the parent is gone",
2562                    id,
2563                    viewport.builder.title
2564                );
2565
2566                return false;
2567            }
2568
2569            let is_our_child = parent == ended_viewport_id && id != ViewportId::ROOT;
2570            if is_our_child {
2571                if !viewport.used {
2572                    log::debug!(
2573                        "Removing viewport {:?} ({:?}): it was never used this pass",
2574                        id,
2575                        viewport.builder.title
2576                    );
2577
2578                    return false; // Only keep children that have been updated this pass
2579                }
2580
2581                viewport.used = false; // reset so we can check again next pass
2582            }
2583
2584            true
2585        });
2586
2587        // If we are an immediate viewport, this will resume the previous viewport.
2588        self.viewport_stack.pop();
2589
2590        // The last viewport is not necessarily the root viewport,
2591        // just the top _immediate_ viewport.
2592        let is_last = self.viewport_stack.is_empty();
2593
2594        let viewport_output = self
2595            .viewports
2596            .iter_mut()
2597            .map(|(&id, viewport)| {
2598                let parent = *self.viewport_parents.entry(id).or_default();
2599                let commands = if is_last {
2600                    // Let the primary immediate viewport handle the commands of its children too.
2601                    // This can make things easier for the backend, as otherwise we may get commands
2602                    // that affect a viewport while its egui logic is running.
2603                    std::mem::take(&mut viewport.commands)
2604                } else {
2605                    vec![]
2606                };
2607
2608                (
2609                    id,
2610                    ViewportOutput {
2611                        parent,
2612                        class: viewport.class,
2613                        builder: viewport.builder.clone(),
2614                        viewport_ui_cb: viewport.viewport_ui_cb.clone(),
2615                        commands,
2616                        repaint_delay: viewport.repaint.repaint_delay,
2617                    },
2618                )
2619            })
2620            .collect();
2621
2622        if is_last {
2623            // Remove dead viewports:
2624            self.viewports.retain(|id, _| all_viewport_ids.contains(id));
2625            debug_assert!(
2626                self.viewports.contains_key(&ViewportId::ROOT),
2627                "Bug in egui: we removed the root viewport"
2628            );
2629            self.viewport_parents
2630                .retain(|id, _| all_viewport_ids.contains(id));
2631        } else {
2632            let viewport_id = self.viewport_id();
2633            self.memory.set_viewport_id(viewport_id);
2634        }
2635
2636        platform_output.num_completed_passes += 1;
2637
2638        FullOutput {
2639            platform_output,
2640            textures_delta,
2641            shapes,
2642            pixels_per_point,
2643            viewport_output,
2644        }
2645    }
2646}
2647
2648impl Context {
2649    /// Tessellate the given shapes into triangle meshes.
2650    ///
2651    /// `pixels_per_point` is used for feathering (anti-aliasing).
2652    /// For this you can use [`FullOutput::pixels_per_point`], [`Self::pixels_per_point`],
2653    /// or whatever is appropriate for your viewport.
2654    pub fn tessellate(
2655        &self,
2656        shapes: Vec<ClippedShape>,
2657        pixels_per_point: f32,
2658    ) -> Vec<ClippedPrimitive> {
2659        profiling::function_scope!();
2660
2661        // A tempting optimization is to reuse the tessellation from last frame if the
2662        // shapes are the same, but just comparing the shapes takes about 50% of the time
2663        // it takes to tessellate them, so it is not a worth optimization.
2664
2665        self.write(|ctx| {
2666            let tessellation_options = ctx.memory.options.tessellation_options;
2667            let texture_atlas = if let Some(fonts) = ctx.fonts.as_ref() {
2668                fonts.texture_atlas()
2669            } else {
2670                log::warn!("No font size matching {pixels_per_point} pixels per point found.");
2671                ctx.fonts
2672                    .iter()
2673                    .next()
2674                    .expect("No fonts loaded")
2675                    .texture_atlas()
2676            };
2677
2678            let paint_stats = PaintStats::from_shapes(&shapes);
2679            let clipped_primitives = {
2680                profiling::scope!("tessellator::tessellate_shapes");
2681                tessellator::Tessellator::new(
2682                    pixels_per_point,
2683                    tessellation_options,
2684                    texture_atlas.size(),
2685                    texture_atlas.prepared_discs(),
2686                )
2687                .tessellate_shapes(shapes)
2688            };
2689            ctx.paint_stats = paint_stats.with_clipped_primitives(&clipped_primitives);
2690            clipped_primitives
2691        })
2692    }
2693
2694    // ---------------------------------------------------------------------
2695
2696    /// Returns the position and size of the egui area that is safe for content rendering.
2697    ///
2698    /// Returns [`Self::viewport_rect`] minus areas that might be partially covered by, for example,
2699    /// the OS status bar or display notches.
2700    ///
2701    /// If you want to render behind e.g. the dynamic island on iOS, use [`Self::viewport_rect`].
2702    pub fn content_rect(&self) -> Rect {
2703        self.input(|i| i.content_rect()).round_ui()
2704    }
2705
2706    /// Returns the position and size of the full area available to egui
2707    ///
2708    /// This includes reas that might be partially covered by, for example, the OS status bar or
2709    /// display notches. See [`Self::content_rect`] to get a rect that is safe for content.
2710    ///
2711    /// This rectangle includes e.g. the dynamic island on iOS.
2712    /// If you want to only render _below_ the that (not behind), then you should use
2713    /// [`Self::content_rect`] instead.
2714    ///
2715    /// See also [`RawInput::safe_area_insets`].
2716    pub fn viewport_rect(&self) -> Rect {
2717        self.input(|i| i.viewport_rect()).round_ui()
2718    }
2719
2720    /// Position and size of the egui area.
2721    #[deprecated(
2722        note = "screen_rect has been split into viewport_rect() and content_rect(). You likely should use content_rect()"
2723    )]
2724    pub fn screen_rect(&self) -> Rect {
2725        self.input(|i| i.content_rect()).round_ui()
2726    }
2727
2728    /// How much space is still available after panels have been added.
2729    pub fn available_rect(&self) -> Rect {
2730        self.pass_state(|s| s.available_rect()).round_ui()
2731    }
2732
2733    /// How much space is used by panels and windows.
2734    pub fn used_rect(&self) -> Rect {
2735        self.write(|ctx| {
2736            let mut used = ctx.viewport().this_pass.used_by_panels;
2737            for (_id, window) in ctx.memory.areas().visible_windows() {
2738                used |= window.rect();
2739            }
2740            used.round_ui()
2741        })
2742    }
2743
2744    /// How much space is used by panels and windows.
2745    ///
2746    /// You can shrink your egui area to this size and still fit all egui components.
2747    pub fn used_size(&self) -> Vec2 {
2748        (self.used_rect().max - Pos2::ZERO).round_ui()
2749    }
2750
2751    // ---------------------------------------------------------------------
2752
2753    /// Is the pointer (mouse/touch) over any egui area?
2754    pub fn is_pointer_over_area(&self) -> bool {
2755        let pointer_pos = self.input(|i| i.pointer.interact_pos());
2756        if let Some(pointer_pos) = pointer_pos {
2757            if let Some(layer) = self.layer_id_at(pointer_pos) {
2758                if layer.order == Order::Background {
2759                    !self.pass_state(|state| state.unused_rect.contains(pointer_pos))
2760                } else {
2761                    true
2762                }
2763            } else {
2764                false
2765            }
2766        } else {
2767            false
2768        }
2769    }
2770
2771    /// True if egui is currently interested in the pointer (mouse or touch).
2772    ///
2773    /// Could be the pointer is hovering over a [`crate::Window`] or the user is dragging a widget.
2774    /// If `false`, the pointer is outside of any egui area and so
2775    /// you may be interested in what it is doing (e.g. controlling your game).
2776    /// Returns `false` if a drag started outside of egui and then moved over an egui area.
2777    pub fn wants_pointer_input(&self) -> bool {
2778        self.is_using_pointer()
2779            || (self.is_pointer_over_area() && !self.input(|i| i.pointer.any_down()))
2780    }
2781
2782    /// Is egui currently using the pointer position (e.g. dragging a slider)?
2783    ///
2784    /// NOTE: this will return `false` if the pointer is just hovering over an egui area.
2785    pub fn is_using_pointer(&self) -> bool {
2786        self.memory(|m| m.interaction().is_using_pointer())
2787    }
2788
2789    /// If `true`, egui is currently listening on text input (e.g. typing text in a [`crate::TextEdit`]).
2790    pub fn wants_keyboard_input(&self) -> bool {
2791        self.memory(|m| m.focused().is_some())
2792    }
2793
2794    /// Highlight this widget, to make it look like it is hovered, even if it isn't.
2795    ///
2796    /// If you call this after the widget has been fully rendered,
2797    /// then it won't be highlighted until the next ui pass.
2798    ///
2799    /// See also [`Response::highlight`].
2800    pub fn highlight_widget(&self, id: Id) {
2801        self.pass_state_mut(|fs| fs.highlight_next_pass.insert(id));
2802    }
2803
2804    /// Is an egui context menu open?
2805    ///
2806    /// This only works with the old, deprecated [`crate::menu`] API.
2807    #[expect(deprecated)]
2808    #[deprecated = "Use `is_popup_open` instead"]
2809    pub fn is_context_menu_open(&self) -> bool {
2810        self.data(|d| {
2811            d.get_temp::<crate::menu::BarState>(crate::menu::CONTEXT_MENU_ID_STR.into())
2812                .is_some_and(|state| state.has_root())
2813        })
2814    }
2815
2816    /// Is a popup or (context) menu open?
2817    ///
2818    /// Will return false for [`crate::Tooltip`]s (which are technically popups as well).
2819    pub fn is_popup_open(&self) -> bool {
2820        self.pass_state_mut(|fs| {
2821            fs.layers
2822                .values()
2823                .any(|layer| !layer.open_popups.is_empty())
2824        })
2825    }
2826}
2827
2828// Ergonomic methods to forward some calls often used in 'if let' without holding the borrow
2829impl Context {
2830    /// Latest reported pointer position.
2831    ///
2832    /// When tapping a touch screen, this will be `None`.
2833    #[inline(always)]
2834    pub fn pointer_latest_pos(&self) -> Option<Pos2> {
2835        self.input(|i| i.pointer.latest_pos())
2836    }
2837
2838    /// If it is a good idea to show a tooltip, where is pointer?
2839    #[inline(always)]
2840    pub fn pointer_hover_pos(&self) -> Option<Pos2> {
2841        self.input(|i| i.pointer.hover_pos())
2842    }
2843
2844    /// If you detect a click or drag and wants to know where it happened, use this.
2845    ///
2846    /// Latest position of the mouse, but ignoring any [`crate::Event::PointerGone`]
2847    /// if there were interactions this pass.
2848    /// When tapping a touch screen, this will be the location of the touch.
2849    #[inline(always)]
2850    pub fn pointer_interact_pos(&self) -> Option<Pos2> {
2851        self.input(|i| i.pointer.interact_pos())
2852    }
2853
2854    /// Calls [`InputState::multi_touch`].
2855    pub fn multi_touch(&self) -> Option<MultiTouchInfo> {
2856        self.input(|i| i.multi_touch())
2857    }
2858}
2859
2860impl Context {
2861    /// Transform the graphics of the given layer.
2862    ///
2863    /// This will also affect input.
2864    /// The direction of the given transform is "into the global coordinate system".
2865    ///
2866    /// This is a sticky setting, remembered from one frame to the next.
2867    ///
2868    /// Can be used to implement pan and zoom (see relevant demo).
2869    ///
2870    /// For a temporary transform, use [`Self::transform_layer_shapes`] or
2871    /// [`Ui::with_visual_transform`].
2872    pub fn set_transform_layer(&self, layer_id: LayerId, transform: TSTransform) {
2873        self.memory_mut(|m| {
2874            if transform == TSTransform::IDENTITY {
2875                m.to_global.remove(&layer_id)
2876            } else {
2877                m.to_global.insert(layer_id, transform)
2878            }
2879        });
2880    }
2881
2882    /// Return how to transform the graphics of the given layer into the global coordinate system.
2883    ///
2884    /// Set this with [`Self::layer_transform_to_global`].
2885    pub fn layer_transform_to_global(&self, layer_id: LayerId) -> Option<TSTransform> {
2886        self.memory(|m| m.to_global.get(&layer_id).copied())
2887    }
2888
2889    /// Return how to transform the graphics of the global coordinate system into the local coordinate system of the given layer.
2890    ///
2891    /// This returns the inverse of [`Self::layer_transform_to_global`].
2892    pub fn layer_transform_from_global(&self, layer_id: LayerId) -> Option<TSTransform> {
2893        self.layer_transform_to_global(layer_id)
2894            .map(|t| t.inverse())
2895    }
2896
2897    /// Transform all the graphics at the given layer.
2898    ///
2899    /// Is used to implement drag-and-drop preview.
2900    ///
2901    /// This only applied to the existing graphics at the layer, not to new graphics added later.
2902    ///
2903    /// For a persistent transform, use [`Self::set_transform_layer`] instead.
2904    pub fn transform_layer_shapes(&self, layer_id: LayerId, transform: TSTransform) {
2905        if transform != TSTransform::IDENTITY {
2906            self.graphics_mut(|g| g.entry(layer_id).transform(transform));
2907        }
2908    }
2909
2910    /// Top-most layer at the given position.
2911    pub fn layer_id_at(&self, pos: Pos2) -> Option<LayerId> {
2912        self.memory(|mem| mem.layer_id_at(pos))
2913    }
2914
2915    /// Moves the given area to the top in its [`Order`].
2916    ///
2917    /// [`crate::Area`]:s and [`crate::Window`]:s also do this automatically when being clicked on or interacted with.
2918    pub fn move_to_top(&self, layer_id: LayerId) {
2919        self.memory_mut(|mem| mem.areas_mut().move_to_top(layer_id));
2920    }
2921
2922    /// Mark the `child` layer as a sublayer of `parent`.
2923    ///
2924    /// Sublayers are moved directly above the parent layer at the end of the frame. This is mainly
2925    /// intended for adding a new [`crate::Area`] inside a [`crate::Window`].
2926    ///
2927    /// This currently only supports one level of nesting. If `parent` is a sublayer of another
2928    /// layer, the behavior is unspecified.
2929    pub fn set_sublayer(&self, parent: LayerId, child: LayerId) {
2930        self.memory_mut(|mem| mem.areas_mut().set_sublayer(parent, child));
2931    }
2932
2933    /// Retrieve the [`LayerId`] of the top level windows.
2934    pub fn top_layer_id(&self) -> Option<LayerId> {
2935        self.memory(|mem| mem.areas().top_layer_id(Order::Middle))
2936    }
2937
2938    /// Does the given rectangle contain the mouse pointer?
2939    ///
2940    /// Will return false if some other area is covering the given layer.
2941    ///
2942    /// The given rectangle is assumed to have been clipped by its parent clip rect.
2943    ///
2944    /// See also [`Response::contains_pointer`].
2945    pub fn rect_contains_pointer(&self, layer_id: LayerId, rect: Rect) -> bool {
2946        let rect = if let Some(to_global) = self.layer_transform_to_global(layer_id) {
2947            to_global * rect
2948        } else {
2949            rect
2950        };
2951        if !rect.is_positive() {
2952            return false;
2953        }
2954
2955        let pointer_pos = self.input(|i| i.pointer.interact_pos());
2956        let Some(pointer_pos) = pointer_pos else {
2957            return false;
2958        };
2959
2960        if !rect.contains(pointer_pos) {
2961            return false;
2962        }
2963
2964        if self.layer_id_at(pointer_pos) != Some(layer_id) {
2965            return false;
2966        }
2967
2968        true
2969    }
2970
2971    // ---------------------------------------------------------------------
2972
2973    /// Whether or not to debug widget layout on hover.
2974    #[cfg(debug_assertions)]
2975    pub fn debug_on_hover(&self) -> bool {
2976        self.options(|opt| opt.style().debug.debug_on_hover)
2977    }
2978
2979    /// Turn on/off whether or not to debug widget layout on hover.
2980    #[cfg(debug_assertions)]
2981    pub fn set_debug_on_hover(&self, debug_on_hover: bool) {
2982        self.all_styles_mut(|style| style.debug.debug_on_hover = debug_on_hover);
2983    }
2984}
2985
2986/// ## Animation
2987impl Context {
2988    /// Returns a value in the range [0, 1], to indicate "how on" this thing is.
2989    ///
2990    /// The first time called it will return `if value { 1.0 } else { 0.0 }`
2991    /// Calling this with `value = true` will always yield a number larger than zero, quickly going towards one.
2992    /// Calling this with `value = false` will always yield a number less than one, quickly going towards zero.
2993    ///
2994    /// The function will call [`Self::request_repaint()`] when appropriate.
2995    ///
2996    /// The animation time is taken from [`Style::animation_time`].
2997    #[track_caller] // To track repaint cause
2998    pub fn animate_bool(&self, id: Id, value: bool) -> f32 {
2999        let animation_time = self.style().animation_time;
3000        self.animate_bool_with_time_and_easing(id, value, animation_time, emath::easing::linear)
3001    }
3002
3003    /// Like [`Self::animate_bool`], but uses an easing function that makes the value move
3004    /// quickly in the beginning and slow down towards the end.
3005    ///
3006    /// The exact easing function may come to change in future versions of egui.
3007    #[track_caller] // To track repaint cause
3008    pub fn animate_bool_responsive(&self, id: Id, value: bool) -> f32 {
3009        self.animate_bool_with_easing(id, value, emath::easing::cubic_out)
3010    }
3011
3012    /// Like [`Self::animate_bool`] but allows you to control the easing function.
3013    #[track_caller] // To track repaint cause
3014    pub fn animate_bool_with_easing(&self, id: Id, value: bool, easing: fn(f32) -> f32) -> f32 {
3015        let animation_time = self.style().animation_time;
3016        self.animate_bool_with_time_and_easing(id, value, animation_time, easing)
3017    }
3018
3019    /// Like [`Self::animate_bool`] but allows you to control the animation time.
3020    #[track_caller] // To track repaint cause
3021    pub fn animate_bool_with_time(&self, id: Id, target_value: bool, animation_time: f32) -> f32 {
3022        self.animate_bool_with_time_and_easing(
3023            id,
3024            target_value,
3025            animation_time,
3026            emath::easing::linear,
3027        )
3028    }
3029
3030    /// Like [`Self::animate_bool`] but allows you to control the animation time and easing function.
3031    ///
3032    /// Use e.g. [`emath::easing::quadratic_out`]
3033    /// for a responsive start and a slow end.
3034    ///
3035    /// The easing function flips when `target_value` is `false`,
3036    /// so that when going back towards 0.0, we get
3037    #[track_caller] // To track repaint cause
3038    pub fn animate_bool_with_time_and_easing(
3039        &self,
3040        id: Id,
3041        target_value: bool,
3042        animation_time: f32,
3043        easing: fn(f32) -> f32,
3044    ) -> f32 {
3045        let animated_value = self.write(|ctx| {
3046            ctx.animation_manager.animate_bool(
3047                &ctx.viewports.entry(ctx.viewport_id()).or_default().input,
3048                animation_time,
3049                id,
3050                target_value,
3051            )
3052        });
3053
3054        let animation_in_progress = 0.0 < animated_value && animated_value < 1.0;
3055        if animation_in_progress {
3056            self.request_repaint();
3057        }
3058
3059        if target_value {
3060            easing(animated_value)
3061        } else {
3062            1.0 - easing(1.0 - animated_value)
3063        }
3064    }
3065
3066    /// Smoothly animate an `f32` value.
3067    ///
3068    /// At the first call the value is written to memory.
3069    /// When it is called with a new value, it linearly interpolates to it in the given time.
3070    #[track_caller] // To track repaint cause
3071    pub fn animate_value_with_time(&self, id: Id, target_value: f32, animation_time: f32) -> f32 {
3072        let animated_value = self.write(|ctx| {
3073            ctx.animation_manager.animate_value(
3074                &ctx.viewports.entry(ctx.viewport_id()).or_default().input,
3075                animation_time,
3076                id,
3077                target_value,
3078            )
3079        });
3080        let animation_in_progress = animated_value != target_value;
3081        if animation_in_progress {
3082            self.request_repaint();
3083        }
3084
3085        animated_value
3086    }
3087
3088    /// Clear memory of any animations.
3089    pub fn clear_animations(&self) {
3090        self.write(|ctx| ctx.animation_manager = Default::default());
3091    }
3092}
3093
3094impl Context {
3095    /// Show a ui for settings (style and tessellation options).
3096    pub fn settings_ui(&self, ui: &mut Ui) {
3097        let prev_options = self.options(|o| o.clone());
3098        let mut options = prev_options.clone();
3099
3100        ui.collapsing("🔠 Font tweak", |ui| {
3101            self.fonts_tweak_ui(ui);
3102        });
3103
3104        options.ui(ui);
3105
3106        if options != prev_options {
3107            self.options_mut(move |o| *o = options);
3108        }
3109    }
3110
3111    fn fonts_tweak_ui(&self, ui: &mut Ui) {
3112        let mut font_definitions = self.write(|ctx| ctx.font_definitions.clone());
3113        let mut changed = false;
3114
3115        for (name, data) in &mut font_definitions.font_data {
3116            ui.collapsing(name, |ui| {
3117                let mut tweak = data.tweak;
3118                if tweak.ui(ui).changed() {
3119                    Arc::make_mut(data).tweak = tweak;
3120                    changed = true;
3121                }
3122            });
3123        }
3124
3125        if changed {
3126            self.set_fonts(font_definitions);
3127        }
3128    }
3129
3130    /// Show the state of egui, including its input and output.
3131    pub fn inspection_ui(&self, ui: &mut Ui) {
3132        use crate::containers::CollapsingHeader;
3133
3134        crate::Grid::new("egui-inspection-grid")
3135            .num_columns(2)
3136            .striped(true)
3137            .show(ui, |ui| {
3138                ui.label("Total ui frames:");
3139                ui.monospace(ui.ctx().cumulative_frame_nr().to_string());
3140                ui.end_row();
3141
3142                ui.label("Total ui passes:");
3143                ui.monospace(ui.ctx().cumulative_pass_nr().to_string());
3144                ui.end_row();
3145
3146                ui.label("Is using pointer")
3147                    .on_hover_text("Is egui currently using the pointer actively (e.g. dragging a slider)?");
3148                ui.monospace(self.is_using_pointer().to_string());
3149                ui.end_row();
3150
3151                ui.label("Wants pointer input")
3152                    .on_hover_text("Is egui currently interested in the location of the pointer (either because it is in use, or because it is hovering over a window).");
3153                ui.monospace(self.wants_pointer_input().to_string());
3154                ui.end_row();
3155
3156                ui.label("Wants keyboard input").on_hover_text("Is egui currently listening for text input?");
3157                ui.monospace(self.wants_keyboard_input().to_string());
3158                ui.end_row();
3159
3160                ui.label("Keyboard focus widget").on_hover_text("Is egui currently listening for text input?");
3161                ui.monospace(self.memory(|m| m.focused())
3162                    .as_ref()
3163                    .map(Id::short_debug_format)
3164                    .unwrap_or_default());
3165                ui.end_row();
3166
3167                let pointer_pos = self
3168                    .pointer_hover_pos()
3169                    .map_or_else(String::new, |pos| format!("{pos:?}"));
3170                ui.label("Pointer pos");
3171                ui.monospace(pointer_pos);
3172                ui.end_row();
3173
3174                let top_layer = self
3175                    .pointer_hover_pos()
3176                    .and_then(|pos| self.layer_id_at(pos))
3177                    .map_or_else(String::new, |layer| layer.short_debug_format());
3178                ui.label("Top layer under mouse");
3179                ui.monospace(top_layer);
3180                ui.end_row();
3181            });
3182
3183        ui.add_space(16.0);
3184
3185        ui.label(format!(
3186            "There are {} text galleys in the layout cache",
3187            self.fonts(|f| f.num_galleys_in_cache())
3188        ))
3189        .on_hover_text("This is approximately the number of text strings on screen");
3190        ui.add_space(16.0);
3191
3192        CollapsingHeader::new("🔃 Repaint Causes")
3193            .default_open(false)
3194            .show(ui, |ui| {
3195                ui.set_min_height(120.0);
3196                ui.label("What caused egui to repaint:");
3197                ui.add_space(8.0);
3198                let causes = ui.ctx().repaint_causes();
3199                for cause in causes {
3200                    ui.label(cause.to_string());
3201                }
3202            });
3203
3204        CollapsingHeader::new("📥 Input")
3205            .default_open(false)
3206            .show(ui, |ui| {
3207                let input = ui.input(|i| i.clone());
3208                input.ui(ui);
3209            });
3210
3211        CollapsingHeader::new("📊 Paint stats")
3212            .default_open(false)
3213            .show(ui, |ui| {
3214                let paint_stats = self.read(|ctx| ctx.paint_stats);
3215                paint_stats.ui(ui);
3216            });
3217
3218        CollapsingHeader::new("🖼 Textures")
3219            .default_open(false)
3220            .show(ui, |ui| {
3221                self.texture_ui(ui);
3222            });
3223
3224        CollapsingHeader::new("🖼 Image loaders")
3225            .default_open(false)
3226            .show(ui, |ui| {
3227                self.loaders_ui(ui);
3228            });
3229
3230        CollapsingHeader::new("🔠 Font texture")
3231            .default_open(false)
3232            .show(ui, |ui| {
3233                let font_image_size = self.fonts(|f| f.font_image_size());
3234                crate::introspection::font_texture_ui(ui, font_image_size);
3235            });
3236
3237        CollapsingHeader::new("Label text selection state")
3238            .default_open(false)
3239            .show(ui, |ui| {
3240                ui.label(format!(
3241                    "{:#?}",
3242                    *ui.ctx()
3243                        .plugin::<crate::text_selection::LabelSelectionState>()
3244                        .lock()
3245                ));
3246            });
3247
3248        CollapsingHeader::new("Interaction")
3249            .default_open(false)
3250            .show(ui, |ui| {
3251                let interact_widgets = self.write(|ctx| ctx.viewport().interact_widgets.clone());
3252                interact_widgets.ui(ui);
3253            });
3254    }
3255
3256    /// Show stats about the allocated textures.
3257    pub fn texture_ui(&self, ui: &mut crate::Ui) {
3258        let tex_mngr = self.tex_manager();
3259        let tex_mngr = tex_mngr.read();
3260
3261        let mut textures: Vec<_> = tex_mngr.allocated().collect();
3262        textures.sort_by_key(|(id, _)| *id);
3263
3264        let mut bytes = 0;
3265        for (_, tex) in &textures {
3266            bytes += tex.bytes_used();
3267        }
3268
3269        ui.label(format!(
3270            "{} allocated texture(s), using {:.1} MB",
3271            textures.len(),
3272            bytes as f64 * 1e-6
3273        ));
3274        let max_preview_size = vec2(48.0, 32.0);
3275
3276        let pixels_per_point = self.pixels_per_point();
3277
3278        ui.group(|ui| {
3279            ScrollArea::vertical()
3280                .max_height(300.0)
3281                .auto_shrink([false, true])
3282                .show(ui, |ui| {
3283                    ui.style_mut().override_text_style = Some(TextStyle::Monospace);
3284                    Grid::new("textures")
3285                        .striped(true)
3286                        .num_columns(4)
3287                        .spacing(vec2(16.0, 2.0))
3288                        .min_row_height(max_preview_size.y)
3289                        .show(ui, |ui| {
3290                            for (&texture_id, meta) in textures {
3291                                let [w, h] = meta.size;
3292                                let point_size = vec2(w as f32, h as f32) / pixels_per_point;
3293
3294                                let mut size = point_size;
3295                                size *= (max_preview_size.x / size.x).min(1.0);
3296                                size *= (max_preview_size.y / size.y).min(1.0);
3297                                ui.image(SizedTexture::new(texture_id, size))
3298                                    .on_hover_ui(|ui| {
3299                                        // show larger on hover
3300                                        let max_size = 0.5 * ui.ctx().content_rect().size();
3301                                        let mut size = point_size;
3302                                        size *= max_size.x / size.x.max(max_size.x);
3303                                        size *= max_size.y / size.y.max(max_size.y);
3304                                        ui.image(SizedTexture::new(texture_id, size));
3305                                    });
3306
3307                                ui.label(format!("{w} x {h}"));
3308                                ui.label(format!("{:.3} MB", meta.bytes_used() as f64 * 1e-6));
3309                                ui.label(format!("{:?}", meta.name));
3310                                ui.end_row();
3311                            }
3312                        });
3313                });
3314        });
3315    }
3316
3317    /// Show stats about different image loaders.
3318    pub fn loaders_ui(&self, ui: &mut crate::Ui) {
3319        struct LoaderInfo {
3320            id: String,
3321            byte_size: usize,
3322        }
3323
3324        let mut byte_loaders = vec![];
3325        let mut image_loaders = vec![];
3326        let mut texture_loaders = vec![];
3327
3328        {
3329            let loaders = self.loaders();
3330            let Loaders {
3331                include: _,
3332                bytes,
3333                image,
3334                texture,
3335            } = loaders.as_ref();
3336
3337            for loader in bytes.lock().iter() {
3338                byte_loaders.push(LoaderInfo {
3339                    id: loader.id().to_owned(),
3340                    byte_size: loader.byte_size(),
3341                });
3342            }
3343            for loader in image.lock().iter() {
3344                image_loaders.push(LoaderInfo {
3345                    id: loader.id().to_owned(),
3346                    byte_size: loader.byte_size(),
3347                });
3348            }
3349            for loader in texture.lock().iter() {
3350                texture_loaders.push(LoaderInfo {
3351                    id: loader.id().to_owned(),
3352                    byte_size: loader.byte_size(),
3353                });
3354            }
3355        }
3356
3357        fn loaders_ui(ui: &mut crate::Ui, title: &str, loaders: &[LoaderInfo]) {
3358            let heading = format!("{} {title} loaders", loaders.len());
3359            crate::CollapsingHeader::new(heading)
3360                .default_open(true)
3361                .show(ui, |ui| {
3362                    Grid::new("loaders")
3363                        .striped(true)
3364                        .num_columns(2)
3365                        .show(ui, |ui| {
3366                            ui.label("ID");
3367                            ui.label("Size");
3368                            ui.end_row();
3369
3370                            for loader in loaders {
3371                                ui.label(&loader.id);
3372                                ui.label(format!("{:.3} MB", loader.byte_size as f64 * 1e-6));
3373                                ui.end_row();
3374                            }
3375                        });
3376                });
3377        }
3378
3379        loaders_ui(ui, "byte", &byte_loaders);
3380        loaders_ui(ui, "image", &image_loaders);
3381        loaders_ui(ui, "texture", &texture_loaders);
3382    }
3383
3384    /// Shows the contents of [`Self::memory`].
3385    pub fn memory_ui(&self, ui: &mut crate::Ui) {
3386        if ui
3387            .button("Reset all")
3388            .on_hover_text("Reset all egui state")
3389            .clicked()
3390        {
3391            self.memory_mut(|mem| *mem = Default::default());
3392        }
3393
3394        let (num_state, num_serialized) = self.data(|d| (d.len(), d.count_serialized()));
3395        ui.label(format!(
3396            "{num_state} widget states stored (of which {num_serialized} are serialized)."
3397        ));
3398
3399        ui.horizontal(|ui| {
3400            ui.label(format!(
3401                "{} areas (panels, windows, popups, …)",
3402                self.memory(|mem| mem.areas().count())
3403            ));
3404            if ui.button("Reset").clicked() {
3405                self.memory_mut(|mem| *mem.areas_mut() = Default::default());
3406            }
3407        });
3408        ui.indent("layers", |ui| {
3409            ui.label("Layers, ordered back to front.");
3410            let layers_ids: Vec<LayerId> = self.memory(|mem| mem.areas().order().to_vec());
3411            for layer_id in layers_ids {
3412                if let Some(area) = AreaState::load(self, layer_id.id) {
3413                    let is_visible = self.memory(|mem| mem.areas().is_visible(&layer_id));
3414                    if !is_visible {
3415                        continue;
3416                    }
3417                    let text = format!("{} - {:?}", layer_id.short_debug_format(), area.rect(),);
3418                    // TODO(emilk): `Sense::hover_highlight()`
3419                    let response =
3420                        ui.add(Label::new(RichText::new(text).monospace()).sense(Sense::click()));
3421                    if response.hovered() && is_visible {
3422                        ui.ctx()
3423                            .debug_painter()
3424                            .debug_rect(area.rect(), Color32::RED, "");
3425                    }
3426                } else {
3427                    ui.monospace(layer_id.short_debug_format());
3428                }
3429            }
3430        });
3431
3432        ui.horizontal(|ui| {
3433            ui.label(format!(
3434                "{} collapsing headers",
3435                self.data(|d| d.count::<containers::collapsing_header::InnerState>())
3436            ));
3437            if ui.button("Reset").clicked() {
3438                self.data_mut(|d| d.remove_by_type::<containers::collapsing_header::InnerState>());
3439            }
3440        });
3441
3442        #[expect(deprecated)]
3443        ui.horizontal(|ui| {
3444            ui.label(format!(
3445                "{} menu bars",
3446                self.data(|d| d.count::<crate::menu::BarState>())
3447            ));
3448            if ui.button("Reset").clicked() {
3449                self.data_mut(|d| d.remove_by_type::<crate::menu::BarState>());
3450            }
3451        });
3452
3453        ui.horizontal(|ui| {
3454            ui.label(format!(
3455                "{} scroll areas",
3456                self.data(|d| d.count::<scroll_area::State>())
3457            ));
3458            if ui.button("Reset").clicked() {
3459                self.data_mut(|d| d.remove_by_type::<scroll_area::State>());
3460            }
3461        });
3462
3463        ui.horizontal(|ui| {
3464            ui.label(format!(
3465                "{} resize areas",
3466                self.data(|d| d.count::<resize::State>())
3467            ));
3468            if ui.button("Reset").clicked() {
3469                self.data_mut(|d| d.remove_by_type::<resize::State>());
3470            }
3471        });
3472
3473        ui.shrink_width_to_current(); // don't let the text below grow this window wider
3474        ui.label("NOTE: the position of this window cannot be reset from within itself.");
3475
3476        ui.collapsing("Interaction", |ui| {
3477            let interaction = self.memory(|mem| mem.interaction().clone());
3478            interaction.ui(ui);
3479        });
3480    }
3481}
3482
3483impl Context {
3484    /// Edit the [`Style`].
3485    pub fn style_ui(&self, ui: &mut Ui, theme: Theme) {
3486        let mut style: Style = (*self.style_of(theme)).clone();
3487        style.ui(ui);
3488        self.set_style_of(theme, style);
3489    }
3490}
3491
3492/// ## Accessibility
3493impl Context {
3494    /// If AccessKit support is active for the current frame, get or create
3495    /// a node builder with the specified ID and return a mutable reference to it.
3496    /// For newly created nodes, the parent is the parent [`Ui`]s ID.
3497    /// And an [`Ui`]s parent can be set with [`crate::UiBuilder::accessibility_parent`].
3498    ///
3499    /// The `Context` lock is held while the given closure is called!
3500    ///
3501    /// Returns `None` if acesskit is off.
3502    // TODO(emilk): consider making both read-only and read-write versions
3503    #[cfg(feature = "accesskit")]
3504    pub fn accesskit_node_builder<R>(
3505        &self,
3506        id: Id,
3507        writer: impl FnOnce(&mut accesskit::Node) -> R,
3508    ) -> Option<R> {
3509        self.write(|ctx| {
3510            ctx.viewport()
3511                .this_pass
3512                .accesskit_state
3513                .is_some()
3514                .then(|| ctx.accesskit_node_builder(id))
3515                .map(writer)
3516        })
3517    }
3518
3519    #[cfg(feature = "accesskit")]
3520    pub(crate) fn register_accesskit_parent(&self, id: Id, parent_id: Id) {
3521        self.write(|ctx| {
3522            if let Some(state) = ctx.viewport().this_pass.accesskit_state.as_mut() {
3523                state.parent_map.insert(id, parent_id);
3524            }
3525        });
3526    }
3527
3528    /// Enable generation of AccessKit tree updates in all future frames.
3529    #[cfg(feature = "accesskit")]
3530    pub fn enable_accesskit(&self) {
3531        self.write(|ctx| ctx.is_accesskit_enabled = true);
3532    }
3533
3534    /// Disable generation of AccessKit tree updates in all future frames.
3535    #[cfg(feature = "accesskit")]
3536    pub fn disable_accesskit(&self) {
3537        self.write(|ctx| ctx.is_accesskit_enabled = false);
3538    }
3539}
3540
3541/// ## Image loading
3542impl Context {
3543    /// Associate some static bytes with a `uri`.
3544    ///
3545    /// The same `uri` may be passed to [`Ui::image`] later to load the bytes as an image.
3546    ///
3547    /// By convention, the `uri` should start with `bytes://`.
3548    /// Following that convention will lead to better error messages.
3549    pub fn include_bytes(&self, uri: impl Into<Cow<'static, str>>, bytes: impl Into<Bytes>) {
3550        self.loaders().include.insert(uri, bytes);
3551    }
3552
3553    /// Returns `true` if the chain of bytes, image, or texture loaders
3554    /// contains a loader with the given `id`.
3555    pub fn is_loader_installed(&self, id: &str) -> bool {
3556        let loaders = self.loaders();
3557
3558        loaders.bytes.lock().iter().any(|l| l.id() == id)
3559            || loaders.image.lock().iter().any(|l| l.id() == id)
3560            || loaders.texture.lock().iter().any(|l| l.id() == id)
3561    }
3562
3563    /// Add a new bytes loader.
3564    ///
3565    /// It will be tried first, before any already installed loaders.
3566    ///
3567    /// See [`load`] for more information.
3568    pub fn add_bytes_loader(&self, loader: Arc<dyn load::BytesLoader + Send + Sync + 'static>) {
3569        self.loaders().bytes.lock().push(loader);
3570    }
3571
3572    /// Add a new image loader.
3573    ///
3574    /// It will be tried first, before any already installed loaders.
3575    ///
3576    /// See [`load`] for more information.
3577    pub fn add_image_loader(&self, loader: Arc<dyn load::ImageLoader + Send + Sync + 'static>) {
3578        self.loaders().image.lock().push(loader);
3579    }
3580
3581    /// Add a new texture loader.
3582    ///
3583    /// It will be tried first, before any already installed loaders.
3584    ///
3585    /// See [`load`] for more information.
3586    pub fn add_texture_loader(&self, loader: Arc<dyn load::TextureLoader + Send + Sync + 'static>) {
3587        self.loaders().texture.lock().push(loader);
3588    }
3589
3590    /// Release all memory and textures related to the given image URI.
3591    ///
3592    /// If you attempt to load the image again, it will be reloaded from scratch.
3593    /// Also this cancels any ongoing loading of the image.
3594    pub fn forget_image(&self, uri: &str) {
3595        use load::BytesLoader as _;
3596
3597        profiling::function_scope!();
3598
3599        let loaders = self.loaders();
3600
3601        loaders.include.forget(uri);
3602        for loader in loaders.bytes.lock().iter() {
3603            loader.forget(uri);
3604        }
3605        for loader in loaders.image.lock().iter() {
3606            loader.forget(uri);
3607        }
3608        for loader in loaders.texture.lock().iter() {
3609            loader.forget(uri);
3610        }
3611    }
3612
3613    /// Release all memory and textures related to images used in [`Ui::image`] or [`crate::Image`].
3614    ///
3615    /// If you attempt to load any images again, they will be reloaded from scratch.
3616    pub fn forget_all_images(&self) {
3617        use load::BytesLoader as _;
3618
3619        profiling::function_scope!();
3620
3621        let loaders = self.loaders();
3622
3623        loaders.include.forget_all();
3624        for loader in loaders.bytes.lock().iter() {
3625            loader.forget_all();
3626        }
3627        for loader in loaders.image.lock().iter() {
3628            loader.forget_all();
3629        }
3630        for loader in loaders.texture.lock().iter() {
3631            loader.forget_all();
3632        }
3633    }
3634
3635    /// Try loading the bytes from the given uri using any available bytes loaders.
3636    ///
3637    /// Loaders are expected to cache results, so that this call is immediate-mode safe.
3638    ///
3639    /// This calls the loaders one by one in the order in which they were registered.
3640    /// If a loader returns [`LoadError::NotSupported`][not_supported],
3641    /// then the next loader is called. This process repeats until all loaders have
3642    /// been exhausted, at which point this returns [`LoadError::NotSupported`][not_supported].
3643    ///
3644    /// # Errors
3645    /// This may fail with:
3646    /// - [`LoadError::NotSupported`][not_supported] if none of the registered loaders support loading the given `uri`.
3647    /// - [`LoadError::Loading`][custom] if one of the loaders _does_ support loading the `uri`, but the loading process failed.
3648    ///
3649    /// ⚠ May deadlock if called from within a `BytesLoader`!
3650    ///
3651    /// [not_supported]: crate::load::LoadError::NotSupported
3652    /// [custom]: crate::load::LoadError::Loading
3653    pub fn try_load_bytes(&self, uri: &str) -> load::BytesLoadResult {
3654        profiling::function_scope!(uri);
3655
3656        let loaders = self.loaders();
3657        let bytes_loaders = loaders.bytes.lock();
3658
3659        // Try most recently added loaders first (hence `.rev()`)
3660        for loader in bytes_loaders.iter().rev() {
3661            let result = loader.load(self, uri);
3662            match result {
3663                Err(load::LoadError::NotSupported) => {}
3664                _ => return result,
3665            }
3666        }
3667
3668        Err(load::LoadError::NoMatchingBytesLoader)
3669    }
3670
3671    /// Try loading the image from the given uri using any available image loaders.
3672    ///
3673    /// Loaders are expected to cache results, so that this call is immediate-mode safe.
3674    ///
3675    /// This calls the loaders one by one in the order in which they were registered.
3676    /// If a loader returns [`LoadError::NotSupported`][not_supported],
3677    /// then the next loader is called. This process repeats until all loaders have
3678    /// been exhausted, at which point this returns [`LoadError::NotSupported`][not_supported].
3679    ///
3680    /// # Errors
3681    /// This may fail with:
3682    /// - [`LoadError::NoImageLoaders`][no_image_loaders] if tbere are no registered image loaders.
3683    /// - [`LoadError::NotSupported`][not_supported] if none of the registered loaders support loading the given `uri`.
3684    /// - [`LoadError::Loading`][custom] if one of the loaders _does_ support loading the `uri`, but the loading process failed.
3685    ///
3686    /// ⚠ May deadlock if called from within an `ImageLoader`!
3687    ///
3688    /// [no_image_loaders]: crate::load::LoadError::NoImageLoaders
3689    /// [not_supported]: crate::load::LoadError::NotSupported
3690    /// [custom]: crate::load::LoadError::Loading
3691    pub fn try_load_image(&self, uri: &str, size_hint: load::SizeHint) -> load::ImageLoadResult {
3692        profiling::function_scope!(uri);
3693
3694        let loaders = self.loaders();
3695        let image_loaders = loaders.image.lock();
3696        if image_loaders.is_empty() {
3697            return Err(load::LoadError::NoImageLoaders);
3698        }
3699
3700        let mut format = None;
3701
3702        // Try most recently added loaders first (hence `.rev()`)
3703        for loader in image_loaders.iter().rev() {
3704            match loader.load(self, uri, size_hint) {
3705                Err(load::LoadError::NotSupported) => {}
3706                Err(load::LoadError::FormatNotSupported { detected_format }) => {
3707                    format = format.or(detected_format);
3708                }
3709                result => return result,
3710            }
3711        }
3712
3713        Err(load::LoadError::NoMatchingImageLoader {
3714            detected_format: format,
3715        })
3716    }
3717
3718    /// Try loading the texture from the given uri using any available texture loaders.
3719    ///
3720    /// Loaders are expected to cache results, so that this call is immediate-mode safe.
3721    ///
3722    /// This calls the loaders one by one in the order in which they were registered.
3723    /// If a loader returns [`LoadError::NotSupported`][not_supported],
3724    /// then the next loader is called. This process repeats until all loaders have
3725    /// been exhausted, at which point this returns [`LoadError::NotSupported`][not_supported].
3726    ///
3727    /// # Errors
3728    /// This may fail with:
3729    /// - [`LoadError::NotSupported`][not_supported] if none of the registered loaders support loading the given `uri`.
3730    /// - [`LoadError::Loading`][custom] if one of the loaders _does_ support loading the `uri`, but the loading process failed.
3731    ///
3732    /// ⚠ May deadlock if called from within a `TextureLoader`!
3733    ///
3734    /// [not_supported]: crate::load::LoadError::NotSupported
3735    /// [custom]: crate::load::LoadError::Loading
3736    pub fn try_load_texture(
3737        &self,
3738        uri: &str,
3739        texture_options: TextureOptions,
3740        size_hint: load::SizeHint,
3741    ) -> load::TextureLoadResult {
3742        profiling::function_scope!(uri);
3743
3744        let loaders = self.loaders();
3745        let texture_loaders = loaders.texture.lock();
3746
3747        // Try most recently added loaders first (hence `.rev()`)
3748        for loader in texture_loaders.iter().rev() {
3749            match loader.load(self, uri, texture_options, size_hint) {
3750                Err(load::LoadError::NotSupported) => {}
3751                result => return result,
3752            }
3753        }
3754
3755        Err(load::LoadError::NoMatchingTextureLoader)
3756    }
3757
3758    /// The loaders of bytes, images, and textures.
3759    pub fn loaders(&self) -> Arc<Loaders> {
3760        self.read(|this| this.loaders.clone())
3761    }
3762
3763    /// Returns `true` if any image is currently being loaded.
3764    pub fn has_pending_images(&self) -> bool {
3765        self.read(|this| {
3766            this.loaders.image.lock().iter().any(|i| i.has_pending())
3767                || this.loaders.bytes.lock().iter().any(|i| i.has_pending())
3768        })
3769    }
3770}
3771
3772/// ## Viewports
3773impl Context {
3774    /// Return the `ViewportId` of the current viewport.
3775    ///
3776    /// If this is the root viewport, this will return [`ViewportId::ROOT`].
3777    ///
3778    /// Don't use this outside of `Self::run`, or after `Self::end_pass`.
3779    pub fn viewport_id(&self) -> ViewportId {
3780        self.read(|ctx| ctx.viewport_id())
3781    }
3782
3783    /// Return the `ViewportId` of his parent.
3784    ///
3785    /// If this is the root viewport, this will return [`ViewportId::ROOT`].
3786    ///
3787    /// Don't use this outside of `Self::run`, or after `Self::end_pass`.
3788    pub fn parent_viewport_id(&self) -> ViewportId {
3789        self.read(|ctx| ctx.parent_viewport_id())
3790    }
3791
3792    /// Read the state of the current viewport.
3793    pub fn viewport<R>(&self, reader: impl FnOnce(&ViewportState) -> R) -> R {
3794        self.write(|ctx| reader(ctx.viewport()))
3795    }
3796
3797    /// Read the state of a specific current viewport.
3798    pub fn viewport_for<R>(
3799        &self,
3800        viewport_id: ViewportId,
3801        reader: impl FnOnce(&ViewportState) -> R,
3802    ) -> R {
3803        self.write(|ctx| reader(ctx.viewport_for(viewport_id)))
3804    }
3805
3806    /// For integrations: Set this to render a sync viewport.
3807    ///
3808    /// This will only set the callback for the current thread,
3809    /// which most likely should be the main thread.
3810    ///
3811    /// When an immediate viewport is created with [`Self::show_viewport_immediate`] it will be rendered by this function.
3812    ///
3813    /// When called, the integration needs to:
3814    /// * Check if there already is a window for this viewport id, and if not open one
3815    /// * Set the window attributes (position, size, …) based on [`ImmediateViewport::builder`].
3816    /// * Call [`Context::run`] with [`ImmediateViewport::viewport_ui_cb`].
3817    /// * Handle the output from [`Context::run`], including rendering
3818    pub fn set_immediate_viewport_renderer(
3819        callback: impl for<'a> Fn(&Self, ImmediateViewport<'a>) + 'static,
3820    ) {
3821        let callback = Box::new(callback);
3822        IMMEDIATE_VIEWPORT_RENDERER.with(|render_sync| {
3823            render_sync.replace(Some(callback));
3824        });
3825    }
3826
3827    /// If `true`, [`Self::show_viewport_deferred`] and [`Self::show_viewport_immediate`] will
3828    /// embed the new viewports inside the existing one, instead of spawning a new native window.
3829    ///
3830    /// `eframe` sets this to `false` on supported platforms, but the default value is `true`.
3831    pub fn embed_viewports(&self) -> bool {
3832        self.read(|ctx| ctx.embed_viewports)
3833    }
3834
3835    /// If `true`, [`Self::show_viewport_deferred`] and [`Self::show_viewport_immediate`] will
3836    /// embed the new viewports inside the existing one, instead of spawning a new native window.
3837    ///
3838    /// `eframe` sets this to `false` on supported platforms, but the default value is `true`.
3839    pub fn set_embed_viewports(&self, value: bool) {
3840        self.write(|ctx| ctx.embed_viewports = value);
3841    }
3842
3843    /// Send a command to the current viewport.
3844    ///
3845    /// This lets you affect the current viewport, e.g. resizing the window.
3846    pub fn send_viewport_cmd(&self, command: ViewportCommand) {
3847        self.send_viewport_cmd_to(self.viewport_id(), command);
3848    }
3849
3850    /// Send a command to a specific viewport.
3851    ///
3852    /// This lets you affect another viewport, e.g. resizing its window.
3853    pub fn send_viewport_cmd_to(&self, id: ViewportId, command: ViewportCommand) {
3854        self.request_repaint_of(id);
3855
3856        if command.requires_parent_repaint() {
3857            self.request_repaint_of(self.parent_viewport_id());
3858        }
3859
3860        self.write(|ctx| ctx.viewport_for(id).commands.push(command));
3861    }
3862
3863    /// Show a deferred viewport, creating a new native window, if possible.
3864    ///
3865    /// The given id must be unique for each viewport.
3866    ///
3867    /// You need to call this each pass when the child viewport should exist.
3868    ///
3869    /// You can check if the user wants to close the viewport by checking the
3870    /// [`crate::ViewportInfo::close_requested`] flags found in [`crate::InputState::viewport`].
3871    ///
3872    /// The given callback will be called whenever the child viewport needs repainting,
3873    /// e.g. on an event or when [`Self::request_repaint`] is called.
3874    /// This means it may be called multiple times, for instance while the
3875    /// parent viewport (the caller) is sleeping but the child viewport is animating.
3876    ///
3877    /// You will need to wrap your viewport state in an `Arc<RwLock<T>>` or `Arc<Mutex<T>>`.
3878    /// When this is called again with the same id in `ViewportBuilder` the render function for that viewport will be updated.
3879    ///
3880    /// You can also use [`Self::show_viewport_immediate`], which uses a simpler `FnOnce`
3881    /// with no need for `Send` or `Sync`. The downside is that it will require
3882    /// the parent viewport (the caller) to repaint anytime the child is repainted,
3883    /// and vice versa.
3884    ///
3885    /// If [`Context::embed_viewports`] is `true` (e.g. if the current egui
3886    /// backend does not support multiple viewports), the given callback
3887    /// will be called immediately, embedding the new viewport in the current one.
3888    /// You can check this with the [`ViewportClass`] given in the callback.
3889    /// If you find [`ViewportClass::Embedded`], you need to create a new [`crate::Window`] for you content.
3890    ///
3891    /// See [`crate::viewport`] for more information about viewports.
3892    pub fn show_viewport_deferred(
3893        &self,
3894        new_viewport_id: ViewportId,
3895        viewport_builder: ViewportBuilder,
3896        viewport_ui_cb: impl Fn(&Self, ViewportClass) + Send + Sync + 'static,
3897    ) {
3898        profiling::function_scope!();
3899
3900        if self.embed_viewports() {
3901            viewport_ui_cb(self, ViewportClass::Embedded);
3902        } else {
3903            self.write(|ctx| {
3904                ctx.viewport_parents
3905                    .insert(new_viewport_id, ctx.viewport_id());
3906
3907                let viewport = ctx.viewports.entry(new_viewport_id).or_default();
3908                viewport.class = ViewportClass::Deferred;
3909                viewport.builder = viewport_builder;
3910                viewport.used = true;
3911                viewport.viewport_ui_cb = Some(Arc::new(move |ctx| {
3912                    (viewport_ui_cb)(ctx, ViewportClass::Deferred);
3913                }));
3914            });
3915        }
3916    }
3917
3918    /// Show an immediate viewport, creating a new native window, if possible.
3919    ///
3920    /// This is the easier type of viewport to use, but it is less performant
3921    /// at it requires both parent and child to repaint if any one of them needs repainting,
3922    /// which effectively produce double work for two viewports, and triple work for three viewports, etc.
3923    /// To avoid this, use [`Self::show_viewport_deferred`] instead.
3924    ///
3925    /// The given id must be unique for each viewport.
3926    ///
3927    /// You need to call this each pass when the child viewport should exist.
3928    ///
3929    /// You can check if the user wants to close the viewport by checking the
3930    /// [`crate::ViewportInfo::close_requested`] flags found in [`crate::InputState::viewport`].
3931    ///
3932    /// The given ui function will be called immediately.
3933    /// This may only be called on the main thread.
3934    /// This call will pause the current viewport and render the child viewport in its own window.
3935    /// This means that the child viewport will not be repainted when the parent viewport is repainted, and vice versa.
3936    ///
3937    /// If [`Context::embed_viewports`] is `true` (e.g. if the current egui
3938    /// backend does not support multiple viewports), the given callback
3939    /// will be called immediately, embedding the new viewport in the current one.
3940    /// You can check this with the [`ViewportClass`] given in the callback.
3941    /// If you find [`ViewportClass::Embedded`], you need to create a new [`crate::Window`] for you content.
3942    ///
3943    /// See [`crate::viewport`] for more information about viewports.
3944    pub fn show_viewport_immediate<T>(
3945        &self,
3946        new_viewport_id: ViewportId,
3947        builder: ViewportBuilder,
3948        mut viewport_ui_cb: impl FnMut(&Self, ViewportClass) -> T,
3949    ) -> T {
3950        profiling::function_scope!();
3951
3952        if self.embed_viewports() {
3953            return viewport_ui_cb(self, ViewportClass::Embedded);
3954        }
3955
3956        IMMEDIATE_VIEWPORT_RENDERER.with(|immediate_viewport_renderer| {
3957            let immediate_viewport_renderer = immediate_viewport_renderer.borrow();
3958            let Some(immediate_viewport_renderer) = immediate_viewport_renderer.as_ref() else {
3959                // This egui backend does not support multiple viewports.
3960                return viewport_ui_cb(self, ViewportClass::Embedded);
3961            };
3962
3963            let ids = self.write(|ctx| {
3964                let parent_viewport_id = ctx.viewport_id();
3965
3966                ctx.viewport_parents
3967                    .insert(new_viewport_id, parent_viewport_id);
3968
3969                let viewport = ctx.viewports.entry(new_viewport_id).or_default();
3970                viewport.builder = builder.clone();
3971                viewport.used = true;
3972                viewport.viewport_ui_cb = None; // it is immediate
3973
3974                ViewportIdPair::from_self_and_parent(new_viewport_id, parent_viewport_id)
3975            });
3976
3977            let mut out = None;
3978            {
3979                let out = &mut out;
3980
3981                let viewport = ImmediateViewport {
3982                    ids,
3983                    builder,
3984                    viewport_ui_cb: Box::new(move |context| {
3985                        *out = Some(viewport_ui_cb(context, ViewportClass::Immediate));
3986                    }),
3987                };
3988
3989                immediate_viewport_renderer(self, viewport);
3990            }
3991
3992            out.expect(
3993                "egui backend is implemented incorrectly - the user callback was never called",
3994            )
3995        })
3996    }
3997}
3998
3999/// ## Interaction
4000impl Context {
4001    /// Read you what widgets are currently being interacted with.
4002    pub fn interaction_snapshot<R>(&self, reader: impl FnOnce(&InteractionSnapshot) -> R) -> R {
4003        self.write(|w| reader(&w.viewport().interact_widgets))
4004    }
4005
4006    /// The widget currently being dragged, if any.
4007    ///
4008    /// For widgets that sense both clicks and drags, this will
4009    /// not be set until the mouse cursor has moved a certain distance.
4010    ///
4011    /// NOTE: if the widget was released this pass, this will be `None`.
4012    /// Use [`Self::drag_stopped_id`] instead.
4013    pub fn dragged_id(&self) -> Option<Id> {
4014        self.interaction_snapshot(|i| i.dragged)
4015    }
4016
4017    /// Is this specific widget being dragged?
4018    ///
4019    /// A widget that sense both clicks and drags is only marked as "dragged"
4020    /// when the mouse has moved a bit.
4021    ///
4022    /// See also: [`crate::Response::dragged`].
4023    pub fn is_being_dragged(&self, id: Id) -> bool {
4024        self.dragged_id() == Some(id)
4025    }
4026
4027    /// This widget just started being dragged this pass.
4028    ///
4029    /// The same widget should also be found in [`Self::dragged_id`].
4030    pub fn drag_started_id(&self) -> Option<Id> {
4031        self.interaction_snapshot(|i| i.drag_started)
4032    }
4033
4034    /// This widget was being dragged, but was released this pass.
4035    pub fn drag_stopped_id(&self) -> Option<Id> {
4036        self.interaction_snapshot(|i| i.drag_stopped)
4037    }
4038
4039    /// Set which widget is being dragged.
4040    pub fn set_dragged_id(&self, id: Id) {
4041        self.write(|ctx| {
4042            let vp = ctx.viewport();
4043            let i = &mut vp.interact_widgets;
4044            if i.dragged != Some(id) {
4045                i.drag_stopped = i.dragged.or(i.drag_stopped);
4046                i.dragged = Some(id);
4047                i.drag_started = Some(id);
4048            }
4049
4050            ctx.memory.interaction_mut().potential_drag_id = Some(id);
4051        });
4052    }
4053
4054    /// Stop dragging any widget.
4055    pub fn stop_dragging(&self) {
4056        self.write(|ctx| {
4057            let vp = ctx.viewport();
4058            let i = &mut vp.interact_widgets;
4059            if i.dragged.is_some() {
4060                i.drag_stopped = i.dragged;
4061                i.dragged = None;
4062            }
4063
4064            ctx.memory.interaction_mut().potential_drag_id = None;
4065        });
4066    }
4067
4068    /// Is something else being dragged?
4069    ///
4070    /// Returns true if we are dragging something, but not the given widget.
4071    #[inline(always)]
4072    pub fn dragging_something_else(&self, not_this: Id) -> bool {
4073        let dragged = self.dragged_id();
4074        dragged.is_some() && dragged != Some(not_this)
4075    }
4076}
4077
4078#[test]
4079fn context_impl_send_sync() {
4080    fn assert_send_sync<T: Send + Sync>() {}
4081    assert_send_sync::<Context>();
4082}
4083
4084#[cfg(test)]
4085mod test {
4086    use super::Context;
4087
4088    #[test]
4089    fn test_single_pass() {
4090        let ctx = Context::default();
4091        ctx.options_mut(|o| o.max_passes = 1.try_into().unwrap());
4092
4093        // A single call, no request to discard:
4094        {
4095            let mut num_calls = 0;
4096            let output = ctx.run(Default::default(), |ctx| {
4097                num_calls += 1;
4098                assert_eq!(ctx.output(|o| o.num_completed_passes), 0);
4099                assert!(!ctx.output(|o| o.requested_discard()));
4100                assert!(!ctx.will_discard());
4101            });
4102            assert_eq!(num_calls, 1);
4103            assert_eq!(output.platform_output.num_completed_passes, 1);
4104            assert!(!output.platform_output.requested_discard());
4105        }
4106
4107        // A single call, with a denied request to discard:
4108        {
4109            let mut num_calls = 0;
4110            let output = ctx.run(Default::default(), |ctx| {
4111                num_calls += 1;
4112                ctx.request_discard("test");
4113                assert!(!ctx.will_discard(), "The request should have been denied");
4114            });
4115            assert_eq!(num_calls, 1);
4116            assert_eq!(output.platform_output.num_completed_passes, 1);
4117            assert!(
4118                output.platform_output.requested_discard(),
4119                "The request should be reported"
4120            );
4121            assert_eq!(
4122                output
4123                    .platform_output
4124                    .request_discard_reasons
4125                    .first()
4126                    .unwrap()
4127                    .reason,
4128                "test"
4129            );
4130        }
4131    }
4132
4133    #[test]
4134    fn test_dual_pass() {
4135        let ctx = Context::default();
4136        ctx.options_mut(|o| o.max_passes = 2.try_into().unwrap());
4137
4138        // Normal single pass:
4139        {
4140            let mut num_calls = 0;
4141            let output = ctx.run(Default::default(), |ctx| {
4142                assert_eq!(ctx.output(|o| o.num_completed_passes), 0);
4143                assert!(!ctx.output(|o| o.requested_discard()));
4144                assert!(!ctx.will_discard());
4145                num_calls += 1;
4146            });
4147            assert_eq!(num_calls, 1);
4148            assert_eq!(output.platform_output.num_completed_passes, 1);
4149            assert!(!output.platform_output.requested_discard());
4150        }
4151
4152        // Request discard once:
4153        {
4154            let mut num_calls = 0;
4155            let output = ctx.run(Default::default(), |ctx| {
4156                assert_eq!(ctx.output(|o| o.num_completed_passes), num_calls);
4157
4158                assert!(!ctx.will_discard());
4159                if num_calls == 0 {
4160                    ctx.request_discard("test");
4161                    assert!(ctx.will_discard());
4162                }
4163
4164                num_calls += 1;
4165            });
4166            assert_eq!(num_calls, 2);
4167            assert_eq!(output.platform_output.num_completed_passes, 2);
4168            assert!(
4169                !output.platform_output.requested_discard(),
4170                "The request should have been cleared when fulfilled"
4171            );
4172        }
4173
4174        // Request discard twice:
4175        {
4176            let mut num_calls = 0;
4177            let output = ctx.run(Default::default(), |ctx| {
4178                assert_eq!(ctx.output(|o| o.num_completed_passes), num_calls);
4179
4180                assert!(!ctx.will_discard());
4181                ctx.request_discard("test");
4182                if num_calls == 0 {
4183                    assert!(ctx.will_discard(), "First request granted");
4184                } else {
4185                    assert!(!ctx.will_discard(), "Second request should be denied");
4186                }
4187
4188                num_calls += 1;
4189            });
4190            assert_eq!(num_calls, 2);
4191            assert_eq!(output.platform_output.num_completed_passes, 2);
4192            assert!(
4193                output.platform_output.requested_discard(),
4194                "The unfulfilled request should be reported"
4195            );
4196        }
4197    }
4198
4199    #[test]
4200    fn test_multi_pass() {
4201        let ctx = Context::default();
4202        ctx.options_mut(|o| o.max_passes = 10.try_into().unwrap());
4203
4204        // Request discard three times:
4205        {
4206            let mut num_calls = 0;
4207            let output = ctx.run(Default::default(), |ctx| {
4208                assert_eq!(ctx.output(|o| o.num_completed_passes), num_calls);
4209
4210                assert!(!ctx.will_discard());
4211                if num_calls <= 2 {
4212                    ctx.request_discard("test");
4213                    assert!(ctx.will_discard());
4214                }
4215
4216                num_calls += 1;
4217            });
4218            assert_eq!(num_calls, 4);
4219            assert_eq!(output.platform_output.num_completed_passes, 4);
4220            assert!(
4221                !output.platform_output.requested_discard(),
4222                "The request should have been cleared when fulfilled"
4223            );
4224        }
4225    }
4226}