1#![warn(missing_docs)] use ahash::{HashMap, HashSet};
4use epaint::emath::TSTransform;
5
6use crate::{
7 area, vec2, EventFilter, Id, IdMap, LayerId, Order, Pos2, Rangef, RawInput, Rect, Style, Vec2,
8 ViewportId, ViewportIdMap, ViewportIdSet,
9};
10
11#[derive(Clone, Debug)]
23#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
24#[cfg_attr(feature = "persistence", serde(default))]
25pub struct Memory {
26 pub options: Options,
28
29 pub data: crate::util::IdTypeMap,
43
44 #[cfg_attr(feature = "persistence", serde(skip))]
70 pub caches: crate::util::cache::CacheStorage,
71
72 #[cfg_attr(feature = "persistence", serde(skip))]
75 pub(crate) new_font_definitions: Option<epaint::text::FontDefinitions>,
76
77 #[cfg_attr(feature = "persistence", serde(skip))]
79 pub(crate) viewport_id: ViewportId,
80
81 #[cfg_attr(feature = "persistence", serde(skip))]
84 popup: Option<Id>,
85
86 #[cfg_attr(feature = "persistence", serde(skip))]
87 everything_is_visible: bool,
88
89 pub layer_transforms: HashMap<LayerId, TSTransform>,
91
92 areas: ViewportIdMap<Areas>,
95
96 #[cfg_attr(feature = "persistence", serde(skip))]
97 pub(crate) interactions: ViewportIdMap<InteractionState>,
98
99 #[cfg_attr(feature = "persistence", serde(skip))]
100 pub(crate) focus: ViewportIdMap<Focus>,
101}
102
103impl Default for Memory {
104 fn default() -> Self {
105 let mut slf = Self {
106 options: Default::default(),
107 data: Default::default(),
108 caches: Default::default(),
109 new_font_definitions: Default::default(),
110 interactions: Default::default(),
111 focus: Default::default(),
112 viewport_id: Default::default(),
113 areas: Default::default(),
114 layer_transforms: Default::default(),
115 popup: Default::default(),
116 everything_is_visible: Default::default(),
117 };
118 slf.interactions.entry(slf.viewport_id).or_default();
119 slf.areas.entry(slf.viewport_id).or_default();
120 slf
121 }
122}
123
124#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
125enum FocusDirection {
126 Up,
128
129 Right,
131
132 Down,
134
135 Left,
137
138 Previous,
140
141 Next,
143
144 #[default]
146 None,
147}
148
149impl FocusDirection {
150 fn is_cardinal(&self) -> bool {
151 match self {
152 Self::Up | Self::Right | Self::Down | Self::Left => true,
153
154 Self::Previous | Self::Next | Self::None => false,
155 }
156 }
157}
158
159#[derive(Clone, Debug, PartialEq)]
165#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
166#[cfg_attr(feature = "serde", serde(default))]
167pub struct Options {
168 #[cfg_attr(feature = "serde", serde(skip))]
170 pub(crate) style: std::sync::Arc<Style>,
171
172 pub zoom_factor: f32,
183
184 #[cfg_attr(feature = "serde", serde(skip))]
195 pub zoom_with_keyboard: bool,
196
197 pub tessellation_options: epaint::TessellationOptions,
199
200 pub repaint_on_widget_change: bool,
206
207 pub screen_reader: bool,
217
218 pub preload_font_glyphs: bool,
225
226 pub warn_on_id_clash: bool,
230
231 pub line_scroll_speed: f32,
235
236 pub scroll_zoom_speed: f32,
238
239 pub reduce_texture_memory: bool,
251}
252
253impl Default for Options {
254 fn default() -> Self {
255 let is_web = cfg!(target_arch = "wasm32");
257 let line_scroll_speed = if is_web {
258 8.0
259 } else {
260 40.0 };
262
263 Self {
264 style: Default::default(),
265 zoom_factor: 1.0,
266 zoom_with_keyboard: true,
267 tessellation_options: Default::default(),
268 repaint_on_widget_change: false,
269 screen_reader: false,
270 preload_font_glyphs: true,
271 warn_on_id_clash: cfg!(debug_assertions),
272
273 line_scroll_speed,
275 scroll_zoom_speed: 1.0 / 200.0,
276 reduce_texture_memory: false,
277 }
278 }
279}
280
281impl Options {
282 pub fn ui(&mut self, ui: &mut crate::Ui) {
284 let Self {
285 style, zoom_factor: _, zoom_with_keyboard,
288 tessellation_options,
289 repaint_on_widget_change,
290 screen_reader: _, preload_font_glyphs: _,
292 warn_on_id_clash,
293
294 line_scroll_speed,
295 scroll_zoom_speed,
296 reduce_texture_memory,
297 } = self;
298
299 use crate::Widget as _;
300
301 CollapsingHeader::new("⚙ Options")
302 .default_open(false)
303 .show(ui, |ui| {
304 ui.checkbox(
305 repaint_on_widget_change,
306 "Repaint if any widget moves or changes id",
307 );
308
309 ui.checkbox(
310 zoom_with_keyboard,
311 "Zoom with keyboard (Cmd +, Cmd -, Cmd 0)",
312 );
313
314 ui.checkbox(warn_on_id_clash, "Warn if two widgets have the same Id");
315
316 ui.checkbox(reduce_texture_memory, "Reduce texture memory");
317 });
318
319 use crate::containers::*;
320 CollapsingHeader::new("🎑 Style")
321 .default_open(true)
322 .show(ui, |ui| {
323 std::sync::Arc::make_mut(style).ui(ui);
324 });
325
326 CollapsingHeader::new("✒ Painting")
327 .default_open(false)
328 .show(ui, |ui| {
329 tessellation_options.ui(ui);
330 ui.vertical_centered(|ui| {
331 crate::reset_button(ui, tessellation_options, "Reset paint settings");
332 });
333 });
334
335 CollapsingHeader::new("🖱 Input")
336 .default_open(false)
337 .show(ui, |ui| {
338 ui.horizontal(|ui| {
339 ui.label("Line scroll speed");
340 ui.add(crate::DragValue::new(line_scroll_speed).range(0.0..=f32::INFINITY))
341 .on_hover_text(
342 "How many lines to scroll with each tick of the mouse wheel",
343 );
344 });
345 ui.horizontal(|ui| {
346 ui.label("Scroll zoom speed");
347 ui.add(
348 crate::DragValue::new(scroll_zoom_speed)
349 .range(0.0..=f32::INFINITY)
350 .speed(0.001),
351 )
352 .on_hover_text("How fast to zoom with ctrl/cmd + scroll");
353 });
354 });
355
356 ui.vertical_centered(|ui| crate::reset_button(ui, self, "Reset all"));
357 }
358}
359
360#[derive(Clone, Debug, Default)]
373pub(crate) struct InteractionState {
374 pub potential_click_id: Option<Id>,
376
377 pub potential_drag_id: Option<Id>,
384}
385
386#[derive(Clone, Debug, Default)]
388pub(crate) struct Focus {
389 focused_widget: Option<FocusWidget>,
391
392 id_previous_frame: Option<Id>,
394
395 id_next_frame: Option<Id>,
397
398 #[cfg(feature = "accesskit")]
399 id_requested_by_accesskit: Option<accesskit::NodeId>,
400
401 give_to_next: bool,
404
405 last_interested: Option<Id>,
407
408 focus_direction: FocusDirection,
410
411 focus_widgets_cache: IdMap<Rect>,
413}
414
415#[derive(Clone, Copy, Debug)]
417struct FocusWidget {
418 pub id: Id,
419 pub filter: EventFilter,
420}
421
422impl FocusWidget {
423 pub fn new(id: Id) -> Self {
424 Self {
425 id,
426 filter: Default::default(),
427 }
428 }
429}
430
431impl InteractionState {
432 pub fn is_using_pointer(&self) -> bool {
434 self.potential_click_id.is_some() || self.potential_drag_id.is_some()
435 }
436}
437
438impl Focus {
439 pub fn focused(&self) -> Option<Id> {
441 self.focused_widget.as_ref().map(|w| w.id)
442 }
443
444 fn begin_frame(&mut self, new_input: &crate::data::input::RawInput) {
445 self.id_previous_frame = self.focused();
446 if let Some(id) = self.id_next_frame.take() {
447 self.focused_widget = Some(FocusWidget::new(id));
448 }
449 let event_filter = self.focused_widget.map(|w| w.filter).unwrap_or_default();
450
451 #[cfg(feature = "accesskit")]
452 {
453 self.id_requested_by_accesskit = None;
454 }
455
456 self.focus_direction = FocusDirection::None;
457
458 for event in &new_input.events {
459 if !event_filter.matches(event) {
460 if let crate::Event::Key {
461 key,
462 pressed: true,
463 modifiers,
464 ..
465 } = event
466 {
467 if let Some(cardinality) = match key {
468 crate::Key::ArrowUp => Some(FocusDirection::Up),
469 crate::Key::ArrowRight => Some(FocusDirection::Right),
470 crate::Key::ArrowDown => Some(FocusDirection::Down),
471 crate::Key::ArrowLeft => Some(FocusDirection::Left),
472
473 crate::Key::Tab => {
474 if modifiers.shift {
475 Some(FocusDirection::Previous)
476 } else {
477 Some(FocusDirection::Next)
478 }
479 }
480 crate::Key::Escape => {
481 self.focused_widget = None;
482 Some(FocusDirection::None)
483 }
484 _ => None,
485 } {
486 self.focus_direction = cardinality;
487 }
488 }
489 }
490
491 #[cfg(feature = "accesskit")]
492 {
493 if let crate::Event::AccessKitActionRequest(accesskit::ActionRequest {
494 action: accesskit::Action::Focus,
495 target,
496 data: None,
497 }) = event
498 {
499 self.id_requested_by_accesskit = Some(*target);
500 }
501 }
502 }
503 }
504
505 pub(crate) fn end_frame(&mut self, used_ids: &IdMap<Rect>) {
506 if self.focus_direction.is_cardinal() {
507 if let Some(found_widget) = self.find_widget_in_direction(used_ids) {
508 self.focused_widget = Some(FocusWidget::new(found_widget));
509 }
510 }
511
512 if let Some(focused_widget) = self.focused_widget {
513 let recently_gained_focus = self.id_previous_frame != Some(focused_widget.id);
515
516 if !recently_gained_focus && !used_ids.contains_key(&focused_widget.id) {
517 self.focused_widget = None;
519 }
520 }
521 }
522
523 pub(crate) fn had_focus_last_frame(&self, id: Id) -> bool {
524 self.id_previous_frame == Some(id)
525 }
526
527 fn interested_in_focus(&mut self, id: Id) {
528 #[cfg(feature = "accesskit")]
529 {
530 if self.id_requested_by_accesskit == Some(id.accesskit_id()) {
531 self.focused_widget = Some(FocusWidget::new(id));
532 self.id_requested_by_accesskit = None;
533 self.give_to_next = false;
534 self.reset_focus();
535 }
536 }
537
538 self.focus_widgets_cache
540 .entry(id)
541 .or_insert(Rect::EVERYTHING);
542
543 if self.give_to_next && !self.had_focus_last_frame(id) {
544 self.focused_widget = Some(FocusWidget::new(id));
545 self.give_to_next = false;
546 } else if self.focused() == Some(id) {
547 if self.focus_direction == FocusDirection::Next {
548 self.focused_widget = None;
549 self.give_to_next = true;
550 self.reset_focus();
551 } else if self.focus_direction == FocusDirection::Previous {
552 self.id_next_frame = self.last_interested; self.reset_focus();
554 }
555 } else if self.focus_direction == FocusDirection::Next
556 && self.focused_widget.is_none()
557 && !self.give_to_next
558 {
559 self.focused_widget = Some(FocusWidget::new(id));
561 self.reset_focus();
562 } else if self.focus_direction == FocusDirection::Previous
563 && self.focused_widget.is_none()
564 && !self.give_to_next
565 {
566 self.focused_widget = self.last_interested.map(FocusWidget::new);
568 self.reset_focus();
569 }
570
571 self.last_interested = Some(id);
572 }
573
574 fn reset_focus(&mut self) {
575 self.focus_direction = FocusDirection::None;
576 }
577
578 fn find_widget_in_direction(&mut self, new_rects: &IdMap<Rect>) -> Option<Id> {
579 fn range_diff(a: Rangef, b: Rangef) -> f32 {
585 let has_significant_overlap = a.intersection(b).span() >= 0.5 * b.span().min(a.span());
586 if has_significant_overlap {
587 0.0
588 } else {
589 a.center() - b.center()
590 }
591 }
592
593 let current_focused = self.focused_widget?;
594
595 let search_direction = match self.focus_direction {
597 FocusDirection::Up => Vec2::UP,
598 FocusDirection::Right => Vec2::RIGHT,
599 FocusDirection::Down => Vec2::DOWN,
600 FocusDirection::Left => Vec2::LEFT,
601 _ => {
602 return None;
603 }
604 };
605
606 self.focus_widgets_cache.retain(|id, old_rect| {
608 if let Some(new_rect) = new_rects.get(id) {
609 *old_rect = *new_rect;
610 true } else {
612 false }
614 });
615
616 let current_rect = self.focus_widgets_cache.get(¤t_focused.id)?;
617
618 let mut best_score = std::f32::INFINITY;
619 let mut best_id = None;
620
621 for (candidate_id, candidate_rect) in &self.focus_widgets_cache {
622 if *candidate_id == current_focused.id {
623 continue;
624 }
625
626 let to_candidate = vec2(
628 range_diff(candidate_rect.x_range(), current_rect.x_range()),
629 range_diff(candidate_rect.y_range(), current_rect.y_range()),
630 );
631
632 let acos_angle = to_candidate.normalized().dot(search_direction);
633
634 let is_in_search_cone = 0.5_f32.sqrt() <= acos_angle;
637 if is_in_search_cone {
638 let distance = to_candidate.length();
639
640 let score = distance / (acos_angle * acos_angle);
642
643 if score < best_score {
644 best_score = score;
645 best_id = Some(*candidate_id);
646 }
647 }
648 }
649
650 best_id
651 }
652}
653
654impl Memory {
655 pub(crate) fn begin_frame(&mut self, new_raw_input: &RawInput, viewports: &ViewportIdSet) {
656 crate::profile_function!();
657
658 self.viewport_id = new_raw_input.viewport_id;
659
660 self.interactions.retain(|id, _| viewports.contains(id));
662 self.areas.retain(|id, _| viewports.contains(id));
663
664 self.areas.entry(self.viewport_id).or_default();
665
666 self.focus
669 .entry(self.viewport_id)
670 .or_default()
671 .begin_frame(new_raw_input);
672 }
673
674 pub(crate) fn end_frame(&mut self, used_ids: &IdMap<Rect>) {
675 self.caches.update();
676 self.areas_mut().end_frame();
677 self.focus_mut().end_frame(used_ids);
678 }
679
680 pub(crate) fn set_viewport_id(&mut self, viewport_id: ViewportId) {
681 self.viewport_id = viewport_id;
682 }
683
684 pub fn areas(&self) -> &Areas {
686 self.areas
687 .get(&self.viewport_id)
688 .expect("Memory broken: no area for the current viewport")
689 }
690
691 pub fn areas_mut(&mut self) -> &mut Areas {
693 self.areas.entry(self.viewport_id).or_default()
694 }
695
696 pub fn layer_id_at(&self, pos: Pos2) -> Option<LayerId> {
698 self.areas().layer_id_at(pos, &self.layer_transforms)
699 }
700
701 pub fn layer_ids(&self) -> impl ExactSizeIterator<Item = LayerId> + '_ {
703 self.areas().order().iter().copied()
704 }
705
706 pub(crate) fn had_focus_last_frame(&self, id: Id) -> bool {
707 self.focus().and_then(|f| f.id_previous_frame) == Some(id)
708 }
709
710 pub(crate) fn lost_focus(&self, id: Id) -> bool {
712 self.had_focus_last_frame(id) && !self.has_focus(id)
713 }
714
715 pub(crate) fn gained_focus(&self, id: Id) -> bool {
717 !self.had_focus_last_frame(id) && self.has_focus(id)
718 }
719
720 #[inline(always)]
727 pub fn has_focus(&self, id: Id) -> bool {
728 self.focused() == Some(id)
729 }
730
731 pub fn focused(&self) -> Option<Id> {
733 self.focus().and_then(|f| f.focused())
734 }
735
736 pub fn set_focus_lock_filter(&mut self, id: Id, event_filter: EventFilter) {
743 if self.had_focus_last_frame(id) && self.has_focus(id) {
744 if let Some(focused) = &mut self.focus_mut().focused_widget {
745 if focused.id == id {
746 focused.filter = event_filter;
747 }
748 }
749 }
750 }
751
752 #[inline(always)]
755 pub fn request_focus(&mut self, id: Id) {
756 self.focus_mut().focused_widget = Some(FocusWidget::new(id));
757 }
758
759 #[inline(always)]
762 pub fn surrender_focus(&mut self, id: Id) {
763 let focus = self.focus_mut();
764 if focus.focused() == Some(id) {
765 focus.focused_widget = None;
766 }
767 }
768
769 #[inline(always)]
777 pub fn interested_in_focus(&mut self, id: Id) {
778 self.focus_mut().interested_in_focus(id);
779 }
780
781 #[inline(always)]
783 pub fn stop_text_input(&mut self) {
784 self.focus_mut().focused_widget = None;
785 }
786
787 #[deprecated = "Use `Context::dragged_id` instead"]
789 #[inline(always)]
790 pub fn is_anything_being_dragged(&self) -> bool {
791 self.interaction().potential_drag_id.is_some()
792 }
793
794 #[deprecated = "Use `Context::is_being_dragged` instead"]
801 #[inline(always)]
802 pub fn is_being_dragged(&self, id: Id) -> bool {
803 self.interaction().potential_drag_id == Some(id)
804 }
805
806 #[deprecated = "Use `Context::dragged_id` instead"]
813 #[inline(always)]
814 pub fn dragged_id(&self) -> Option<Id> {
815 self.interaction().potential_drag_id
816 }
817
818 #[inline(always)]
820 #[deprecated = "Use `Context::set_dragged_id` instead"]
821 pub fn set_dragged_id(&mut self, id: Id) {
822 self.interaction_mut().potential_drag_id = Some(id);
823 }
824
825 #[inline(always)]
827 #[deprecated = "Use `Context::stop_dragging` instead"]
828 pub fn stop_dragging(&mut self) {
829 self.interaction_mut().potential_drag_id = None;
830 }
831
832 #[inline(always)]
836 #[deprecated = "Use `Context::dragging_something_else` instead"]
837 pub fn dragging_something_else(&self, not_this: Id) -> bool {
838 let drag_id = self.interaction().potential_drag_id;
839 drag_id.is_some() && drag_id != Some(not_this)
840 }
841
842 pub fn reset_areas(&mut self) {
845 for area in self.areas.values_mut() {
846 *area = Default::default();
847 }
848 }
849
850 pub fn area_rect(&self, id: impl Into<Id>) -> Option<Rect> {
852 self.areas().get(id.into()).map(|state| state.rect())
853 }
854
855 pub(crate) fn interaction(&self) -> &InteractionState {
856 self.interactions
857 .get(&self.viewport_id)
858 .expect("Failed to get interaction")
859 }
860
861 pub(crate) fn interaction_mut(&mut self) -> &mut InteractionState {
862 self.interactions.entry(self.viewport_id).or_default()
863 }
864
865 pub(crate) fn focus(&self) -> Option<&Focus> {
866 self.focus.get(&self.viewport_id)
867 }
868
869 pub(crate) fn focus_mut(&mut self) -> &mut Focus {
870 self.focus.entry(self.viewport_id).or_default()
871 }
872}
873
874impl Memory {
878 pub fn is_popup_open(&self, popup_id: Id) -> bool {
880 self.popup == Some(popup_id) || self.everything_is_visible()
881 }
882
883 pub fn any_popup_open(&self) -> bool {
885 self.popup.is_some() || self.everything_is_visible()
886 }
887
888 pub fn open_popup(&mut self, popup_id: Id) {
890 self.popup = Some(popup_id);
891 }
892
893 pub fn close_popup(&mut self) {
895 self.popup = None;
896 }
897
898 pub fn toggle_popup(&mut self, popup_id: Id) {
902 if self.is_popup_open(popup_id) {
903 self.close_popup();
904 } else {
905 self.open_popup(popup_id);
906 }
907 }
908
909 #[inline(always)]
915 pub fn everything_is_visible(&self) -> bool {
916 self.everything_is_visible
917 }
918
919 pub fn set_everything_is_visible(&mut self, value: bool) {
925 self.everything_is_visible = value;
926 }
927}
928
929#[derive(Clone, Debug, Default)]
934#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
935#[cfg_attr(feature = "serde", serde(default))]
936pub struct Areas {
937 areas: IdMap<area::AreaState>,
938
939 order: Vec<LayerId>,
941
942 visible_last_frame: ahash::HashSet<LayerId>,
943 visible_current_frame: ahash::HashSet<LayerId>,
944
945 wants_to_be_on_top: ahash::HashSet<LayerId>,
951
952 sublayers: ahash::HashMap<LayerId, HashSet<LayerId>>,
956}
957
958impl Areas {
959 pub(crate) fn count(&self) -> usize {
960 self.areas.len()
961 }
962
963 pub(crate) fn get(&self, id: Id) -> Option<&area::AreaState> {
964 self.areas.get(&id)
965 }
966
967 pub(crate) fn order(&self) -> &[LayerId] {
969 &self.order
970 }
971
972 pub(crate) fn order_map(&self) -> HashMap<LayerId, usize> {
974 self.order
975 .iter()
976 .enumerate()
977 .map(|(i, id)| (*id, i))
978 .collect()
979 }
980
981 pub(crate) fn set_state(&mut self, layer_id: LayerId, state: area::AreaState) {
982 self.visible_current_frame.insert(layer_id);
983 self.areas.insert(layer_id.id, state);
984 if !self.order.iter().any(|x| *x == layer_id) {
985 self.order.push(layer_id);
986 }
987 }
988
989 pub fn layer_id_at(
991 &self,
992 pos: Pos2,
993 layer_transforms: &HashMap<LayerId, TSTransform>,
994 ) -> Option<LayerId> {
995 for layer in self.order.iter().rev() {
996 if self.is_visible(layer) {
997 if let Some(state) = self.areas.get(&layer.id) {
998 let mut rect = state.rect();
999 if state.interactable {
1000 if let Some(transform) = layer_transforms.get(layer) {
1001 rect = *transform * rect;
1002 }
1003
1004 if rect.contains(pos) {
1005 return Some(*layer);
1006 }
1007 }
1008 }
1009 }
1010 }
1011 None
1012 }
1013
1014 pub fn visible_last_frame(&self, layer_id: &LayerId) -> bool {
1015 self.visible_last_frame.contains(layer_id)
1016 }
1017
1018 pub fn is_visible(&self, layer_id: &LayerId) -> bool {
1019 self.visible_last_frame.contains(layer_id) || self.visible_current_frame.contains(layer_id)
1020 }
1021
1022 pub fn visible_layer_ids(&self) -> ahash::HashSet<LayerId> {
1023 self.visible_last_frame
1024 .iter()
1025 .copied()
1026 .chain(self.visible_current_frame.iter().copied())
1027 .collect()
1028 }
1029
1030 pub(crate) fn visible_windows(&self) -> impl Iterator<Item = (LayerId, &area::AreaState)> {
1031 self.visible_layer_ids()
1032 .into_iter()
1033 .filter(|layer| layer.order == crate::Order::Middle)
1034 .filter(|&layer| !self.is_sublayer(&layer))
1035 .filter_map(|layer| Some((layer, self.get(layer.id)?)))
1036 }
1037
1038 pub fn move_to_top(&mut self, layer_id: LayerId) {
1039 self.visible_current_frame.insert(layer_id);
1040 self.wants_to_be_on_top.insert(layer_id);
1041
1042 if !self.order.iter().any(|x| *x == layer_id) {
1043 self.order.push(layer_id);
1044 }
1045 }
1046
1047 pub fn set_sublayer(&mut self, parent: LayerId, child: LayerId) {
1055 self.sublayers.entry(parent).or_default().insert(child);
1056 }
1057
1058 pub fn top_layer_id(&self, order: Order) -> Option<LayerId> {
1059 self.order
1060 .iter()
1061 .filter(|layer| layer.order == order && !self.is_sublayer(layer))
1062 .last()
1063 .copied()
1064 }
1065
1066 pub(crate) fn is_sublayer(&self, layer: &LayerId) -> bool {
1067 self.sublayers
1068 .iter()
1069 .any(|(_, children)| children.contains(layer))
1070 }
1071
1072 pub(crate) fn end_frame(&mut self) {
1073 let Self {
1074 visible_last_frame,
1075 visible_current_frame,
1076 order,
1077 wants_to_be_on_top,
1078 sublayers,
1079 ..
1080 } = self;
1081
1082 std::mem::swap(visible_last_frame, visible_current_frame);
1083 visible_current_frame.clear();
1084 order.sort_by_key(|layer| (layer.order, wants_to_be_on_top.contains(layer)));
1085 wants_to_be_on_top.clear();
1086 let sublayers = std::mem::take(sublayers);
1088 for (parent, children) in sublayers {
1089 let mut moved_layers = vec![parent];
1090 order.retain(|l| {
1091 if children.contains(l) {
1092 moved_layers.push(*l);
1093 false
1094 } else {
1095 true
1096 }
1097 });
1098 let Some(parent_pos) = order.iter().position(|l| l == &parent) else {
1099 continue;
1100 };
1101 order.splice(parent_pos..=parent_pos, moved_layers);
1102 }
1103 }
1104}
1105
1106#[test]
1109fn memory_impl_send_sync() {
1110 fn assert_send_sync<T: Send + Sync>() {}
1111 assert_send_sync::<Memory>();
1112}