Skip to content

Commit

Permalink
Add option to center a window
Browse files Browse the repository at this point in the history
  • Loading branch information
LoipesMas committed Jun 13, 2022
1 parent b7d784d commit f6fee60
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 25 deletions.
2 changes: 1 addition & 1 deletion crates/bevy_window/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub mod prelude {
#[doc(hidden)]
pub use crate::{
CursorEntered, CursorIcon, CursorLeft, CursorMoved, FileDragAndDrop, ReceivedCharacter,
Window, WindowDescriptor, WindowMoved, Windows,
Window, WindowDescriptor, WindowMoved, WindowPosition, Windows,
};
}

Expand Down
28 changes: 25 additions & 3 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ pub enum WindowCommand {
SetPosition {
position: IVec2,
},
Center,
SetResizeConstraints {
resize_constraints: WindowResizeConstraints,
},
Expand Down Expand Up @@ -370,6 +371,16 @@ impl Window {
.push(WindowCommand::SetPosition { position });
}

/// Modifies the position of the window to be in the center of the current monitor
///
/// # Platform-specific
/// - iOS: Can only be called on the main thread.
/// - Web / Android / Wayland: Unsupported.
#[inline]
pub fn center_window(&mut self) {
self.command_queue.push(WindowCommand::Center);
}

/// Modifies the minimum and maximum window bounds for resizing in logical pixels.
#[inline]
pub fn set_resize_constraints(&mut self, resize_constraints: WindowResizeConstraints) {
Expand Down Expand Up @@ -624,6 +635,17 @@ impl Window {
}
}

/// Defines where window should be placed at on creation.
#[derive(Debug, Clone)]
pub enum WindowPosition {
/// Position will be set by window manager
Default,
/// Window will be centered at primary monitor
Centered,
/// Window will be placed at specified position
At(Vec2),
}

/// Describes the information needed for creating a window.
///
/// This should be set up before adding the [`WindowPlugin`](crate::WindowPlugin).
Expand All @@ -641,8 +663,8 @@ pub struct WindowDescriptor {
/// May vary from the physical height due to different pixel density on different monitors.
pub height: f32,
/// The position on the screen that the window will be centered at.
/// If set to `None`, some platform-specific position will be chosen.
pub position: Option<Vec2>,
/// See [`WindowPosition`] for available values.
pub position: WindowPosition,
/// Sets minimum and maximum resize limits.
pub resize_constraints: WindowResizeConstraints,
/// Overrides the window's ratio of physical pixels to logical pixels.
Expand Down Expand Up @@ -697,7 +719,7 @@ impl Default for WindowDescriptor {
title: "app".to_string(),
width: 1280.,
height: 720.,
position: None,
position: WindowPosition::Default,
resize_constraints: WindowResizeConstraints::default(),
scale_factor_override: None,
present_mode: PresentMode::Fifo,
Expand Down
15 changes: 15 additions & 0 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,21 @@ fn change_window(
y: position[1],
});
}
bevy_window::WindowCommand::Center => {
let window = winit_windows.get_window(id).unwrap();

// What to do if current_monitor is None?
// Abort?
// Or use primary_monitor? And then what if that also is None?
let screen_size = window.current_monitor().unwrap().size();

let window_size = window.outer_size();

window.set_outer_position(PhysicalPosition {
x: (screen_size.width - window_size.width) as f64 / 2.,
y: (screen_size.height - window_size.height) as f64 / 2.,
});
}
bevy_window::WindowCommand::SetResizeConstraints { resize_constraints } => {
let window = winit_windows.get_window(id).unwrap();
let constraints = resize_constraints.check_constraints();
Expand Down
59 changes: 38 additions & 21 deletions crates/bevy_winit/src/winit_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use bevy_math::IVec2;
use bevy_utils::HashMap;
use bevy_window::{Window, WindowDescriptor, WindowId, WindowMode};
use raw_window_handle::HasRawWindowHandle;
use winit::dpi::LogicalSize;
use winit::dpi::{LogicalPosition, LogicalSize, PhysicalPosition};

#[derive(Debug, Default)]
pub struct WinitWindows {
Expand Down Expand Up @@ -49,30 +49,47 @@ impl WinitWindows {
..
} = window_descriptor;

if let Some(position) = position {
if let Some(sf) = scale_factor_override {
winit_window_builder = winit_window_builder.with_position(
winit::dpi::LogicalPosition::new(
position[0] as f64,
position[1] as f64,
)
.to_physical::<f64>(*sf),
);
} else {
winit_window_builder =
winit_window_builder.with_position(winit::dpi::LogicalPosition::new(
position[0] as f64,
position[1] as f64,
));
use bevy_window::WindowPosition::*;
match position {
Default => { /* Window manager will handle position */ }
Centered => {
if let Some(monitor) = event_loop.primary_monitor() {
let screen_size = monitor.size();

let scale_factor = scale_factor_override.unwrap_or(1.0);

// Logical to physical window size
let (width, height): (f64, f64) = LogicalSize::new(*width, *height)
.to_physical::<f64>(scale_factor)
.into();

let position = PhysicalPosition::new(
(screen_size.width as f64 - width) / 2.,
(screen_size.height as f64 - height) / 2.,
);

winit_window_builder = winit_window_builder.with_position(position);
}
}
At(position) => {
if let Some(sf) = scale_factor_override {
winit_window_builder = winit_window_builder.with_position(
LogicalPosition::new(position[0] as f64, position[1] as f64)
.to_physical::<f64>(*sf),
);
} else {
winit_window_builder = winit_window_builder.with_position(
LogicalPosition::new(position[0] as f64, position[1] as f64),
);
}
}
}

if let Some(sf) = scale_factor_override {
winit_window_builder.with_inner_size(
winit::dpi::LogicalSize::new(*width, *height).to_physical::<f64>(*sf),
)
} else {
winit_window_builder
.with_inner_size(winit::dpi::LogicalSize::new(*width, *height))
.with_inner_size(LogicalSize::new(*width, *height).to_physical::<f64>(*sf))
} else {
winit_window_builder.with_inner_size(LogicalSize::new(*width, *height))
}
}
.with_resizable(window_descriptor.resizable)
Expand Down

0 comments on commit f6fee60

Please sign in to comment.