Skip to content

Commit 490aa35

Browse files
committed
Add option to center a window
1 parent b7d784d commit 490aa35

File tree

4 files changed

+79
-25
lines changed

4 files changed

+79
-25
lines changed

crates/bevy_window/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub mod prelude {
1616
#[doc(hidden)]
1717
pub use crate::{
1818
CursorEntered, CursorIcon, CursorLeft, CursorMoved, FileDragAndDrop, ReceivedCharacter,
19-
Window, WindowDescriptor, WindowMoved, Windows,
19+
Window, WindowDescriptor, WindowMoved, WindowPosition, Windows,
2020
};
2121
}
2222

crates/bevy_window/src/window.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ pub enum WindowCommand {
216216
SetPosition {
217217
position: IVec2,
218218
},
219+
Center,
219220
SetResizeConstraints {
220221
resize_constraints: WindowResizeConstraints,
221222
},
@@ -370,6 +371,16 @@ impl Window {
370371
.push(WindowCommand::SetPosition { position });
371372
}
372373

374+
/// Modifies the position of the window to be in the center of the current monitor
375+
///
376+
/// # Platform-specific
377+
/// - iOS: Can only be called on the main thread.
378+
/// - Web / Android / Wayland: Unsupported.
379+
#[inline]
380+
pub fn center_window(&mut self) {
381+
self.command_queue.push(WindowCommand::Center);
382+
}
383+
373384
/// Modifies the minimum and maximum window bounds for resizing in logical pixels.
374385
#[inline]
375386
pub fn set_resize_constraints(&mut self, resize_constraints: WindowResizeConstraints) {
@@ -624,6 +635,17 @@ impl Window {
624635
}
625636
}
626637

638+
/// Defines where window should be placed at creation.
639+
#[derive(Debug, Clone)]
640+
pub enum WindowPosition {
641+
/// Position will be set by window manager
642+
Default,
643+
/// Window will be centered at primary monitor
644+
Centered,
645+
/// Window will be placed at
646+
At(Vec2),
647+
}
648+
627649
/// Describes the information needed for creating a window.
628650
///
629651
/// This should be set up before adding the [`WindowPlugin`](crate::WindowPlugin).
@@ -641,8 +663,8 @@ pub struct WindowDescriptor {
641663
/// May vary from the physical height due to different pixel density on different monitors.
642664
pub height: f32,
643665
/// The position on the screen that the window will be centered at.
644-
/// If set to `None`, some platform-specific position will be chosen.
645-
pub position: Option<Vec2>,
666+
/// See [`WindowPosition`] for available values.
667+
pub position: WindowPosition,
646668
/// Sets minimum and maximum resize limits.
647669
pub resize_constraints: WindowResizeConstraints,
648670
/// Overrides the window's ratio of physical pixels to logical pixels.
@@ -697,7 +719,7 @@ impl Default for WindowDescriptor {
697719
title: "app".to_string(),
698720
width: 1280.,
699721
height: 720.,
700-
position: None,
722+
position: WindowPosition::Default,
701723
resize_constraints: WindowResizeConstraints::default(),
702724
scale_factor_override: None,
703725
present_mode: PresentMode::Fifo,

crates/bevy_winit/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,21 @@ fn change_window(
158158
y: position[1],
159159
});
160160
}
161+
bevy_window::WindowCommand::Center => {
162+
let window = winit_windows.get_window(id).unwrap();
163+
164+
// What to do if current_monitor is None?
165+
// Abort?
166+
// Or use primary_monitor? And then what if that also is None?
167+
let screen_size = window.current_monitor().unwrap().size();
168+
169+
let window_size = window.outer_size();
170+
171+
window.set_outer_position(PhysicalPosition {
172+
x: (screen_size.width - window_size.width) as f64 / 2.,
173+
y: (screen_size.height - window_size.height) as f64 / 2.,
174+
});
175+
}
161176
bevy_window::WindowCommand::SetResizeConstraints { resize_constraints } => {
162177
let window = winit_windows.get_window(id).unwrap();
163178
let constraints = resize_constraints.check_constraints();

crates/bevy_winit/src/winit_windows.rs

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use bevy_math::IVec2;
22
use bevy_utils::HashMap;
33
use bevy_window::{Window, WindowDescriptor, WindowId, WindowMode};
44
use raw_window_handle::HasRawWindowHandle;
5-
use winit::dpi::LogicalSize;
5+
use winit::dpi::{LogicalPosition, LogicalSize, PhysicalPosition};
66

77
#[derive(Debug, Default)]
88
pub struct WinitWindows {
@@ -49,30 +49,47 @@ impl WinitWindows {
4949
..
5050
} = window_descriptor;
5151

52-
if let Some(position) = position {
53-
if let Some(sf) = scale_factor_override {
54-
winit_window_builder = winit_window_builder.with_position(
55-
winit::dpi::LogicalPosition::new(
56-
position[0] as f64,
57-
position[1] as f64,
58-
)
59-
.to_physical::<f64>(*sf),
60-
);
61-
} else {
62-
winit_window_builder =
63-
winit_window_builder.with_position(winit::dpi::LogicalPosition::new(
64-
position[0] as f64,
65-
position[1] as f64,
66-
));
52+
use bevy_window::WindowPosition::*;
53+
match position {
54+
Default => { /* Window manager will handle position*/ }
55+
Centered => {
56+
if let Some(monitor) = event_loop.primary_monitor() {
57+
let screen_size = monitor.size();
58+
59+
let scale_factor = scale_factor_override.unwrap_or(1.0);
60+
61+
// Logical to physical window size
62+
let (width, height): (f64, f64) = LogicalSize::new(*width, *height)
63+
.to_physical::<f64>(scale_factor)
64+
.into();
65+
66+
let position = PhysicalPosition::new(
67+
(screen_size.width as f64 - width) / 2.,
68+
(screen_size.height as f64 - height) / 2.,
69+
);
70+
71+
winit_window_builder = winit_window_builder.with_position(position);
72+
}
73+
}
74+
At(position) => {
75+
if let Some(sf) = scale_factor_override {
76+
winit_window_builder = winit_window_builder.with_position(
77+
LogicalPosition::new(position[0] as f64, position[1] as f64)
78+
.to_physical::<f64>(*sf),
79+
);
80+
} else {
81+
winit_window_builder = winit_window_builder.with_position(
82+
LogicalPosition::new(position[0] as f64, position[1] as f64),
83+
);
84+
}
6785
}
6886
}
87+
6988
if let Some(sf) = scale_factor_override {
70-
winit_window_builder.with_inner_size(
71-
winit::dpi::LogicalSize::new(*width, *height).to_physical::<f64>(*sf),
72-
)
73-
} else {
7489
winit_window_builder
75-
.with_inner_size(winit::dpi::LogicalSize::new(*width, *height))
90+
.with_inner_size(LogicalSize::new(*width, *height).to_physical::<f64>(*sf))
91+
} else {
92+
winit_window_builder.with_inner_size(LogicalSize::new(*width, *height))
7693
}
7794
}
7895
.with_resizable(window_descriptor.resizable)

0 commit comments

Comments
 (0)