Skip to content

Commit 739b1e5

Browse files
authored
Push window resize and scale factor messages to bevy_window_events (#24046)
I was initially using `MessageReader<WindowResized>` in my system for my app but once my system grew to use more and more window events, I refactored to using `MessageReader<WindowEvent>` and matching on its variants. This is where I ran into the issue of the `WindowEvent::WindowResized` case never matching. When making this PR, I noticed `WindowEvent::WindowBackendScaleFactorChanged` and `WindowEvent::WindowScaleFactorChanged` had the same issue. # Objective Fixes #15268 ## Solution Instead of writing into `MessageWriter<WindowResized>`, `MessageWriter<WindowBackendScaleFactorChanged>` and `MessageWriter<WindowScaleFactorChanged>`, push into `bevy_window_events` where it gets sent to the `forward_bevy_events` function for syncing the messages. ## Testing I made local modifications to the `window_resizing` example to use a `MessageReader<WindowEvent>` instead of `MessageReader<WindowResized>` like so: ```rs fn on_resize_system( mut text: Single<&mut Text, With<ResolutionText>>, mut resize_reader: MessageReader<WindowEvent>, ) { for e in resize_reader.read() { if let WindowEvent::WindowResized(e) = e { // When resolution is being changed text.0 = format!("{:.1} x {:.1}", e.width, e.height); } } } ``` I ran this example on linux wayland.
1 parent 1a21cbe commit 739b1e5

3 files changed

Lines changed: 226 additions & 67 deletions

File tree

crates/bevy_winit/src/state.rs

Lines changed: 209 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use bevy_app::{App, AppExit, PluginsState};
33
use bevy_ecs::{
44
change_detection::{DetectChanges, Res},
55
entity::Entity,
6-
message::{MessageCursor, MessageWriter},
6+
message::MessageCursor,
77
prelude::*,
88
system::SystemState,
99
world::FromWorld,
@@ -79,10 +79,7 @@ pub(crate) struct WinitAppRunnerState {
7979
/// Raw Winit window events to send
8080
raw_winit_events: Vec<RawWinitWindowEvent>,
8181

82-
message_writer_system_state: SystemState<(
83-
MessageWriter<'static, WindowResized>,
84-
MessageWriter<'static, WindowBackendScaleFactorChanged>,
85-
MessageWriter<'static, WindowScaleFactorChanged>,
82+
windows_system_state: SystemState<
8683
Query<
8784
'static,
8885
'static,
@@ -92,19 +89,16 @@ pub(crate) struct WinitAppRunnerState {
9289
&'static mut WinitWindowPressedKeys,
9390
),
9491
>,
95-
)>,
92+
>,
9693
/// time at which next tick is scheduled to run when `update_mode` is [`UpdateMode::Reactive`]
9794
scheduled_tick_start: Option<Instant>,
9895
}
9996

10097
impl WinitAppRunnerState {
10198
fn new(mut app: App) -> Self {
102-
let message_writer_system_state: SystemState<(
103-
MessageWriter<WindowResized>,
104-
MessageWriter<WindowBackendScaleFactorChanged>,
105-
MessageWriter<WindowScaleFactorChanged>,
99+
let windows_system_state: SystemState<
106100
Query<(&mut Window, &mut CachedWindow, &mut WinitWindowPressedKeys)>,
107-
)> = SystemState::new(app.world_mut());
101+
> = SystemState::new(app.world_mut());
108102

109103
Self {
110104
app,
@@ -122,7 +116,7 @@ impl WinitAppRunnerState {
122116
startup_forced_updates: 5,
123117
bevy_window_events: Vec::new(),
124118
raw_winit_events: Vec::new(),
125-
message_writer_system_state,
119+
windows_system_state,
126120
scheduled_tick_start: None,
127121
}
128122
}
@@ -219,13 +213,8 @@ impl ApplicationHandler<WinitUserEvent> for WinitAppRunnerState {
219213

220214
WINIT_WINDOWS.with_borrow(|winit_windows| {
221215
ACCESS_KIT_ADAPTERS.with_borrow_mut(|access_kit_adapters| {
222-
let (
223-
mut window_resized,
224-
mut window_backend_scale_factor_changed,
225-
mut window_scale_factor_changed,
226-
mut windows,
227-
) = self
228-
.message_writer_system_state
216+
let mut windows = self
217+
.windows_system_state
229218
.get_mut(self.app.world_mut())
230219
.unwrap();
231220

@@ -256,17 +245,18 @@ impl ApplicationHandler<WinitUserEvent> for WinitAppRunnerState {
256245
}
257246

258247
match event {
259-
WindowEvent::Resized(size) => {
260-
react_to_resize(window, &mut win, size, &mut window_resized);
261-
}
248+
WindowEvent::Resized(size) => self
249+
.bevy_window_events
250+
.send(react_to_resize(window, &mut win, size)),
262251
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
263-
react_to_scale_factor_change(
264-
window,
265-
&mut win,
266-
scale_factor,
267-
&mut window_backend_scale_factor_changed,
268-
&mut window_scale_factor_changed,
269-
);
252+
let (window_backend_scale_factor_changed, window_scale_factor_changed) =
253+
react_to_scale_factor_change(window, &mut win, scale_factor);
254+
255+
self.bevy_window_events
256+
.send(window_backend_scale_factor_changed);
257+
if let Some(window_scale_factor_changed) = window_scale_factor_changed {
258+
self.bevy_window_events.send(window_scale_factor_changed);
259+
}
270260
}
271261
WindowEvent::CloseRequested => self
272262
.bevy_window_events
@@ -926,42 +916,51 @@ pub(crate) fn react_to_resize(
926916
window_entity: Entity,
927917
window: &mut Window,
928918
size: PhysicalSize<u32>,
929-
window_resized: &mut MessageWriter<WindowResized>,
930-
) {
919+
) -> WindowResized {
931920
window
932921
.resolution
933922
.set_physical_resolution(size.width, size.height);
934923

935-
window_resized.write(WindowResized {
924+
WindowResized {
936925
window: window_entity,
937926
width: window.width(),
938927
height: window.height(),
939-
});
928+
}
940929
}
941930

942931
pub(crate) fn react_to_scale_factor_change(
943932
window_entity: Entity,
944933
window: &mut Window,
945934
scale_factor: f64,
946-
window_backend_scale_factor_changed: &mut MessageWriter<WindowBackendScaleFactorChanged>,
947-
window_scale_factor_changed: &mut MessageWriter<WindowScaleFactorChanged>,
935+
) -> (
936+
WindowBackendScaleFactorChanged,
937+
Option<WindowScaleFactorChanged>,
948938
) {
949939
let prior_factor = window.resolution.scale_factor();
950940
window.resolution.set_scale_factor(scale_factor as f32);
951941

952-
window_backend_scale_factor_changed.write(WindowBackendScaleFactorChanged {
942+
let window_backend_scale_factor_changed = WindowBackendScaleFactorChanged {
953943
window: window_entity,
954944
scale_factor,
955-
});
945+
};
956946

957947
let scale_factor_override = window.resolution.scale_factor_override();
958948

959-
if scale_factor_override.is_none() && !relative_eq!(scale_factor as f32, prior_factor) {
960-
window_scale_factor_changed.write(WindowScaleFactorChanged {
961-
window: window_entity,
962-
scale_factor,
963-
});
964-
}
949+
let window_scale_factor_changed =
950+
if scale_factor_override.is_none() && !relative_eq!(scale_factor as f32, prior_factor) {
951+
let window_scale_factor_changed = WindowScaleFactorChanged {
952+
window: window_entity,
953+
scale_factor,
954+
};
955+
Some(window_scale_factor_changed)
956+
} else {
957+
None
958+
};
959+
960+
(
961+
window_backend_scale_factor_changed,
962+
window_scale_factor_changed,
963+
)
965964
}
966965

967966
#[cfg(test)]
@@ -1011,6 +1010,30 @@ mod tests {
10111010
})
10121011
);
10131012
assert_eq!(window_scale_factor_changed_messages_iter.next(), None);
1013+
1014+
let window_event_messages = app.world().resource::<Messages<BevyWindowEvent>>();
1015+
assert_eq!(window_event_messages.len(), 2);
1016+
1017+
let mut window_event_messages_iter = window_event_messages.iter_current_update_messages();
1018+
assert_eq!(
1019+
window_event_messages_iter.next(),
1020+
Some(&BevyWindowEvent::WindowBackendScaleFactorChanged(
1021+
WindowBackendScaleFactorChanged {
1022+
window: window_entity,
1023+
scale_factor: 2.0
1024+
}
1025+
))
1026+
);
1027+
assert_eq!(
1028+
window_event_messages_iter.next(),
1029+
Some(&BevyWindowEvent::WindowScaleFactorChanged(
1030+
WindowScaleFactorChanged {
1031+
window: window_entity,
1032+
scale_factor: 2.0
1033+
}
1034+
))
1035+
);
1036+
assert_eq!(window_event_messages_iter.next(), None);
10141037
}
10151038

10161039
#[test]
@@ -1043,6 +1066,21 @@ mod tests {
10431066
let window_scale_factor_changed_messages =
10441067
app.world().resource::<Messages<WindowScaleFactorChanged>>();
10451068
assert!(window_scale_factor_changed_messages.is_empty());
1069+
1070+
let window_event_messages = app.world().resource::<Messages<BevyWindowEvent>>();
1071+
assert_eq!(window_event_messages.len(), 1);
1072+
1073+
let mut window_event_messages_iter = window_event_messages.iter_current_update_messages();
1074+
assert_eq!(
1075+
window_event_messages_iter.next(),
1076+
Some(&BevyWindowEvent::WindowBackendScaleFactorChanged(
1077+
WindowBackendScaleFactorChanged {
1078+
window: window_entity,
1079+
scale_factor: 1.0
1080+
}
1081+
))
1082+
);
1083+
assert_eq!(window_event_messages_iter.next(), None);
10461084
}
10471085

10481086
fn setup_react_to_scale_factor_change_test_app(
@@ -1052,20 +1090,30 @@ mod tests {
10521090
let mut app = App::new();
10531091
app.add_message::<WindowBackendScaleFactorChanged>();
10541092
app.add_message::<WindowScaleFactorChanged>();
1093+
app.add_message::<BevyWindowEvent>();
10551094
app.add_systems(
10561095
Update,
10571096
move |mut window: Single<(Entity, &mut Window)>,
1058-
mut window_backend_scale_factor_changed: MessageWriter<
1059-
WindowBackendScaleFactorChanged,
1060-
>,
1061-
mut window_scale_factor_changed: MessageWriter<WindowScaleFactorChanged>| {
1062-
react_to_scale_factor_change(
1063-
window.0,
1064-
&mut window.1,
1065-
changed_scale_factor,
1066-
&mut window_backend_scale_factor_changed,
1067-
&mut window_scale_factor_changed,
1068-
);
1097+
mut window_backend_scale_factor_changed_writer: MessageWriter<
1098+
WindowBackendScaleFactorChanged,
1099+
>,
1100+
mut window_scale_factor_changed_writer: MessageWriter<
1101+
WindowScaleFactorChanged,
1102+
>,
1103+
mut window_event: MessageWriter<BevyWindowEvent>| {
1104+
let (window_backend_scale_factor_changed, window_scale_factor_changed) =
1105+
react_to_scale_factor_change(window.0, &mut window.1, changed_scale_factor);
1106+
window_backend_scale_factor_changed_writer
1107+
.write(window_backend_scale_factor_changed.clone());
1108+
window_event.write(BevyWindowEvent::WindowBackendScaleFactorChanged(
1109+
window_backend_scale_factor_changed,
1110+
));
1111+
if let Some(window_scale_factor_changed) = window_scale_factor_changed {
1112+
window_scale_factor_changed_writer.write(window_scale_factor_changed.clone());
1113+
window_event.write(BevyWindowEvent::WindowScaleFactorChanged(
1114+
window_scale_factor_changed,
1115+
));
1116+
}
10691117
},
10701118
);
10711119

@@ -1075,4 +1123,111 @@ mod tests {
10751123

10761124
(app, window_entity)
10771125
}
1126+
1127+
#[test]
1128+
fn test_react_to_resize_with_changed_size() {
1129+
let (mut app, window_entity) =
1130+
setup_react_to_resize(PhysicalSize::new(1280, 720), PhysicalSize::new(1920, 1080));
1131+
app.update();
1132+
1133+
let window = app.world().get::<Window>(window_entity).unwrap();
1134+
assert_eq!(window.resolution.physical_width(), 1920);
1135+
assert_eq!(window.resolution.physical_height(), 1080);
1136+
1137+
let window_resized_messages = app.world().resource::<Messages<WindowResized>>();
1138+
assert_eq!(window_resized_messages.len(), 1);
1139+
1140+
let mut window_resized_messages_iter =
1141+
window_resized_messages.iter_current_update_messages();
1142+
assert_eq!(
1143+
window_resized_messages_iter.next(),
1144+
Some(&WindowResized {
1145+
window: window_entity,
1146+
width: 1920.0,
1147+
height: 1080.0
1148+
})
1149+
);
1150+
assert_eq!(window_resized_messages_iter.next(), None);
1151+
1152+
let window_event_messages = app.world().resource::<Messages<BevyWindowEvent>>();
1153+
assert_eq!(window_event_messages.len(), 1);
1154+
1155+
let mut window_event_messages_iter = window_event_messages.iter_current_update_messages();
1156+
assert_eq!(
1157+
window_event_messages_iter.next(),
1158+
Some(&BevyWindowEvent::WindowResized(WindowResized {
1159+
window: window_entity,
1160+
width: 1920.0,
1161+
height: 1080.0
1162+
}))
1163+
);
1164+
assert_eq!(window_event_messages_iter.next(), None);
1165+
}
1166+
1167+
#[test]
1168+
fn test_react_to_resize_with_same_size() {
1169+
let (mut app, window_entity) =
1170+
setup_react_to_resize(PhysicalSize::new(1280, 720), PhysicalSize::new(1280, 720));
1171+
app.update();
1172+
1173+
let window = app.world().get::<Window>(window_entity).unwrap();
1174+
assert_eq!(window.resolution.physical_width(), 1280);
1175+
assert_eq!(window.resolution.physical_height(), 720);
1176+
1177+
let window_resized_messages = app.world().resource::<Messages<WindowResized>>();
1178+
assert_eq!(window_resized_messages.len(), 1);
1179+
1180+
let mut window_resized_messages_iter =
1181+
window_resized_messages.iter_current_update_messages();
1182+
assert_eq!(
1183+
window_resized_messages_iter.next(),
1184+
Some(&WindowResized {
1185+
window: window_entity,
1186+
width: 1280.0,
1187+
height: 720.0
1188+
})
1189+
);
1190+
assert_eq!(window_resized_messages_iter.next(), None);
1191+
1192+
let window_event_messages = app.world().resource::<Messages<BevyWindowEvent>>();
1193+
assert_eq!(window_event_messages.len(), 1);
1194+
1195+
let mut window_event_messages_iter = window_event_messages.iter_current_update_messages();
1196+
assert_eq!(
1197+
window_event_messages_iter.next(),
1198+
Some(&BevyWindowEvent::WindowResized(WindowResized {
1199+
window: window_entity,
1200+
width: 1280.0,
1201+
height: 720.0
1202+
}))
1203+
);
1204+
assert_eq!(window_event_messages_iter.next(), None);
1205+
}
1206+
1207+
fn setup_react_to_resize(
1208+
initial_size: PhysicalSize<u32>,
1209+
changed_size: PhysicalSize<u32>,
1210+
) -> (App, Entity) {
1211+
let mut app = App::new();
1212+
app.add_message::<WindowResized>();
1213+
app.add_message::<BevyWindowEvent>();
1214+
app.add_systems(
1215+
Update,
1216+
move |mut window: Single<(Entity, &mut Window)>,
1217+
mut window_resized_writer: MessageWriter<WindowResized>,
1218+
mut window_event: MessageWriter<BevyWindowEvent>| {
1219+
let window_resized = react_to_resize(window.0, &mut window.1, changed_size);
1220+
window_resized_writer.write(window_resized.clone());
1221+
window_event.write(BevyWindowEvent::WindowResized(window_resized));
1222+
},
1223+
);
1224+
1225+
let mut window = Window::default();
1226+
window
1227+
.resolution
1228+
.set_physical_resolution(initial_size.width, initial_size.height);
1229+
let window_entity = app.world_mut().spawn(window).id();
1230+
1231+
(app, window_entity)
1232+
}
10781233
}

crates/bevy_winit/src/system.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ pub(crate) fn changed_windows(
310310
>,
311311
monitors: Res<WinitMonitors>,
312312
mut window_resized: MessageWriter<WindowResized>,
313+
mut window_event: MessageWriter<WindowEvent>,
313314
_non_send_marker: NonSendMarker,
314315
) {
315316
WINIT_WINDOWS.with_borrow(|winit_windows| {
@@ -423,7 +424,9 @@ pub(crate) fn changed_windows(
423424

424425
if physical_size != cached_physical_size
425426
&& let Some(new_physical_size) = winit_window.request_inner_size(physical_size) {
426-
react_to_resize(entity, &mut window, new_physical_size, &mut window_resized);
427+
let event = react_to_resize(entity, &mut window, new_physical_size);
428+
window_resized.write(event.clone());
429+
window_event.write(WindowEvent::WindowResized(event));
427430
}
428431
}
429432

0 commit comments

Comments
 (0)