Fix issues where screen and window sizes contained Pixels, but were declared as DevicePixels (#12991)

On most platforms, things were working correctly, but had the wrong
type. On X11, there were some problems with window and display size
calculations.

Release Notes:

- Fixed issues with window positioning on X11

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Max Brunsfeld 2024-06-13 10:48:37 -07:00 committed by GitHub
parent 22dc88ed3d
commit da281d6d8f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 331 additions and 367 deletions

View file

@ -14,8 +14,8 @@ use futures::{
use fuzzy::StringMatchCandidate; use fuzzy::StringMatchCandidate;
use gpui::{ use gpui::{
actions, percentage, point, size, Animation, AnimationExt, AppContext, BackgroundExecutor, actions, percentage, point, size, Animation, AnimationExt, AppContext, BackgroundExecutor,
Bounds, DevicePixels, EventEmitter, Global, PromptLevel, ReadGlobal, Subscription, Task, Bounds, EventEmitter, Global, PromptLevel, ReadGlobal, Subscription, Task, TitlebarOptions,
TitlebarOptions, Transformation, UpdateGlobal, View, WindowBounds, WindowHandle, WindowOptions, Transformation, UpdateGlobal, View, WindowBounds, WindowHandle, WindowOptions,
}; };
use heed::{types::SerdeBincode, Database, RoTxn}; use heed::{types::SerdeBincode, Database, RoTxn};
use language::{language_settings::SoftWrap, Buffer, LanguageRegistry}; use language::{language_settings::SoftWrap, Buffer, LanguageRegistry};
@ -80,11 +80,7 @@ pub fn open_prompt_library(
cx.spawn(|cx| async move { cx.spawn(|cx| async move {
let store = store.await?; let store = store.await?;
cx.update(|cx| { cx.update(|cx| {
let bounds = Bounds::centered( let bounds = Bounds::centered(None, size(px(1024.0), px(768.0)), cx);
None,
size(DevicePixels::from(1024), DevicePixels::from(768)),
cx,
);
cx.open_window( cx.open_window(
WindowOptions { WindowOptions {
titlebar: Some(TitlebarOptions { titlebar: Some(TitlebarOptions {

View file

@ -13,8 +13,8 @@ use call::{report_call_event_for_room, ActiveCall};
pub use collab_panel::CollabPanel; pub use collab_panel::CollabPanel;
pub use collab_titlebar_item::CollabTitlebarItem; pub use collab_titlebar_item::CollabTitlebarItem;
use gpui::{ use gpui::{
actions, point, AppContext, DevicePixels, Pixels, PlatformDisplay, Size, Task, actions, point, AppContext, Pixels, PlatformDisplay, Size, Task, WindowBackgroundAppearance,
WindowBackgroundAppearance, WindowBounds, WindowContext, WindowKind, WindowOptions, WindowBounds, WindowContext, WindowKind, WindowOptions,
}; };
use panel_settings::MessageEditorSettings; use panel_settings::MessageEditorSettings;
pub use panel_settings::{ pub use panel_settings::{
@ -22,6 +22,7 @@ pub use panel_settings::{
}; };
use release_channel::ReleaseChannel; use release_channel::ReleaseChannel;
use settings::Settings; use settings::Settings;
use ui::px;
use workspace::{notifications::DetachAndPromptErr, AppState}; use workspace::{notifications::DetachAndPromptErr, AppState};
actions!( actions!(
@ -96,22 +97,19 @@ pub fn toggle_deafen(_: &ToggleDeafen, cx: &mut AppContext) {
fn notification_window_options( fn notification_window_options(
screen: Rc<dyn PlatformDisplay>, screen: Rc<dyn PlatformDisplay>,
window_size: Size<Pixels>, size: Size<Pixels>,
cx: &AppContext, cx: &AppContext,
) -> WindowOptions { ) -> WindowOptions {
let notification_margin_width = DevicePixels::from(16); let notification_margin_width = px(16.);
let notification_margin_height = DevicePixels::from(-0) - DevicePixels::from(48); let notification_margin_height = px(-48.);
let screen_bounds = screen.bounds(); let bounds = gpui::Bounds::<Pixels> {
let size: Size<DevicePixels> = window_size.into(); origin: screen.bounds().upper_right()
let bounds = gpui::Bounds::<DevicePixels> {
origin: screen_bounds.upper_right()
- point( - point(
size.width + notification_margin_width, size.width + notification_margin_width,
notification_margin_height, notification_margin_height,
), ),
size: window_size.into(), size,
}; };
let app_id = ReleaseChannel::global(cx).app_id(); let app_id = ReleaseChannel::global(cx).app_id();

View file

@ -7659,8 +7659,8 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
cx.open_window( cx.open_window(
WindowOptions { WindowOptions {
window_bounds: Some(WindowBounds::Windowed(Bounds::from_corners( window_bounds: Some(WindowBounds::Windowed(Bounds::from_corners(
gpui::Point::new(0.into(), 0.into()), gpui::Point::new(px(0.), px(0.)),
gpui::Point::new(10.into(), 80.into()), gpui::Point::new(px(10.), px(80.)),
))), ))),
..Default::default() ..Default::default()
}, },

View file

@ -80,8 +80,8 @@ fn main() {
}), }),
window_bounds: Some(WindowBounds::Windowed(Bounds { window_bounds: Some(WindowBounds::Windowed(Bounds {
size: size(px(1100.), px(600.)).into(), size: size(px(1100.), px(600.)),
origin: Point::new(DevicePixels::from(200), DevicePixels::from(200)), origin: Point::new(px(200.), px(200.)),
})), })),
..Default::default() ..Default::default()

View file

@ -24,21 +24,18 @@ fn main() {
for screen in cx.displays() { for screen in cx.displays() {
let options = { let options = {
let popup_margin_width = DevicePixels::from(16); let margin_right = px(16.);
let popup_margin_height = DevicePixels::from(-0) - DevicePixels::from(48); let margin_height = px(-48.);
let window_size = Size { let size = Size {
width: px(400.), width: px(400.),
height: px(72.), height: px(72.),
}; };
let screen_bounds = screen.bounds(); let bounds = gpui::Bounds::<Pixels> {
let size: Size<DevicePixels> = window_size.into(); origin: screen.bounds().upper_right()
- point(size.width + margin_right, margin_height),
let bounds = gpui::Bounds::<DevicePixels> { size,
origin: screen_bounds.upper_right()
- point(size.width + popup_margin_width, popup_margin_height),
size: window_size.into(),
}; };
WindowOptions { WindowOptions {

View file

@ -363,15 +363,6 @@ pub struct Size<T: Clone + Default + Debug> {
pub height: T, pub height: T,
} }
impl From<Size<DevicePixels>> for Size<Pixels> {
fn from(size: Size<DevicePixels>) -> Self {
Size {
width: Pixels(size.width.0 as f32),
height: Pixels(size.height.0 as f32),
}
}
}
/// Constructs a new `Size<T>` with the provided width and height. /// Constructs a new `Size<T>` with the provided width and height.
/// ///
/// # Arguments /// # Arguments
@ -633,15 +624,6 @@ impl<T: Clone + Default + Debug> From<Point<T>> for Size<T> {
} }
} }
impl From<Size<Pixels>> for Size<DevicePixels> {
fn from(size: Size<Pixels>) -> Self {
Size {
width: DevicePixels(size.width.0 as i32),
height: DevicePixels(size.height.0 as i32),
}
}
}
impl From<Size<Pixels>> for Size<DefiniteLength> { impl From<Size<Pixels>> for Size<DefiniteLength> {
fn from(size: Size<Pixels>) -> Self { fn from(size: Size<Pixels>) -> Self {
Size { Size {
@ -722,28 +704,27 @@ pub struct Bounds<T: Clone + Default + Debug> {
pub size: Size<T>, pub size: Size<T>,
} }
impl Bounds<DevicePixels> { impl Bounds<Pixels> {
/// Generate a centered bounds for the given display or primary display if none is provided /// Generate a centered bounds for the given display or primary display if none is provided
pub fn centered( pub fn centered(
display_id: Option<DisplayId>, display_id: Option<DisplayId>,
size: impl Into<Size<DevicePixels>>, size: Size<Pixels>,
cx: &mut AppContext, cx: &mut AppContext,
) -> Self { ) -> Self {
let display = display_id let display = display_id
.and_then(|id| cx.find_display(id)) .and_then(|id| cx.find_display(id))
.or_else(|| cx.primary_display()); .or_else(|| cx.primary_display());
let size = size.into();
display display
.map(|display| { .map(|display| {
let center = display.bounds().center(); let center = display.bounds().center();
Bounds { Bounds {
origin: point(center.x - size.width / 2, center.y - size.height / 2), origin: point(center.x - size.width / 2., center.y - size.height / 2.),
size, size,
} }
}) })
.unwrap_or_else(|| Bounds { .unwrap_or_else(|| Bounds {
origin: point(DevicePixels(0), DevicePixels(0)), origin: point(px(0.), px(0.)),
size, size,
}) })
} }
@ -757,8 +738,8 @@ impl Bounds<DevicePixels> {
display display
.map(|display| display.bounds()) .map(|display| display.bounds())
.unwrap_or_else(|| Bounds { .unwrap_or_else(|| Bounds {
origin: point(DevicePixels(0), DevicePixels(0)), origin: point(px(0.), px(0.)),
size: size(DevicePixels(1024), DevicePixels(768)), size: size(px(1024.), px(768.)),
}) })
} }
} }
@ -1309,6 +1290,26 @@ impl<T: PartialOrd + Default + Debug + Clone> Bounds<T> {
} }
} }
impl Size<DevicePixels> {
/// Converts the size from physical to logical pixels.
pub(crate) fn to_pixels(self, scale_factor: f32) -> Size<Pixels> {
size(
px(self.width.0 as f32 / scale_factor),
px(self.height.0 as f32 / scale_factor),
)
}
}
impl Size<Pixels> {
/// Converts the size from physical to logical pixels.
pub(crate) fn to_device_pixels(self, scale_factor: f32) -> Size<DevicePixels> {
size(
DevicePixels((self.width.0 * scale_factor) as i32),
DevicePixels((self.height.0 * scale_factor) as i32),
)
}
}
impl Bounds<Pixels> { impl Bounds<Pixels> {
/// Scales the bounds by a given factor, typically used to adjust for display scaling. /// Scales the bounds by a given factor, typically used to adjust for display scaling.
/// ///
@ -1346,6 +1347,30 @@ impl Bounds<Pixels> {
size: self.size.scale(factor), size: self.size.scale(factor),
} }
} }
/// Convert the bounds from logical pixels to physical pixels
pub fn to_device_pixels(&self, factor: f32) -> Bounds<DevicePixels> {
Bounds {
origin: point(
DevicePixels((self.origin.x.0 * factor) as i32),
DevicePixels((self.origin.y.0 * factor) as i32),
),
size: self.size.to_device_pixels(factor),
}
}
}
impl Bounds<DevicePixels> {
/// Convert the bounds from physical pixels to logical pixels
pub fn to_pixels(self, scale_factor: f32) -> Bounds<Pixels> {
Bounds {
origin: point(
px(self.origin.x.0 as f32 / scale_factor),
px(self.origin.y.0 as f32 / scale_factor),
),
size: self.size.to_pixels(scale_factor),
}
}
} }
impl<T: Clone + Debug + Copy + Default> Copy for Bounds<T> {} impl<T: Clone + Debug + Copy + Default> Copy for Bounds<T> {}

View file

@ -187,12 +187,12 @@ pub trait PlatformDisplay: Send + Sync + Debug {
fn uuid(&self) -> Result<Uuid>; fn uuid(&self) -> Result<Uuid>;
/// Get the bounds for this display /// Get the bounds for this display
fn bounds(&self) -> Bounds<DevicePixels>; fn bounds(&self) -> Bounds<Pixels>;
/// Get the default bounds for this display to place a window /// Get the default bounds for this display to place a window
fn default_bounds(&self) -> Bounds<DevicePixels> { fn default_bounds(&self) -> Bounds<Pixels> {
let center = self.bounds().center(); let center = self.bounds().center();
let offset = DEFAULT_WINDOW_SIZE / 2; let offset = DEFAULT_WINDOW_SIZE / 2.0;
let origin = point(center.x - offset.width, center.y - offset.height); let origin = point(center.x - offset.width, center.y - offset.height);
Bounds::new(origin, DEFAULT_WINDOW_SIZE) Bounds::new(origin, DEFAULT_WINDOW_SIZE)
} }
@ -211,7 +211,7 @@ impl Debug for DisplayId {
unsafe impl Send for DisplayId {} unsafe impl Send for DisplayId {}
pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle { pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle {
fn bounds(&self) -> Bounds<DevicePixels>; fn bounds(&self) -> Bounds<Pixels>;
fn is_maximized(&self) -> bool; fn is_maximized(&self) -> bool;
fn window_bounds(&self) -> WindowBounds; fn window_bounds(&self) -> WindowBounds;
fn content_size(&self) -> Size<Pixels>; fn content_size(&self) -> Size<Pixels>;
@ -569,7 +569,7 @@ pub struct WindowOptions {
/// The variables that can be configured when creating a new window /// The variables that can be configured when creating a new window
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct WindowParams { pub(crate) struct WindowParams {
pub bounds: Bounds<DevicePixels>, pub bounds: Bounds<Pixels>,
/// The titlebar configuration of the window /// The titlebar configuration of the window
pub titlebar: Option<TitlebarOptions>, pub titlebar: Option<TitlebarOptions>,
@ -597,13 +597,13 @@ pub(crate) struct WindowParams {
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
pub enum WindowBounds { pub enum WindowBounds {
/// Indicates that the window should open in a windowed state with the given bounds. /// Indicates that the window should open in a windowed state with the given bounds.
Windowed(Bounds<DevicePixels>), Windowed(Bounds<Pixels>),
/// Indicates that the window should open in a maximized state. /// Indicates that the window should open in a maximized state.
/// The bounds provided here represent the restore size of the window. /// The bounds provided here represent the restore size of the window.
Maximized(Bounds<DevicePixels>), Maximized(Bounds<Pixels>),
/// Indicates that the window should open in fullscreen mode. /// Indicates that the window should open in fullscreen mode.
/// The bounds provided here represent the restore size of the window. /// The bounds provided here represent the restore size of the window.
Fullscreen(Bounds<DevicePixels>), Fullscreen(Bounds<Pixels>),
} }
impl Default for WindowBounds { impl Default for WindowBounds {
@ -614,7 +614,7 @@ impl Default for WindowBounds {
impl WindowBounds { impl WindowBounds {
/// Retrieve the inner bounds /// Retrieve the inner bounds
pub fn get_bounds(&self) -> Bounds<DevicePixels> { pub fn get_bounds(&self) -> Bounds<Pixels> {
match self { match self {
WindowBounds::Windowed(bounds) => *bounds, WindowBounds::Windowed(bounds) => *bounds,
WindowBounds::Maximized(bounds) => *bounds, WindowBounds::Maximized(bounds) => *bounds,

View file

@ -3,8 +3,8 @@
use super::{BladeAtlas, PATH_TEXTURE_FORMAT}; use super::{BladeAtlas, PATH_TEXTURE_FORMAT};
use crate::{ use crate::{
AtlasTextureKind, AtlasTile, Bounds, ContentMask, Hsla, MonochromeSprite, Path, PathId, AtlasTextureKind, AtlasTile, Bounds, ContentMask, DevicePixels, Hsla, MonochromeSprite, Path,
PathVertex, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size, PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size,
Underline, Underline,
}; };
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
@ -417,10 +417,10 @@ impl BladeRenderer {
} }
} }
pub fn update_drawable_size(&mut self, size: Size<f64>) { pub fn update_drawable_size(&mut self, size: Size<DevicePixels>) {
let gpu_size = gpu::Extent { let gpu_size = gpu::Extent {
width: size.width as u32, width: size.width.0 as u32,
height: size.height as u32, height: size.height.0 as u32,
depth: 1, depth: 1,
}; };

View file

@ -557,7 +557,7 @@ impl LinuxClient for WaylandClient {
Rc::new(WaylandDisplay { Rc::new(WaylandDisplay {
id: id.clone(), id: id.clone(),
name: output.name.clone(), name: output.name.clone(),
bounds: output.bounds, bounds: output.bounds.to_pixels(output.scale as f32),
}) as Rc<dyn PlatformDisplay> }) as Rc<dyn PlatformDisplay>
}) })
.collect() .collect()
@ -573,7 +573,7 @@ impl LinuxClient for WaylandClient {
Rc::new(WaylandDisplay { Rc::new(WaylandDisplay {
id: object_id.clone(), id: object_id.clone(),
name: output.name.clone(), name: output.name.clone(),
bounds: output.bounds, bounds: output.bounds.to_pixels(output.scale as f32),
}) as Rc<dyn PlatformDisplay> }) as Rc<dyn PlatformDisplay>
}) })
}) })

View file

@ -6,14 +6,14 @@ use std::{
use uuid::Uuid; use uuid::Uuid;
use wayland_backend::client::ObjectId; use wayland_backend::client::ObjectId;
use crate::{Bounds, DevicePixels, DisplayId, PlatformDisplay}; use crate::{Bounds, DisplayId, Pixels, PlatformDisplay};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct WaylandDisplay { pub(crate) struct WaylandDisplay {
/// The ID of the wl_output object /// The ID of the wl_output object
pub id: ObjectId, pub id: ObjectId,
pub name: Option<String>, pub name: Option<String>,
pub bounds: Bounds<DevicePixels>, pub bounds: Bounds<Pixels>,
} }
impl Hash for WaylandDisplay { impl Hash for WaylandDisplay {
@ -35,7 +35,7 @@ impl PlatformDisplay for WaylandDisplay {
} }
} }
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
self.bounds self.bounds
} }
} }

View file

@ -1,6 +1,5 @@
use std::cell::{Ref, RefCell, RefMut}; use std::cell::{Ref, RefCell, RefMut};
use std::ffi::c_void; use std::ffi::c_void;
use std::num::NonZeroU32;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@ -26,9 +25,9 @@ use crate::platform::linux::wayland::serial::SerialKind;
use crate::platform::{PlatformAtlas, PlatformInputHandler, PlatformWindow}; use crate::platform::{PlatformAtlas, PlatformInputHandler, PlatformWindow};
use crate::scene::Scene; use crate::scene::Scene;
use crate::{ use crate::{
px, size, AnyWindowHandle, Bounds, DevicePixels, Globals, Modifiers, Output, Pixels, px, size, AnyWindowHandle, Bounds, Globals, Modifiers, Output, Pixels, PlatformDisplay,
PlatformDisplay, PlatformInput, Point, PromptLevel, Size, WaylandClientStatePtr, PlatformInput, Point, PromptLevel, Size, WaylandClientStatePtr, WindowAppearance,
WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowParams, WindowBackgroundAppearance, WindowBounds, WindowParams,
}; };
#[derive(Default)] #[derive(Default)]
@ -76,13 +75,13 @@ pub struct WaylandWindowState {
display: Option<(ObjectId, Output)>, display: Option<(ObjectId, Output)>,
globals: Globals, globals: Globals,
renderer: BladeRenderer, renderer: BladeRenderer,
bounds: Bounds<u32>, bounds: Bounds<Pixels>,
scale: f32, scale: f32,
input_handler: Option<PlatformInputHandler>, input_handler: Option<PlatformInputHandler>,
decoration_state: WaylandDecorationState, decoration_state: WaylandDecorationState,
fullscreen: bool, fullscreen: bool,
maximized: bool, maximized: bool,
windowed_bounds: Bounds<DevicePixels>, windowed_bounds: Bounds<Pixels>,
client: WaylandClientStatePtr, client: WaylandClientStatePtr,
handle: AnyWindowHandle, handle: AnyWindowHandle,
active: bool, active: bool,
@ -108,8 +107,6 @@ impl WaylandWindowState {
globals: Globals, globals: Globals,
options: WindowParams, options: WindowParams,
) -> anyhow::Result<Self> { ) -> anyhow::Result<Self> {
let bounds = options.bounds.map(|p| p.0 as u32);
let raw = RawWindow { let raw = RawWindow {
window: surface.id().as_ptr().cast::<c_void>(), window: surface.id().as_ptr().cast::<c_void>(),
display: surface display: surface
@ -134,8 +131,8 @@ impl WaylandWindowState {
); );
let config = BladeSurfaceConfig { let config = BladeSurfaceConfig {
size: gpu::Extent { size: gpu::Extent {
width: bounds.size.width, width: options.bounds.size.width.0 as u32,
height: bounds.size.height, height: options.bounds.size.height.0 as u32,
depth: 1, depth: 1,
}, },
transparent: options.window_background != WindowBackgroundAppearance::Opaque, transparent: options.window_background != WindowBackgroundAppearance::Opaque,
@ -153,7 +150,7 @@ impl WaylandWindowState {
outputs: HashMap::default(), outputs: HashMap::default(),
display: None, display: None,
renderer: BladeRenderer::new(gpu, config), renderer: BladeRenderer::new(gpu, config),
bounds, bounds: options.bounds,
scale: 1.0, scale: 1.0,
input_handler: None, input_handler: None,
decoration_state: WaylandDecorationState::Client, decoration_state: WaylandDecorationState::Client,
@ -349,10 +346,16 @@ impl WaylandWindowStatePtr {
pub fn handle_toplevel_event(&self, event: xdg_toplevel::Event) -> bool { pub fn handle_toplevel_event(&self, event: xdg_toplevel::Event) -> bool {
match event { match event {
xdg_toplevel::Event::Configure { xdg_toplevel::Event::Configure {
mut width, width,
mut height, height,
states, states,
} => { } => {
let mut size = if width == 0 || height == 0 {
None
} else {
Some(size(px(width as f32), px(height as f32)))
};
let fullscreen = states.contains(&(xdg_toplevel::State::Fullscreen as u8)); let fullscreen = states.contains(&(xdg_toplevel::State::Fullscreen as u8));
let maximized = states.contains(&(xdg_toplevel::State::Maximized as u8)); let maximized = states.contains(&(xdg_toplevel::State::Maximized as u8));
@ -362,19 +365,20 @@ impl WaylandWindowStatePtr {
state.maximized = maximized; state.maximized = maximized;
if got_unmaximized { if got_unmaximized {
width = state.windowed_bounds.size.width.0; size = Some(state.windowed_bounds.size);
height = state.windowed_bounds.size.height.0; } else if !fullscreen && !maximized {
} else if width != 0 && height != 0 && !fullscreen && !maximized { if let Some(size) = size {
state.windowed_bounds = Bounds { state.windowed_bounds = Bounds {
origin: Point::default(), origin: Point::default(),
size: size(width.into(), height.into()), size,
}; };
} }
}
let width = NonZeroU32::new(width as u32);
let height = NonZeroU32::new(height as u32);
drop(state); drop(state);
self.resize(width, height); if let Some(size) = size {
self.resize(size);
}
false false
} }
@ -483,63 +487,43 @@ impl WaylandWindowStatePtr {
bounds bounds
} }
pub fn set_size_and_scale( pub fn set_size_and_scale(&self, size: Option<Size<Pixels>>, scale: Option<f32>) {
&self, let (size, scale) = {
width: Option<NonZeroU32>,
height: Option<NonZeroU32>,
scale: Option<f32>,
) {
let (width, height, scale) = {
let mut state = self.state.borrow_mut(); let mut state = self.state.borrow_mut();
if width.map_or(true, |width| width.get() == state.bounds.size.width) if size.map_or(true, |size| size == state.bounds.size)
&& height.map_or(true, |height| height.get() == state.bounds.size.height)
&& scale.map_or(true, |scale| scale == state.scale) && scale.map_or(true, |scale| scale == state.scale)
{ {
return; return;
} }
if let Some(width) = width { if let Some(size) = size {
state.bounds.size.width = width.get(); state.bounds.size = size;
}
if let Some(height) = height {
state.bounds.size.height = height.get();
} }
if let Some(scale) = scale { if let Some(scale) = scale {
state.scale = scale; state.scale = scale;
} }
let width = state.bounds.size.width; let device_bounds = state.bounds.to_device_pixels(state.scale);
let height = state.bounds.size.height; state.renderer.update_drawable_size(device_bounds.size);
let scale = state.scale; (state.bounds.size, state.scale)
state.renderer.update_drawable_size(size(
width as f64 * scale as f64,
height as f64 * scale as f64,
));
(width, height, scale)
}; };
if let Some(ref mut fun) = self.callbacks.borrow_mut().resize { if let Some(ref mut fun) = self.callbacks.borrow_mut().resize {
fun( fun(size, scale);
Size {
width: px(width as f32),
height: px(height as f32),
},
scale,
);
} }
{ {
let state = self.state.borrow(); let state = self.state.borrow();
if let Some(viewport) = &state.viewport { if let Some(viewport) = &state.viewport {
viewport.set_destination(width as i32, height as i32); viewport.set_destination(size.width.0 as i32, size.height.0 as i32);
} }
} }
} }
pub fn resize(&self, width: Option<NonZeroU32>, height: Option<NonZeroU32>) { pub fn resize(&self, size: Size<Pixels>) {
self.set_size_and_scale(width, height, None); self.set_size_and_scale(Some(size), None);
} }
pub fn rescale(&self, scale: f32) { pub fn rescale(&self, scale: f32) {
self.set_size_and_scale(None, None, Some(scale)); self.set_size_and_scale(None, Some(scale));
} }
/// Notifies the window of the state of the decorations. /// Notifies the window of the state of the decorations.
@ -625,8 +609,8 @@ impl rwh::HasDisplayHandle for WaylandWindow {
} }
impl PlatformWindow for WaylandWindow { impl PlatformWindow for WaylandWindow {
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
self.borrow().bounds.map(|p| DevicePixels(p as i32)) self.borrow().bounds
} }
fn is_maximized(&self) -> bool { fn is_maximized(&self) -> bool {
@ -640,16 +624,13 @@ impl PlatformWindow for WaylandWindow {
} else if state.maximized { } else if state.maximized {
WindowBounds::Maximized(state.windowed_bounds) WindowBounds::Maximized(state.windowed_bounds)
} else { } else {
WindowBounds::Windowed(state.bounds.map(|p| DevicePixels(p as i32))) drop(state);
WindowBounds::Windowed(self.bounds())
} }
} }
fn content_size(&self) -> Size<Pixels> { fn content_size(&self) -> Size<Pixels> {
let state = self.borrow(); self.borrow().bounds.size
Size {
width: Pixels(state.bounds.size.width as f32),
height: Pixels(state.bounds.size.height as f32),
}
} }
fn scale_factor(&self) -> f32 { fn scale_factor(&self) -> f32 {
@ -661,11 +642,12 @@ impl PlatformWindow for WaylandWindow {
} }
fn display(&self) -> Option<Rc<dyn PlatformDisplay>> { fn display(&self) -> Option<Rc<dyn PlatformDisplay>> {
self.borrow().display.as_ref().map(|(id, display)| { let state = self.borrow();
state.display.as_ref().map(|(id, display)| {
Rc::new(WaylandDisplay { Rc::new(WaylandDisplay {
id: id.clone(), id: id.clone(),
name: display.name.clone(), name: display.name.clone(),
bounds: display.bounds, bounds: display.bounds.to_pixels(state.scale),
}) as Rc<dyn PlatformDisplay> }) as Rc<dyn PlatformDisplay>
}) })
} }

View file

@ -908,8 +908,11 @@ impl LinuxClient for X11Client {
.iter() .iter()
.enumerate() .enumerate()
.filter_map(|(root_id, _)| { .filter_map(|(root_id, _)| {
Some(Rc::new(X11Display::new(&state.xcb_connection, root_id)?) Some(Rc::new(X11Display::new(
as Rc<dyn PlatformDisplay>) &state.xcb_connection,
state.scale_factor,
root_id,
)?) as Rc<dyn PlatformDisplay>)
}) })
.collect() .collect()
} }
@ -918,7 +921,11 @@ impl LinuxClient for X11Client {
let state = self.0.borrow(); let state = self.0.borrow();
Some(Rc::new( Some(Rc::new(
X11Display::new(&state.xcb_connection, state.x_root_index) X11Display::new(
&state.xcb_connection,
state.scale_factor,
state.x_root_index,
)
.expect("There should always be a root index"), .expect("There should always be a root index"),
)) ))
} }
@ -928,6 +935,7 @@ impl LinuxClient for X11Client {
Some(Rc::new(X11Display::new( Some(Rc::new(X11Display::new(
&state.xcb_connection, &state.xcb_connection,
state.scale_factor,
id.0 as usize, id.0 as usize,
)?)) )?))
} }

View file

@ -2,25 +2,29 @@ use anyhow::Result;
use uuid::Uuid; use uuid::Uuid;
use x11rb::{connection::Connection as _, xcb_ffi::XCBConnection}; use x11rb::{connection::Connection as _, xcb_ffi::XCBConnection};
use crate::{Bounds, DevicePixels, DisplayId, PlatformDisplay, Size}; use crate::{px, Bounds, DisplayId, Pixels, PlatformDisplay, Size};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct X11Display { pub(crate) struct X11Display {
x_screen_index: usize, x_screen_index: usize,
bounds: Bounds<DevicePixels>, bounds: Bounds<Pixels>,
uuid: Uuid, uuid: Uuid,
} }
impl X11Display { impl X11Display {
pub(crate) fn new(xc: &XCBConnection, x_screen_index: usize) -> Option<Self> { pub(crate) fn new(
xc: &XCBConnection,
scale_factor: f32,
x_screen_index: usize,
) -> Option<Self> {
let screen = xc.setup().roots.get(x_screen_index).unwrap(); let screen = xc.setup().roots.get(x_screen_index).unwrap();
Some(Self { Some(Self {
x_screen_index: x_screen_index, x_screen_index,
bounds: Bounds { bounds: Bounds {
origin: Default::default(), origin: Default::default(),
size: Size { size: Size {
width: DevicePixels(screen.width_in_pixels as i32), width: px(screen.width_in_pixels as f32 / scale_factor),
height: DevicePixels(screen.height_in_pixels as i32), height: px(screen.height_in_pixels as f32 / scale_factor),
}, },
}, },
uuid: Uuid::from_bytes([0; 16]), uuid: Uuid::from_bytes([0; 16]),
@ -37,7 +41,7 @@ impl PlatformDisplay for X11Display {
Ok(self.uuid) Ok(self.uuid)
} }
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
self.bounds self.bounds
} }
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
platform::blade::{BladeRenderer, BladeSurfaceConfig}, platform::blade::{BladeRenderer, BladeSurfaceConfig},
size, AnyWindowHandle, Bounds, DevicePixels, ForegroundExecutor, Modifiers, Pixels, px, size, AnyWindowHandle, Bounds, DevicePixels, ForegroundExecutor, Modifiers, Pixels,
PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point,
PromptLevel, Scene, Size, WindowAppearance, WindowBackgroundAppearance, WindowBounds, PromptLevel, Scene, Size, WindowAppearance, WindowBackgroundAppearance, WindowBounds,
WindowKind, WindowParams, X11ClientStatePtr, WindowKind, WindowParams, X11ClientStatePtr,
@ -162,7 +162,7 @@ pub struct X11WindowState {
atoms: XcbAtoms, atoms: XcbAtoms,
x_root_window: xproto::Window, x_root_window: xproto::Window,
_raw: RawWindow, _raw: RawWindow,
bounds: Bounds<i32>, bounds: Bounds<Pixels>,
scale_factor: f32, scale_factor: f32,
renderer: BladeRenderer, renderer: BladeRenderer,
display: Rc<dyn PlatformDisplay>, display: Rc<dyn PlatformDisplay>,
@ -273,10 +273,10 @@ impl X11WindowState {
visual.depth, visual.depth,
x_window, x_window,
visual_set.root, visual_set.root,
params.bounds.origin.x.0 as i16, (params.bounds.origin.x.0 * scale_factor) as i16,
params.bounds.origin.y.0 as i16, (params.bounds.origin.y.0 * scale_factor) as i16,
params.bounds.size.width.0 as u16, (params.bounds.size.width.0 * scale_factor) as u16,
params.bounds.size.height.0 as u16, (params.bounds.size.height.0 * scale_factor) as u16,
0, 0,
xproto::WindowClass::INPUT_OUTPUT, xproto::WindowClass::INPUT_OUTPUT,
visual.id, visual.id,
@ -370,10 +370,12 @@ impl X11WindowState {
Ok(Self { Ok(Self {
client, client,
executor, executor,
display: Rc::new(X11Display::new(xcb_connection, x_screen_index).unwrap()), display: Rc::new(
X11Display::new(xcb_connection, scale_factor, x_screen_index).unwrap(),
),
_raw: raw, _raw: raw,
x_root_window: visual_set.root, x_root_window: visual_set.root,
bounds: params.bounds.map(|v| v.0), bounds: params.bounds,
scale_factor, scale_factor,
renderer: BladeRenderer::new(gpu, config), renderer: BladeRenderer::new(gpu, config),
atoms: *atoms, atoms: *atoms,
@ -627,6 +629,7 @@ impl X11WindowStatePtr {
let is_resize; let is_resize;
{ {
let mut state = self.state.borrow_mut(); let mut state = self.state.borrow_mut();
let bounds = bounds.map(|f| px(f as f32 / state.scale_factor));
is_resize = bounds.size.width != state.bounds.size.width is_resize = bounds.size.width != state.bounds.size.width
|| bounds.size.height != state.bounds.size.height; || bounds.size.height != state.bounds.size.height;
@ -641,9 +644,10 @@ impl X11WindowStatePtr {
let gpu_size = query_render_extent(&self.xcb_connection, self.x_window); let gpu_size = query_render_extent(&self.xcb_connection, self.x_window);
if state.renderer.viewport_size() != gpu_size { if state.renderer.viewport_size() != gpu_size {
state state.renderer.update_drawable_size(size(
.renderer DevicePixels(gpu_size.width as i32),
.update_drawable_size(size(gpu_size.width as f64, gpu_size.height as f64)); DevicePixels(gpu_size.height as i32),
));
resize_args = Some((state.content_size(), state.scale_factor)); resize_args = Some((state.content_size(), state.scale_factor));
} }
} }
@ -678,8 +682,8 @@ impl X11WindowStatePtr {
} }
impl PlatformWindow for X11Window { impl PlatformWindow for X11Window {
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
self.0.state.borrow().bounds.map(|v| v.into()) self.0.state.borrow().bounds
} }
fn is_maximized(&self) -> bool { fn is_maximized(&self) -> bool {
@ -693,7 +697,11 @@ impl PlatformWindow for X11Window {
fn window_bounds(&self) -> WindowBounds { fn window_bounds(&self) -> WindowBounds {
let state = self.0.state.borrow(); let state = self.0.state.borrow();
WindowBounds::Windowed(state.bounds.map(|p| DevicePixels(p))) if self.is_maximized() {
WindowBounds::Maximized(state.bounds)
} else {
WindowBounds::Windowed(state.bounds)
}
} }
fn content_size(&self) -> Size<Pixels> { fn content_size(&self) -> Size<Pixels> {

View file

@ -1,4 +1,4 @@
use crate::{point, size, Bounds, DevicePixels, DisplayId, PlatformDisplay}; use crate::{px, size, Bounds, DisplayId, Pixels, PlatformDisplay};
use anyhow::Result; use anyhow::Result;
use cocoa::{ use cocoa::{
appkit::NSScreen, appkit::NSScreen,
@ -102,18 +102,15 @@ impl PlatformDisplay for MacDisplay {
])) ]))
} }
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
unsafe { unsafe {
// CGDisplayBounds is in "global display" coordinates, where 0 is // CGDisplayBounds is in "global display" coordinates, where 0 is
// the top left of the primary display. // the top left of the primary display.
let bounds = CGDisplayBounds(self.0); let bounds = CGDisplayBounds(self.0);
Bounds { Bounds {
origin: point(DevicePixels(0), DevicePixels(0)), origin: Default::default(),
size: size( size: size(px(bounds.size.width as f32), px(bounds.size.height as f32)),
DevicePixels(bounds.size.width as i32),
DevicePixels(bounds.size.height as i32),
),
} }
} }
} }

View file

@ -8,7 +8,7 @@ use anyhow::{anyhow, Result};
use block::ConcreteBlock; use block::ConcreteBlock;
use cocoa::{ use cocoa::{
base::{NO, YES}, base::{NO, YES},
foundation::NSUInteger, foundation::{NSSize, NSUInteger},
quartzcore::AutoresizingMask, quartzcore::AutoresizingMask,
}; };
use collections::HashMap; use collections::HashMap;
@ -268,7 +268,11 @@ impl MetalRenderer {
.set_presents_with_transaction(presents_with_transaction); .set_presents_with_transaction(presents_with_transaction);
} }
pub fn update_drawable_size(&mut self, size: Size<f64>) { pub fn update_drawable_size(&mut self, size: Size<DevicePixels>) {
let size = NSSize {
width: size.width.0 as f64,
height: size.height.0 as f64,
};
unsafe { unsafe {
let _: () = msg_send![ let _: () = msg_send![
self.layer(), self.layer(),

View file

@ -1,11 +1,10 @@
use super::{ns_string, renderer, MacDisplay, NSRange, NSStringExt}; use super::{ns_string, renderer, MacDisplay, NSRange, NSStringExt};
use crate::{ use crate::{
platform::PlatformInputHandler, point, px, size, AnyWindowHandle, Bounds, DevicePixels, platform::PlatformInputHandler, point, px, size, AnyWindowHandle, Bounds, DisplayLink,
DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor, KeyDownEvent, Keystroke, ExternalPaths, FileDropEvent, ForegroundExecutor, KeyDownEvent, Keystroke, Modifiers,
Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,
Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformWindow, Point, PromptLevel, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformWindow, Point, PromptLevel, Size, Timer,
Size, Timer, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowKind, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowKind, WindowParams,
WindowParams,
}; };
use block::ConcreteBlock; use block::ConcreteBlock;
use cocoa::{ use cocoa::{
@ -345,7 +344,7 @@ struct MacWindowState {
external_files_dragged: bool, external_files_dragged: bool,
// Whether the next left-mouse click is also the focusing click. // Whether the next left-mouse click is also the focusing click.
first_mouse: bool, first_mouse: bool,
fullscreen_restore_bounds: Bounds<DevicePixels>, fullscreen_restore_bounds: Bounds<Pixels>,
} }
impl MacWindowState { impl MacWindowState {
@ -439,7 +438,7 @@ impl MacWindowState {
} }
} }
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
let mut window_frame = unsafe { NSWindow::frame(self.native_window) }; let mut window_frame = unsafe { NSWindow::frame(self.native_window) };
let screen_frame = unsafe { let screen_frame = unsafe {
let screen = NSWindow::screen(self.native_window); let screen = NSWindow::screen(self.native_window);
@ -452,12 +451,12 @@ impl MacWindowState {
let bounds = Bounds::new( let bounds = Bounds::new(
point( point(
((window_frame.origin.x - screen_frame.origin.x) as i32).into(), px((window_frame.origin.x - screen_frame.origin.x) as f32),
((window_frame.origin.y - screen_frame.origin.y) as i32).into(), px((window_frame.origin.y - screen_frame.origin.y) as f32),
), ),
size( size(
(window_frame.size.width as i32).into(), px(window_frame.size.width as f32),
(window_frame.size.height as i32).into(), px(window_frame.size.height as f32),
), ),
); );
bounds bounds
@ -473,13 +472,6 @@ impl MacWindowState {
get_scale_factor(self.native_window) get_scale_factor(self.native_window)
} }
fn update_drawable_size(&mut self, drawable_size: NSSize) {
self.renderer.update_drawable_size(Size {
width: drawable_size.width,
height: drawable_size.height,
})
}
fn titlebar_height(&self) -> Pixels { fn titlebar_height(&self) -> Pixels {
unsafe { unsafe {
let frame = NSWindow::frame(self.native_window); let frame = NSWindow::frame(self.native_window);
@ -599,14 +591,6 @@ impl MacWindow {
let native_view = NSView::init(native_view); let native_view = NSView::init(native_view);
assert!(!native_view.is_null()); assert!(!native_view.is_null());
let window_size = {
let scale = get_scale_factor(native_window);
size(
bounds.size.width.0 as f32 * scale,
bounds.size.height.0 as f32 * scale,
)
};
let mut window = Self(Arc::new(Mutex::new(MacWindowState { let mut window = Self(Arc::new(Mutex::new(MacWindowState {
handle, handle,
executor, executor,
@ -617,7 +601,7 @@ impl MacWindow {
renderer_context, renderer_context,
native_window as *mut _, native_window as *mut _,
native_view as *mut _, native_view as *mut _,
window_size, bounds.size.map(|pixels| pixels.0),
window_background != WindowBackgroundAppearance::Opaque, window_background != WindowBackgroundAppearance::Opaque,
), ),
request_frame_callback: None, request_frame_callback: None,
@ -772,7 +756,7 @@ impl Drop for MacWindow {
} }
impl PlatformWindow for MacWindow { impl PlatformWindow for MacWindow {
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
self.0.as_ref().lock().bounds() self.0.as_ref().lock().bounds()
} }
@ -1580,20 +1564,17 @@ extern "C" fn view_did_change_backing_properties(this: &Object, _: Sel) {
let window_state = unsafe { get_window_state(this) }; let window_state = unsafe { get_window_state(this) };
let mut lock = window_state.as_ref().lock(); let mut lock = window_state.as_ref().lock();
let scale_factor = lock.scale_factor() as f64; let scale_factor = lock.scale_factor();
let size = lock.content_size(); let size = lock.content_size();
let drawable_size: NSSize = NSSize { let drawable_size = size.to_device_pixels(scale_factor);
width: f64::from(size.width) * scale_factor,
height: f64::from(size.height) * scale_factor,
};
unsafe { unsafe {
let _: () = msg_send![ let _: () = msg_send![
lock.renderer.layer(), lock.renderer.layer(),
setContentsScale: scale_factor setContentsScale: scale_factor as f64
]; ];
} }
lock.update_drawable_size(drawable_size); lock.renderer.update_drawable_size(drawable_size);
if let Some(mut callback) = lock.resize_callback.take() { if let Some(mut callback) = lock.resize_callback.take() {
let content_size = lock.content_size(); let content_size = lock.content_size();
@ -1608,7 +1589,8 @@ extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) {
let window_state = unsafe { get_window_state(this) }; let window_state = unsafe { get_window_state(this) };
let mut lock = window_state.as_ref().lock(); let mut lock = window_state.as_ref().lock();
if lock.content_size() == size.into() { let new_size = Size::<Pixels>::from(size);
if lock.content_size() == new_size {
return; return;
} }
@ -1616,16 +1598,10 @@ extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) {
let _: () = msg_send![super(this, class!(NSView)), setFrameSize: size]; let _: () = msg_send![super(this, class!(NSView)), setFrameSize: size];
} }
let scale_factor = lock.scale_factor() as f64; let scale_factor = lock.scale_factor();
let drawable_size: NSSize = NSSize { let drawable_size = new_size.to_device_pixels(scale_factor);
width: size.width * scale_factor, lock.renderer.update_drawable_size(drawable_size);
height: size.height * scale_factor,
};
lock.update_drawable_size(drawable_size);
drop(lock);
let mut lock = window_state.lock();
if let Some(mut callback) = lock.resize_callback.take() { if let Some(mut callback) = lock.resize_callback.take() {
let content_size = lock.content_size(); let content_size = lock.content_size();
let scale_factor = lock.scale_factor(); let scale_factor = lock.scale_factor();

View file

@ -1,12 +1,11 @@
use crate::{px, Bounds, DisplayId, Pixels, PlatformDisplay, Point};
use anyhow::{Ok, Result}; use anyhow::{Ok, Result};
use crate::{Bounds, DevicePixels, DisplayId, PlatformDisplay, Point};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct TestDisplay { pub(crate) struct TestDisplay {
id: DisplayId, id: DisplayId,
uuid: uuid::Uuid, uuid: uuid::Uuid,
bounds: Bounds<DevicePixels>, bounds: Bounds<Pixels>,
} }
impl TestDisplay { impl TestDisplay {
@ -14,10 +13,7 @@ impl TestDisplay {
TestDisplay { TestDisplay {
id: DisplayId(1), id: DisplayId(1),
uuid: uuid::Uuid::new_v4(), uuid: uuid::Uuid::new_v4(),
bounds: Bounds::from_corners( bounds: Bounds::from_corners(Point::default(), Point::new(px(1920.), px(1080.))),
Point::default(),
Point::new(DevicePixels(1920), DevicePixels(1080)),
),
} }
} }
} }
@ -31,7 +27,7 @@ impl PlatformDisplay for TestDisplay {
Ok(self.uuid) Ok(self.uuid)
} }
fn bounds(&self) -> crate::Bounds<crate::DevicePixels> { fn bounds(&self) -> crate::Bounds<crate::Pixels> {
self.bounds self.bounds
} }
} }

View file

@ -1,8 +1,8 @@
use crate::{ use crate::{
AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, DevicePixels, AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, DispatchEventResult, Pixels,
DispatchEventResult, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point,
PlatformInputHandler, PlatformWindow, Point, Size, TestPlatform, TileId, WindowAppearance, Size, TestPlatform, TileId, WindowAppearance, WindowBackgroundAppearance, WindowBounds,
WindowBackgroundAppearance, WindowBounds, WindowParams, WindowParams,
}; };
use collections::HashMap; use collections::HashMap;
use parking_lot::Mutex; use parking_lot::Mutex;
@ -13,7 +13,7 @@ use std::{
}; };
pub(crate) struct TestWindowState { pub(crate) struct TestWindowState {
pub(crate) bounds: Bounds<DevicePixels>, pub(crate) bounds: Bounds<Pixels>,
pub(crate) handle: AnyWindowHandle, pub(crate) handle: AnyWindowHandle,
display: Rc<dyn PlatformDisplay>, display: Rc<dyn PlatformDisplay>,
pub(crate) title: Option<String>, pub(crate) title: Option<String>,
@ -79,7 +79,7 @@ impl TestWindow {
let Some(mut callback) = lock.resize_callback.take() else { let Some(mut callback) = lock.resize_callback.take() else {
return; return;
}; };
lock.bounds.size = size.map(|pixels| (pixels.0 as i32).into()); lock.bounds.size = size;
drop(lock); drop(lock);
callback(size, scale_factor); callback(size, scale_factor);
self.0.lock().resize_callback = Some(callback); self.0.lock().resize_callback = Some(callback);
@ -108,7 +108,7 @@ impl TestWindow {
} }
impl PlatformWindow for TestWindow { impl PlatformWindow for TestWindow {
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
self.0.lock().bounds self.0.lock().bounds
} }
@ -121,7 +121,7 @@ impl PlatformWindow for TestWindow {
} }
fn content_size(&self) -> Size<Pixels> { fn content_size(&self) -> Size<Pixels> {
self.bounds().size.into() self.bounds().size
} }
fn scale_factor(&self) -> f32 { fn scale_factor(&self) -> f32 {

View file

@ -8,13 +8,13 @@ use windows::{
Win32::{Foundation::*, Graphics::Gdi::*}, Win32::{Foundation::*, Graphics::Gdi::*},
}; };
use crate::{Bounds, DevicePixels, DisplayId, PlatformDisplay, Point, Size}; use crate::{px, Bounds, DisplayId, Pixels, PlatformDisplay, Point, Size};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub(crate) struct WindowsDisplay { pub(crate) struct WindowsDisplay {
pub handle: HMONITOR, pub handle: HMONITOR,
pub display_id: DisplayId, pub display_id: DisplayId,
bounds: Bounds<DevicePixels>, bounds: Bounds<Pixels>,
uuid: Uuid, uuid: Uuid,
} }
@ -34,12 +34,12 @@ impl WindowsDisplay {
display_id, display_id,
bounds: Bounds { bounds: Bounds {
origin: Point { origin: Point {
x: DevicePixels(size.left), x: px(size.left as f32),
y: DevicePixels(size.top), y: px(size.top as f32),
}, },
size: Size { size: Size {
width: DevicePixels(size.right - size.left), width: px((size.right - size.left) as f32),
height: DevicePixels(size.bottom - size.top), height: px((size.bottom - size.top) as f32),
}, },
}, },
uuid, uuid,
@ -60,12 +60,12 @@ impl WindowsDisplay {
display_id: DisplayId(display_id as _), display_id: DisplayId(display_id as _),
bounds: Bounds { bounds: Bounds {
origin: Point { origin: Point {
x: DevicePixels(size.left as i32), x: px(size.left as f32),
y: DevicePixels(size.top as i32), y: px(size.top as f32),
}, },
size: Size { size: Size {
width: DevicePixels((size.right - size.left) as i32), width: px((size.right - size.left) as f32),
height: DevicePixels((size.bottom - size.top) as i32), height: px((size.bottom - size.top) as f32),
}, },
}, },
uuid, uuid,
@ -82,12 +82,12 @@ impl WindowsDisplay {
display_id, display_id,
bounds: Bounds { bounds: Bounds {
origin: Point { origin: Point {
x: DevicePixels(size.left as i32), x: px(size.left as f32),
y: DevicePixels(size.top as i32), y: px(size.top as f32),
}, },
size: Size { size: Size {
width: DevicePixels((size.right - size.left) as i32), width: px((size.right - size.left) as f32),
height: DevicePixels((size.bottom - size.top) as i32), height: px((size.bottom - size.top) as f32),
}, },
}, },
uuid, uuid,
@ -109,11 +109,11 @@ impl WindowsDisplay {
} }
/// Check if the center point of given bounds is inside this monitor /// Check if the center point of given bounds is inside this monitor
pub fn check_given_bounds(&self, bounds: Bounds<DevicePixels>) -> bool { pub fn check_given_bounds(&self, bounds: Bounds<Pixels>) -> bool {
let center = bounds.center(); let center = bounds.center();
let center = POINT { let center = POINT {
x: center.x.0, x: center.x.0 as i32,
y: center.y.0, y: center.y.0 as i32,
}; };
let monitor = unsafe { MonitorFromPoint(center, MONITOR_DEFAULTTONULL) }; let monitor = unsafe { MonitorFromPoint(center, MONITOR_DEFAULTTONULL) };
if monitor.is_invalid() { if monitor.is_invalid() {
@ -167,7 +167,7 @@ impl PlatformDisplay for WindowsDisplay {
Ok(self.uuid) Ok(self.uuid)
} }
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
self.bounds self.bounds
} }
} }

View file

@ -98,13 +98,13 @@ fn handle_move_msg(
lparam: LPARAM, lparam: LPARAM,
state_ptr: Rc<WindowsWindowStatePtr>, state_ptr: Rc<WindowsWindowStatePtr>,
) -> Option<isize> { ) -> Option<isize> {
let x = lparam.signed_loword() as i32; let x = lparam.signed_loword() as f32;
let y = lparam.signed_hiword() as i32; let y = lparam.signed_hiword() as f32;
let mut lock = state_ptr.state.borrow_mut(); let mut lock = state_ptr.state.borrow_mut();
lock.origin = point(x.into(), y.into()); lock.origin = point(px(x), px(y));
let size = lock.physical_size; let size = lock.physical_size;
let center_x = x + size.width.0 / 2; let center_x = x + size.width.0 / 2.;
let center_y = y + size.height.0 / 2; let center_y = y + size.height.0 / 2.;
let monitor_bounds = lock.display.bounds(); let monitor_bounds = lock.display.bounds();
if center_x < monitor_bounds.left().0 if center_x < monitor_bounds.left().0
|| center_x > monitor_bounds.right().0 || center_x > monitor_bounds.right().0
@ -131,18 +131,15 @@ fn handle_move_msg(
fn handle_size_msg(lparam: LPARAM, state_ptr: Rc<WindowsWindowStatePtr>) -> Option<isize> { fn handle_size_msg(lparam: LPARAM, state_ptr: Rc<WindowsWindowStatePtr>) -> Option<isize> {
let width = lparam.loword().max(1) as i32; let width = lparam.loword().max(1) as i32;
let height = lparam.hiword().max(1) as i32; let height = lparam.hiword().max(1) as i32;
let new_physical_size = size(width.into(), height.into());
let mut lock = state_ptr.state.borrow_mut(); let mut lock = state_ptr.state.borrow_mut();
let new_size = size(DevicePixels(width), DevicePixels(height));
let scale_factor = lock.scale_factor; let scale_factor = lock.scale_factor;
lock.physical_size = new_physical_size; lock.renderer.update_drawable_size(new_size);
lock.renderer.update_drawable_size(Size { let new_size = new_size.to_pixels(lock.scale_factor);
width: width as f64, lock.physical_size = new_size;
height: height as f64,
});
if let Some(mut callback) = lock.callbacks.resize.take() { if let Some(mut callback) = lock.callbacks.resize.take() {
drop(lock); drop(lock);
let logical_size = logical_size(new_physical_size, scale_factor); callback(new_size, scale_factor);
callback(logical_size, scale_factor);
state_ptr.state.borrow_mut().callbacks.resize = Some(callback); state_ptr.state.borrow_mut().callbacks.resize = Some(callback);
} }
Some(0) Some(0)

View file

@ -27,14 +27,14 @@ use windows::{
}; };
use crate::platform::blade::BladeRenderer; use crate::platform::blade::BladeRenderer;
use crate::*; use crate::{Pixels, *};
pub(crate) struct WindowsWindow(pub Rc<WindowsWindowStatePtr>); pub(crate) struct WindowsWindow(pub Rc<WindowsWindowStatePtr>);
pub struct WindowsWindowState { pub struct WindowsWindowState {
pub origin: Point<DevicePixels>, pub origin: Point<Pixels>,
pub physical_size: Size<DevicePixels>, pub physical_size: Size<Pixels>,
pub fullscreen_restore_bounds: Bounds<DevicePixels>, pub fullscreen_restore_bounds: Bounds<Pixels>,
pub scale_factor: f32, pub scale_factor: f32,
pub callbacks: Callbacks, pub callbacks: Callbacks,
@ -68,8 +68,8 @@ impl WindowsWindowState {
current_cursor: HCURSOR, current_cursor: HCURSOR,
display: WindowsDisplay, display: WindowsDisplay,
) -> Self { ) -> Self {
let origin = point(cs.x.into(), cs.y.into()); let origin = point(px(cs.x as f32), px(cs.y as f32));
let physical_size = size(cs.cx.into(), cs.cy.into()); let physical_size = size(px(cs.cx as f32), px(cs.cy as f32));
let fullscreen_restore_bounds = Bounds { let fullscreen_restore_bounds = Bounds {
origin, origin,
size: physical_size, size: physical_size,
@ -113,7 +113,7 @@ impl WindowsWindowState {
!self.is_fullscreen() && unsafe { IsZoomed(self.hwnd) }.as_bool() !self.is_fullscreen() && unsafe { IsZoomed(self.hwnd) }.as_bool()
} }
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
Bounds { Bounds {
origin: self.origin, origin: self.origin,
size: self.physical_size, size: self.physical_size,
@ -131,12 +131,12 @@ impl WindowsWindowState {
}; };
let bounds = Bounds { let bounds = Bounds {
origin: point( origin: point(
DevicePixels(placement.rcNormalPosition.left), px(placement.rcNormalPosition.left as f32),
DevicePixels(placement.rcNormalPosition.top), px(placement.rcNormalPosition.top as f32),
), ),
size: size( size: size(
DevicePixels(placement.rcNormalPosition.right - placement.rcNormalPosition.left), px((placement.rcNormalPosition.right - placement.rcNormalPosition.left) as f32),
DevicePixels(placement.rcNormalPosition.bottom - placement.rcNormalPosition.top), px((placement.rcNormalPosition.bottom - placement.rcNormalPosition.top) as f32),
), ),
}; };
@ -154,7 +154,7 @@ impl WindowsWindowState {
/// Currently, GPUI uses logical size of the app to handle mouse interactions (such as /// Currently, GPUI uses logical size of the app to handle mouse interactions (such as
/// whether the mouse collides with other elements of GPUI). /// whether the mouse collides with other elements of GPUI).
fn content_size(&self) -> Size<Pixels> { fn content_size(&self) -> Size<Pixels> {
logical_size(self.physical_size, self.scale_factor) self.physical_size
} }
fn title_bar_padding(&self) -> Pixels { fn title_bar_padding(&self) -> Pixels {
@ -306,6 +306,7 @@ impl WindowsWindow {
} else { } else {
display.default_bounds() display.default_bounds()
}; };
let bounds = bounds.to_device_pixels(wnd.0.state.borrow().scale_factor);
placement.rcNormalPosition.left = bounds.left().0; placement.rcNormalPosition.left = bounds.left().0;
placement.rcNormalPosition.right = bounds.right().0; placement.rcNormalPosition.right = bounds.right().0;
placement.rcNormalPosition.top = bounds.top().0; placement.rcNormalPosition.top = bounds.top().0;
@ -353,7 +354,7 @@ impl Drop for WindowsWindow {
} }
impl PlatformWindow for WindowsWindow { impl PlatformWindow for WindowsWindow {
fn bounds(&self) -> Bounds<DevicePixels> { fn bounds(&self) -> Bounds<Pixels> {
self.0.state.borrow().bounds() self.0.state.borrow().bounds()
} }
@ -554,10 +555,10 @@ impl PlatformWindow for WindowsWindow {
unsafe { GetWindowRect(state_ptr.hwnd, &mut rc) }.log_err(); unsafe { GetWindowRect(state_ptr.hwnd, &mut rc) }.log_err();
let _ = lock.fullscreen.insert(StyleAndBounds { let _ = lock.fullscreen.insert(StyleAndBounds {
style, style,
x: rc.left, x: px(rc.left as f32),
y: rc.top, y: px(rc.top as f32),
cx: rc.right - rc.left, cx: px((rc.right - rc.left) as f32),
cy: rc.bottom - rc.top, cy: px((rc.bottom - rc.top) as f32),
}); });
let style = style let style = style
& !(WS_THICKFRAME & !(WS_THICKFRAME
@ -568,10 +569,10 @@ impl PlatformWindow for WindowsWindow {
let bounds = lock.display.bounds(); let bounds = lock.display.bounds();
StyleAndBounds { StyleAndBounds {
style, style,
x: bounds.left().0, x: bounds.left(),
y: bounds.top().0, y: bounds.top(),
cx: bounds.size.width.0, cx: bounds.size.width,
cy: bounds.size.height.0, cy: bounds.size.height,
} }
}; };
drop(lock); drop(lock);
@ -580,10 +581,10 @@ impl PlatformWindow for WindowsWindow {
SetWindowPos( SetWindowPos(
state_ptr.hwnd, state_ptr.hwnd,
HWND::default(), HWND::default(),
x, x.0 as i32,
y, y.0 as i32,
cx, cx.0 as i32,
cy, cy.0 as i32,
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER,
) )
} }
@ -836,10 +837,10 @@ impl ClickState {
struct StyleAndBounds { struct StyleAndBounds {
style: WINDOW_STYLE, style: WINDOW_STYLE,
x: i32, x: Pixels,
y: i32, y: Pixels,
cx: i32, cx: Pixels,
cy: i32, cy: Pixels,
} }
fn register_wnd_class(icon_handle: HICON) -> PCWSTR { fn register_wnd_class(icon_handle: HICON) -> PCWSTR {

View file

@ -52,8 +52,7 @@ mod prompts;
pub use prompts::*; pub use prompts::*;
pub(crate) const DEFAULT_WINDOW_SIZE: Size<DevicePixels> = pub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1024.), px(700.));
size(DevicePixels(1024), DevicePixels(700));
/// Represents the two different phases when dispatching events. /// Represents the two different phases when dispatching events.
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)] #[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
@ -581,8 +580,8 @@ pub(crate) struct ElementStateBox {
pub(crate) type_name: &'static str, pub(crate) type_name: &'static str,
} }
fn default_bounds(display_id: Option<DisplayId>, cx: &mut AppContext) -> Bounds<DevicePixels> { fn default_bounds(display_id: Option<DisplayId>, cx: &mut AppContext) -> Bounds<Pixels> {
const DEFAULT_WINDOW_OFFSET: Point<DevicePixels> = point(DevicePixels(0), DevicePixels(35)); const DEFAULT_WINDOW_OFFSET: Point<Pixels> = point(px(0.), px(35.));
cx.active_window() cx.active_window()
.and_then(|w| w.update(cx, |_, cx| cx.bounds()).ok()) .and_then(|w| w.update(cx, |_, cx| cx.bounds()).ok())
@ -594,9 +593,7 @@ fn default_bounds(display_id: Option<DisplayId>, cx: &mut AppContext) -> Bounds<
display display
.map(|display| display.default_bounds()) .map(|display| display.default_bounds())
.unwrap_or_else(|| { .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE))
Bounds::new(point(DevicePixels(0), DevicePixels(0)), DEFAULT_WINDOW_SIZE)
})
}) })
} }
@ -1145,7 +1142,7 @@ impl<'a> WindowContext<'a> {
} }
/// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays. /// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays.
pub fn bounds(&self) -> Bounds<DevicePixels> { pub fn bounds(&self) -> Bounds<Pixels> {
self.window.platform_window.bounds() self.window.platform_window.bounds()
} }

View file

@ -12,6 +12,7 @@ use sqlez::{
statement::Statement, statement::Statement,
}; };
use ui::px;
use util::ResultExt; use util::ResultExt;
use uuid::Uuid; use uuid::Uuid;
@ -77,10 +78,10 @@ impl Bind for SerializedWindowBounds {
let next_index = statement.bind(&"Windowed", start_index)?; let next_index = statement.bind(&"Windowed", start_index)?;
statement.bind( statement.bind(
&( &(
SerializedDevicePixels(bounds.origin.x), SerializedPixels(bounds.origin.x),
SerializedDevicePixels(bounds.origin.y), SerializedPixels(bounds.origin.y),
SerializedDevicePixels(bounds.size.width), SerializedPixels(bounds.size.width),
SerializedDevicePixels(bounds.size.height), SerializedPixels(bounds.size.height),
), ),
next_index, next_index,
) )
@ -89,10 +90,10 @@ impl Bind for SerializedWindowBounds {
let next_index = statement.bind(&"Maximized", start_index)?; let next_index = statement.bind(&"Maximized", start_index)?;
statement.bind( statement.bind(
&( &(
SerializedDevicePixels(bounds.origin.x), SerializedPixels(bounds.origin.x),
SerializedDevicePixels(bounds.origin.y), SerializedPixels(bounds.origin.y),
SerializedDevicePixels(bounds.size.width), SerializedPixels(bounds.size.width),
SerializedDevicePixels(bounds.size.height), SerializedPixels(bounds.size.height),
), ),
next_index, next_index,
) )
@ -101,10 +102,10 @@ impl Bind for SerializedWindowBounds {
let next_index = statement.bind(&"FullScreen", start_index)?; let next_index = statement.bind(&"FullScreen", start_index)?;
statement.bind( statement.bind(
&( &(
SerializedDevicePixels(bounds.origin.x), SerializedPixels(bounds.origin.x),
SerializedDevicePixels(bounds.origin.y), SerializedPixels(bounds.origin.y),
SerializedDevicePixels(bounds.size.width), SerializedPixels(bounds.size.width),
SerializedDevicePixels(bounds.size.height), SerializedPixels(bounds.size.height),
), ),
next_index, next_index,
) )
@ -116,40 +117,17 @@ impl Bind for SerializedWindowBounds {
impl Column for SerializedWindowBounds { impl Column for SerializedWindowBounds {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> { fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let (window_state, next_index) = String::column(statement, start_index)?; let (window_state, next_index) = String::column(statement, start_index)?;
let ((x, y, width, height), _): ((i32, i32, i32, i32), _) =
Column::column(statement, next_index)?;
let bounds = Bounds {
origin: point(px(x as f32), px(y as f32)),
size: size(px(width as f32), px(height as f32)),
};
let status = match window_state.as_str() { let status = match window_state.as_str() {
"Windowed" | "Fixed" => { "Windowed" | "Fixed" => SerializedWindowBounds(WindowBounds::Windowed(bounds)),
let ((x, y, width, height), _) = Column::column(statement, next_index)?; "Maximized" => SerializedWindowBounds(WindowBounds::Maximized(bounds)),
let x: i32 = x; "FullScreen" => SerializedWindowBounds(WindowBounds::Fullscreen(bounds)),
let y: i32 = y;
let width: i32 = width;
let height: i32 = height;
SerializedWindowBounds(WindowBounds::Windowed(Bounds {
origin: point(x.into(), y.into()),
size: size(width.into(), height.into()),
}))
}
"Maximized" => {
let ((x, y, width, height), _) = Column::column(statement, next_index)?;
let x: i32 = x;
let y: i32 = y;
let width: i32 = width;
let height: i32 = height;
SerializedWindowBounds(WindowBounds::Maximized(Bounds {
origin: point(x.into(), y.into()),
size: size(width.into(), height.into()),
}))
}
"FullScreen" => {
let ((x, y, width, height), _) = Column::column(statement, next_index)?;
let x: i32 = x;
let y: i32 = y;
let width: i32 = width;
let height: i32 = height;
SerializedWindowBounds(WindowBounds::Fullscreen(Bounds {
origin: point(x.into(), y.into()),
size: size(width.into(), height.into()),
}))
}
_ => bail!("Window State did not have a valid string"), _ => bail!("Window State did not have a valid string"),
}; };
@ -158,16 +136,16 @@ impl Column for SerializedWindowBounds {
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
struct SerializedDevicePixels(gpui::DevicePixels); struct SerializedPixels(gpui::Pixels);
impl sqlez::bindable::StaticColumnCount for SerializedDevicePixels {} impl sqlez::bindable::StaticColumnCount for SerializedPixels {}
impl sqlez::bindable::Bind for SerializedDevicePixels { impl sqlez::bindable::Bind for SerializedPixels {
fn bind( fn bind(
&self, &self,
statement: &sqlez::statement::Statement, statement: &sqlez::statement::Statement,
start_index: i32, start_index: i32,
) -> anyhow::Result<i32> { ) -> anyhow::Result<i32> {
let this: i32 = self.0.into(); let this: i32 = self.0 .0 as i32;
this.bind(statement, start_index) this.bind(statement, start_index)
} }
} }

View file

@ -28,10 +28,10 @@ use futures::{
}; };
use gpui::{ use gpui::{
actions, canvas, impl_actions, point, relative, size, Action, AnyElement, AnyView, AnyWeakView, actions, canvas, impl_actions, point, relative, size, Action, AnyElement, AnyView, AnyWeakView,
AppContext, AsyncAppContext, AsyncWindowContext, Bounds, DevicePixels, DragMoveEvent, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, DragMoveEvent, Entity as _, EntityId,
Entity as _, EntityId, EventEmitter, FocusHandle, FocusableView, Global, KeyContext, Keystroke, EventEmitter, FocusHandle, FocusableView, Global, KeyContext, Keystroke, ManagedView, Model,
ManagedView, Model, ModelContext, PathPromptOptions, Point, PromptLevel, Render, Size, ModelContext, PathPromptOptions, Point, PromptLevel, Render, Size, Subscription, Task, View,
Subscription, Task, View, WeakView, WindowBounds, WindowHandle, WindowOptions, WeakView, WindowBounds, WindowHandle, WindowOptions,
}; };
use item::{ use item::{
FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, PreviewTabsSettings, FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, PreviewTabsSettings,
@ -79,7 +79,7 @@ use theme::{ActiveTheme, SystemAppearance, ThemeSettings};
pub use toolbar::{Toolbar, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView}; pub use toolbar::{Toolbar, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView};
pub use ui; pub use ui;
use ui::{ use ui::{
div, h_flex, Context as _, Div, FluentBuilder, InteractiveElement as _, IntoElement, div, h_flex, px, Context as _, Div, FluentBuilder, InteractiveElement as _, IntoElement,
ParentElement as _, Pixels, SharedString, Styled as _, ViewContext, VisualContext as _, ParentElement as _, Pixels, SharedString, Styled as _, ViewContext, VisualContext as _,
WindowContext, WindowContext,
}; };
@ -96,11 +96,11 @@ use crate::persistence::{
use crate::{notifications::NotificationId, persistence::model::LocalPathsOrder}; use crate::{notifications::NotificationId, persistence::model::LocalPathsOrder};
lazy_static! { lazy_static! {
static ref ZED_WINDOW_SIZE: Option<Size<DevicePixels>> = env::var("ZED_WINDOW_SIZE") static ref ZED_WINDOW_SIZE: Option<Size<Pixels>> = env::var("ZED_WINDOW_SIZE")
.ok() .ok()
.as_deref() .as_deref()
.and_then(parse_pixel_size_env_var); .and_then(parse_pixel_size_env_var);
static ref ZED_WINDOW_POSITION: Option<Point<DevicePixels>> = env::var("ZED_WINDOW_POSITION") static ref ZED_WINDOW_POSITION: Option<Point<Pixels>> = env::var("ZED_WINDOW_POSITION")
.ok() .ok()
.as_deref() .as_deref()
.and_then(parse_pixel_position_env_var); .and_then(parse_pixel_position_env_var);
@ -3981,7 +3981,7 @@ impl Workspace {
} }
} }
fn window_bounds_env_override() -> Option<Bounds<DevicePixels>> { fn window_bounds_env_override() -> Option<Bounds<Pixels>> {
ZED_WINDOW_POSITION ZED_WINDOW_POSITION
.zip(*ZED_WINDOW_SIZE) .zip(*ZED_WINDOW_SIZE)
.map(|(position, size)| Bounds { .map(|(position, size)| Bounds {
@ -5158,18 +5158,18 @@ pub fn reload(reload: &Reload, cx: &mut AppContext) {
.detach_and_log_err(cx); .detach_and_log_err(cx);
} }
fn parse_pixel_position_env_var(value: &str) -> Option<Point<DevicePixels>> { fn parse_pixel_position_env_var(value: &str) -> Option<Point<Pixels>> {
let mut parts = value.split(','); let mut parts = value.split(',');
let x: usize = parts.next()?.parse().ok()?; let x: usize = parts.next()?.parse().ok()?;
let y: usize = parts.next()?.parse().ok()?; let y: usize = parts.next()?.parse().ok()?;
Some(point((x as i32).into(), (y as i32).into())) Some(point(px(x as f32), px(y as f32)))
} }
fn parse_pixel_size_env_var(value: &str) -> Option<Size<DevicePixels>> { fn parse_pixel_size_env_var(value: &str) -> Option<Size<Pixels>> {
let mut parts = value.split(','); let mut parts = value.split(',');
let width: usize = parts.next()?.parse().ok()?; let width: usize = parts.next()?.parse().ok()?;
let height: usize = parts.next()?.parse().ok()?; let height: usize = parts.next()?.parse().ok()?;
Some(size((width as i32).into(), (height as i32).into())) Some(size(px(width as f32), px(height as f32)))
} }
#[cfg(test)] #[cfg(test)]