Skip to content

Commit

Permalink
Added use_dpi setting to WindowDescriptor (#1131)
Browse files Browse the repository at this point in the history
Added scale_factor_override
  • Loading branch information
TheRawMeatball authored Dec 28, 2020
1 parent 4825051 commit 3cb2e22
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 36 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ path = "examples/window/clear_color.rs"
name = "multiple_windows"
path = "examples/window/multiple_windows.rs"

[[example]]
name = "scale_factor_override"
path = "examples/window/scale_factor_override.rs"

[[example]]
name = "window_settings"
path = "examples/window/window_settings.rs"
Expand Down
41 changes: 32 additions & 9 deletions crates/bevy_ui/src/flex/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
mod convert;

use crate::{Node, Style};
use bevy_ecs::{Changed, Entity, Query, Res, ResMut, With, Without};
use bevy_app::{EventReader, Events};
use bevy_ecs::{Changed, Entity, Local, Query, QueryFilter, Res, ResMut, With, Without};
use bevy_math::Vec2;
use bevy_text::CalculatedSize;
use bevy_transform::prelude::{Children, Parent, Transform};
use bevy_utils::HashMap;
use bevy_window::{Window, WindowId, Windows};
use bevy_window::{Window, WindowId, WindowScaleFactorChanged, Windows};
use std::fmt;
use stretch::{number::Number, Stretch};

Expand Down Expand Up @@ -161,11 +162,15 @@ impl FlexSurface {
unsafe impl Send for FlexSurface {}
unsafe impl Sync for FlexSurface {}

#[allow(clippy::too_many_arguments)]
pub fn flex_node_system(
windows: Res<Windows>,
mut scale_factor_reader: Local<EventReader<WindowScaleFactorChanged>>,
scale_factor_events: Res<Events<WindowScaleFactorChanged>>,
mut flex_surface: ResMut<FlexSurface>,
root_node_query: Query<Entity, (With<Node>, Without<Parent>)>,
node_query: Query<(Entity, &Style, Option<&CalculatedSize>), (With<Node>, Changed<Style>)>,
full_node_query: Query<(Entity, &Style, Option<&CalculatedSize>), With<Node>>,
changed_size_query: Query<
(Entity, &Style, &CalculatedSize),
(With<Node>, Changed<CalculatedSize>),
Expand All @@ -185,13 +190,31 @@ pub fn flex_node_system(
1.
};

// update changed nodes
for (entity, style, calculated_size) in node_query.iter() {
// TODO: remove node from old hierarchy if its root has changed
if let Some(calculated_size) = calculated_size {
flex_surface.upsert_leaf(entity, &style, *calculated_size, logical_to_physical_factor);
} else {
flex_surface.upsert_node(entity, &style, logical_to_physical_factor);
if scale_factor_reader.latest(&scale_factor_events).is_some() {
update_changed(
&mut *flex_surface,
logical_to_physical_factor,
full_node_query,
);
} else {
update_changed(&mut *flex_surface, logical_to_physical_factor, node_query);
}

fn update_changed<F>(
flex_surface: &mut FlexSurface,
scaling_factor: f64,
query: Query<(Entity, &Style, Option<&CalculatedSize>), F>,
) where
F: QueryFilter,
{
// update changed nodes
for (entity, style, calculated_size) in query.iter() {
// TODO: remove node from old hierarchy if its root has changed
if let Some(calculated_size) = calculated_size {
flex_surface.upsert_leaf(entity, &style, *calculated_size, scaling_factor);
} else {
flex_surface.upsert_node(entity, &style, scaling_factor);
}
}
}

Expand Down
13 changes: 13 additions & 0 deletions crates/bevy_window/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,16 @@ pub struct WindowFocused {
pub id: WindowId,
pub focused: bool,
}

/// An event that indicates a window's scale factor has changed.
#[derive(Debug, Clone)]
pub struct WindowScaleFactorChanged {
pub id: WindowId,
pub scale_factor: f64,
}
/// An event that indicates a window's OS-reported scale factor has changed.
#[derive(Debug, Clone)]
pub struct WindowBackendScaleFactorChanged {
pub id: WindowId,
pub scale_factor: f64,
}
2 changes: 2 additions & 0 deletions crates/bevy_window/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ impl Plugin for WindowPlugin {
.add_event::<CursorLeft>()
.add_event::<ReceivedCharacter>()
.add_event::<WindowFocused>()
.add_event::<WindowScaleFactorChanged>()
.add_event::<WindowBackendScaleFactorChanged>()
.init_resource::<Windows>();

if self.add_primary_window {
Expand Down
60 changes: 51 additions & 9 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ pub struct Window {
requested_height: f32,
physical_width: u32,
physical_height: u32,
scale_factor: f64,
scale_factor_override: Option<f64>,
backend_scale_factor: f64,
title: String,
vsync: bool,
resizable: bool,
Expand All @@ -77,8 +78,12 @@ pub enum WindowCommand {
SetTitle {
title: String,
},
SetScaleFactor {
scale_factor: f64,
},
SetResolution {
resolution: (f32, f32),
logical_resolution: (f32, f32),
scale_factor: f64,
},
SetVsync {
vsync: bool,
Expand Down Expand Up @@ -129,7 +134,8 @@ impl Window {
requested_height: window_descriptor.height,
physical_width,
physical_height,
scale_factor,
scale_factor_override: window_descriptor.scale_factor_override,
backend_scale_factor: scale_factor,
title: window_descriptor.title.clone(),
vsync: window_descriptor.vsync,
resizable: window_descriptor.resizable,
Expand All @@ -152,13 +158,13 @@ impl Window {
/// The current logical width of the window's client area.
#[inline]
pub fn width(&self) -> f32 {
(self.physical_width as f64 / self.scale_factor) as f32
(self.physical_width as f64 / self.scale_factor()) as f32
}

/// The current logical height of the window's client area.
#[inline]
pub fn height(&self) -> f32 {
(self.physical_height as f64 / self.scale_factor) as f32
(self.physical_height as f64 / self.scale_factor()) as f32
}

/// The requested window client area width in logical pixels from window
Expand Down Expand Up @@ -201,18 +207,40 @@ impl Window {

/// Request the OS to resize the window such the the client area matches the
/// specified width and height.
#[allow(clippy::float_cmp)]
pub fn set_resolution(&mut self, width: f32, height: f32) {
if self.requested_width == width && self.requested_height == height {
return;
}
self.requested_width = width;
self.requested_height = height;
self.command_queue.push(WindowCommand::SetResolution {
resolution: (self.requested_width, self.requested_height),
logical_resolution: (self.requested_width, self.requested_height),
scale_factor: self.scale_factor(),
});
}

/// Override the os-reported scaling factor
#[allow(clippy::float_cmp)]
pub fn set_scale_factor_override(&mut self, scale_factor: Option<f64>) {
if self.scale_factor_override == scale_factor {
return;
}

self.scale_factor_override = scale_factor;
self.command_queue.push(WindowCommand::SetScaleFactor {
scale_factor: self.scale_factor(),
});
self.command_queue.push(WindowCommand::SetResolution {
logical_resolution: (self.requested_width, self.requested_height),
scale_factor: self.scale_factor(),
});
}

#[allow(missing_docs)]
#[inline]
pub fn update_scale_factor_from_backend(&mut self, scale_factor: f64) {
self.scale_factor = scale_factor;
self.backend_scale_factor = scale_factor;
}

#[allow(missing_docs)]
Expand All @@ -225,9 +253,21 @@ impl Window {
/// The ratio of physical pixels to logical pixels
///
/// `physical_pixels = logical_pixels * scale_factor`
#[inline]
pub fn scale_factor(&self) -> f64 {
self.scale_factor
self.scale_factor_override
.unwrap_or(self.backend_scale_factor)
}

/// The window scale factor as reported by the window backend.
/// This value is unaffected by scale_factor_override.
#[inline]
pub fn backend_scale_factor(&self) -> f64 {
self.backend_scale_factor
}

#[inline]
pub fn scale_factor_override(&self) -> Option<f64> {
self.scale_factor_override
}

#[inline]
Expand Down Expand Up @@ -335,6 +375,7 @@ impl Window {
pub struct WindowDescriptor {
pub width: f32,
pub height: f32,
pub scale_factor_override: Option<f64>,
pub title: String,
pub vsync: bool,
pub resizable: bool,
Expand All @@ -352,6 +393,7 @@ impl Default for WindowDescriptor {
title: "bevy".to_string(),
width: 1280.,
height: 720.,
scale_factor_override: None,
vsync: true,
resizable: true,
decorations: true,
Expand Down
59 changes: 49 additions & 10 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ use bevy_ecs::{IntoSystem, Resources, World};
use bevy_math::Vec2;
use bevy_utils::tracing::{error, trace, warn};
use bevy_window::{
CreateWindow, CursorEntered, CursorLeft, CursorMoved, ReceivedCharacter, WindowCloseRequested,
WindowCreated, WindowFocused, WindowResized, Windows,
CreateWindow, CursorEntered, CursorLeft, CursorMoved, ReceivedCharacter,
WindowBackendScaleFactorChanged, WindowCloseRequested, WindowCreated, WindowFocused,
WindowResized, WindowScaleFactorChanged, Windows,
};
use winit::{
event::{self, DeviceEvent, Event, WindowEvent},
Expand Down Expand Up @@ -76,14 +77,21 @@ fn change_window(_: &mut World, resources: &mut Resources) {
let window = winit_windows.get_window(id).unwrap();
window.set_title(&title);
}
bevy_window::WindowCommand::SetScaleFactor { scale_factor } => {
let mut window_dpi_changed_events = resources
.get_mut::<Events<WindowScaleFactorChanged>>()
.unwrap();
window_dpi_changed_events.send(WindowScaleFactorChanged { id, scale_factor });
}
bevy_window::WindowCommand::SetResolution {
resolution: (logical_width, logical_height),
logical_resolution: (width, height),
scale_factor,
} => {
let window = winit_windows.get_window(id).unwrap();
window.set_inner_size(winit::dpi::LogicalSize::new(
logical_width,
logical_height,
));
window.set_inner_size(
winit::dpi::LogicalSize::new(width, height)
.to_physical::<f64>(scale_factor),
);
}
bevy_window::WindowCommand::SetVsync { .. } => (),
bevy_window::WindowCommand::SetResizable { resizable } => {
Expand Down Expand Up @@ -342,13 +350,44 @@ pub fn winit_runner_with(mut app: App, mut event_loop: EventLoop<()>) {
scale_factor,
new_inner_size,
} => {
let mut backend_scale_factor_change_events = app
.resources
.get_mut::<Events<WindowBackendScaleFactorChanged>>()
.unwrap();
backend_scale_factor_change_events.send(WindowBackendScaleFactorChanged {
id: window_id,
scale_factor,
});
#[allow(clippy::float_cmp)]
if window.scale_factor() != scale_factor {
let mut scale_factor_change_events = app
.resources
.get_mut::<Events<WindowScaleFactorChanged>>()
.unwrap();

scale_factor_change_events.send(WindowScaleFactorChanged {
id: window_id,
scale_factor,
});
}

window.update_scale_factor_from_backend(scale_factor);

if window.physical_width() != new_inner_size.width
|| window.physical_height() != new_inner_size.height
{
let mut resize_events =
app.resources.get_mut::<Events<WindowResized>>().unwrap();
resize_events.send(WindowResized {
id: window_id,
width: window.width(),
height: window.height(),
});
}
window.update_actual_size_from_backend(
new_inner_size.width,
new_inner_size.height,
);
window.update_scale_factor_from_backend(scale_factor);
// should we send a resize event to indicate the change in
// logical size?
}
WindowEvent::Focused(focused) => {
let mut focused_events =
Expand Down
25 changes: 18 additions & 7 deletions crates/bevy_winit/src/winit_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,24 @@ impl WinitWindows {
false => get_best_videomode(&event_loop.primary_monitor().unwrap()),
}),
)),
_ => winit_window_builder
.with_inner_size(winit::dpi::LogicalSize::new(
window_descriptor.width,
window_descriptor.height,
))
.with_resizable(window_descriptor.resizable)
.with_decorations(window_descriptor.decorations),
_ => {
let WindowDescriptor {
width,
height,
scale_factor_override,
..
} = window_descriptor;
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_resizable(window_descriptor.resizable)
.with_decorations(window_descriptor.decorations),
};

#[allow(unused_mut)]
Expand Down
Loading

0 comments on commit 3cb2e22

Please sign in to comment.