Skip to content
Open
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
2 changes: 2 additions & 0 deletions core/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod level;
mod mode;
mod position;
mod redraw_request;
mod size;
mod user_attention;

pub use direction::Direction;
Expand All @@ -22,4 +23,5 @@ pub use position::Position;
pub use redraw_request::RedrawRequest;
pub use screenshot::Screenshot;
pub use settings::Settings;
pub use size::Size;
pub use user_attention::UserAttention;
4 changes: 2 additions & 2 deletions core/src/window/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub use platform::PlatformSpecific;
#[derive(Debug, Clone)]
pub struct Settings {
/// The initial logical dimensions of the window.
pub size: Size,
pub size: crate::window::Size,

/// Whether the window should start maximized.
pub maximized: bool,
Expand Down Expand Up @@ -85,7 +85,7 @@ pub struct Settings {
impl Default for Settings {
fn default() -> Self {
Self {
size: Size::new(1024.0, 768.0),
size: crate::window::Size::default(),
maximized: false,
fullscreen: false,
position: Position::default(),
Expand Down
67 changes: 67 additions & 0 deletions core/src/window/size.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use std::{fmt::Debug, ops::Add, sync::Arc};

/// The size of a window upon creation.
#[derive(Clone)]
pub enum Size {
/// Sets the size of the window directly.
Fixed(crate::Size),
/// Allows you to set the size of the window based on the monitors resolution
///
/// The function receives the the monitor's resolution as input.
FromScreensize(Arc<dyn Send + Sync + Fn(crate::Size) -> crate::Size>),
}

impl Size {
/// Returns the default fixed windows size.
/// The output is an [`iced::Size`].
///
/// If you want to populate the [`iced::window::Settings`], you can use the `default()` function instead.
pub fn default_window_size() -> crate::Size {
crate::Size::new(1024.0, 768.0)
}

pub fn from_screen_size(
func: impl 'static + Send + Sync + Fn(crate::Size) -> crate::Size,
) -> Self {
Self::FromScreensize(Arc::new(func))
}
}

impl Default for Size {
fn default() -> Self {
Self::Fixed(Self::default_window_size())
}
}

impl Debug for Size {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Fixed(size) => write!(f, "Fixed({:?})", size),
Self::FromScreensize(_) => {
write!(f, "FromScreensize(...)")
}
}
}
}

impl<Source> From<Source> for Size
where
Source: Into<crate::Size>,
{
fn from(value: Source) -> Self {
Self::Fixed(value.into())
}
}

impl Add<crate::Size> for Size {
type Output = Self;

fn add(self, other: crate::Size) -> Self {
match self {
Self::Fixed(size) => Self::Fixed(size + other),
Self::FromScreensize(func) => {
Self::from_screen_size(move |size| func(size) + other)
}
}
}
}
2 changes: 1 addition & 1 deletion examples/solar_system/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl State {

pub fn new() -> State {
let now = Instant::now();
let size = window::Settings::default().size;
let size = window::Size::default_window_size();

State {
sun: image::Handle::from_bytes(
Expand Down
6 changes: 3 additions & 3 deletions src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ use crate::shell;
use crate::theme;
use crate::window;
use crate::{
Element, Executor, Font, Preset, Result, Settings, Size, Subscription,
Task, Theme,
Element, Executor, Font, Preset, Result, Settings, Subscription, Task,
Theme,
};

use iced_debug as debug;
Expand Down Expand Up @@ -277,7 +277,7 @@ impl<P: Program> Application<P> {
}

/// Sets the [`window::Settings::size`] of the [`Application`].
pub fn window_size(self, size: impl Into<Size>) -> Self {
pub fn window_size(self, size: impl Into<crate::window::Size>) -> Self {
Self {
window: window::Settings {
size: size.into(),
Expand Down
2 changes: 1 addition & 1 deletion test/src/simulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ where
settings: Settings,
element: impl Into<Element<'a, Message, Theme, Renderer>>,
) -> Self {
Self::with_size(settings, window::Settings::default().size, element)
Self::with_size(settings, window::Size::default_window_size(), element)
}

/// Creates a new [`Simulator`] with the given [`Settings`] and size.
Expand Down
10 changes: 9 additions & 1 deletion tester/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,17 @@ impl<P: Program + 'static> Tester<P> {
let (state, _) = program.boot();
let window = program.window().unwrap_or_default();

let size = match window.size {
window::Size::Fixed(size) => size,
// Since there is no monitor, we fall back to a default size
window::Size::FromScreensize(_) => {
window::Size::default_window_size()
}
};

Self {
mode: emulator::Mode::default(),
viewport: window.size,
viewport: size,
presets: combo_box::State::new(
program
.presets()
Expand Down
123 changes: 73 additions & 50 deletions winit/src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ pub fn window_attributes(

attributes = attributes
.with_title(title)
.with_inner_size(winit::dpi::LogicalSize {
width: settings.size.width * scale_factor,
height: settings.size.height * scale_factor,
})
.with_maximized(settings.maximized)
.with_fullscreen(
settings
Expand All @@ -45,8 +41,17 @@ pub fn window_attributes(
.with_window_level(window_level(settings.level))
.with_visible(settings.visible);

let size = size(primary_monitor.as_ref(), settings.size, scale_factor);

if let Some(size) = size {
attributes = attributes.with_inner_size(winit::dpi::LogicalSize {
width: size.width,
height: size.height,
});
}

if let Some(position) =
position(primary_monitor.as_ref(), settings.size, settings.position)
position(primary_monitor.as_ref(), size, settings.position)
{
attributes = attributes.with_position(position);
}
Expand Down Expand Up @@ -336,12 +341,36 @@ pub fn window_level(level: window::Level) -> winit::window::WindowLevel {
}
}

/// Converts a [`window::Size`] into a [`winit`] logical size for a given monitor and scale factor.
///
/// [`winit`]: https://github.com/rust-windowing/winit
pub fn size(
monitor: Option<&winit::monitor::MonitorHandle>,
size: window::Size,
scale_factor: f32,
) -> Option<crate::Size> {
let monitor = monitor?;

match size {
window::Size::Fixed(size) => Some(size * scale_factor),
window::Size::FromScreensize(to_size) => {
let resolution: winit::dpi::LogicalSize<f32> =
monitor.size().to_logical(monitor.scale_factor());

let size = to_size(Size::new(resolution.width, resolution.height))
* scale_factor;

Some(size)
}
}
}

/// Converts a [`window::Position`] into a [`winit`] logical position for a given monitor.
///
/// [`winit`]: https://github.com/rust-windowing/winit
pub fn position(
monitor: Option<&winit::monitor::MonitorHandle>,
size: Size,
size: Option<Size>,
position: window::Position,
) -> Option<winit::dpi::Position> {
match position {
Expand All @@ -353,57 +382,51 @@ pub fn position(
}))
}
window::Position::SpecificWith(to_position) => {
if let Some(monitor) = monitor {
let start = monitor.position();
let (monitor, size) = monitor.zip(size)?;
let start = monitor.position();

let resolution: winit::dpi::LogicalSize<f32> =
monitor.size().to_logical(monitor.scale_factor());

let position = to_position(
size,
Size::new(resolution.width, resolution.height),
);
let resolution: winit::dpi::LogicalSize<f32> =
monitor.size().to_logical(monitor.scale_factor());

let centered: winit::dpi::PhysicalPosition<i32> =
winit::dpi::LogicalPosition {
x: position.x,
y: position.y,
}
.to_physical(monitor.scale_factor());
let position = to_position(
size,
Size::new(resolution.width, resolution.height),
);

Some(winit::dpi::Position::Physical(
winit::dpi::PhysicalPosition {
x: start.x + centered.x,
y: start.y + centered.y,
},
))
} else {
None
}
let centered: winit::dpi::PhysicalPosition<i32> =
winit::dpi::LogicalPosition {
x: position.x,
y: position.y,
}
.to_physical(monitor.scale_factor());

Some(winit::dpi::Position::Physical(
winit::dpi::PhysicalPosition {
x: start.x + centered.x,
y: start.y + centered.y,
},
))
}
window::Position::Centered => {
if let Some(monitor) = monitor {
let start = monitor.position();
let (monitor, size) = monitor.zip(size)?;
let start = monitor.position();

let resolution: winit::dpi::LogicalSize<f64> =
monitor.size().to_logical(monitor.scale_factor());

let centered: winit::dpi::PhysicalPosition<i32> =
winit::dpi::LogicalPosition {
x: (resolution.width - f64::from(size.width)) / 2.0,
y: (resolution.height - f64::from(size.height)) / 2.0,
}
.to_physical(monitor.scale_factor());
let resolution: winit::dpi::LogicalSize<f64> =
monitor.size().to_logical(monitor.scale_factor());

Some(winit::dpi::Position::Physical(
winit::dpi::PhysicalPosition {
x: start.x + centered.x,
y: start.y + centered.y,
},
))
} else {
None
}
let centered: winit::dpi::PhysicalPosition<i32> =
winit::dpi::LogicalPosition {
x: (resolution.width - f64::from(size.width)) / 2.0,
y: (resolution.height - f64::from(size.height)) / 2.0,
}
.to_physical(monitor.scale_factor());

Some(winit::dpi::Position::Physical(
winit::dpi::PhysicalPosition {
x: start.x + centered.x,
y: start.y + centered.y,
},
))
}
}
}
Expand Down