Skip to content

Commit fafd368

Browse files
authored
Fix window resize stretching the canvas instead of resizing the sketch surface (#127) (#170)
1 parent d27eb85 commit fafd368

6 files changed

Lines changed: 85 additions & 14 deletions

File tree

crates/processing_glfw/src/lib.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use processing_core::error::Result;
1313
use processing_input::{
1414
input_cursor_grab_mode, input_cursor_visible, input_flush, input_set_char,
1515
input_set_cursor_enter, input_set_cursor_leave, input_set_focus, input_set_key,
16-
input_set_mouse_button, input_set_mouse_move, input_set_scroll,
16+
input_set_mouse_button, input_set_mouse_move, input_set_scroll, input_window_resize,
1717
};
1818
use processing_render::surface::{MonitorWorkarea, WindowControls};
1919

@@ -256,6 +256,7 @@ impl GlfwContext {
256256
}
257257
};
258258

259+
let mut pending_resize: Option<(i32, i32)> = None;
259260
for (_, event) in glfw::flush_messages(&self.events) {
260261
match event {
261262
WindowEvent::Close => {
@@ -300,6 +301,10 @@ impl GlfwContext {
300301
WindowEvent::Focus(focused) => {
301302
input_set_focus(surface, focused).unwrap();
302303
}
304+
WindowEvent::Size(width, height) => {
305+
// A drag delivers many Size events per poll; keep only the last and apply it once after the loop.
306+
pending_resize = Some((width, height));
307+
}
303308
_ => {}
304309
}
305310
}
@@ -309,6 +314,12 @@ impl GlfwContext {
309314
return false;
310315
}
311316

317+
// Apply the coalesced resize once, the WindowResized message and Window change are processed this poll.
318+
if let Some((width, height)) = pending_resize {
319+
input_window_resize(surface, width as f32, height as f32).unwrap();
320+
processing_render::surface_resize(surface, width as u32, height as u32).unwrap();
321+
}
322+
312323
let Ok(_) = input_flush() else {
313324
return false;
314325
};
@@ -355,6 +366,9 @@ impl GlfwContext {
355366
Ok(())
356367
});
357368
self.last_applied.position = frame_pos;
369+
370+
let (w, h) = self.window.get_size();
371+
self.last_applied.size = bevy::math::UVec2::new(w.max(0) as u32, h.max(0) as u32);
358372
}
359373

360374
#[cfg(not(feature = "wayland"))]
@@ -529,8 +543,8 @@ fn read_desired_window(surface: Entity) -> Option<DesiredWindow> {
529543
_ => None,
530544
},
531545
size: bevy::math::UVec2::new(
532-
window.resolution.physical_width(),
533-
window.resolution.physical_height(),
546+
window.resolution.width() as u32,
547+
window.resolution.height() as u32,
534548
),
535549
visible: window.visible,
536550
resizable: window.resizable,

crates/processing_input/src/lib.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use bevy::input::mouse::{
88
};
99
use bevy::input::touch::TouchPhase;
1010
use bevy::prelude::*;
11-
use bevy::window::CursorMoved;
11+
use bevy::window::{CursorMoved, WindowResized};
1212

1313
use processing_core::app_mut;
1414
use processing_core::error;
@@ -342,3 +342,14 @@ pub fn input_mouse_scrolled() -> error::Result<bool> {
342342
Ok(d.x != 0.0 || d.y != 0.0)
343343
})
344344
}
345+
346+
pub fn input_window_resize(surface: Entity, width: f32, height: f32) -> error::Result<()> {
347+
app_mut(|app| {
348+
app.world_mut().write_message(WindowResized {
349+
window: surface,
350+
width,
351+
height,
352+
});
353+
Ok(())
354+
})
355+
}

crates/processing_pyo3/src/lib.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,12 @@ pub(crate) fn reset_tracked_globals() {
120120
fn sync_globals(module: &Bound<'_, PyModule>, globals: &Bound<'_, PyAny>) -> PyResult<()> {
121121
let graphics =
122122
get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?;
123-
input::sync_globals(
124-
globals,
125-
graphics.surface.entity,
126-
graphics.width,
127-
graphics.height,
128-
)?;
129-
surface::sync_globals(globals, &graphics.surface, graphics.width, graphics.height)?;
123+
let width = ::processing::prelude::surface_width(graphics.surface.entity)
124+
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
125+
let height = ::processing::prelude::surface_height(graphics.surface.entity)
126+
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
127+
input::sync_globals(globals, graphics.surface.entity, width, height)?;
128+
surface::sync_globals(globals, &graphics.surface, width, height)?;
130129
time::sync_globals(globals)?;
131130
Ok(())
132131
}

crates/processing_render/src/graphics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ impl CameraProjection for ProcessingProjection {
117117
fn update(&mut self, _width: f32, _height: f32) {
118118
// this gets called with the render target's physical dimensions (i.e. accounting for
119119
// scale factor), but our projection is in logical pixel units
120-
// TODO: handle resizes?
120+
self.width = _width;
121+
self.height = _height;
121122
}
122123

123124
fn far(&self) -> f32 {

crates/processing_render/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,24 @@ pub fn surface_physical_height(entity: Entity) -> error::Result<u32> {
17021702
})
17031703
}
17041704

1705+
pub fn surface_width(entity: Entity) -> error::Result<u32> {
1706+
app_mut(|app| {
1707+
Ok(app
1708+
.world_mut()
1709+
.run_system_cached_with(surface::width, entity)
1710+
.unwrap())
1711+
})
1712+
}
1713+
1714+
pub fn surface_height(entity: Entity) -> error::Result<u32> {
1715+
app_mut(|app| {
1716+
Ok(app
1717+
.world_mut()
1718+
.run_system_cached_with(surface::height, entity)
1719+
.unwrap())
1720+
})
1721+
}
1722+
17051723
pub fn monitor_list() -> error::Result<Vec<Entity>> {
17061724
app_mut(|app| Ok(app.world_mut().run_system_cached(monitor::list).unwrap()))
17071725
}

crates/processing_render/src/surface.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@
2121
use bevy::{
2222
app::{App, Plugin},
2323
asset::Assets,
24+
camera::RenderTarget,
2425
ecs::query::QueryEntityError,
2526
math::{IRect, IVec2},
2627
prelude::{Commands, Component, Entity, In, Query, ResMut, Window, With, default},
2728
render::render_resource::{Extent3d, TextureFormat},
2829
window::{
2930
CompositeAlphaMode, Monitor, RawHandleWrapper, WindowLevel, WindowMode, WindowPosition,
30-
WindowResolution, WindowWrapper,
31+
WindowRef, WindowResolution, WindowWrapper,
3132
},
3233
};
3334
use raw_window_handle::{
@@ -39,7 +40,7 @@ use processing_core::error::{self, ProcessingError, Result};
3940
#[cfg(not(target_os = "windows"))]
4041
use std::ptr::NonNull;
4142

42-
use crate::image::Image;
43+
use crate::{graphics::SurfaceSize, image::Image};
4344

4445
#[derive(Component, Debug, Clone)]
4546
pub struct Surface;
@@ -394,7 +395,11 @@ pub fn destroy(
394395
pub fn resize(
395396
In((window_entity, width, height)): In<(Entity, u32, u32)>,
396397
mut windows: Query<&mut Window>,
398+
mut graphics_query: Query<(&RenderTarget, &mut SurfaceSize)>,
397399
) -> Result<()> {
400+
let width = width.max(1);
401+
let height = height.max(1);
402+
398403
if let Ok(mut window) = windows.get_mut(window_entity) {
399404
let scale = window.resolution.scale_factor();
400405
let physical_w = (width as f32 * scale) as u32;
@@ -403,6 +408,15 @@ pub fn resize(
403408
.resolution
404409
.set_physical_resolution(physical_w, physical_h);
405410
}
411+
412+
// SurfaceSize changes on resize, if not handled will break APIs dependent on correct SurfaceSize
413+
for (target, mut surface_size) in graphics_query.iter_mut() {
414+
if let RenderTarget::Window(WindowRef::Entity(surface)) = *target
415+
&& surface == window_entity
416+
{
417+
*surface_size = SurfaceSize(width, height);
418+
}
419+
}
406420
Ok(())
407421
}
408422

@@ -448,6 +462,20 @@ pub fn physical_height(In(entity): In<Entity>, query: Query<&Window>) -> u32 {
448462
.unwrap_or(0)
449463
}
450464

465+
pub fn width(In(entity): In<Entity>, query: Query<&Window>) -> u32 {
466+
query
467+
.get(entity)
468+
.map(|w| w.resolution.width() as u32)
469+
.unwrap_or(0)
470+
}
471+
472+
pub fn height(In(entity): In<Entity>, query: Query<&Window>) -> u32 {
473+
query
474+
.get(entity)
475+
.map(|w| w.resolution.height() as u32)
476+
.unwrap_or(0)
477+
}
478+
451479
pub fn set_title(
452480
In((entity, title)): In<(Entity, String)>,
453481
mut windows: Query<&mut Window>,

0 commit comments

Comments
 (0)