Skip to content

Commit caa0d5b

Browse files
committed
Require event loop to run when creating Window
Creating window when event loop is not running generally doesn't work, since a bunch of events and sync OS requests can't be processed. This is also an issue on e.g. Android, since window can't be created outside event loop easily. Thus restrict the window creation, as well as other resource creation to running event loop. Given that all the examples use the bad pattern of creating the window when event loop is not running and also most example existence is questionable, since they show single thing and the majority of their code is window/event loop initialization, they wore merged into a single example 'window.rs' example that showcases very simple application using winit. Fixes #3399.
1 parent 4d4d6e5 commit caa0d5b

85 files changed

Lines changed: 1357 additions & 3211 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Unreleased` header.
1111

1212
# Unreleased
1313

14+
- **Breaking:** Rename `EventLoopWindowTarget` to `ActiveEventLoop`.
15+
- **Breaking:** Remove `Deref` implementation for `EventLoop` that gave `EventLoopWindowTarget`.
1416
- On X11, fix swapped instance and general class names.
1517
- **Breaking:** Removed unnecessary generic parameter `T` from `EventLoopWindowTarget`.
1618
- On Windows, macOS, X11, Wayland and Web, implement setting images as cursors. See the `custom_cursors.rs` example.

examples/child_window.rs

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
#[cfg(all(
2-
feature = "rwh_06",
3-
any(x11_platform, macos_platform, windows_platform)
4-
))]
5-
#[path = "util/fill.rs"]
6-
mod fill;
7-
81
#[cfg(all(
92
feature = "rwh_06",
103
any(x11_platform, macos_platform, windows_platform)
@@ -13,19 +6,18 @@ mod fill;
136
fn main() -> Result<(), impl std::error::Error> {
147
use std::collections::HashMap;
158

9+
#[path = "util/fill.rs"]
10+
mod fill;
11+
1612
use winit::{
1713
dpi::{LogicalPosition, LogicalSize, Position},
1814
event::{ElementState, Event, KeyEvent, WindowEvent},
19-
event_loop::{EventLoop, EventLoopWindowTarget},
15+
event_loop::{ActiveEventLoop, EventLoop},
2016
raw_window_handle::HasRawWindowHandle,
2117
window::{Window, WindowId},
2218
};
2319

24-
fn spawn_child_window(
25-
parent: &Window,
26-
event_loop: &EventLoopWindowTarget,
27-
windows: &mut HashMap<WindowId, Window>,
28-
) {
20+
fn spawn_child_window(parent: &Window, event_loop: &ActiveEventLoop) -> Window {
2921
let parent = parent.raw_window_handle().unwrap();
3022
let mut builder = Window::builder()
3123
.with_title("child window")
@@ -34,31 +26,34 @@ fn main() -> Result<(), impl std::error::Error> {
3426
.with_visible(true);
3527
// `with_parent_window` is unsafe. Parent window must be a valid window.
3628
builder = unsafe { builder.with_parent_window(Some(parent)) };
37-
let child_window = builder.build(event_loop).unwrap();
3829

39-
let id = child_window.id();
40-
windows.insert(id, child_window);
41-
println!("child window created with id: {id:?}");
30+
builder.build(event_loop).unwrap()
4231
}
4332

4433
let mut windows = HashMap::new();
4534

4635
let event_loop: EventLoop<()> = EventLoop::new().unwrap();
47-
let parent_window = Window::builder()
48-
.with_title("parent window")
49-
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
50-
.with_inner_size(LogicalSize::new(640.0f32, 480.0f32))
51-
.build(&event_loop)
52-
.unwrap();
36+
let mut parent_window_id = unsafe { WindowId::dummy() };
5337

54-
println!("parent window: {parent_window:?})");
38+
event_loop.run(move |event: Event<()>, event_loop| {
39+
match event {
40+
Event::Resumed => {
41+
let window = Window::builder()
42+
.with_title("parent window")
43+
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
44+
.with_inner_size(LogicalSize::new(640.0f32, 480.0f32))
45+
.build(event_loop)
46+
.unwrap();
5547

56-
event_loop.run(move |event: Event<()>, elwt| {
57-
if let Event::WindowEvent { event, window_id } = event {
58-
match event {
48+
parent_window_id = window.id();
49+
50+
println!("Parent window id: {parent_window_id:?})");
51+
windows.insert(parent_window_id, window);
52+
}
53+
Event::WindowEvent { window_id, event } => match event {
5954
WindowEvent::CloseRequested => {
6055
windows.clear();
61-
elwt.exit();
56+
event_loop.exit();
6257
}
6358
WindowEvent::CursorEntered { device_id: _ } => {
6459
// On x11, println when the cursor entered in a window even if the child window is created
@@ -75,23 +70,28 @@ fn main() -> Result<(), impl std::error::Error> {
7570
},
7671
..
7772
} => {
78-
spawn_child_window(&parent_window, elwt, &mut windows);
73+
let parent_window = windows.get(&parent_window_id).unwrap();
74+
let child_window = spawn_child_window(parent_window, event_loop);
75+
let child_id = child_window.id();
76+
println!("Child window created with id: {child_id:?}");
77+
windows.insert(child_id, child_window);
7978
}
8079
WindowEvent::RedrawRequested => {
8180
if let Some(window) = windows.get(&window_id) {
8281
fill::fill_window(window);
8382
}
8483
}
8584
_ => (),
86-
}
85+
},
86+
_ => (),
8787
}
8888
})
8989
}
9090

91-
#[cfg(not(all(
91+
#[cfg(all(
9292
feature = "rwh_06",
93-
any(x11_platform, macos_platform, windows_platform)
94-
)))]
93+
not(any(x11_platform, macos_platform, windows_platform))
94+
))]
9595
fn main() {
9696
panic!("This example is supported only on x11, macOS, and Windows, with the `rwh_06` feature enabled.");
9797
}

examples/control_flow.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,14 @@ fn main() -> Result<(), impl std::error::Error> {
3737
println!("Press 'Esc' to close the window.");
3838

3939
let event_loop = EventLoop::new().unwrap();
40-
let window = Window::builder()
41-
.with_title("Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.")
42-
.build(&event_loop)
43-
.unwrap();
4440

4541
let mut mode = Mode::Wait;
4642
let mut request_redraw = false;
4743
let mut wait_cancelled = false;
4844
let mut close_requested = false;
4945

50-
event_loop.run(move |event, elwt| {
46+
let mut window = None;
47+
event_loop.run(move |event, event_loop| {
5148
use winit::event::StartCause;
5249
println!("{event:?}");
5350
match event {
@@ -57,6 +54,12 @@ fn main() -> Result<(), impl std::error::Error> {
5754
_ => false,
5855
}
5956
}
57+
Event::Resumed => {
58+
window = Some(Window::builder()
59+
.with_title("Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.")
60+
.build(event_loop)
61+
.unwrap());
62+
}
6063
Event::WindowEvent { event, .. } => match event {
6164
WindowEvent::CloseRequested => {
6265
close_requested = true;
@@ -94,32 +97,34 @@ fn main() -> Result<(), impl std::error::Error> {
9497
_ => (),
9598
},
9699
WindowEvent::RedrawRequested => {
97-
fill::fill_window(&window);
100+
let window = window.as_ref().unwrap();
101+
window.pre_present_notify();
102+
fill::fill_window(window);
98103
}
99104
_ => (),
100105
},
101106
Event::AboutToWait => {
102107
if request_redraw && !wait_cancelled && !close_requested {
103-
window.request_redraw();
108+
window.as_ref().unwrap().request_redraw();
104109
}
105110

106111
match mode {
107-
Mode::Wait => elwt.set_control_flow(ControlFlow::Wait),
112+
Mode::Wait => event_loop.set_control_flow(ControlFlow::Wait),
108113
Mode::WaitUntil => {
109114
if !wait_cancelled {
110-
elwt.set_control_flow(ControlFlow::WaitUntil(
115+
event_loop.set_control_flow(ControlFlow::WaitUntil(
111116
time::Instant::now() + WAIT_TIME,
112117
));
113118
}
114119
}
115120
Mode::Poll => {
116121
thread::sleep(POLL_SLEEP_TIME);
117-
elwt.set_control_flow(ControlFlow::Poll);
122+
event_loop.set_control_flow(ControlFlow::Poll);
118123
}
119124
};
120125

121126
if close_requested {
122-
elwt.exit();
127+
event_loop.exit();
123128
}
124129
}
125130
_ => (),

examples/cursor.rs

Lines changed: 0 additions & 88 deletions
This file was deleted.

examples/cursor_grab.rs

Lines changed: 0 additions & 73 deletions
This file was deleted.

0 commit comments

Comments
 (0)