mirror of
https://github.com/rust-windowing/winit.git
synced 2026-08-29 04:40:04 -04:00
wayland: implement resize increments
This commit is contained in:
@@ -834,7 +834,7 @@ pub trait Window: AsAny + Send + Sync + fmt::Debug {
|
|||||||
///
|
///
|
||||||
/// ## Platform-specific
|
/// ## Platform-specific
|
||||||
///
|
///
|
||||||
/// - **iOS / Android / Web / Wayland / Orbital:** Always returns [`None`].
|
/// - **iOS / Android / Web / Orbital:** Always returns [`None`].
|
||||||
fn surface_resize_increments(&self) -> Option<PhysicalSize<u32>>;
|
fn surface_resize_increments(&self) -> Option<PhysicalSize<u32>>;
|
||||||
|
|
||||||
/// Sets resize increments of the surface.
|
/// Sets resize increments of the surface.
|
||||||
@@ -846,7 +846,6 @@ pub trait Window: AsAny + Send + Sync + fmt::Debug {
|
|||||||
///
|
///
|
||||||
/// - **macOS:** Increments are converted to logical size and then macOS rounds them to whole
|
/// - **macOS:** Increments are converted to logical size and then macOS rounds them to whole
|
||||||
/// numbers.
|
/// numbers.
|
||||||
/// - **Wayland:** Not implemented.
|
|
||||||
/// - **iOS / Android / Web / Orbital:** Unsupported.
|
/// - **iOS / Android / Web / Orbital:** Unsupported.
|
||||||
fn set_surface_resize_increments(&self, increments: Option<Size>);
|
fn set_surface_resize_increments(&self, increments: Option<Size>);
|
||||||
|
|
||||||
|
|||||||
@@ -171,6 +171,12 @@ impl Window {
|
|||||||
Cursor::Custom(cursor) => window_state.set_custom_cursor(cursor),
|
Cursor::Custom(cursor) => window_state.set_custom_cursor(cursor),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply resize increments.
|
||||||
|
if let Some(increments) = attributes.surface_resize_increments {
|
||||||
|
let increments = increments.to_logical(window_state.scale_factor());
|
||||||
|
window_state.set_resize_increments(Some(increments));
|
||||||
|
}
|
||||||
|
|
||||||
// Activate the window when the token is passed.
|
// Activate the window when the token is passed.
|
||||||
if let (Some(xdg_activation), Some(token)) = (xdg_activation.as_ref(), activation_token) {
|
if let (Some(xdg_activation), Some(token)) = (xdg_activation.as_ref(), activation_token) {
|
||||||
xdg_activation.activate(token.into_raw(), &surface);
|
xdg_activation.activate(token.into_raw(), &surface);
|
||||||
@@ -370,11 +376,18 @@ impl CoreWindow for Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn surface_resize_increments(&self) -> Option<PhysicalSize<u32>> {
|
fn surface_resize_increments(&self) -> Option<PhysicalSize<u32>> {
|
||||||
None
|
let window_state = self.window_state.lock().unwrap();
|
||||||
|
let scale_factor = window_state.scale_factor();
|
||||||
|
window_state
|
||||||
|
.resize_increments()
|
||||||
|
.map(|size| super::logical_to_physical_rounded(size, scale_factor))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_surface_resize_increments(&self, _increments: Option<Size>) {
|
fn set_surface_resize_increments(&self, increments: Option<Size>) {
|
||||||
warn!("`set_surface_resize_increments` is not implemented for Wayland");
|
let mut window_state = self.window_state.lock().unwrap();
|
||||||
|
let scale_factor = window_state.scale_factor();
|
||||||
|
let increments = increments.map(|size| size.to_logical(scale_factor));
|
||||||
|
window_state.set_resize_increments(increments);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_title(&self, title: &str) {
|
fn set_title(&self, title: &str) {
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ pub struct WindowState {
|
|||||||
/// Min size.
|
/// Min size.
|
||||||
min_surface_size: LogicalSize<u32>,
|
min_surface_size: LogicalSize<u32>,
|
||||||
max_surface_size: Option<LogicalSize<u32>>,
|
max_surface_size: Option<LogicalSize<u32>>,
|
||||||
|
resize_increments: Option<LogicalSize<u32>>,
|
||||||
|
|
||||||
/// The size of the window when no states were applied to it. The primary use for it
|
/// The size of the window when no states were applied to it. The primary use for it
|
||||||
/// is to fallback to original window size, before it was maximized, if the compositor
|
/// is to fallback to original window size, before it was maximized, if the compositor
|
||||||
@@ -223,6 +224,7 @@ impl WindowState {
|
|||||||
last_configure: None,
|
last_configure: None,
|
||||||
max_surface_size: None,
|
max_surface_size: None,
|
||||||
min_surface_size: MIN_WINDOW_SIZE,
|
min_surface_size: MIN_WINDOW_SIZE,
|
||||||
|
resize_increments: None,
|
||||||
pointer_constraints,
|
pointer_constraints,
|
||||||
pointers: Default::default(),
|
pointers: Default::default(),
|
||||||
queue_handle: queue_handle.clone(),
|
queue_handle: queue_handle.clone(),
|
||||||
@@ -361,6 +363,42 @@ impl WindowState {
|
|||||||
.unwrap_or(new_size.height);
|
.unwrap_or(new_size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply size increments.
|
||||||
|
//
|
||||||
|
// We conditionally apply increments to avoid conflicts with the compositor's layout rules:
|
||||||
|
// 1. If the window is floating (constrain == true), we snap to increments to ensure the
|
||||||
|
// app's grid alignment.
|
||||||
|
// 2. If the user is interactively resizing (is_resizing), we snap the size to provide
|
||||||
|
// feedback.
|
||||||
|
//
|
||||||
|
// However, we MUST NOT snap if the compositor enforces a specific size (constrain == false,
|
||||||
|
// or states like Maximized/Tiled). Snapping in these cases (e.g. corner tiling) would
|
||||||
|
// shrink the window below the allocated area, creating visible gaps between valid
|
||||||
|
// windows or screen edges.
|
||||||
|
if (constrain || configure.is_resizing())
|
||||||
|
&& !configure.is_maximized()
|
||||||
|
&& !configure.is_fullscreen()
|
||||||
|
&& !configure.is_tiled()
|
||||||
|
{
|
||||||
|
if let Some(increments) = self.resize_increments {
|
||||||
|
// We use min size as a base size for the increments, similar to how X11 does it.
|
||||||
|
//
|
||||||
|
// This ensures that we can always reach the min size and the increments are
|
||||||
|
// calculated from it.
|
||||||
|
let (delta_width, delta_height) = (
|
||||||
|
new_size.width.saturating_sub(self.min_surface_size.width),
|
||||||
|
new_size.height.saturating_sub(self.min_surface_size.height),
|
||||||
|
);
|
||||||
|
|
||||||
|
let width = self.min_surface_size.width
|
||||||
|
+ (delta_width / increments.width) * increments.width;
|
||||||
|
let height = self.min_surface_size.height
|
||||||
|
+ (delta_height / increments.height) * increments.height;
|
||||||
|
|
||||||
|
new_size = (width, height).into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let new_state = configure.state;
|
let new_state = configure.state;
|
||||||
let old_state = self.last_configure.as_ref().map(|configure| configure.state);
|
let old_state = self.last_configure.as_ref().map(|configure| configure.state);
|
||||||
|
|
||||||
@@ -749,6 +787,18 @@ impl WindowState {
|
|||||||
self.selected_cursor = SelectedCursor::Custom(cursor);
|
self.selected_cursor = SelectedCursor::Custom(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the resize increments of the window.
|
||||||
|
pub fn set_resize_increments(&mut self, increments: Option<LogicalSize<u32>>) {
|
||||||
|
self.resize_increments = increments;
|
||||||
|
// NOTE: We don't update the window size here, because it will be done on the next resize
|
||||||
|
// or configure event.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the resize increments of the window.
|
||||||
|
pub fn resize_increments(&self) -> Option<LogicalSize<u32>> {
|
||||||
|
self.resize_increments
|
||||||
|
}
|
||||||
|
|
||||||
fn apply_custom_cursor(&self, cursor: &CustomCursor) {
|
fn apply_custom_cursor(&self, cursor: &CustomCursor) {
|
||||||
self.apply_on_pointer(|pointer, data| {
|
self.apply_on_pointer(|pointer, data| {
|
||||||
let surface = pointer.surface();
|
let surface = pointer.surface();
|
||||||
|
|||||||
Reference in New Issue
Block a user