Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions crates/processing_glfw/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use processing_core::error::Result;
use processing_input::{
input_cursor_grab_mode, input_cursor_visible, input_flush, input_set_char,
input_set_cursor_enter, input_set_cursor_leave, input_set_focus, input_set_key,
input_set_mouse_button, input_set_mouse_move, input_set_scroll,
input_set_mouse_button, input_set_mouse_move, input_set_scroll, input_window_resize,
};
use processing_render::surface::{MonitorWorkarea, WindowControls};

Expand Down Expand Up @@ -256,6 +256,7 @@ impl GlfwContext {
}
};

let mut pending_resize: Option<(i32, i32)> = None;
for (_, event) in glfw::flush_messages(&self.events) {
match event {
WindowEvent::Close => {
Expand Down Expand Up @@ -300,6 +301,10 @@ impl GlfwContext {
WindowEvent::Focus(focused) => {
input_set_focus(surface, focused).unwrap();
}
WindowEvent::Size(width, height) => {
// A drag delivers many Size events per poll; keep only the last and apply it once after the loop.
pending_resize = Some((width, height));
}
_ => {}
}
}
Expand All @@ -309,6 +314,12 @@ impl GlfwContext {
return false;
}

// Apply the coalesced resize once, the WindowResized message and Window change are processed this poll.
if let Some((width, height)) = pending_resize {
input_window_resize(surface, width as f32, height as f32).unwrap();
processing_render::surface_resize(surface, width as u32, height as u32).unwrap();
}

let Ok(_) = input_flush() else {
return false;
};
Expand Down Expand Up @@ -355,6 +366,9 @@ impl GlfwContext {
Ok(())
});
self.last_applied.position = frame_pos;

let (w, h) = self.window.get_size();
self.last_applied.size = bevy::math::UVec2::new(w.max(0) as u32, h.max(0) as u32);
}

#[cfg(not(feature = "wayland"))]
Expand Down Expand Up @@ -529,8 +543,8 @@ fn read_desired_window(surface: Entity) -> Option<DesiredWindow> {
_ => None,
},
size: bevy::math::UVec2::new(
window.resolution.physical_width(),
window.resolution.physical_height(),
window.resolution.width() as u32,
window.resolution.height() as u32,
),
visible: window.visible,
resizable: window.resizable,
Expand Down
13 changes: 12 additions & 1 deletion crates/processing_input/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use bevy::input::mouse::{
};
use bevy::input::touch::TouchPhase;
use bevy::prelude::*;
use bevy::window::CursorMoved;
use bevy::window::{CursorMoved, WindowResized};

use processing_core::app_mut;
use processing_core::error;
Expand Down Expand Up @@ -342,3 +342,14 @@ pub fn input_mouse_scrolled() -> error::Result<bool> {
Ok(d.x != 0.0 || d.y != 0.0)
})
}

pub fn input_window_resize(surface: Entity, width: f32, height: f32) -> error::Result<()> {
app_mut(|app| {
app.world_mut().write_message(WindowResized {
window: surface,
width,
height,
});
Ok(())
})
}
13 changes: 6 additions & 7 deletions crates/processing_pyo3/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,12 @@ pub(crate) fn reset_tracked_globals() {
fn sync_globals(module: &Bound<'_, PyModule>, globals: &Bound<'_, PyAny>) -> PyResult<()> {
let graphics =
get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?;
input::sync_globals(
globals,
graphics.surface.entity,
graphics.width,
graphics.height,
)?;
surface::sync_globals(globals, &graphics.surface, graphics.width, graphics.height)?;
let width = ::processing::prelude::surface_width(graphics.surface.entity)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
let height = ::processing::prelude::surface_height(graphics.surface.entity)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
input::sync_globals(globals, graphics.surface.entity, width, height)?;
surface::sync_globals(globals, &graphics.surface, width, height)?;
time::sync_globals(globals)?;
Ok(())
}
Expand Down
3 changes: 2 additions & 1 deletion crates/processing_render/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ impl CameraProjection for ProcessingProjection {
fn update(&mut self, _width: f32, _height: f32) {
// this gets called with the render target's physical dimensions (i.e. accounting for
// scale factor), but our projection is in logical pixel units
// TODO: handle resizes?
self.width = _width;
self.height = _height;
}

fn far(&self) -> f32 {
Expand Down
18 changes: 18 additions & 0 deletions crates/processing_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1702,6 +1702,24 @@ pub fn surface_physical_height(entity: Entity) -> error::Result<u32> {
})
}

pub fn surface_width(entity: Entity) -> error::Result<u32> {
app_mut(|app| {
Ok(app
.world_mut()
.run_system_cached_with(surface::width, entity)
.unwrap())
})
}

pub fn surface_height(entity: Entity) -> error::Result<u32> {
app_mut(|app| {
Ok(app
.world_mut()
.run_system_cached_with(surface::height, entity)
.unwrap())
})
}

pub fn monitor_list() -> error::Result<Vec<Entity>> {
app_mut(|app| Ok(app.world_mut().run_system_cached(monitor::list).unwrap()))
}
Expand Down
32 changes: 30 additions & 2 deletions crates/processing_render/src/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@
use bevy::{
app::{App, Plugin},
asset::Assets,
camera::RenderTarget,
ecs::query::QueryEntityError,
math::{IRect, IVec2},
prelude::{Commands, Component, Entity, In, Query, ResMut, Window, With, default},
render::render_resource::{Extent3d, TextureFormat},
window::{
CompositeAlphaMode, Monitor, RawHandleWrapper, WindowLevel, WindowMode, WindowPosition,
WindowResolution, WindowWrapper,
WindowRef, WindowResolution, WindowWrapper,
},
};
use raw_window_handle::{
Expand All @@ -39,7 +40,7 @@ use processing_core::error::{self, ProcessingError, Result};
#[cfg(not(target_os = "windows"))]
use std::ptr::NonNull;

use crate::image::Image;
use crate::{graphics::SurfaceSize, image::Image};

#[derive(Component, Debug, Clone)]
pub struct Surface;
Expand Down Expand Up @@ -394,7 +395,11 @@ pub fn destroy(
pub fn resize(
In((window_entity, width, height)): In<(Entity, u32, u32)>,
mut windows: Query<&mut Window>,
mut graphics_query: Query<(&RenderTarget, &mut SurfaceSize)>,
) -> Result<()> {
let width = width.max(1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so width and height are clamped between 0 and 1?

@arrxy arrxy Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let width = width.max(1);
This is width = max(width, 1), as 0 or negative width and height are not handled.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arrxy i'm asking about 1. what is the significance there?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh I put the min limit 1, so that the box cannot be shrinked to nothing.

let height = height.max(1);

if let Ok(mut window) = windows.get_mut(window_entity) {
let scale = window.resolution.scale_factor();
let physical_w = (width as f32 * scale) as u32;
Expand All @@ -403,6 +408,15 @@ pub fn resize(
.resolution
.set_physical_resolution(physical_w, physical_h);
}

// SurfaceSize changes on resize, if not handled will break APIs dependent on correct SurfaceSize
for (target, mut surface_size) in graphics_query.iter_mut() {
if let RenderTarget::Window(WindowRef::Entity(surface)) = *target
&& surface == window_entity
{
*surface_size = SurfaceSize(width, height);
}
}
Ok(())
}

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

pub fn width(In(entity): In<Entity>, query: Query<&Window>) -> u32 {
query
.get(entity)
.map(|w| w.resolution.width() as u32)
.unwrap_or(0)
}

pub fn height(In(entity): In<Entity>, query: Query<&Window>) -> u32 {
query
.get(entity)
.map(|w| w.resolution.height() as u32)
.unwrap_or(0)
}

pub fn set_title(
In((entity, title)): In<(Entity, String)>,
mut windows: Query<&mut Window>,
Expand Down
Loading