pub struct Window { /* private fields */ }Expand description
Represents a window.
The window is closed when dropped.
§Threading
This is Send + Sync, meaning that it can be freely used from other
threads.
However, some platforms (macOS, Web and iOS) only allow user interface interactions on the main thread, so on those platforms, if you use the window from a thread other than the main, the code is scheduled to run on the main thread, and your thread may be blocked until that completes.
§Platform-specific
Web: The Window, which is represented by a HTMLElementCanvas, can
not be closed by dropping the Window.
Implementations§
Source§impl Window
Base Window functions.
impl Window
Base Window functions.
Sourcepub fn default_attributes() -> WindowAttributes
pub fn default_attributes() -> WindowAttributes
Create a new WindowAttributes which allows modifying the window’s attributes before
creation.
Examples found in repository?
More examples
3fn main() -> Result<(), impl std::error::Error> {
4 use std::collections::HashMap;
5
6 use rio_winit_fork::dpi::{LogicalPosition, LogicalSize, Position};
7 use rio_winit_fork::event::{ElementState, Event, KeyEvent, WindowEvent};
8 use rio_winit_fork::event_loop::{ActiveEventLoop, EventLoop};
9 use rio_winit_fork::raw_window_handle::HasRawWindowHandle;
10 use rio_winit_fork::window::Window;
11
12 #[path = "util/fill.rs"]
13 mod fill;
14
15 fn spawn_child_window(parent: &Window, event_loop: &ActiveEventLoop) -> Window {
16 let parent = parent.raw_window_handle().unwrap();
17 let mut window_attributes = Window::default_attributes()
18 .with_title("child window")
19 .with_inner_size(LogicalSize::new(200.0f32, 200.0f32))
20 .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
21 .with_visible(true);
22 // `with_parent_window` is unsafe. Parent window must be a valid window.
23 window_attributes = unsafe { window_attributes.with_parent_window(Some(parent)) };
24
25 event_loop.create_window(window_attributes).unwrap()
26 }
27
28 let mut windows = HashMap::new();
29
30 let event_loop: EventLoop<()> = EventLoop::new().unwrap();
31 let mut parent_window_id = None;
32
33 event_loop.run(move |event: Event<()>, event_loop| {
34 match event {
35 Event::Resumed => {
36 let attributes = Window::default_attributes()
37 .with_title("parent window")
38 .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
39 .with_inner_size(LogicalSize::new(640.0f32, 480.0f32));
40 let window = event_loop.create_window(attributes).unwrap();
41
42 parent_window_id = Some(window.id());
43
44 println!("Parent window id: {parent_window_id:?})");
45 windows.insert(window.id(), window);
46 },
47 Event::WindowEvent { window_id, event } => match event {
48 WindowEvent::CloseRequested => {
49 windows.clear();
50 event_loop.exit();
51 },
52 WindowEvent::CursorEntered { device_id: _ } => {
53 // On x11, println when the cursor entered in a window even if the child window
54 // is created by some key inputs.
55 // the child windows are always placed at (0, 0) with size (200, 200) in the
56 // parent window, so we also can see this log when we move
57 // the cursor around (200, 200) in parent window.
58 println!("cursor entered in the window {window_id:?}");
59 },
60 WindowEvent::KeyboardInput {
61 event: KeyEvent { state: ElementState::Pressed, .. },
62 ..
63 } => {
64 let parent_window = windows.get(&parent_window_id.unwrap()).unwrap();
65 let child_window = spawn_child_window(parent_window, event_loop);
66 let child_id = child_window.id();
67 println!("Child window created with id: {child_id:?}");
68 windows.insert(child_id, child_window);
69 },
70 WindowEvent::RedrawRequested => {
71 if let Some(window) = windows.get(&window_id) {
72 fill::fill_window(window);
73 }
74 },
75 _ => (),
76 },
77 _ => (),
78 }
79 })
80}123 fn create_window(
124 &mut self,
125 event_loop: &ActiveEventLoop,
126 _tab_id: Option<String>,
127 ) -> Result<WindowId, Box<dyn Error>> {
128 // TODO read-out activation token.
129
130 #[allow(unused_mut)]
131 let mut window_attributes = Window::default_attributes()
132 .with_title("Winit window")
133 .with_transparent(true)
134 .with_window_icon(Some(self.icon.clone()));
135
136 #[cfg(any(x11_platform, wayland_platform))]
137 if let Some(token) = event_loop.read_token_from_env() {
138 startup_notify::reset_activation_token_env();
139 info!("Using token {:?} to activate a window", token);
140 window_attributes = window_attributes.with_activation_token(token);
141 }
142
143 #[cfg(macos_platform)]
144 if let Some(tab_id) = _tab_id {
145 window_attributes = window_attributes.with_tabbing_identifier(&tab_id);
146 }
147
148 #[cfg(web_platform)]
149 {
150 use rio_winit_fork::platform::web::WindowAttributesExtWebSys;
151 window_attributes = window_attributes.with_append(true);
152 }
153
154 let window = event_loop.create_window(window_attributes)?;
155
156 #[cfg(ios_platform)]
157 {
158 use rio_winit_fork::platform::ios::WindowExtIOS;
159 window.recognize_doubletap_gesture(true);
160 window.recognize_pinch_gesture(true);
161 window.recognize_rotation_gesture(true);
162 window.recognize_pan_gesture(true, 2, 2);
163 }
164
165 let window_state = WindowState::new(self, window)?;
166 let window_id = window_state.window.id();
167 info!("Created new window with id={window_id:?}");
168 self.windows.insert(window_id, window_state);
169 Ok(window_id)
170 }Sourcepub fn id(&self) -> WindowId
pub fn id(&self) -> WindowId
Returns an identifier unique to the window.
Examples found in repository?
More examples
54 fn create_surface(
55 &mut self,
56 window: &Window,
57 ) -> &mut Surface<&'static Window, &'static Window> {
58 self.surfaces.entry(window.id()).or_insert_with(|| {
59 Surface::new(&self.context.borrow(), unsafe {
60 mem::transmute::<&'_ Window, &'static Window>(window)
61 })
62 .expect("Failed to create a softbuffer surface")
63 })
64 }
65
66 fn destroy_surface(&mut self, window: &Window) {
67 self.surfaces.remove(&window.id());
68 }123 fn create_window(
124 &mut self,
125 event_loop: &ActiveEventLoop,
126 _tab_id: Option<String>,
127 ) -> Result<WindowId, Box<dyn Error>> {
128 // TODO read-out activation token.
129
130 #[allow(unused_mut)]
131 let mut window_attributes = Window::default_attributes()
132 .with_title("Winit window")
133 .with_transparent(true)
134 .with_window_icon(Some(self.icon.clone()));
135
136 #[cfg(any(x11_platform, wayland_platform))]
137 if let Some(token) = event_loop.read_token_from_env() {
138 startup_notify::reset_activation_token_env();
139 info!("Using token {:?} to activate a window", token);
140 window_attributes = window_attributes.with_activation_token(token);
141 }
142
143 #[cfg(macos_platform)]
144 if let Some(tab_id) = _tab_id {
145 window_attributes = window_attributes.with_tabbing_identifier(&tab_id);
146 }
147
148 #[cfg(web_platform)]
149 {
150 use rio_winit_fork::platform::web::WindowAttributesExtWebSys;
151 window_attributes = window_attributes.with_append(true);
152 }
153
154 let window = event_loop.create_window(window_attributes)?;
155
156 #[cfg(ios_platform)]
157 {
158 use rio_winit_fork::platform::ios::WindowExtIOS;
159 window.recognize_doubletap_gesture(true);
160 window.recognize_pinch_gesture(true);
161 window.recognize_rotation_gesture(true);
162 window.recognize_pan_gesture(true, 2, 2);
163 }
164
165 let window_state = WindowState::new(self, window)?;
166 let window_id = window_state.window.id();
167 info!("Created new window with id={window_id:?}");
168 self.windows.insert(window_id, window_state);
169 Ok(window_id)
170 }
171
172 fn handle_action(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, action: Action) {
173 // let cursor_position = self.cursor_position;
174 let window = self.windows.get_mut(&window_id).unwrap();
175 info!("Executing action: {action:?}");
176 match action {
177 Action::CloseWindow => {
178 let _ = self.windows.remove(&window_id);
179 },
180 Action::CreateNewWindow => {
181 #[cfg(any(x11_platform, wayland_platform))]
182 if let Err(err) = window.window.request_activation_token() {
183 info!("Failed to get activation token: {err}");
184 } else {
185 return;
186 }
187
188 if let Err(err) = self.create_window(event_loop, None) {
189 error!("Error creating new window: {err}");
190 }
191 },
192 Action::ToggleResizeIncrements => window.toggle_resize_increments(),
193 Action::ToggleCursorVisibility => window.toggle_cursor_visibility(),
194 Action::ToggleResizable => window.toggle_resizable(),
195 Action::ToggleDecorations => window.toggle_decorations(),
196 Action::ToggleFullscreen => window.toggle_fullscreen(),
197 Action::ToggleMaximize => window.toggle_maximize(),
198 Action::ToggleImeInput => window.toggle_ime(),
199 Action::Minimize => window.minimize(),
200 Action::NextCursor => window.next_cursor(),
201 Action::NextCustomCursor => window.next_custom_cursor(&self.custom_cursors),
202 #[cfg(web_platform)]
203 Action::UrlCustomCursor => window.url_custom_cursor(event_loop),
204 #[cfg(web_platform)]
205 Action::AnimationCustomCursor => {
206 window.animation_custom_cursor(event_loop, &self.custom_cursors)
207 },
208 Action::CycleCursorGrab => window.cycle_cursor_grab(),
209 Action::DragWindow => window.drag_window(),
210 Action::DragResizeWindow => window.drag_resize_window(),
211 Action::ShowWindowMenu => window.show_menu(),
212 Action::PrintHelp => self.print_help(),
213 #[cfg(macos_platform)]
214 Action::CycleOptionAsAlt => window.cycle_option_as_alt(),
215 #[cfg(macos_platform)]
216 Action::CreateNewTab => {
217 let tab_id = window.window.tabbing_identifier();
218 if let Err(err) = self.create_window(event_loop, Some(tab_id)) {
219 error!("Error creating new window: {err}");
220 }
221 },
222 Action::RequestResize => window.swap_dimensions(),
223 }
224 }
225
226 fn dump_monitors(&self, event_loop: &ActiveEventLoop) {
227 info!("Monitors information");
228 let primary_monitor = event_loop.primary_monitor();
229 for monitor in event_loop.available_monitors() {
230 let intro = if primary_monitor.as_ref() == Some(&monitor) {
231 "Primary monitor"
232 } else {
233 "Monitor"
234 };
235
236 if let Some(name) = monitor.name() {
237 info!("{intro}: {name}");
238 } else {
239 info!("{intro}: [no name]");
240 }
241
242 let PhysicalSize { width, height } = monitor.size();
243 info!(
244 " Current mode: {width}x{height}{}",
245 if let Some(m_hz) = monitor.refresh_rate_millihertz() {
246 format!(" @ {}.{} Hz", m_hz / 1000, m_hz % 1000)
247 } else {
248 String::new()
249 }
250 );
251
252 let PhysicalPosition { x, y } = monitor.position();
253 info!(" Position: {x},{y}");
254
255 info!(" Scale factor: {}", monitor.scale_factor());
256
257 info!(" Available modes (width x height x bit-depth):");
258 for mode in monitor.video_modes() {
259 let PhysicalSize { width, height } = mode.size();
260 let bits = mode.bit_depth();
261 let m_hz = mode.refresh_rate_millihertz();
262 info!(" {width}x{height}x{bits} @ {}.{} Hz", m_hz / 1000, m_hz % 1000);
263 }
264 }
265 }
266
267 /// Process the key binding.
268 fn process_key_binding(key: &str, mods: &ModifiersState) -> Option<Action> {
269 KEY_BINDINGS
270 .iter()
271 .find_map(|binding| binding.is_triggered_by(&key, mods).then_some(binding.action))
272 }
273
274 /// Process mouse binding.
275 fn process_mouse_binding(button: MouseButton, mods: &ModifiersState) -> Option<Action> {
276 MOUSE_BINDINGS
277 .iter()
278 .find_map(|binding| binding.is_triggered_by(&button, mods).then_some(binding.action))
279 }
280
281 fn print_help(&self) {
282 info!("Keyboard bindings:");
283 for binding in KEY_BINDINGS {
284 info!(
285 "{}{:<10} - {} ({})",
286 modifiers_to_string(binding.mods),
287 binding.trigger,
288 binding.action,
289 binding.action.help(),
290 );
291 }
292 info!("Mouse bindings:");
293 for binding in MOUSE_BINDINGS {
294 info!(
295 "{}{:<10} - {} ({})",
296 modifiers_to_string(binding.mods),
297 mouse_button_to_string(binding.trigger),
298 binding.action,
299 binding.action.help(),
300 );
301 }
302 }
303}
304
305impl ApplicationHandler<UserEvent> for Application {
306 fn user_event(&mut self, _event_loop: &ActiveEventLoop, event: UserEvent) {
307 info!("User event: {event:?}");
308 }
309
310 fn window_event(
311 &mut self,
312 event_loop: &ActiveEventLoop,
313 window_id: WindowId,
314 event: WindowEvent,
315 ) {
316 let window = match self.windows.get_mut(&window_id) {
317 Some(window) => window,
318 None => return,
319 };
320
321 match event {
322 WindowEvent::Resized(size) => {
323 window.resize(size);
324 },
325 WindowEvent::Focused(focused) => {
326 if focused {
327 info!("Window={window_id:?} focused");
328 } else {
329 info!("Window={window_id:?} unfocused");
330 }
331 },
332 WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
333 info!("Window={window_id:?} changed scale to {scale_factor}");
334 },
335 WindowEvent::ThemeChanged(theme) => {
336 info!("Theme changed to {theme:?}");
337 window.set_theme(theme);
338 },
339 WindowEvent::RedrawRequested => {
340 if let Err(err) = window.draw() {
341 error!("Error drawing window: {err}");
342 }
343 },
344 WindowEvent::Occluded(occluded) => {
345 window.set_occluded(occluded);
346 },
347 WindowEvent::CloseRequested => {
348 info!("Closing Window={window_id:?}");
349 self.windows.remove(&window_id);
350 },
351 WindowEvent::ModifiersChanged(modifiers) => {
352 window.modifiers = modifiers.state();
353 info!("Modifiers changed to {:?}", window.modifiers);
354 },
355 WindowEvent::MouseWheel { delta, .. } => match delta {
356 MouseScrollDelta::LineDelta(x, y) => {
357 info!("Mouse wheel Line Delta: ({x},{y})");
358 },
359 MouseScrollDelta::PixelDelta(px) => {
360 info!("Mouse wheel Pixel Delta: ({},{})", px.x, px.y);
361 },
362 },
363 WindowEvent::KeyboardInput { event, is_synthetic: false, .. } => {
364 let mods = window.modifiers;
365
366 // Dispatch actions only on press.
367 if event.state.is_pressed() {
368 let action = if let Key::Character(ch) = event.logical_key.as_ref() {
369 Self::process_key_binding(&ch.to_uppercase(), &mods)
370 } else {
371 None
372 };
373
374 if let Some(action) = action {
375 self.handle_action(event_loop, window_id, action);
376 }
377 }
378 },
379 WindowEvent::MouseInput { button, state, .. } => {
380 let mods = window.modifiers;
381 if let Some(action) =
382 state.is_pressed().then(|| Self::process_mouse_binding(button, &mods)).flatten()
383 {
384 self.handle_action(event_loop, window_id, action);
385 }
386 },
387 WindowEvent::CursorLeft { .. } => {
388 info!("Cursor left Window={window_id:?}");
389 window.cursor_left();
390 },
391 WindowEvent::CursorMoved { position, .. } => {
392 info!("Moved cursor to {position:?}");
393 window.cursor_moved(position);
394 },
395 WindowEvent::ActivationTokenDone { token: _token, .. } => {
396 #[cfg(any(x11_platform, wayland_platform))]
397 {
398 startup_notify::set_activation_token_env(_token);
399 if let Err(err) = self.create_window(event_loop, None) {
400 error!("Error creating new window: {err}");
401 }
402 }
403 },
404 WindowEvent::Ime(event) => match event {
405 Ime::Enabled => info!("IME enabled for Window={window_id:?}"),
406 Ime::Preedit(text, caret_pos) => {
407 info!("Preedit: {}, with caret at {:?}", text, caret_pos);
408 },
409 Ime::Commit(text) => {
410 info!("Committed: {}", text);
411 },
412 Ime::Disabled => info!("IME disabled for Window={window_id:?}"),
413 },
414 WindowEvent::PinchGesture { delta, .. } => {
415 window.zoom += delta;
416 let zoom = window.zoom;
417 if delta > 0.0 {
418 info!("Zoomed in {delta:.5} (now: {zoom:.5})");
419 } else {
420 info!("Zoomed out {delta:.5} (now: {zoom:.5})");
421 }
422 },
423 WindowEvent::RotationGesture { delta, .. } => {
424 window.rotated += delta;
425 let rotated = window.rotated;
426 if delta > 0.0 {
427 info!("Rotated counterclockwise {delta:.5} (now: {rotated:.5})");
428 } else {
429 info!("Rotated clockwise {delta:.5} (now: {rotated:.5})");
430 }
431 },
432 WindowEvent::PanGesture { delta, phase, .. } => {
433 window.panned.x += delta.x;
434 window.panned.y += delta.y;
435 info!("Panned ({delta:?})) (now: {:?}), {phase:?}", window.panned);
436 },
437 WindowEvent::DoubleTapGesture { .. } => {
438 info!("Smart zoom");
439 },
440 WindowEvent::TouchpadPressure { .. }
441 | WindowEvent::HoveredFileCancelled
442 | WindowEvent::KeyboardInput { .. }
443 | WindowEvent::CursorEntered { .. }
444 | WindowEvent::AxisMotion { .. }
445 | WindowEvent::DroppedFile(_)
446 | WindowEvent::HoveredFile(_)
447 | WindowEvent::Destroyed
448 | WindowEvent::Touch(_)
449 | WindowEvent::Moved(_) => (),
450 }
451 }
452
453 fn device_event(
454 &mut self,
455 _event_loop: &ActiveEventLoop,
456 device_id: DeviceId,
457 event: DeviceEvent,
458 ) {
459 info!("Device {device_id:?} event: {event:?}");
460 }
461
462 fn resumed(&mut self, event_loop: &ActiveEventLoop) {
463 info!("Resumed the event loop");
464 self.dump_monitors(event_loop);
465
466 // Create initial window.
467 self.create_window(event_loop, None).expect("failed to create initial window");
468
469 self.print_help();
470 }
471
472 fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
473 if self.windows.is_empty() {
474 info!("No windows left, exiting...");
475 event_loop.exit();
476 }
477 }
478
479 #[cfg(not(any(android_platform, ios_platform)))]
480 fn exiting(&mut self, _event_loop: &ActiveEventLoop) {
481 // We must drop the context here.
482 self.context = None;
483 }
484}
485
486/// State of the window.
487struct WindowState {
488 /// IME input.
489 ime: bool,
490 /// Render surface.
491 ///
492 /// NOTE: This surface must be dropped before the `Window`.
493 #[cfg(not(any(android_platform, ios_platform)))]
494 surface: Surface<DisplayHandle<'static>, Arc<Window>>,
495 /// The actual winit Window.
496 window: Arc<Window>,
497 /// The window theme we're drawing with.
498 theme: Theme,
499 /// Cursor position over the window.
500 cursor_position: Option<PhysicalPosition<f64>>,
501 /// Window modifiers state.
502 modifiers: ModifiersState,
503 /// Occlusion state of the window.
504 occluded: bool,
505 /// Current cursor grab mode.
506 cursor_grab: CursorGrabMode,
507 /// The amount of zoom into window.
508 zoom: f64,
509 /// The amount of rotation of the window.
510 rotated: f32,
511 /// The amount of pan of the window.
512 panned: PhysicalPosition<f32>,
513
514 #[cfg(macos_platform)]
515 option_as_alt: OptionAsAlt,
516
517 // Cursor states.
518 named_idx: usize,
519 custom_idx: usize,
520 cursor_hidden: bool,
521}
522
523impl WindowState {
524 fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
525 let window = Arc::new(window);
526
527 // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
528 // it doesn't outlive it.
529 #[cfg(not(any(android_platform, ios_platform)))]
530 let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
531
532 let theme = window.theme().unwrap_or(Theme::Dark);
533 info!("Theme: {theme:?}");
534 let named_idx = 0;
535 window.set_cursor(CURSORS[named_idx]);
536
537 // Allow IME out of the box.
538 let ime = true;
539 window.set_ime_allowed(ime);
540
541 let size = window.inner_size();
542 let mut state = Self {
543 #[cfg(macos_platform)]
544 option_as_alt: window.option_as_alt(),
545 custom_idx: app.custom_cursors.len() - 1,
546 cursor_grab: CursorGrabMode::None,
547 named_idx,
548 #[cfg(not(any(android_platform, ios_platform)))]
549 surface,
550 window,
551 theme,
552 ime,
553 cursor_position: Default::default(),
554 cursor_hidden: Default::default(),
555 modifiers: Default::default(),
556 occluded: Default::default(),
557 rotated: Default::default(),
558 panned: Default::default(),
559 zoom: Default::default(),
560 };
561
562 state.resize(size);
563 Ok(state)
564 }
565
566 pub fn toggle_ime(&mut self) {
567 self.ime = !self.ime;
568 self.window.set_ime_allowed(self.ime);
569 if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
570 self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
571 }
572 }
573
574 pub fn minimize(&mut self) {
575 self.window.set_minimized(true);
576 }
577
578 pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) {
579 self.cursor_position = Some(position);
580 if self.ime {
581 self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
582 }
583 }
584
585 pub fn cursor_left(&mut self) {
586 self.cursor_position = None;
587 }
588
589 /// Toggle maximized.
590 fn toggle_maximize(&self) {
591 let maximized = self.window.is_maximized();
592 self.window.set_maximized(!maximized);
593 }
594
595 /// Toggle window decorations.
596 fn toggle_decorations(&self) {
597 let decorated = self.window.is_decorated();
598 self.window.set_decorations(!decorated);
599 }
600
601 /// Toggle window resizable state.
602 fn toggle_resizable(&self) {
603 let resizable = self.window.is_resizable();
604 self.window.set_resizable(!resizable);
605 }
606
607 /// Toggle cursor visibility
608 fn toggle_cursor_visibility(&mut self) {
609 self.cursor_hidden = !self.cursor_hidden;
610 self.window.set_cursor_visible(!self.cursor_hidden);
611 }
612
613 /// Toggle resize increments on a window.
614 fn toggle_resize_increments(&mut self) {
615 let new_increments = match self.window.resize_increments() {
616 Some(_) => None,
617 None => Some(LogicalSize::new(25.0, 25.0)),
618 };
619 info!("Had increments: {}", new_increments.is_none());
620 self.window.set_resize_increments(new_increments);
621 }
622
623 /// Toggle fullscreen.
624 fn toggle_fullscreen(&self) {
625 let fullscreen = if self.window.fullscreen().is_some() {
626 None
627 } else {
628 Some(Fullscreen::Borderless(None))
629 };
630
631 self.window.set_fullscreen(fullscreen);
632 }
633
634 /// Cycle through the grab modes ignoring errors.
635 fn cycle_cursor_grab(&mut self) {
636 self.cursor_grab = match self.cursor_grab {
637 CursorGrabMode::None => CursorGrabMode::Confined,
638 CursorGrabMode::Confined => CursorGrabMode::Locked,
639 CursorGrabMode::Locked => CursorGrabMode::None,
640 };
641 info!("Changing cursor grab mode to {:?}", self.cursor_grab);
642 if let Err(err) = self.window.set_cursor_grab(self.cursor_grab) {
643 error!("Error setting cursor grab: {err}");
644 }
645 }
646
647 #[cfg(macos_platform)]
648 fn cycle_option_as_alt(&mut self) {
649 self.option_as_alt = match self.option_as_alt {
650 OptionAsAlt::None => OptionAsAlt::OnlyLeft,
651 OptionAsAlt::OnlyLeft => OptionAsAlt::OnlyRight,
652 OptionAsAlt::OnlyRight => OptionAsAlt::Both,
653 OptionAsAlt::Both => OptionAsAlt::None,
654 };
655 info!("Setting option as alt {:?}", self.option_as_alt);
656 self.window.set_option_as_alt(self.option_as_alt);
657 }
658
659 /// Swap the window dimensions with `request_inner_size`.
660 fn swap_dimensions(&mut self) {
661 let old_inner_size = self.window.inner_size();
662 let mut inner_size = old_inner_size;
663
664 mem::swap(&mut inner_size.width, &mut inner_size.height);
665 info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
666
667 if let Some(new_inner_size) = self.window.request_inner_size(inner_size) {
668 if old_inner_size == new_inner_size {
669 info!("Inner size change got ignored");
670 } else {
671 self.resize(new_inner_size);
672 }
673 } else {
674 info!("Request inner size is asynchronous");
675 }
676 }
677
678 /// Pick the next cursor.
679 fn next_cursor(&mut self) {
680 self.named_idx = (self.named_idx + 1) % CURSORS.len();
681 info!("Setting cursor to \"{:?}\"", CURSORS[self.named_idx]);
682 self.window.set_cursor(Cursor::Icon(CURSORS[self.named_idx]));
683 }
684
685 /// Pick the next custom cursor.
686 fn next_custom_cursor(&mut self, custom_cursors: &[CustomCursor]) {
687 self.custom_idx = (self.custom_idx + 1) % custom_cursors.len();
688 let cursor = Cursor::Custom(custom_cursors[self.custom_idx].clone());
689 self.window.set_cursor(cursor);
690 }
691
692 /// Custom cursor from an URL.
693 #[cfg(web_platform)]
694 fn url_custom_cursor(&mut self, event_loop: &ActiveEventLoop) {
695 let cursor = event_loop.create_custom_cursor(url_custom_cursor());
696
697 self.window.set_cursor(cursor);
698 }
699
700 /// Custom cursor from a URL.
701 #[cfg(web_platform)]
702 fn animation_custom_cursor(
703 &mut self,
704 event_loop: &ActiveEventLoop,
705 custom_cursors: &[CustomCursor],
706 ) {
707 use std::time::Duration;
708 use rio_winit_fork::platform::web::CustomCursorExtWebSys;
709
710 let cursors = vec![
711 custom_cursors[0].clone(),
712 custom_cursors[1].clone(),
713 event_loop.create_custom_cursor(url_custom_cursor()),
714 ];
715 let cursor = CustomCursor::from_animation(Duration::from_secs(3), cursors).unwrap();
716 let cursor = event_loop.create_custom_cursor(cursor);
717
718 self.window.set_cursor(cursor);
719 }
720
721 /// Resize the window to the new size.
722 fn resize(&mut self, size: PhysicalSize<u32>) {
723 info!("Resized to {size:?}");
724 #[cfg(not(any(android_platform, ios_platform)))]
725 {
726 let (width, height) = match (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
727 {
728 (Some(width), Some(height)) => (width, height),
729 _ => return,
730 };
731 self.surface.resize(width, height).expect("failed to resize inner buffer");
732 }
733 self.window.request_redraw();
734 }
735
736 /// Change the theme.
737 fn set_theme(&mut self, theme: Theme) {
738 self.theme = theme;
739 self.window.request_redraw();
740 }
741
742 /// Show window menu.
743 fn show_menu(&self) {
744 if let Some(position) = self.cursor_position {
745 self.window.show_window_menu(position);
746 }
747 }
748
749 /// Drag the window.
750 fn drag_window(&self) {
751 if let Err(err) = self.window.drag_window() {
752 info!("Error starting window drag: {err}");
753 } else {
754 info!("Dragging window Window={:?}", self.window.id());
755 }
756 }
757
758 /// Drag-resize the window.
759 fn drag_resize_window(&self) {
760 let position = match self.cursor_position {
761 Some(position) => position,
762 None => {
763 info!("Drag-resize requires cursor to be inside the window");
764 return;
765 },
766 };
767
768 let win_size = self.window.inner_size();
769 let border_size = BORDER_SIZE * self.window.scale_factor();
770
771 let x_direction = if position.x < border_size {
772 ResizeDirection::West
773 } else if position.x > (win_size.width as f64 - border_size) {
774 ResizeDirection::East
775 } else {
776 // Use arbitrary direction instead of None for simplicity.
777 ResizeDirection::SouthEast
778 };
779
780 let y_direction = if position.y < border_size {
781 ResizeDirection::North
782 } else if position.y > (win_size.height as f64 - border_size) {
783 ResizeDirection::South
784 } else {
785 // Use arbitrary direction instead of None for simplicity.
786 ResizeDirection::SouthEast
787 };
788
789 let direction = match (x_direction, y_direction) {
790 (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest,
791 (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest,
792 (ResizeDirection::West, _) => ResizeDirection::West,
793 (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast,
794 (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast,
795 (ResizeDirection::East, _) => ResizeDirection::East,
796 (_, ResizeDirection::South) => ResizeDirection::South,
797 (_, ResizeDirection::North) => ResizeDirection::North,
798 _ => return,
799 };
800
801 if let Err(err) = self.window.drag_resize_window(direction) {
802 info!("Error starting window drag-resize: {err}");
803 } else {
804 info!("Drag-resizing window Window={:?}", self.window.id());
805 }
806 }
807
808 /// Change window occlusion state.
809 fn set_occluded(&mut self, occluded: bool) {
810 self.occluded = occluded;
811 if !occluded {
812 self.window.request_redraw();
813 }
814 }
815
816 /// Draw the window contents.
817 #[cfg(not(any(android_platform, ios_platform)))]
818 fn draw(&mut self) -> Result<(), Box<dyn Error>> {
819 if self.occluded {
820 info!("Skipping drawing occluded window={:?}", self.window.id());
821 return Ok(());
822 }
823
824 const WHITE: u32 = 0xffffffff;
825 const DARK_GRAY: u32 = 0xff181818;
826
827 let color = match self.theme {
828 Theme::Light => WHITE,
829 Theme::Dark => DARK_GRAY,
830 };
831
832 let mut buffer = self.surface.buffer_mut()?;
833 buffer.fill(color);
834 self.window.pre_present_notify();
835 buffer.present()?;
836 Ok(())
837 }3fn main() -> Result<(), impl std::error::Error> {
4 use std::collections::HashMap;
5
6 use rio_winit_fork::dpi::{LogicalPosition, LogicalSize, Position};
7 use rio_winit_fork::event::{ElementState, Event, KeyEvent, WindowEvent};
8 use rio_winit_fork::event_loop::{ActiveEventLoop, EventLoop};
9 use rio_winit_fork::raw_window_handle::HasRawWindowHandle;
10 use rio_winit_fork::window::Window;
11
12 #[path = "util/fill.rs"]
13 mod fill;
14
15 fn spawn_child_window(parent: &Window, event_loop: &ActiveEventLoop) -> Window {
16 let parent = parent.raw_window_handle().unwrap();
17 let mut window_attributes = Window::default_attributes()
18 .with_title("child window")
19 .with_inner_size(LogicalSize::new(200.0f32, 200.0f32))
20 .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
21 .with_visible(true);
22 // `with_parent_window` is unsafe. Parent window must be a valid window.
23 window_attributes = unsafe { window_attributes.with_parent_window(Some(parent)) };
24
25 event_loop.create_window(window_attributes).unwrap()
26 }
27
28 let mut windows = HashMap::new();
29
30 let event_loop: EventLoop<()> = EventLoop::new().unwrap();
31 let mut parent_window_id = None;
32
33 event_loop.run(move |event: Event<()>, event_loop| {
34 match event {
35 Event::Resumed => {
36 let attributes = Window::default_attributes()
37 .with_title("parent window")
38 .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
39 .with_inner_size(LogicalSize::new(640.0f32, 480.0f32));
40 let window = event_loop.create_window(attributes).unwrap();
41
42 parent_window_id = Some(window.id());
43
44 println!("Parent window id: {parent_window_id:?})");
45 windows.insert(window.id(), window);
46 },
47 Event::WindowEvent { window_id, event } => match event {
48 WindowEvent::CloseRequested => {
49 windows.clear();
50 event_loop.exit();
51 },
52 WindowEvent::CursorEntered { device_id: _ } => {
53 // On x11, println when the cursor entered in a window even if the child window
54 // is created by some key inputs.
55 // the child windows are always placed at (0, 0) with size (200, 200) in the
56 // parent window, so we also can see this log when we move
57 // the cursor around (200, 200) in parent window.
58 println!("cursor entered in the window {window_id:?}");
59 },
60 WindowEvent::KeyboardInput {
61 event: KeyEvent { state: ElementState::Pressed, .. },
62 ..
63 } => {
64 let parent_window = windows.get(&parent_window_id.unwrap()).unwrap();
65 let child_window = spawn_child_window(parent_window, event_loop);
66 let child_id = child_window.id();
67 println!("Child window created with id: {child_id:?}");
68 windows.insert(child_id, child_window);
69 },
70 WindowEvent::RedrawRequested => {
71 if let Some(window) = windows.get(&window_id) {
72 fill::fill_window(window);
73 }
74 },
75 _ => (),
76 },
77 _ => (),
78 }
79 })
80}Sourcepub fn scale_factor(&self) -> f64
pub fn scale_factor(&self) -> f64
Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa.
Note that this value can change depending on user action (for example if the window is
moved to another screen); as such, tracking WindowEvent::ScaleFactorChanged events is
the most robust way to track the DPI you need to use to draw.
This value may differ from MonitorHandle::scale_factor.
See the dpi crate for more information.
§Platform-specific
The scale factor is calculated differently on different platforms:
-
Windows: On Windows 8 and 10, per-monitor scaling is readily configured by users from the display settings. While users are free to select any option they want, they’re only given a selection of “nice” scale factors, i.e. 1.0, 1.25, 1.5… on Windows 7. The scale factor is global and changing it requires logging out. See this article for technical details.
-
macOS: Recent macOS versions allow the user to change the scaling factor for specific displays. When available, the user may pick a per-monitor scaling factor from a set of pre-defined settings. All “retina displays” have a scaling factor above 1.0 by default, but the specific value varies across devices.
-
X11: Many man-hours have been spent trying to figure out how to handle DPI in X11. Winit currently uses a three-pronged approach:
- Use the value in the
WINIT_X11_SCALE_FACTORenvironment variable if present. - If not present, use the value set in
Xft.dpiin Xresources. - Otherwise, calculate the scale factor based on the millimeter monitor dimensions provided by XRandR.
If
WINIT_X11_SCALE_FACTORis set torandr, it’ll ignore theXft.dpifield and use the XRandR scaling method. Generally speaking, you should try to configure the standard system variables to do what you want before resorting toWINIT_X11_SCALE_FACTOR. - Use the value in the
-
Wayland: The scale factor is suggested by the compositor for each window individually by using the wp-fractional-scale protocol if available. Falls back to integer-scale factors otherwise.
The monitor scale factor may differ from the window scale factor.
-
iOS: Scale factors are set by Apple to the value that best suits the device, and range from
1.0to3.0. See this article and this article for more information.This uses the underlying
UIView’scontentScaleFactor. -
Android: Scale factors are set by the manufacturer to the value that best suits the device, and range from
1.0to4.0. See this article for more information.This is currently unimplemented, and this function always returns 1.0.
-
Web: The scale factor is the ratio between CSS pixels and the physical device pixels. In other words, it is the value of
window.devicePixelRatio. It is affected by both the screen scaling and the browser zoom level and can go below1.0. -
Orbital: This is currently unimplemented, and this function always returns 1.0.
Examples found in repository?
759 fn drag_resize_window(&self) {
760 let position = match self.cursor_position {
761 Some(position) => position,
762 None => {
763 info!("Drag-resize requires cursor to be inside the window");
764 return;
765 },
766 };
767
768 let win_size = self.window.inner_size();
769 let border_size = BORDER_SIZE * self.window.scale_factor();
770
771 let x_direction = if position.x < border_size {
772 ResizeDirection::West
773 } else if position.x > (win_size.width as f64 - border_size) {
774 ResizeDirection::East
775 } else {
776 // Use arbitrary direction instead of None for simplicity.
777 ResizeDirection::SouthEast
778 };
779
780 let y_direction = if position.y < border_size {
781 ResizeDirection::North
782 } else if position.y > (win_size.height as f64 - border_size) {
783 ResizeDirection::South
784 } else {
785 // Use arbitrary direction instead of None for simplicity.
786 ResizeDirection::SouthEast
787 };
788
789 let direction = match (x_direction, y_direction) {
790 (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest,
791 (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest,
792 (ResizeDirection::West, _) => ResizeDirection::West,
793 (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast,
794 (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast,
795 (ResizeDirection::East, _) => ResizeDirection::East,
796 (_, ResizeDirection::South) => ResizeDirection::South,
797 (_, ResizeDirection::North) => ResizeDirection::North,
798 _ => return,
799 };
800
801 if let Err(err) = self.window.drag_resize_window(direction) {
802 info!("Error starting window drag-resize: {err}");
803 } else {
804 info!("Drag-resizing window Window={:?}", self.window.id());
805 }
806 }Sourcepub fn request_redraw(&self)
pub fn request_redraw(&self)
Queues a WindowEvent::RedrawRequested event to be emitted that aligns with the windowing
system drawing loop.
This is the strongly encouraged method of redrawing windows, as it can integrate with
OS-requested redraws (e.g. when a window gets resized). To improve the event delivery
consider using Window::pre_present_notify as described in docs.
Applications should always aim to redraw whenever they receive a RedrawRequested event.
There are no strong guarantees about when exactly a RedrawRequest event will be emitted
with respect to other events, since the requirements can vary significantly between
windowing systems.
However as the event aligns with the windowing system drawing loop, it may not arrive in same or even next event loop iteration.
§Platform-specific
- Windows This API uses
RedrawWindowto request aWM_PAINTmessage andRedrawRequestedis emitted in sync with anyWM_PAINTmessages. - iOS: Can only be called on the main thread.
- Wayland: The events are aligned with the frame callbacks when
Window::pre_present_notifyis used. - Web:
WindowEvent::RedrawRequestedwill be aligned with therequestAnimationFrame.
Examples found in repository?
More examples
722 fn resize(&mut self, size: PhysicalSize<u32>) {
723 info!("Resized to {size:?}");
724 #[cfg(not(any(android_platform, ios_platform)))]
725 {
726 let (width, height) = match (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
727 {
728 (Some(width), Some(height)) => (width, height),
729 _ => return,
730 };
731 self.surface.resize(width, height).expect("failed to resize inner buffer");
732 }
733 self.window.request_redraw();
734 }
735
736 /// Change the theme.
737 fn set_theme(&mut self, theme: Theme) {
738 self.theme = theme;
739 self.window.request_redraw();
740 }
741
742 /// Show window menu.
743 fn show_menu(&self) {
744 if let Some(position) = self.cursor_position {
745 self.window.show_window_menu(position);
746 }
747 }
748
749 /// Drag the window.
750 fn drag_window(&self) {
751 if let Err(err) = self.window.drag_window() {
752 info!("Error starting window drag: {err}");
753 } else {
754 info!("Dragging window Window={:?}", self.window.id());
755 }
756 }
757
758 /// Drag-resize the window.
759 fn drag_resize_window(&self) {
760 let position = match self.cursor_position {
761 Some(position) => position,
762 None => {
763 info!("Drag-resize requires cursor to be inside the window");
764 return;
765 },
766 };
767
768 let win_size = self.window.inner_size();
769 let border_size = BORDER_SIZE * self.window.scale_factor();
770
771 let x_direction = if position.x < border_size {
772 ResizeDirection::West
773 } else if position.x > (win_size.width as f64 - border_size) {
774 ResizeDirection::East
775 } else {
776 // Use arbitrary direction instead of None for simplicity.
777 ResizeDirection::SouthEast
778 };
779
780 let y_direction = if position.y < border_size {
781 ResizeDirection::North
782 } else if position.y > (win_size.height as f64 - border_size) {
783 ResizeDirection::South
784 } else {
785 // Use arbitrary direction instead of None for simplicity.
786 ResizeDirection::SouthEast
787 };
788
789 let direction = match (x_direction, y_direction) {
790 (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest,
791 (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest,
792 (ResizeDirection::West, _) => ResizeDirection::West,
793 (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast,
794 (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast,
795 (ResizeDirection::East, _) => ResizeDirection::East,
796 (_, ResizeDirection::South) => ResizeDirection::South,
797 (_, ResizeDirection::North) => ResizeDirection::North,
798 _ => return,
799 };
800
801 if let Err(err) = self.window.drag_resize_window(direction) {
802 info!("Error starting window drag-resize: {err}");
803 } else {
804 info!("Drag-resizing window Window={:?}", self.window.id());
805 }
806 }
807
808 /// Change window occlusion state.
809 fn set_occluded(&mut self, occluded: bool) {
810 self.occluded = occluded;
811 if !occluded {
812 self.window.request_redraw();
813 }
814 }30 fn window_event(
31 &mut self,
32 event_loop: &ActiveEventLoop,
33 _window_id: WindowId,
34 event: WindowEvent,
35 ) {
36 println!("{event:?}");
37
38 let window = match self.window.as_ref() {
39 Some(window) => window,
40 None => return,
41 };
42
43 match event {
44 WindowEvent::CloseRequested => event_loop.exit(),
45 WindowEvent::RedrawRequested => {
46 fill::fill_window(window);
47 window.request_redraw();
48 },
49 _ => (),
50 }
51 }125 fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
126 if self.request_redraw && !self.wait_cancelled && !self.close_requested {
127 self.window.as_ref().unwrap().request_redraw();
128 }
129
130 match self.mode {
131 Mode::Wait => event_loop.set_control_flow(ControlFlow::Wait),
132 Mode::WaitUntil => {
133 if !self.wait_cancelled {
134 event_loop
135 .set_control_flow(ControlFlow::WaitUntil(time::Instant::now() + WAIT_TIME));
136 }
137 },
138 Mode::Poll => {
139 thread::sleep(POLL_SLEEP_TIME);
140 event_loop.set_control_flow(ControlFlow::Poll);
141 },
142 };
143
144 if self.close_requested {
145 event_loop.exit();
146 }
147 }Sourcepub fn pre_present_notify(&self)
pub fn pre_present_notify(&self)
Notify the windowing system before presenting to the window.
You should call this event after your drawing operations, but before you submit
the buffer to the display or commit your drawings. Doing so will help winit to properly
schedule and make assumptions about its internal state. For example, it could properly
throttle WindowEvent::RedrawRequested.
§Example
This example illustrates how it looks with OpenGL, but it applies to other graphics APIs and software rendering.
// Do the actual drawing with OpenGL.
// Notify winit that we're about to submit buffer to the windowing system.
window.pre_present_notify();
// Submit buffer to the windowing system.
swap_buffers();§Platform-specific
Wayland: - schedules a frame callback to throttle WindowEvent::RedrawRequested.
Examples found in repository?
818 fn draw(&mut self) -> Result<(), Box<dyn Error>> {
819 if self.occluded {
820 info!("Skipping drawing occluded window={:?}", self.window.id());
821 return Ok(());
822 }
823
824 const WHITE: u32 = 0xffffffff;
825 const DARK_GRAY: u32 = 0xff181818;
826
827 let color = match self.theme {
828 Theme::Light => WHITE,
829 Theme::Dark => DARK_GRAY,
830 };
831
832 let mut buffer = self.surface.buffer_mut()?;
833 buffer.fill(color);
834 self.window.pre_present_notify();
835 buffer.present()?;
836 Ok(())
837 }More examples
77 fn window_event(
78 &mut self,
79 _event_loop: &ActiveEventLoop,
80 _window_id: WindowId,
81 event: WindowEvent,
82 ) {
83 info!("{event:?}");
84
85 match event {
86 WindowEvent::CloseRequested => {
87 self.close_requested = true;
88 },
89 WindowEvent::KeyboardInput {
90 event: KeyEvent { logical_key: key, state: ElementState::Pressed, .. },
91 ..
92 } => match key.as_ref() {
93 // WARNING: Consider using `key_without_modifiers()` if available on your platform.
94 // See the `key_binding` example
95 Key::Character("1") => {
96 self.mode = Mode::Wait;
97 warn!("mode: {:?}", self.mode);
98 },
99 Key::Character("2") => {
100 self.mode = Mode::WaitUntil;
101 warn!("mode: {:?}", self.mode);
102 },
103 Key::Character("3") => {
104 self.mode = Mode::Poll;
105 warn!("mode: {:?}", self.mode);
106 },
107 Key::Character("r") => {
108 self.request_redraw = !self.request_redraw;
109 warn!("request_redraw: {}", self.request_redraw);
110 },
111 Key::Named(NamedKey::Escape) => {
112 self.close_requested = true;
113 },
114 _ => (),
115 },
116 WindowEvent::RedrawRequested => {
117 let window = self.window.as_ref().unwrap();
118 window.pre_present_notify();
119 fill::fill_window(window);
120 },
121 _ => (),
122 }
123 }Sourcepub fn reset_dead_keys(&self)
pub fn reset_dead_keys(&self)
Reset the dead key state of the keyboard.
This is useful when a dead key is bound to trigger an action. Then this function can be called to reset the dead key state so that follow-up text input won’t be affected by the dead key.
§Platform-specific
- Web, macOS: Does nothing
Source§impl Window
Position and size functions.
impl Window
Position and size functions.
Sourcepub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError>
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError>
Returns the position of the top-left hand corner of the window’s client area relative to the top-left hand corner of the desktop.
The same conditions that apply to Window::outer_position apply to this method.
§Platform-specific
- iOS: Can only be called on the main thread. Returns the top left coordinates of the window’s safe area in the screen space coordinate system.
- Web: Returns the top-left coordinates relative to the viewport. Note: this returns
the same value as
Window::outer_position. - Android / Wayland: Always returns
NotSupportedError.
Sourcepub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError>
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError>
Returns the position of the top-left hand corner of the window relative to the top-left hand corner of the desktop.
Note that the top-left hand corner of the desktop is not necessarily the same as the screen. If the user uses a desktop with multiple monitors, the top-left hand corner of the desktop is the top-left hand corner of the monitor at the top-left of the desktop.
The coordinates can be negative if the top-left hand corner of the window is outside of the visible screen region.
§Platform-specific
- iOS: Can only be called on the main thread. Returns the top left coordinates of the window in the screen space coordinate system.
- Web: Returns the top-left coordinates relative to the viewport.
- Android / Wayland: Always returns
NotSupportedError.
Sourcepub fn set_outer_position<P: Into<Position>>(&self, position: P)
pub fn set_outer_position<P: Into<Position>>(&self, position: P)
Modifies the position of the window.
See Window::outer_position for more information about the coordinates.
This automatically un-maximizes the window if it’s maximized.
// Specify the position in logical dimensions like this:
window.set_outer_position(LogicalPosition::new(400.0, 200.0));
// Or specify the position in physical dimensions like this:
window.set_outer_position(PhysicalPosition::new(400, 200));§Platform-specific
- iOS: Can only be called on the main thread. Sets the top left coordinates of the window in the screen space coordinate system.
- Web: Sets the top-left coordinates relative to the viewport. Doesn’t account for CSS
transform. - Android / Wayland: Unsupported.
Sourcepub fn inner_size(&self) -> PhysicalSize<u32>
pub fn inner_size(&self) -> PhysicalSize<u32>
Returns the physical size of the window’s client area.
The client area is the content of the window, excluding the title bar and borders.
§Platform-specific
Examples found in repository?
71 pub fn fill_window(window: &Window) {
72 GC.with(|gc| {
73 let size = window.inner_size();
74 let (Some(width), Some(height)) =
75 (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
76 else {
77 return;
78 };
79
80 // Either get the last context used or create a new one.
81 let mut gc = gc.borrow_mut();
82 let surface =
83 gc.get_or_insert_with(|| GraphicsContext::new(window)).create_surface(window);
84
85 // Fill a buffer with a solid color.
86 const DARK_GRAY: u32 = 0xff181818;
87
88 surface.resize(width, height).expect("Failed to resize the softbuffer surface");
89
90 let mut buffer = surface.buffer_mut().expect("Failed to get the softbuffer buffer");
91 buffer.fill(DARK_GRAY);
92 buffer.present().expect("Failed to present the softbuffer buffer");
93 })
94 }More examples
524 fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
525 let window = Arc::new(window);
526
527 // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
528 // it doesn't outlive it.
529 #[cfg(not(any(android_platform, ios_platform)))]
530 let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
531
532 let theme = window.theme().unwrap_or(Theme::Dark);
533 info!("Theme: {theme:?}");
534 let named_idx = 0;
535 window.set_cursor(CURSORS[named_idx]);
536
537 // Allow IME out of the box.
538 let ime = true;
539 window.set_ime_allowed(ime);
540
541 let size = window.inner_size();
542 let mut state = Self {
543 #[cfg(macos_platform)]
544 option_as_alt: window.option_as_alt(),
545 custom_idx: app.custom_cursors.len() - 1,
546 cursor_grab: CursorGrabMode::None,
547 named_idx,
548 #[cfg(not(any(android_platform, ios_platform)))]
549 surface,
550 window,
551 theme,
552 ime,
553 cursor_position: Default::default(),
554 cursor_hidden: Default::default(),
555 modifiers: Default::default(),
556 occluded: Default::default(),
557 rotated: Default::default(),
558 panned: Default::default(),
559 zoom: Default::default(),
560 };
561
562 state.resize(size);
563 Ok(state)
564 }
565
566 pub fn toggle_ime(&mut self) {
567 self.ime = !self.ime;
568 self.window.set_ime_allowed(self.ime);
569 if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
570 self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
571 }
572 }
573
574 pub fn minimize(&mut self) {
575 self.window.set_minimized(true);
576 }
577
578 pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) {
579 self.cursor_position = Some(position);
580 if self.ime {
581 self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
582 }
583 }
584
585 pub fn cursor_left(&mut self) {
586 self.cursor_position = None;
587 }
588
589 /// Toggle maximized.
590 fn toggle_maximize(&self) {
591 let maximized = self.window.is_maximized();
592 self.window.set_maximized(!maximized);
593 }
594
595 /// Toggle window decorations.
596 fn toggle_decorations(&self) {
597 let decorated = self.window.is_decorated();
598 self.window.set_decorations(!decorated);
599 }
600
601 /// Toggle window resizable state.
602 fn toggle_resizable(&self) {
603 let resizable = self.window.is_resizable();
604 self.window.set_resizable(!resizable);
605 }
606
607 /// Toggle cursor visibility
608 fn toggle_cursor_visibility(&mut self) {
609 self.cursor_hidden = !self.cursor_hidden;
610 self.window.set_cursor_visible(!self.cursor_hidden);
611 }
612
613 /// Toggle resize increments on a window.
614 fn toggle_resize_increments(&mut self) {
615 let new_increments = match self.window.resize_increments() {
616 Some(_) => None,
617 None => Some(LogicalSize::new(25.0, 25.0)),
618 };
619 info!("Had increments: {}", new_increments.is_none());
620 self.window.set_resize_increments(new_increments);
621 }
622
623 /// Toggle fullscreen.
624 fn toggle_fullscreen(&self) {
625 let fullscreen = if self.window.fullscreen().is_some() {
626 None
627 } else {
628 Some(Fullscreen::Borderless(None))
629 };
630
631 self.window.set_fullscreen(fullscreen);
632 }
633
634 /// Cycle through the grab modes ignoring errors.
635 fn cycle_cursor_grab(&mut self) {
636 self.cursor_grab = match self.cursor_grab {
637 CursorGrabMode::None => CursorGrabMode::Confined,
638 CursorGrabMode::Confined => CursorGrabMode::Locked,
639 CursorGrabMode::Locked => CursorGrabMode::None,
640 };
641 info!("Changing cursor grab mode to {:?}", self.cursor_grab);
642 if let Err(err) = self.window.set_cursor_grab(self.cursor_grab) {
643 error!("Error setting cursor grab: {err}");
644 }
645 }
646
647 #[cfg(macos_platform)]
648 fn cycle_option_as_alt(&mut self) {
649 self.option_as_alt = match self.option_as_alt {
650 OptionAsAlt::None => OptionAsAlt::OnlyLeft,
651 OptionAsAlt::OnlyLeft => OptionAsAlt::OnlyRight,
652 OptionAsAlt::OnlyRight => OptionAsAlt::Both,
653 OptionAsAlt::Both => OptionAsAlt::None,
654 };
655 info!("Setting option as alt {:?}", self.option_as_alt);
656 self.window.set_option_as_alt(self.option_as_alt);
657 }
658
659 /// Swap the window dimensions with `request_inner_size`.
660 fn swap_dimensions(&mut self) {
661 let old_inner_size = self.window.inner_size();
662 let mut inner_size = old_inner_size;
663
664 mem::swap(&mut inner_size.width, &mut inner_size.height);
665 info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
666
667 if let Some(new_inner_size) = self.window.request_inner_size(inner_size) {
668 if old_inner_size == new_inner_size {
669 info!("Inner size change got ignored");
670 } else {
671 self.resize(new_inner_size);
672 }
673 } else {
674 info!("Request inner size is asynchronous");
675 }
676 }
677
678 /// Pick the next cursor.
679 fn next_cursor(&mut self) {
680 self.named_idx = (self.named_idx + 1) % CURSORS.len();
681 info!("Setting cursor to \"{:?}\"", CURSORS[self.named_idx]);
682 self.window.set_cursor(Cursor::Icon(CURSORS[self.named_idx]));
683 }
684
685 /// Pick the next custom cursor.
686 fn next_custom_cursor(&mut self, custom_cursors: &[CustomCursor]) {
687 self.custom_idx = (self.custom_idx + 1) % custom_cursors.len();
688 let cursor = Cursor::Custom(custom_cursors[self.custom_idx].clone());
689 self.window.set_cursor(cursor);
690 }
691
692 /// Custom cursor from an URL.
693 #[cfg(web_platform)]
694 fn url_custom_cursor(&mut self, event_loop: &ActiveEventLoop) {
695 let cursor = event_loop.create_custom_cursor(url_custom_cursor());
696
697 self.window.set_cursor(cursor);
698 }
699
700 /// Custom cursor from a URL.
701 #[cfg(web_platform)]
702 fn animation_custom_cursor(
703 &mut self,
704 event_loop: &ActiveEventLoop,
705 custom_cursors: &[CustomCursor],
706 ) {
707 use std::time::Duration;
708 use rio_winit_fork::platform::web::CustomCursorExtWebSys;
709
710 let cursors = vec![
711 custom_cursors[0].clone(),
712 custom_cursors[1].clone(),
713 event_loop.create_custom_cursor(url_custom_cursor()),
714 ];
715 let cursor = CustomCursor::from_animation(Duration::from_secs(3), cursors).unwrap();
716 let cursor = event_loop.create_custom_cursor(cursor);
717
718 self.window.set_cursor(cursor);
719 }
720
721 /// Resize the window to the new size.
722 fn resize(&mut self, size: PhysicalSize<u32>) {
723 info!("Resized to {size:?}");
724 #[cfg(not(any(android_platform, ios_platform)))]
725 {
726 let (width, height) = match (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
727 {
728 (Some(width), Some(height)) => (width, height),
729 _ => return,
730 };
731 self.surface.resize(width, height).expect("failed to resize inner buffer");
732 }
733 self.window.request_redraw();
734 }
735
736 /// Change the theme.
737 fn set_theme(&mut self, theme: Theme) {
738 self.theme = theme;
739 self.window.request_redraw();
740 }
741
742 /// Show window menu.
743 fn show_menu(&self) {
744 if let Some(position) = self.cursor_position {
745 self.window.show_window_menu(position);
746 }
747 }
748
749 /// Drag the window.
750 fn drag_window(&self) {
751 if let Err(err) = self.window.drag_window() {
752 info!("Error starting window drag: {err}");
753 } else {
754 info!("Dragging window Window={:?}", self.window.id());
755 }
756 }
757
758 /// Drag-resize the window.
759 fn drag_resize_window(&self) {
760 let position = match self.cursor_position {
761 Some(position) => position,
762 None => {
763 info!("Drag-resize requires cursor to be inside the window");
764 return;
765 },
766 };
767
768 let win_size = self.window.inner_size();
769 let border_size = BORDER_SIZE * self.window.scale_factor();
770
771 let x_direction = if position.x < border_size {
772 ResizeDirection::West
773 } else if position.x > (win_size.width as f64 - border_size) {
774 ResizeDirection::East
775 } else {
776 // Use arbitrary direction instead of None for simplicity.
777 ResizeDirection::SouthEast
778 };
779
780 let y_direction = if position.y < border_size {
781 ResizeDirection::North
782 } else if position.y > (win_size.height as f64 - border_size) {
783 ResizeDirection::South
784 } else {
785 // Use arbitrary direction instead of None for simplicity.
786 ResizeDirection::SouthEast
787 };
788
789 let direction = match (x_direction, y_direction) {
790 (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest,
791 (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest,
792 (ResizeDirection::West, _) => ResizeDirection::West,
793 (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast,
794 (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast,
795 (ResizeDirection::East, _) => ResizeDirection::East,
796 (_, ResizeDirection::South) => ResizeDirection::South,
797 (_, ResizeDirection::North) => ResizeDirection::North,
798 _ => return,
799 };
800
801 if let Err(err) = self.window.drag_resize_window(direction) {
802 info!("Error starting window drag-resize: {err}");
803 } else {
804 info!("Drag-resizing window Window={:?}", self.window.id());
805 }
806 }Sourcepub fn request_inner_size<S: Into<Size>>(
&self,
size: S,
) -> Option<PhysicalSize<u32>>
pub fn request_inner_size<S: Into<Size>>( &self, size: S, ) -> Option<PhysicalSize<u32>>
Request the new size for the window.
On platforms where the size is entirely controlled by the user the applied size will be returned immediately, resize event in such case may not be generated.
On platforms where resizing is disallowed by the windowing system, the current inner size is returned immediately, and the user one is ignored.
When None is returned, it means that the request went to the display system,
and the actual size will be delivered later with the WindowEvent::Resized.
See Window::inner_size for more information about the values.
The request could automatically un-maximize the window if it’s maximized.
// Specify the size in logical dimensions like this:
let _ = window.request_inner_size(LogicalSize::new(400.0, 200.0));
// Or specify the size in physical dimensions like this:
let _ = window.request_inner_size(PhysicalSize::new(400, 200));§Platform-specific
- Web: Sets the size of the canvas element. Doesn’t account for CSS
transform.
Examples found in repository?
660 fn swap_dimensions(&mut self) {
661 let old_inner_size = self.window.inner_size();
662 let mut inner_size = old_inner_size;
663
664 mem::swap(&mut inner_size.width, &mut inner_size.height);
665 info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
666
667 if let Some(new_inner_size) = self.window.request_inner_size(inner_size) {
668 if old_inner_size == new_inner_size {
669 info!("Inner size change got ignored");
670 } else {
671 self.resize(new_inner_size);
672 }
673 } else {
674 info!("Request inner size is asynchronous");
675 }
676 }Sourcepub fn outer_size(&self) -> PhysicalSize<u32>
pub fn outer_size(&self) -> PhysicalSize<u32>
Returns the physical size of the entire window.
These dimensions include the title bar and borders. If you don’t want that (and you usually
don’t), use Window::inner_size instead.
§Platform-specific
- iOS: Can only be called on the main thread. Returns the
PhysicalSizeof the window in screen space coordinates. - Web: Returns the size of the canvas element. Note: this returns the same value as
Window::inner_size.
Sourcepub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>)
pub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>)
Sets a minimum dimension size for the window.
// Specify the size in logical dimensions like this:
window.set_min_inner_size(Some(LogicalSize::new(400.0, 200.0)));
// Or specify the size in physical dimensions like this:
window.set_min_inner_size(Some(PhysicalSize::new(400, 200)));§Platform-specific
- iOS / Android / Orbital: Unsupported.
Sourcepub fn set_max_inner_size<S: Into<Size>>(&self, max_size: Option<S>)
pub fn set_max_inner_size<S: Into<Size>>(&self, max_size: Option<S>)
Sets a maximum dimension size for the window.
// Specify the size in logical dimensions like this:
window.set_max_inner_size(Some(LogicalSize::new(400.0, 200.0)));
// Or specify the size in physical dimensions like this:
window.set_max_inner_size(Some(PhysicalSize::new(400, 200)));§Platform-specific
- iOS / Android / Orbital: Unsupported.
Sourcepub fn resize_increments(&self) -> Option<PhysicalSize<u32>>
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>>
Sourcepub fn set_resize_increments<S: Into<Size>>(&self, increments: Option<S>)
pub fn set_resize_increments<S: Into<Size>>(&self, increments: Option<S>)
Sets window resize increments.
This is a niche constraint hint usually employed by terminal emulators and other apps that need “blocky” resizes.
§Platform-specific
- macOS: Increments are converted to logical size and then macOS rounds them to whole numbers.
- Wayland: Not implemented.
- iOS / Android / Web / Orbital: Unsupported.
Source§impl Window
Misc. attribute functions.
impl Window
Misc. attribute functions.
Sourcepub fn set_transparent(&self, transparent: bool)
pub fn set_transparent(&self, transparent: bool)
Change the window transparency state.
This is just a hint that may not change anything about the window transparency, however doing a mismatch between the content of your window and this hint may result in visual artifacts.
The default value follows the WindowAttributes::with_transparent.
§Platform-specific
- macOS: If you’re not drawing to the window yourself, you might have to set the background color of the window to enable transparency.
- Web / iOS / Android: Unsupported.
- X11: Can only be set while building the window, with
WindowAttributes::with_transparent.
Sourcepub fn set_blur(&self, blur: bool)
pub fn set_blur(&self, blur: bool)
Change the window blur state.
If true, this will make the transparent window background blurry.
§Platform-specific
- Android / iOS / X11 / Web / Windows: Unsupported.
- Wayland: Only works with org_kde_kwin_blur_manager protocol.
Sourcepub fn set_visible(&self, visible: bool)
pub fn set_visible(&self, visible: bool)
Modifies the window’s visibility.
If false, this will hide the window. If true, this will show the window.
§Platform-specific
- Android / Wayland / Web: Unsupported.
- iOS: Can only be called on the main thread.
Sourcepub fn is_visible(&self) -> Option<bool>
pub fn is_visible(&self) -> Option<bool>
Gets the window’s current visibility state.
None means it couldn’t be determined, so it is not recommended to use this to drive your
rendering backend.
§Platform-specific
- X11: Not implemented.
- Wayland / iOS / Android / Web: Unsupported.
Sourcepub fn set_resizable(&self, resizable: bool)
pub fn set_resizable(&self, resizable: bool)
Sets whether the window is resizable or not.
Note that making the window unresizable doesn’t exempt you from handling
WindowEvent::Resized, as that event can still be triggered by DPI scaling, entering
fullscreen mode, etc. Also, the window could still be resized by calling
Window::request_inner_size.
§Platform-specific
This only has an effect on desktop platforms.
- X11: Due to a bug in XFCE, this has no effect on Xfwm.
- iOS / Android / Web: Unsupported.
Sourcepub fn is_resizable(&self) -> bool
pub fn is_resizable(&self) -> bool
Gets the window’s current resizable state.
§Platform-specific
- X11: Not implemented.
- iOS / Android / Web: Unsupported.
Sets the enabled window buttons.
§Platform-specific
- Wayland / X11 / Orbital: Not implemented.
- Web / iOS / Android: Unsupported.
Gets the enabled window buttons.
§Platform-specific
- Wayland / X11 / Orbital: Not implemented. Always returns
WindowButtons::all. - Web / iOS / Android: Unsupported. Always returns
WindowButtons::all.
Sourcepub fn set_minimized(&self, minimized: bool)
pub fn set_minimized(&self, minimized: bool)
Sets the window to minimized or back
§Platform-specific
- iOS / Android / Web / Orbital: Unsupported.
- Wayland: Un-minimize is unsupported.
Sourcepub fn is_minimized(&self) -> Option<bool>
pub fn is_minimized(&self) -> Option<bool>
Sourcepub fn set_maximized(&self, maximized: bool)
pub fn set_maximized(&self, maximized: bool)
Sourcepub fn is_maximized(&self) -> bool
pub fn is_maximized(&self) -> bool
Sourcepub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>)
pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>)
Sets the window to fullscreen or back.
§Platform-specific
-
macOS:
Fullscreen::Exclusiveprovides true exclusive mode with a video mode change. Caveat! macOS doesn’t provide task switching (or spaces!) while in exclusive fullscreen mode. This mode should be used when a video mode change is desired, but for a better user experience, borderless fullscreen might be preferred.Fullscreen::Borderlessprovides a borderless fullscreen window on a separate space. This is the idiomatic way for fullscreen games to work on macOS. SeeWindowExtMacOs::set_simple_fullscreenif separate spaces are not preferred.The dock and the menu bar are disabled in exclusive fullscreen mode.
-
iOS: Can only be called on the main thread.
-
Wayland: Does not support exclusive fullscreen mode and will no-op a request.
-
Windows: Screen saver is disabled in fullscreen mode.
-
Android / Orbital: Unsupported.
-
Web: Does nothing without a transient activation.
Sourcepub fn fullscreen(&self) -> Option<Fullscreen>
pub fn fullscreen(&self) -> Option<Fullscreen>
Gets the window’s current fullscreen state.
§Platform-specific
- iOS: Can only be called on the main thread.
- Android / Orbital: Will always return
None. - Wayland: Can return
Borderless(None)when there are no monitors. - Web: Can only return
NoneorBorderless(None).
Sourcepub fn set_decorations(&self, decorations: bool)
pub fn set_decorations(&self, decorations: bool)
Turn window decorations on or off.
Enable/disable window decorations provided by the server or Winit. By default this is enabled. Note that fullscreen windows and windows on mobile and web platforms naturally do not have decorations.
§Platform-specific
- iOS / Android / Web: No effect.
Sourcepub fn is_decorated(&self) -> bool
pub fn is_decorated(&self) -> bool
Gets the window’s current decorations state.
Returns true when windows are decorated (server-side or by Winit).
Also returns true when no decorations are required (mobile, web).
§Platform-specific
- iOS / Android / Web: Always returns
true.
Sourcepub fn set_window_level(&self, level: WindowLevel)
pub fn set_window_level(&self, level: WindowLevel)
Change the window level.
This is just a hint to the OS, and the system could ignore it.
See WindowLevel for details.
Sourcepub fn set_window_icon(&self, window_icon: Option<Icon>)
pub fn set_window_icon(&self, window_icon: Option<Icon>)
Sets the window icon.
On Windows and X11, this is typically the small icon in the top-left corner of the titlebar.
§Platform-specific
-
iOS / Android / Web / Wayland / macOS / Orbital: Unsupported.
-
Windows: Sets
ICON_SMALL. The base size for a window icon is 16x16, but it’s recommended to account for screen scaling and pick a multiple of that, i.e. 32x32. -
X11: Has no universal guidelines for icon sizes, so you’re at the whims of the WM. That said, it’s usually in the same ballpark as on Windows.
Sourcepub fn set_ime_cursor_area<P: Into<Position>, S: Into<Size>>(
&self,
position: P,
size: S,
)
pub fn set_ime_cursor_area<P: Into<Position>, S: Into<Size>>( &self, position: P, size: S, )
Set the IME cursor editing area, where the position is the top left corner of that area
and size is the size of this area starting from the position. An example of such area
could be a input field in the UI or line in the editor.
The windowing system could place a candidate box close to that area, but try to not obscure the specified area, so the user input to it stays visible.
The candidate box is the window / popup / overlay that allows you to select the desired characters. The look of this box may differ between input devices, even on the same platform.
(Apple’s official term is “candidate window”, see their chinese and japanese guides).
§Example
// Specify the position in logical dimensions like this:
window.set_ime_cursor_area(LogicalPosition::new(400.0, 200.0), LogicalSize::new(100, 100));
// Or specify the position in physical dimensions like this:
window.set_ime_cursor_area(PhysicalPosition::new(400, 200), PhysicalSize::new(100, 100));§Platform-specific
- X11: - area is not supported, only position.
- iOS / Android / Web / Orbital: Unsupported.
Examples found in repository?
566 pub fn toggle_ime(&mut self) {
567 self.ime = !self.ime;
568 self.window.set_ime_allowed(self.ime);
569 if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
570 self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
571 }
572 }
573
574 pub fn minimize(&mut self) {
575 self.window.set_minimized(true);
576 }
577
578 pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) {
579 self.cursor_position = Some(position);
580 if self.ime {
581 self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
582 }
583 }Sourcepub fn set_ime_allowed(&self, allowed: bool)
pub fn set_ime_allowed(&self, allowed: bool)
Sets whether the window should get IME events
When IME is allowed, the window will receive Ime events, and during the
preedit phase the window will NOT get KeyboardInput events. The window
should allow IME while it is expecting text input.
When IME is not allowed, the window won’t receive Ime events, and will
receive KeyboardInput events for every keypress instead. Not allowing
IME is useful for games for example.
IME is not allowed by default.
§Platform-specific
- macOS: IME must be enabled to receive text-input where dead-key sequences are combined.
- iOS / Android / Web / Orbital: Unsupported.
- X11: Enabling IME will disable dead keys reporting during compose.
Examples found in repository?
524 fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
525 let window = Arc::new(window);
526
527 // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
528 // it doesn't outlive it.
529 #[cfg(not(any(android_platform, ios_platform)))]
530 let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
531
532 let theme = window.theme().unwrap_or(Theme::Dark);
533 info!("Theme: {theme:?}");
534 let named_idx = 0;
535 window.set_cursor(CURSORS[named_idx]);
536
537 // Allow IME out of the box.
538 let ime = true;
539 window.set_ime_allowed(ime);
540
541 let size = window.inner_size();
542 let mut state = Self {
543 #[cfg(macos_platform)]
544 option_as_alt: window.option_as_alt(),
545 custom_idx: app.custom_cursors.len() - 1,
546 cursor_grab: CursorGrabMode::None,
547 named_idx,
548 #[cfg(not(any(android_platform, ios_platform)))]
549 surface,
550 window,
551 theme,
552 ime,
553 cursor_position: Default::default(),
554 cursor_hidden: Default::default(),
555 modifiers: Default::default(),
556 occluded: Default::default(),
557 rotated: Default::default(),
558 panned: Default::default(),
559 zoom: Default::default(),
560 };
561
562 state.resize(size);
563 Ok(state)
564 }
565
566 pub fn toggle_ime(&mut self) {
567 self.ime = !self.ime;
568 self.window.set_ime_allowed(self.ime);
569 if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
570 self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
571 }
572 }Sourcepub fn set_ime_purpose(&self, purpose: ImePurpose)
pub fn set_ime_purpose(&self, purpose: ImePurpose)
Sets the IME purpose for the window using ImePurpose.
§Platform-specific
- iOS / Android / Web / Windows / X11 / macOS / Orbital: Unsupported.
Sourcepub fn focus_window(&self)
pub fn focus_window(&self)
Brings the window to the front and sets input focus. Has no effect if the window is already in focus, minimized, or not visible.
This method steals input focus from other applications. Do not use this method unless you are certain that’s what the user wants. Focus stealing can cause an extremely disruptive user experience.
§Platform-specific
- iOS / Android / Wayland / Orbital: Unsupported.
Sourcepub fn has_focus(&self) -> bool
pub fn has_focus(&self) -> bool
Gets whether the window has keyboard focus.
This queries the same state information as WindowEvent::Focused.
Sourcepub fn request_user_attention(&self, request_type: Option<UserAttentionType>)
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>)
Requests user attention to the window, this has no effect if the application
is already focused. How requesting for user attention manifests is platform dependent,
see UserAttentionType for details.
Providing None will unset the request for user attention. Unsetting the request for
user attention might not be done automatically by the WM when the window receives input.
§Platform-specific
- iOS / Android / Web / Orbital: Unsupported.
- macOS:
Nonehas no effect. - X11: Requests for user attention must be manually cleared.
- Wayland: Requires
xdg_activation_v1protocol,Nonehas no effect.
Sourcepub fn set_theme(&self, theme: Option<Theme>)
pub fn set_theme(&self, theme: Option<Theme>)
Sets the current window theme. Use None to fallback to system default.
§Platform-specific
- macOS: This is an app-wide setting.
- Wayland: Sets the theme for the client side decorations. Using
Nonewill use dbus to get the system preference. - X11: Sets
_GTK_THEME_VARIANThint todarkorlightand ifNoneis used, it will default toTheme::Dark. - iOS / Android / Web / Orbital: Unsupported.
Sourcepub fn theme(&self) -> Option<Theme>
pub fn theme(&self) -> Option<Theme>
Returns the current window theme.
§Platform-specific
- macOS: This is an app-wide setting.
- iOS / Android / Wayland / x11 / Orbital: Unsupported.
Examples found in repository?
524 fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
525 let window = Arc::new(window);
526
527 // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
528 // it doesn't outlive it.
529 #[cfg(not(any(android_platform, ios_platform)))]
530 let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
531
532 let theme = window.theme().unwrap_or(Theme::Dark);
533 info!("Theme: {theme:?}");
534 let named_idx = 0;
535 window.set_cursor(CURSORS[named_idx]);
536
537 // Allow IME out of the box.
538 let ime = true;
539 window.set_ime_allowed(ime);
540
541 let size = window.inner_size();
542 let mut state = Self {
543 #[cfg(macos_platform)]
544 option_as_alt: window.option_as_alt(),
545 custom_idx: app.custom_cursors.len() - 1,
546 cursor_grab: CursorGrabMode::None,
547 named_idx,
548 #[cfg(not(any(android_platform, ios_platform)))]
549 surface,
550 window,
551 theme,
552 ime,
553 cursor_position: Default::default(),
554 cursor_hidden: Default::default(),
555 modifiers: Default::default(),
556 occluded: Default::default(),
557 rotated: Default::default(),
558 panned: Default::default(),
559 zoom: Default::default(),
560 };
561
562 state.resize(size);
563 Ok(state)
564 }Sourcepub fn set_content_protected(&self, protected: bool)
pub fn set_content_protected(&self, protected: bool)
Prevents the window contents from being captured by other apps.
§Platform-specific
- macOS: if
false,NSWindowSharingNoneis used but doesn’t completely prevent all apps from reading the window content, for instance, QuickTime. - iOS / Android / x11 / Wayland / Web / Orbital: Unsupported.
Source§impl Window
Cursor functions.
impl Window
Cursor functions.
Sourcepub fn set_cursor(&self, cursor: impl Into<Cursor>)
pub fn set_cursor(&self, cursor: impl Into<Cursor>)
Modifies the cursor icon of the window.
§Platform-specific
- iOS / Android / Orbital: Unsupported.
- Web: Custom cursors have to be loaded and decoded first, until then the previous cursor is shown.
Examples found in repository?
524 fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
525 let window = Arc::new(window);
526
527 // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
528 // it doesn't outlive it.
529 #[cfg(not(any(android_platform, ios_platform)))]
530 let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
531
532 let theme = window.theme().unwrap_or(Theme::Dark);
533 info!("Theme: {theme:?}");
534 let named_idx = 0;
535 window.set_cursor(CURSORS[named_idx]);
536
537 // Allow IME out of the box.
538 let ime = true;
539 window.set_ime_allowed(ime);
540
541 let size = window.inner_size();
542 let mut state = Self {
543 #[cfg(macos_platform)]
544 option_as_alt: window.option_as_alt(),
545 custom_idx: app.custom_cursors.len() - 1,
546 cursor_grab: CursorGrabMode::None,
547 named_idx,
548 #[cfg(not(any(android_platform, ios_platform)))]
549 surface,
550 window,
551 theme,
552 ime,
553 cursor_position: Default::default(),
554 cursor_hidden: Default::default(),
555 modifiers: Default::default(),
556 occluded: Default::default(),
557 rotated: Default::default(),
558 panned: Default::default(),
559 zoom: Default::default(),
560 };
561
562 state.resize(size);
563 Ok(state)
564 }
565
566 pub fn toggle_ime(&mut self) {
567 self.ime = !self.ime;
568 self.window.set_ime_allowed(self.ime);
569 if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
570 self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
571 }
572 }
573
574 pub fn minimize(&mut self) {
575 self.window.set_minimized(true);
576 }
577
578 pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) {
579 self.cursor_position = Some(position);
580 if self.ime {
581 self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20));
582 }
583 }
584
585 pub fn cursor_left(&mut self) {
586 self.cursor_position = None;
587 }
588
589 /// Toggle maximized.
590 fn toggle_maximize(&self) {
591 let maximized = self.window.is_maximized();
592 self.window.set_maximized(!maximized);
593 }
594
595 /// Toggle window decorations.
596 fn toggle_decorations(&self) {
597 let decorated = self.window.is_decorated();
598 self.window.set_decorations(!decorated);
599 }
600
601 /// Toggle window resizable state.
602 fn toggle_resizable(&self) {
603 let resizable = self.window.is_resizable();
604 self.window.set_resizable(!resizable);
605 }
606
607 /// Toggle cursor visibility
608 fn toggle_cursor_visibility(&mut self) {
609 self.cursor_hidden = !self.cursor_hidden;
610 self.window.set_cursor_visible(!self.cursor_hidden);
611 }
612
613 /// Toggle resize increments on a window.
614 fn toggle_resize_increments(&mut self) {
615 let new_increments = match self.window.resize_increments() {
616 Some(_) => None,
617 None => Some(LogicalSize::new(25.0, 25.0)),
618 };
619 info!("Had increments: {}", new_increments.is_none());
620 self.window.set_resize_increments(new_increments);
621 }
622
623 /// Toggle fullscreen.
624 fn toggle_fullscreen(&self) {
625 let fullscreen = if self.window.fullscreen().is_some() {
626 None
627 } else {
628 Some(Fullscreen::Borderless(None))
629 };
630
631 self.window.set_fullscreen(fullscreen);
632 }
633
634 /// Cycle through the grab modes ignoring errors.
635 fn cycle_cursor_grab(&mut self) {
636 self.cursor_grab = match self.cursor_grab {
637 CursorGrabMode::None => CursorGrabMode::Confined,
638 CursorGrabMode::Confined => CursorGrabMode::Locked,
639 CursorGrabMode::Locked => CursorGrabMode::None,
640 };
641 info!("Changing cursor grab mode to {:?}", self.cursor_grab);
642 if let Err(err) = self.window.set_cursor_grab(self.cursor_grab) {
643 error!("Error setting cursor grab: {err}");
644 }
645 }
646
647 #[cfg(macos_platform)]
648 fn cycle_option_as_alt(&mut self) {
649 self.option_as_alt = match self.option_as_alt {
650 OptionAsAlt::None => OptionAsAlt::OnlyLeft,
651 OptionAsAlt::OnlyLeft => OptionAsAlt::OnlyRight,
652 OptionAsAlt::OnlyRight => OptionAsAlt::Both,
653 OptionAsAlt::Both => OptionAsAlt::None,
654 };
655 info!("Setting option as alt {:?}", self.option_as_alt);
656 self.window.set_option_as_alt(self.option_as_alt);
657 }
658
659 /// Swap the window dimensions with `request_inner_size`.
660 fn swap_dimensions(&mut self) {
661 let old_inner_size = self.window.inner_size();
662 let mut inner_size = old_inner_size;
663
664 mem::swap(&mut inner_size.width, &mut inner_size.height);
665 info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
666
667 if let Some(new_inner_size) = self.window.request_inner_size(inner_size) {
668 if old_inner_size == new_inner_size {
669 info!("Inner size change got ignored");
670 } else {
671 self.resize(new_inner_size);
672 }
673 } else {
674 info!("Request inner size is asynchronous");
675 }
676 }
677
678 /// Pick the next cursor.
679 fn next_cursor(&mut self) {
680 self.named_idx = (self.named_idx + 1) % CURSORS.len();
681 info!("Setting cursor to \"{:?}\"", CURSORS[self.named_idx]);
682 self.window.set_cursor(Cursor::Icon(CURSORS[self.named_idx]));
683 }
684
685 /// Pick the next custom cursor.
686 fn next_custom_cursor(&mut self, custom_cursors: &[CustomCursor]) {
687 self.custom_idx = (self.custom_idx + 1) % custom_cursors.len();
688 let cursor = Cursor::Custom(custom_cursors[self.custom_idx].clone());
689 self.window.set_cursor(cursor);
690 }Sourcepub fn set_cursor_icon(&self, icon: CursorIcon)
👎Deprecated: Renamed to set_cursor
pub fn set_cursor_icon(&self, icon: CursorIcon)
set_cursorDeprecated! Use Window::set_cursor() instead.
Sourcepub fn set_cursor_position<P: Into<Position>>(
&self,
position: P,
) -> Result<(), ExternalError>
pub fn set_cursor_position<P: Into<Position>>( &self, position: P, ) -> Result<(), ExternalError>
Changes the position of the cursor in window coordinates.
// Specify the position in logical dimensions like this:
window.set_cursor_position(LogicalPosition::new(400.0, 200.0));
// Or specify the position in physical dimensions like this:
window.set_cursor_position(PhysicalPosition::new(400, 200));§Platform-specific
- Wayland: Cursor must be in
CursorGrabMode::Locked. - iOS / Android / Web / Orbital: Always returns an
ExternalError::NotSupported.
Sourcepub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError>
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError>
Sourcepub fn set_cursor_visible(&self, visible: bool)
pub fn set_cursor_visible(&self, visible: bool)
Modifies the cursor’s visibility.
If false, this will hide the cursor. If true, this will show the cursor.
§Platform-specific
- Windows: The cursor is only hidden within the confines of the window.
- X11: The cursor is only hidden within the confines of the window.
- Wayland: The cursor is only hidden within the confines of the window.
- macOS: The cursor is hidden as long as the window has input focus, even if the cursor is outside of the window.
- iOS / Android: Unsupported.
Sourcepub fn drag_window(&self) -> Result<(), ExternalError>
pub fn drag_window(&self) -> Result<(), ExternalError>
Moves the window with the left mouse button until the button is released.
There’s no guarantee that this will work unless the left mouse button was pressed immediately before this function is called.
§Platform-specific
- X11: Un-grabs the cursor.
- Wayland: Requires the cursor to be inside the window to be dragged.
- macOS: May prevent the button release event to be triggered.
- iOS / Android / Web: Always returns an
ExternalError::NotSupported.
Sourcepub fn drag_resize_window(
&self,
direction: ResizeDirection,
) -> Result<(), ExternalError>
pub fn drag_resize_window( &self, direction: ResizeDirection, ) -> Result<(), ExternalError>
Resizes the window with the left mouse button until the button is released.
There’s no guarantee that this will work unless the left mouse button was pressed immediately before this function is called.
§Platform-specific
- macOS: Always returns an
ExternalError::NotSupported - iOS / Android / Web: Always returns an
ExternalError::NotSupported.
Examples found in repository?
759 fn drag_resize_window(&self) {
760 let position = match self.cursor_position {
761 Some(position) => position,
762 None => {
763 info!("Drag-resize requires cursor to be inside the window");
764 return;
765 },
766 };
767
768 let win_size = self.window.inner_size();
769 let border_size = BORDER_SIZE * self.window.scale_factor();
770
771 let x_direction = if position.x < border_size {
772 ResizeDirection::West
773 } else if position.x > (win_size.width as f64 - border_size) {
774 ResizeDirection::East
775 } else {
776 // Use arbitrary direction instead of None for simplicity.
777 ResizeDirection::SouthEast
778 };
779
780 let y_direction = if position.y < border_size {
781 ResizeDirection::North
782 } else if position.y > (win_size.height as f64 - border_size) {
783 ResizeDirection::South
784 } else {
785 // Use arbitrary direction instead of None for simplicity.
786 ResizeDirection::SouthEast
787 };
788
789 let direction = match (x_direction, y_direction) {
790 (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest,
791 (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest,
792 (ResizeDirection::West, _) => ResizeDirection::West,
793 (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast,
794 (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast,
795 (ResizeDirection::East, _) => ResizeDirection::East,
796 (_, ResizeDirection::South) => ResizeDirection::South,
797 (_, ResizeDirection::North) => ResizeDirection::North,
798 _ => return,
799 };
800
801 if let Err(err) = self.window.drag_resize_window(direction) {
802 info!("Error starting window drag-resize: {err}");
803 } else {
804 info!("Drag-resizing window Window={:?}", self.window.id());
805 }
806 }Show window menu at a specified position .
This is the context menu that is normally shown when interacting with the title bar. This is useful when implementing custom decorations.
§Platform-specific
Android / iOS / macOS / Orbital / Wayland / Web / X11: Unsupported.
Sourcepub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError>
pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError>
Modifies whether the window catches cursor events.
If true, the window will catch the cursor events. If false, events are passed through
the window such that any other window behind it receives them. By default hittest is
enabled.
§Platform-specific
- iOS / Android / Web / Orbital: Always returns an
ExternalError::NotSupported.
Source§impl Window
Monitor info functions.
impl Window
Monitor info functions.
Sourcepub fn current_monitor(&self) -> Option<MonitorHandle>
pub fn current_monitor(&self) -> Option<MonitorHandle>
Returns the monitor on which the window currently resides.
Returns None if current monitor can’t be detected.
Sourcepub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle>
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle>
Returns the list of all the monitors available on the system.
This is the same as ActiveEventLoop::available_monitors, and is provided for
convenience.
Sourcepub fn primary_monitor(&self) -> Option<MonitorHandle>
pub fn primary_monitor(&self) -> Option<MonitorHandle>
Returns the primary monitor of the system.
Returns None if it can’t identify any monitor as a primary one.
This is the same as ActiveEventLoop::primary_monitor, and is provided for convenience.
§Platform-specific
Wayland / Web: Always returns None.
Trait Implementations§
Source§impl HasDisplayHandle for Window
Available on crate feature rwh_06 only.
impl HasDisplayHandle for Window
rwh_06 only.Source§fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError>
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError>
Source§impl HasWindowHandle for Window
Available on crate feature rwh_06 only.
impl HasWindowHandle for Window
rwh_06 only.Source§fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError>
fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError>
Source§impl WindowExtAndroid for Window
Available on android_platform only.
impl WindowExtAndroid for Window
android_platform only.Source§impl WindowExtIOS for Window
Available on ios_platform only.
impl WindowExtIOS for Window
ios_platform only.Source§fn set_scale_factor(&self, scale_factor: f64)
fn set_scale_factor(&self, scale_factor: f64)
Source§fn set_valid_orientations(&self, valid_orientations: ValidOrientations)
fn set_valid_orientations(&self, valid_orientations: ValidOrientations)
Source§fn set_preferred_screen_edges_deferring_system_gestures(
&self,
edges: ScreenEdge,
)
fn set_preferred_screen_edges_deferring_system_gestures( &self, edges: ScreenEdge, )
Source§fn set_preferred_status_bar_style(&self, status_bar_style: StatusBarStyle)
fn set_preferred_status_bar_style(&self, status_bar_style: StatusBarStyle)
Source§fn recognize_pinch_gesture(&self, should_recognize: bool)
fn recognize_pinch_gesture(&self, should_recognize: bool)
Source§fn recognize_pan_gesture(
&self,
should_recognize: bool,
minimum_number_of_touches: u8,
maximum_number_of_touches: u8,
)
fn recognize_pan_gesture( &self, should_recognize: bool, minimum_number_of_touches: u8, maximum_number_of_touches: u8, )
Source§fn recognize_doubletap_gesture(&self, should_recognize: bool)
fn recognize_doubletap_gesture(&self, should_recognize: bool)
Source§impl WindowExtMacOS for Window
Available on macos_platform only.
impl WindowExtMacOS for Window
macos_platform only.Source§fn simple_fullscreen(&self) -> bool
fn simple_fullscreen(&self) -> bool
Source§fn set_simple_fullscreen(&self, fullscreen: bool) -> bool
fn set_simple_fullscreen(&self, fullscreen: bool) -> bool
Source§fn has_shadow(&self) -> bool
fn has_shadow(&self) -> bool
Source§fn set_has_shadow(&self, has_shadow: bool)
fn set_has_shadow(&self, has_shadow: bool)
Source§fn set_tabbing_identifier(&self, identifier: &str)
fn set_tabbing_identifier(&self, identifier: &str)
Source§fn tabbing_identifier(&self) -> String
fn tabbing_identifier(&self) -> String
Source§fn select_next_tab(&self)
fn select_next_tab(&self)
Source§fn select_previous_tab(&self)
fn select_previous_tab(&self)
Source§fn select_tab_at_index(&self, index: usize)
fn select_tab_at_index(&self, index: usize)
Source§fn is_document_edited(&self) -> bool
fn is_document_edited(&self) -> bool
Source§fn set_document_edited(&self, edited: bool)
fn set_document_edited(&self, edited: bool)
Source§fn set_option_as_alt(&self, option_as_alt: OptionAsAlt)
fn set_option_as_alt(&self, option_as_alt: OptionAsAlt)
OptionAsAlt. Read moreSource§fn option_as_alt(&self) -> OptionAsAlt
fn option_as_alt(&self) -> OptionAsAlt
WindowExtMacOS::set_option_as_alt.Source§impl WindowExtStartupNotify for Window
Available on x11_platform or wayland_platform only.
impl WindowExtStartupNotify for Window
x11_platform or wayland_platform only.Source§fn request_activation_token(
&self,
) -> Result<AsyncRequestSerial, NotSupportedError>
fn request_activation_token( &self, ) -> Result<AsyncRequestSerial, NotSupportedError>
Source§impl WindowExtWebSys for Window
Available on web_platform only.
impl WindowExtWebSys for Window
web_platform only.Source§fn canvas(&self) -> Option<HtmlCanvasElement>
fn canvas(&self) -> Option<HtmlCanvasElement>
Source§fn prevent_default(&self) -> bool
fn prevent_default(&self) -> bool
Source§fn set_prevent_default(&self, prevent_default: bool)
fn set_prevent_default(&self, prevent_default: bool)
event.preventDefault() should be called on events on the
canvas that have side effects. Read moreSource§impl WindowExtWindows for Window
Available on windows_platform only.
impl WindowExtWindows for Window
windows_platform only.Source§fn set_enable(&self, enabled: bool)
fn set_enable(&self, enabled: bool)
Source§fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>)
fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>)
ICON_BIG. A good ceiling here is 256x256.Source§fn set_skip_taskbar(&self, skip: bool)
fn set_skip_taskbar(&self, skip: bool)
Source§fn set_undecorated_shadow(&self, shadow: bool)
fn set_undecorated_shadow(&self, shadow: bool)
Source§fn set_system_backdrop(&self, backdrop_type: BackdropType)
fn set_system_backdrop(&self, backdrop_type: BackdropType)
Source§fn set_border_color(&self, color: Option<Color>)
fn set_border_color(&self, color: Option<Color>)
Source§fn set_title_background_color(&self, color: Option<Color>)
fn set_title_background_color(&self, color: Option<Color>)
Source§fn set_title_text_color(&self, color: Color)
fn set_title_text_color(&self, color: Color)
Source§fn set_corner_preference(&self, preference: CornerPreference)
fn set_corner_preference(&self, preference: CornerPreference)
Source§unsafe fn window_handle_any_thread(
&self,
) -> Result<WindowHandle<'_>, HandleError>
unsafe fn window_handle_any_thread( &self, ) -> Result<WindowHandle<'_>, HandleError>
rwh_06 only.impl WindowExtWayland for Window
wayland_platform only.impl WindowExtX11 for Window
x11_platform only.Auto Trait Implementations§
impl Freeze for Window
impl RefUnwindSafe for Window
impl Send for Window
impl Sync for Window
impl Unpin for Window
impl UnwindSafe for Window
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> HasRawDisplayHandle for Twhere
T: HasDisplayHandle + ?Sized,
impl<T> HasRawDisplayHandle for Twhere
T: HasDisplayHandle + ?Sized,
Source§fn raw_display_handle(&self) -> Result<RawDisplayHandle, HandleError>
fn raw_display_handle(&self) -> Result<RawDisplayHandle, HandleError>
HasDisplayHandle insteadSource§impl<T> HasRawWindowHandle for Twhere
T: HasWindowHandle + ?Sized,
impl<T> HasRawWindowHandle for Twhere
T: HasWindowHandle + ?Sized,
Source§fn raw_window_handle(&self) -> Result<RawWindowHandle, HandleError>
fn raw_window_handle(&self) -> Result<RawWindowHandle, HandleError>
HasWindowHandle insteadSource§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<W> WindowBorrowExtWindows for W
impl<W> WindowBorrowExtWindows for W
Source§unsafe fn any_thread(self) -> AnyThread<Self>
unsafe fn any_thread(self) -> AnyThread<Self>
windows_platform only.