Skip to content

Commit 964b047

Browse files
committed
Make raw_window_handle field in Window and ExtractedWindow an Option. (#6114)
# Objective - Trying to make it possible to do write tests that don't require a raw window handle. - Fixes #6106. ## Solution - Make the interface and type changes. Avoid accessing `None`. --- ## Changelog - Converted `raw_window_handle` field in both `Window` and `ExtractedWindow` to `Option<RawWindowHandleWrapper>`. - Revised accessor function `Window::raw_window_handle()` to return `Option<RawWindowHandleWrapper>`. - Skip conditions in loops that would require a raw window handle (to create a `Surface`, for example). ## Migration Guide `Window::raw_window_handle()` now returns `Option<RawWindowHandleWrapper>`. Co-authored-by: targrub <62773321+targrub@users.noreply.github.com>
1 parent bfd6285 commit 964b047

File tree

4 files changed

+87
-19
lines changed

4 files changed

+87
-19
lines changed

crates/bevy_render/src/lib.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,21 @@ impl Plugin for RenderPlugin {
144144
.register_type::<Color>();
145145

146146
if let Some(backends) = options.backends {
147+
let windows = app.world.resource_mut::<bevy_window::Windows>();
147148
let instance = wgpu::Instance::new(backends);
148149
let surface = {
149-
let windows = app.world.resource_mut::<bevy_window::Windows>();
150-
let raw_handle = windows.get_primary().map(|window| unsafe {
151-
let handle = window.raw_window_handle().get_handle();
152-
instance.create_surface(&handle)
153-
});
154-
raw_handle
150+
if let Some(window) = windows.get_primary() {
151+
if let Some(raw_window_handle) = window.raw_window_handle() {
152+
unsafe {
153+
let handle = raw_window_handle.get_handle();
154+
Some(instance.create_surface(&handle))
155+
}
156+
} else {
157+
None
158+
}
159+
} else {
160+
None
161+
}
155162
};
156163
let request_adapter_options = wgpu::RequestAdapterOptions {
157164
power_preference: options.power_preference,

crates/bevy_render/src/view/window.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl Plugin for WindowRenderPlugin {
3838

3939
pub struct ExtractedWindow {
4040
pub id: WindowId,
41-
pub handle: RawWindowHandleWrapper,
41+
pub raw_window_handle: Option<RawWindowHandleWrapper>,
4242
pub physical_width: u32,
4343
pub physical_height: u32,
4444
pub present_mode: PresentMode,
@@ -83,7 +83,7 @@ fn extract_windows(
8383
.entry(window.id())
8484
.or_insert(ExtractedWindow {
8585
id: window.id(),
86-
handle: window.raw_window_handle(),
86+
raw_window_handle: window.raw_window_handle(),
8787
physical_width: new_width,
8888
physical_height: new_height,
8989
present_mode: window.present_mode(),
@@ -161,14 +161,20 @@ pub fn prepare_windows(
161161
render_instance: Res<RenderInstance>,
162162
render_adapter: Res<RenderAdapter>,
163163
) {
164-
let window_surfaces = window_surfaces.deref_mut();
165-
for window in windows.windows.values_mut() {
164+
for window in windows
165+
.windows
166+
.values_mut()
167+
// value of raw_winndow_handle only None if synthetic test
168+
.filter(|x| x.raw_window_handle.is_some())
169+
{
170+
let window_surfaces = window_surfaces.deref_mut();
166171
let surface = window_surfaces
167172
.surfaces
168173
.entry(window.id)
169174
.or_insert_with(|| unsafe {
170175
// NOTE: On some OSes this MUST be called from the main thread.
171-
render_instance.create_surface(&window.handle.get_handle())
176+
render_instance
177+
.create_surface(&window.raw_window_handle.as_ref().unwrap().get_handle())
172178
});
173179

174180
let swap_chain_descriptor = wgpu::SurfaceConfiguration {

crates/bevy_window/src/window.rs

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,59 @@ impl WindowResizeConstraints {
187187
/// }
188188
/// }
189189
/// ```
190+
/// To test code that uses `Window`s, one can test it with varying `Window` parameters by
191+
/// creating `WindowResizeConstraints` or `WindowDescriptor` structures.
192+
/// values by setting
193+
///
194+
/// ```
195+
/// # use bevy_utils::default;
196+
/// # use bevy_window::{Window, WindowCommand, WindowDescriptor, WindowId, WindowResizeConstraints};
197+
/// # fn compute_window_area(w: &Window) -> f32 {
198+
/// # w.width() * w.height()
199+
/// # }
200+
/// # fn grow_window_to_text_size(_window: &mut Window, _text: &str) {}
201+
/// # fn set_new_title(window: &mut Window, text: String) { window.set_title(text); }
202+
/// # fn a_window_resize_test() {
203+
/// let resize_constraints = WindowResizeConstraints {
204+
/// min_width: 400.0,
205+
/// min_height: 300.0,
206+
/// max_width: 1280.0,
207+
/// max_height: 1024.0,
208+
/// };
209+
/// let window_descriptor = WindowDescriptor {
210+
/// width: 800.0,
211+
/// height: 600.0,
212+
/// resizable: true,
213+
/// resize_constraints,
214+
/// ..default()
215+
/// };
216+
/// let mut window = Window::new(
217+
/// WindowId::new(),
218+
/// &window_descriptor,
219+
/// 100, // physical_width
220+
/// 100, // physical_height
221+
/// 1.0, // scale_factor
222+
/// None, None);
223+
///
224+
/// let area = compute_window_area(&window);
225+
/// assert_eq!(area, 100.0 * 100.0);
226+
///
227+
/// grow_window_to_text_size(&mut window, "very long text that does not wrap");
228+
/// assert_eq!(window.physical_width(), window.requested_width() as u32);
229+
/// grow_window_to_text_size(&mut window, "very long text that does wrap, creating a maximum width window");
230+
/// assert_eq!(window.physical_width(), window.requested_width() as u32);
231+
///
232+
/// set_new_title(&mut window, "new title".to_string());
233+
/// let mut found_command = false;
234+
/// for command in window.drain_commands() {
235+
/// if command == (WindowCommand::SetTitle{ title: "new title".to_string() }) {
236+
/// found_command = true;
237+
/// break;
238+
/// }
239+
/// }
240+
/// assert_eq!(found_command, true);
241+
/// }
242+
/// ```
190243
#[derive(Debug)]
191244
pub struct Window {
192245
id: WindowId,
@@ -206,7 +259,7 @@ pub struct Window {
206259
cursor_visible: bool,
207260
cursor_locked: bool,
208261
physical_cursor_position: Option<DVec2>,
209-
raw_window_handle: RawWindowHandleWrapper,
262+
raw_window_handle: Option<RawWindowHandleWrapper>,
210263
focused: bool,
211264
mode: WindowMode,
212265
canvas: Option<String>,
@@ -217,7 +270,7 @@ pub struct Window {
217270
///
218271
/// Bevy apps don't interact with this `enum` directly. Instead, they should use the methods on [`Window`].
219272
/// This `enum` is meant for authors of windowing plugins. See the documentation on [`crate::WindowPlugin`] for more information.
220-
#[derive(Debug)]
273+
#[derive(Debug, PartialEq)]
221274
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
222275
pub enum WindowCommand {
223276
/// Set the window's [`WindowMode`].
@@ -315,7 +368,7 @@ impl Window {
315368
physical_height: u32,
316369
scale_factor: f64,
317370
position: Option<IVec2>,
318-
raw_window_handle: RawWindowHandle,
371+
raw_window_handle: Option<RawWindowHandle>,
319372
) -> Self {
320373
Window {
321374
id,
@@ -335,7 +388,7 @@ impl Window {
335388
cursor_locked: window_descriptor.cursor_locked,
336389
cursor_icon: CursorIcon::Default,
337390
physical_cursor_position: None,
338-
raw_window_handle: RawWindowHandleWrapper::new(raw_window_handle),
391+
raw_window_handle: raw_window_handle.map(RawWindowHandleWrapper::new),
339392
focused: true,
340393
mode: window_descriptor.mode,
341394
canvas: window_descriptor.canvas.clone(),
@@ -719,9 +772,11 @@ impl Window {
719772
pub fn is_focused(&self) -> bool {
720773
self.focused
721774
}
722-
/// Get the [`RawWindowHandleWrapper`] corresponding to this window
723-
pub fn raw_window_handle(&self) -> RawWindowHandleWrapper {
724-
self.raw_window_handle.clone()
775+
/// Get the [`RawWindowHandleWrapper`] corresponding to this window if set.
776+
///
777+
/// During normal use, this can be safely unwrapped; the value should only be [`None`] when synthetically constructed for tests.
778+
pub fn raw_window_handle(&self) -> Option<RawWindowHandleWrapper> {
779+
self.raw_window_handle.as_ref().cloned()
725780
}
726781

727782
/// The "html canvas" element selector.

crates/bevy_winit/src/winit_windows.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ impl WinitWindows {
201201
inner_size.height,
202202
scale_factor,
203203
position,
204-
raw_window_handle,
204+
Some(raw_window_handle),
205205
)
206206
}
207207

0 commit comments

Comments
 (0)