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 containers::area::AreaState;
6use epaint::{
7    emath::TSTransform, mutex::*, stats::*, text::Fonts, util::OrderedFloat, TessellationOptions, *,
8};
9
10use crate::{
11    animation_manager::AnimationManager,
12    data::output::PlatformOutput,
13    frame_state::FrameState,
14    input_state::*,
15    layers::GraphicLayers,
16    load::{Bytes, Loaders, SizedTexture},
17    memory::Options,
18    os::OperatingSystem,
19    output::FullOutput,
20    util::IdTypeMap,
21    viewport::ViewportClass,
22    TextureHandle, ViewportCommand, *,
23};
24
25use self::{hit_test::WidgetHits, interaction::InteractionSnapshot};
26
27/// Information given to the backend about when it is time to repaint the ui.
28///
29/// This is given in the callback set by [`Context::set_request_repaint_callback`].
30#[derive(Clone, Copy, Debug)]
31pub struct RequestRepaintInfo {
32    /// This is used to specify what viewport that should repaint.
33    pub viewport_id: ViewportId,
34
35    /// Repaint after this duration. If zero, repaint as soon as possible.
36    pub delay: Duration,
37
38    /// The current frame number.
39    ///
40    /// This can be compared to [`Context::frame_nr`] to see if we've already
41    /// triggered the painting of the next frame.
42    pub current_frame_nr: u64,
43}
44
45// ----------------------------------------------------------------------------
46
47thread_local! {
48    static IMMEDIATE_VIEWPORT_RENDERER: RefCell<Option<Box<ImmediateViewportRendererCallback>>> = Default::default();
49}
50
51// ----------------------------------------------------------------------------
52
53struct WrappedTextureManager(Arc<RwLock<epaint::TextureManager>>);
54
55impl Default for WrappedTextureManager {
56    fn default() -> Self {
57        let mut tex_mngr = epaint::textures::TextureManager::default();
58
59        // Will be filled in later
60        let font_id = tex_mngr.alloc(
61            "egui_font_texture".into(),
62            epaint::FontImage::new([0, 0]).into(),
63            Default::default(),
64        );
65        assert_eq!(font_id, TextureId::default());
66
67        Self(Arc::new(RwLock::new(tex_mngr)))
68    }
69}
70
71// ----------------------------------------------------------------------------
72
73/// Generic event callback.
74pub type ContextCallback = Arc<dyn Fn(&Context) + Send + Sync>;
75
76#[derive(Clone)]
77struct NamedContextCallback {
78    debug_name: &'static str,
79    callback: ContextCallback,
80}
81
82/// Callbacks that users can register
83#[derive(Clone, Default)]
84struct Plugins {
85    pub on_begin_frame: Vec<NamedContextCallback>,
86    pub on_end_frame: Vec<NamedContextCallback>,
87}
88
89impl Plugins {
90    fn call(ctx: &Context, _cb_name: &str, callbacks: &[NamedContextCallback]) {
91        crate::profile_scope!("plugins", _cb_name);
92        for NamedContextCallback {
93            debug_name: _name,
94            callback,
95        } in callbacks
96        {
97            crate::profile_scope!("plugin", _name);
98            (callback)(ctx);
99        }
100    }
101
102    fn on_begin_frame(&self, ctx: &Context) {
103        Self::call(ctx, "on_begin_frame", &self.on_begin_frame);
104    }
105
106    fn on_end_frame(&self, ctx: &Context) {
107        Self::call(ctx, "on_end_frame", &self.on_end_frame);
108    }
109}
110
111// ----------------------------------------------------------------------------
112
113/// Repaint-logic
114impl ContextImpl {
115    /// This is where we update the repaint logic.
116    fn begin_frame_repaint_logic(&mut self, viewport_id: ViewportId) {
117        let viewport = self.viewports.entry(viewport_id).or_default();
118
119        std::mem::swap(
120            &mut viewport.repaint.prev_causes,
121            &mut viewport.repaint.causes,
122        );
123        viewport.repaint.causes.clear();
124
125        viewport.repaint.prev_frame_paint_delay = viewport.repaint.repaint_delay;
126
127        if viewport.repaint.outstanding == 0 {
128            // We are repainting now, so we can wait a while for the next repaint.
129            viewport.repaint.repaint_delay = Duration::MAX;
130        } else {
131            viewport.repaint.repaint_delay = Duration::ZERO;
132            viewport.repaint.outstanding -= 1;
133            if let Some(callback) = &self.request_repaint_callback {
134                (callback)(RequestRepaintInfo {
135                    viewport_id,
136                    delay: Duration::ZERO,
137                    current_frame_nr: viewport.repaint.frame_nr,
138                });
139            }
140        }
141    }
142
143    fn request_repaint(&mut self, viewport_id: ViewportId, cause: RepaintCause) {
144        self.request_repaint_after(Duration::ZERO, viewport_id, cause);
145    }
146
147    fn request_repaint_after(
148        &mut self,
149        mut delay: Duration,
150        viewport_id: ViewportId,
151        cause: RepaintCause,
152    ) {
153        let viewport = self.viewports.entry(viewport_id).or_default();
154
155        if delay == Duration::ZERO {
156            // Each request results in two repaints, just to give some things time to settle.
157            // This solves some corner-cases of missing repaints on frame-delayed responses.
158            viewport.repaint.outstanding = 1;
159        } else {
160            // For non-zero delays, we only repaint once, because
161            // otherwise we would just schedule an immediate repaint _now_,
162            // which would then clear the delay and repaint again.
163            // Hovering a tooltip is a good example of a case where we want to repaint after a delay.
164        }
165
166        if let Ok(predicted_frame_time) = Duration::try_from_secs_f32(viewport.input.predicted_dt) {
167            // Make it less likely we over-shoot the target:
168            delay = delay.saturating_sub(predicted_frame_time);
169        }
170
171        viewport.repaint.causes.push(cause);
172
173        // We save some CPU time by only calling the callback if we need to.
174        // If the new delay is greater or equal to the previous lowest,
175        // it means we have already called the callback, and don't need to do it again.
176        if delay < viewport.repaint.repaint_delay {
177            viewport.repaint.repaint_delay = delay;
178
179            if let Some(callback) = &self.request_repaint_callback {
180                (callback)(RequestRepaintInfo {
181                    viewport_id,
182                    delay,
183                    current_frame_nr: viewport.repaint.frame_nr,
184                });
185            }
186        }
187    }
188
189    #[must_use]
190    fn requested_immediate_repaint_prev_frame(&self, viewport_id: &ViewportId) -> bool {
191        self.viewports.get(viewport_id).map_or(false, |v| {
192            v.repaint.requested_immediate_repaint_prev_frame()
193        })
194    }
195
196    #[must_use]
197    fn has_requested_repaint(&self, viewport_id: &ViewportId) -> bool {
198        self.viewports.get(viewport_id).map_or(false, |v| {
199            0 < v.repaint.outstanding || v.repaint.repaint_delay < Duration::MAX
200        })
201    }
202}
203
204// ----------------------------------------------------------------------------
205
206/// State stored per viewport.
207///
208/// Mostly for internal use.
209/// Things here may move and change without warning.
210#[derive(Default)]
211pub struct ViewportState {
212    /// The type of viewport.
213    ///
214    /// This will never be [`ViewportClass::Embedded`],
215    /// since those don't result in real viewports.
216    pub class: ViewportClass,
217
218    /// The latest delta
219    pub builder: ViewportBuilder,
220
221    /// The user-code that shows the GUI, used for deferred viewports.
222    ///
223    /// `None` for immediate viewports.
224    pub viewport_ui_cb: Option<Arc<DeferredViewportUiCallback>>,
225
226    pub input: InputState,
227
228    /// State that is collected during a frame and then cleared.
229    pub this_frame: FrameState,
230
231    /// The final [`FrameState`] from last frame.
232    ///
233    /// Only read from.
234    pub prev_frame: FrameState,
235
236    /// Has this viewport been updated this frame?
237    pub used: bool,
238
239    /// State related to repaint scheduling.
240    repaint: ViewportRepaintInfo,
241
242    // ----------------------
243    // Updated at the start of the frame:
244    //
245    /// Which widgets are under the pointer?
246    pub hits: WidgetHits,
247
248    /// What widgets are being interacted with this frame?
249    ///
250    /// Based on the widgets from last frame, and input in this frame.
251    pub interact_widgets: InteractionSnapshot,
252
253    // ----------------------
254    // The output of a frame:
255    //
256    pub graphics: GraphicLayers,
257    // Most of the things in `PlatformOutput` are not actually viewport dependent.
258    pub output: PlatformOutput,
259    pub commands: Vec<ViewportCommand>,
260}
261
262/// What called [`Context::request_repaint`]?
263#[derive(Clone)]
264pub struct RepaintCause {
265    /// What file had the call that requested the repaint?
266    pub file: &'static str,
267
268    /// What line number of the call that requested the repaint?
269    pub line: u32,
270}
271
272impl std::fmt::Debug for RepaintCause {
273    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274        write!(f, "{}:{}", self.file, self.line)
275    }
276}
277
278impl RepaintCause {
279    /// Capture the file and line number of the call site.
280    #[allow(clippy::new_without_default)]
281    #[track_caller]
282    pub fn new() -> Self {
283        let caller = Location::caller();
284        Self {
285            file: caller.file(),
286            line: caller.line(),
287        }
288    }
289}
290
291impl std::fmt::Display for RepaintCause {
292    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
293        write!(f, "{}:{}", self.file, self.line)
294    }
295}
296
297/// Per-viewport state related to repaint scheduling.
298struct ViewportRepaintInfo {
299    /// Monotonically increasing counter.
300    frame_nr: u64,
301
302    /// The duration which the backend will poll for new events
303    /// before forcing another egui update, even if there's no new events.
304    ///
305    /// Also used to suppress multiple calls to the repaint callback during the same frame.
306    ///
307    /// This is also returned in [`crate::ViewportOutput`].
308    repaint_delay: Duration,
309
310    /// While positive, keep requesting repaints. Decrement at the start of each frame.
311    outstanding: u8,
312
313    /// What caused repaints during this frame?
314    causes: Vec<RepaintCause>,
315
316    /// What triggered a repaint the previous frame?
317    /// (i.e: why are we updating now?)
318    prev_causes: Vec<RepaintCause>,
319
320    /// What was the output of `repaint_delay` on the previous frame?
321    ///
322    /// If this was zero, we are repainting as quickly as possible
323    /// (as far as we know).
324    prev_frame_paint_delay: Duration,
325}
326
327impl Default for ViewportRepaintInfo {
328    fn default() -> Self {
329        Self {
330            frame_nr: 0,
331
332            // We haven't scheduled a repaint yet.
333            repaint_delay: Duration::MAX,
334
335            // Let's run a couple of frames at the start, because why not.
336            outstanding: 1,
337
338            causes: Default::default(),
339            prev_causes: Default::default(),
340
341            prev_frame_paint_delay: Duration::MAX,
342        }
343    }
344}
345
346impl ViewportRepaintInfo {
347    pub fn requested_immediate_repaint_prev_frame(&self) -> bool {
348        self.prev_frame_paint_delay == Duration::ZERO
349    }
350}
351
352// ----------------------------------------------------------------------------
353
354#[derive(Default)]
355struct ContextImpl {
356    /// Since we could have multiple viewports across multiple monitors with
357    /// different `pixels_per_point`, we need a `Fonts` instance for each unique
358    /// `pixels_per_point`.
359    /// This is because the `Fonts` depend on `pixels_per_point` for the font atlas
360    /// as well as kerning, font sizes, etc.
361    fonts: std::collections::BTreeMap<OrderedFloat<f32>, Fonts>,
362    font_definitions: FontDefinitions,
363
364    memory: Memory,
365    animation_manager: AnimationManager,
366
367    plugins: Plugins,
368
369    /// All viewports share the same texture manager and texture namespace.
370    ///
371    /// In all viewports, [`TextureId::default`] is special, and points to the font atlas.
372    /// The font-atlas texture _may_ be different across viewports, as they may have different
373    /// `pixels_per_point`, so we do special book-keeping for that.
374    /// See <https://github.com/emilk/egui/issues/3664>.
375    tex_manager: WrappedTextureManager,
376
377    /// Set during the frame, becomes active at the start of the next frame.
378    new_zoom_factor: Option<f32>,
379
380    os: OperatingSystem,
381
382    /// How deeply nested are we?
383    viewport_stack: Vec<ViewportIdPair>,
384
385    /// What is the last viewport rendered?
386    last_viewport: ViewportId,
387
388    paint_stats: PaintStats,
389
390    request_repaint_callback: Option<Box<dyn Fn(RequestRepaintInfo) + Send + Sync>>,
391
392    viewport_parents: ViewportIdMap<ViewportId>,
393    viewports: ViewportIdMap<ViewportState>,
394
395    embed_viewports: bool,
396
397    #[cfg(feature = "accesskit")]
398    is_accesskit_enabled: bool,
399    #[cfg(feature = "accesskit")]
400    accesskit_node_classes: accesskit::NodeClassSet,
401
402    loaders: Arc<Loaders>,
403}
404
405impl ContextImpl {
406    fn begin_frame_mut(&mut self, mut new_raw_input: RawInput) {
407        let viewport_id = new_raw_input.viewport_id;
408        let parent_id = new_raw_input
409            .viewports
410            .get(&viewport_id)
411            .and_then(|v| v.parent)
412            .unwrap_or_default();
413        let ids = ViewportIdPair::from_self_and_parent(viewport_id, parent_id);
414
415        let is_outermost_viewport = self.viewport_stack.is_empty(); // not necessarily root, just outermost immediate viewport
416        self.viewport_stack.push(ids);
417
418        self.begin_frame_repaint_logic(viewport_id);
419
420        let viewport = self.viewports.entry(viewport_id).or_default();
421
422        if is_outermost_viewport {
423            if let Some(new_zoom_factor) = self.new_zoom_factor.take() {
424                let ratio = self.memory.options.zoom_factor / new_zoom_factor;
425                self.memory.options.zoom_factor = new_zoom_factor;
426
427                let input = &viewport.input;
428                // This is a bit hacky, but is required to avoid jitter:
429                let mut rect = input.screen_rect;
430                rect.min = (ratio * rect.min.to_vec2()).to_pos2();
431                rect.max = (ratio * rect.max.to_vec2()).to_pos2();
432                new_raw_input.screen_rect = Some(rect);
433                // We should really scale everything else in the input too,
434                // but the `screen_rect` is the most important part.
435            }
436        }
437        let native_pixels_per_point = new_raw_input
438            .viewport()
439            .native_pixels_per_point
440            .unwrap_or(1.0);
441        let pixels_per_point = self.memory.options.zoom_factor * native_pixels_per_point;
442
443        let all_viewport_ids: ViewportIdSet = self.all_viewport_ids();
444
445        let viewport = self.viewports.entry(self.viewport_id()).or_default();
446
447        self.memory.begin_frame(&new_raw_input, &all_viewport_ids);
448
449        viewport.input = std::mem::take(&mut viewport.input).begin_frame(
450            new_raw_input,
451            viewport.repaint.requested_immediate_repaint_prev_frame(),
452            pixels_per_point,
453            &self.memory.options,
454        );
455
456        let screen_rect = viewport.input.screen_rect;
457
458        viewport.this_frame.begin_frame(screen_rect);
459
460        {
461            let area_order = self.memory.areas().order_map();
462
463            let mut layers: Vec<LayerId> = viewport.prev_frame.widgets.layer_ids().collect();
464
465            layers.sort_by(|a, b| {
466                if a.order == b.order {
467                    // Maybe both are windows, so respect area order:
468                    area_order.get(a).cmp(&area_order.get(b))
469                } else {
470                    // comparing e.g. background to tooltips
471                    a.order.cmp(&b.order)
472                }
473            });
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_frame.widgets,
480                    &layers,
481                    &self.memory.layer_transforms,
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_frame.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(screen_rect.left_top()),
503                pivot: Align2::LEFT_TOP,
504                size: Some(screen_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            crate::profile_scope!("accesskit");
513            use crate::frame_state::AccessKitFrameState;
514            let id = crate::accesskit_root_id();
515            let mut builder = accesskit::NodeBuilder::new(accesskit::Role::Window);
516            let pixels_per_point = viewport.input.pixels_per_point();
517            builder.set_transform(accesskit::Affine::scale(pixels_per_point.into()));
518            let mut node_builders = IdMap::default();
519            node_builders.insert(id, builder);
520            viewport.this_frame.accesskit_state = Some(AccessKitFrameState {
521                node_builders,
522                parent_stack: vec![id],
523            });
524        }
525
526        self.update_fonts_mut();
527    }
528
529    /// Load fonts unless already loaded.
530    fn update_fonts_mut(&mut self) {
531        crate::profile_function!();
532
533        let input = &self.viewport().input;
534        let pixels_per_point = input.pixels_per_point();
535        let max_texture_side = input.max_texture_side;
536
537        if let Some(font_definitions) = self.memory.new_font_definitions.take() {
538            // New font definition loaded, so we need to reload all fonts.
539            self.fonts.clear();
540            self.font_definitions = font_definitions;
541            #[cfg(feature = "log")]
542            log::debug!("Loading new font definitions");
543        }
544
545        let mut is_new = false;
546
547        let fonts = self
548            .fonts
549            .entry(pixels_per_point.into())
550            .or_insert_with(|| {
551                #[cfg(feature = "log")]
552                log::trace!("Creating new Fonts for pixels_per_point={pixels_per_point}");
553
554                is_new = true;
555                crate::profile_scope!("Fonts::new");
556                Fonts::new(
557                    pixels_per_point,
558                    max_texture_side,
559                    self.font_definitions.clone(),
560                )
561            });
562
563        {
564            crate::profile_scope!("Fonts::begin_frame");
565            fonts.begin_frame(pixels_per_point, max_texture_side);
566        }
567
568        if is_new && self.memory.options.preload_font_glyphs {
569            crate::profile_scope!("preload_font_glyphs");
570            // Preload the most common characters for the most common fonts.
571            // This is not very important to do, but may save a few GPU operations.
572            for font_id in self.memory.options.style.text_styles.values() {
573                fonts.lock().fonts.font(font_id).preload_common_characters();
574            }
575        }
576    }
577
578    #[cfg(feature = "accesskit")]
579    fn accesskit_node_builder(&mut self, id: Id) -> &mut accesskit::NodeBuilder {
580        let state = self.viewport().this_frame.accesskit_state.as_mut().unwrap();
581        let builders = &mut state.node_builders;
582        if let std::collections::hash_map::Entry::Vacant(entry) = builders.entry(id) {
583            entry.insert(Default::default());
584            let parent_id = state.parent_stack.last().unwrap();
585            let parent_builder = builders.get_mut(parent_id).unwrap();
586            parent_builder.push_child(id.accesskit_id());
587        }
588        builders.get_mut(&id).unwrap()
589    }
590
591    fn pixels_per_point(&mut self) -> f32 {
592        self.viewport().input.pixels_per_point
593    }
594
595    /// Return the `ViewportId` of the current viewport.
596    ///
597    /// For the root viewport this will return [`ViewportId::ROOT`].
598    pub(crate) fn viewport_id(&self) -> ViewportId {
599        self.viewport_stack.last().copied().unwrap_or_default().this
600    }
601
602    /// Return the `ViewportId` of his parent.
603    ///
604    /// For the root viewport this will return [`ViewportId::ROOT`].
605    pub(crate) fn parent_viewport_id(&self) -> ViewportId {
606        let viewport_id = self.viewport_id();
607        *self
608            .viewport_parents
609            .get(&viewport_id)
610            .unwrap_or(&ViewportId::ROOT)
611    }
612
613    fn all_viewport_ids(&self) -> ViewportIdSet {
614        self.viewports
615            .keys()
616            .copied()
617            .chain([ViewportId::ROOT])
618            .collect()
619    }
620
621    /// The current active viewport
622    pub(crate) fn viewport(&mut self) -> &mut ViewportState {
623        self.viewports.entry(self.viewport_id()).or_default()
624    }
625
626    fn viewport_for(&mut self, viewport_id: ViewportId) -> &mut ViewportState {
627        self.viewports.entry(viewport_id).or_default()
628    }
629}
630
631// ----------------------------------------------------------------------------
632
633/// Your handle to egui.
634///
635/// This is the first thing you need when working with egui.
636/// Contains the [`InputState`], [`Memory`], [`PlatformOutput`], and more.
637///
638/// [`Context`] is cheap to clone, and any clones refers to the same mutable data
639/// ([`Context`] uses refcounting internally).
640///
641/// ## Locking
642/// All methods are marked `&self`; [`Context`] has interior mutability protected by an [`RwLock`].
643///
644/// To access parts of a `Context` you need to use some of the helper functions that take closures:
645///
646/// ```
647/// # let ctx = egui::Context::default();
648/// if ctx.input(|i| i.key_pressed(egui::Key::A)) {
649///     ctx.output_mut(|o| o.copied_text = "Hello!".to_string());
650/// }
651/// ```
652///
653/// Within such a closure you may NOT recursively lock the same [`Context`], as that can lead to a deadlock.
654/// Therefore it is important that any lock of [`Context`] is short-lived.
655///
656/// These are effectively transactional accesses.
657///
658/// [`Ui`] has many of the same accessor functions, and the same applies there.
659///
660/// ## Example:
661///
662/// ``` no_run
663/// # fn handle_platform_output(_: egui::PlatformOutput) {}
664/// # fn paint(textures_delta: egui::TexturesDelta, _: Vec<egui::ClippedPrimitive>) {}
665/// let mut ctx = egui::Context::default();
666///
667/// // Game loop:
668/// loop {
669///     let raw_input = egui::RawInput::default();
670///     let full_output = ctx.run(raw_input, |ctx| {
671///         egui::CentralPanel::default().show(&ctx, |ui| {
672///             ui.label("Hello world!");
673///             if ui.button("Click me").clicked() {
674///                 // take some action here
675///             }
676///         });
677///     });
678///     handle_platform_output(full_output.platform_output);
679///     let clipped_primitives = ctx.tessellate(full_output.shapes, full_output.pixels_per_point);
680///     paint(full_output.textures_delta, clipped_primitives);
681/// }
682/// ```
683#[derive(Clone)]
684pub struct Context(Arc<RwLock<ContextImpl>>);
685
686impl std::fmt::Debug for Context {
687    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
688        f.debug_struct("Context").finish_non_exhaustive()
689    }
690}
691
692impl std::cmp::PartialEq for Context {
693    fn eq(&self, other: &Self) -> bool {
694        Arc::ptr_eq(&self.0, &other.0)
695    }
696}
697
698impl Default for Context {
699    fn default() -> Self {
700        let ctx_impl = ContextImpl {
701            embed_viewports: true,
702            ..Default::default()
703        };
704        let ctx = Self(Arc::new(RwLock::new(ctx_impl)));
705
706        // Register built-in plugins:
707        crate::debug_text::register(&ctx);
708        crate::text_selection::LabelSelectionState::register(&ctx);
709        crate::DragAndDrop::register(&ctx);
710
711        ctx
712    }
713}
714
715impl Context {
716    /// Do read-only (shared access) transaction on Context
717    fn read<R>(&self, reader: impl FnOnce(&ContextImpl) -> R) -> R {
718        reader(&self.0.read())
719    }
720
721    /// Do read-write (exclusive access) transaction on Context
722    fn write<R>(&self, writer: impl FnOnce(&mut ContextImpl) -> R) -> R {
723        writer(&mut self.0.write())
724    }
725
726    /// Run the ui code for one frame.
727    ///
728    /// Put your widgets into a [`SidePanel`], [`TopBottomPanel`], [`CentralPanel`], [`Window`] or [`Area`].
729    ///
730    /// This will modify the internal reference to point to a new generation of [`Context`].
731    /// Any old clones of this [`Context`] will refer to the old [`Context`], which will not get new input.
732    ///
733    /// You can alternatively run [`Self::begin_frame`] and [`Context::end_frame`].
734    ///
735    /// ```
736    /// // One egui context that you keep reusing:
737    /// let mut ctx = egui::Context::default();
738    ///
739    /// // Each frame:
740    /// let input = egui::RawInput::default();
741    /// let full_output = ctx.run(input, |ctx| {
742    ///     egui::CentralPanel::default().show(&ctx, |ui| {
743    ///         ui.label("Hello egui!");
744    ///     });
745    /// });
746    /// // handle full_output
747    /// ```
748    #[must_use]
749    pub fn run(&self, new_input: RawInput, run_ui: impl FnOnce(&Self)) -> FullOutput {
750        crate::profile_function!();
751
752        self.begin_frame(new_input);
753        run_ui(self);
754        self.end_frame()
755    }
756
757    /// An alternative to calling [`Self::run`].
758    ///
759    /// ```
760    /// // One egui context that you keep reusing:
761    /// let mut ctx = egui::Context::default();
762    ///
763    /// // Each frame:
764    /// let input = egui::RawInput::default();
765    /// ctx.begin_frame(input);
766    ///
767    /// egui::CentralPanel::default().show(&ctx, |ui| {
768    ///     ui.label("Hello egui!");
769    /// });
770    ///
771    /// let full_output = ctx.end_frame();
772    /// // handle full_output
773    /// ```
774    pub fn begin_frame(&self, new_input: RawInput) {
775        crate::profile_function!();
776
777        self.write(|ctx| ctx.begin_frame_mut(new_input));
778
779        // Plugs run just after the frame has started:
780        self.read(|ctx| ctx.plugins.clone()).on_begin_frame(self);
781    }
782}
783
784/// ## Borrows parts of [`Context`]
785/// These functions all lock the [`Context`].
786/// Please see the documentation of [`Context`] for how locking works!
787impl Context {
788    /// Read-only access to [`InputState`].
789    ///
790    /// Note that this locks the [`Context`].
791    ///
792    /// ```
793    /// # let mut ctx = egui::Context::default();
794    /// ctx.input(|i| {
795    ///     // ⚠️ Using `ctx` (even from other `Arc` reference) again here will lead to a deadlock!
796    /// });
797    ///
798    /// if let Some(pos) = ctx.input(|i| i.pointer.hover_pos()) {
799    ///     // This is fine!
800    /// }
801    /// ```
802    #[inline]
803    pub fn input<R>(&self, reader: impl FnOnce(&InputState) -> R) -> R {
804        self.write(move |ctx| reader(&ctx.viewport().input))
805    }
806
807    /// This will create a `InputState::default()` if there is no input state for that viewport
808    #[inline]
809    pub fn input_for<R>(&self, id: ViewportId, reader: impl FnOnce(&InputState) -> R) -> R {
810        self.write(move |ctx| reader(&ctx.viewport_for(id).input))
811    }
812
813    /// Read-write access to [`InputState`].
814    #[inline]
815    pub fn input_mut<R>(&self, writer: impl FnOnce(&mut InputState) -> R) -> R {
816        self.input_mut_for(self.viewport_id(), writer)
817    }
818
819    /// This will create a `InputState::default()` if there is no input state for that viewport
820    #[inline]
821    pub fn input_mut_for<R>(&self, id: ViewportId, writer: impl FnOnce(&mut InputState) -> R) -> R {
822        self.write(move |ctx| writer(&mut ctx.viewport_for(id).input))
823    }
824
825    /// Read-only access to [`Memory`].
826    #[inline]
827    pub fn memory<R>(&self, reader: impl FnOnce(&Memory) -> R) -> R {
828        self.read(move |ctx| reader(&ctx.memory))
829    }
830
831    /// Read-write access to [`Memory`].
832    #[inline]
833    pub fn memory_mut<R>(&self, writer: impl FnOnce(&mut Memory) -> R) -> R {
834        self.write(move |ctx| writer(&mut ctx.memory))
835    }
836
837    /// Read-only access to [`IdTypeMap`], which stores superficial widget state.
838    #[inline]
839    pub fn data<R>(&self, reader: impl FnOnce(&IdTypeMap) -> R) -> R {
840        self.read(move |ctx| reader(&ctx.memory.data))
841    }
842
843    /// Read-write access to [`IdTypeMap`], which stores superficial widget state.
844    #[inline]
845    pub fn data_mut<R>(&self, writer: impl FnOnce(&mut IdTypeMap) -> R) -> R {
846        self.write(move |ctx| writer(&mut ctx.memory.data))
847    }
848
849    /// Read-write access to [`GraphicLayers`], where painted [`crate::Shape`]s are written to.
850    #[inline]
851    pub fn graphics_mut<R>(&self, writer: impl FnOnce(&mut GraphicLayers) -> R) -> R {
852        self.write(move |ctx| writer(&mut ctx.viewport().graphics))
853    }
854
855    /// Read-only access to [`GraphicLayers`], where painted [`crate::Shape`]s are written to.
856    #[inline]
857    pub fn graphics<R>(&self, reader: impl FnOnce(&GraphicLayers) -> R) -> R {
858        self.write(move |ctx| reader(&ctx.viewport().graphics))
859    }
860
861    /// Read-only access to [`PlatformOutput`].
862    ///
863    /// This is what egui outputs each frame.
864    ///
865    /// ```
866    /// # let mut ctx = egui::Context::default();
867    /// ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Progress);
868    /// ```
869    #[inline]
870    pub fn output<R>(&self, reader: impl FnOnce(&PlatformOutput) -> R) -> R {
871        self.write(move |ctx| reader(&ctx.viewport().output))
872    }
873
874    /// Read-write access to [`PlatformOutput`].
875    #[inline]
876    pub fn output_mut<R>(&self, writer: impl FnOnce(&mut PlatformOutput) -> R) -> R {
877        self.write(move |ctx| writer(&mut ctx.viewport().output))
878    }
879
880    /// Read-only access to [`FrameState`].
881    ///
882    /// This is only valid between [`Context::begin_frame`] and [`Context::end_frame`].
883    #[inline]
884    pub(crate) fn frame_state<R>(&self, reader: impl FnOnce(&FrameState) -> R) -> R {
885        self.write(move |ctx| reader(&ctx.viewport().this_frame))
886    }
887
888    /// Read-write access to [`FrameState`].
889    ///
890    /// This is only valid between [`Context::begin_frame`] and [`Context::end_frame`].
891    #[inline]
892    pub(crate) fn frame_state_mut<R>(&self, writer: impl FnOnce(&mut FrameState) -> R) -> R {
893        self.write(move |ctx| writer(&mut ctx.viewport().this_frame))
894    }
895
896    /// Read-only access to the [`FrameState`] from the previous frame.
897    ///
898    /// This is swapped at the end of each frame.
899    #[inline]
900    pub(crate) fn prev_frame_state<R>(&self, reader: impl FnOnce(&FrameState) -> R) -> R {
901        self.write(move |ctx| reader(&ctx.viewport().prev_frame))
902    }
903
904    /// Read-only access to [`Fonts`].
905    ///
906    /// Not valid until first call to [`Context::run()`].
907    /// That's because since we don't know the proper `pixels_per_point` until then.
908    #[inline]
909    pub fn fonts<R>(&self, reader: impl FnOnce(&Fonts) -> R) -> R {
910        self.write(move |ctx| {
911            let pixels_per_point = ctx.pixels_per_point();
912            reader(
913                ctx.fonts
914                    .get(&pixels_per_point.into())
915                    .expect("No fonts available until first call to Context::run()"),
916            )
917        })
918    }
919
920    /// Read-only access to [`Options`].
921    #[inline]
922    pub fn options<R>(&self, reader: impl FnOnce(&Options) -> R) -> R {
923        self.read(move |ctx| reader(&ctx.memory.options))
924    }
925
926    /// Read-write access to [`Options`].
927    #[inline]
928    pub fn options_mut<R>(&self, writer: impl FnOnce(&mut Options) -> R) -> R {
929        self.write(move |ctx| writer(&mut ctx.memory.options))
930    }
931
932    /// Read-only access to [`TessellationOptions`].
933    #[inline]
934    pub fn tessellation_options<R>(&self, reader: impl FnOnce(&TessellationOptions) -> R) -> R {
935        self.read(move |ctx| reader(&ctx.memory.options.tessellation_options))
936    }
937
938    /// Read-write access to [`TessellationOptions`].
939    #[inline]
940    pub fn tessellation_options_mut<R>(
941        &self,
942        writer: impl FnOnce(&mut TessellationOptions) -> R,
943    ) -> R {
944        self.write(move |ctx| writer(&mut ctx.memory.options.tessellation_options))
945    }
946
947    /// If the given [`Id`] has been used previously the same frame at different position,
948    /// then an error will be printed on screen.
949    ///
950    /// This function is already called for all widgets that do any interaction,
951    /// but you can call this from widgets that store state but that does not interact.
952    ///
953    /// The given [`Rect`] should be approximately where the widget will be.
954    /// The most important thing is that [`Rect::min`] is approximately correct,
955    /// because that's where the warning will be painted. If you don't know what size to pick, just pick [`Vec2::ZERO`].
956    pub fn check_for_id_clash(&self, id: Id, new_rect: Rect, what: &str) {
957        let prev_rect = self.frame_state_mut(move |state| state.used_ids.insert(id, new_rect));
958
959        if !self.options(|opt| opt.warn_on_id_clash) {
960            return;
961        }
962
963        let Some(prev_rect) = prev_rect else { return };
964
965        // it is ok to reuse the same ID for e.g. a frame around a widget,
966        // or to check for interaction with the same widget twice:
967        let is_same_rect = prev_rect.expand(0.1).contains_rect(new_rect)
968            || new_rect.expand(0.1).contains_rect(prev_rect);
969        if is_same_rect {
970            return;
971        }
972
973        let show_error = |widget_rect: Rect, text: String| {
974            let screen_rect = self.screen_rect();
975
976            let text = format!("🔥 {text}");
977            let color = self.style().visuals.error_fg_color;
978            let painter = self.debug_painter();
979            painter.rect_stroke(widget_rect, 0.0, (1.0, color));
980
981            let below = widget_rect.bottom() + 32.0 < screen_rect.bottom();
982
983            let text_rect = if below {
984                painter.debug_text(
985                    widget_rect.left_bottom() + vec2(0.0, 2.0),
986                    Align2::LEFT_TOP,
987                    color,
988                    text,
989                )
990            } else {
991                painter.debug_text(
992                    widget_rect.left_top() - vec2(0.0, 2.0),
993                    Align2::LEFT_BOTTOM,
994                    color,
995                    text,
996                )
997            };
998
999            if let Some(pointer_pos) = self.pointer_hover_pos() {
1000                if text_rect.contains(pointer_pos) {
1001                    let tooltip_pos = if below {
1002                        text_rect.left_bottom() + vec2(2.0, 4.0)
1003                    } else {
1004                        text_rect.left_top() + vec2(2.0, -4.0)
1005                    };
1006
1007                    painter.error(
1008                        tooltip_pos,
1009                        format!("Widget is {} this text.\n\n\
1010                             ID clashes happens when things like Windows or CollapsingHeaders share names,\n\
1011                             or when things like Plot and Grid:s aren't given unique id_source:s.\n\n\
1012                             Sometimes the solution is to use ui.push_id.",
1013                         if below { "above" } else { "below" })
1014                    );
1015                }
1016            }
1017        };
1018
1019        let id_str = id.short_debug_format();
1020
1021        if prev_rect.min.distance(new_rect.min) < 4.0 {
1022            show_error(new_rect, format!("Double use of {what} ID {id_str}"));
1023        } else {
1024            show_error(prev_rect, format!("First use of {what} ID {id_str}"));
1025            show_error(new_rect, format!("Second use of {what} ID {id_str}"));
1026        }
1027    }
1028
1029    // ---------------------------------------------------------------------
1030
1031    /// Create a widget and check for interaction.
1032    ///
1033    /// If this is not called, the widget doesn't exist.
1034    ///
1035    /// You should use [`Ui::interact`] instead.
1036    ///
1037    /// If the widget already exists, its state (sense, Rect, etc) will be updated.
1038    #[allow(clippy::too_many_arguments)]
1039    pub(crate) fn create_widget(&self, w: WidgetRect) -> Response {
1040        // Remember this widget
1041        self.write(|ctx| {
1042            let viewport = ctx.viewport();
1043
1044            // We add all widgets here, even non-interactive ones,
1045            // because we need this list not only for checking for blocking widgets,
1046            // but also to know when we have reached the widget we are checking for cover.
1047            viewport.this_frame.widgets.insert(w.layer_id, w);
1048
1049            if w.sense.focusable {
1050                ctx.memory.interested_in_focus(w.id);
1051            }
1052        });
1053
1054        if !w.enabled || !w.sense.focusable || !w.layer_id.allow_interaction() {
1055            // Not interested or allowed input:
1056            self.memory_mut(|mem| mem.surrender_focus(w.id));
1057        }
1058
1059        if w.sense.interactive() || w.sense.focusable {
1060            self.check_for_id_clash(w.id, w.rect, "widget");
1061        }
1062
1063        #[allow(clippy::let_and_return)]
1064        let res = self.get_response(w);
1065
1066        #[cfg(feature = "accesskit")]
1067        if w.sense.focusable {
1068            // Make sure anything that can receive focus has an AccessKit node.
1069            // TODO(mwcampbell): For nodes that are filled from widget info,
1070            // some information is written to the node twice.
1071            self.accesskit_node_builder(w.id, |builder| res.fill_accesskit_node_common(builder));
1072        }
1073
1074        res
1075    }
1076
1077    /// Read the response of some widget, which may be called _before_ creating the widget (!).
1078    ///
1079    /// This is because widget interaction happens at the start of the frame, using the previous frame's widgets.
1080    ///
1081    /// If the widget was not visible the previous frame (or this frame), this will return `None`.
1082    pub fn read_response(&self, id: Id) -> Option<Response> {
1083        self.write(|ctx| {
1084            let viewport = ctx.viewport();
1085            viewport
1086                .this_frame
1087                .widgets
1088                .get(id)
1089                .or_else(|| viewport.prev_frame.widgets.get(id))
1090                .copied()
1091        })
1092        .map(|widget_rect| self.get_response(widget_rect))
1093    }
1094
1095    /// Returns `true` if the widget with the given `Id` contains the pointer.
1096    #[deprecated = "Use Response.contains_pointer or Context::read_response instead"]
1097    pub fn widget_contains_pointer(&self, id: Id) -> bool {
1098        self.read_response(id)
1099            .map_or(false, |response| response.contains_pointer)
1100    }
1101
1102    /// Do all interaction for an existing widget, without (re-)registering it.
1103    fn get_response(&self, widget_rect: WidgetRect) -> Response {
1104        let WidgetRect {
1105            id,
1106            layer_id,
1107            rect,
1108            interact_rect,
1109            sense,
1110            enabled,
1111        } = widget_rect;
1112
1113        // previous frame + "highlight next frame" == "highlight this frame"
1114        let highlighted = self.prev_frame_state(|fs| fs.highlight_next_frame.contains(&id));
1115
1116        let mut res = Response {
1117            ctx: self.clone(),
1118            layer_id,
1119            id,
1120            rect,
1121            interact_rect,
1122            sense,
1123            enabled,
1124            contains_pointer: false,
1125            hovered: false,
1126            highlighted,
1127            clicked: false,
1128            fake_primary_click: false,
1129            long_touched: false,
1130            drag_started: false,
1131            dragged: false,
1132            drag_stopped: false,
1133            is_pointer_button_down_on: false,
1134            interact_pointer_pos: None,
1135            changed: false,
1136        };
1137
1138        self.write(|ctx| {
1139            let viewport = ctx.viewports.entry(ctx.viewport_id()).or_default();
1140
1141            res.contains_pointer = viewport.interact_widgets.contains_pointer.contains(&id);
1142
1143            let input = &viewport.input;
1144            let memory = &mut ctx.memory;
1145
1146            if enabled
1147                && sense.click
1148                && memory.has_focus(id)
1149                && (input.key_pressed(Key::Space) || input.key_pressed(Key::Enter))
1150            {
1151                // Space/enter works like a primary click for e.g. selected buttons
1152                res.fake_primary_click = true;
1153            }
1154
1155            #[cfg(feature = "accesskit")]
1156            if enabled
1157                && sense.click
1158                && input.has_accesskit_action_request(id, accesskit::Action::Default)
1159            {
1160                res.fake_primary_click = true;
1161            }
1162
1163            if enabled && sense.click && Some(id) == viewport.interact_widgets.long_touched {
1164                res.long_touched = true;
1165            }
1166
1167            let interaction = memory.interaction();
1168
1169            res.is_pointer_button_down_on = interaction.potential_click_id == Some(id)
1170                || interaction.potential_drag_id == Some(id);
1171
1172            if res.enabled {
1173                res.hovered = viewport.interact_widgets.hovered.contains(&id);
1174                res.dragged = Some(id) == viewport.interact_widgets.dragged;
1175                res.drag_started = Some(id) == viewport.interact_widgets.drag_started;
1176                res.drag_stopped = Some(id) == viewport.interact_widgets.drag_stopped;
1177            }
1178
1179            let clicked = Some(id) == viewport.interact_widgets.clicked;
1180            let mut any_press = false;
1181
1182            for pointer_event in &input.pointer.pointer_events {
1183                match pointer_event {
1184                    PointerEvent::Moved(_) => {}
1185                    PointerEvent::Pressed { .. } => {
1186                        any_press = true;
1187                    }
1188                    PointerEvent::Released { click, .. } => {
1189                        if enabled && sense.click && clicked && click.is_some() {
1190                            res.clicked = true;
1191                        }
1192
1193                        res.is_pointer_button_down_on = false;
1194                        res.dragged = false;
1195                    }
1196                }
1197            }
1198
1199            // is_pointer_button_down_on is false when released, but we want interact_pointer_pos
1200            // to still work.
1201            let is_interacted_with =
1202                res.is_pointer_button_down_on || res.long_touched || clicked || res.drag_stopped;
1203            if is_interacted_with {
1204                res.interact_pointer_pos = input.pointer.interact_pos();
1205                if let (Some(transform), Some(pos)) = (
1206                    memory.layer_transforms.get(&res.layer_id),
1207                    &mut res.interact_pointer_pos,
1208                ) {
1209                    *pos = transform.inverse() * *pos;
1210                }
1211            }
1212
1213            if input.pointer.any_down() && !is_interacted_with {
1214                // We don't hover widgets while interacting with *other* widgets:
1215                res.hovered = false;
1216            }
1217
1218            let pointer_pressed_elsewhere = any_press && !res.hovered;
1219            if pointer_pressed_elsewhere && memory.has_focus(id) {
1220                memory.surrender_focus(id);
1221            }
1222        });
1223
1224        res
1225    }
1226
1227    /// This is called by [`Response::widget_info`], but can also be called directly.
1228    ///
1229    /// With some debug flags it will store the widget info in [`WidgetRects`] for later display.
1230    #[inline]
1231    pub fn register_widget_info(&self, id: Id, make_info: impl Fn() -> crate::WidgetInfo) {
1232        #[cfg(debug_assertions)]
1233        self.write(|ctx| {
1234            if ctx.memory.options.style.debug.show_interactive_widgets {
1235                ctx.viewport().this_frame.widgets.set_info(id, make_info());
1236            }
1237        });
1238
1239        #[cfg(not(debug_assertions))]
1240        {
1241            _ = (self, id, make_info);
1242        }
1243    }
1244
1245    /// Get a full-screen painter for a new or existing layer
1246    pub fn layer_painter(&self, layer_id: LayerId) -> Painter {
1247        let screen_rect = self.screen_rect();
1248        Painter::new(self.clone(), layer_id, screen_rect)
1249    }
1250
1251    /// Paint on top of everything else
1252    pub fn debug_painter(&self) -> Painter {
1253        Self::layer_painter(self, LayerId::debug())
1254    }
1255
1256    /// Print this text next to the cursor at the end of the frame.
1257    ///
1258    /// If you call this multiple times, the text will be appended.
1259    ///
1260    /// This only works if compiled with `debug_assertions`.
1261    ///
1262    /// ```
1263    /// # let ctx = egui::Context::default();
1264    /// # let state = true;
1265    /// ctx.debug_text(format!("State: {state:?}"));
1266    /// ```
1267    ///
1268    /// This is just a convenience for calling [`crate::debug_text::print`].
1269    #[track_caller]
1270    pub fn debug_text(&self, text: impl Into<WidgetText>) {
1271        crate::debug_text::print(self, text);
1272    }
1273
1274    /// What operating system are we running on?
1275    ///
1276    /// When compiling natively, this is
1277    /// figured out from the `target_os`.
1278    ///
1279    /// For web, this can be figured out from the user-agent,
1280    /// and is done so by [`eframe`](https://github.com/emilk/egui/tree/master/crates/eframe).
1281    pub fn os(&self) -> OperatingSystem {
1282        self.read(|ctx| ctx.os)
1283    }
1284
1285    /// Set the operating system we are running on.
1286    ///
1287    /// If you are writing wasm-based integration for egui you
1288    /// may want to set this based on e.g. the user-agent.
1289    pub fn set_os(&self, os: OperatingSystem) {
1290        self.write(|ctx| ctx.os = os);
1291    }
1292
1293    /// Set the cursor icon.
1294    ///
1295    /// Equivalent to:
1296    /// ```
1297    /// # let ctx = egui::Context::default();
1298    /// ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::PointingHand);
1299    /// ```
1300    pub fn set_cursor_icon(&self, cursor_icon: CursorIcon) {
1301        self.output_mut(|o| o.cursor_icon = cursor_icon);
1302    }
1303
1304    /// Open an URL in a browser.
1305    ///
1306    /// Equivalent to:
1307    /// ```
1308    /// # let ctx = egui::Context::default();
1309    /// # let open_url = egui::OpenUrl::same_tab("http://www.example.com");
1310    /// ctx.output_mut(|o| o.open_url = Some(open_url));
1311    /// ```
1312    pub fn open_url(&self, open_url: crate::OpenUrl) {
1313        self.output_mut(|o| o.open_url = Some(open_url));
1314    }
1315
1316    /// Copy the given text to the system clipboard.
1317    ///
1318    /// Empty strings are ignored.
1319    ///
1320    /// Equivalent to:
1321    /// ```
1322    /// # let ctx = egui::Context::default();
1323    /// ctx.output_mut(|o| o.copied_text = "Copy this".to_owned());
1324    /// ```
1325    pub fn copy_text(&self, text: String) {
1326        self.output_mut(|o| o.copied_text = text);
1327    }
1328
1329    /// Format the given shortcut in a human-readable way (e.g. `Ctrl+Shift+X`).
1330    ///
1331    /// Can be used to get the text for [`Button::shortcut_text`].
1332    pub fn format_shortcut(&self, shortcut: &KeyboardShortcut) -> String {
1333        let os = self.os();
1334
1335        let is_mac = matches!(os, OperatingSystem::Mac | OperatingSystem::IOS);
1336
1337        let can_show_symbols = || {
1338            let ModifierNames {
1339                alt,
1340                ctrl,
1341                shift,
1342                mac_cmd,
1343                ..
1344            } = ModifierNames::SYMBOLS;
1345
1346            let font_id = TextStyle::Body.resolve(&self.style());
1347            self.fonts(|f| {
1348                let mut lock = f.lock();
1349                let font = lock.fonts.font(&font_id);
1350                font.has_glyphs(alt)
1351                    && font.has_glyphs(ctrl)
1352                    && font.has_glyphs(shift)
1353                    && font.has_glyphs(mac_cmd)
1354            })
1355        };
1356
1357        if is_mac && can_show_symbols() {
1358            shortcut.format(&ModifierNames::SYMBOLS, is_mac)
1359        } else {
1360            shortcut.format(&ModifierNames::NAMES, is_mac)
1361        }
1362    }
1363
1364    /// The current frame number for the current viewport.
1365    ///
1366    /// Starts at zero, and is incremented at the end of [`Self::run`] or by [`Self::end_frame`].
1367    ///
1368    /// Between calls to [`Self::run`], this is the frame number of the coming frame.
1369    pub fn frame_nr(&self) -> u64 {
1370        self.frame_nr_for(self.viewport_id())
1371    }
1372
1373    /// The current frame number.
1374    ///
1375    /// Starts at zero, and is incremented at the end of [`Self::run`] or by [`Self::end_frame`].
1376    ///
1377    /// Between calls to [`Self::run`], this is the frame number of the coming frame.
1378    pub fn frame_nr_for(&self, id: ViewportId) -> u64 {
1379        self.read(|ctx| ctx.viewports.get(&id).map_or(0, |v| v.repaint.frame_nr))
1380    }
1381
1382    /// Call this if there is need to repaint the UI, i.e. if you are showing an animation.
1383    ///
1384    /// If this is called at least once in a frame, then there will be another frame right after this.
1385    /// Call as many times as you wish, only one repaint will be issued.
1386    ///
1387    /// To request repaint with a delay, use [`Self::request_repaint_after`].
1388    ///
1389    /// If called from outside the UI thread, the UI thread will wake up and run,
1390    /// provided the egui integration has set that up via [`Self::set_request_repaint_callback`]
1391    /// (this will work on `eframe`).
1392    ///
1393    /// This will repaint the current viewport.
1394    #[track_caller]
1395    pub fn request_repaint(&self) {
1396        self.request_repaint_of(self.viewport_id());
1397    }
1398
1399    /// Call this if there is need to repaint the UI, i.e. if you are showing an animation.
1400    ///
1401    /// If this is called at least once in a frame, then there will be another frame right after this.
1402    /// Call as many times as you wish, only one repaint will be issued.
1403    ///
1404    /// To request repaint with a delay, use [`Self::request_repaint_after_for`].
1405    ///
1406    /// If called from outside the UI thread, the UI thread will wake up and run,
1407    /// provided the egui integration has set that up via [`Self::set_request_repaint_callback`]
1408    /// (this will work on `eframe`).
1409    ///
1410    /// This will repaint the specified viewport.
1411    #[track_caller]
1412    pub fn request_repaint_of(&self, id: ViewportId) {
1413        let cause = RepaintCause::new();
1414        self.write(|ctx| ctx.request_repaint(id, cause));
1415    }
1416
1417    /// Request repaint after at most the specified duration elapses.
1418    ///
1419    /// The backend can chose to repaint sooner, for instance if some other code called
1420    /// this method with a lower duration, or if new events arrived.
1421    ///
1422    /// The function can be multiple times, but only the *smallest* duration will be considered.
1423    /// So, if the function is called two times with `1 second` and `2 seconds`, egui will repaint
1424    /// after `1 second`
1425    ///
1426    /// This is primarily useful for applications who would like to save battery by avoiding wasted
1427    /// redraws when the app is not in focus. But sometimes the GUI of the app might become stale
1428    /// and outdated if it is not updated for too long.
1429    ///
1430    /// Let's say, something like a stopwatch widget that displays the time in seconds. You would waste
1431    /// resources repainting multiple times within the same second (when you have no input),
1432    /// just calculate the difference of duration between current time and next second change,
1433    /// and call this function, to make sure that you are displaying the latest updated time, but
1434    /// not wasting resources on needless repaints within the same second.
1435    ///
1436    /// ### Quirk:
1437    /// Duration begins at the next frame. Let's say for example that it's a very inefficient app
1438    /// and takes 500 milliseconds per frame at 2 fps. The widget / user might want a repaint in
1439    /// next 500 milliseconds. Now, app takes 1000 ms per frame (1 fps) because the backend event
1440    /// timeout takes 500 milliseconds AFTER the vsync swap buffer.
1441    /// So, it's not that we are requesting repaint within X duration. We are rather timing out
1442    /// during app idle time where we are not receiving any new input events.
1443    ///
1444    /// This repaints the current viewport
1445    #[track_caller]
1446    pub fn request_repaint_after(&self, duration: Duration) {
1447        self.request_repaint_after_for(duration, self.viewport_id());
1448    }
1449
1450    /// Repaint after this many seconds.
1451    ///
1452    /// See [`Self::request_repaint_after`] for details.
1453    #[track_caller]
1454    pub fn request_repaint_after_secs(&self, seconds: f32) {
1455        if let Ok(duration) = std::time::Duration::try_from_secs_f32(seconds) {
1456            self.request_repaint_after(duration);
1457        }
1458    }
1459
1460    /// Request repaint after at most the specified duration elapses.
1461    ///
1462    /// The backend can chose to repaint sooner, for instance if some other code called
1463    /// this method with a lower duration, or if new events arrived.
1464    ///
1465    /// The function can be multiple times, but only the *smallest* duration will be considered.
1466    /// So, if the function is called two times with `1 second` and `2 seconds`, egui will repaint
1467    /// after `1 second`
1468    ///
1469    /// This is primarily useful for applications who would like to save battery by avoiding wasted
1470    /// redraws when the app is not in focus. But sometimes the GUI of the app might become stale
1471    /// and outdated if it is not updated for too long.
1472    ///
1473    /// Let's say, something like a stopwatch widget that displays the time in seconds. You would waste
1474    /// resources repainting multiple times within the same second (when you have no input),
1475    /// just calculate the difference of duration between current time and next second change,
1476    /// and call this function, to make sure that you are displaying the latest updated time, but
1477    /// not wasting resources on needless repaints within the same second.
1478    ///
1479    /// ### Quirk:
1480    /// Duration begins at the next frame. Let's say for example that it's a very inefficient app
1481    /// and takes 500 milliseconds per frame at 2 fps. The widget / user might want a repaint in
1482    /// next 500 milliseconds. Now, app takes 1000 ms per frame (1 fps) because the backend event
1483    /// timeout takes 500 milliseconds AFTER the vsync swap buffer.
1484    /// So, it's not that we are requesting repaint within X duration. We are rather timing out
1485    /// during app idle time where we are not receiving any new input events.
1486    ///
1487    /// This repaints the specified viewport
1488    #[track_caller]
1489    pub fn request_repaint_after_for(&self, duration: Duration, id: ViewportId) {
1490        let cause = RepaintCause::new();
1491        self.write(|ctx| ctx.request_repaint_after(duration, id, cause));
1492    }
1493
1494    /// Was a repaint requested last frame for the current viewport?
1495    #[must_use]
1496    pub fn requested_repaint_last_frame(&self) -> bool {
1497        self.requested_repaint_last_frame_for(&self.viewport_id())
1498    }
1499
1500    /// Was a repaint requested last frame for the given viewport?
1501    #[must_use]
1502    pub fn requested_repaint_last_frame_for(&self, viewport_id: &ViewportId) -> bool {
1503        self.read(|ctx| ctx.requested_immediate_repaint_prev_frame(viewport_id))
1504    }
1505
1506    /// Has a repaint been requested for the current viewport?
1507    #[must_use]
1508    pub fn has_requested_repaint(&self) -> bool {
1509        self.has_requested_repaint_for(&self.viewport_id())
1510    }
1511
1512    /// Has a repaint been requested for the given viewport?
1513    #[must_use]
1514    pub fn has_requested_repaint_for(&self, viewport_id: &ViewportId) -> bool {
1515        self.read(|ctx| ctx.has_requested_repaint(viewport_id))
1516    }
1517
1518    /// Why are we repainting?
1519    ///
1520    /// This can be helpful in debugging why egui is constantly repainting.
1521    pub fn repaint_causes(&self) -> Vec<RepaintCause> {
1522        self.read(|ctx| {
1523            ctx.viewports
1524                .get(&ctx.viewport_id())
1525                .map(|v| v.repaint.prev_causes.clone())
1526        })
1527        .unwrap_or_default()
1528    }
1529
1530    /// For integrations: this callback will be called when an egui user calls [`Self::request_repaint`] or [`Self::request_repaint_after`].
1531    ///
1532    /// This lets you wake up a sleeping UI thread.
1533    ///
1534    /// Note that only one callback can be set. Any new call overrides the previous callback.
1535    pub fn set_request_repaint_callback(
1536        &self,
1537        callback: impl Fn(RequestRepaintInfo) + Send + Sync + 'static,
1538    ) {
1539        let callback = Box::new(callback);
1540        self.write(|ctx| ctx.request_repaint_callback = Some(callback));
1541    }
1542}
1543
1544/// Callbacks
1545impl Context {
1546    /// Call the given callback at the start of each frame
1547    /// of each viewport.
1548    ///
1549    /// This can be used for egui _plugins_.
1550    /// See [`crate::debug_text`] for an example.
1551    pub fn on_begin_frame(&self, debug_name: &'static str, cb: ContextCallback) {
1552        let named_cb = NamedContextCallback {
1553            debug_name,
1554            callback: cb,
1555        };
1556        self.write(|ctx| ctx.plugins.on_begin_frame.push(named_cb));
1557    }
1558
1559    /// Call the given callback at the end of each frame
1560    /// of each viewport.
1561    ///
1562    /// This can be used for egui _plugins_.
1563    /// See [`crate::debug_text`] for an example.
1564    pub fn on_end_frame(&self, debug_name: &'static str, cb: ContextCallback) {
1565        let named_cb = NamedContextCallback {
1566            debug_name,
1567            callback: cb,
1568        };
1569        self.write(|ctx| ctx.plugins.on_end_frame.push(named_cb));
1570    }
1571}
1572
1573impl Context {
1574    /// Tell `egui` which fonts to use.
1575    ///
1576    /// The default `egui` fonts only support latin and cyrillic alphabets,
1577    /// but you can call this to install additional fonts that support e.g. korean characters.
1578    ///
1579    /// The new fonts will become active at the start of the next frame.
1580    pub fn set_fonts(&self, font_definitions: FontDefinitions) {
1581        crate::profile_function!();
1582
1583        let pixels_per_point = self.pixels_per_point();
1584
1585        let mut update_fonts = true;
1586
1587        self.read(|ctx| {
1588            if let Some(current_fonts) = ctx.fonts.get(&pixels_per_point.into()) {
1589                // NOTE: this comparison is expensive since it checks TTF data for equality
1590                if current_fonts.lock().fonts.definitions() == &font_definitions {
1591                    update_fonts = false; // no need to update
1592                }
1593            }
1594        });
1595
1596        if update_fonts {
1597            self.memory_mut(|mem| mem.new_font_definitions = Some(font_definitions));
1598        }
1599    }
1600
1601    /// The [`Style`] used by all subsequent windows, panels etc.
1602    pub fn style(&self) -> Arc<Style> {
1603        self.options(|opt| opt.style.clone())
1604    }
1605
1606    /// Mutate the [`Style`] used by all subsequent windows, panels etc.
1607    ///
1608    /// Example:
1609    /// ```
1610    /// # let mut ctx = egui::Context::default();
1611    /// ctx.style_mut(|style| {
1612    ///     style.spacing.item_spacing = egui::vec2(10.0, 20.0);
1613    /// });
1614    /// ```
1615    pub fn style_mut(&self, mutate_style: impl FnOnce(&mut Style)) {
1616        self.options_mut(|opt| mutate_style(std::sync::Arc::make_mut(&mut opt.style)));
1617    }
1618
1619    /// The [`Style`] used by all new windows, panels etc.
1620    ///
1621    /// You can also change this using [`Self::style_mut`]
1622    ///
1623    /// You can use [`Ui::style_mut`] to change the style of a single [`Ui`].
1624    pub fn set_style(&self, style: impl Into<Arc<Style>>) {
1625        self.options_mut(|opt| opt.style = style.into());
1626    }
1627
1628    /// The [`Visuals`] used by all subsequent windows, panels etc.
1629    ///
1630    /// You can also use [`Ui::visuals_mut`] to change the visuals of a single [`Ui`].
1631    ///
1632    /// Example:
1633    /// ```
1634    /// # let mut ctx = egui::Context::default();
1635    /// ctx.set_visuals(egui::Visuals::light()); // Switch to light mode
1636    /// ```
1637    pub fn set_visuals(&self, visuals: crate::Visuals) {
1638        self.options_mut(|opt| std::sync::Arc::make_mut(&mut opt.style).visuals = visuals);
1639    }
1640
1641    /// The number of physical pixels for each logical point.
1642    ///
1643    /// This is calculated as [`Self::zoom_factor`] * [`Self::native_pixels_per_point`]
1644    #[inline(always)]
1645    pub fn pixels_per_point(&self) -> f32 {
1646        self.input(|i| i.pixels_per_point)
1647    }
1648
1649    /// Set the number of physical pixels for each logical point.
1650    /// Will become active at the start of the next frame.
1651    ///
1652    /// This will actually translate to a call to [`Self::set_zoom_factor`].
1653    pub fn set_pixels_per_point(&self, pixels_per_point: f32) {
1654        if pixels_per_point != self.pixels_per_point() {
1655            self.set_zoom_factor(pixels_per_point / self.native_pixels_per_point().unwrap_or(1.0));
1656        }
1657    }
1658
1659    /// The number of physical pixels for each logical point on this monitor.
1660    ///
1661    /// This is given as input to egui via [`ViewportInfo::native_pixels_per_point`]
1662    /// and cannot be changed.
1663    #[inline(always)]
1664    pub fn native_pixels_per_point(&self) -> Option<f32> {
1665        self.input(|i| i.viewport().native_pixels_per_point)
1666    }
1667
1668    /// Global zoom factor of the UI.
1669    ///
1670    /// This is used to calculate the `pixels_per_point`
1671    /// for the UI as `pixels_per_point = zoom_fator * native_pixels_per_point`.
1672    ///
1673    /// The default is 1.0.
1674    /// Make larger to make everything larger.
1675    #[inline(always)]
1676    pub fn zoom_factor(&self) -> f32 {
1677        self.options(|o| o.zoom_factor)
1678    }
1679
1680    /// Sets zoom factor of the UI.
1681    /// Will become active at the start of the next frame.
1682    ///
1683    /// Note that calling this will not update [`Self::zoom_factor`] until the end of the frame.
1684    ///
1685    /// This is used to calculate the `pixels_per_point`
1686    /// for the UI as `pixels_per_point = zoom_fator * native_pixels_per_point`.
1687    ///
1688    /// The default is 1.0.
1689    /// Make larger to make everything larger.
1690    ///
1691    /// It is better to call this than modifying
1692    /// [`Options::zoom_factor`].
1693    #[inline(always)]
1694    pub fn set_zoom_factor(&self, zoom_factor: f32) {
1695        let cause = RepaintCause::new();
1696        self.write(|ctx| {
1697            if ctx.memory.options.zoom_factor != zoom_factor {
1698                ctx.new_zoom_factor = Some(zoom_factor);
1699                for viewport_id in ctx.all_viewport_ids() {
1700                    ctx.request_repaint(viewport_id, cause.clone());
1701                }
1702            }
1703        });
1704    }
1705
1706    /// Useful for pixel-perfect rendering
1707    #[inline]
1708    pub(crate) fn round_to_pixel(&self, point: f32) -> f32 {
1709        let pixels_per_point = self.pixels_per_point();
1710        (point * pixels_per_point).round() / pixels_per_point
1711    }
1712
1713    /// Useful for pixel-perfect rendering
1714    #[inline]
1715    pub(crate) fn round_pos_to_pixels(&self, pos: Pos2) -> Pos2 {
1716        pos2(self.round_to_pixel(pos.x), self.round_to_pixel(pos.y))
1717    }
1718
1719    /// Useful for pixel-perfect rendering
1720    #[inline]
1721    pub(crate) fn round_vec_to_pixels(&self, vec: Vec2) -> Vec2 {
1722        vec2(self.round_to_pixel(vec.x), self.round_to_pixel(vec.y))
1723    }
1724
1725    /// Useful for pixel-perfect rendering
1726    #[inline]
1727    pub(crate) fn round_rect_to_pixels(&self, rect: Rect) -> Rect {
1728        Rect {
1729            min: self.round_pos_to_pixels(rect.min),
1730            max: self.round_pos_to_pixels(rect.max),
1731        }
1732    }
1733
1734    /// Allocate a texture.
1735    ///
1736    /// This is for advanced users.
1737    /// Most users should use [`crate::Ui::image`] or [`Self::try_load_texture`]
1738    /// instead.
1739    ///
1740    /// In order to display an image you must convert it to a texture using this function.
1741    /// The function will hand over the image data to the egui backend, which will
1742    /// upload it to the GPU.
1743    ///
1744    /// ⚠️ Make sure to only call this ONCE for each image, i.e. NOT in your main GUI code.
1745    /// The call is NOT immediate safe.
1746    ///
1747    /// The given name can be useful for later debugging, and will be visible if you call [`Self::texture_ui`].
1748    ///
1749    /// For how to load an image, see [`ImageData`] and [`ColorImage::from_rgba_unmultiplied`].
1750    ///
1751    /// ```
1752    /// struct MyImage {
1753    ///     texture: Option<egui::TextureHandle>,
1754    /// }
1755    ///
1756    /// impl MyImage {
1757    ///     fn ui(&mut self, ui: &mut egui::Ui) {
1758    ///         let texture: &egui::TextureHandle = self.texture.get_or_insert_with(|| {
1759    ///             // Load the texture only once.
1760    ///             ui.ctx().load_texture(
1761    ///                 "my-image",
1762    ///                 egui::ColorImage::example(),
1763    ///                 Default::default()
1764    ///             )
1765    ///         });
1766    ///
1767    ///         // Show the image:
1768    ///         ui.image((texture.id(), texture.size_vec2()));
1769    ///     }
1770    /// }
1771    /// ```
1772    ///
1773    /// See also [`crate::ImageData`], [`crate::Ui::image`] and [`crate::Image`].
1774    pub fn load_texture(
1775        &self,
1776        name: impl Into<String>,
1777        image: impl Into<ImageData>,
1778        options: TextureOptions,
1779    ) -> TextureHandle {
1780        let name = name.into();
1781        let image = image.into();
1782        let max_texture_side = self.input(|i| i.max_texture_side);
1783        debug_assert!(
1784            image.width() <= max_texture_side && image.height() <= max_texture_side,
1785            "Texture {:?} has size {}x{}, but the maximum texture side is {}",
1786            name,
1787            image.width(),
1788            image.height(),
1789            max_texture_side
1790        );
1791        let tex_mngr = self.tex_manager();
1792        let tex_id = tex_mngr.write().alloc(name, image, options);
1793        TextureHandle::new(tex_mngr, tex_id)
1794    }
1795
1796    /// Low-level texture manager.
1797    ///
1798    /// In general it is easier to use [`Self::load_texture`] and [`TextureHandle`].
1799    ///
1800    /// You can show stats about the allocated textures using [`Self::texture_ui`].
1801    pub fn tex_manager(&self) -> Arc<RwLock<epaint::textures::TextureManager>> {
1802        self.read(|ctx| ctx.tex_manager.0.clone())
1803    }
1804
1805    // ---------------------------------------------------------------------
1806
1807    /// Constrain the position of a window/area so it fits within the provided boundary.
1808    pub(crate) fn constrain_window_rect_to_area(&self, window: Rect, area: Rect) -> Rect {
1809        let mut pos = window.min;
1810
1811        // Constrain to screen, unless window is too large to fit:
1812        let margin_x = (window.width() - area.width()).at_least(0.0);
1813        let margin_y = (window.height() - area.height()).at_least(0.0);
1814
1815        pos.x = pos.x.at_most(area.right() + margin_x - window.width()); // move left if needed
1816        pos.x = pos.x.at_least(area.left() - margin_x); // move right if needed
1817        pos.y = pos.y.at_most(area.bottom() + margin_y - window.height()); // move right if needed
1818        pos.y = pos.y.at_least(area.top() - margin_y); // move down if needed
1819
1820        pos = self.round_pos_to_pixels(pos);
1821
1822        Rect::from_min_size(pos, window.size())
1823    }
1824}
1825
1826impl Context {
1827    /// Call at the end of each frame.
1828    #[must_use]
1829    pub fn end_frame(&self) -> FullOutput {
1830        crate::profile_function!();
1831
1832        if self.options(|o| o.zoom_with_keyboard) {
1833            crate::gui_zoom::zoom_with_keyboard(self);
1834        }
1835
1836        // Plugins run just before the frame ends.
1837        self.read(|ctx| ctx.plugins.clone()).on_end_frame(self);
1838
1839        #[cfg(debug_assertions)]
1840        self.debug_painting();
1841
1842        self.write(|ctx| ctx.end_frame())
1843    }
1844
1845    /// Called at the end of the frame.
1846    #[cfg(debug_assertions)]
1847    fn debug_painting(&self) {
1848        let paint_widget = |widget: &WidgetRect, text: &str, color: Color32| {
1849            let rect = widget.interact_rect;
1850            if rect.is_positive() {
1851                let painter = Painter::new(self.clone(), widget.layer_id, Rect::EVERYTHING);
1852                painter.debug_rect(rect, color, text);
1853            }
1854        };
1855
1856        let paint_widget_id = |id: Id, text: &str, color: Color32| {
1857            if let Some(widget) =
1858                self.write(|ctx| ctx.viewport().this_frame.widgets.get(id).copied())
1859            {
1860                paint_widget(&widget, text, color);
1861            }
1862        };
1863
1864        if self.style().debug.show_interactive_widgets {
1865            // Show all interactive widgets:
1866            let rects = self.write(|ctx| ctx.viewport().this_frame.widgets.clone());
1867            for (layer_id, rects) in rects.layers() {
1868                let painter = Painter::new(self.clone(), *layer_id, Rect::EVERYTHING);
1869                for rect in rects {
1870                    if rect.sense.interactive() {
1871                        let (color, text) = if rect.sense.click && rect.sense.drag {
1872                            (Color32::from_rgb(0x88, 0, 0x88), "click+drag")
1873                        } else if rect.sense.click {
1874                            (Color32::from_rgb(0x88, 0, 0), "click")
1875                        } else if rect.sense.drag {
1876                            (Color32::from_rgb(0, 0, 0x88), "drag")
1877                        } else {
1878                            // unreachable since we only show interactive
1879                            (Color32::from_rgb(0, 0, 0x88), "hover")
1880                        };
1881                        painter.debug_rect(rect.interact_rect, color, text);
1882                    }
1883                }
1884            }
1885
1886            // Show the ones actually interacted with:
1887            {
1888                let interact_widgets = self.write(|ctx| ctx.viewport().interact_widgets.clone());
1889                let InteractionSnapshot {
1890                    clicked,
1891                    long_touched: _,
1892                    drag_started: _,
1893                    dragged,
1894                    drag_stopped: _,
1895                    contains_pointer,
1896                    hovered,
1897                } = interact_widgets;
1898
1899                if true {
1900                    for &id in &contains_pointer {
1901                        paint_widget_id(id, "contains_pointer", Color32::BLUE);
1902                    }
1903
1904                    let widget_rects = self.write(|w| w.viewport().this_frame.widgets.clone());
1905
1906                    let mut contains_pointer: Vec<Id> = contains_pointer.iter().copied().collect();
1907                    contains_pointer.sort_by_key(|&id| {
1908                        widget_rects
1909                            .order(id)
1910                            .map(|(layer_id, order_in_layer)| (layer_id.order, order_in_layer))
1911                    });
1912
1913                    let mut debug_text = "Widgets in order:\n".to_owned();
1914                    for id in contains_pointer {
1915                        let mut widget_text = format!("{id:?}");
1916                        if let Some(rect) = widget_rects.get(id) {
1917                            widget_text += &format!(" {:?} {:?}", rect.rect, rect.sense);
1918                        }
1919                        if let Some(info) = widget_rects.info(id) {
1920                            widget_text += &format!(" {info:?}");
1921                        }
1922                        debug_text += &format!("{widget_text}\n");
1923                    }
1924                    self.debug_text(debug_text);
1925                }
1926                if true {
1927                    for widget in hovered {
1928                        paint_widget_id(widget, "hovered", Color32::WHITE);
1929                    }
1930                }
1931                for &widget in &clicked {
1932                    paint_widget_id(widget, "clicked", Color32::RED);
1933                }
1934                for &widget in &dragged {
1935                    paint_widget_id(widget, "dragged", Color32::GREEN);
1936                }
1937            }
1938        }
1939
1940        if self.style().debug.show_widget_hits {
1941            let hits = self.write(|ctx| ctx.viewport().hits.clone());
1942            let WidgetHits {
1943                contains_pointer,
1944                click,
1945                drag,
1946            } = hits;
1947
1948            if true {
1949                for widget in &contains_pointer {
1950                    paint_widget(widget, "contains_pointer", Color32::BLUE);
1951                }
1952            }
1953            for widget in &click {
1954                paint_widget(widget, "click", Color32::RED);
1955            }
1956            for widget in &drag {
1957                paint_widget(widget, "drag", Color32::GREEN);
1958            }
1959        }
1960
1961        if let Some(debug_rect) = self.frame_state_mut(|fs| fs.debug_rect.take()) {
1962            debug_rect.paint(&self.debug_painter());
1963        }
1964    }
1965}
1966
1967impl ContextImpl {
1968    fn end_frame(&mut self) -> FullOutput {
1969        let ended_viewport_id = self.viewport_id();
1970        let viewport = self.viewports.entry(ended_viewport_id).or_default();
1971        let pixels_per_point = viewport.input.pixels_per_point;
1972
1973        viewport.repaint.frame_nr += 1;
1974
1975        self.memory.end_frame(&viewport.this_frame.used_ids);
1976
1977        if let Some(fonts) = self.fonts.get(&pixels_per_point.into()) {
1978            let tex_mngr = &mut self.tex_manager.0.write();
1979            if let Some(font_image_delta) = fonts.font_image_delta() {
1980                // A partial font atlas update, e.g. a new glyph has been entered.
1981                tex_mngr.set(TextureId::default(), font_image_delta);
1982            }
1983
1984            if 1 < self.fonts.len() {
1985                // We have multiple different `pixels_per_point`,
1986                // e.g. because we have many viewports spread across
1987                // monitors with different DPI scaling.
1988                // All viewports share the same texture namespace and renderer,
1989                // so the all use `TextureId::default()` for the font texture.
1990                // This is a problem.
1991                // We solve this with a hack: we always upload the full font atlas
1992                // every frame, for all viewports.
1993                // This ensures it is up-to-date, solving
1994                // https://github.com/emilk/egui/issues/3664
1995                // at the cost of a lot of performance.
1996                // (This will override any smaller delta that was uploaded above.)
1997                crate::profile_scope!("full_font_atlas_update");
1998                let full_delta = ImageDelta::full(fonts.image(), TextureAtlas::texture_options());
1999                tex_mngr.set(TextureId::default(), full_delta);
2000            }
2001        }
2002
2003        // Inform the backend of all textures that have been updated (including font atlas).
2004        let textures_delta = self.tex_manager.0.write().take_delta();
2005
2006        #[cfg_attr(not(feature = "accesskit"), allow(unused_mut))]
2007        let mut platform_output: PlatformOutput = std::mem::take(&mut viewport.output);
2008
2009        #[cfg(feature = "accesskit")]
2010        {
2011            crate::profile_scope!("accesskit");
2012            let state = viewport.this_frame.accesskit_state.take();
2013            if let Some(state) = state {
2014                let root_id = crate::accesskit_root_id().accesskit_id();
2015                let nodes = {
2016                    state
2017                        .node_builders
2018                        .into_iter()
2019                        .map(|(id, builder)| {
2020                            (
2021                                id.accesskit_id(),
2022                                builder.build(&mut self.accesskit_node_classes),
2023                            )
2024                        })
2025                        .collect()
2026                };
2027                let focus_id = self
2028                    .memory
2029                    .focused()
2030                    .map_or(root_id, |id| id.accesskit_id());
2031                platform_output.accesskit_update = Some(accesskit::TreeUpdate {
2032                    nodes,
2033                    tree: Some(accesskit::Tree::new(root_id)),
2034                    focus: focus_id,
2035                });
2036            }
2037        }
2038
2039        let shapes = viewport
2040            .graphics
2041            .drain(self.memory.areas().order(), &self.memory.layer_transforms);
2042
2043        let mut repaint_needed = false;
2044
2045        if self.memory.options.repaint_on_widget_change {
2046            crate::profile_function!("compare-widget-rects");
2047            if viewport.prev_frame.widgets != viewport.this_frame.widgets {
2048                repaint_needed = true; // Some widget has moved
2049            }
2050        }
2051
2052        std::mem::swap(&mut viewport.prev_frame, &mut viewport.this_frame);
2053
2054        if repaint_needed {
2055            self.request_repaint(ended_viewport_id, RepaintCause::new());
2056        } else if let Some(delay) = viewport.input.wants_repaint_after() {
2057            self.request_repaint_after(delay, ended_viewport_id, RepaintCause::new());
2058        }
2059
2060        //  -------------------
2061
2062        let all_viewport_ids = self.all_viewport_ids();
2063
2064        self.last_viewport = ended_viewport_id;
2065
2066        self.viewports.retain(|&id, viewport| {
2067            let parent = *self.viewport_parents.entry(id).or_default();
2068
2069            if !all_viewport_ids.contains(&parent) {
2070                #[cfg(feature = "log")]
2071                log::debug!(
2072                    "Removing viewport {:?} ({:?}): the parent is gone",
2073                    id,
2074                    viewport.builder.title
2075                );
2076
2077                return false;
2078            }
2079
2080            let is_our_child = parent == ended_viewport_id && id != ViewportId::ROOT;
2081            if is_our_child {
2082                if !viewport.used {
2083                    #[cfg(feature = "log")]
2084                    log::debug!(
2085                        "Removing viewport {:?} ({:?}): it was never used this frame",
2086                        id,
2087                        viewport.builder.title
2088                    );
2089
2090                    return false; // Only keep children that have been updated this frame
2091                }
2092
2093                viewport.used = false; // reset so we can check again next frame
2094            }
2095
2096            true
2097        });
2098
2099        // If we are an immediate viewport, this will resume the previous viewport.
2100        self.viewport_stack.pop();
2101
2102        // The last viewport is not necessarily the root viewport,
2103        // just the top _immediate_ viewport.
2104        let is_last = self.viewport_stack.is_empty();
2105
2106        let viewport_output = self
2107            .viewports
2108            .iter_mut()
2109            .map(|(&id, viewport)| {
2110                let parent = *self.viewport_parents.entry(id).or_default();
2111                let commands = if is_last {
2112                    // Let the primary immediate viewport handle the commands of its children too.
2113                    // This can make things easier for the backend, as otherwise we may get commands
2114                    // that affect a viewport while its egui logic is running.
2115                    std::mem::take(&mut viewport.commands)
2116                } else {
2117                    vec![]
2118                };
2119
2120                (
2121                    id,
2122                    ViewportOutput {
2123                        parent,
2124                        class: viewport.class,
2125                        builder: viewport.builder.clone(),
2126                        viewport_ui_cb: viewport.viewport_ui_cb.clone(),
2127                        commands,
2128                        repaint_delay: viewport.repaint.repaint_delay,
2129                    },
2130                )
2131            })
2132            .collect();
2133
2134        if is_last {
2135            // Remove dead viewports:
2136            self.viewports.retain(|id, _| all_viewport_ids.contains(id));
2137            self.viewport_parents
2138                .retain(|id, _| all_viewport_ids.contains(id));
2139        } else {
2140            let viewport_id = self.viewport_id();
2141            self.memory.set_viewport_id(viewport_id);
2142        }
2143
2144        let active_pixels_per_point: std::collections::BTreeSet<OrderedFloat<f32>> = self
2145            .viewports
2146            .values()
2147            .map(|v| v.input.pixels_per_point.into())
2148            .collect();
2149        self.fonts.retain(|pixels_per_point, _| {
2150            if active_pixels_per_point.contains(pixels_per_point) {
2151                true
2152            } else {
2153                #[cfg(feature = "log")]
2154                log::trace!(
2155                    "Freeing Fonts with pixels_per_point={} because it is no longer needed",
2156                    pixels_per_point.into_inner()
2157                );
2158                false
2159            }
2160        });
2161
2162        FullOutput {
2163            platform_output,
2164            textures_delta,
2165            shapes,
2166            pixels_per_point,
2167            viewport_output,
2168        }
2169    }
2170}
2171
2172impl Context {
2173    /// Tessellate the given shapes into triangle meshes.
2174    ///
2175    /// `pixels_per_point` is used for feathering (anti-aliasing).
2176    /// For this you can use [`FullOutput::pixels_per_point`], [`Self::pixels_per_point`],
2177    /// or whatever is appropriate for your viewport.
2178    pub fn tessellate(
2179        &self,
2180        shapes: Vec<ClippedShape>,
2181        pixels_per_point: f32,
2182    ) -> Vec<ClippedPrimitive> {
2183        crate::profile_function!();
2184
2185        // A tempting optimization is to reuse the tessellation from last frame if the
2186        // shapes are the same, but just comparing the shapes takes about 50% of the time
2187        // it takes to tessellate them, so it is not a worth optimization.
2188
2189        self.write(|ctx| {
2190            let tessellation_options = ctx.memory.options.tessellation_options;
2191            let texture_atlas = ctx
2192                .fonts
2193                .get(&pixels_per_point.into())
2194                .expect("tessellate called with a different pixels_per_point than the font atlas was created with. \
2195                         You should use egui::FullOutput::pixels_per_point when tessellating.")
2196                .texture_atlas();
2197            let (font_tex_size, prepared_discs) = {
2198                let atlas = texture_atlas.lock();
2199                (atlas.size(), atlas.prepared_discs())
2200            };
2201
2202            let paint_stats = PaintStats::from_shapes(&shapes);
2203            let clipped_primitives = {
2204                crate::profile_scope!("tessellator::tessellate_shapes");
2205                tessellator::Tessellator::new(
2206                    pixels_per_point,
2207                    tessellation_options,
2208                    font_tex_size,
2209                    prepared_discs,
2210                )
2211                .tessellate_shapes(shapes)
2212            };
2213            ctx.paint_stats = paint_stats.with_clipped_primitives(&clipped_primitives);
2214            clipped_primitives
2215        })
2216    }
2217
2218    // ---------------------------------------------------------------------
2219
2220    /// Position and size of the egui area.
2221    pub fn screen_rect(&self) -> Rect {
2222        self.input(|i| i.screen_rect())
2223    }
2224
2225    /// How much space is still available after panels has been added.
2226    ///
2227    /// This is the "background" area, what egui doesn't cover with panels (but may cover with windows).
2228    /// This is also the area to which windows are constrained.
2229    pub fn available_rect(&self) -> Rect {
2230        self.frame_state(|s| s.available_rect())
2231    }
2232
2233    /// How much space is used by panels and windows.
2234    pub fn used_rect(&self) -> Rect {
2235        self.write(|ctx| {
2236            let mut used = ctx.viewport().this_frame.used_by_panels;
2237            for (_id, window) in ctx.memory.areas().visible_windows() {
2238                used = used.union(window.rect());
2239            }
2240            used
2241        })
2242    }
2243
2244    /// How much space is used by panels and windows.
2245    ///
2246    /// You can shrink your egui area to this size and still fit all egui components.
2247    pub fn used_size(&self) -> Vec2 {
2248        self.used_rect().max - Pos2::ZERO
2249    }
2250
2251    // ---------------------------------------------------------------------
2252
2253    /// Is the pointer (mouse/touch) over any egui area?
2254    pub fn is_pointer_over_area(&self) -> bool {
2255        let pointer_pos = self.input(|i| i.pointer.interact_pos());
2256        if let Some(pointer_pos) = pointer_pos {
2257            if let Some(layer) = self.layer_id_at(pointer_pos) {
2258                if layer.order == Order::Background {
2259                    !self.frame_state(|state| state.unused_rect.contains(pointer_pos))
2260                } else {
2261                    true
2262                }
2263            } else {
2264                false
2265            }
2266        } else {
2267            false
2268        }
2269    }
2270
2271    /// True if egui is currently interested in the pointer (mouse or touch).
2272    ///
2273    /// Could be the pointer is hovering over a [`Window`] or the user is dragging a widget.
2274    /// If `false`, the pointer is outside of any egui area and so
2275    /// you may be interested in what it is doing (e.g. controlling your game).
2276    /// Returns `false` if a drag started outside of egui and then moved over an egui area.
2277    pub fn wants_pointer_input(&self) -> bool {
2278        self.is_using_pointer()
2279            || (self.is_pointer_over_area() && !self.input(|i| i.pointer.any_down()))
2280    }
2281
2282    /// Is egui currently using the pointer position (e.g. dragging a slider)?
2283    ///
2284    /// NOTE: this will return `false` if the pointer is just hovering over an egui area.
2285    pub fn is_using_pointer(&self) -> bool {
2286        self.memory(|m| m.interaction().is_using_pointer())
2287    }
2288
2289    /// If `true`, egui is currently listening on text input (e.g. typing text in a [`TextEdit`]).
2290    pub fn wants_keyboard_input(&self) -> bool {
2291        self.memory(|m| m.focused().is_some())
2292    }
2293
2294    /// Highlight this widget, to make it look like it is hovered, even if it isn't.
2295    ///
2296    /// The highlight takes on frame to take effect if you call this after the widget has been fully rendered.
2297    ///
2298    /// See also [`Response::highlight`].
2299    pub fn highlight_widget(&self, id: Id) {
2300        self.frame_state_mut(|fs| fs.highlight_next_frame.insert(id));
2301    }
2302
2303    /// Is an egui context menu open?
2304    pub fn is_context_menu_open(&self) -> bool {
2305        self.data(|d| {
2306            d.get_temp::<crate::menu::BarState>(menu::CONTEXT_MENU_ID_STR.into())
2307                .map_or(false, |state| state.has_root())
2308        })
2309    }
2310}
2311
2312// Ergonomic methods to forward some calls often used in 'if let' without holding the borrow
2313impl Context {
2314    /// Latest reported pointer position.
2315    ///
2316    /// When tapping a touch screen, this will be `None`.
2317    #[inline(always)]
2318    pub fn pointer_latest_pos(&self) -> Option<Pos2> {
2319        self.input(|i| i.pointer.latest_pos())
2320    }
2321
2322    /// If it is a good idea to show a tooltip, where is pointer?
2323    #[inline(always)]
2324    pub fn pointer_hover_pos(&self) -> Option<Pos2> {
2325        self.input(|i| i.pointer.hover_pos())
2326    }
2327
2328    /// If you detect a click or drag and wants to know where it happened, use this.
2329    ///
2330    /// Latest position of the mouse, but ignoring any [`Event::PointerGone`]
2331    /// if there were interactions this frame.
2332    /// When tapping a touch screen, this will be the location of the touch.
2333    #[inline(always)]
2334    pub fn pointer_interact_pos(&self) -> Option<Pos2> {
2335        self.input(|i| i.pointer.interact_pos())
2336    }
2337
2338    /// Calls [`InputState::multi_touch`].
2339    pub fn multi_touch(&self) -> Option<MultiTouchInfo> {
2340        self.input(|i| i.multi_touch())
2341    }
2342}
2343
2344impl Context {
2345    /// Transform the graphics of the given layer.
2346    ///
2347    /// This will also affect input.
2348    ///
2349    /// This is a sticky setting, remembered from one frame to the next.
2350    ///
2351    /// Can be used to implement pan and zoom (see relevant demo).
2352    ///
2353    /// For a temporary transform, use [`Self::transform_layer_shapes`] instead.
2354    pub fn set_transform_layer(&self, layer_id: LayerId, transform: TSTransform) {
2355        self.memory_mut(|m| {
2356            if transform == TSTransform::IDENTITY {
2357                m.layer_transforms.remove(&layer_id)
2358            } else {
2359                m.layer_transforms.insert(layer_id, transform)
2360            }
2361        });
2362    }
2363
2364    /// Move all the graphics at the given layer.
2365    ///
2366    /// Is used to implement drag-and-drop preview.
2367    ///
2368    /// This only applied to the existing graphics at the layer, not to new graphics added later.
2369    ///
2370    /// For a persistent transform, use [`Self::set_transform_layer`] instead.
2371    #[deprecated = "Use `transform_layer_shapes` instead"]
2372    pub fn translate_layer(&self, layer_id: LayerId, delta: Vec2) {
2373        if delta != Vec2::ZERO {
2374            let transform = emath::TSTransform::from_translation(delta);
2375            self.transform_layer_shapes(layer_id, transform);
2376        }
2377    }
2378
2379    /// Transform all the graphics at the given layer.
2380    ///
2381    /// Is used to implement drag-and-drop preview.
2382    ///
2383    /// This only applied to the existing graphics at the layer, not to new graphics added later.
2384    ///
2385    /// For a persistent transform, use [`Self::set_transform_layer`] instead.
2386    pub fn transform_layer_shapes(&self, layer_id: LayerId, transform: TSTransform) {
2387        if transform != TSTransform::IDENTITY {
2388            self.graphics_mut(|g| g.entry(layer_id).transform(transform));
2389        }
2390    }
2391
2392    /// Top-most layer at the given position.
2393    pub fn layer_id_at(&self, pos: Pos2) -> Option<LayerId> {
2394        self.memory(|mem| mem.layer_id_at(pos))
2395    }
2396
2397    /// Moves the given area to the top in its [`Order`].
2398    ///
2399    /// [`Area`]:s and [`Window`]:s also do this automatically when being clicked on or interacted with.
2400    pub fn move_to_top(&self, layer_id: LayerId) {
2401        self.memory_mut(|mem| mem.areas_mut().move_to_top(layer_id));
2402    }
2403
2404    /// Mark the `child` layer as a sublayer of `parent`.
2405    ///
2406    /// Sublayers are moved directly above the parent layer at the end of the frame. This is mainly
2407    /// intended for adding a new [`Area`] inside a [`Window`].
2408    ///
2409    /// This currently only supports one level of nesting. If `parent` is a sublayer of another
2410    /// layer, the behavior is unspecified.
2411    pub fn set_sublayer(&self, parent: LayerId, child: LayerId) {
2412        self.memory_mut(|mem| mem.areas_mut().set_sublayer(parent, child));
2413    }
2414
2415    /// Retrieve the [`LayerId`] of the top level windows.
2416    pub fn top_layer_id(&self) -> Option<LayerId> {
2417        self.memory(|mem| mem.areas().top_layer_id(Order::Middle))
2418    }
2419
2420    /// Does the given rectangle contain the mouse pointer?
2421    ///
2422    /// Will return false if some other area is covering the given layer.
2423    ///
2424    /// The given rectangle is assumed to have been clipped by its parent clip rect.
2425    ///
2426    /// See also [`Response::contains_pointer`].
2427    pub fn rect_contains_pointer(&self, layer_id: LayerId, rect: Rect) -> bool {
2428        let rect =
2429            if let Some(transform) = self.memory(|m| m.layer_transforms.get(&layer_id).copied()) {
2430                transform * rect
2431            } else {
2432                rect
2433            };
2434        if !rect.is_positive() {
2435            return false;
2436        }
2437
2438        let pointer_pos = self.input(|i| i.pointer.interact_pos());
2439        let Some(pointer_pos) = pointer_pos else {
2440            return false;
2441        };
2442
2443        if !rect.contains(pointer_pos) {
2444            return false;
2445        }
2446
2447        if self.layer_id_at(pointer_pos) != Some(layer_id) {
2448            return false;
2449        }
2450
2451        true
2452    }
2453
2454    // ---------------------------------------------------------------------
2455
2456    /// Whether or not to debug widget layout on hover.
2457    #[cfg(debug_assertions)]
2458    pub fn debug_on_hover(&self) -> bool {
2459        self.options(|opt| opt.style.debug.debug_on_hover)
2460    }
2461
2462    /// Turn on/off whether or not to debug widget layout on hover.
2463    #[cfg(debug_assertions)]
2464    pub fn set_debug_on_hover(&self, debug_on_hover: bool) {
2465        self.style_mut(|style| style.debug.debug_on_hover = debug_on_hover);
2466    }
2467}
2468
2469/// ## Animation
2470impl Context {
2471    /// Returns a value in the range [0, 1], to indicate "how on" this thing is.
2472    ///
2473    /// The first time called it will return `if value { 1.0 } else { 0.0 }`
2474    /// Calling this with `value = true` will always yield a number larger than zero, quickly going towards one.
2475    /// Calling this with `value = false` will always yield a number less than one, quickly going towards zero.
2476    ///
2477    /// The function will call [`Self::request_repaint()`] when appropriate.
2478    ///
2479    /// The animation time is taken from [`Style::animation_time`].
2480    #[track_caller] // To track repaint cause
2481    pub fn animate_bool(&self, id: Id, value: bool) -> f32 {
2482        let animation_time = self.style().animation_time;
2483        self.animate_bool_with_time_and_easing(id, value, animation_time, emath::easing::linear)
2484    }
2485
2486    /// Like [`Self::animate_bool`], but uses an easing function that makes the value move
2487    /// quickly in the beginning and slow down towards the end.
2488    ///
2489    /// The exact easing function may come to change in future versions of egui.
2490    #[track_caller] // To track repaint cause
2491    pub fn animate_bool_responsive(&self, id: Id, value: bool) -> f32 {
2492        self.animate_bool_with_easing(id, value, emath::easing::cubic_out)
2493    }
2494
2495    /// Like [`Self::animate_bool`] but allows you to control the easing function.
2496    #[track_caller] // To track repaint cause
2497    pub fn animate_bool_with_easing(&self, id: Id, value: bool, easing: fn(f32) -> f32) -> f32 {
2498        let animation_time = self.style().animation_time;
2499        self.animate_bool_with_time_and_easing(id, value, animation_time, easing)
2500    }
2501
2502    /// Like [`Self::animate_bool`] but allows you to control the animation time.
2503    #[track_caller] // To track repaint cause
2504    pub fn animate_bool_with_time(&self, id: Id, target_value: bool, animation_time: f32) -> f32 {
2505        self.animate_bool_with_time_and_easing(
2506            id,
2507            target_value,
2508            animation_time,
2509            emath::easing::linear,
2510        )
2511    }
2512
2513    /// Like [`Self::animate_bool`] but allows you to control the animation time and easing function.
2514    ///
2515    /// Use e.g. [`emath::easing::quadratic_out`]
2516    /// for a responsive start and a slow end.
2517    ///
2518    /// The easing function flips when `target_value` is `false`,
2519    /// so that when going back towards 0.0, we get
2520    #[track_caller] // To track repaint cause
2521    pub fn animate_bool_with_time_and_easing(
2522        &self,
2523        id: Id,
2524        target_value: bool,
2525        animation_time: f32,
2526        easing: fn(f32) -> f32,
2527    ) -> f32 {
2528        let animated_value = self.write(|ctx| {
2529            ctx.animation_manager.animate_bool(
2530                &ctx.viewports.entry(ctx.viewport_id()).or_default().input,
2531                animation_time,
2532                id,
2533                target_value,
2534            )
2535        });
2536
2537        let animation_in_progress = 0.0 < animated_value && animated_value < 1.0;
2538        if animation_in_progress {
2539            self.request_repaint();
2540        }
2541
2542        if target_value {
2543            easing(animated_value)
2544        } else {
2545            1.0 - easing(1.0 - animated_value)
2546        }
2547    }
2548
2549    /// Smoothly animate an `f32` value.
2550    ///
2551    /// At the first call the value is written to memory.
2552    /// When it is called with a new value, it linearly interpolates to it in the given time.
2553    #[track_caller] // To track repaint cause
2554    pub fn animate_value_with_time(&self, id: Id, target_value: f32, animation_time: f32) -> f32 {
2555        let animated_value = self.write(|ctx| {
2556            ctx.animation_manager.animate_value(
2557                &ctx.viewports.entry(ctx.viewport_id()).or_default().input,
2558                animation_time,
2559                id,
2560                target_value,
2561            )
2562        });
2563        let animation_in_progress = animated_value != target_value;
2564        if animation_in_progress {
2565            self.request_repaint();
2566        }
2567
2568        animated_value
2569    }
2570
2571    /// Clear memory of any animations.
2572    pub fn clear_animations(&self) {
2573        self.write(|ctx| ctx.animation_manager = Default::default());
2574    }
2575}
2576
2577impl Context {
2578    /// Show a ui for settings (style and tessellation options).
2579    pub fn settings_ui(&self, ui: &mut Ui) {
2580        let prev_options = self.options(|o| o.clone());
2581        let mut options = prev_options.clone();
2582
2583        options.ui(ui);
2584
2585        if options != prev_options {
2586            self.options_mut(move |o| *o = options);
2587        }
2588    }
2589
2590    /// Show the state of egui, including its input and output.
2591    pub fn inspection_ui(&self, ui: &mut Ui) {
2592        use crate::containers::*;
2593
2594        ui.label(format!("Is using pointer: {}", self.is_using_pointer()))
2595            .on_hover_text(
2596                "Is egui currently using the pointer actively (e.g. dragging a slider)?",
2597            );
2598        ui.label(format!("Wants pointer input: {}", self.wants_pointer_input()))
2599            .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).");
2600        ui.label(format!(
2601            "Wants keyboard input: {}",
2602            self.wants_keyboard_input()
2603        ))
2604        .on_hover_text("Is egui currently listening for text input?");
2605        ui.label(format!(
2606            "Keyboard focus widget: {}",
2607            self.memory(|m| m.focused())
2608                .as_ref()
2609                .map(Id::short_debug_format)
2610                .unwrap_or_default()
2611        ))
2612        .on_hover_text("Is egui currently listening for text input?");
2613
2614        let pointer_pos = self
2615            .pointer_hover_pos()
2616            .map_or_else(String::new, |pos| format!("{pos:?}"));
2617        ui.label(format!("Pointer pos: {pointer_pos}"));
2618
2619        let top_layer = self
2620            .pointer_hover_pos()
2621            .and_then(|pos| self.layer_id_at(pos))
2622            .map_or_else(String::new, |layer| layer.short_debug_format());
2623        ui.label(format!("Top layer under mouse: {top_layer}"));
2624
2625        ui.add_space(16.0);
2626
2627        ui.label(format!(
2628            "There are {} text galleys in the layout cache",
2629            self.fonts(|f| f.num_galleys_in_cache())
2630        ))
2631        .on_hover_text("This is approximately the number of text strings on screen");
2632        ui.add_space(16.0);
2633
2634        CollapsingHeader::new("🔃 Repaint Causes")
2635            .default_open(false)
2636            .show(ui, |ui| {
2637                ui.set_min_height(120.0);
2638                ui.label("What caused egui to repaint:");
2639                ui.add_space(8.0);
2640                let causes = ui.ctx().repaint_causes();
2641                for cause in causes {
2642                    ui.label(cause.to_string());
2643                }
2644            });
2645
2646        CollapsingHeader::new("📥 Input")
2647            .default_open(false)
2648            .show(ui, |ui| {
2649                let input = ui.input(|i| i.clone());
2650                input.ui(ui);
2651            });
2652
2653        CollapsingHeader::new("📊 Paint stats")
2654            .default_open(false)
2655            .show(ui, |ui| {
2656                let paint_stats = self.read(|ctx| ctx.paint_stats);
2657                paint_stats.ui(ui);
2658            });
2659
2660        CollapsingHeader::new("🖼 Textures")
2661            .default_open(false)
2662            .show(ui, |ui| {
2663                self.texture_ui(ui);
2664            });
2665
2666        CollapsingHeader::new("🔠 Font texture")
2667            .default_open(false)
2668            .show(ui, |ui| {
2669                let font_image_size = self.fonts(|f| f.font_image_size());
2670                crate::introspection::font_texture_ui(ui, font_image_size);
2671            });
2672
2673        CollapsingHeader::new("Label text selection state")
2674            .default_open(false)
2675            .show(ui, |ui| {
2676                ui.label(format!(
2677                    "{:#?}",
2678                    crate::text_selection::LabelSelectionState::load(ui.ctx())
2679                ));
2680            });
2681
2682        CollapsingHeader::new("Interaction")
2683            .default_open(false)
2684            .show(ui, |ui| {
2685                let interact_widgets = self.write(|ctx| ctx.viewport().interact_widgets.clone());
2686                interact_widgets.ui(ui);
2687            });
2688    }
2689
2690    /// Show stats about the allocated textures.
2691    pub fn texture_ui(&self, ui: &mut crate::Ui) {
2692        let tex_mngr = self.tex_manager();
2693        let tex_mngr = tex_mngr.read();
2694
2695        let mut textures: Vec<_> = tex_mngr.allocated().collect();
2696        textures.sort_by_key(|(id, _)| *id);
2697
2698        let mut bytes = 0;
2699        for (_, tex) in &textures {
2700            bytes += tex.bytes_used();
2701        }
2702
2703        ui.label(format!(
2704            "{} allocated texture(s), using {:.1} MB",
2705            textures.len(),
2706            bytes as f64 * 1e-6
2707        ));
2708        let max_preview_size = vec2(48.0, 32.0);
2709
2710        ui.group(|ui| {
2711            ScrollArea::vertical()
2712                .max_height(300.0)
2713                .auto_shrink([false, true])
2714                .show(ui, |ui| {
2715                    ui.style_mut().override_text_style = Some(TextStyle::Monospace);
2716                    Grid::new("textures")
2717                        .striped(true)
2718                        .num_columns(4)
2719                        .spacing(vec2(16.0, 2.0))
2720                        .min_row_height(max_preview_size.y)
2721                        .show(ui, |ui| {
2722                            for (&texture_id, meta) in textures {
2723                                let [w, h] = meta.size;
2724
2725                                let mut size = vec2(w as f32, h as f32);
2726                                size *= (max_preview_size.x / size.x).min(1.0);
2727                                size *= (max_preview_size.y / size.y).min(1.0);
2728                                ui.image(SizedTexture::new(texture_id, size))
2729                                    .on_hover_ui(|ui| {
2730                                        // show larger on hover
2731                                        let max_size = 0.5 * ui.ctx().screen_rect().size();
2732                                        let mut size = vec2(w as f32, h as f32);
2733                                        size *= max_size.x / size.x.max(max_size.x);
2734                                        size *= max_size.y / size.y.max(max_size.y);
2735                                        ui.image(SizedTexture::new(texture_id, size));
2736                                    });
2737
2738                                ui.label(format!("{w} x {h}"));
2739                                ui.label(format!("{:.3} MB", meta.bytes_used() as f64 * 1e-6));
2740                                ui.label(format!("{:?}", meta.name));
2741                                ui.end_row();
2742                            }
2743                        });
2744                });
2745        });
2746    }
2747
2748    /// Shows the contents of [`Self::memory`].
2749    pub fn memory_ui(&self, ui: &mut crate::Ui) {
2750        if ui
2751            .button("Reset all")
2752            .on_hover_text("Reset all egui state")
2753            .clicked()
2754        {
2755            self.memory_mut(|mem| *mem = Default::default());
2756        }
2757
2758        let (num_state, num_serialized) = self.data(|d| (d.len(), d.count_serialized()));
2759        ui.label(format!(
2760            "{num_state} widget states stored (of which {num_serialized} are serialized)."
2761        ));
2762
2763        ui.horizontal(|ui| {
2764            ui.label(format!(
2765                "{} areas (panels, windows, popups, …)",
2766                self.memory(|mem| mem.areas().count())
2767            ));
2768            if ui.button("Reset").clicked() {
2769                self.memory_mut(|mem| *mem.areas_mut() = Default::default());
2770            }
2771        });
2772        ui.indent("areas", |ui| {
2773            ui.label("Visible areas, ordered back to front.");
2774            ui.label("Hover to highlight");
2775            let layers_ids: Vec<LayerId> = self.memory(|mem| mem.areas().order().to_vec());
2776            for layer_id in layers_ids {
2777                let area = AreaState::load(self, layer_id.id);
2778                if let Some(area) = area {
2779                    let is_visible = self.memory(|mem| mem.areas().is_visible(&layer_id));
2780                    if !is_visible {
2781                        continue;
2782                    }
2783                    let text = format!("{} - {:?}", layer_id.short_debug_format(), area.rect(),);
2784                    // TODO(emilk): `Sense::hover_highlight()`
2785                    if ui
2786                        .add(Label::new(RichText::new(text).monospace()).sense(Sense::click()))
2787                        .hovered
2788                        && is_visible
2789                    {
2790                        ui.ctx()
2791                            .debug_painter()
2792                            .debug_rect(area.rect(), Color32::RED, "");
2793                    }
2794                }
2795            }
2796        });
2797
2798        ui.horizontal(|ui| {
2799            ui.label(format!(
2800                "{} collapsing headers",
2801                self.data(|d| d.count::<containers::collapsing_header::InnerState>())
2802            ));
2803            if ui.button("Reset").clicked() {
2804                self.data_mut(|d| d.remove_by_type::<containers::collapsing_header::InnerState>());
2805            }
2806        });
2807
2808        ui.horizontal(|ui| {
2809            ui.label(format!(
2810                "{} menu bars",
2811                self.data(|d| d.count::<menu::BarState>())
2812            ));
2813            if ui.button("Reset").clicked() {
2814                self.data_mut(|d| d.remove_by_type::<menu::BarState>());
2815            }
2816        });
2817
2818        ui.horizontal(|ui| {
2819            ui.label(format!(
2820                "{} scroll areas",
2821                self.data(|d| d.count::<scroll_area::State>())
2822            ));
2823            if ui.button("Reset").clicked() {
2824                self.data_mut(|d| d.remove_by_type::<scroll_area::State>());
2825            }
2826        });
2827
2828        ui.horizontal(|ui| {
2829            ui.label(format!(
2830                "{} resize areas",
2831                self.data(|d| d.count::<resize::State>())
2832            ));
2833            if ui.button("Reset").clicked() {
2834                self.data_mut(|d| d.remove_by_type::<resize::State>());
2835            }
2836        });
2837
2838        ui.shrink_width_to_current(); // don't let the text below grow this window wider
2839        ui.label("NOTE: the position of this window cannot be reset from within itself.");
2840
2841        ui.collapsing("Interaction", |ui| {
2842            let interaction = self.memory(|mem| mem.interaction().clone());
2843            interaction.ui(ui);
2844        });
2845    }
2846}
2847
2848impl Context {
2849    /// Edit the active [`Style`].
2850    pub fn style_ui(&self, ui: &mut Ui) {
2851        let mut style: Style = (*self.style()).clone();
2852        style.ui(ui);
2853        self.set_style(style);
2854    }
2855}
2856
2857/// ## Accessibility
2858impl Context {
2859    /// Call the provided function with the given ID pushed on the stack of
2860    /// parent IDs for accessibility purposes. If the `accesskit` feature
2861    /// is disabled or if AccessKit support is not active for this frame,
2862    /// the function is still called, but with no other effect.
2863    ///
2864    /// No locks are held while the given closure is called.
2865    #[allow(clippy::unused_self)]
2866    #[inline]
2867    pub fn with_accessibility_parent(&self, _id: Id, f: impl FnOnce()) {
2868        // TODO(emilk): this isn't thread-safe - another thread can call this function between the push/pop calls
2869        #[cfg(feature = "accesskit")]
2870        self.frame_state_mut(|fs| {
2871            if let Some(state) = fs.accesskit_state.as_mut() {
2872                state.parent_stack.push(_id);
2873            }
2874        });
2875
2876        f();
2877
2878        #[cfg(feature = "accesskit")]
2879        self.frame_state_mut(|fs| {
2880            if let Some(state) = fs.accesskit_state.as_mut() {
2881                assert_eq!(state.parent_stack.pop(), Some(_id));
2882            }
2883        });
2884    }
2885
2886    /// If AccessKit support is active for the current frame, get or create
2887    /// a node builder with the specified ID and return a mutable reference to it.
2888    /// For newly created nodes, the parent is the node with the ID at the top
2889    /// of the stack managed by [`Context::with_accessibility_parent`].
2890    ///
2891    /// The `Context` lock is held while the given closure is called!
2892    ///
2893    /// Returns `None` if acesskit is off.
2894    // TODO(emilk): consider making both read-only and read-write versions
2895    #[cfg(feature = "accesskit")]
2896    pub fn accesskit_node_builder<R>(
2897        &self,
2898        id: Id,
2899        writer: impl FnOnce(&mut accesskit::NodeBuilder) -> R,
2900    ) -> Option<R> {
2901        self.write(|ctx| {
2902            ctx.viewport()
2903                .this_frame
2904                .accesskit_state
2905                .is_some()
2906                .then(|| ctx.accesskit_node_builder(id))
2907                .map(writer)
2908        })
2909    }
2910
2911    /// Enable generation of AccessKit tree updates in all future frames.
2912    ///
2913    /// If it's practical for the egui integration to immediately run the egui
2914    /// application when it is either initializing the AccessKit adapter or
2915    /// being called by the AccessKit adapter to provide the initial tree update,
2916    /// then it should do so, to provide a complete AccessKit tree to the adapter
2917    /// immediately. Otherwise, it should enqueue a repaint and use the
2918    /// placeholder tree update from [`Context::accesskit_placeholder_tree_update`]
2919    /// in the meantime.
2920    #[cfg(feature = "accesskit")]
2921    pub fn enable_accesskit(&self) {
2922        self.write(|ctx| ctx.is_accesskit_enabled = true);
2923    }
2924
2925    /// Return a tree update that the egui integration should provide to the
2926    /// AccessKit adapter if it cannot immediately run the egui application
2927    /// to get a full tree update after running [`Context::enable_accesskit`].
2928    #[cfg(feature = "accesskit")]
2929    pub fn accesskit_placeholder_tree_update(&self) -> accesskit::TreeUpdate {
2930        crate::profile_function!();
2931
2932        use accesskit::{NodeBuilder, Role, Tree, TreeUpdate};
2933
2934        let root_id = crate::accesskit_root_id().accesskit_id();
2935        self.write(|ctx| TreeUpdate {
2936            nodes: vec![(
2937                root_id,
2938                NodeBuilder::new(Role::Window).build(&mut ctx.accesskit_node_classes),
2939            )],
2940            tree: Some(Tree::new(root_id)),
2941            focus: root_id,
2942        })
2943    }
2944}
2945
2946/// ## Image loading
2947impl Context {
2948    /// Associate some static bytes with a `uri`.
2949    ///
2950    /// The same `uri` may be passed to [`Ui::image`] later to load the bytes as an image.
2951    ///
2952    /// By convention, the `uri` should start with `bytes://`.
2953    /// Following that convention will lead to better error messages.
2954    pub fn include_bytes(&self, uri: impl Into<Cow<'static, str>>, bytes: impl Into<Bytes>) {
2955        self.loaders().include.insert(uri, bytes);
2956    }
2957
2958    /// Returns `true` if the chain of bytes, image, or texture loaders
2959    /// contains a loader with the given `id`.
2960    pub fn is_loader_installed(&self, id: &str) -> bool {
2961        let loaders = self.loaders();
2962
2963        loaders.bytes.lock().iter().any(|l| l.id() == id)
2964            || loaders.image.lock().iter().any(|l| l.id() == id)
2965            || loaders.texture.lock().iter().any(|l| l.id() == id)
2966    }
2967
2968    /// Add a new bytes loader.
2969    ///
2970    /// It will be tried first, before any already installed loaders.
2971    ///
2972    /// See [`load`] for more information.
2973    pub fn add_bytes_loader(&self, loader: Arc<dyn load::BytesLoader + Send + Sync + 'static>) {
2974        self.loaders().bytes.lock().push(loader);
2975    }
2976
2977    /// Add a new image loader.
2978    ///
2979    /// It will be tried first, before any already installed loaders.
2980    ///
2981    /// See [`load`] for more information.
2982    pub fn add_image_loader(&self, loader: Arc<dyn load::ImageLoader + Send + Sync + 'static>) {
2983        self.loaders().image.lock().push(loader);
2984    }
2985
2986    /// Add a new texture loader.
2987    ///
2988    /// It will be tried first, before any already installed loaders.
2989    ///
2990    /// See [`load`] for more information.
2991    pub fn add_texture_loader(&self, loader: Arc<dyn load::TextureLoader + Send + Sync + 'static>) {
2992        self.loaders().texture.lock().push(loader);
2993    }
2994
2995    /// Release all memory and textures related to the given image URI.
2996    ///
2997    /// If you attempt to load the image again, it will be reloaded from scratch.
2998    pub fn forget_image(&self, uri: &str) {
2999        use load::BytesLoader as _;
3000
3001        crate::profile_function!();
3002
3003        let loaders = self.loaders();
3004
3005        loaders.include.forget(uri);
3006        for loader in loaders.bytes.lock().iter() {
3007            loader.forget(uri);
3008        }
3009        for loader in loaders.image.lock().iter() {
3010            loader.forget(uri);
3011        }
3012        for loader in loaders.texture.lock().iter() {
3013            loader.forget(uri);
3014        }
3015    }
3016
3017    /// Release all memory and textures related to images used in [`Ui::image`] or [`Image`].
3018    ///
3019    /// If you attempt to load any images again, they will be reloaded from scratch.
3020    pub fn forget_all_images(&self) {
3021        use load::BytesLoader as _;
3022
3023        crate::profile_function!();
3024
3025        let loaders = self.loaders();
3026
3027        loaders.include.forget_all();
3028        for loader in loaders.bytes.lock().iter() {
3029            loader.forget_all();
3030        }
3031        for loader in loaders.image.lock().iter() {
3032            loader.forget_all();
3033        }
3034        for loader in loaders.texture.lock().iter() {
3035            loader.forget_all();
3036        }
3037    }
3038
3039    /// Try loading the bytes from the given uri using any available bytes loaders.
3040    ///
3041    /// Loaders are expected to cache results, so that this call is immediate-mode safe.
3042    ///
3043    /// This calls the loaders one by one in the order in which they were registered.
3044    /// If a loader returns [`LoadError::NotSupported`][not_supported],
3045    /// then the next loader is called. This process repeats until all loaders have
3046    /// been exhausted, at which point this returns [`LoadError::NotSupported`][not_supported].
3047    ///
3048    /// # Errors
3049    /// This may fail with:
3050    /// - [`LoadError::NotSupported`][not_supported] if none of the registered loaders support loading the given `uri`.
3051    /// - [`LoadError::Loading`][custom] if one of the loaders _does_ support loading the `uri`, but the loading process failed.
3052    ///
3053    /// ⚠ May deadlock if called from within a `BytesLoader`!
3054    ///
3055    /// [not_supported]: crate::load::LoadError::NotSupported
3056    /// [custom]: crate::load::LoadError::Loading
3057    pub fn try_load_bytes(&self, uri: &str) -> load::BytesLoadResult {
3058        crate::profile_function!(uri);
3059
3060        let loaders = self.loaders();
3061        let bytes_loaders = loaders.bytes.lock();
3062
3063        // Try most recently added loaders first (hence `.rev()`)
3064        for loader in bytes_loaders.iter().rev() {
3065            match loader.load(self, uri) {
3066                Err(load::LoadError::NotSupported) => continue,
3067                result => return result,
3068            }
3069        }
3070
3071        Err(load::LoadError::NoMatchingBytesLoader)
3072    }
3073
3074    /// Try loading the image from the given uri using any available image loaders.
3075    ///
3076    /// Loaders are expected to cache results, so that this call is immediate-mode safe.
3077    ///
3078    /// This calls the loaders one by one in the order in which they were registered.
3079    /// If a loader returns [`LoadError::NotSupported`][not_supported],
3080    /// then the next loader is called. This process repeats until all loaders have
3081    /// been exhausted, at which point this returns [`LoadError::NotSupported`][not_supported].
3082    ///
3083    /// # Errors
3084    /// This may fail with:
3085    /// - [`LoadError::NoImageLoaders`][no_image_loaders] if tbere are no registered image loaders.
3086    /// - [`LoadError::NotSupported`][not_supported] if none of the registered loaders support loading the given `uri`.
3087    /// - [`LoadError::Loading`][custom] if one of the loaders _does_ support loading the `uri`, but the loading process failed.
3088    ///
3089    /// ⚠ May deadlock if called from within an `ImageLoader`!
3090    ///
3091    /// [no_image_loaders]: crate::load::LoadError::NoImageLoaders
3092    /// [not_supported]: crate::load::LoadError::NotSupported
3093    /// [custom]: crate::load::LoadError::Loading
3094    pub fn try_load_image(&self, uri: &str, size_hint: load::SizeHint) -> load::ImageLoadResult {
3095        crate::profile_function!(uri);
3096
3097        let loaders = self.loaders();
3098        let image_loaders = loaders.image.lock();
3099        if image_loaders.is_empty() {
3100            return Err(load::LoadError::NoImageLoaders);
3101        }
3102
3103        // Try most recently added loaders first (hence `.rev()`)
3104        for loader in image_loaders.iter().rev() {
3105            match loader.load(self, uri, size_hint) {
3106                Err(load::LoadError::NotSupported) => continue,
3107                result => return result,
3108            }
3109        }
3110
3111        Err(load::LoadError::NoMatchingImageLoader)
3112    }
3113
3114    /// Try loading the texture from the given uri using any available texture loaders.
3115    ///
3116    /// Loaders are expected to cache results, so that this call is immediate-mode safe.
3117    ///
3118    /// This calls the loaders one by one in the order in which they were registered.
3119    /// If a loader returns [`LoadError::NotSupported`][not_supported],
3120    /// then the next loader is called. This process repeats until all loaders have
3121    /// been exhausted, at which point this returns [`LoadError::NotSupported`][not_supported].
3122    ///
3123    /// # Errors
3124    /// This may fail with:
3125    /// - [`LoadError::NotSupported`][not_supported] if none of the registered loaders support loading the given `uri`.
3126    /// - [`LoadError::Loading`][custom] if one of the loaders _does_ support loading the `uri`, but the loading process failed.
3127    ///
3128    /// ⚠ May deadlock if called from within a `TextureLoader`!
3129    ///
3130    /// [not_supported]: crate::load::LoadError::NotSupported
3131    /// [custom]: crate::load::LoadError::Loading
3132    pub fn try_load_texture(
3133        &self,
3134        uri: &str,
3135        texture_options: TextureOptions,
3136        size_hint: load::SizeHint,
3137    ) -> load::TextureLoadResult {
3138        crate::profile_function!(uri);
3139
3140        let loaders = self.loaders();
3141        let texture_loaders = loaders.texture.lock();
3142
3143        // Try most recently added loaders first (hence `.rev()`)
3144        for loader in texture_loaders.iter().rev() {
3145            match loader.load(self, uri, texture_options, size_hint) {
3146                Err(load::LoadError::NotSupported) => continue,
3147                result => return result,
3148            }
3149        }
3150
3151        Err(load::LoadError::NoMatchingTextureLoader)
3152    }
3153
3154    /// The loaders of bytes, images, and textures.
3155    pub fn loaders(&self) -> Arc<Loaders> {
3156        crate::profile_function!();
3157        self.read(|this| this.loaders.clone())
3158    }
3159}
3160
3161/// ## Viewports
3162impl Context {
3163    /// Return the `ViewportId` of the current viewport.
3164    ///
3165    /// If this is the root viewport, this will return [`ViewportId::ROOT`].
3166    ///
3167    /// Don't use this outside of `Self::run`, or after `Self::end_frame`.
3168    pub fn viewport_id(&self) -> ViewportId {
3169        self.read(|ctx| ctx.viewport_id())
3170    }
3171
3172    /// Return the `ViewportId` of his parent.
3173    ///
3174    /// If this is the root viewport, this will return [`ViewportId::ROOT`].
3175    ///
3176    /// Don't use this outside of `Self::run`, or after `Self::end_frame`.
3177    pub fn parent_viewport_id(&self) -> ViewportId {
3178        self.read(|ctx| ctx.parent_viewport_id())
3179    }
3180
3181    /// Read the state of the current viewport.
3182    pub fn viewport<R>(&self, reader: impl FnOnce(&ViewportState) -> R) -> R {
3183        self.write(|ctx| reader(ctx.viewport()))
3184    }
3185
3186    /// Read the state of a specific current viewport.
3187    pub fn viewport_for<R>(
3188        &self,
3189        viewport_id: ViewportId,
3190        reader: impl FnOnce(&ViewportState) -> R,
3191    ) -> R {
3192        self.write(|ctx| reader(ctx.viewport_for(viewport_id)))
3193    }
3194
3195    /// For integrations: Set this to render a sync viewport.
3196    ///
3197    /// This will only set the callback for the current thread,
3198    /// which most likely should be the main thread.
3199    ///
3200    /// When an immediate viewport is created with [`Self::show_viewport_immediate`] it will be rendered by this function.
3201    ///
3202    /// When called, the integration needs to:
3203    /// * Check if there already is a window for this viewport id, and if not open one
3204    /// * Set the window attributes (position, size, …) based on [`ImmediateViewport::builder`].
3205    /// * Call [`Context::run`] with [`ImmediateViewport::viewport_ui_cb`].
3206    /// * Handle the output from [`Context::run`], including rendering
3207    #[allow(clippy::unused_self)]
3208    pub fn set_immediate_viewport_renderer(
3209        callback: impl for<'a> Fn(&Self, ImmediateViewport<'a>) + 'static,
3210    ) {
3211        let callback = Box::new(callback);
3212        IMMEDIATE_VIEWPORT_RENDERER.with(|render_sync| {
3213            render_sync.replace(Some(callback));
3214        });
3215    }
3216
3217    /// If `true`, [`Self::show_viewport_deferred`] and [`Self::show_viewport_immediate`] will
3218    /// embed the new viewports inside the existing one, instead of spawning a new native window.
3219    ///
3220    /// `eframe` sets this to `false` on supported platforms, but the default value is `true`.
3221    pub fn embed_viewports(&self) -> bool {
3222        self.read(|ctx| ctx.embed_viewports)
3223    }
3224
3225    /// If `true`, [`Self::show_viewport_deferred`] and [`Self::show_viewport_immediate`] will
3226    /// embed the new viewports inside the existing one, instead of spawning a new native window.
3227    ///
3228    /// `eframe` sets this to `false` on supported platforms, but the default value is `true`.
3229    pub fn set_embed_viewports(&self, value: bool) {
3230        self.write(|ctx| ctx.embed_viewports = value);
3231    }
3232
3233    /// Send a command to the current viewport.
3234    ///
3235    /// This lets you affect the current viewport, e.g. resizing the window.
3236    pub fn send_viewport_cmd(&self, command: ViewportCommand) {
3237        self.send_viewport_cmd_to(self.viewport_id(), command);
3238    }
3239
3240    /// Send a command to a specific viewport.
3241    ///
3242    /// This lets you affect another viewport, e.g. resizing its window.
3243    pub fn send_viewport_cmd_to(&self, id: ViewportId, command: ViewportCommand) {
3244        self.request_repaint_of(id);
3245
3246        if command.requires_parent_repaint() {
3247            self.request_repaint_of(self.parent_viewport_id());
3248        }
3249
3250        self.write(|ctx| ctx.viewport_for(id).commands.push(command));
3251    }
3252
3253    /// Show a deferred viewport, creating a new native window, if possible.
3254    ///
3255    /// The given id must be unique for each viewport.
3256    ///
3257    /// You need to call this each frame when the child viewport should exist.
3258    ///
3259    /// You can check if the user wants to close the viewport by checking the
3260    /// [`crate::ViewportInfo::close_requested`] flags found in [`crate::InputState::viewport`].
3261    ///
3262    /// The given callback will be called whenever the child viewport needs repainting,
3263    /// e.g. on an event or when [`Self::request_repaint`] is called.
3264    /// This means it may be called multiple times, for instance while the
3265    /// parent viewport (the caller) is sleeping but the child viewport is animating.
3266    ///
3267    /// You will need to wrap your viewport state in an `Arc<RwLock<T>>` or `Arc<Mutex<T>>`.
3268    /// When this is called again with the same id in `ViewportBuilder` the render function for that viewport will be updated.
3269    ///
3270    /// You can also use [`Self::show_viewport_immediate`], which uses a simpler `FnOnce`
3271    /// with no need for `Send` or `Sync`. The downside is that it will require
3272    /// the parent viewport (the caller) to repaint anytime the child is repainted,
3273    /// and vice versa.
3274    ///
3275    /// If [`Context::embed_viewports`] is `true` (e.g. if the current egui
3276    /// backend does not support multiple viewports), the given callback
3277    /// will be called immediately, embedding the new viewport in the current one.
3278    /// You can check this with the [`ViewportClass`] given in the callback.
3279    /// If you find [`ViewportClass::Embedded`], you need to create a new [`crate::Window`] for you content.
3280    ///
3281    /// See [`crate::viewport`] for more information about viewports.
3282    pub fn show_viewport_deferred(
3283        &self,
3284        new_viewport_id: ViewportId,
3285        viewport_builder: ViewportBuilder,
3286        viewport_ui_cb: impl Fn(&Self, ViewportClass) + Send + Sync + 'static,
3287    ) {
3288        crate::profile_function!();
3289
3290        if self.embed_viewports() {
3291            viewport_ui_cb(self, ViewportClass::Embedded);
3292        } else {
3293            self.write(|ctx| {
3294                ctx.viewport_parents
3295                    .insert(new_viewport_id, ctx.viewport_id());
3296
3297                let viewport = ctx.viewports.entry(new_viewport_id).or_default();
3298                viewport.class = ViewportClass::Deferred;
3299                viewport.builder = viewport_builder;
3300                viewport.used = true;
3301                viewport.viewport_ui_cb = Some(Arc::new(move |ctx| {
3302                    (viewport_ui_cb)(ctx, ViewportClass::Deferred);
3303                }));
3304            });
3305        }
3306    }
3307
3308    /// Show an immediate viewport, creating a new native window, if possible.
3309    ///
3310    /// This is the easier type of viewport to use, but it is less performant
3311    /// at it requires both parent and child to repaint if any one of them needs repainting,
3312    /// which efficvely produce double work for two viewports, and triple work for three viewports, etc.
3313    /// To avoid this, use [`Self::show_viewport_deferred`] instead.
3314    ///
3315    /// The given id must be unique for each viewport.
3316    ///
3317    /// You need to call this each frame when the child viewport should exist.
3318    ///
3319    /// You can check if the user wants to close the viewport by checking the
3320    /// [`crate::ViewportInfo::close_requested`] flags found in [`crate::InputState::viewport`].
3321    ///
3322    /// The given ui function will be called immediately.
3323    /// This may only be called on the main thread.
3324    /// This call will pause the current viewport and render the child viewport in its own window.
3325    /// This means that the child viewport will not be repainted when the parent viewport is repainted, and vice versa.
3326    ///
3327    /// If [`Context::embed_viewports`] is `true` (e.g. if the current egui
3328    /// backend does not support multiple viewports), the given callback
3329    /// will be called immediately, embedding the new viewport in the current one.
3330    /// You can check this with the [`ViewportClass`] given in the callback.
3331    /// If you find [`ViewportClass::Embedded`], you need to create a new [`crate::Window`] for you content.
3332    ///
3333    /// See [`crate::viewport`] for more information about viewports.
3334    pub fn show_viewport_immediate<T>(
3335        &self,
3336        new_viewport_id: ViewportId,
3337        builder: ViewportBuilder,
3338        viewport_ui_cb: impl FnOnce(&Self, ViewportClass) -> T,
3339    ) -> T {
3340        crate::profile_function!();
3341
3342        if self.embed_viewports() {
3343            return viewport_ui_cb(self, ViewportClass::Embedded);
3344        }
3345
3346        IMMEDIATE_VIEWPORT_RENDERER.with(|immediate_viewport_renderer| {
3347            let immediate_viewport_renderer = immediate_viewport_renderer.borrow();
3348            let Some(immediate_viewport_renderer) = immediate_viewport_renderer.as_ref() else {
3349                // This egui backend does not support multiple viewports.
3350                return viewport_ui_cb(self, ViewportClass::Embedded);
3351            };
3352
3353            let ids = self.write(|ctx| {
3354                let parent_viewport_id = ctx.viewport_id();
3355
3356                ctx.viewport_parents
3357                    .insert(new_viewport_id, parent_viewport_id);
3358
3359                let viewport = ctx.viewports.entry(new_viewport_id).or_default();
3360                viewport.builder = builder.clone();
3361                viewport.used = true;
3362                viewport.viewport_ui_cb = None; // it is immediate
3363
3364                ViewportIdPair::from_self_and_parent(new_viewport_id, parent_viewport_id)
3365            });
3366
3367            let mut out = None;
3368            {
3369                let out = &mut out;
3370
3371                let viewport = ImmediateViewport {
3372                    ids,
3373                    builder,
3374                    viewport_ui_cb: Box::new(move |context| {
3375                        *out = Some(viewport_ui_cb(context, ViewportClass::Immediate));
3376                    }),
3377                };
3378
3379                immediate_viewport_renderer(self, viewport);
3380            }
3381
3382            out.expect(
3383                "egui backend is implemented incorrectly - the user callback was never called",
3384            )
3385        })
3386    }
3387}
3388
3389/// ## Interaction
3390impl Context {
3391    /// Read you what widgets are currently being interacted with.
3392    pub fn interaction_snapshot<R>(&self, reader: impl FnOnce(&InteractionSnapshot) -> R) -> R {
3393        self.write(|w| reader(&w.viewport().interact_widgets))
3394    }
3395
3396    /// The widget currently being dragged, if any.
3397    ///
3398    /// For widgets that sense both clicks and drags, this will
3399    /// not be set until the mouse cursor has moved a certain distance.
3400    ///
3401    /// NOTE: if the widget was released this frame, this will be `None`.
3402    /// Use [`Self::drag_stopped_id`] instead.
3403    pub fn dragged_id(&self) -> Option<Id> {
3404        self.interaction_snapshot(|i| i.dragged)
3405    }
3406
3407    /// Is this specific widget being dragged?
3408    ///
3409    /// A widget that sense both clicks and drags is only marked as "dragged"
3410    /// when the mouse has moved a bit
3411    ///
3412    /// See also: [`crate::Response::dragged`].
3413    pub fn is_being_dragged(&self, id: Id) -> bool {
3414        self.dragged_id() == Some(id)
3415    }
3416
3417    /// This widget just started being dragged this frame.
3418    ///
3419    /// The same widget should also be found in [`Self::dragged_id`].
3420    pub fn drag_started_id(&self) -> Option<Id> {
3421        self.interaction_snapshot(|i| i.drag_started)
3422    }
3423
3424    /// This widget was being dragged, but was released this frame
3425    pub fn drag_stopped_id(&self) -> Option<Id> {
3426        self.interaction_snapshot(|i| i.drag_stopped)
3427    }
3428
3429    /// Set which widget is being dragged.
3430    pub fn set_dragged_id(&self, id: Id) {
3431        self.write(|ctx| {
3432            let vp = ctx.viewport();
3433            let i = &mut vp.interact_widgets;
3434            if i.dragged != Some(id) {
3435                i.drag_stopped = i.dragged.or(i.drag_stopped);
3436                i.dragged = Some(id);
3437                i.drag_started = Some(id);
3438            }
3439
3440            ctx.memory.interaction_mut().potential_drag_id = Some(id);
3441        });
3442    }
3443
3444    /// Stop dragging any widget.
3445    pub fn stop_dragging(&self) {
3446        self.write(|ctx| {
3447            let vp = ctx.viewport();
3448            let i = &mut vp.interact_widgets;
3449            if i.dragged.is_some() {
3450                i.drag_stopped = i.dragged;
3451                i.dragged = None;
3452            }
3453
3454            ctx.memory.interaction_mut().potential_drag_id = None;
3455        });
3456    }
3457
3458    /// Is something else being dragged?
3459    ///
3460    /// Returns true if we are dragging something, but not the given widget.
3461    #[inline(always)]
3462    pub fn dragging_something_else(&self, not_this: Id) -> bool {
3463        let dragged = self.dragged_id();
3464        dragged.is_some() && dragged != Some(not_this)
3465    }
3466}
3467
3468#[test]
3469fn context_impl_send_sync() {
3470    fn assert_send_sync<T: Send + Sync>() {}
3471    assert_send_sync::<Context>();
3472}