iced_winit/
program.rs

1//! Create interactive, native cross-platform applications for WGPU.
2#[path = "application/drag_resize.rs"]
3mod drag_resize;
4mod state;
5pub(crate) mod window_manager;
6
7use iced_futures::core::window::Id;
8pub use runtime::{default, Appearance, DefaultStyle};
9use window_manager::ViewFn;
10use winit::dpi::PhysicalSize;
11use winit::event::WindowEvent;
12use winit::event_loop::OwnedDisplayHandle;
13
14use crate::conversion;
15use crate::core;
16use crate::core::mouse;
17use crate::core::renderer;
18use crate::core::time::Instant;
19use crate::core::widget::operation;
20use crate::core::widget::Operation;
21use crate::core::window;
22use crate::core::Clipboard as CoreClipboard;
23use crate::core::Length;
24use crate::core::{Element, Point, Size};
25use crate::futures::futures::channel::mpsc;
26use crate::futures::futures::channel::oneshot;
27use crate::futures::futures::task;
28use crate::futures::futures::{Future, StreamExt};
29use crate::futures::subscription::{self, Subscription};
30use crate::futures::{Executor, Runtime};
31use crate::graphics;
32use crate::graphics::{compositor, Compositor};
33use crate::platform_specific;
34use crate::runtime::user_interface::{self, UserInterface};
35use crate::runtime::Debug;
36use crate::runtime::{self, Action, Task};
37use crate::{Clipboard, Error, Proxy, Settings};
38use dnd::DndSurface;
39use dnd::Icon;
40use iced_futures::core::widget::operation::search_id;
41use iced_graphics::Viewport;
42pub use state::State;
43use window_clipboard::mime::ClipboardStoreData;
44use winit::raw_window_handle::HasWindowHandle;
45
46pub(crate) use window_manager::WindowManager;
47
48use rustc_hash::FxHashMap;
49use std::any::Any;
50use std::borrow::Cow;
51use std::collections::HashMap;
52use std::mem::ManuallyDrop;
53use std::sync::Arc;
54use std::sync::Mutex;
55use std::time::Duration;
56
57/// An interactive, native, cross-platform, multi-windowed application.
58///
59/// This trait is the main entrypoint of multi-window Iced. Once implemented, you can run
60/// your GUI application by simply calling [`run`]. It will run in
61/// its own window.
62///
63/// A [`Program`] can execute asynchronous actions by returning a
64/// [`Task`] in some of its methods.
65///
66/// When using a [`Program`] with the `debug` feature enabled, a debug view
67/// can be toggled by pressing `F12`.
68pub trait Program
69where
70    Self: Sized,
71    Self::Theme: DefaultStyle,
72{
73    /// The type of __messages__ your [`Program`] will produce.
74    type Message: std::fmt::Debug + Send;
75
76    /// The theme used to draw the [`Program`].
77    type Theme;
78
79    /// The [`Executor`] that will run commands and subscriptions.
80    ///
81    /// The [default executor] can be a good starting point!
82    ///
83    /// [`Executor`]: Self::Executor
84    /// [default executor]: crate::futures::backend::default::Executor
85    type Executor: Executor;
86
87    /// The graphics backend to use to draw the [`Program`].
88    type Renderer: core::Renderer + core::text::Renderer;
89
90    /// The data needed to initialize your [`Program`].
91    type Flags;
92
93    /// Initializes the [`Program`] with the flags provided to
94    /// [`run`] as part of the [`Settings`].
95    ///
96    /// Here is where you should return the initial state of your app.
97    ///
98    /// Additionally, you can return a [`Task`] if you need to perform some
99    /// async action in the background on startup. This is useful if you want to
100    /// load state from a file, perform an initial HTTP request, etc.
101    fn new(flags: Self::Flags) -> (Self, Task<Self::Message>);
102
103    /// Returns the current title of the [`Program`].
104    ///
105    /// This title can be dynamic! The runtime will automatically update the
106    /// title of your application when necessary.
107    fn title(&self, window: window::Id) -> String;
108
109    /// Handles a __message__ and updates the state of the [`Program`].
110    ///
111    /// This is where you define your __update logic__. All the __messages__,
112    /// produced by either user interactions or commands, will be handled by
113    /// this method.
114    ///
115    /// Any [`Task`] returned will be executed immediately in the background by the
116    /// runtime.
117    fn update(&mut self, message: Self::Message) -> Task<Self::Message>;
118
119    /// Returns the widgets to display in the [`Program`] for the `window`.
120    ///
121    /// These widgets can produce __messages__ based on user interaction.
122    fn view(
123        &self,
124        window: window::Id,
125    ) -> Element<'_, Self::Message, Self::Theme, Self::Renderer>;
126
127    /// Returns the current `Theme` of the [`Program`].
128    fn theme(&self, window: window::Id) -> Self::Theme;
129
130    /// Returns the `Style` variation of the `Theme`.
131    fn style(&self, theme: &Self::Theme) -> Appearance {
132        theme.default_style()
133    }
134
135    /// Returns the event `Subscription` for the current state of the
136    /// application.
137    ///
138    /// The messages produced by the `Subscription` will be handled by
139    /// [`update`](#tymethod.update).
140    ///
141    /// A `Subscription` will be kept alive as long as you keep returning it!
142    ///
143    /// By default, it returns an empty subscription.
144    fn subscription(&self) -> Subscription<Self::Message> {
145        Subscription::none()
146    }
147
148    /// Returns the scale factor of the window of the [`Program`].
149    ///
150    /// It can be used to dynamically control the size of the UI at runtime
151    /// (i.e. zooming).
152    ///
153    /// For instance, a scale factor of `2.0` will make widgets twice as big,
154    /// while a scale factor of `0.5` will shrink them to half their size.
155    ///
156    /// By default, it returns `1.0`.
157    #[allow(unused_variables)]
158    fn scale_factor(&self, window: window::Id) -> f64 {
159        1.0
160    }
161
162    fn with_program<T>(&self, f: impl Fn(&Self) -> T) -> T {
163        f(self)
164    }
165}
166
167/// Runs a [`Program`] with an executor, compositor, and the provided
168/// settings.
169pub fn run<P, C>(
170    settings: Settings,
171    graphics_settings: graphics::Settings,
172    window_settings: Option<window::Settings>,
173    flags: P::Flags,
174) -> Result<(), Error>
175where
176    P: Program + 'static,
177    C: Compositor<Renderer = P::Renderer> + 'static,
178    P::Theme: DefaultStyle,
179{
180    use winit::event_loop::EventLoop;
181
182    let mut debug = Debug::new();
183    debug.startup_started();
184
185    let event_loop = EventLoop::new().expect("Create event loop");
186    #[cfg(feature = "wayland")]
187    let is_wayland =
188        winit::platform::wayland::EventLoopExtWayland::is_wayland(&event_loop);
189    #[cfg(not(feature = "wayland"))]
190    let is_wayland = false;
191
192    let (event_sender, event_receiver) = mpsc::unbounded();
193    let (proxy, worker): (Proxy<<P as Program>::Message>, _) =
194        Proxy::new(event_loop.create_proxy(), event_sender.clone());
195
196    let mut runtime = {
197        let executor =
198            P::Executor::new().map_err(Error::ExecutorCreationFailed)?;
199        executor.spawn(worker);
200
201        Runtime::new(executor, proxy.clone())
202    };
203
204    let (program, task) = runtime.enter(|| P::new(flags));
205    let is_daemon = window_settings.is_none() || settings.is_daemon;
206
207    let task = if let Some(window_settings) = window_settings {
208        let mut task = Some(task);
209
210        let open = iced_runtime::task::oneshot(|channel| {
211            iced_runtime::Action::Window(iced_runtime::window::Action::Open(
212                iced_runtime::core::window::Id::RESERVED,
213                window_settings,
214                channel,
215            ))
216        });
217
218        open.then(move |_| task.take().unwrap_or(Task::none()))
219    } else {
220        task
221    };
222
223    if let Some(stream) = runtime::task::into_stream(task) {
224        runtime.run(stream);
225    }
226
227    runtime.track(subscription::into_recipes(
228        runtime.enter(|| program.subscription().map(Action::Output)),
229    ));
230
231    let (boot_sender, boot_receiver) = oneshot::channel();
232    let (control_sender, control_receiver) = mpsc::unbounded();
233
234    let instance = Box::pin(run_instance::<P, C>(
235        program,
236        runtime,
237        proxy.clone(),
238        debug,
239        boot_receiver,
240        event_receiver,
241        control_sender.clone(),
242        event_loop.owned_display_handle(),
243        is_daemon,
244    ));
245
246    let context = task::Context::from_waker(task::noop_waker_ref());
247
248    struct Runner<Message: 'static, F, C> {
249        instance: std::pin::Pin<Box<F>>,
250        context: task::Context<'static>,
251        id: Option<String>,
252        boot: Option<BootConfig<C>>,
253        sender: mpsc::UnboundedSender<Event<Message>>,
254        receiver: mpsc::UnboundedReceiver<Control>,
255        error: Option<Error>,
256        proxy: Proxy<Message>,
257
258        #[cfg(target_arch = "wasm32")]
259        is_booted: std::rc::Rc<std::cell::RefCell<bool>>,
260        #[cfg(target_arch = "wasm32")]
261        canvas: Option<web_sys::HtmlCanvasElement>,
262    }
263
264    struct BootConfig<C> {
265        sender: oneshot::Sender<Boot<C>>,
266        fonts: Vec<Cow<'static, [u8]>>,
267        graphics_settings: graphics::Settings,
268        control_sender: mpsc::UnboundedSender<Control>,
269        is_wayland: bool,
270    }
271
272    let runner = Runner {
273        instance,
274        context,
275        id: settings.id,
276        boot: Some(BootConfig {
277            sender: boot_sender,
278            fonts: settings.fonts,
279            graphics_settings,
280            control_sender,
281            is_wayland,
282        }),
283        sender: event_sender,
284        receiver: control_receiver,
285        error: None,
286        proxy: proxy.clone(),
287
288        #[cfg(target_arch = "wasm32")]
289        is_booted: std::rc::Rc::new(std::cell::RefCell::new(false)),
290        #[cfg(target_arch = "wasm32")]
291        canvas: None,
292    };
293
294    impl<Message, F, C> winit::application::ApplicationHandler
295        for Runner<Message, F, C>
296    where
297        Message: std::fmt::Debug,
298        F: Future<Output = ()>,
299        C: Compositor + 'static,
300    {
301        fn proxy_wake_up(
302            &mut self,
303            event_loop: &dyn winit::event_loop::ActiveEventLoop,
304        ) {
305            self.process_event(event_loop, None);
306        }
307
308        fn new_events(
309            &mut self,
310            event_loop: &dyn winit::event_loop::ActiveEventLoop,
311            cause: winit::event::StartCause,
312        ) {
313            if self.boot.is_some() {
314                return;
315            }
316            self.process_event(event_loop, Some(Event::NewEvents(cause)));
317        }
318
319        fn window_event(
320            &mut self,
321            event_loop: &dyn winit::event_loop::ActiveEventLoop,
322            window_id: winit::window::WindowId,
323            event: winit::event::WindowEvent,
324        ) {
325            #[cfg(target_os = "windows")]
326            let is_move_or_resize = matches!(
327                event,
328                winit::event::WindowEvent::SurfaceResized(_)
329                    | winit::event::WindowEvent::Moved(_)
330            );
331
332            #[cfg(feature = "wayland")]
333            {
334                if matches!(event, WindowEvent::RedrawRequested) {
335                    for id in
336                        crate::subsurface_widget::subsurface_ids(window_id)
337                    {
338                        _ = self.sender.start_send(Event::Winit(
339                            id,
340                            WindowEvent::RedrawRequested,
341                        ));
342                    }
343                } else if matches!(event, WindowEvent::RedrawRequested) {
344                    for id in
345                        crate::subsurface_widget::subsurface_ids(window_id)
346                    {
347                        _ = self.sender.start_send(Event::Winit(
348                            id,
349                            WindowEvent::CloseRequested,
350                        ));
351                    }
352                }
353            }
354
355            self.process_event(
356                event_loop,
357                Some(Event::Winit(window_id, event)),
358            );
359
360            // TODO: Remove when unnecessary
361            // On Windows, we emulate an `AboutToWait` event after every `Resized` event
362            // since the event loop does not resume during resize interaction.
363            // More details: https://github.com/rust-windowing/winit/issues/3272
364            #[cfg(target_os = "windows")]
365            {
366                if is_move_or_resize {
367                    self.process_event(event_loop, Some(Event::AboutToWait));
368                }
369            }
370        }
371
372        fn about_to_wait(
373            &mut self,
374            event_loop: &dyn winit::event_loop::ActiveEventLoop,
375        ) {
376            self.process_event(event_loop, Some(Event::AboutToWait));
377        }
378
379        fn can_create_surfaces(
380            &mut self,
381            event_loop: &dyn winit::event_loop::ActiveEventLoop,
382        ) {
383            // create initial window
384            let Some(BootConfig {
385                sender,
386                fonts,
387                graphics_settings,
388                control_sender,
389                is_wayland,
390            }) = self.boot.take()
391            else {
392                return;
393            };
394
395            let window: Arc<dyn winit::window::Window> = match event_loop
396                .create_window(
397                    winit::window::WindowAttributes::default()
398                        .with_visible(false),
399                ) {
400                Ok(window) => Arc::from(window),
401                Err(error) => {
402                    self.error = Some(Error::WindowCreationFailed(error));
403                    event_loop.exit();
404                    return;
405                }
406            };
407
408            #[cfg(target_arch = "wasm32")]
409            {
410                use winit::platform::web::WindowExtWebSys;
411                self.canvas = window.canvas();
412            }
413
414            let proxy = self.proxy.raw.clone();
415            let finish_boot = async move {
416                let mut compositor =
417                    C::new(graphics_settings, window.clone()).await?;
418
419                for font in fonts {
420                    compositor.load_font(font);
421                }
422
423                sender
424                    .send(Boot {
425                        compositor,
426                        is_wayland,
427                        clipboard: Clipboard::connect(
428                            window,
429                            crate::clipboard::ControlSender {
430                                sender: control_sender,
431                                proxy,
432                            },
433                        ),
434                    })
435                    .ok()
436                    .expect("Send boot event");
437
438                Ok::<_, graphics::Error>(())
439            };
440
441            #[cfg(not(target_arch = "wasm32"))]
442            if let Err(error) =
443                crate::futures::futures::executor::block_on(finish_boot)
444            {
445                self.error = Some(Error::GraphicsCreationFailed(error));
446                event_loop.exit();
447            }
448
449            #[cfg(target_arch = "wasm32")]
450            {
451                let is_booted = self.is_booted.clone();
452
453                wasm_bindgen_futures::spawn_local(async move {
454                    finish_boot.await.expect("Finish boot!");
455
456                    *is_booted.borrow_mut() = true;
457                });
458
459                event_loop
460                    .set_control_flow(winit::event_loop::ControlFlow::Poll);
461            }
462        }
463    }
464
465    impl<Message, F, C> Runner<Message, F, C>
466    where
467        F: Future<Output = ()>,
468        C: Compositor,
469    {
470        fn process_event(
471            &mut self,
472            event_loop: &dyn winit::event_loop::ActiveEventLoop,
473            event: Option<Event<Message>>,
474        ) {
475            if event_loop.exiting() {
476                return;
477            }
478
479            if let Some(event) = event {
480                self.sender.start_send(event).expect("Send event");
481            }
482
483            loop {
484                let poll = self.instance.as_mut().poll(&mut self.context);
485
486                match poll {
487                    task::Poll::Pending => match self.receiver.try_next() {
488                        Ok(Some(control)) => match control {
489                            Control::ChangeFlow(flow) => {
490                                use winit::event_loop::ControlFlow;
491
492                                match (event_loop.control_flow(), flow) {
493                                    (
494                                        ControlFlow::WaitUntil(current),
495                                        ControlFlow::WaitUntil(new),
496                                    ) if new < current => {}
497                                    (
498                                        ControlFlow::WaitUntil(target),
499                                        ControlFlow::Wait,
500                                    ) if target > Instant::now() => {}
501                                    _ => {
502                                        event_loop.set_control_flow(flow);
503                                    }
504                                }
505                            }
506                            Control::CreateWindow {
507                                id,
508                                settings,
509                                title,
510                                monitor,
511                                on_open,
512                            } => {
513                                let exit_on_close_request =
514                                    settings.exit_on_close_request;
515                                let resize_border = settings.resize_border;
516
517                                let visible = settings.visible;
518
519                                #[cfg(target_arch = "wasm32")]
520                                let target =
521                                    settings.platform_specific.target.clone();
522
523                                let window_attributes =
524                                    conversion::window_attributes(
525                                        settings,
526                                        &title,
527                                        monitor
528                                            .or(event_loop.primary_monitor()),
529                                        self.id.clone(),
530                                    )
531                                    .with_visible(false);
532
533                                #[cfg(target_arch = "wasm32")]
534                                let window_attributes = {
535                                    use winit::platform::web::WindowAttributesExtWebSys;
536                                    window_attributes
537                                        .with_canvas(self.canvas.take())
538                                };
539
540                                log::info!("Window attributes for id `{id:#?}`: {window_attributes:#?}");
541
542                                let window = Arc::from(
543                                    event_loop
544                                        .create_window(window_attributes)
545                                        .expect("Create window"),
546                                );
547
548                                #[cfg(target_arch = "wasm32")]
549                                {
550                                    use winit::platform::web::WindowExtWebSys;
551
552                                    let canvas = window
553                                        .canvas()
554                                        .expect("Get window canvas");
555
556                                    let _ = canvas.set_attribute(
557                                        "style",
558                                        "display: block; width: 100%; height: 100%",
559                                    );
560
561                                    let window = web_sys::window().unwrap();
562                                    let document = window.document().unwrap();
563                                    let body = document.body().unwrap();
564
565                                    let target = target.and_then(|target| {
566                                        body.query_selector(&format!(
567                                            "#{target}"
568                                        ))
569                                        .ok()
570                                        .unwrap_or(None)
571                                    });
572
573                                    match target {
574                                        Some(node) => {
575                                            let _ = node
576                                                .replace_with_with_node_1(
577                                                    &canvas,
578                                                )
579                                                .expect(&format!(
580                                                    "Could not replace #{}",
581                                                    node.id()
582                                                ));
583                                        }
584                                        None => {
585                                            let _ = body
586                                                .append_child(&canvas)
587                                                .expect(
588                                                "Append canvas to HTML body",
589                                            );
590                                        }
591                                    };
592                                }
593
594                                self.process_event(
595                                    event_loop,
596                                    Some(Event::WindowCreated {
597                                        id,
598                                        window,
599                                        exit_on_close_request,
600                                        make_visible: visible,
601                                        on_open,
602                                        resize_border,
603                                    }),
604                                );
605                            }
606                            Control::Exit => {
607                                event_loop.exit();
608                            }
609                            Control::Dnd(e) => {
610                                self.sender.start_send(Event::Dnd(e)).unwrap();
611                            }
612                            #[cfg(feature = "a11y")]
613                            Control::Accessibility(id, event) => {
614                                self.process_event(
615                                    event_loop,
616                                    Some(Event::Accessibility(id, event)),
617                                );
618                            }
619                            #[cfg(feature = "a11y")]
620                            Control::AccessibilityEnabled(event) => {
621                                self.process_event(
622                                    event_loop,
623                                    Some(Event::AccessibilityEnabled(event)),
624                                );
625                            }
626                            Control::PlatformSpecific(e) => {
627                                self.sender
628                                    .start_send(Event::PlatformSpecific(e))
629                                    .unwrap();
630                            }
631                            Control::AboutToWait => {
632                                self.sender
633                                    .start_send(Event::AboutToWait)
634                                    .expect("Send event");
635                            }
636                            Control::Winit(id, e) => {
637                                #[cfg(feature = "wayland")]
638                                {
639                                    if matches!(e, WindowEvent::RedrawRequested)
640                                    {
641                                        for id in crate::subsurface_widget::subsurface_ids(id) {
642                                            _ = self.sender
643                                                .start_send(Event::Winit(
644                                                id,
645                                                WindowEvent::RedrawRequested,
646                                            ));
647                                        }
648                                    } else if matches!(
649                                        e,
650                                        WindowEvent::RedrawRequested
651                                    ) {
652                                        for id in crate::subsurface_widget::subsurface_ids(id) {
653                                            _ = self.sender
654                                                .start_send(Event::Winit(
655                                                id,
656                                                WindowEvent::CloseRequested,
657                                            ));
658                                        }
659                                    }
660                                }
661                                self.sender
662                                    .start_send(Event::Winit(id, e))
663                                    .expect("Send event");
664                            }
665                            Control::StartDnd => {
666                                self.sender
667                                    .start_send(Event::StartDnd)
668                                    .expect("Send event");
669                            }
670                        },
671                        _ => {
672                            break;
673                        }
674                    },
675                    task::Poll::Ready(_) => {
676                        event_loop.exit();
677                        break;
678                    }
679                };
680            }
681        }
682    }
683
684    #[cfg(not(target_arch = "wasm32"))]
685    {
686        let mut runner = runner;
687        let _ = event_loop.run_app(&mut runner);
688
689        runner.error.map(Err).unwrap_or(Ok(()))
690    }
691
692    #[cfg(target_arch = "wasm32")]
693    {
694        use winit::platform::web::EventLoopExtWebSys;
695        let _ = event_loop.spawn_app(runner);
696
697        Ok(())
698    }
699}
700
701struct Boot<C> {
702    compositor: C,
703    is_wayland: bool,
704    clipboard: Clipboard,
705}
706
707pub(crate) enum Event<Message: 'static> {
708    WindowCreated {
709        id: window::Id,
710        window: Arc<dyn winit::window::Window>,
711        exit_on_close_request: bool,
712        make_visible: bool,
713        on_open: oneshot::Sender<window::Id>,
714        resize_border: u32,
715    },
716    Dnd(dnd::DndEvent<dnd::DndSurface>),
717    #[cfg(feature = "a11y")]
718    Accessibility(window::Id, iced_accessibility::accesskit::ActionRequest),
719    #[cfg(feature = "a11y")]
720    AccessibilityEnabled(bool),
721    Winit(winit::window::WindowId, winit::event::WindowEvent),
722    AboutToWait,
723    UserEvent(Action<Message>),
724    NewEvents(winit::event::StartCause),
725    PlatformSpecific(crate::platform_specific::Event),
726    StartDnd,
727}
728
729pub(crate) enum Control {
730    ChangeFlow(winit::event_loop::ControlFlow),
731    Exit,
732    CreateWindow {
733        id: window::Id,
734        settings: window::Settings,
735        title: String,
736        monitor: Option<winit::monitor::MonitorHandle>,
737        on_open: oneshot::Sender<window::Id>,
738    },
739    Dnd(dnd::DndEvent<dnd::DndSurface>),
740    #[cfg(feature = "a11y")]
741    Accessibility(window::Id, iced_accessibility::accesskit::ActionRequest),
742    #[cfg(feature = "a11y")]
743    AccessibilityEnabled(bool),
744    PlatformSpecific(crate::platform_specific::Event),
745    AboutToWait,
746    Winit(winit::window::WindowId, winit::event::WindowEvent),
747    StartDnd,
748}
749
750async fn run_instance<'a, P, C>(
751    mut program: P,
752    mut runtime: Runtime<P::Executor, Proxy<P::Message>, Action<P::Message>>,
753    mut proxy: Proxy<P::Message>,
754    mut debug: Debug,
755    boot: oneshot::Receiver<Boot<C>>,
756    mut event_receiver: mpsc::UnboundedReceiver<Event<P::Message>>,
757    mut control_sender: mpsc::UnboundedSender<Control>,
758    display_handle: OwnedDisplayHandle,
759    is_daemon: bool,
760) where
761    P: Program + 'static,
762    C: Compositor<Renderer = P::Renderer> + 'static,
763    P::Theme: DefaultStyle,
764{
765    use winit::event;
766    use winit::event_loop::ControlFlow;
767
768    let Boot {
769        mut compositor,
770        is_wayland,
771        mut clipboard,
772    } = boot.await.expect("Receive boot");
773
774    let mut platform_specific_handler =
775        crate::platform_specific::PlatformSpecific::default();
776    #[cfg(all(feature = "wayland", target_os = "linux"))]
777    if is_wayland {
778        platform_specific_handler = platform_specific_handler.with_wayland(
779            control_sender.clone(),
780            proxy.raw.clone(),
781            display_handle,
782        );
783    }
784
785    let mut window_manager = WindowManager::new();
786    let mut is_window_opening = !is_daemon;
787
788    let mut events = Vec::new();
789    let mut messages = Vec::new();
790    let mut actions = 0;
791
792    #[cfg(feature = "a11y")]
793    let (mut adapters, mut a11y_enabled) = if let Some((main_id, title, raw)) =
794        window_manager.ids().next().and_then(|id| {
795            window_manager
796                .get(id)
797                .map(|w| (id, w.state.title.clone(), w.raw.clone()))
798        }) {
799        let node_id = core::id::window_node_id();
800        use crate::a11y::*;
801        use iced_accessibility::accesskit::{
802            ActivationHandler, NodeBuilder, NodeId, Role, Tree, TreeUpdate,
803        };
804        use iced_accessibility::accesskit_winit::Adapter;
805
806        let activation_handler = WinitActivationHandler {
807            proxy: control_sender.clone(),
808            title: title.clone(),
809        };
810
811        let action_handler = WinitActionHandler {
812            id: main_id,
813            proxy: control_sender.clone(),
814        };
815
816        let deactivation_handler = WinitDeactivationHandler {
817            proxy: control_sender.clone(),
818        };
819        (
820            HashMap::from([(
821                main_id,
822                (
823                    node_id,
824                    Adapter::with_direct_handlers(
825                        raw.as_ref(),
826                        activation_handler,
827                        action_handler,
828                        deactivation_handler,
829                    ),
830                ),
831            )]),
832            false,
833        )
834    } else {
835        (Default::default(), false)
836    };
837
838    let mut ui_caches = FxHashMap::default();
839    let mut user_interfaces: ManuallyDrop<
840        HashMap<
841            window::Id,
842            UserInterface<
843                '_,
844                <P as Program>::Message,
845                <P as Program>::Theme,
846                <P as Program>::Renderer,
847            >,
848            rustc_hash::FxBuildHasher,
849        >,
850    > = ManuallyDrop::new(FxHashMap::default());
851
852    let mut cur_dnd_surface: Option<window::Id> = None;
853
854    let mut dnd_surface: Option<
855        Arc<Box<dyn HasWindowHandle + Send + Sync + 'static>>,
856    > = None;
857
858    debug.startup_finished();
859    loop {
860        // Empty the queue if possible
861        let event = if let Ok(event) = event_receiver.try_next() {
862            event
863        } else {
864            event_receiver.next().await
865        };
866
867        let Some(event) = event else {
868            break;
869        };
870        let mut rebuild_a11y_tree = false;
871
872        match event {
873            Event::StartDnd => {
874                let queued = clipboard.get_queued();
875                for crate::clipboard::StartDnd {
876                    internal,
877                    source_surface,
878                    icon_surface,
879                    content,
880                    actions,
881                } in queued
882                {
883                    let Some(window_id) = source_surface.and_then(|source| {
884                        match source {
885                            core::clipboard::DndSource::Surface(s) => Some(s),
886                            core::clipboard::DndSource::Widget(w) => {
887                                // search windows for widget with operation
888                                user_interfaces.iter_mut().find_map(
889                                    |(ui_id, ui)| {
890                                        let Some(ui_renderer) = window_manager
891                                            .get_mut(ui_id.clone())
892                                            .map(|w| &w.renderer)
893                                        else {
894                                            return None;
895                                        };
896
897                                        let operation: Box<dyn Operation<()>> =
898                                            Box::new(operation::map(
899                                                Box::new(search_id::search_id(
900                                                    w.clone(),
901                                                )),
902                                                |_| {},
903                                            ));
904                                        let mut current_operation =
905                                            Some(operation);
906
907                                        while let Some(mut operation) =
908                                            current_operation.take()
909                                        {
910                                            ui.operate(
911                                                ui_renderer,
912                                                operation.as_mut(),
913                                            );
914
915                                            match operation.finish() {
916                                                operation::Outcome::None => {}
917                                                operation::Outcome::Some(
918                                                    (),
919                                                ) => {
920                                                    return Some(ui_id.clone());
921                                                }
922                                                operation::Outcome::Chain(
923                                                    next,
924                                                ) => {
925                                                    current_operation =
926                                                        Some(next);
927                                                }
928                                            }
929                                        }
930                                        None
931                                    },
932                                )
933                            }
934                        }
935                    }) else {
936                        eprintln!("No source surface");
937                        continue;
938                    };
939
940                    let Some(window) = window_manager.get_mut(window_id) else {
941                        eprintln!("No window");
942                        continue;
943                    };
944
945                    let state = &window.state;
946                    let mut dnd_buffer = None;
947                    let icon_surface = icon_surface.map(|i| {
948                        let mut icon_surface =
949                            i.downcast::<P::Theme, P::Renderer>();
950
951                        let mut renderer = compositor.create_renderer();
952
953                        let lim = core::layout::Limits::new(
954                            Size::new(1., 1.),
955                            Size::new(
956                                state.viewport().physical_width() as f32,
957                                state.viewport().physical_height() as f32,
958                            ),
959                        );
960
961                        let mut tree = core::widget::Tree {
962                            id: icon_surface.element.as_widget().id(),
963                            tag: icon_surface.element.as_widget().tag(),
964                            state: icon_surface.state,
965                            children: icon_surface
966                                .element
967                                .as_widget()
968                                .children(),
969                        };
970
971                        let size = icon_surface
972                            .element
973                            .as_widget()
974                            .layout(&mut tree, &renderer, &lim);
975                        icon_surface.element.as_widget_mut().diff(&mut tree);
976
977                        let size = lim.resolve(
978                            Length::Shrink,
979                            Length::Shrink,
980                            size.size(),
981                        );
982                        let viewport = Viewport::with_logical_size(
983                            size,
984                            state.viewport().scale_factor(),
985                        );
986
987                        let mut ui = UserInterface::build(
988                            icon_surface.element,
989                            size,
990                            user_interface::Cache::default(),
991                            &mut renderer,
992                        );
993                        _ = ui.draw(
994                            &mut renderer,
995                            state.theme(),
996                            &renderer::Style {
997                                icon_color: state.icon_color(),
998                                text_color: state.text_color(),
999                                scale_factor: state.scale_factor(),
1000                            },
1001                            Default::default(),
1002                        );
1003                        let mut bytes = compositor.screenshot(
1004                            &mut renderer,
1005                            &viewport,
1006                            core::Color::TRANSPARENT,
1007                            &debug.overlay(),
1008                        );
1009                        for pix in bytes.chunks_exact_mut(4) {
1010                            // rgba -> argb little endian
1011                            pix.swap(0, 2);
1012                        }
1013                        // update subsurfaces
1014                        if let Some(surface) =
1015                            platform_specific_handler.create_surface()
1016                        {
1017                            // TODO Remove id
1018                            let id = window::Id::unique();
1019                            platform_specific_handler
1020                                .update_subsurfaces(id, &surface);
1021                            let surface = Arc::new(surface);
1022                            dnd_surface = Some(surface.clone());
1023                            dnd_buffer = Some((
1024                                viewport.physical_size(),
1025                                state.scale_factor(),
1026                                bytes,
1027                                icon_surface.offset,
1028                            ));
1029                            Icon::Surface(dnd::DndSurface(surface))
1030                        } else {
1031                            platform_specific_handler.clear_subsurface_list();
1032                            Icon::Buffer {
1033                                data: Arc::new(bytes),
1034                                width: viewport.physical_width(),
1035                                height: viewport.physical_height(),
1036                                transparent: true,
1037                            }
1038                        }
1039                    });
1040
1041                    clipboard.start_dnd_winit(
1042                        internal,
1043                        DndSurface(Arc::new(Box::new(window.raw.clone()))),
1044                        icon_surface,
1045                        content,
1046                        actions,
1047                    );
1048
1049                    // This needs to be after `wl_data_device::start_drag` for the offset to have an effect
1050                    if let (Some(surface), Some((size, scale, bytes, offset))) =
1051                        (dnd_surface.as_ref(), dnd_buffer)
1052                    {
1053                        platform_specific_handler.update_surface_shm(
1054                            &surface,
1055                            size.width,
1056                            size.height,
1057                            scale,
1058                            &bytes,
1059                            offset,
1060                        );
1061                    }
1062                }
1063            }
1064            Event::WindowCreated {
1065                id,
1066                window,
1067                exit_on_close_request,
1068                make_visible,
1069                on_open,
1070                resize_border,
1071            } => {
1072                let window = window_manager.insert(
1073                    id,
1074                    window,
1075                    &program,
1076                    &mut compositor,
1077                    exit_on_close_request,
1078                    resize_border,
1079                );
1080                #[cfg(feature = "wayland")]
1081                platform_specific_handler.send_wayland(
1082                    platform_specific::Action::TrackWindow(
1083                        window.raw.clone(),
1084                        id,
1085                    ),
1086                );
1087                #[cfg(feature = "a11y")]
1088                {
1089                    use crate::a11y::*;
1090                    use iced_accessibility::accesskit::{
1091                        ActivationHandler, NodeBuilder, NodeId, Role, Tree,
1092                        TreeUpdate,
1093                    };
1094                    use iced_accessibility::accesskit_winit::Adapter;
1095
1096                    let node_id = core::id::window_node_id();
1097
1098                    let activation_handler = WinitActivationHandler {
1099                        proxy: control_sender.clone(),
1100                        title: window.state.title.clone(),
1101                    };
1102
1103                    let action_handler = WinitActionHandler {
1104                        id,
1105                        proxy: control_sender.clone(),
1106                    };
1107
1108                    let deactivation_handler = WinitDeactivationHandler {
1109                        proxy: control_sender.clone(),
1110                    };
1111                    _ = adapters.insert(
1112                        id,
1113                        (
1114                            node_id,
1115                            Adapter::with_direct_handlers(
1116                                window.raw.as_ref(),
1117                                activation_handler,
1118                                action_handler,
1119                                deactivation_handler,
1120                            ),
1121                        ),
1122                    );
1123                }
1124
1125                let logical_size = window.state.logical_size();
1126
1127                let _ = user_interfaces.insert(
1128                    id,
1129                    build_user_interface(
1130                        &program,
1131                        user_interface::Cache::default(),
1132                        &mut window.renderer,
1133                        logical_size,
1134                        &mut debug,
1135                        id,
1136                        window.raw.clone(),
1137                        window.prev_dnd_destination_rectangles_count,
1138                        &mut clipboard,
1139                    ),
1140                );
1141                let _ = ui_caches.insert(id, user_interface::Cache::default());
1142
1143                if make_visible {
1144                    window.raw.set_visible(true);
1145                }
1146
1147                events.push((
1148                    Some(id),
1149                    core::Event::Window(window::Event::Opened {
1150                        position: window.position(),
1151                        size: window.size(),
1152                    }),
1153                ));
1154
1155                if clipboard.window_id().is_none() {
1156                    clipboard = Clipboard::connect(
1157                        window.raw.clone(),
1158                        crate::clipboard::ControlSender {
1159                            sender: control_sender.clone(),
1160                            proxy: proxy.raw.clone(),
1161                        },
1162                    );
1163                }
1164
1165                let _ = on_open.send(id);
1166                is_window_opening = false;
1167            }
1168            Event::UserEvent(action) => {
1169                rebuild_a11y_tree = true;
1170                let exited = run_action(
1171                    action,
1172                    &program,
1173                    &mut compositor,
1174                    &mut events,
1175                    &mut messages,
1176                    &mut clipboard,
1177                    &mut control_sender,
1178                    &mut debug,
1179                    &mut user_interfaces,
1180                    &mut window_manager,
1181                    &mut ui_caches,
1182                    &mut is_window_opening,
1183                    &mut platform_specific_handler,
1184                );
1185                if exited {
1186                    runtime.track(None.into_iter());
1187                }
1188                actions += 1;
1189            }
1190            Event::NewEvents(
1191                event::StartCause::Init
1192                | event::StartCause::ResumeTimeReached { .. },
1193            ) => {
1194                if window_manager.ids().next().is_none() {
1195                    _ = control_sender
1196                        .start_send(Control::ChangeFlow(ControlFlow::Wait));
1197                }
1198                for (_id, window) in window_manager.iter_mut() {
1199                    window.request_redraw();
1200                }
1201            }
1202            Event::Winit(window_id, event) => {
1203                #[cfg(feature = "a11y")]
1204                {
1205                    if let Some((id, window)) =
1206                        window_manager.get_mut_alias(window_id)
1207                    {
1208                        if let Some(Some((_, adapter))) =
1209                            a11y_enabled.then(|| adapters.get_mut(&id))
1210                        {
1211                            adapter.process_event(window.raw.as_ref(), &event);
1212                        };
1213                    }
1214                }
1215                match event {
1216                    event::WindowEvent::RedrawRequested => {
1217                        let Some((id, window)) =
1218                            window_manager.get_mut_alias(window_id)
1219                        else {
1220                            continue;
1221                        };
1222
1223                        window.redraw_requested = false;
1224
1225                        // TODO: Avoid redrawing all the time by forcing widgets to
1226                        // request redraws on state changes
1227                        //
1228                        // Then, we can use the `interface_state` here to decide if a redraw
1229                        // is needed right away, or simply wait until a specific time.
1230                        let redraw_event = core::Event::Window(
1231                            window::Event::RedrawRequested(Instant::now()),
1232                        );
1233
1234                        let cursor = window.state.cursor();
1235
1236                        let ui = user_interfaces
1237                            .get_mut(&id)
1238                            .expect("Get user interface");
1239
1240                        let (ui_state, _) = ui.update(
1241                            &[redraw_event.clone()],
1242                            cursor,
1243                            &mut window.renderer,
1244                            &mut clipboard,
1245                            &mut messages,
1246                        );
1247
1248                        debug.draw_started();
1249                        let new_mouse_interaction = ui.draw(
1250                            &mut window.renderer,
1251                            window.state.theme(),
1252                            &renderer::Style {
1253                                icon_color: window.state.icon_color(),
1254                                text_color: window.state.text_color(),
1255                                scale_factor: window.state.scale_factor(),
1256                            },
1257                            cursor,
1258                        );
1259                        platform_specific_handler.update_subsurfaces(
1260                            id,
1261                            window.raw.rwh_06_window_handle(),
1262                        );
1263                        debug.draw_finished();
1264
1265                        if new_mouse_interaction != window.mouse_interaction {
1266                            if let Some(interaction) =
1267                                conversion::mouse_interaction(
1268                                    new_mouse_interaction,
1269                                )
1270                            {
1271                                if matches!(
1272                                    window.mouse_interaction,
1273                                    mouse::Interaction::Hide
1274                                ) {
1275                                    window.raw.set_cursor_visible(true);
1276                                }
1277                                window.raw.set_cursor(interaction.into())
1278                            } else {
1279                                window.raw.set_cursor_visible(false);
1280                            }
1281
1282                            window.mouse_interaction = new_mouse_interaction;
1283                        }
1284
1285                        runtime.broadcast(subscription::Event::Interaction {
1286                            window: id,
1287                            event: redraw_event,
1288                            status: core::event::Status::Ignored,
1289                        });
1290
1291                        if control_sender
1292                            .start_send(Control::ChangeFlow(match ui_state {
1293                                user_interface::State::Updated {
1294                                    redraw_request: Some(redraw_request),
1295                                } => match redraw_request {
1296                                    window::RedrawRequest::NextFrame => {
1297                                        window.request_redraw();
1298
1299                                        ControlFlow::Wait
1300                                    }
1301                                    window::RedrawRequest::At(at) => {
1302                                        ControlFlow::WaitUntil(at)
1303                                    }
1304                                },
1305                                _ => ControlFlow::Wait,
1306                            }))
1307                            .is_err()
1308                        {
1309                            panic!("send error");
1310                        }
1311
1312                        let physical_size = window.state.physical_size();
1313                        if physical_size.width == 0 || physical_size.height == 0
1314                        {
1315                            continue;
1316                        }
1317                        if window.viewport_version
1318                            != window.state.viewport_version()
1319                        {
1320                            let logical_size = window.state.logical_size();
1321                            debug.layout_started();
1322                            let mut ui = user_interfaces
1323                                .remove(&id)
1324                                .expect("Remove user interface")
1325                                .relayout(logical_size, &mut window.renderer);
1326
1327                            let _ = user_interfaces.insert(id, ui);
1328                            debug.layout_finished();
1329
1330                            debug.draw_started();
1331                            let new_mouse_interaction = user_interfaces
1332                                .get_mut(&id)
1333                                .expect("Get user interface")
1334                                .draw(
1335                                    &mut window.renderer,
1336                                    window.state.theme(),
1337                                    &renderer::Style {
1338                                        icon_color: window.state.icon_color(),
1339                                        text_color: window.state.text_color(),
1340                                        scale_factor: window
1341                                            .state
1342                                            .scale_factor(),
1343                                    },
1344                                    window.state.cursor(),
1345                                );
1346                            platform_specific_handler.update_subsurfaces(
1347                                id,
1348                                window.raw.rwh_06_window_handle(),
1349                            );
1350                            debug.draw_finished();
1351
1352                            if new_mouse_interaction != window.mouse_interaction
1353                            {
1354                                if let Some(interaction) =
1355                                    conversion::mouse_interaction(
1356                                        new_mouse_interaction,
1357                                    )
1358                                {
1359                                    if matches!(
1360                                        window.mouse_interaction,
1361                                        mouse::Interaction::Hide
1362                                    ) {
1363                                        window.raw.set_cursor_visible(true);
1364                                    }
1365                                    window.raw.set_cursor(interaction.into())
1366                                } else {
1367                                    window.raw.set_cursor_visible(false);
1368                                }
1369
1370                                window.mouse_interaction =
1371                                    new_mouse_interaction;
1372                            }
1373                            compositor.configure_surface(
1374                                &mut window.surface,
1375                                physical_size.width,
1376                                physical_size.height,
1377                            );
1378
1379                            window.viewport_version =
1380                                window.state.viewport_version();
1381                        }
1382
1383                        window.raw.pre_present_notify();
1384                        debug.render_started();
1385                        match compositor.present(
1386                            &mut window.renderer,
1387                            &mut window.surface,
1388                            window.state.viewport(),
1389                            window.state.background_color(),
1390                            &debug.overlay(),
1391                        ) {
1392                            Ok(()) => {
1393                                debug.render_finished();
1394                            }
1395                            Err(error) => {
1396                                match error {
1397                                    // This is an unrecoverable error.
1398                                    compositor::SurfaceError::OutOfMemory => {
1399                                        panic!("{:?}", error);
1400                                    }
1401                                    compositor::SurfaceError::NoDamage => {
1402                                        debug.render_finished();
1403
1404                                        // TODO Ideally there would be a way to know if some widget wants to animate?
1405                                        let _ = control_sender.start_send(
1406                                        Control::ChangeFlow(
1407                                                ControlFlow::WaitUntil(
1408                                                    Instant::now().checked_add(
1409                                                        Duration::from_millis(100),
1410                                                    ).unwrap_or(Instant::now()),
1411                                                ),
1412                                            ),
1413                                        );
1414                                    }
1415                                    _ => {
1416                                        debug.render_finished();
1417                                        log::error!(
1418                                            "Error {error:?} when \
1419                                        presenting surface."
1420                                        );
1421
1422                                        // Try rendering all windows again next frame.
1423                                        for (_id, window) in
1424                                            window_manager.iter_mut()
1425                                        {
1426                                            window.request_redraw();
1427                                        }
1428                                    }
1429                                }
1430                            }
1431                        }
1432                    }
1433                    window_event => {
1434                        if !is_daemon
1435                            && matches!(
1436                                window_event,
1437                                winit::event::WindowEvent::Destroyed
1438                            )
1439                            && !is_window_opening
1440                            && window_manager.is_empty()
1441                        {
1442                            runtime.track(None.into_iter());
1443                            control_sender
1444                                .start_send(Control::Exit)
1445                                .expect("Send control action");
1446
1447                            continue;
1448                        }
1449
1450                        let Some((id, window)) =
1451                            window_manager.get_mut_alias(window_id)
1452                        else {
1453                            continue;
1454                        };
1455
1456                        // Initiates a drag resize window state when found.
1457                        if let Some(func) =
1458                            window.drag_resize_window_func.as_mut()
1459                        {
1460                            if func(window.raw.as_ref(), &window_event) {
1461                                continue;
1462                            }
1463                        }
1464
1465                        if matches!(
1466                            window_event,
1467                            winit::event::WindowEvent::CloseRequested
1468                        ) && window.exit_on_close_request
1469                        {
1470                            _ = run_action(
1471                                Action::Window(runtime::window::Action::Close(
1472                                    id,
1473                                )),
1474                                &program,
1475                                &mut compositor,
1476                                &mut events,
1477                                &mut messages,
1478                                &mut clipboard,
1479                                &mut control_sender,
1480                                &mut debug,
1481                                &mut user_interfaces,
1482                                &mut window_manager,
1483                                &mut ui_caches,
1484                                &mut is_window_opening,
1485                                &mut platform_specific_handler,
1486                            );
1487                        } else {
1488                            window.state.update(
1489                                window.raw.as_ref(),
1490                                &window_event,
1491                                &mut debug,
1492                            );
1493                            if let Some(event) = conversion::window_event(
1494                                window_event,
1495                                window.state.scale_factor(),
1496                                window.state.modifiers(),
1497                            ) {
1498                                events.push((Some(id), event));
1499                            }
1500                        }
1501                    }
1502                    _ => {}
1503                }
1504            }
1505            Event::AboutToWait => {
1506                let skip = events.is_empty() && messages.is_empty();
1507                if skip
1508                    && window_manager.iter_mut().all(|(_, w)| !w.resize_enabled)
1509                {
1510                    _ = control_sender
1511                        .start_send(Control::ChangeFlow(ControlFlow::Wait));
1512                    continue;
1513                }
1514
1515                debug.event_processing_started();
1516                let mut uis_stale = false;
1517                let mut resized = false;
1518                for (id, window) in window_manager.iter_mut() {
1519                    if skip && !window.resize_enabled {
1520                        _ = control_sender
1521                            .start_send(Control::ChangeFlow(ControlFlow::Wait));
1522                        continue;
1523                    }
1524                    let mut window_events = vec![];
1525
1526                    events.retain(|(window_id, event)| {
1527                        if *window_id == Some(id) {
1528                            window_events.push(event.clone());
1529                            false
1530                        } else {
1531                            true
1532                        }
1533                    });
1534                    let no_window_events = window_events.is_empty();
1535                    #[cfg(feature = "wayland")]
1536                    window_events.push(core::Event::PlatformSpecific(
1537                        core::event::PlatformSpecific::Wayland(
1538                            core::event::wayland::Event::RequestResize,
1539                        ),
1540                    ));
1541                    let (ui_state, statuses) = user_interfaces
1542                        .get_mut(&id)
1543                        .expect("Get user interface")
1544                        .update(
1545                            &window_events,
1546                            window.state.cursor(),
1547                            &mut window.renderer,
1548                            &mut clipboard,
1549                            &mut messages,
1550                        );
1551
1552                    let mut needs_redraw =
1553                        !no_window_events || !messages.is_empty();
1554
1555                    if let Some(requested_size) =
1556                        clipboard.requested_logical_size.lock().unwrap().take()
1557                    {
1558                        let requested_physical_size: PhysicalSize<u32> =
1559                            winit::dpi::PhysicalSize::from_logical(
1560                                requested_size.cast::<u32>(),
1561                                window.state.scale_factor(),
1562                            );
1563
1564                        let physical_size = window.state.physical_size();
1565                        if requested_physical_size.width != physical_size.width
1566                            || requested_physical_size.height
1567                                != physical_size.height
1568                        {
1569                            // FIXME what to do when we are stuck in a configure event/resize request loop
1570                            // We don't have control over how winit handles this.
1571                            window.resize_enabled = true;
1572                            resized = true;
1573                            needs_redraw = true;
1574                            let s = winit::dpi::Size::Logical(
1575                                requested_size.cast(),
1576                            );
1577                            _ = window.raw.request_surface_size(s);
1578                            window.raw.set_min_surface_size(Some(s));
1579                            window.raw.set_max_surface_size(Some(s));
1580                            window.state.synchronize(
1581                                &program,
1582                                id,
1583                                window.raw.as_ref(),
1584                            );
1585                        }
1586                    }
1587                    if needs_redraw {
1588                        window.request_redraw();
1589                    } else {
1590                        _ = control_sender
1591                            .start_send(Control::ChangeFlow(ControlFlow::Wait));
1592                        continue;
1593                    }
1594
1595                    if !uis_stale {
1596                        uis_stale =
1597                            matches!(ui_state, user_interface::State::Outdated);
1598                    }
1599
1600                    for (event, status) in
1601                        window_events.into_iter().zip(statuses.into_iter())
1602                    {
1603                        runtime.broadcast(subscription::Event::Interaction {
1604                            window: id,
1605                            event,
1606                            status,
1607                        });
1608                    }
1609                }
1610
1611                if !resized && skip {
1612                    _ = control_sender
1613                        .start_send(Control::ChangeFlow(ControlFlow::Wait));
1614                    continue;
1615                }
1616
1617                for (id, event) in events.drain(..) {
1618                    if id.is_none()
1619                        && matches!(
1620                            event,
1621                            core::Event::Keyboard(_)
1622                                | core::Event::Touch(_)
1623                                | core::Event::Mouse(_)
1624                        )
1625                    {
1626                        _ = control_sender
1627                            .start_send(Control::ChangeFlow(ControlFlow::Wait));
1628                        continue;
1629                    }
1630                    runtime.broadcast(subscription::Event::Interaction {
1631                        window: id.unwrap_or(window::Id::NONE),
1632                        event,
1633                        status: core::event::Status::Ignored,
1634                    });
1635                }
1636
1637                debug.event_processing_finished();
1638
1639                if !messages.is_empty() || uis_stale {
1640                    let cached_interfaces: FxHashMap<
1641                        window::Id,
1642                        user_interface::Cache,
1643                    > = ManuallyDrop::into_inner(user_interfaces)
1644                        .drain()
1645                        .map(|(id, ui)| (id, ui.into_cache()))
1646                        .collect();
1647
1648                    update(
1649                        &mut program,
1650                        &mut runtime,
1651                        &mut debug,
1652                        &mut messages,
1653                    );
1654
1655                    for (id, window) in window_manager.iter_mut() {
1656                        window.state.synchronize(
1657                            &program,
1658                            id,
1659                            window.raw.as_ref(),
1660                        );
1661
1662                        window.request_redraw();
1663                    }
1664                    rebuild_a11y_tree = true;
1665
1666                    user_interfaces = ManuallyDrop::new(build_user_interfaces(
1667                        &program,
1668                        &mut debug,
1669                        &mut window_manager,
1670                        cached_interfaces,
1671                        &mut clipboard,
1672                    ));
1673
1674                    if actions > 0 {
1675                        proxy.free_slots(actions);
1676                        actions = 0;
1677                    }
1678                }
1679
1680                debug.draw_started();
1681
1682                for (id, window) in window_manager.iter_mut() {
1683                    // TODO: Avoid redrawing all the time by forcing widgets to
1684                    //  request redraws on state changes
1685                    //
1686                    // Then, we can use the `interface_state` here to decide if a redraw
1687                    // is needed right away, or simply wait until a specific time.
1688                    let redraw_event = core::Event::Window(
1689                        window::Event::RedrawRequested(Instant::now()),
1690                    );
1691
1692                    let cursor = window.state.cursor();
1693
1694                    let ui = user_interfaces
1695                        .get_mut(&id)
1696                        .expect("Get user interface");
1697
1698                    let (ui_state, _) = ui.update(
1699                        &[redraw_event.clone()],
1700                        cursor,
1701                        &mut window.renderer,
1702                        &mut clipboard,
1703                        &mut messages,
1704                    );
1705
1706                    let new_mouse_interaction = {
1707                        let state = &window.state;
1708
1709                        ui.draw(
1710                            &mut window.renderer,
1711                            state.theme(),
1712                            &renderer::Style {
1713                                icon_color: state.icon_color(),
1714                                text_color: state.text_color(),
1715                                scale_factor: state.scale_factor(),
1716                            },
1717                            cursor,
1718                        )
1719                    };
1720                    platform_specific_handler.clear_subsurface_list();
1721
1722                    if new_mouse_interaction != window.mouse_interaction {
1723                        if let Some(interaction) =
1724                            conversion::mouse_interaction(new_mouse_interaction)
1725                        {
1726                            if matches!(
1727                                window.mouse_interaction,
1728                                mouse::Interaction::Hide
1729                            ) {
1730                                window.raw.set_cursor_visible(true);
1731                            }
1732                            window.raw.set_cursor(interaction.into())
1733                        } else {
1734                            window.raw.set_cursor_visible(false);
1735                        }
1736
1737                        window.mouse_interaction = new_mouse_interaction;
1738                    }
1739
1740                    // TODO once widgets can request to be redrawn, we can avoid always requesting a
1741                    // redraw
1742                    window.request_redraw();
1743                    runtime.broadcast(subscription::Event::Interaction {
1744                        window: id,
1745                        event: redraw_event,
1746                        status: core::event::Status::Ignored,
1747                    });
1748
1749                    let _ = control_sender.start_send(Control::ChangeFlow(
1750                        match ui_state {
1751                            user_interface::State::Updated {
1752                                redraw_request: Some(redraw_request),
1753                            } => match redraw_request {
1754                                window::RedrawRequest::NextFrame => {
1755                                    window.request_redraw();
1756
1757                                    ControlFlow::Wait
1758                                }
1759                                window::RedrawRequest::At(at) => {
1760                                    ControlFlow::WaitUntil(at)
1761                                }
1762                            },
1763                            _ => ControlFlow::Wait,
1764                        },
1765                    ));
1766                }
1767
1768                debug.draw_finished();
1769            }
1770
1771            Event::Dnd(e) => {
1772                match &e {
1773                    dnd::DndEvent::Offer(_, dnd::OfferEvent::Leave) => {
1774                        events.push((cur_dnd_surface, core::Event::Dnd(e)));
1775                        // XXX can't clear the dnd surface on leave because
1776                        // the data event comes after
1777                        // cur_dnd_surface = None;
1778                    }
1779                    dnd::DndEvent::Offer(
1780                        _,
1781                        dnd::OfferEvent::Enter { surface, .. },
1782                    ) => {
1783                        let window_handle = surface.0.window_handle().ok();
1784                        let window_id = window_manager.iter_mut().find_map(
1785                            |(id, window)| {
1786                                if window
1787                                    .raw
1788                                    .window_handle()
1789                                    .ok()
1790                                    .zip(window_handle)
1791                                    .map(|(a, b)| a == b)
1792                                    .unwrap_or_default()
1793                                {
1794                                    Some(id)
1795                                } else {
1796                                    None
1797                                }
1798                            },
1799                        );
1800                        cur_dnd_surface = window_id;
1801                        events.push((cur_dnd_surface, core::Event::Dnd(e)));
1802                    }
1803                    dnd::DndEvent::Offer(..) => {
1804                        events.push((cur_dnd_surface, core::Event::Dnd(e)));
1805                    }
1806                    dnd::DndEvent::Source(evt) => {
1807                        match evt {
1808                            dnd::SourceEvent::Finished
1809                            | dnd::SourceEvent::Cancelled => {
1810                                dnd_surface = None;
1811                            }
1812                            _ => {}
1813                        }
1814                        for w in window_manager.ids() {
1815                            events.push((Some(w), core::Event::Dnd(e.clone())));
1816                        }
1817                    }
1818                };
1819            }
1820            #[cfg(feature = "a11y")]
1821            Event::Accessibility(id, e) => {
1822                rebuild_a11y_tree = true;
1823                match e.action {
1824                    iced_accessibility::accesskit::Action::Focus => {
1825                        // TODO send a command for this
1826                    }
1827                    _ => {}
1828                }
1829                events.push((Some(id), conversion::a11y(e)));
1830            }
1831            #[cfg(feature = "a11y")]
1832            Event::AccessibilityEnabled(enabled) => {
1833                a11y_enabled = enabled;
1834            }
1835            Event::PlatformSpecific(e) => {
1836                crate::platform_specific::handle_event(
1837                    e,
1838                    &mut events,
1839                    &mut platform_specific_handler,
1840                    &program,
1841                    &mut compositor,
1842                    &mut window_manager,
1843                    &mut debug,
1844                    &mut user_interfaces,
1845                    &mut clipboard,
1846                    #[cfg(feature = "a11y")]
1847                    &mut adapters,
1848                );
1849            }
1850            _ => {
1851                // log ignored events?
1852            }
1853        }
1854        #[cfg(feature = "a11y")]
1855        {
1856            use iced_accessibility::{
1857                accesskit::{NodeBuilder, NodeId, Role, Tree, TreeUpdate},
1858                A11yId, A11yNode, A11yTree,
1859            };
1860            if !a11y_enabled || !rebuild_a11y_tree {
1861                continue;
1862            }
1863
1864            for id in window_manager.ids() {
1865                let Some((a11y_id, adapter)) = adapters.get_mut(&id) else {
1866                    continue;
1867                };
1868                let Some(window) = window_manager.get(id) else {
1869                    continue;
1870                };
1871                let interface =
1872                    user_interfaces.get_mut(&id).expect("Get user interface");
1873
1874                // TODO cleanup duplication
1875                let child_tree = interface.a11y_nodes(window.state.cursor());
1876                let mut root = NodeBuilder::new(Role::Window);
1877                root.set_name(window.state.title.to_string());
1878                let window_tree = A11yTree::node_with_child_tree(
1879                    A11yNode::new(root, *a11y_id),
1880                    child_tree,
1881                );
1882                let tree = Tree::new(NodeId(*a11y_id));
1883
1884                let focus = Arc::new(std::sync::Mutex::new(None));
1885                let focus_clone = focus.clone();
1886                let operation: Box<dyn Operation<()>> =
1887                    Box::new(operation::map(
1888                        Box::new(operation::focusable::find_focused()),
1889                        move |id| {
1890                            let mut guard = focus.lock().unwrap();
1891                            _ = guard.replace(id);
1892                        },
1893                    ));
1894                let mut current_operation = Some(operation);
1895
1896                while let Some(mut operation) = current_operation.take() {
1897                    interface.operate(&window.renderer, operation.as_mut());
1898
1899                    match operation.finish() {
1900                        operation::Outcome::None => {}
1901                        operation::Outcome::Some(()) => {
1902                            break;
1903                        }
1904                        operation::Outcome::Chain(next) => {
1905                            current_operation = Some(next);
1906                        }
1907                    }
1908                }
1909                let mut guard = focus_clone.lock().unwrap();
1910                let focus = guard
1911                    .take()
1912                    .map(|id| A11yId::Widget(id))
1913                    .filter(|f_id| window_tree.contains(f_id));
1914                tracing::debug!(
1915                    "tree root: {:?}\nchildren: {:?}\nfocus: {:?}\n",
1916                    window_tree
1917                        .root()
1918                        .iter()
1919                        .map(|n| (n.node(), n.id()))
1920                        .collect::<Vec<_>>(),
1921                    window_tree
1922                        .children()
1923                        .iter()
1924                        .map(|n| (n.node(), n.id()))
1925                        .collect::<Vec<_>>(),
1926                    &focus,
1927                );
1928                let focus =
1929                    focus.map(|id| id.into()).unwrap_or_else(|| tree.root);
1930                adapter.update_if_active(|| TreeUpdate {
1931                    nodes: window_tree.into(),
1932                    tree: Some(tree),
1933                    focus,
1934                });
1935            }
1936        }
1937    }
1938
1939    let _ = ManuallyDrop::into_inner(user_interfaces);
1940}
1941
1942/// Builds a window's [`UserInterface`] for the [`Program`].
1943pub(crate) fn build_user_interface<'a, P: Program>(
1944    program: &'a P,
1945    cache: user_interface::Cache,
1946    renderer: &mut P::Renderer,
1947    size: Size,
1948    debug: &mut Debug,
1949    id: window::Id,
1950    raw: Arc<dyn winit::window::Window>,
1951    prev_dnd_destination_rectangles_count: usize,
1952    clipboard: &mut Clipboard,
1953) -> UserInterface<'a, P::Message, P::Theme, P::Renderer>
1954where
1955    P::Theme: DefaultStyle,
1956{
1957    debug.view_started();
1958    let view = program.view(id);
1959    debug.view_finished();
1960
1961    debug.layout_started();
1962    let user_interface = UserInterface::build(view, size, cache, renderer);
1963    debug.layout_finished();
1964
1965    let dnd_rectangles = user_interface
1966        .dnd_rectangles(prev_dnd_destination_rectangles_count, renderer);
1967    let new_dnd_rectangles_count = dnd_rectangles.as_ref().len();
1968    if new_dnd_rectangles_count > 0 || prev_dnd_destination_rectangles_count > 0
1969    {
1970        clipboard.register_dnd_destination(
1971            DndSurface(Arc::new(Box::new(raw.clone()))),
1972            dnd_rectangles.into_rectangles(),
1973        );
1974    }
1975
1976    user_interface
1977}
1978
1979fn update<P: Program, E: Executor>(
1980    program: &mut P,
1981    runtime: &mut Runtime<E, Proxy<P::Message>, Action<P::Message>>,
1982    debug: &mut Debug,
1983    messages: &mut Vec<P::Message>,
1984) where
1985    P::Theme: DefaultStyle,
1986{
1987    for message in messages.drain(..) {
1988        debug.log_message(&message);
1989        debug.update_started();
1990
1991        let task = runtime.enter(|| program.update(message));
1992        debug.update_finished();
1993
1994        if let Some(stream) = runtime::task::into_stream(task) {
1995            runtime.run(stream);
1996        }
1997    }
1998
1999    let subscription = runtime.enter(|| program.subscription());
2000    runtime.track(subscription::into_recipes(subscription.map(Action::Output)));
2001}
2002
2003fn run_action<P, C>(
2004    action: Action<P::Message>,
2005    program: &P,
2006    compositor: &mut C,
2007    events: &mut Vec<(Option<window::Id>, core::Event)>,
2008    messages: &mut Vec<P::Message>,
2009    clipboard: &mut Clipboard,
2010    control_sender: &mut mpsc::UnboundedSender<Control>,
2011    debug: &mut Debug,
2012    interfaces: &mut FxHashMap<
2013        window::Id,
2014        UserInterface<'_, P::Message, P::Theme, P::Renderer>,
2015    >,
2016    window_manager: &mut WindowManager<P, C>,
2017    ui_caches: &mut FxHashMap<window::Id, user_interface::Cache>,
2018    is_window_opening: &mut bool,
2019    platform_specific: &mut crate::platform_specific::PlatformSpecific,
2020) -> bool
2021where
2022    P: Program,
2023    C: Compositor<Renderer = P::Renderer> + 'static,
2024    P::Theme: DefaultStyle,
2025{
2026    use crate::runtime::clipboard;
2027    use crate::runtime::system;
2028    use crate::runtime::window;
2029
2030    match action {
2031        Action::Output(message) => {
2032            messages.push(message);
2033        }
2034        Action::Clipboard(action) => match action {
2035            clipboard::Action::Read { target, channel } => {
2036                let _ = channel.send(clipboard.read(target));
2037            }
2038            clipboard::Action::Write { target, contents } => {
2039                clipboard.write(target, contents);
2040            }
2041            clipboard::Action::WriteData(contents, kind) => {
2042                clipboard.write_data(kind, ClipboardStoreData(contents))
2043            }
2044            clipboard::Action::ReadData(allowed, tx, kind) => {
2045                let contents = clipboard.read_data(kind, allowed);
2046                _ = tx.send(contents);
2047            }
2048        },
2049        Action::Window(action) => match action {
2050            window::Action::Open(id, settings, channel) => {
2051                let monitor = window_manager.last_monitor();
2052
2053                control_sender
2054                    .start_send(Control::CreateWindow {
2055                        id,
2056                        settings,
2057                        title: program.title(id),
2058                        monitor,
2059                        on_open: channel,
2060                    })
2061                    .expect("Send control action");
2062
2063                *is_window_opening = true;
2064            }
2065            window::Action::Close(id) => {
2066                let _ = ui_caches.remove(&id);
2067                let _ = interfaces.remove(&id);
2068                #[cfg(feature = "wayland")]
2069                platform_specific
2070                    .send_wayland(platform_specific::Action::RemoveWindow(id));
2071
2072                if let Some(window) = window_manager.remove(id) {
2073                    clipboard.register_dnd_destination(
2074                        DndSurface(Arc::new(Box::new(window.raw.clone()))),
2075                        Vec::new(),
2076                    );
2077                    let proxy = clipboard.proxy();
2078                    if clipboard.window_id() == Some(window.raw.id()) {
2079                        *clipboard = window_manager
2080                            .first()
2081                            .map(|window| window.raw.clone())
2082                            .zip(proxy)
2083                            .map(|(w, proxy)| {
2084                                Clipboard::connect(
2085                                    w,
2086                                    crate::clipboard::ControlSender {
2087                                        sender: control_sender.clone(),
2088                                        proxy,
2089                                    },
2090                                )
2091                            })
2092                            .unwrap_or_else(Clipboard::unconnected);
2093                    }
2094
2095                    events.push((
2096                        Some(id),
2097                        core::Event::Window(core::window::Event::Closed),
2098                    ));
2099                }
2100            }
2101            window::Action::GetOldest(channel) => {
2102                let id =
2103                    window_manager.iter_mut().next().map(|(id, _window)| id);
2104
2105                let _ = channel.send(id);
2106            }
2107            window::Action::GetLatest(channel) => {
2108                let id =
2109                    window_manager.iter_mut().last().map(|(id, _window)| id);
2110
2111                let _ = channel.send(id);
2112            }
2113            window::Action::Drag(id) => {
2114                if let Some(window) = window_manager.get_mut(id) {
2115                    let _ = window.raw.drag_window();
2116                }
2117            }
2118            window::Action::Resize(id, size) => {
2119                if let Some(window) = window_manager.get_mut(id) {
2120                    let _ = window.raw.request_surface_size(
2121                        winit::dpi::LogicalSize {
2122                            width: size.width,
2123                            height: size.height,
2124                        }
2125                        .into(),
2126                    );
2127                }
2128            }
2129            window::Action::GetSize(id, channel) => {
2130                if let Some(window) = window_manager.get_mut(id) {
2131                    let size = window
2132                        .raw
2133                        .surface_size()
2134                        .to_logical(window.raw.scale_factor());
2135
2136                    let _ = channel.send(Size::new(size.width, size.height));
2137                }
2138            }
2139            window::Action::GetMaximized(id, channel) => {
2140                if let Some(window) = window_manager.get_mut(id) {
2141                    let _ = channel.send(window.raw.is_maximized());
2142                }
2143            }
2144            window::Action::Maximize(id, maximized) => {
2145                if let Some(window) = window_manager.get_mut(id) {
2146                    window.raw.set_maximized(maximized);
2147                }
2148            }
2149            window::Action::GetMinimized(id, channel) => {
2150                if let Some(window) = window_manager.get_mut(id) {
2151                    let _ = channel.send(window.raw.is_minimized());
2152                }
2153            }
2154            window::Action::Minimize(id, minimized) => {
2155                if let Some(window) = window_manager.get_mut(id) {
2156                    window.raw.set_minimized(minimized);
2157                }
2158            }
2159            window::Action::GetPosition(id, channel) => {
2160                if let Some(window) = window_manager.get(id) {
2161                    let position = window
2162                        .raw
2163                        .inner_position()
2164                        .map(|position| {
2165                            let position = position
2166                                .to_logical::<f32>(window.raw.scale_factor());
2167
2168                            Point::new(position.x, position.y)
2169                        })
2170                        .ok();
2171
2172                    let _ = channel.send(position);
2173                }
2174            }
2175            window::Action::GetScaleFactor(id, channel) => {
2176                if let Some(window) = window_manager.get_mut(id) {
2177                    let scale_factor = window.raw.scale_factor();
2178
2179                    let _ = channel.send(scale_factor as f32);
2180                }
2181            }
2182            window::Action::Move(id, position) => {
2183                if let Some(window) = window_manager.get_mut(id) {
2184                    window.raw.set_outer_position(
2185                        winit::dpi::LogicalPosition {
2186                            x: position.x,
2187                            y: position.y,
2188                        }
2189                        .into(),
2190                    );
2191                }
2192            }
2193            window::Action::ChangeMode(id, mode) => {
2194                if let Some(window) = window_manager.get_mut(id) {
2195                    window.raw.set_visible(conversion::visible(mode));
2196                    window.raw.set_fullscreen(conversion::fullscreen(
2197                        window.raw.current_monitor(),
2198                        mode,
2199                    ));
2200                }
2201            }
2202            window::Action::ChangeIcon(id, icon) => {
2203                if let Some(window) = window_manager.get_mut(id) {
2204                    window.raw.set_window_icon(conversion::icon(icon));
2205                }
2206            }
2207            window::Action::GetMode(id, channel) => {
2208                if let Some(window) = window_manager.get_mut(id) {
2209                    let mode = if window.raw.is_visible().unwrap_or(true) {
2210                        conversion::mode(window.raw.fullscreen())
2211                    } else {
2212                        core::window::Mode::Hidden
2213                    };
2214
2215                    let _ = channel.send(mode);
2216                }
2217            }
2218            window::Action::ToggleMaximize(id) => {
2219                if let Some(window) = window_manager.get_mut(id) {
2220                    window.raw.set_maximized(!window.raw.is_maximized());
2221                }
2222            }
2223            window::Action::ToggleDecorations(id) => {
2224                if let Some(window) = window_manager.get_mut(id) {
2225                    window.raw.set_decorations(!window.raw.is_decorated());
2226                }
2227            }
2228            window::Action::RequestUserAttention(id, attention_type) => {
2229                if let Some(window) = window_manager.get_mut(id) {
2230                    window.raw.request_user_attention(
2231                        attention_type.map(conversion::user_attention),
2232                    );
2233                }
2234            }
2235            window::Action::GainFocus(id) => {
2236                if let Some(window) = window_manager.get_mut(id) {
2237                    window.raw.focus_window();
2238                }
2239            }
2240            window::Action::ChangeLevel(id, level) => {
2241                if let Some(window) = window_manager.get_mut(id) {
2242                    window
2243                        .raw
2244                        .set_window_level(conversion::window_level(level));
2245                }
2246            }
2247            window::Action::ShowSystemMenu(id) => {
2248                if let Some(window) = window_manager.get_mut(id) {
2249                    if let mouse::Cursor::Available(point) =
2250                        window.state.cursor()
2251                    {
2252                        window.raw.show_window_menu(
2253                            winit::dpi::LogicalPosition {
2254                                x: point.x,
2255                                y: point.y,
2256                            }
2257                            .into(),
2258                        );
2259                    }
2260                }
2261            }
2262            window::Action::GetRawId(id, channel) => {
2263                if let Some(window) = window_manager.get_mut(id) {
2264                    let _ = channel.send(window.raw.id().into());
2265                }
2266            }
2267            window::Action::RunWithHandle(id, f) => {
2268                use window::raw_window_handle::HasWindowHandle;
2269
2270                if let Some(handle) = window_manager
2271                    .get_mut(id)
2272                    .and_then(|window| window.raw.window_handle().ok())
2273                {
2274                    f(handle);
2275                }
2276            }
2277            window::Action::Screenshot(id, channel) => {
2278                if let Some(window) = window_manager.get_mut(id) {
2279                    let bytes = compositor.screenshot(
2280                        &mut window.renderer,
2281                        window.state.viewport(),
2282                        window.state.background_color(),
2283                        &debug.overlay(),
2284                    );
2285
2286                    let _ = channel.send(window::Screenshot::new(
2287                        bytes,
2288                        window.state.physical_size(),
2289                        window.state.viewport().scale_factor(),
2290                    ));
2291                }
2292            }
2293            window::Action::EnableMousePassthrough(id) => {
2294                if let Some(window) = window_manager.get_mut(id) {
2295                    let _ = window.raw.set_cursor_hittest(false);
2296                }
2297            }
2298            window::Action::DisableMousePassthrough(id) => {
2299                if let Some(window) = window_manager.get_mut(id) {
2300                    let _ = window.raw.set_cursor_hittest(true);
2301                }
2302            }
2303            window::Action::EnableBlur(id) => {
2304                if let Some(window) = window_manager.get_mut(id) {
2305                    window.raw.set_blur(true);
2306                }
2307            }
2308            window::Action::DisableBlur(id) => {
2309                if let Some(window) = window_manager.get_mut(id) {
2310                    window.raw.set_blur(false);
2311                }
2312            }
2313        },
2314        Action::System(action) => match action {
2315            system::Action::QueryInformation(_channel) => {
2316                #[cfg(feature = "system")]
2317                {
2318                    let graphics_info = compositor.fetch_information();
2319
2320                    let _ = std::thread::spawn(move || {
2321                        let information =
2322                            crate::system::information(graphics_info);
2323
2324                        let _ = _channel.send(information);
2325                    });
2326                }
2327            }
2328        },
2329        Action::Widget(operation) => {
2330            let mut current_operation = Some(operation);
2331
2332            while let Some(mut operation) = current_operation.take() {
2333                for (id, ui) in interfaces.iter_mut() {
2334                    if let Some(window) = window_manager.get_mut(*id) {
2335                        ui.operate(&window.renderer, operation.as_mut());
2336                    }
2337                }
2338
2339                match operation.finish() {
2340                    operation::Outcome::None => {}
2341                    operation::Outcome::Some(()) => {}
2342                    operation::Outcome::Chain(next) => {
2343                        current_operation = Some(next);
2344                    }
2345                }
2346            }
2347        }
2348        Action::LoadFont { bytes, channel } => {
2349            // TODO: Error handling (?)
2350            compositor.load_font(bytes.clone());
2351
2352            let _ = channel.send(Ok(()));
2353        }
2354        Action::Exit => {
2355            control_sender
2356                .start_send(Control::Exit)
2357                .expect("Send control action");
2358            return true;
2359        }
2360        Action::Dnd(a) => match a {
2361            iced_runtime::dnd::DndAction::RegisterDndDestination {
2362                surface,
2363                rectangles,
2364            } => {
2365                clipboard.register_dnd_destination(surface, rectangles);
2366            }
2367            iced_runtime::dnd::DndAction::EndDnd => {
2368                clipboard.end_dnd();
2369            }
2370            iced_runtime::dnd::DndAction::PeekDnd(m, channel) => {
2371                let data = clipboard.peek_dnd(m);
2372                _ = channel.send(data);
2373            }
2374            iced_runtime::dnd::DndAction::SetAction(a) => {
2375                clipboard.set_action(a);
2376            }
2377        },
2378        Action::PlatformSpecific(a) => {
2379            platform_specific.send_action(a);
2380        }
2381    }
2382    false
2383}
2384
2385/// Build the user interface for every window.
2386pub fn build_user_interfaces<'a, P: Program, C>(
2387    program: &'a P,
2388    debug: &mut Debug,
2389    window_manager: &mut WindowManager<P, C>,
2390    mut cached_user_interfaces: FxHashMap<window::Id, user_interface::Cache>,
2391    clipboard: &mut Clipboard,
2392) -> FxHashMap<window::Id, UserInterface<'a, P::Message, P::Theme, P::Renderer>>
2393where
2394    C: Compositor<Renderer = P::Renderer>,
2395    P::Theme: DefaultStyle,
2396{
2397    cached_user_interfaces
2398        .drain()
2399        .filter_map(|(id, cache)| {
2400            let window = window_manager.get_mut(id)?;
2401            let interface = build_user_interface(
2402                program,
2403                cache,
2404                &mut window.renderer,
2405                window.state.logical_size(),
2406                debug,
2407                id,
2408                window.raw.clone(),
2409                window.prev_dnd_destination_rectangles_count,
2410                clipboard,
2411            );
2412
2413            let dnd_rectangles = interface.dnd_rectangles(
2414                window.prev_dnd_destination_rectangles_count,
2415                &window.renderer,
2416            );
2417            let new_dnd_rectangles_count = dnd_rectangles.as_ref().len();
2418            if new_dnd_rectangles_count > 0
2419                || window.prev_dnd_destination_rectangles_count > 0
2420            {
2421                clipboard.register_dnd_destination(
2422                    DndSurface(Arc::new(Box::new(window.raw.clone()))),
2423                    dnd_rectangles.into_rectangles(),
2424                );
2425            }
2426
2427            window.prev_dnd_destination_rectangles_count =
2428                new_dnd_rectangles_count;
2429
2430            Some((id, interface))
2431        })
2432        .collect()
2433}
2434
2435/// Returns true if the provided event should cause a [`Program`] to
2436/// exit.
2437pub fn user_force_quit(
2438    event: &winit::event::WindowEvent,
2439    _modifiers: winit::keyboard::ModifiersState,
2440) -> bool {
2441    match event {
2442        #[cfg(target_os = "macos")]
2443        winit::event::WindowEvent::KeyboardInput {
2444            event:
2445                winit::event::KeyEvent {
2446                    logical_key: winit::keyboard::Key::Character(c),
2447                    state: winit::event::ElementState::Pressed,
2448                    ..
2449                },
2450            ..
2451        } if c == "q" && _modifiers.super_key() => true,
2452        _ => false,
2453    }
2454}