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_window::dpi::{LogicalPosition, LogicalSize, Position};
7 use rio_window::event::{ElementState, Event, KeyEvent, WindowEvent};
8 use rio_window::event_loop::{ActiveEventLoop, EventLoop};
9 use rio_window::raw_window_handle::HasRawWindowHandle;
10 use rio_window::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:
62 KeyEvent {
63 state: ElementState::Pressed,
64 ..
65 },
66 ..
67 } => {
68 let parent_window = windows.get(&parent_window_id.unwrap()).unwrap();
69 let child_window = spawn_child_window(parent_window, event_loop);
70 let child_id = child_window.id();
71 println!("Child window created with id: {child_id:?}");
72 windows.insert(child_id, child_window);
73 }
74 WindowEvent::RedrawRequested => {
75 if let Some(window) = windows.get(&window_id) {
76 fill::fill_window(window);
77 }
78 }
79 _ => (),
80 },
81 _ => (),
82 }
83 })
84}
131 fn create_window(
132 &mut self,
133 event_loop: &ActiveEventLoop,
134 _tab_id: Option<String>,
135 ) -> Result<WindowId, Box<dyn Error>> {
136 // TODO read-out activation token.
137
138 #[allow(unused_mut)]
139 let mut window_attributes = Window::default_attributes()
140 .with_title("Winit window")
141 .with_transparent(true)
142 .with_window_icon(Some(self.icon.clone()));
143
144 #[cfg(any(x11_platform, wayland_platform))]
145 if let Some(token) = event_loop.read_token_from_env() {
146 startup_notify::reset_activation_token_env();
147 info!("Using token {:?} to activate a window", token);
148 window_attributes = window_attributes.with_activation_token(token);
149 }
150
151 #[cfg(macos_platform)]
152 if let Some(tab_id) = _tab_id {
153 window_attributes = window_attributes.with_tabbing_identifier(&tab_id);
154 }
155
156 #[cfg(web_platform)]
157 {
158 use rio_window::platform::web::WindowAttributesExtWebSys;
159 window_attributes = window_attributes.with_append(true);
160 }
161
162 let window = event_loop.create_window(window_attributes)?;
163
164 #[cfg(ios_platform)]
165 {
166 use rio_window::platform::ios::WindowExtIOS;
167 window.recognize_doubletap_gesture(true);
168 window.recognize_pinch_gesture(true);
169 window.recognize_rotation_gesture(true);
170 window.recognize_pan_gesture(true, 2, 2);
171 }
172
173 let window_state = WindowState::new(self, window)?;
174 let window_id = window_state.window.id();
175 info!("Created new window with id={window_id:?}");
176 self.windows.insert(window_id, window_state);
177 Ok(window_id)
178 }
Sourcepub fn id(&self) -> WindowId
pub fn id(&self) -> WindowId
Returns an identifier unique to the window.
Examples found in repository?
More examples
56 fn create_surface(
57 &mut self,
58 window: &Window,
59 ) -> &mut Surface<&'static Window, &'static Window> {
60 self.surfaces.entry(window.id()).or_insert_with(|| {
61 Surface::new(&self.context.borrow(), unsafe {
62 mem::transmute::<&'_ Window, &'static Window>(window)
63 })
64 .expect("Failed to create a softbuffer surface")
65 })
66 }
67
68 fn destroy_surface(&mut self, window: &Window) {
69 self.surfaces.remove(&window.id());
70 }
131 fn create_window(
132 &mut self,
133 event_loop: &ActiveEventLoop,
134 _tab_id: Option<String>,
135 ) -> Result<WindowId, Box<dyn Error>> {
136 // TODO read-out activation token.
137
138 #[allow(unused_mut)]
139 let mut window_attributes = Window::default_attributes()
140 .with_title("Winit window")
141 .with_transparent(true)
142 .with_window_icon(Some(self.icon.clone()));
143
144 #[cfg(any(x11_platform, wayland_platform))]
145 if let Some(token) = event_loop.read_token_from_env() {
146 startup_notify::reset_activation_token_env();
147 info!("Using token {:?} to activate a window", token);
148 window_attributes = window_attributes.with_activation_token(token);
149 }
150
151 #[cfg(macos_platform)]
152 if let Some(tab_id) = _tab_id {
153 window_attributes = window_attributes.with_tabbing_identifier(&tab_id);
154 }
155
156 #[cfg(web_platform)]
157 {
158 use rio_window::platform::web::WindowAttributesExtWebSys;
159 window_attributes = window_attributes.with_append(true);
160 }
161
162 let window = event_loop.create_window(window_attributes)?;
163
164 #[cfg(ios_platform)]
165 {
166 use rio_window::platform::ios::WindowExtIOS;
167 window.recognize_doubletap_gesture(true);
168 window.recognize_pinch_gesture(true);
169 window.recognize_rotation_gesture(true);
170 window.recognize_pan_gesture(true, 2, 2);
171 }
172
173 let window_state = WindowState::new(self, window)?;
174 let window_id = window_state.window.id();
175 info!("Created new window with id={window_id:?}");
176 self.windows.insert(window_id, window_state);
177 Ok(window_id)
178 }
179
180 fn handle_action(
181 &mut self,
182 event_loop: &ActiveEventLoop,
183 window_id: WindowId,
184 action: Action,
185 ) {
186 // let cursor_position = self.cursor_position;
187 let window = self.windows.get_mut(&window_id).unwrap();
188 info!("Executing action: {action:?}");
189 match action {
190 Action::CloseWindow => {
191 let _ = self.windows.remove(&window_id);
192 }
193 Action::CreateNewWindow => {
194 #[cfg(any(x11_platform, wayland_platform))]
195 if let Err(err) = window.window.request_activation_token() {
196 info!("Failed to get activation token: {err}");
197 } else {
198 return;
199 }
200
201 if let Err(err) = self.create_window(event_loop, None) {
202 error!("Error creating new window: {err}");
203 }
204 }
205 Action::ToggleResizeIncrements => window.toggle_resize_increments(),
206 Action::ToggleCursorVisibility => window.toggle_cursor_visibility(),
207 Action::ToggleResizable => window.toggle_resizable(),
208 Action::ToggleDecorations => window.toggle_decorations(),
209 Action::ToggleFullscreen => window.toggle_fullscreen(),
210 Action::ToggleMaximize => window.toggle_maximize(),
211 Action::ToggleImeInput => window.toggle_ime(),
212 Action::Minimize => window.minimize(),
213 Action::NextCursor => window.next_cursor(),
214 Action::NextCustomCursor => window.next_custom_cursor(&self.custom_cursors),
215 #[cfg(web_platform)]
216 Action::UrlCustomCursor => window.url_custom_cursor(event_loop),
217 #[cfg(web_platform)]
218 Action::AnimationCustomCursor => {
219 window.animation_custom_cursor(event_loop, &self.custom_cursors)
220 }
221 Action::CycleCursorGrab => window.cycle_cursor_grab(),
222 Action::DragWindow => window.drag_window(),
223 Action::DragResizeWindow => window.drag_resize_window(),
224 Action::ShowWindowMenu => window.show_menu(),
225 Action::PrintHelp => self.print_help(),
226 #[cfg(macos_platform)]
227 Action::CycleOptionAsAlt => window.cycle_option_as_alt(),
228 #[cfg(macos_platform)]
229 Action::CreateNewTab => {
230 let tab_id = window.window.tabbing_identifier();
231 if let Err(err) = self.create_window(event_loop, Some(tab_id)) {
232 error!("Error creating new window: {err}");
233 }
234 }
235 Action::RequestResize => window.swap_dimensions(),
236 }
237 }
238
239 fn dump_monitors(&self, event_loop: &ActiveEventLoop) {
240 info!("Monitors information");
241 let primary_monitor = event_loop.primary_monitor();
242 for monitor in event_loop.available_monitors() {
243 let intro = if primary_monitor.as_ref() == Some(&monitor) {
244 "Primary monitor"
245 } else {
246 "Monitor"
247 };
248
249 if let Some(name) = monitor.name() {
250 info!("{intro}: {name}");
251 } else {
252 info!("{intro}: [no name]");
253 }
254
255 let PhysicalSize { width, height } = monitor.size();
256 info!(
257 " Current mode: {width}x{height}{}",
258 if let Some(m_hz) = monitor.refresh_rate_millihertz() {
259 format!(" @ {}.{} Hz", m_hz / 1000, m_hz % 1000)
260 } else {
261 String::new()
262 }
263 );
264
265 let PhysicalPosition { x, y } = monitor.position();
266 info!(" Position: {x},{y}");
267
268 info!(" Scale factor: {}", monitor.scale_factor());
269
270 info!(" Available modes (width x height x bit-depth):");
271 for mode in monitor.video_modes() {
272 let PhysicalSize { width, height } = mode.size();
273 let bits = mode.bit_depth();
274 let m_hz = mode.refresh_rate_millihertz();
275 info!(
276 " {width}x{height}x{bits} @ {}.{} Hz",
277 m_hz / 1000,
278 m_hz % 1000
279 );
280 }
281 }
282 }
283
284 /// Process the key binding.
285 fn process_key_binding(key: &str, mods: &ModifiersState) -> Option<Action> {
286 KEY_BINDINGS.iter().find_map(|binding| {
287 binding
288 .is_triggered_by(&key, mods)
289 .then_some(binding.action)
290 })
291 }
292
293 /// Process mouse binding.
294 fn process_mouse_binding(
295 button: MouseButton,
296 mods: &ModifiersState,
297 ) -> Option<Action> {
298 MOUSE_BINDINGS.iter().find_map(|binding| {
299 binding
300 .is_triggered_by(&button, mods)
301 .then_some(binding.action)
302 })
303 }
304
305 fn print_help(&self) {
306 info!("Keyboard bindings:");
307 for binding in KEY_BINDINGS {
308 info!(
309 "{}{:<10} - {} ({})",
310 modifiers_to_string(binding.mods),
311 binding.trigger,
312 binding.action,
313 binding.action.help(),
314 );
315 }
316 info!("Mouse bindings:");
317 for binding in MOUSE_BINDINGS {
318 info!(
319 "{}{:<10} - {} ({})",
320 modifiers_to_string(binding.mods),
321 mouse_button_to_string(binding.trigger),
322 binding.action,
323 binding.action.help(),
324 );
325 }
326 }
327}
328
329impl ApplicationHandler<UserEvent> for Application {
330 fn user_event(&mut self, _event_loop: &ActiveEventLoop, event: UserEvent) {
331 info!("User event: {event:?}");
332 }
333
334 fn window_event(
335 &mut self,
336 event_loop: &ActiveEventLoop,
337 window_id: WindowId,
338 event: WindowEvent,
339 ) {
340 let window = match self.windows.get_mut(&window_id) {
341 Some(window) => window,
342 None => return,
343 };
344
345 match event {
346 WindowEvent::Resized(size) => {
347 window.resize(size);
348 }
349 WindowEvent::Focused(focused) => {
350 if focused {
351 info!("Window={window_id:?} focused");
352 } else {
353 info!("Window={window_id:?} unfocused");
354 }
355 }
356 WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
357 info!("Window={window_id:?} changed scale to {scale_factor}");
358 }
359 WindowEvent::ThemeChanged(theme) => {
360 info!("Theme changed to {theme:?}");
361 window.set_theme(theme);
362 }
363 WindowEvent::RedrawRequested => {
364 if let Err(err) = window.draw() {
365 error!("Error drawing window: {err}");
366 }
367 }
368 WindowEvent::Occluded(occluded) => {
369 window.set_occluded(occluded);
370 }
371 WindowEvent::CloseRequested => {
372 info!("Closing Window={window_id:?}");
373 self.windows.remove(&window_id);
374 }
375 WindowEvent::ModifiersChanged(modifiers) => {
376 window.modifiers = modifiers.state();
377 info!("Modifiers changed to {:?}", window.modifiers);
378 }
379 WindowEvent::MouseWheel { delta, .. } => match delta {
380 MouseScrollDelta::LineDelta(x, y) => {
381 info!("Mouse wheel Line Delta: ({x},{y})");
382 }
383 MouseScrollDelta::PixelDelta(px) => {
384 info!("Mouse wheel Pixel Delta: ({},{})", px.x, px.y);
385 }
386 },
387 WindowEvent::KeyboardInput {
388 event,
389 is_synthetic: false,
390 ..
391 } => {
392 let mods = window.modifiers;
393
394 // Dispatch actions only on press.
395 if event.state.is_pressed() {
396 let action = if let Key::Character(ch) = event.logical_key.as_ref() {
397 Self::process_key_binding(&ch.to_uppercase(), &mods)
398 } else {
399 None
400 };
401
402 if let Some(action) = action {
403 self.handle_action(event_loop, window_id, action);
404 }
405 }
406 }
407 WindowEvent::MouseInput { button, state, .. } => {
408 let mods = window.modifiers;
409 if let Some(action) = state
410 .is_pressed()
411 .then(|| Self::process_mouse_binding(button, &mods))
412 .flatten()
413 {
414 self.handle_action(event_loop, window_id, action);
415 }
416 }
417 WindowEvent::CursorLeft { .. } => {
418 info!("Cursor left Window={window_id:?}");
419 window.cursor_left();
420 }
421 WindowEvent::CursorMoved { position, .. } => {
422 info!("Moved cursor to {position:?}");
423 window.cursor_moved(position);
424 }
425 WindowEvent::ActivationTokenDone { token: _token, .. } => {
426 #[cfg(any(x11_platform, wayland_platform))]
427 {
428 startup_notify::set_activation_token_env(_token);
429 if let Err(err) = self.create_window(event_loop, None) {
430 error!("Error creating new window: {err}");
431 }
432 }
433 }
434 WindowEvent::Ime(event) => match event {
435 Ime::Enabled => info!("IME enabled for Window={window_id:?}"),
436 Ime::Preedit(text, caret_pos) => {
437 info!("Preedit: {}, with caret at {:?}", text, caret_pos);
438 }
439 Ime::Commit(text) => {
440 info!("Committed: {}", text);
441 }
442 Ime::Disabled => info!("IME disabled for Window={window_id:?}"),
443 },
444 WindowEvent::PinchGesture { delta, .. } => {
445 window.zoom += delta;
446 let zoom = window.zoom;
447 if delta > 0.0 {
448 info!("Zoomed in {delta:.5} (now: {zoom:.5})");
449 } else {
450 info!("Zoomed out {delta:.5} (now: {zoom:.5})");
451 }
452 }
453 WindowEvent::RotationGesture { delta, .. } => {
454 window.rotated += delta;
455 let rotated = window.rotated;
456 if delta > 0.0 {
457 info!("Rotated counterclockwise {delta:.5} (now: {rotated:.5})");
458 } else {
459 info!("Rotated clockwise {delta:.5} (now: {rotated:.5})");
460 }
461 }
462 WindowEvent::PanGesture { delta, phase, .. } => {
463 window.panned.x += delta.x;
464 window.panned.y += delta.y;
465 info!("Panned ({delta:?})) (now: {:?}), {phase:?}", window.panned);
466 }
467 WindowEvent::DoubleTapGesture { .. } => {
468 info!("Smart zoom");
469 }
470 WindowEvent::TouchpadPressure { .. }
471 | WindowEvent::HoveredFileCancelled
472 | WindowEvent::KeyboardInput { .. }
473 | WindowEvent::CursorEntered { .. }
474 | WindowEvent::AxisMotion { .. }
475 | WindowEvent::DroppedFile(_)
476 | WindowEvent::HoveredFile(_)
477 | WindowEvent::Destroyed
478 | WindowEvent::Touch(_)
479 | WindowEvent::Moved(_) => (),
480 }
481 }
482
483 fn device_event(
484 &mut self,
485 _event_loop: &ActiveEventLoop,
486 device_id: DeviceId,
487 event: DeviceEvent,
488 ) {
489 info!("Device {device_id:?} event: {event:?}");
490 }
491
492 fn resumed(&mut self, event_loop: &ActiveEventLoop) {
493 info!("Resumed the event loop");
494 self.dump_monitors(event_loop);
495
496 // Create initial window.
497 self.create_window(event_loop, None)
498 .expect("failed to create initial window");
499
500 self.print_help();
501 }
502
503 fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
504 if self.windows.is_empty() {
505 info!("No windows left, exiting...");
506 event_loop.exit();
507 }
508 }
509
510 #[cfg(not(any(android_platform, ios_platform)))]
511 fn exiting(&mut self, _event_loop: &ActiveEventLoop) {
512 // We must drop the context here.
513 self.context = None;
514 }
515}
516
517/// State of the window.
518struct WindowState {
519 /// IME input.
520 ime: bool,
521 /// Render surface.
522 ///
523 /// NOTE: This surface must be dropped before the `Window`.
524 #[cfg(not(any(android_platform, ios_platform)))]
525 surface: Surface<DisplayHandle<'static>, Arc<Window>>,
526 /// The actual winit Window.
527 window: Arc<Window>,
528 /// The window theme we're drawing with.
529 theme: Theme,
530 /// Cursor position over the window.
531 cursor_position: Option<PhysicalPosition<f64>>,
532 /// Window modifiers state.
533 modifiers: ModifiersState,
534 /// Occlusion state of the window.
535 occluded: bool,
536 /// Current cursor grab mode.
537 cursor_grab: CursorGrabMode,
538 /// The amount of zoom into window.
539 zoom: f64,
540 /// The amount of rotation of the window.
541 rotated: f32,
542 /// The amount of pan of the window.
543 panned: PhysicalPosition<f32>,
544
545 #[cfg(macos_platform)]
546 option_as_alt: OptionAsAlt,
547
548 // Cursor states.
549 named_idx: usize,
550 custom_idx: usize,
551 cursor_hidden: bool,
552}
553
554impl WindowState {
555 fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
556 let window = Arc::new(window);
557
558 // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
559 // it doesn't outlive it.
560 #[cfg(not(any(android_platform, ios_platform)))]
561 let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
562
563 let theme = window.theme().unwrap_or(Theme::Dark);
564 info!("Theme: {theme:?}");
565 let named_idx = 0;
566 window.set_cursor(CURSORS[named_idx]);
567
568 // Allow IME out of the box.
569 let ime = true;
570 window.set_ime_allowed(ime);
571
572 let size = window.inner_size();
573 let mut state = Self {
574 #[cfg(macos_platform)]
575 option_as_alt: window.option_as_alt(),
576 custom_idx: app.custom_cursors.len() - 1,
577 cursor_grab: CursorGrabMode::None,
578 named_idx,
579 #[cfg(not(any(android_platform, ios_platform)))]
580 surface,
581 window,
582 theme,
583 ime,
584 cursor_position: Default::default(),
585 cursor_hidden: Default::default(),
586 modifiers: Default::default(),
587 occluded: Default::default(),
588 rotated: Default::default(),
589 panned: Default::default(),
590 zoom: Default::default(),
591 };
592
593 state.resize(size);
594 Ok(state)
595 }
596
597 pub fn toggle_ime(&mut self) {
598 self.ime = !self.ime;
599 self.window.set_ime_allowed(self.ime);
600 if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
601 self.window
602 .set_ime_cursor_area(position, PhysicalSize::new(20, 20));
603 }
604 }
605
606 pub fn minimize(&mut self) {
607 self.window.set_minimized(true);
608 }
609
610 pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) {
611 self.cursor_position = Some(position);
612 if self.ime {
613 self.window
614 .set_ime_cursor_area(position, PhysicalSize::new(20, 20));
615 }
616 }
617
618 pub fn cursor_left(&mut self) {
619 self.cursor_position = None;
620 }
621
622 /// Toggle maximized.
623 fn toggle_maximize(&self) {
624 let maximized = self.window.is_maximized();
625 self.window.set_maximized(!maximized);
626 }
627
628 /// Toggle window decorations.
629 fn toggle_decorations(&self) {
630 let decorated = self.window.is_decorated();
631 self.window.set_decorations(!decorated);
632 }
633
634 /// Toggle window resizable state.
635 fn toggle_resizable(&self) {
636 let resizable = self.window.is_resizable();
637 self.window.set_resizable(!resizable);
638 }
639
640 /// Toggle cursor visibility
641 fn toggle_cursor_visibility(&mut self) {
642 self.cursor_hidden = !self.cursor_hidden;
643 self.window.set_cursor_visible(!self.cursor_hidden);
644 }
645
646 /// Toggle resize increments on a window.
647 fn toggle_resize_increments(&mut self) {
648 let new_increments = match self.window.resize_increments() {
649 Some(_) => None,
650 None => Some(LogicalSize::new(25.0, 25.0)),
651 };
652 info!("Had increments: {}", new_increments.is_none());
653 self.window.set_resize_increments(new_increments);
654 }
655
656 /// Toggle fullscreen.
657 fn toggle_fullscreen(&self) {
658 let fullscreen = if self.window.fullscreen().is_some() {
659 None
660 } else {
661 Some(Fullscreen::Borderless(None))
662 };
663
664 self.window.set_fullscreen(fullscreen);
665 }
666
667 /// Cycle through the grab modes ignoring errors.
668 fn cycle_cursor_grab(&mut self) {
669 self.cursor_grab = match self.cursor_grab {
670 CursorGrabMode::None => CursorGrabMode::Confined,
671 CursorGrabMode::Confined => CursorGrabMode::Locked,
672 CursorGrabMode::Locked => CursorGrabMode::None,
673 };
674 info!("Changing cursor grab mode to {:?}", self.cursor_grab);
675 if let Err(err) = self.window.set_cursor_grab(self.cursor_grab) {
676 error!("Error setting cursor grab: {err}");
677 }
678 }
679
680 #[cfg(macos_platform)]
681 fn cycle_option_as_alt(&mut self) {
682 self.option_as_alt = match self.option_as_alt {
683 OptionAsAlt::None => OptionAsAlt::OnlyLeft,
684 OptionAsAlt::OnlyLeft => OptionAsAlt::OnlyRight,
685 OptionAsAlt::OnlyRight => OptionAsAlt::Both,
686 OptionAsAlt::Both => OptionAsAlt::None,
687 };
688 info!("Setting option as alt {:?}", self.option_as_alt);
689 self.window.set_option_as_alt(self.option_as_alt);
690 }
691
692 /// Swap the window dimensions with `request_inner_size`.
693 fn swap_dimensions(&mut self) {
694 let old_inner_size = self.window.inner_size();
695 let mut inner_size = old_inner_size;
696
697 mem::swap(&mut inner_size.width, &mut inner_size.height);
698 info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
699
700 if let Some(new_inner_size) = self.window.request_inner_size(inner_size) {
701 if old_inner_size == new_inner_size {
702 info!("Inner size change got ignored");
703 } else {
704 self.resize(new_inner_size);
705 }
706 } else {
707 info!("Request inner size is asynchronous");
708 }
709 }
710
711 /// Pick the next cursor.
712 fn next_cursor(&mut self) {
713 self.named_idx = (self.named_idx + 1) % CURSORS.len();
714 info!("Setting cursor to \"{:?}\"", CURSORS[self.named_idx]);
715 self.window
716 .set_cursor(Cursor::Icon(CURSORS[self.named_idx]));
717 }
718
719 /// Pick the next custom cursor.
720 fn next_custom_cursor(&mut self, custom_cursors: &[CustomCursor]) {
721 self.custom_idx = (self.custom_idx + 1) % custom_cursors.len();
722 let cursor = Cursor::Custom(custom_cursors[self.custom_idx].clone());
723 self.window.set_cursor(cursor);
724 }
725
726 /// Custom cursor from an URL.
727 #[cfg(web_platform)]
728 fn url_custom_cursor(&mut self, event_loop: &ActiveEventLoop) {
729 let cursor = event_loop.create_custom_cursor(url_custom_cursor());
730
731 self.window.set_cursor(cursor);
732 }
733
734 /// Custom cursor from a URL.
735 #[cfg(web_platform)]
736 fn animation_custom_cursor(
737 &mut self,
738 event_loop: &ActiveEventLoop,
739 custom_cursors: &[CustomCursor],
740 ) {
741 use rio_window::platform::web::CustomCursorExtWebSys;
742 use std::time::Duration;
743
744 let cursors = vec![
745 custom_cursors[0].clone(),
746 custom_cursors[1].clone(),
747 event_loop.create_custom_cursor(url_custom_cursor()),
748 ];
749 let cursor =
750 CustomCursor::from_animation(Duration::from_secs(3), cursors).unwrap();
751 let cursor = event_loop.create_custom_cursor(cursor);
752
753 self.window.set_cursor(cursor);
754 }
755
756 /// Resize the window to the new size.
757 fn resize(&mut self, size: PhysicalSize<u32>) {
758 info!("Resized to {size:?}");
759 #[cfg(not(any(android_platform, ios_platform)))]
760 {
761 let (width, height) =
762 match (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) {
763 (Some(width), Some(height)) => (width, height),
764 _ => return,
765 };
766 self.surface
767 .resize(width, height)
768 .expect("failed to resize inner buffer");
769 }
770 self.window.request_redraw();
771 }
772
773 /// Change the theme.
774 fn set_theme(&mut self, theme: Theme) {
775 self.theme = theme;
776 self.window.request_redraw();
777 }
778
779 /// Show window menu.
780 fn show_menu(&self) {
781 if let Some(position) = self.cursor_position {
782 self.window.show_window_menu(position);
783 }
784 }
785
786 /// Drag the window.
787 fn drag_window(&self) {
788 if let Err(err) = self.window.drag_window() {
789 info!("Error starting window drag: {err}");
790 } else {
791 info!("Dragging window Window={:?}", self.window.id());
792 }
793 }
794
795 /// Drag-resize the window.
796 fn drag_resize_window(&self) {
797 let position = match self.cursor_position {
798 Some(position) => position,
799 None => {
800 info!("Drag-resize requires cursor to be inside the window");
801 return;
802 }
803 };
804
805 let win_size = self.window.inner_size();
806 let border_size = BORDER_SIZE * self.window.scale_factor();
807
808 let x_direction = if position.x < border_size {
809 ResizeDirection::West
810 } else if position.x > (win_size.width as f64 - border_size) {
811 ResizeDirection::East
812 } else {
813 // Use arbitrary direction instead of None for simplicity.
814 ResizeDirection::SouthEast
815 };
816
817 let y_direction = if position.y < border_size {
818 ResizeDirection::North
819 } else if position.y > (win_size.height as f64 - border_size) {
820 ResizeDirection::South
821 } else {
822 // Use arbitrary direction instead of None for simplicity.
823 ResizeDirection::SouthEast
824 };
825
826 let direction = match (x_direction, y_direction) {
827 (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest,
828 (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest,
829 (ResizeDirection::West, _) => ResizeDirection::West,
830 (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast,
831 (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast,
832 (ResizeDirection::East, _) => ResizeDirection::East,
833 (_, ResizeDirection::South) => ResizeDirection::South,
834 (_, ResizeDirection::North) => ResizeDirection::North,
835 _ => return,
836 };
837
838 if let Err(err) = self.window.drag_resize_window(direction) {
839 info!("Error starting window drag-resize: {err}");
840 } else {
841 info!("Drag-resizing window Window={:?}", self.window.id());
842 }
843 }
844
845 /// Change window occlusion state.
846 fn set_occluded(&mut self, occluded: bool) {
847 self.occluded = occluded;
848 if !occluded {
849 self.window.request_redraw();
850 }
851 }
852
853 /// Draw the window contents.
854 #[cfg(not(any(android_platform, ios_platform)))]
855 fn draw(&mut self) -> Result<(), Box<dyn Error>> {
856 if self.occluded {
857 info!("Skipping drawing occluded window={:?}", self.window.id());
858 return Ok(());
859 }
860
861 const WHITE: u32 = 0xffffffff;
862 const DARK_GRAY: u32 = 0xff181818;
863
864 let color = match self.theme {
865 Theme::Light => WHITE,
866 Theme::Dark => DARK_GRAY,
867 };
868
869 let mut buffer = self.surface.buffer_mut()?;
870 buffer.fill(color);
871 self.window.pre_present_notify();
872 buffer.present()?;
873 Ok(())
874 }
3fn main() -> Result<(), impl std::error::Error> {
4 use std::collections::HashMap;
5
6 use rio_window::dpi::{LogicalPosition, LogicalSize, Position};
7 use rio_window::event::{ElementState, Event, KeyEvent, WindowEvent};
8 use rio_window::event_loop::{ActiveEventLoop, EventLoop};
9 use rio_window::raw_window_handle::HasRawWindowHandle;
10 use rio_window::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:
62 KeyEvent {
63 state: ElementState::Pressed,
64 ..
65 },
66 ..
67 } => {
68 let parent_window = windows.get(&parent_window_id.unwrap()).unwrap();
69 let child_window = spawn_child_window(parent_window, event_loop);
70 let child_id = child_window.id();
71 println!("Child window created with id: {child_id:?}");
72 windows.insert(child_id, child_window);
73 }
74 WindowEvent::RedrawRequested => {
75 if let Some(window) = windows.get(&window_id) {
76 fill::fill_window(window);
77 }
78 }
79 _ => (),
80 },
81 _ => (),
82 }
83 })
84}
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_FACTOR
environment variable if present. - If not present, use the value set in
Xft.dpi
in Xresources. - Otherwise, calculate the scale factor based on the millimeter monitor dimensions provided by XRandR.
If
WINIT_X11_SCALE_FACTOR
is set torandr
, it’ll ignore theXft.dpi
field 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.0
to3.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.0
to4.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?
796 fn drag_resize_window(&self) {
797 let position = match self.cursor_position {
798 Some(position) => position,
799 None => {
800 info!("Drag-resize requires cursor to be inside the window");
801 return;
802 }
803 };
804
805 let win_size = self.window.inner_size();
806 let border_size = BORDER_SIZE * self.window.scale_factor();
807
808 let x_direction = if position.x < border_size {
809 ResizeDirection::West
810 } else if position.x > (win_size.width as f64 - border_size) {
811 ResizeDirection::East
812 } else {
813 // Use arbitrary direction instead of None for simplicity.
814 ResizeDirection::SouthEast
815 };
816
817 let y_direction = if position.y < border_size {
818 ResizeDirection::North
819 } else if position.y > (win_size.height as f64 - border_size) {
820 ResizeDirection::South
821 } else {
822 // Use arbitrary direction instead of None for simplicity.
823 ResizeDirection::SouthEast
824 };
825
826 let direction = match (x_direction, y_direction) {
827 (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest,
828 (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest,
829 (ResizeDirection::West, _) => ResizeDirection::West,
830 (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast,
831 (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast,
832 (ResizeDirection::East, _) => ResizeDirection::East,
833 (_, ResizeDirection::South) => ResizeDirection::South,
834 (_, ResizeDirection::North) => ResizeDirection::North,
835 _ => return,
836 };
837
838 if let Err(err) = self.window.drag_resize_window(direction) {
839 info!("Error starting window drag-resize: {err}");
840 } else {
841 info!("Drag-resizing window Window={:?}", self.window.id());
842 }
843 }
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
RedrawWindow
to request aWM_PAINT
message andRedrawRequested
is emitted in sync with anyWM_PAINT
messages. - iOS: Can only be called on the main thread.
- Wayland: The events are aligned with the frame callbacks when
Window::pre_present_notify
is used. - Web:
WindowEvent::RedrawRequested
will be aligned with therequestAnimationFrame
.
Examples found in repository?
More examples
757 fn resize(&mut self, size: PhysicalSize<u32>) {
758 info!("Resized to {size:?}");
759 #[cfg(not(any(android_platform, ios_platform)))]
760 {
761 let (width, height) =
762 match (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) {
763 (Some(width), Some(height)) => (width, height),
764 _ => return,
765 };
766 self.surface
767 .resize(width, height)
768 .expect("failed to resize inner buffer");
769 }
770 self.window.request_redraw();
771 }
772
773 /// Change the theme.
774 fn set_theme(&mut self, theme: Theme) {
775 self.theme = theme;
776 self.window.request_redraw();
777 }
778
779 /// Show window menu.
780 fn show_menu(&self) {
781 if let Some(position) = self.cursor_position {
782 self.window.show_window_menu(position);
783 }
784 }
785
786 /// Drag the window.
787 fn drag_window(&self) {
788 if let Err(err) = self.window.drag_window() {
789 info!("Error starting window drag: {err}");
790 } else {
791 info!("Dragging window Window={:?}", self.window.id());
792 }
793 }
794
795 /// Drag-resize the window.
796 fn drag_resize_window(&self) {
797 let position = match self.cursor_position {
798 Some(position) => position,
799 None => {
800 info!("Drag-resize requires cursor to be inside the window");
801 return;
802 }
803 };
804
805 let win_size = self.window.inner_size();
806 let border_size = BORDER_SIZE * self.window.scale_factor();
807
808 let x_direction = if position.x < border_size {
809 ResizeDirection::West
810 } else if position.x > (win_size.width as f64 - border_size) {
811 ResizeDirection::East
812 } else {
813 // Use arbitrary direction instead of None for simplicity.
814 ResizeDirection::SouthEast
815 };
816
817 let y_direction = if position.y < border_size {
818 ResizeDirection::North
819 } else if position.y > (win_size.height as f64 - border_size) {
820 ResizeDirection::South
821 } else {
822 // Use arbitrary direction instead of None for simplicity.
823 ResizeDirection::SouthEast
824 };
825
826 let direction = match (x_direction, y_direction) {
827 (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest,
828 (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest,
829 (ResizeDirection::West, _) => ResizeDirection::West,
830 (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast,
831 (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast,
832 (ResizeDirection::East, _) => ResizeDirection::East,
833 (_, ResizeDirection::South) => ResizeDirection::South,
834 (_, ResizeDirection::North) => ResizeDirection::North,
835 _ => return,
836 };
837
838 if let Err(err) = self.window.drag_resize_window(direction) {
839 info!("Error starting window drag-resize: {err}");
840 } else {
841 info!("Drag-resizing window Window={:?}", self.window.id());
842 }
843 }
844
845 /// Change window occlusion state.
846 fn set_occluded(&mut self, occluded: bool) {
847 self.occluded = occluded;
848 if !occluded {
849 self.window.request_redraw();
850 }
851 }
37 fn window_event(
38 &mut self,
39 event_loop: &ActiveEventLoop,
40 _window_id: WindowId,
41 event: WindowEvent,
42 ) {
43 println!("{event:?}");
44
45 let window = match self.window.as_ref() {
46 Some(window) => window,
47 None => return,
48 };
49
50 match event {
51 WindowEvent::CloseRequested => event_loop.exit(),
52 WindowEvent::RedrawRequested => {
53 fill::fill_window(window);
54 window.request_redraw();
55 }
56 _ => (),
57 }
58 }
130 fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
131 if self.request_redraw && !self.wait_cancelled && !self.close_requested {
132 self.window.as_ref().unwrap().request_redraw();
133 }
134
135 match self.mode {
136 Mode::Wait => event_loop.set_control_flow(ControlFlow::Wait),
137 Mode::WaitUntil => {
138 if !self.wait_cancelled {
139 event_loop.set_control_flow(ControlFlow::WaitUntil(
140 time::Instant::now() + WAIT_TIME,
141 ));
142 }
143 }
144 Mode::Poll => {
145 thread::sleep(POLL_SLEEP_TIME);
146 event_loop.set_control_flow(ControlFlow::Poll);
147 }
148 };
149
150 if self.close_requested {
151 event_loop.exit();
152 }
153 }
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?
30 fn window_event(
31 &mut self,
32 event_loop: &ActiveEventLoop,
33 _window_id: WindowId,
34 event: WindowEvent,
35 ) {
36 let window = self.window.as_ref().unwrap();
37 match event {
38 WindowEvent::CloseRequested => event_loop.exit(),
39 WindowEvent::RedrawRequested => {
40 window.pre_present_notify();
41 fill::fill_window(window);
42 }
43 _ => (),
44 }
45 }
More examples
855 fn draw(&mut self) -> Result<(), Box<dyn Error>> {
856 if self.occluded {
857 info!("Skipping drawing occluded window={:?}", self.window.id());
858 return Ok(());
859 }
860
861 const WHITE: u32 = 0xffffffff;
862 const DARK_GRAY: u32 = 0xff181818;
863
864 let color = match self.theme {
865 Theme::Light => WHITE,
866 Theme::Dark => DARK_GRAY,
867 };
868
869 let mut buffer = self.surface.buffer_mut()?;
870 buffer.fill(color);
871 self.window.pre_present_notify();
872 buffer.present()?;
873 Ok(())
874 }
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:
91 KeyEvent {
92 logical_key: key,
93 state: ElementState::Pressed,
94 ..
95 },
96 ..
97 } => match key.as_ref() {
98 // WARNING: Consider using `key_without_modifiers()` if available on your platform.
99 // See the `key_binding` example
100 Key::Character("1") => {
101 self.mode = Mode::Wait;
102 warn!("mode: {:?}", self.mode);
103 }
104 Key::Character("2") => {
105 self.mode = Mode::WaitUntil;
106 warn!("mode: {:?}", self.mode);
107 }
108 Key::Character("3") => {
109 self.mode = Mode::Poll;
110 warn!("mode: {:?}", self.mode);
111 }
112 Key::Character("r") => {
113 self.request_redraw = !self.request_redraw;
114 warn!("request_redraw: {}", self.request_redraw);
115 }
116 Key::Named(NamedKey::Escape) => {
117 self.close_requested = true;
118 }
119 _ => (),
120 },
121 WindowEvent::RedrawRequested => {
122 let window = self.window.as_ref().unwrap();
123 window.pre_present_notify();
124 fill::fill_window(window);
125 }
126 _ => (),
127 }
128 }
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?
73 pub fn fill_window(window: &Window) {
74 GC.with(|gc| {
75 let size = window.inner_size();
76 let (Some(width), Some(height)) =
77 (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
78 else {
79 return;
80 };
81
82 // Either get the last context used or create a new one.
83 let mut gc = gc.borrow_mut();
84 let surface = gc
85 .get_or_insert_with(|| GraphicsContext::new(window))
86 .create_surface(window);
87
88 // Fill a buffer with a solid color.
89 const DARK_GRAY: u32 = 0xff181818;
90
91 surface
92 .resize(width, height)
93 .expect("Failed to resize the softbuffer surface");
94
95 let mut buffer = surface
96 .buffer_mut()
97 .expect("Failed to get the softbuffer buffer");
98 buffer.fill(DARK_GRAY);
99 buffer
100 .present()
101 .expect("Failed to present the softbuffer buffer");
102 })
103 }
More examples
555 fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
556 let window = Arc::new(window);
557
558 // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
559 // it doesn't outlive it.
560 #[cfg(not(any(android_platform, ios_platform)))]
561 let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
562
563 let theme = window.theme().unwrap_or(Theme::Dark);
564 info!("Theme: {theme:?}");
565 let named_idx = 0;
566 window.set_cursor(CURSORS[named_idx]);
567
568 // Allow IME out of the box.
569 let ime = true;
570 window.set_ime_allowed(ime);
571
572 let size = window.inner_size();
573 let mut state = Self {
574 #[cfg(macos_platform)]
575 option_as_alt: window.option_as_alt(),
576 custom_idx: app.custom_cursors.len() - 1,
577 cursor_grab: CursorGrabMode::None,
578 named_idx,
579 #[cfg(not(any(android_platform, ios_platform)))]
580 surface,
581 window,
582 theme,
583 ime,
584 cursor_position: Default::default(),
585 cursor_hidden: Default::default(),
586 modifiers: Default::default(),
587 occluded: Default::default(),
588 rotated: Default::default(),
589 panned: Default::default(),
590 zoom: Default::default(),
591 };
592
593 state.resize(size);
594 Ok(state)
595 }
596
597 pub fn toggle_ime(&mut self) {
598 self.ime = !self.ime;
599 self.window.set_ime_allowed(self.ime);
600 if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
601 self.window
602 .set_ime_cursor_area(position, PhysicalSize::new(20, 20));
603 }
604 }
605
606 pub fn minimize(&mut self) {
607 self.window.set_minimized(true);
608 }
609
610 pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) {
611 self.cursor_position = Some(position);
612 if self.ime {
613 self.window
614 .set_ime_cursor_area(position, PhysicalSize::new(20, 20));
615 }
616 }
617
618 pub fn cursor_left(&mut self) {
619 self.cursor_position = None;
620 }
621
622 /// Toggle maximized.
623 fn toggle_maximize(&self) {
624 let maximized = self.window.is_maximized();
625 self.window.set_maximized(!maximized);
626 }
627
628 /// Toggle window decorations.
629 fn toggle_decorations(&self) {
630 let decorated = self.window.is_decorated();
631 self.window.set_decorations(!decorated);
632 }
633
634 /// Toggle window resizable state.
635 fn toggle_resizable(&self) {
636 let resizable = self.window.is_resizable();
637 self.window.set_resizable(!resizable);
638 }
639
640 /// Toggle cursor visibility
641 fn toggle_cursor_visibility(&mut self) {
642 self.cursor_hidden = !self.cursor_hidden;
643 self.window.set_cursor_visible(!self.cursor_hidden);
644 }
645
646 /// Toggle resize increments on a window.
647 fn toggle_resize_increments(&mut self) {
648 let new_increments = match self.window.resize_increments() {
649 Some(_) => None,
650 None => Some(LogicalSize::new(25.0, 25.0)),
651 };
652 info!("Had increments: {}", new_increments.is_none());
653 self.window.set_resize_increments(new_increments);
654 }
655
656 /// Toggle fullscreen.
657 fn toggle_fullscreen(&self) {
658 let fullscreen = if self.window.fullscreen().is_some() {
659 None
660 } else {
661 Some(Fullscreen::Borderless(None))
662 };
663
664 self.window.set_fullscreen(fullscreen);
665 }
666
667 /// Cycle through the grab modes ignoring errors.
668 fn cycle_cursor_grab(&mut self) {
669 self.cursor_grab = match self.cursor_grab {
670 CursorGrabMode::None => CursorGrabMode::Confined,
671 CursorGrabMode::Confined => CursorGrabMode::Locked,
672 CursorGrabMode::Locked => CursorGrabMode::None,
673 };
674 info!("Changing cursor grab mode to {:?}", self.cursor_grab);
675 if let Err(err) = self.window.set_cursor_grab(self.cursor_grab) {
676 error!("Error setting cursor grab: {err}");
677 }
678 }
679
680 #[cfg(macos_platform)]
681 fn cycle_option_as_alt(&mut self) {
682 self.option_as_alt = match self.option_as_alt {
683 OptionAsAlt::None => OptionAsAlt::OnlyLeft,
684 OptionAsAlt::OnlyLeft => OptionAsAlt::OnlyRight,
685 OptionAsAlt::OnlyRight => OptionAsAlt::Both,
686 OptionAsAlt::Both => OptionAsAlt::None,
687 };
688 info!("Setting option as alt {:?}", self.option_as_alt);
689 self.window.set_option_as_alt(self.option_as_alt);
690 }
691
692 /// Swap the window dimensions with `request_inner_size`.
693 fn swap_dimensions(&mut self) {
694 let old_inner_size = self.window.inner_size();
695 let mut inner_size = old_inner_size;
696
697 mem::swap(&mut inner_size.width, &mut inner_size.height);
698 info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
699
700 if let Some(new_inner_size) = self.window.request_inner_size(inner_size) {
701 if old_inner_size == new_inner_size {
702 info!("Inner size change got ignored");
703 } else {
704 self.resize(new_inner_size);
705 }
706 } else {
707 info!("Request inner size is asynchronous");
708 }
709 }
710
711 /// Pick the next cursor.
712 fn next_cursor(&mut self) {
713 self.named_idx = (self.named_idx + 1) % CURSORS.len();
714 info!("Setting cursor to \"{:?}\"", CURSORS[self.named_idx]);
715 self.window
716 .set_cursor(Cursor::Icon(CURSORS[self.named_idx]));
717 }
718
719 /// Pick the next custom cursor.
720 fn next_custom_cursor(&mut self, custom_cursors: &[CustomCursor]) {
721 self.custom_idx = (self.custom_idx + 1) % custom_cursors.len();
722 let cursor = Cursor::Custom(custom_cursors[self.custom_idx].clone());
723 self.window.set_cursor(cursor);
724 }
725
726 /// Custom cursor from an URL.
727 #[cfg(web_platform)]
728 fn url_custom_cursor(&mut self, event_loop: &ActiveEventLoop) {
729 let cursor = event_loop.create_custom_cursor(url_custom_cursor());
730
731 self.window.set_cursor(cursor);
732 }
733
734 /// Custom cursor from a URL.
735 #[cfg(web_platform)]
736 fn animation_custom_cursor(
737 &mut self,
738 event_loop: &ActiveEventLoop,
739 custom_cursors: &[CustomCursor],
740 ) {
741 use rio_window::platform::web::CustomCursorExtWebSys;
742 use std::time::Duration;
743
744 let cursors = vec![
745 custom_cursors[0].clone(),
746 custom_cursors[1].clone(),
747 event_loop.create_custom_cursor(url_custom_cursor()),
748 ];
749 let cursor =
750 CustomCursor::from_animation(Duration::from_secs(3), cursors).unwrap();
751 let cursor = event_loop.create_custom_cursor(cursor);
752
753 self.window.set_cursor(cursor);
754 }
755
756 /// Resize the window to the new size.
757 fn resize(&mut self, size: PhysicalSize<u32>) {
758 info!("Resized to {size:?}");
759 #[cfg(not(any(android_platform, ios_platform)))]
760 {
761 let (width, height) =
762 match (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) {
763 (Some(width), Some(height)) => (width, height),
764 _ => return,
765 };
766 self.surface
767 .resize(width, height)
768 .expect("failed to resize inner buffer");
769 }
770 self.window.request_redraw();
771 }
772
773 /// Change the theme.
774 fn set_theme(&mut self, theme: Theme) {
775 self.theme = theme;
776 self.window.request_redraw();
777 }
778
779 /// Show window menu.
780 fn show_menu(&self) {
781 if let Some(position) = self.cursor_position {
782 self.window.show_window_menu(position);
783 }
784 }
785
786 /// Drag the window.
787 fn drag_window(&self) {
788 if let Err(err) = self.window.drag_window() {
789 info!("Error starting window drag: {err}");
790 } else {
791 info!("Dragging window Window={:?}", self.window.id());
792 }
793 }
794
795 /// Drag-resize the window.
796 fn drag_resize_window(&self) {
797 let position = match self.cursor_position {
798 Some(position) => position,
799 None => {
800 info!("Drag-resize requires cursor to be inside the window");
801 return;
802 }
803 };
804
805 let win_size = self.window.inner_size();
806 let border_size = BORDER_SIZE * self.window.scale_factor();
807
808 let x_direction = if position.x < border_size {
809 ResizeDirection::West
810 } else if position.x > (win_size.width as f64 - border_size) {
811 ResizeDirection::East
812 } else {
813 // Use arbitrary direction instead of None for simplicity.
814 ResizeDirection::SouthEast
815 };
816
817 let y_direction = if position.y < border_size {
818 ResizeDirection::North
819 } else if position.y > (win_size.height as f64 - border_size) {
820 ResizeDirection::South
821 } else {
822 // Use arbitrary direction instead of None for simplicity.
823 ResizeDirection::SouthEast
824 };
825
826 let direction = match (x_direction, y_direction) {
827 (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest,
828 (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest,
829 (ResizeDirection::West, _) => ResizeDirection::West,
830 (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast,
831 (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast,
832 (ResizeDirection::East, _) => ResizeDirection::East,
833 (_, ResizeDirection::South) => ResizeDirection::South,
834 (_, ResizeDirection::North) => ResizeDirection::North,
835 _ => return,
836 };
837
838 if let Err(err) = self.window.drag_resize_window(direction) {
839 info!("Error starting window drag-resize: {err}");
840 } else {
841 info!("Drag-resizing window Window={:?}", self.window.id());
842 }
843 }
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?
693 fn swap_dimensions(&mut self) {
694 let old_inner_size = self.window.inner_size();
695 let mut inner_size = old_inner_size;
696
697 mem::swap(&mut inner_size.width, &mut inner_size.height);
698 info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
699
700 if let Some(new_inner_size) = self.window.request_inner_size(inner_size) {
701 if old_inner_size == new_inner_size {
702 info!("Inner size change got ignored");
703 } else {
704 self.resize(new_inner_size);
705 }
706 } else {
707 info!("Request inner size is asynchronous");
708 }
709 }
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
PhysicalSize
of 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::Exclusive
provides 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::Borderless
provides a borderless fullscreen window on a separate space. This is the idiomatic way for fullscreen games to work on macOS. SeeWindowExtMacOs::set_simple_fullscreen
if 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
None
orBorderless(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?
597 pub fn toggle_ime(&mut self) {
598 self.ime = !self.ime;
599 self.window.set_ime_allowed(self.ime);
600 if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
601 self.window
602 .set_ime_cursor_area(position, PhysicalSize::new(20, 20));
603 }
604 }
605
606 pub fn minimize(&mut self) {
607 self.window.set_minimized(true);
608 }
609
610 pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) {
611 self.cursor_position = Some(position);
612 if self.ime {
613 self.window
614 .set_ime_cursor_area(position, PhysicalSize::new(20, 20));
615 }
616 }
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?
555 fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
556 let window = Arc::new(window);
557
558 // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
559 // it doesn't outlive it.
560 #[cfg(not(any(android_platform, ios_platform)))]
561 let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
562
563 let theme = window.theme().unwrap_or(Theme::Dark);
564 info!("Theme: {theme:?}");
565 let named_idx = 0;
566 window.set_cursor(CURSORS[named_idx]);
567
568 // Allow IME out of the box.
569 let ime = true;
570 window.set_ime_allowed(ime);
571
572 let size = window.inner_size();
573 let mut state = Self {
574 #[cfg(macos_platform)]
575 option_as_alt: window.option_as_alt(),
576 custom_idx: app.custom_cursors.len() - 1,
577 cursor_grab: CursorGrabMode::None,
578 named_idx,
579 #[cfg(not(any(android_platform, ios_platform)))]
580 surface,
581 window,
582 theme,
583 ime,
584 cursor_position: Default::default(),
585 cursor_hidden: Default::default(),
586 modifiers: Default::default(),
587 occluded: Default::default(),
588 rotated: Default::default(),
589 panned: Default::default(),
590 zoom: Default::default(),
591 };
592
593 state.resize(size);
594 Ok(state)
595 }
596
597 pub fn toggle_ime(&mut self) {
598 self.ime = !self.ime;
599 self.window.set_ime_allowed(self.ime);
600 if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
601 self.window
602 .set_ime_cursor_area(position, PhysicalSize::new(20, 20));
603 }
604 }
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:
None
has no effect. - X11: Requests for user attention must be manually cleared.
- Wayland: Requires
xdg_activation_v1
protocol,None
has 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
None
will use dbus to get the system preference. - X11: Sets
_GTK_THEME_VARIANT
hint todark
orlight
and ifNone
is 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?
555 fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
556 let window = Arc::new(window);
557
558 // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
559 // it doesn't outlive it.
560 #[cfg(not(any(android_platform, ios_platform)))]
561 let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
562
563 let theme = window.theme().unwrap_or(Theme::Dark);
564 info!("Theme: {theme:?}");
565 let named_idx = 0;
566 window.set_cursor(CURSORS[named_idx]);
567
568 // Allow IME out of the box.
569 let ime = true;
570 window.set_ime_allowed(ime);
571
572 let size = window.inner_size();
573 let mut state = Self {
574 #[cfg(macos_platform)]
575 option_as_alt: window.option_as_alt(),
576 custom_idx: app.custom_cursors.len() - 1,
577 cursor_grab: CursorGrabMode::None,
578 named_idx,
579 #[cfg(not(any(android_platform, ios_platform)))]
580 surface,
581 window,
582 theme,
583 ime,
584 cursor_position: Default::default(),
585 cursor_hidden: Default::default(),
586 modifiers: Default::default(),
587 occluded: Default::default(),
588 rotated: Default::default(),
589 panned: Default::default(),
590 zoom: Default::default(),
591 };
592
593 state.resize(size);
594 Ok(state)
595 }
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
,NSWindowSharingNone
is 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?
555 fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
556 let window = Arc::new(window);
557
558 // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
559 // it doesn't outlive it.
560 #[cfg(not(any(android_platform, ios_platform)))]
561 let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
562
563 let theme = window.theme().unwrap_or(Theme::Dark);
564 info!("Theme: {theme:?}");
565 let named_idx = 0;
566 window.set_cursor(CURSORS[named_idx]);
567
568 // Allow IME out of the box.
569 let ime = true;
570 window.set_ime_allowed(ime);
571
572 let size = window.inner_size();
573 let mut state = Self {
574 #[cfg(macos_platform)]
575 option_as_alt: window.option_as_alt(),
576 custom_idx: app.custom_cursors.len() - 1,
577 cursor_grab: CursorGrabMode::None,
578 named_idx,
579 #[cfg(not(any(android_platform, ios_platform)))]
580 surface,
581 window,
582 theme,
583 ime,
584 cursor_position: Default::default(),
585 cursor_hidden: Default::default(),
586 modifiers: Default::default(),
587 occluded: Default::default(),
588 rotated: Default::default(),
589 panned: Default::default(),
590 zoom: Default::default(),
591 };
592
593 state.resize(size);
594 Ok(state)
595 }
596
597 pub fn toggle_ime(&mut self) {
598 self.ime = !self.ime;
599 self.window.set_ime_allowed(self.ime);
600 if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
601 self.window
602 .set_ime_cursor_area(position, PhysicalSize::new(20, 20));
603 }
604 }
605
606 pub fn minimize(&mut self) {
607 self.window.set_minimized(true);
608 }
609
610 pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) {
611 self.cursor_position = Some(position);
612 if self.ime {
613 self.window
614 .set_ime_cursor_area(position, PhysicalSize::new(20, 20));
615 }
616 }
617
618 pub fn cursor_left(&mut self) {
619 self.cursor_position = None;
620 }
621
622 /// Toggle maximized.
623 fn toggle_maximize(&self) {
624 let maximized = self.window.is_maximized();
625 self.window.set_maximized(!maximized);
626 }
627
628 /// Toggle window decorations.
629 fn toggle_decorations(&self) {
630 let decorated = self.window.is_decorated();
631 self.window.set_decorations(!decorated);
632 }
633
634 /// Toggle window resizable state.
635 fn toggle_resizable(&self) {
636 let resizable = self.window.is_resizable();
637 self.window.set_resizable(!resizable);
638 }
639
640 /// Toggle cursor visibility
641 fn toggle_cursor_visibility(&mut self) {
642 self.cursor_hidden = !self.cursor_hidden;
643 self.window.set_cursor_visible(!self.cursor_hidden);
644 }
645
646 /// Toggle resize increments on a window.
647 fn toggle_resize_increments(&mut self) {
648 let new_increments = match self.window.resize_increments() {
649 Some(_) => None,
650 None => Some(LogicalSize::new(25.0, 25.0)),
651 };
652 info!("Had increments: {}", new_increments.is_none());
653 self.window.set_resize_increments(new_increments);
654 }
655
656 /// Toggle fullscreen.
657 fn toggle_fullscreen(&self) {
658 let fullscreen = if self.window.fullscreen().is_some() {
659 None
660 } else {
661 Some(Fullscreen::Borderless(None))
662 };
663
664 self.window.set_fullscreen(fullscreen);
665 }
666
667 /// Cycle through the grab modes ignoring errors.
668 fn cycle_cursor_grab(&mut self) {
669 self.cursor_grab = match self.cursor_grab {
670 CursorGrabMode::None => CursorGrabMode::Confined,
671 CursorGrabMode::Confined => CursorGrabMode::Locked,
672 CursorGrabMode::Locked => CursorGrabMode::None,
673 };
674 info!("Changing cursor grab mode to {:?}", self.cursor_grab);
675 if let Err(err) = self.window.set_cursor_grab(self.cursor_grab) {
676 error!("Error setting cursor grab: {err}");
677 }
678 }
679
680 #[cfg(macos_platform)]
681 fn cycle_option_as_alt(&mut self) {
682 self.option_as_alt = match self.option_as_alt {
683 OptionAsAlt::None => OptionAsAlt::OnlyLeft,
684 OptionAsAlt::OnlyLeft => OptionAsAlt::OnlyRight,
685 OptionAsAlt::OnlyRight => OptionAsAlt::Both,
686 OptionAsAlt::Both => OptionAsAlt::None,
687 };
688 info!("Setting option as alt {:?}", self.option_as_alt);
689 self.window.set_option_as_alt(self.option_as_alt);
690 }
691
692 /// Swap the window dimensions with `request_inner_size`.
693 fn swap_dimensions(&mut self) {
694 let old_inner_size = self.window.inner_size();
695 let mut inner_size = old_inner_size;
696
697 mem::swap(&mut inner_size.width, &mut inner_size.height);
698 info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
699
700 if let Some(new_inner_size) = self.window.request_inner_size(inner_size) {
701 if old_inner_size == new_inner_size {
702 info!("Inner size change got ignored");
703 } else {
704 self.resize(new_inner_size);
705 }
706 } else {
707 info!("Request inner size is asynchronous");
708 }
709 }
710
711 /// Pick the next cursor.
712 fn next_cursor(&mut self) {
713 self.named_idx = (self.named_idx + 1) % CURSORS.len();
714 info!("Setting cursor to \"{:?}\"", CURSORS[self.named_idx]);
715 self.window
716 .set_cursor(Cursor::Icon(CURSORS[self.named_idx]));
717 }
718
719 /// Pick the next custom cursor.
720 fn next_custom_cursor(&mut self, custom_cursors: &[CustomCursor]) {
721 self.custom_idx = (self.custom_idx + 1) % custom_cursors.len();
722 let cursor = Cursor::Custom(custom_cursors[self.custom_idx].clone());
723 self.window.set_cursor(cursor);
724 }
Sourcepub fn set_cursor_icon(&self, icon: CursorIcon)
👎Deprecated: Renamed to set_cursor
pub fn set_cursor_icon(&self, icon: CursorIcon)
set_cursor
Deprecated! 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?
796 fn drag_resize_window(&self) {
797 let position = match self.cursor_position {
798 Some(position) => position,
799 None => {
800 info!("Drag-resize requires cursor to be inside the window");
801 return;
802 }
803 };
804
805 let win_size = self.window.inner_size();
806 let border_size = BORDER_SIZE * self.window.scale_factor();
807
808 let x_direction = if position.x < border_size {
809 ResizeDirection::West
810 } else if position.x > (win_size.width as f64 - border_size) {
811 ResizeDirection::East
812 } else {
813 // Use arbitrary direction instead of None for simplicity.
814 ResizeDirection::SouthEast
815 };
816
817 let y_direction = if position.y < border_size {
818 ResizeDirection::North
819 } else if position.y > (win_size.height as f64 - border_size) {
820 ResizeDirection::South
821 } else {
822 // Use arbitrary direction instead of None for simplicity.
823 ResizeDirection::SouthEast
824 };
825
826 let direction = match (x_direction, y_direction) {
827 (ResizeDirection::West, ResizeDirection::North) => ResizeDirection::NorthWest,
828 (ResizeDirection::West, ResizeDirection::South) => ResizeDirection::SouthWest,
829 (ResizeDirection::West, _) => ResizeDirection::West,
830 (ResizeDirection::East, ResizeDirection::North) => ResizeDirection::NorthEast,
831 (ResizeDirection::East, ResizeDirection::South) => ResizeDirection::SouthEast,
832 (ResizeDirection::East, _) => ResizeDirection::East,
833 (_, ResizeDirection::South) => ResizeDirection::South,
834 (_, ResizeDirection::North) => ResizeDirection::North,
835 _ => return,
836 };
837
838 if let Err(err) = self.window.drag_resize_window(direction) {
839 info!("Error starting window drag-resize: {err}");
840 } else {
841 info!("Drag-resizing window Window={:?}", self.window.id());
842 }
843 }
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
impl HasDisplayHandle for Window
Source§fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError>
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError>
Source§impl HasWindowHandle for Window
impl HasWindowHandle for Window
Source§fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError>
fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError>
Source§impl WindowExtMacOS for Window
impl WindowExtMacOS for Window
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§fn set_unified_titlebar(&self, unified_titlebar: bool)
fn set_unified_titlebar(&self, unified_titlebar: bool)
Source§fn unified_titlebar(&self) -> bool
fn unified_titlebar(&self) -> bool
WindowExtMacOS::set_unified_titlebar
.Source§impl WindowExtStartupNotify for Window
impl WindowExtStartupNotify for Window
Source§fn request_activation_token(
&self,
) -> Result<AsyncRequestSerial, NotSupportedError>
fn request_activation_token( &self, ) -> Result<AsyncRequestSerial, NotSupportedError>
Source§impl WindowExtWebSys for Window
impl WindowExtWebSys for Window
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
impl WindowExtWindows for Window
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§fn set_cloaked(&self, cloaked: bool)
fn set_cloaked(&self, cloaked: bool)
Source§unsafe fn window_handle_any_thread(
&self,
) -> Result<WindowHandle<'_>, HandleError>
unsafe fn window_handle_any_thread( &self, ) -> Result<WindowHandle<'_>, HandleError>
impl WindowExtWayland for Window
impl WindowExtX11 for Window
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> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for 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
instead