freya_winit/
renderer.rs

1use std::{
2    borrow::Cow,
3    fmt,
4    pin::Pin,
5    task::Waker,
6};
7
8use accesskit_winit::WindowEvent as AccessibilityWindowEvent;
9use freya_core::integration::*;
10use freya_engine::prelude::{
11    FontCollection,
12    FontMgr,
13};
14use futures_lite::future::FutureExt as _;
15use futures_util::{
16    FutureExt as _,
17    StreamExt,
18    select,
19};
20use ragnarok::{
21    EventsExecutorRunner,
22    EventsMeasurerRunner,
23};
24use rustc_hash::FxHashMap;
25use torin::prelude::{
26    CursorPoint,
27    Size2D,
28};
29use winit::{
30    application::ApplicationHandler,
31    event::{
32        ElementState,
33        Ime,
34        MouseScrollDelta,
35        Touch,
36        TouchPhase,
37        WindowEvent,
38    },
39    event_loop::EventLoopProxy,
40    window::{
41        Theme,
42        Window,
43        WindowId,
44    },
45};
46
47use crate::{
48    accessibility::AccessibilityTask,
49    config::WindowConfig,
50    plugins::{
51        PluginEvent,
52        PluginHandle,
53        PluginsManager,
54    },
55    window::AppWindow,
56    winit_mappings::{
57        self,
58        map_winit_mouse_button,
59        map_winit_touch_force,
60        map_winit_touch_phase,
61    },
62};
63
64pub struct WinitRenderer {
65    pub windows_configs: Vec<WindowConfig>,
66    #[cfg(feature = "tray")]
67    pub(crate) tray: (
68        Option<crate::config::TrayIconGetter>,
69        Option<crate::config::TrayHandler>,
70    ),
71    pub resumed: bool,
72    pub windows: FxHashMap<WindowId, AppWindow>,
73    pub proxy: EventLoopProxy<NativeEvent>,
74    pub plugins: PluginsManager,
75    pub fallback_fonts: Vec<Cow<'static, str>>,
76    pub screen_reader: ScreenReader,
77    pub font_manager: FontMgr,
78    pub font_collection: FontCollection,
79    pub futures: Vec<Pin<Box<dyn Future<Output = ()>>>>,
80    pub waker: Waker,
81}
82
83#[derive(Debug)]
84pub enum NativeWindowEventAction {
85    PollRunner,
86
87    Accessibility(AccessibilityWindowEvent),
88
89    PlatformEvent(PlatformEvent),
90
91    User(UserEvent),
92}
93
94pub struct WithWindowCallback(pub(crate) Box<dyn FnOnce(&mut Window)>);
95
96impl fmt::Debug for WithWindowCallback {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        f.write_str("WithWindowCallback")
99    }
100}
101
102#[derive(Debug)]
103pub enum NativeWindowErasedEventAction {
104    LaunchWindow {
105        window_config: WindowConfig,
106        ack: futures_channel::oneshot::Sender<WindowId>,
107    },
108    CloseWindow(WindowId),
109    WithWindow {
110        window_id: Option<WindowId>,
111        callback: WithWindowCallback,
112    },
113}
114
115#[derive(Debug)]
116pub struct NativeWindowEvent {
117    pub window_id: WindowId,
118    pub action: NativeWindowEventAction,
119}
120
121#[cfg(feature = "tray")]
122#[derive(Debug)]
123pub enum NativeTrayEventAction {
124    TrayEvent(tray_icon::TrayIconEvent),
125    MenuEvent(tray_icon::menu::MenuEvent),
126    LaunchWindow(SingleThreadErasedEvent),
127}
128
129#[cfg(feature = "tray")]
130#[derive(Debug)]
131pub struct NativeTrayEvent {
132    pub action: NativeTrayEventAction,
133}
134
135#[derive(Debug)]
136pub enum NativeGenericEvent {
137    PollFutures,
138}
139
140#[derive(Debug)]
141pub enum NativeEvent {
142    Window(NativeWindowEvent),
143    #[cfg(feature = "tray")]
144    Tray(NativeTrayEvent),
145    Generic(NativeGenericEvent),
146}
147
148impl From<accesskit_winit::Event> for NativeEvent {
149    fn from(event: accesskit_winit::Event) -> Self {
150        NativeEvent::Window(NativeWindowEvent {
151            window_id: event.window_id,
152            action: NativeWindowEventAction::Accessibility(event.window_event),
153        })
154    }
155}
156
157impl ApplicationHandler<NativeEvent> for WinitRenderer {
158    fn resumed(&mut self, active_event_loop: &winit::event_loop::ActiveEventLoop) {
159        if !self.resumed {
160            #[cfg(feature = "tray")]
161            {
162                #[cfg(not(target_os = "linux"))]
163                if let Some(tray_icon) = self.tray.0.take() {
164                    let _tray_icon = (tray_icon)();
165                }
166
167                #[cfg(target_os = "macos")]
168                {
169                    use objc2_core_foundation::CFRunLoop;
170
171                    let rl = CFRunLoop::main().expect("Failed to run CFRunLoop");
172                    CFRunLoop::wake_up(&rl);
173                }
174            }
175
176            for window_config in self.windows_configs.drain(..) {
177                let app_window = AppWindow::new(
178                    window_config,
179                    active_event_loop,
180                    &self.proxy,
181                    &mut self.plugins,
182                    &self.font_collection,
183                    &self.font_manager,
184                    &self.fallback_fonts,
185                    self.screen_reader.clone(),
186                );
187
188                self.proxy
189                    .send_event(NativeEvent::Window(NativeWindowEvent {
190                        window_id: app_window.window.id(),
191                        action: NativeWindowEventAction::PollRunner,
192                    }))
193                    .ok();
194
195                self.windows.insert(app_window.window.id(), app_window);
196            }
197            self.resumed = true;
198
199            let _ = self
200                .proxy
201                .send_event(NativeEvent::Generic(NativeGenericEvent::PollFutures));
202        }
203    }
204
205    fn user_event(
206        &mut self,
207        active_event_loop: &winit::event_loop::ActiveEventLoop,
208        event: NativeEvent,
209    ) {
210        match event {
211            NativeEvent::Generic(NativeGenericEvent::PollFutures) => {
212                let mut cx = std::task::Context::from_waker(&self.waker);
213                self.futures
214                    .retain_mut(|fut| fut.poll(&mut cx).is_pending());
215            }
216            #[cfg(feature = "tray")]
217            NativeEvent::Tray(NativeTrayEvent { action }) => match action {
218                NativeTrayEventAction::TrayEvent(icon_event) => {
219                    use crate::tray::{
220                        TrayContext,
221                        TrayEvent,
222                    };
223                    if let Some((tray_context, tray_handler)) =
224                        TrayContext::new(active_event_loop, self)
225                    {
226                        (tray_handler)(TrayEvent::Icon(icon_event), tray_context)
227                    }
228                }
229                NativeTrayEventAction::MenuEvent(menu_event) => {
230                    use crate::tray::{
231                        TrayContext,
232                        TrayEvent,
233                    };
234                    if let Some((tray_context, tray_handler)) =
235                        TrayContext::new(active_event_loop, self)
236                    {
237                        (tray_handler)(TrayEvent::Menu(menu_event), tray_context)
238                    }
239                }
240                NativeTrayEventAction::LaunchWindow(data) => {
241                    let window_config = data
242                        .0
243                        .downcast::<WindowConfig>()
244                        .expect("Expected WindowConfig");
245                    let app_window = AppWindow::new(
246                        *window_config,
247                        active_event_loop,
248                        &self.proxy,
249                        &mut self.plugins,
250                        &self.font_collection,
251                        &self.font_manager,
252                        &self.fallback_fonts,
253                        self.screen_reader.clone(),
254                    );
255
256                    self.proxy
257                        .send_event(NativeEvent::Window(NativeWindowEvent {
258                            window_id: app_window.window.id(),
259                            action: NativeWindowEventAction::PollRunner,
260                        }))
261                        .ok();
262
263                    self.windows.insert(app_window.window.id(), app_window);
264                }
265            },
266            NativeEvent::Window(NativeWindowEvent { action, window_id }) => {
267                if let Some(app) = &mut self.windows.get_mut(&window_id) {
268                    match action {
269                        NativeWindowEventAction::PollRunner => {
270                            let mut cx = std::task::Context::from_waker(&app.waker);
271
272                            {
273                                let fut = std::pin::pin!(async {
274                                    select! {
275                                        events_chunk = app.events_receiver.next() => {
276                                            match events_chunk {
277                                                Some(EventsChunk::Processed(processed_events)) => {
278                                                    let events_executor_adapter = EventsExecutorAdapter {
279                                                        runner: &mut app.runner,
280                                                    };
281                                                    events_executor_adapter.run(&mut app.nodes_state, processed_events);
282                                                }
283                                                Some(EventsChunk::Batch(events)) => {
284                                                    for event in events {
285                                                        app.runner.handle_event(event.node_id, event.name, event.data, event.bubbles);
286                                                    }
287                                                }
288                                                _ => {}
289                                            }
290
291                                        },
292                                         _ = app.runner.handle_events().fuse() => {},
293                                    }
294                                });
295
296                                match fut.poll(&mut cx) {
297                                    std::task::Poll::Ready(_) => {
298                                        self.proxy
299                                            .send_event(NativeEvent::Window(NativeWindowEvent {
300                                                window_id: app.window.id(),
301                                                action: NativeWindowEventAction::PollRunner,
302                                            }))
303                                            .ok();
304                                    }
305                                    std::task::Poll::Pending => {}
306                                }
307                            }
308
309                            self.plugins.send(
310                                PluginEvent::StartedUpdatingTree {
311                                    window: &app.window,
312                                    tree: &app.tree,
313                                },
314                                PluginHandle::new(&self.proxy),
315                            );
316                            let mutations = app.runner.sync_and_update();
317                            let result = app.tree.apply_mutations(mutations);
318                            if result.needs_render {
319                                app.process_layout_on_next_render = true;
320                                app.window.request_redraw();
321                            }
322                            self.plugins.send(
323                                PluginEvent::FinishedUpdatingTree {
324                                    window: &app.window,
325                                    tree: &app.tree,
326                                },
327                                PluginHandle::new(&self.proxy),
328                            );
329                        }
330                        NativeWindowEventAction::Accessibility(
331                            accesskit_winit::WindowEvent::AccessibilityDeactivated,
332                        ) => {
333                            self.screen_reader.set(false);
334                        }
335                        NativeWindowEventAction::Accessibility(
336                            accesskit_winit::WindowEvent::ActionRequested(_),
337                        ) => {}
338                        NativeWindowEventAction::Accessibility(
339                            accesskit_winit::WindowEvent::InitialTreeRequested,
340                        ) => {
341                            app.accessibility_tasks_for_next_render = AccessibilityTask::Init;
342                            app.window.request_redraw();
343                            self.screen_reader.set(true);
344                        }
345                        NativeWindowEventAction::User(user_event) => match user_event {
346                            UserEvent::RequestRedraw => {
347                                app.window.request_redraw();
348                            }
349                            UserEvent::FocusAccessibilityNode(strategy) => {
350                                let task = match strategy {
351                                    AccessibilityFocusStrategy::Backward(_)
352                                    | AccessibilityFocusStrategy::Forward(_) => {
353                                        AccessibilityTask::ProcessUpdate {
354                                            mode: Some(NavigationMode::Keyboard),
355                                        }
356                                    }
357                                    _ => AccessibilityTask::ProcessUpdate { mode: None },
358                                };
359                                app.tree.accessibility_diff.request_focus(strategy);
360                                app.accessibility_tasks_for_next_render = task;
361                                app.window.request_redraw();
362                            }
363                            UserEvent::SetCursorIcon(cursor_icon) => {
364                                app.window.set_cursor(cursor_icon);
365                            }
366                            UserEvent::Erased(data) => {
367                                let action = data
368                                    .0
369                                    .downcast::<NativeWindowErasedEventAction>()
370                                    .expect("Expected NativeWindowErasedEventAction");
371                                match *action {
372                                    NativeWindowErasedEventAction::LaunchWindow {
373                                        window_config,
374                                        ack,
375                                    } => {
376                                        let app_window = AppWindow::new(
377                                            window_config,
378                                            active_event_loop,
379                                            &self.proxy,
380                                            &mut self.plugins,
381                                            &self.font_collection,
382                                            &self.font_manager,
383                                            &self.fallback_fonts,
384                                            self.screen_reader.clone(),
385                                        );
386
387                                        let window_id = app_window.window.id();
388
389                                        let _ = self.proxy.send_event(NativeEvent::Window(
390                                            NativeWindowEvent {
391                                                window_id,
392                                                action: NativeWindowEventAction::PollRunner,
393                                            },
394                                        ));
395
396                                        self.windows.insert(window_id, app_window);
397                                        let _ = ack.send(window_id);
398                                    }
399                                    NativeWindowErasedEventAction::CloseWindow(window_id) => {
400                                        // Its fine to ignore if the window doesnt exist anymore
401                                        let _ = self.windows.remove(&window_id);
402                                    }
403                                    NativeWindowErasedEventAction::WithWindow {
404                                        window_id,
405                                        callback,
406                                    } => {
407                                        if let Some(window_id) = window_id {
408                                            if let Some(app) = self.windows.get_mut(&window_id) {
409                                                (callback.0)(&mut app.window)
410                                            }
411                                        } else {
412                                            (callback.0)(&mut app.window)
413                                        }
414                                    }
415                                }
416                            }
417                        },
418                        NativeWindowEventAction::PlatformEvent(platform_event) => {
419                            let mut events_measurer_adapter = EventsMeasurerAdapter {
420                                tree: &mut app.tree,
421                                scale_factor: app.window.scale_factor(),
422                            };
423                            let processed_events = events_measurer_adapter.run(
424                                &mut vec![platform_event],
425                                &mut app.nodes_state,
426                                app.accessibility.focused_node_id(),
427                            );
428                            app.events_sender
429                                .unbounded_send(EventsChunk::Processed(processed_events))
430                                .unwrap();
431                        }
432                    }
433                }
434            }
435        }
436    }
437
438    fn window_event(
439        &mut self,
440        event_loop: &winit::event_loop::ActiveEventLoop,
441        window_id: winit::window::WindowId,
442        event: winit::event::WindowEvent,
443    ) {
444        if let Some(app) = &mut self.windows.get_mut(&window_id) {
445            app.accessibility_adapter.process_event(&app.window, &event);
446            match event {
447                WindowEvent::ThemeChanged(theme) => {
448                    app.platform.preferred_theme.set(match theme {
449                        Theme::Light => PreferredTheme::Light,
450                        Theme::Dark => PreferredTheme::Dark,
451                    });
452                }
453                WindowEvent::ScaleFactorChanged { .. } => {
454                    app.window.request_redraw();
455                    app.process_layout_on_next_render = true;
456                    app.tree.layout.reset();
457                }
458                WindowEvent::CloseRequested => {
459                    self.windows.remove(&window_id);
460                    let has_windows = !self.windows.is_empty();
461
462                    let has_tray = {
463                        #[cfg(feature = "tray")]
464                        {
465                            self.tray.1.is_some()
466                        }
467                        #[cfg(not(feature = "tray"))]
468                        {
469                            false
470                        }
471                    };
472
473                    // Only exit when there is no window and no tray
474                    if !has_windows && !has_tray {
475                        event_loop.exit();
476                    }
477                }
478                WindowEvent::ModifiersChanged(modifiers) => {
479                    app.modifiers_state = modifiers.state();
480                }
481                WindowEvent::RedrawRequested => {
482                    hotpath::measure_block!("RedrawRequested", {
483                        if app.process_layout_on_next_render {
484                            self.plugins.send(
485                                PluginEvent::StartedMeasuringLayout {
486                                    window: &app.window,
487                                    tree: &app.tree,
488                                },
489                                PluginHandle::new(&self.proxy),
490                            );
491                            let size: Size2D = (
492                                app.window.inner_size().width as f32,
493                                app.window.inner_size().height as f32,
494                            )
495                                .into();
496
497                            app.tree.measure_layout(
498                                size,
499                                &self.font_collection,
500                                &self.font_manager,
501                                &app.events_sender,
502                                app.window.scale_factor(),
503                                &self.fallback_fonts,
504                            );
505                            app.platform.root_size.set_if_modified(size);
506                            app.process_layout_on_next_render = false;
507                            self.plugins.send(
508                                PluginEvent::FinishedMeasuringLayout {
509                                    window: &app.window,
510                                    tree: &app.tree,
511                                },
512                                PluginHandle::new(&self.proxy),
513                            );
514                        }
515
516                        app.driver.present(
517                            app.window.inner_size().cast(),
518                            &app.window,
519                            |surface| {
520                                self.plugins.send(
521                                    PluginEvent::BeforeRender {
522                                        window: &app.window,
523                                        canvas: surface.canvas(),
524                                        font_collection: &self.font_collection,
525                                        tree: &app.tree,
526                                    },
527                                    PluginHandle::new(&self.proxy),
528                                );
529
530                                let render_pipeline = RenderPipeline {
531                                    font_collection: &mut self.font_collection,
532                                    font_manager: &self.font_manager,
533                                    tree: &app.tree,
534                                    canvas: surface.canvas(),
535                                    scale_factor: app.window.scale_factor(),
536                                    background: app.background,
537                                };
538
539                                render_pipeline.render();
540
541                                self.plugins.send(
542                                    PluginEvent::AfterRender {
543                                        window: &app.window,
544                                        canvas: surface.canvas(),
545                                        font_collection: &self.font_collection,
546                                        tree: &app.tree,
547                                        animation_clock: &app.animation_clock,
548                                    },
549                                    PluginHandle::new(&self.proxy),
550                                );
551                                self.plugins.send(
552                                    PluginEvent::BeforePresenting {
553                                        window: &app.window,
554                                        font_collection: &self.font_collection,
555                                        tree: &app.tree,
556                                    },
557                                    PluginHandle::new(&self.proxy),
558                                );
559                            },
560                        );
561                        self.plugins.send(
562                            PluginEvent::AfterPresenting {
563                                window: &app.window,
564                                font_collection: &self.font_collection,
565                                tree: &app.tree,
566                            },
567                            PluginHandle::new(&self.proxy),
568                        );
569
570                        self.plugins.send(
571                            PluginEvent::BeforeAccessibility {
572                                window: &app.window,
573                                font_collection: &self.font_collection,
574                                tree: &app.tree,
575                            },
576                            PluginHandle::new(&self.proxy),
577                        );
578
579                        match app.accessibility_tasks_for_next_render.take() {
580                            AccessibilityTask::ProcessUpdate { mode } => {
581                                let update = app
582                                    .accessibility
583                                    .process_updates(&mut app.tree, &app.events_sender);
584                                app.platform
585                                    .focused_accessibility_id
586                                    .set_if_modified(update.focus);
587                                let node_id = app.accessibility.focused_node_id().unwrap();
588                                let layout_node = app.tree.layout.get(&node_id).unwrap();
589                                app.platform.focused_accessibility_node.set_if_modified(
590                                    AccessibilityTree::create_node(node_id, layout_node, &app.tree),
591                                );
592                                if let Some(mode) = mode {
593                                    app.platform.navigation_mode.set(mode);
594                                }
595                                app.accessibility_adapter.update_if_active(|| update);
596                            }
597                            AccessibilityTask::Init => {
598                                let update = app.accessibility.init(&mut app.tree);
599                                app.platform
600                                    .focused_accessibility_id
601                                    .set_if_modified(update.focus);
602                                let node_id = app.accessibility.focused_node_id().unwrap();
603                                let layout_node = app.tree.layout.get(&node_id).unwrap();
604                                app.platform.focused_accessibility_node.set_if_modified(
605                                    AccessibilityTree::create_node(node_id, layout_node, &app.tree),
606                                );
607                                app.accessibility_adapter.update_if_active(|| update);
608                            }
609                            AccessibilityTask::None => {}
610                        }
611
612                        self.plugins.send(
613                            PluginEvent::AfterAccessibility {
614                                window: &app.window,
615                                font_collection: &self.font_collection,
616                                tree: &app.tree,
617                            },
618                            PluginHandle::new(&self.proxy),
619                        );
620
621                        if app.ticker_sender.receiver_count() > 0 {
622                            app.ticker_sender.broadcast_blocking(()).unwrap();
623                        }
624
625                        self.plugins.send(
626                            PluginEvent::AfterRedraw {
627                                window: &app.window,
628                                font_collection: &self.font_collection,
629                                tree: &app.tree,
630                            },
631                            PluginHandle::new(&self.proxy),
632                        );
633                    });
634                }
635                WindowEvent::Resized(size) => {
636                    app.driver.resize(size);
637
638                    app.window.request_redraw();
639
640                    app.process_layout_on_next_render = true;
641                    app.tree.layout.clear_dirty();
642                    app.tree.layout.invalidate(NodeId::ROOT);
643                }
644
645                WindowEvent::MouseInput { state, button, .. } => {
646                    app.mouse_state = state;
647                    app.platform
648                        .navigation_mode
649                        .set(NavigationMode::NotKeyboard);
650
651                    let name = if state == ElementState::Pressed {
652                        MouseEventName::MouseDown
653                    } else {
654                        MouseEventName::MouseUp
655                    };
656                    let platform_event = PlatformEvent::Mouse {
657                        name,
658                        cursor: (app.position.x, app.position.y).into(),
659                        button: Some(map_winit_mouse_button(button)),
660                    };
661                    let mut events_measurer_adapter = EventsMeasurerAdapter {
662                        tree: &mut app.tree,
663                        scale_factor: app.window.scale_factor(),
664                    };
665                    let processed_events = events_measurer_adapter.run(
666                        &mut vec![platform_event],
667                        &mut app.nodes_state,
668                        app.accessibility.focused_node_id(),
669                    );
670                    app.events_sender
671                        .unbounded_send(EventsChunk::Processed(processed_events))
672                        .unwrap();
673                }
674
675                WindowEvent::KeyboardInput { event, .. } => {
676                    let name = match event.state {
677                        ElementState::Pressed => KeyboardEventName::KeyDown,
678                        ElementState::Released => KeyboardEventName::KeyUp,
679                    };
680                    let platform_event = PlatformEvent::Keyboard {
681                        name,
682                        key: winit_mappings::map_winit_key(&event.logical_key),
683                        code: winit_mappings::map_winit_physical_key(&event.physical_key),
684                        modifiers: winit_mappings::map_winit_modifiers(app.modifiers_state),
685                    };
686                    let mut events_measurer_adapter = EventsMeasurerAdapter {
687                        tree: &mut app.tree,
688                        scale_factor: app.window.scale_factor(),
689                    };
690                    let processed_events = events_measurer_adapter.run(
691                        &mut vec![platform_event],
692                        &mut app.nodes_state,
693                        app.accessibility.focused_node_id(),
694                    );
695                    app.events_sender
696                        .unbounded_send(EventsChunk::Processed(processed_events))
697                        .unwrap();
698                }
699
700                WindowEvent::MouseWheel { delta, phase, .. } => {
701                    const WHEEL_SPEED_MODIFIER: f64 = 53.0;
702                    const TOUCHPAD_SPEED_MODIFIER: f64 = 2.0;
703
704                    if TouchPhase::Moved == phase {
705                        let scroll_data = {
706                            match delta {
707                                MouseScrollDelta::LineDelta(x, y) => (
708                                    (x as f64 * WHEEL_SPEED_MODIFIER),
709                                    (y as f64 * WHEEL_SPEED_MODIFIER),
710                                ),
711                                MouseScrollDelta::PixelDelta(pos) => (
712                                    (pos.x * TOUCHPAD_SPEED_MODIFIER),
713                                    (pos.y * TOUCHPAD_SPEED_MODIFIER),
714                                ),
715                            }
716                        };
717
718                        let platform_event = PlatformEvent::Wheel {
719                            name: WheelEventName::Wheel,
720                            scroll: scroll_data.into(),
721                            cursor: app.position,
722                            source: WheelSource::Device,
723                        };
724                        let mut events_measurer_adapter = EventsMeasurerAdapter {
725                            tree: &mut app.tree,
726                            scale_factor: app.window.scale_factor(),
727                        };
728                        let processed_events = events_measurer_adapter.run(
729                            &mut vec![platform_event],
730                            &mut app.nodes_state,
731                            app.accessibility.focused_node_id(),
732                        );
733                        app.events_sender
734                            .unbounded_send(EventsChunk::Processed(processed_events))
735                            .unwrap();
736                    }
737                }
738
739                WindowEvent::CursorLeft { .. } => {
740                    if app.mouse_state == ElementState::Released {
741                        app.position = CursorPoint::from((-1., -1.));
742                        let platform_event = PlatformEvent::Mouse {
743                            name: MouseEventName::MouseMove,
744                            cursor: app.position,
745                            button: None,
746                        };
747                        let mut events_measurer_adapter = EventsMeasurerAdapter {
748                            tree: &mut app.tree,
749                            scale_factor: app.window.scale_factor(),
750                        };
751                        let processed_events = events_measurer_adapter.run(
752                            &mut vec![platform_event],
753                            &mut app.nodes_state,
754                            app.accessibility.focused_node_id(),
755                        );
756                        app.events_sender
757                            .unbounded_send(EventsChunk::Processed(processed_events))
758                            .unwrap();
759                    }
760                }
761                WindowEvent::CursorMoved { position, .. } => {
762                    app.position = CursorPoint::from((position.x, position.y));
763
764                    let mut platform_event = vec![PlatformEvent::Mouse {
765                        name: MouseEventName::MouseMove,
766                        cursor: app.position,
767                        button: None,
768                    }];
769
770                    for dropped_file_path in app.dropped_file_paths.drain(..) {
771                        platform_event.push(PlatformEvent::File {
772                            name: FileEventName::FileDrop,
773                            file_path: Some(dropped_file_path),
774                            cursor: app.position,
775                        });
776                    }
777
778                    let mut events_measurer_adapter = EventsMeasurerAdapter {
779                        tree: &mut app.tree,
780                        scale_factor: app.window.scale_factor(),
781                    };
782                    let processed_events = events_measurer_adapter.run(
783                        &mut platform_event,
784                        &mut app.nodes_state,
785                        app.accessibility.focused_node_id(),
786                    );
787                    app.events_sender
788                        .unbounded_send(EventsChunk::Processed(processed_events))
789                        .unwrap();
790                }
791
792                WindowEvent::Touch(Touch {
793                    location,
794                    phase,
795                    id,
796                    force,
797                    ..
798                }) => {
799                    app.position = CursorPoint::from((location.x, location.y));
800
801                    let name = match phase {
802                        TouchPhase::Cancelled => TouchEventName::TouchCancel,
803                        TouchPhase::Ended => TouchEventName::TouchEnd,
804                        TouchPhase::Moved => TouchEventName::TouchMove,
805                        TouchPhase::Started => TouchEventName::TouchStart,
806                    };
807
808                    let platform_event = PlatformEvent::Touch {
809                        name,
810                        location: app.position,
811                        finger_id: id,
812                        phase: map_winit_touch_phase(phase),
813                        force: force.map(map_winit_touch_force),
814                    };
815                    let mut events_measurer_adapter = EventsMeasurerAdapter {
816                        tree: &mut app.tree,
817                        scale_factor: app.window.scale_factor(),
818                    };
819                    let processed_events = events_measurer_adapter.run(
820                        &mut vec![platform_event],
821                        &mut app.nodes_state,
822                        app.accessibility.focused_node_id(),
823                    );
824                    app.events_sender
825                        .unbounded_send(EventsChunk::Processed(processed_events))
826                        .unwrap();
827                    app.position = CursorPoint::from((location.x, location.y));
828                }
829                WindowEvent::Ime(Ime::Preedit(text, pos)) => {
830                    let platform_event = PlatformEvent::ImePreedit {
831                        name: ImeEventName::Preedit,
832                        text,
833                        cursor: pos,
834                    };
835                    let mut events_measurer_adapter = EventsMeasurerAdapter {
836                        tree: &mut app.tree,
837                        scale_factor: app.window.scale_factor(),
838                    };
839                    let processed_events = events_measurer_adapter.run(
840                        &mut vec![platform_event],
841                        &mut app.nodes_state,
842                        app.accessibility.focused_node_id(),
843                    );
844                    app.events_sender
845                        .unbounded_send(EventsChunk::Processed(processed_events))
846                        .unwrap();
847                }
848                WindowEvent::DroppedFile(file_path) => {
849                    app.dropped_file_paths.push(file_path);
850                }
851                WindowEvent::HoveredFile(file_path) => {
852                    let platform_event = PlatformEvent::File {
853                        name: FileEventName::FileHover,
854                        file_path: Some(file_path),
855                        cursor: app.position,
856                    };
857                    let mut events_measurer_adapter = EventsMeasurerAdapter {
858                        tree: &mut app.tree,
859                        scale_factor: app.window.scale_factor(),
860                    };
861                    let processed_events = events_measurer_adapter.run(
862                        &mut vec![platform_event],
863                        &mut app.nodes_state,
864                        app.accessibility.focused_node_id(),
865                    );
866                    app.events_sender
867                        .unbounded_send(EventsChunk::Processed(processed_events))
868                        .unwrap();
869                }
870                WindowEvent::HoveredFileCancelled => {
871                    let platform_event = PlatformEvent::File {
872                        name: FileEventName::FileHoverCancelled,
873                        file_path: None,
874                        cursor: app.position,
875                    };
876                    let mut events_measurer_adapter = EventsMeasurerAdapter {
877                        tree: &mut app.tree,
878                        scale_factor: app.window.scale_factor(),
879                    };
880                    let processed_events = events_measurer_adapter.run(
881                        &mut vec![platform_event],
882                        &mut app.nodes_state,
883                        app.accessibility.focused_node_id(),
884                    );
885                    app.events_sender
886                        .unbounded_send(EventsChunk::Processed(processed_events))
887                        .unwrap();
888                }
889                _ => {}
890            }
891        }
892    }
893}