egui/
context.rs

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