1use std::{cell::RefCell, fmt::Debug, rc::Rc};
14
15use cranpose_core::{NodeId, collections::map::HashSet};
16use cranpose_foundation::{PointerButtons, PointerSource, RotaryScrollEvent};
17use cranpose_render_common::Renderer;
18use cranpose_ui::{
19 LayoutTree, PlatformTextInputHandler, SemanticsTree, pointer_icon_session::PointerIconState,
20};
21use cranpose_ui_graphics::{Point, PointerIcon, Size};
22use web_time::Instant;
23
24use crate::{
25 AppShell, DevOverlayControl, FramePacingMode, FrameRatePreference, FrameSchedule,
26 FrameScheduler, FrameUpdateResult, PlatformFrameDriver, ShellApp, SurfaceRoutingScratch,
27 hit_path_tracker::{HitPathTracker, PointerId},
28};
29
30#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
34pub enum RootId {
35 Primary,
37 Window(u64),
39}
40
41pub struct RootSurface<R: Renderer> {
49 pub(crate) id: RootId,
50 pub(crate) root: Option<NodeId>,
51 pub(crate) renderer: R,
52 pub(crate) cursor: (f32, f32),
53 pub(crate) viewport: (f32, f32),
54 pub(crate) buffer_size: (u32, u32),
55 pub(crate) layout_tree: Option<LayoutTree>,
56 pub(crate) semantics_tree: Option<SemanticsTree>,
57 semantics_moved: bool,
60 pub(crate) modal_focus: Vec<(NodeId, Option<NodeId>)>,
61 pub(crate) frame_rate_preference: FrameRatePreference,
62 pub(crate) scene_dirty: bool,
63 pub(crate) scoped_layout_scene_nodes: Vec<NodeId>,
64 pub(crate) scoped_moved_scene_nodes: Vec<NodeId>,
66 pub(crate) scoped_draw_nodes: Vec<NodeId>,
67 pub(crate) scoped_layer_property_nodes: Vec<NodeId>,
68 pub(crate) structural_scene_nodes: Vec<NodeId>,
69 pub(crate) partial_scene_nodes: Vec<NodeId>,
70 pub(crate) redraw_walk: Vec<NodeId>,
73 pub(crate) retained_visual_nodes: HashSet<NodeId>,
74 pub(crate) is_dirty: bool,
75 pub(crate) buttons_pressed: PointerButtons,
76 pub(crate) pointer_source: PointerSource,
77 pub(crate) hit_path_tracker: HitPathTracker,
78 pub(crate) hovered_nodes: Vec<NodeId>,
79 pub(crate) on_rotary_scroll: Option<Rc<dyn Fn(RotaryScrollEvent) -> bool>>,
80 pub(crate) dev_overlay_controls: Vec<DevOverlayControl>,
81 pub(crate) inspector: crate::inspector::DeveloperInspector,
82 pub(crate) dev_overlay_text: String,
83 pub(crate) dev_overlay_last_refresh: Option<Instant>,
84 pub(crate) dev_overlay_viewport: Option<Size>,
85 pub(crate) frame_scheduler: FrameScheduler,
86 pub(crate) pointer_icon: PointerIconState,
87 pub(crate) last_update: FrameUpdateResult,
88 pub(crate) frame_owed: bool,
89 pub(crate) screen_origin: Option<Point>,
90}
91
92impl<R: Renderer> RootSurface<R> {
93 pub(crate) fn new(
94 id: RootId,
95 renderer: R,
96 buffer_size: (u32, u32),
97 viewport: (f32, f32),
98 ) -> Self {
99 Self {
100 id,
101 root: None,
102 renderer,
103 cursor: (0.0, 0.0),
104 viewport,
105 buffer_size,
106 layout_tree: None,
107 semantics_tree: None,
108 semantics_moved: false,
109 modal_focus: Vec::new(),
110 frame_rate_preference: FrameRatePreference::default(),
111 scene_dirty: true,
112 scoped_layout_scene_nodes: Vec::new(),
113 scoped_moved_scene_nodes: Vec::new(),
114 scoped_draw_nodes: Vec::new(),
115 scoped_layer_property_nodes: Vec::new(),
116 structural_scene_nodes: Vec::new(),
117 partial_scene_nodes: Vec::new(),
118 redraw_walk: Vec::new(),
119 retained_visual_nodes: HashSet::default(),
120 is_dirty: true,
121 buttons_pressed: PointerButtons::NONE,
122 pointer_source: PointerSource::Unknown,
123 hit_path_tracker: HitPathTracker::new(),
124 hovered_nodes: Vec::new(),
125 on_rotary_scroll: None,
126 dev_overlay_controls: Vec::new(),
127 inspector: crate::inspector::DeveloperInspector::default(),
128 dev_overlay_text: String::new(),
129 dev_overlay_last_refresh: None,
130 dev_overlay_viewport: None,
131 frame_scheduler: FrameScheduler::default(),
132 pointer_icon: PointerIconState::new(),
133 last_update: FrameUpdateResult::default(),
134 frame_owed: false,
135 screen_origin: None,
136 }
137 }
138
139 pub(crate) fn root_node(&self, app: &ShellApp) -> Option<NodeId> {
140 match self.id {
141 RootId::Primary => app.composition.root(),
142 RootId::Window(_) => self.root,
143 }
144 }
145
146 pub(crate) fn owns_nodes_under(&self, window_root: Option<NodeId>) -> bool {
147 match self.id {
148 RootId::Primary => window_root.is_none(),
149 RootId::Window(_) => self.root.is_some() && self.root == window_root,
150 }
151 }
152
153 pub(crate) fn viewport_size(&self) -> Size {
154 Size {
155 width: self.viewport.0,
156 height: self.viewport.1,
157 }
158 }
159
160 pub(crate) fn screen_point_inside(&self, screen: Point) -> Option<Point> {
161 let origin = self.screen_origin?;
162 let local = Point {
163 x: screen.x - origin.x,
164 y: screen.y - origin.y,
165 };
166 (local.x >= 0.0
167 && local.y >= 0.0
168 && local.x <= self.viewport.0
169 && local.y <= self.viewport.1)
170 .then_some(local)
171 }
172
173 pub(crate) fn set_root(&mut self, root: Option<NodeId>) {
174 if self.root == root {
175 return;
176 }
177 self.root = root;
178 self.forget_snapshots();
179 self.invalidate_scene_root(root);
180 self.retained_visual_nodes.clear();
181 self.hit_path_tracker.clear();
182 self.hovered_nodes.clear();
183 self.buttons_pressed = PointerButtons::NONE;
184 self.is_dirty = true;
185 }
186
187 pub(crate) fn invalidate_scene_root(&mut self, root: Option<NodeId>) {
188 self.scoped_layout_scene_nodes.clear();
189 self.scoped_layout_scene_nodes.extend(root);
190 self.scoped_moved_scene_nodes.clear();
191 self.scoped_draw_nodes.clear();
192 self.scoped_layer_property_nodes.clear();
193 self.structural_scene_nodes.clear();
194 self.partial_scene_nodes.clear();
195 self.scene_dirty = true;
196 }
197
198 pub(crate) fn forget_snapshots(&mut self) {
201 self.layout_tree = None;
202 self.semantics_moved = true;
203 }
204
205 pub(crate) fn has_active_pointer_gesture(&self) -> bool {
206 self.buttons_pressed != PointerButtons::NONE
207 && self.hit_path_tracker.has_path(PointerId::PRIMARY)
208 }
209
210 pub(crate) fn renderer_warmup_due(&self, app: &ShellApp) -> bool {
211 self.renderer.needs_frame_warmup() && !app.runtime.runtime_handle().has_frame_callbacks()
212 }
213
214 pub(crate) fn needs_redraw_in_context(&self, app: &ShellApp) -> bool {
215 app.has_stale_work_in_context()
216 || app.composition.should_recompose()
217 || self.is_dirty
218 || self.scene_dirty
219 || self.renderer_warmup_due(app)
220 }
221
222 pub(crate) fn compute_frame_schedule(
223 &self,
224 app: &ShellApp,
225 surfaces_dirty: bool,
226 ) -> FrameSchedule {
227 let app_context = Rc::clone(&app.app_context);
228 let (needs_update, needs_frame) = app_context.enter(|| {
229 let needs_frame = self.is_dirty
230 || self.scene_dirty
231 || app.wants_frame_in_context()
232 || self.has_active_pointer_gesture()
233 || self.renderer_warmup_due(app);
234 (app.needs_ui_update_in_context(surfaces_dirty), needs_frame)
235 });
236 FrameSchedule {
237 needs_update,
238 needs_frame,
239 next_deadline: app.next_event_time(),
240 }
241 }
242
243 pub(crate) fn invalidate_dev_overlay_text(&mut self) {
244 self.dev_overlay_text.clear();
245 self.dev_overlay_last_refresh = None;
246 self.dev_overlay_viewport = None;
247 }
248
249 pub(crate) fn dev_overlay_control_center(&self, mode: FramePacingMode) -> Option<(f32, f32)> {
250 self.dev_overlay_controls
251 .iter()
252 .find(|control| control.mode == mode)
253 .map(|control| {
254 (
255 control.bounds.x + control.bounds.width * 0.5,
256 control.bounds.y + control.bounds.height * 0.5,
257 )
258 })
259 }
260
261 pub(crate) fn layout_tree_in_context(&mut self, app: &mut ShellApp) -> Option<&LayoutTree> {
262 if self.layout_tree.is_none() {
263 let root = self.root_node(app)?;
264 let mut applier = app.composition.applier_mut();
265 match cranpose_ui::build_layout_tree_from_applier(&mut applier, root) {
266 Ok(layout_tree) => {
267 self.layout_tree = layout_tree;
268 }
269 Err(err) => {
270 log::debug!("failed to build layout snapshot: {err}");
271 return None;
272 }
273 }
274 }
275 self.layout_tree.as_ref()
276 }
277
278 pub(crate) fn top_modal(&self, app: &mut ShellApp) -> Option<NodeId> {
281 let root = self.root_node(app)?;
282 let mut applier = app.composition.applier_mut();
283 cranpose_ui::top_modal_from_applier(&mut applier, root).unwrap_or_else(|err| {
284 log::debug!("failed to find the top modal under root #{root}: {err}");
285 None
286 })
287 }
288
289 pub(crate) fn semantics_tree_in_context(
290 &mut self,
291 app: &mut ShellApp,
292 ) -> Option<&SemanticsTree> {
293 if !app.semantics_enabled && !self.inspector.state.open {
294 return None;
295 }
296 self.semantics_tree_for_input(app)
297 }
298
299 pub(crate) fn semantics_tree_for_input(
300 &mut self,
301 app: &mut ShellApp,
302 ) -> Option<&SemanticsTree> {
303 app.flush_semantics_invalidations();
304 let root = self.root_node(app)?;
305 let semantics_dirty = {
306 let mut applier = app.composition.applier_mut();
307 cranpose_ui::tree_needs_semantics(&mut *applier, root).unwrap_or_else(|err| {
308 log::debug!("failed to check semantics dirty status for root #{root}: {err}");
309 true
310 })
311 };
312 if self.semantics_tree.is_none() || self.semantics_moved || semantics_dirty {
313 let mut applier = app.composition.applier_mut();
314 match cranpose_ui::update_semantics_tree_from_applier(
315 &mut applier,
316 root,
317 &mut self.semantics_tree,
318 ) {
319 Ok(()) => {
320 #[cfg(debug_assertions)]
321 crate::semantics_check::assert_matches_rebuild(
322 &mut applier,
323 root,
324 self.semantics_tree.as_ref(),
325 );
326 self.semantics_moved = false;
327 app.semantics_snapshot_revision =
328 app.semantics_snapshot_revision.wrapping_add(1);
329 }
330 Err(err) => {
331 log::debug!("failed to build semantics snapshot: {err}");
332 return None;
333 }
334 }
335 }
336 self.semantics_tree.as_ref()
337 }
338}
339
340#[derive(Default)]
341pub(crate) struct TextInputRoutes {
342 active: Option<RootId>,
343 shown: Option<RootId>,
344 handlers: Vec<(RootId, Rc<dyn PlatformTextInputHandler>)>,
345}
346
347impl TextInputRoutes {
348 pub(crate) fn active(&self) -> RootId {
349 self.active.unwrap_or(RootId::Primary)
350 }
351
352 pub(crate) fn set_active(&mut self, root: RootId) {
353 self.active = Some(root);
354 }
355
356 pub(crate) fn set_handler(&mut self, root: RootId, handler: Rc<dyn PlatformTextInputHandler>) {
357 self.remove(root);
358 self.handlers.push((root, handler));
359 }
360
361 pub(crate) fn remove(&mut self, root: RootId) {
362 self.handlers.retain(|(id, _)| *id != root);
363 if self.shown == Some(root) {
364 self.shown = None;
365 }
366 }
367
368 fn handler(&self, root: RootId) -> Option<Rc<dyn PlatformTextInputHandler>> {
369 self.handlers
370 .iter()
371 .find(|(id, _)| *id == root)
372 .map(|(_, handler)| Rc::clone(handler))
373 }
374
375 fn take_show_target(&mut self) -> Option<Rc<dyn PlatformTextInputHandler>> {
376 let active = self.active();
377 let handler = self.handler(active);
378 if handler.is_some() {
379 self.shown = Some(active);
380 }
381 handler
382 }
383
384 fn take_hide_target(&mut self) -> Option<Rc<dyn PlatformTextInputHandler>> {
385 let target = self.shown.take().unwrap_or_else(|| self.active());
386 self.handler(target)
387 }
388}
389
390pub(crate) struct TextInputRouter {
391 pub(crate) routes: Rc<RefCell<TextInputRoutes>>,
392}
393
394impl PlatformTextInputHandler for TextInputRouter {
395 fn show_keyboard(&self) {
396 let handler = self.routes.borrow_mut().take_show_target();
397 if let Some(handler) = handler {
398 handler.show_keyboard();
399 }
400 }
401
402 fn hide_keyboard(&self) {
403 let handler = self.routes.borrow_mut().take_hide_target();
404 if let Some(handler) = handler {
405 handler.hide_keyboard();
406 }
407 }
408}
409
410#[derive(Clone, Copy)]
411pub(crate) enum SurfaceDirtyLane {
412 Layout,
413 Moved,
414 Draw,
415 LayerProperties,
416 Structural,
417}
418
419fn append_surface_dirty_node(
420 surface: &mut RootSurface<impl Renderer>,
421 surface_index: usize,
422 node: NodeId,
423 lane: SurfaceDirtyLane,
424 seen: &mut HashSet<(usize, NodeId)>,
425) {
426 match lane {
427 SurfaceDirtyLane::Layout => {
428 surface.scene_dirty = true;
429 if seen.insert((surface_index, node)) {
430 surface.scoped_layout_scene_nodes.push(node);
431 }
432 }
433 SurfaceDirtyLane::Moved => {
434 surface.scene_dirty = true;
435 if seen.insert((surface_index, node)) {
436 surface.scoped_moved_scene_nodes.push(node);
437 }
438 }
439 SurfaceDirtyLane::Draw => surface.scoped_draw_nodes.push(node),
440 SurfaceDirtyLane::LayerProperties => surface.scoped_layer_property_nodes.push(node),
441 SurfaceDirtyLane::Structural => {
442 if seen.insert((surface_index, node)) {
443 surface.structural_scene_nodes.push(node);
444 }
445 }
446 }
447}
448
449fn queued_scene_nodes<R: Renderer>(surface: &RootSurface<R>, lane: SurfaceDirtyLane) -> &[NodeId] {
452 match lane {
453 SurfaceDirtyLane::Layout => &surface.scoped_layout_scene_nodes,
454 SurfaceDirtyLane::Moved => &surface.scoped_moved_scene_nodes,
455 SurfaceDirtyLane::Draw
456 | SurfaceDirtyLane::LayerProperties
457 | SurfaceDirtyLane::Structural => &[],
458 }
459}
460
461pub(crate) fn route_nodes_by_surface<R: Renderer>(
462 app: &mut ShellApp,
463 surfaces: &mut [RootSurface<R>],
464 nodes: impl IntoIterator<Item = NodeId>,
465 lane: SurfaceDirtyLane,
466 scratch: &mut SurfaceRoutingScratch,
467) {
468 let Some(primary_root) = app.composition.root() else {
469 scratch.attached.clear();
470 scratch.owners.clear();
471 return;
472 };
473 let mut applier = app.composition.applier_mut();
474 applier.scene_nodes_attached_to_into(
475 nodes,
476 primary_root,
477 &mut scratch.attached,
478 &mut scratch.attachment,
479 );
480 if scratch.attached.is_empty() {
481 scratch.owners.clear();
482 return;
483 }
484 scratch.seen.clear();
485 for (index, surface) in surfaces.iter().enumerate() {
486 scratch.seen.extend(
487 queued_scene_nodes(surface, lane)
488 .iter()
489 .map(|node| (index, *node)),
490 );
491 }
492 if app.app_context.window_roots().is_empty() {
493 scratch.owners.clear();
494 if let Some(index) = surfaces
495 .iter()
496 .position(|surface| surface.id == RootId::Primary)
497 {
498 let surface = &mut surfaces[index];
499 for node in scratch.attached.iter().flatten().copied() {
500 append_surface_dirty_node(surface, index, node, lane, &mut scratch.seen);
501 }
502 }
503 return;
504 }
505 cranpose_ui::nearest_window_roots_into(
506 &mut applier,
507 scratch.attached.iter().flatten().copied(),
508 &mut scratch.owners,
509 &mut scratch.window_roots,
510 );
511 for (node, owner) in scratch.attached.iter().flatten().zip(&scratch.owners) {
512 let node = *node;
513 if let Some(index) = surfaces
514 .iter()
515 .position(|surface| surface.owns_nodes_under(*owner))
516 {
517 let surface = &mut surfaces[index];
518 append_surface_dirty_node(surface, index, node, lane, &mut scratch.seen);
519 }
520 }
521}
522
523pub struct SurfaceMut<'a, R: Renderer> {
530 pub(crate) shell: &'a mut AppShell<R>,
531 pub(crate) index: usize,
532}
533
534impl<'a, R> SurfaceMut<'a, R>
535where
536 R: Renderer,
537 R::Error: Debug,
538{
539 pub(crate) fn new(shell: &'a mut AppShell<R>, index: usize) -> Self {
540 Self { shell, index }
541 }
542
543 pub fn shell(&mut self) -> &mut AppShell<R> {
546 self.shell
547 }
548
549 pub(crate) fn shell_app(&mut self) -> &mut ShellApp {
550 &mut self.shell.app
551 }
552
553 pub(crate) fn shell_app_ref(&self) -> &ShellApp {
554 &self.shell.app
555 }
556
557 pub(crate) fn surface(&self) -> &RootSurface<R> {
558 &self.shell.surfaces[self.index]
559 }
560
561 pub(crate) fn surface_mut(&mut self) -> &mut RootSurface<R> {
562 &mut self.shell.surfaces[self.index]
563 }
564
565 pub(crate) fn parts(&mut self) -> (&mut ShellApp, &mut RootSurface<R>) {
566 let shell = &mut *self.shell;
567 (&mut shell.app, &mut shell.surfaces[self.index])
568 }
569
570 pub fn id(&self) -> RootId {
572 self.surface().id
573 }
574
575 pub fn root(&self) -> Option<NodeId> {
577 let surface = self.surface();
578 surface.root_node(self.shell_app_ref())
579 }
580
581 pub fn renderer(&mut self) -> &mut R {
583 &mut self.surface_mut().renderer
584 }
585
586 pub fn with_renderer<T>(&mut self, block: impl FnOnce(&mut R) -> T) -> T {
589 let (app, surface) = self.parts();
590 app.app_context.enter(|| block(&mut surface.renderer))
591 }
592
593 pub fn scene(&self) -> &R::Scene {
595 self.surface().renderer.scene()
596 }
597
598 pub fn set_viewport(&mut self, width: f32, height: f32) {
606 self.surface_mut().viewport = (width, height);
607 match self.id() {
608 RootId::Primary => self.shell_app().request_forced_layout_pass(),
609 RootId::Window(_) => {
610 if let Some(root) = self.root() {
611 let app_context = Rc::clone(&self.shell_app_ref().app_context);
612 app_context.enter(|| cranpose_ui::schedule_measure_repass(root));
613 }
614 self.shell_app().request_layout_pass();
615 }
616 }
617 let root = self.root();
618 self.surface_mut().invalidate_scene_root(root);
619 self.mark_dirty();
620 }
621
622 pub fn set_screen_origin(&mut self, origin: Option<Point>) {
628 self.surface_mut().screen_origin = origin;
629 }
630
631 pub fn screen_origin(&self) -> Option<Point> {
634 self.surface().screen_origin
635 }
636
637 pub fn viewport_size(&self) -> (f32, f32) {
639 self.surface().viewport
640 }
641
642 pub fn set_buffer_size(&mut self, width: u32, height: u32) {
644 self.surface_mut().buffer_size = (width, height);
645 }
646
647 pub fn buffer_size(&self) -> (u32, u32) {
649 self.surface().buffer_size
650 }
651
652 pub fn mark_dirty(&mut self) {
654 self.surface_mut().is_dirty = true;
655 }
656
657 pub fn needs_redraw(&self) -> bool {
661 let app_context = Rc::clone(&self.shell_app_ref().app_context);
662 app_context.enter(|| self.surface().needs_redraw_in_context(self.shell_app_ref()))
663 }
664
665 pub fn has_active_pointer_gesture(&self) -> bool {
668 self.surface().has_active_pointer_gesture()
669 }
670
671 pub fn last_update_result(&self) -> FrameUpdateResult {
674 self.surface().last_update
675 }
676
677 pub fn frame_owed(&self) -> bool {
682 self.surface().frame_owed
683 }
684
685 pub fn take_frame_owed(&mut self) -> bool {
687 std::mem::take(&mut self.surface_mut().frame_owed)
688 }
689
690 fn compute_frame_schedule(&self) -> FrameSchedule {
691 self.surface()
692 .compute_frame_schedule(self.shell_app_ref(), self.shell.any_surface_dirty())
693 }
694
695 pub fn frame_schedule(&self) -> FrameSchedule {
698 let schedule = self.compute_frame_schedule();
699 self.surface().frame_scheduler.record(schedule);
700 schedule
701 }
702
703 pub fn schedule_platform_frame<D>(&self, driver: &D) -> FrameSchedule
705 where
706 D: PlatformFrameDriver + ?Sized,
707 {
708 let schedule = self.compute_frame_schedule();
709 self.surface().frame_scheduler.schedule(schedule, driver);
710 schedule
711 }
712
713 pub fn frame_scheduler_snapshot(&self) -> FrameSchedule {
715 self.surface().frame_scheduler.snapshot()
716 }
717
718 pub fn set_frame_rate_preference(&mut self, preference: FrameRatePreference) {
721 self.surface_mut().frame_rate_preference = preference;
722 }
723
724 pub fn frame_rate_preference(&self) -> FrameRatePreference {
726 self.surface().frame_rate_preference
727 }
728
729 pub fn dev_overlay_control_center(&self, mode: FramePacingMode) -> Option<(f32, f32)> {
732 self.surface().dev_overlay_control_center(mode)
733 }
734
735 pub(crate) fn dev_overlay_press(&mut self, x: f32, y: f32) -> bool {
736 if !self.shell_app_ref().dev_options.frame_pacing_controls {
737 return false;
738 }
739 let Some(mode) = self
740 .surface()
741 .dev_overlay_controls
742 .iter()
743 .find(|control| control.bounds.contains(x, y))
744 .map(|control| control.mode)
745 else {
746 return false;
747 };
748 self.shell().set_frame_pacing_mode(mode);
749 true
750 }
751
752 pub fn with_layout_tree<T>(&mut self, block: impl FnOnce(Option<&LayoutTree>) -> T) -> T {
754 let (app, surface) = self.parts();
755 let app_context = Rc::clone(&app.app_context);
756 app_context.enter(|| block(surface.layout_tree_in_context(app)))
757 }
758
759 pub fn with_semantics_tree<T>(&mut self, block: impl FnOnce(Option<&SemanticsTree>) -> T) -> T {
762 let (app, surface) = self.parts();
763 let app_context = Rc::clone(&app.app_context);
764 app_context.enter(|| block(surface.semantics_tree_in_context(app)))
765 }
766
767 pub fn take_pointer_icon_change(&self) -> Option<PointerIcon> {
770 self.surface().pointer_icon.take_change()
771 }
772
773 pub fn refresh_pointer_icon(&self) {
776 self.surface().pointer_icon.refresh();
777 }
778
779 pub fn set_platform_text_input(&mut self, handler: Rc<dyn PlatformTextInputHandler>) {
784 let id = self.id();
785 let app = self.shell_app();
786 app.text_input_routes.borrow_mut().set_handler(id, handler);
787 app.install_text_input_router();
788 }
789
790 pub fn activate(&mut self) {
793 let id = self.id();
794 self.shell_app()
795 .text_input_routes
796 .borrow_mut()
797 .set_active(id);
798 }
799}