1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2#![forbid(unsafe_code)]
3#![doc(
4 html_logo_url = "https://bevyengine.org/assets/icon.png",
5 html_favicon_url = "https://bevyengine.org/assets/icon.png"
6)]
7
8extern crate alloc;
16
17use bevy_derive::Deref;
18use bevy_reflect::prelude::ReflectDefault;
19use bevy_reflect::Reflect;
20use bevy_window::{RawHandleWrapperHolder, WindowEvent};
21use core::marker::PhantomData;
22use winit::{event_loop::EventLoop, window::WindowId};
23
24use bevy_a11y::AccessibilityRequested;
25use bevy_app::{App, Last, Plugin};
26use bevy_ecs::prelude::*;
27use bevy_window::{exit_on_all_closed, Window, WindowCreated};
28use system::{changed_windows, check_keyboard_focus_lost, despawn_windows};
29pub use system::{create_monitors, create_windows};
30#[cfg(all(target_family = "wasm", target_os = "unknown"))]
31pub use winit::platform::web::CustomCursorExtWebSys;
32pub use winit::{
33 event_loop::EventLoopProxy,
34 window::{CustomCursor as WinitCustomCursor, CustomCursorSource},
35};
36pub use winit_config::*;
37pub use winit_windows::*;
38
39use crate::{
40 accessibility::{AccessKitAdapters, AccessKitPlugin, WinitActionRequestHandlers},
41 state::winit_runner,
42 winit_monitors::WinitMonitors,
43};
44
45pub mod accessibility;
46mod converters;
47pub mod cursor;
48#[cfg(feature = "custom_cursor")]
49mod custom_cursor;
50mod state;
51mod system;
52mod winit_config;
53mod winit_monitors;
54mod winit_windows;
55
56#[derive(Default)]
69pub struct WinitPlugin<T: Event = WakeUp> {
70 pub run_on_any_thread: bool,
80 marker: PhantomData<T>,
81}
82
83impl<T: Event> Plugin for WinitPlugin<T> {
84 fn name(&self) -> &str {
85 "bevy_winit::WinitPlugin"
86 }
87
88 fn build(&self, app: &mut App) {
89 let mut event_loop_builder = EventLoop::<T>::with_user_event();
90
91 #[cfg(all(target_os = "linux", feature = "x11"))]
93 {
94 use winit::platform::x11::EventLoopBuilderExtX11;
95
96 event_loop_builder.with_any_thread(self.run_on_any_thread);
101 }
102
103 #[cfg(all(target_os = "linux", feature = "wayland"))]
105 {
106 use winit::platform::wayland::EventLoopBuilderExtWayland;
107 event_loop_builder.with_any_thread(self.run_on_any_thread);
108 }
109
110 #[cfg(target_os = "windows")]
111 {
112 use winit::platform::windows::EventLoopBuilderExtWindows;
113 event_loop_builder.with_any_thread(self.run_on_any_thread);
114 }
115
116 #[cfg(target_os = "android")]
117 {
118 use winit::platform::android::EventLoopBuilderExtAndroid;
119 let msg = "Bevy must be setup with the #[bevy_main] macro on Android";
120 event_loop_builder.with_android_app(bevy_window::ANDROID_APP.get().expect(msg).clone());
121 }
122
123 let event_loop = event_loop_builder
124 .build()
125 .expect("Failed to build event loop");
126
127 app.init_non_send_resource::<WinitWindows>()
128 .init_resource::<WinitMonitors>()
129 .init_resource::<WinitSettings>()
130 .insert_resource(DisplayHandleWrapper(event_loop.owned_display_handle()))
131 .add_event::<RawWinitWindowEvent>()
132 .set_runner(|app| winit_runner(app, event_loop))
133 .add_systems(
134 Last,
135 (
136 changed_windows.ambiguous_with(exit_on_all_closed),
139 despawn_windows,
140 check_keyboard_focus_lost,
141 )
142 .chain(),
143 );
144
145 app.add_plugins(AccessKitPlugin);
146 app.add_plugins(cursor::CursorPlugin);
147 }
148}
149
150#[derive(Debug, Default, Clone, Copy, Event, Reflect)]
153#[reflect(Debug, Default, Clone)]
154pub struct WakeUp;
155
156#[derive(Debug, Clone, Event)]
164pub struct RawWinitWindowEvent {
165 pub window_id: WindowId,
167 pub event: winit::event::WindowEvent,
169}
170
171#[derive(Resource, Deref)]
178pub struct EventLoopProxyWrapper<T: 'static>(EventLoopProxy<T>);
179
180#[derive(Resource, Deref)]
187pub struct DisplayHandleWrapper(pub winit::event_loop::OwnedDisplayHandle);
188
189trait AppSendEvent {
190 fn send(&mut self, event: impl Into<WindowEvent>);
191}
192
193impl AppSendEvent for Vec<WindowEvent> {
194 fn send(&mut self, event: impl Into<WindowEvent>) {
195 self.push(Into::<WindowEvent>::into(event));
196 }
197}
198
199pub type CreateWindowParams<'w, 's, F = ()> = (
201 Commands<'w, 's>,
202 Query<
203 'w,
204 's,
205 (
206 Entity,
207 &'static mut Window,
208 Option<&'static RawHandleWrapperHolder>,
209 ),
210 F,
211 >,
212 EventWriter<'w, WindowCreated>,
213 NonSendMut<'w, WinitWindows>,
214 NonSendMut<'w, AccessKitAdapters>,
215 ResMut<'w, WinitActionRequestHandlers>,
216 Res<'w, AccessibilityRequested>,
217 Res<'w, WinitMonitors>,
218);
219
220pub type CreateMonitorParams<'w, 's> = (Commands<'w, 's>, ResMut<'w, WinitMonitors>);