Detailed changes
@@ -5,42 +5,55 @@ use util::ResultExt;
use uuid::Uuid;
use windows::{
core::*,
- Win32::{Foundation::*, Graphics::Gdi::*},
+ Win32::{
+ Foundation::*,
+ Graphics::Gdi::*,
+ UI::{
+ HiDpi::{GetDpiForMonitor, MDT_EFFECTIVE_DPI},
+ WindowsAndMessaging::USER_DEFAULT_SCREEN_DPI,
+ },
+ },
};
-use crate::{px, Bounds, DisplayId, Pixels, PlatformDisplay, Point, Size};
+use crate::{logical_point, point, size, Bounds, DevicePixels, DisplayId, Pixels, PlatformDisplay};
#[derive(Debug, Clone, Copy)]
pub(crate) struct WindowsDisplay {
pub handle: HMONITOR,
pub display_id: DisplayId,
+ scale_factor: f32,
bounds: Bounds<Pixels>,
+ physical_bounds: Bounds<DevicePixels>,
uuid: Uuid,
}
impl WindowsDisplay {
pub(crate) fn new(display_id: DisplayId) -> Option<Self> {
- let Some(screen) = available_monitors().into_iter().nth(display_id.0 as _) else {
- return None;
- };
- let Ok(info) = get_monitor_info(screen).inspect_err(|e| log::error!("{}", e)) else {
- return None;
- };
- let size = info.monitorInfo.rcMonitor;
+ let screen = available_monitors().into_iter().nth(display_id.0 as _)?;
+ let info = get_monitor_info(screen).log_err()?;
+ let monitor_size = info.monitorInfo.rcMonitor;
let uuid = generate_uuid(&info.szDevice);
+ let scale_factor = get_scale_factor_for_monitor(screen).log_err()?;
+ let physical_size = size(
+ (monitor_size.right - monitor_size.left).into(),
+ (monitor_size.bottom - monitor_size.top).into(),
+ );
Some(WindowsDisplay {
handle: screen,
display_id,
+ scale_factor,
bounds: Bounds {
- origin: Point {
- x: px(size.left as f32),
- y: px(size.top as f32),
- },
- size: Size {
- width: px((size.right - size.left) as f32),
- height: px((size.bottom - size.top) as f32),
- },
+ origin: logical_point(
+ monitor_size.left as f32,
+ monitor_size.top as f32,
+ scale_factor,
+ ),
+ size: physical_size.to_pixels(scale_factor),
+ },
+ physical_bounds: Bounds {
+ origin: point(monitor_size.left.into(), monitor_size.top.into()),
+ size: physical_size,
},
uuid,
})
@@ -48,25 +61,34 @@ impl WindowsDisplay {
pub fn new_with_handle(monitor: HMONITOR) -> Self {
let info = get_monitor_info(monitor).expect("unable to get monitor info");
- let size = info.monitorInfo.rcMonitor;
+ let monitor_size = info.monitorInfo.rcMonitor;
let uuid = generate_uuid(&info.szDevice);
let display_id = available_monitors()
.iter()
.position(|handle| handle.0 == monitor.0)
.unwrap();
+ let scale_factor =
+ get_scale_factor_for_monitor(monitor).expect("unable to get scale factor for monitor");
+ let physical_size = size(
+ (monitor_size.right - monitor_size.left).into(),
+ (monitor_size.bottom - monitor_size.top).into(),
+ );
WindowsDisplay {
handle: monitor,
display_id: DisplayId(display_id as _),
+ scale_factor,
bounds: Bounds {
- origin: Point {
- x: px(size.left as f32),
- y: px(size.top as f32),
- },
- size: Size {
- width: px((size.right - size.left) as f32),
- height: px((size.bottom - size.top) as f32),
- },
+ origin: logical_point(
+ monitor_size.left as f32,
+ monitor_size.top as f32,
+ scale_factor,
+ ),
+ size: physical_size.to_pixels(scale_factor),
+ },
+ physical_bounds: Bounds {
+ origin: point(monitor_size.left.into(), monitor_size.top.into()),
+ size: physical_size,
},
uuid,
}
@@ -74,21 +96,30 @@ impl WindowsDisplay {
fn new_with_handle_and_id(handle: HMONITOR, display_id: DisplayId) -> Self {
let info = get_monitor_info(handle).expect("unable to get monitor info");
- let size = info.monitorInfo.rcMonitor;
+ let monitor_size = info.monitorInfo.rcMonitor;
let uuid = generate_uuid(&info.szDevice);
+ let scale_factor =
+ get_scale_factor_for_monitor(handle).expect("unable to get scale factor for monitor");
+ let physical_size = size(
+ (monitor_size.right - monitor_size.left).into(),
+ (monitor_size.bottom - monitor_size.top).into(),
+ );
WindowsDisplay {
handle,
display_id,
+ scale_factor,
bounds: Bounds {
- origin: Point {
- x: px(size.left as f32),
- y: px(size.top as f32),
- },
- size: Size {
- width: px((size.right - size.left) as f32),
- height: px((size.bottom - size.top) as f32),
- },
+ origin: logical_point(
+ monitor_size.left as f32,
+ monitor_size.top as f32,
+ scale_factor,
+ ),
+ size: physical_size.to_pixels(scale_factor),
+ },
+ physical_bounds: Bounds {
+ origin: point(monitor_size.left.into(), monitor_size.top.into()),
+ size: physical_size,
},
uuid,
}
@@ -112,8 +143,8 @@ impl WindowsDisplay {
pub fn check_given_bounds(&self, bounds: Bounds<Pixels>) -> bool {
let center = bounds.center();
let center = POINT {
- x: center.x.0 as i32,
- y: center.y.0 as i32,
+ x: (center.x.0 * self.scale_factor) as i32,
+ y: (center.y.0 * self.scale_factor) as i32,
};
let monitor = unsafe { MonitorFromPoint(center, MONITOR_DEFAULTTONULL) };
if monitor.is_invalid() {
@@ -156,6 +187,10 @@ impl WindowsDisplay {
pub fn is_connected(hmonitor: HMONITOR) -> bool {
available_monitors().iter().contains(&hmonitor)
}
+
+ pub fn physical_bounds(&self) -> Bounds<DevicePixels> {
+ self.physical_bounds
+ }
}
impl PlatformDisplay for WindowsDisplay {
@@ -221,3 +256,11 @@ fn generate_uuid(device_name: &[u16]) -> Uuid {
.collect_vec();
Uuid::new_v5(&Uuid::NAMESPACE_DNS, &name)
}
+
+fn get_scale_factor_for_monitor(monitor: HMONITOR) -> Result<f32> {
+ let mut dpi_x = 0;
+ let mut dpi_y = 0;
+ unsafe { GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &mut dpi_x, &mut dpi_y) }?;
+ assert_eq!(dpi_x, dpi_y);
+ Ok(dpi_x as f32 / USER_DEFAULT_SCREEN_DPI as f32)
+}
@@ -98,13 +98,16 @@ fn handle_move_msg(
lparam: LPARAM,
state_ptr: Rc<WindowsWindowStatePtr>,
) -> Option<isize> {
- let x = lparam.signed_loword() as f32;
- let y = lparam.signed_hiword() as f32;
let mut lock = state_ptr.state.borrow_mut();
- lock.origin = point(px(x), px(y));
- let size = lock.physical_size;
- let center_x = x + size.width.0 / 2.;
- let center_y = y + size.height.0 / 2.;
+ let origin = logical_point(
+ lparam.signed_loword() as f32,
+ lparam.signed_hiword() as f32,
+ lock.scale_factor,
+ );
+ lock.origin = origin;
+ let size = lock.logical_size;
+ let center_x = origin.x.0 + size.width.0 / 2.;
+ let center_y = origin.y.0 + size.height.0 / 2.;
let monitor_bounds = lock.display.bounds();
if center_x < monitor_bounds.left().0
|| center_x > monitor_bounds.right().0
@@ -135,8 +138,8 @@ fn handle_size_msg(lparam: LPARAM, state_ptr: Rc<WindowsWindowStatePtr>) -> Opti
let new_size = size(DevicePixels(width), DevicePixels(height));
let scale_factor = lock.scale_factor;
lock.renderer.update_drawable_size(new_size);
- let new_size = new_size.to_pixels(lock.scale_factor);
- lock.physical_size = new_size;
+ let new_size = new_size.to_pixels(scale_factor);
+ lock.logical_size = new_size;
if let Some(mut callback) = lock.callbacks.resize.take() {
drop(lock);
callback(new_size, scale_factor);
@@ -111,14 +111,6 @@ pub(crate) fn load_cursor(style: CursorStyle) -> HCURSOR {
})
}
-#[inline]
-pub(crate) fn logical_size(physical_size: Size<DevicePixels>, scale_factor: f32) -> Size<Pixels> {
- Size {
- width: px(physical_size.width.0 as f32 / scale_factor),
- height: px(physical_size.height.0 as f32 / scale_factor),
- }
-}
-
#[inline]
pub(crate) fn logical_point(x: f32, y: f32, scale_factor: f32) -> Point<Pixels> {
Point {
@@ -27,13 +27,13 @@ use windows::{
};
use crate::platform::blade::BladeRenderer;
-use crate::{Pixels, *};
+use crate::*;
pub(crate) struct WindowsWindow(pub Rc<WindowsWindowStatePtr>);
pub struct WindowsWindowState {
pub origin: Point<Pixels>,
- pub physical_size: Size<Pixels>,
+ pub logical_size: Size<Pixels>,
pub fullscreen_restore_bounds: Bounds<Pixels>,
pub scale_factor: f32,
@@ -68,16 +68,19 @@ impl WindowsWindowState {
current_cursor: HCURSOR,
display: WindowsDisplay,
) -> Self {
- let origin = point(px(cs.x as f32), px(cs.y as f32));
- let physical_size = size(px(cs.cx as f32), px(cs.cy as f32));
- let fullscreen_restore_bounds = Bounds {
- origin,
- size: physical_size,
- };
let scale_factor = {
let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32;
monitor_dpi / USER_DEFAULT_SCREEN_DPI as f32
};
+ let origin = logical_point(cs.x as f32, cs.y as f32, scale_factor);
+ let logical_size = {
+ let physical_size = size(DevicePixels(cs.cx), DevicePixels(cs.cy));
+ physical_size.to_pixels(scale_factor)
+ };
+ let fullscreen_restore_bounds = Bounds {
+ origin,
+ size: logical_size,
+ };
let renderer = windows_renderer::windows_renderer(hwnd, transparent);
let callbacks = Callbacks::default();
let input_handler = None;
@@ -88,7 +91,7 @@ impl WindowsWindowState {
Self {
origin,
- physical_size,
+ logical_size,
fullscreen_restore_bounds,
scale_factor,
callbacks,
@@ -116,7 +119,7 @@ impl WindowsWindowState {
fn bounds(&self) -> Bounds<Pixels> {
Bounds {
origin: self.origin,
- size: self.physical_size,
+ size: self.logical_size,
}
}
@@ -129,15 +132,17 @@ impl WindowsWindowState {
GetWindowPlacement(self.hwnd, &mut placement).log_err();
placement
};
+ let physical_size = size(
+ DevicePixels(placement.rcNormalPosition.right - placement.rcNormalPosition.left),
+ DevicePixels(placement.rcNormalPosition.bottom - placement.rcNormalPosition.top),
+ );
let bounds = Bounds {
- origin: point(
- px(placement.rcNormalPosition.left as f32),
- px(placement.rcNormalPosition.top as f32),
- ),
- size: size(
- px((placement.rcNormalPosition.right - placement.rcNormalPosition.left) as f32),
- px((placement.rcNormalPosition.bottom - placement.rcNormalPosition.top) as f32),
+ origin: logical_point(
+ placement.rcNormalPosition.left as f32,
+ placement.rcNormalPosition.top as f32,
+ self.scale_factor,
),
+ size: physical_size.to_pixels(self.scale_factor),
};
if self.is_fullscreen() {
@@ -154,7 +159,7 @@ impl WindowsWindowState {
/// Currently, GPUI uses logical size of the app to handle mouse interactions (such as
/// whether the mouse collides with other elements of GPUI).
fn content_size(&self) -> Size<Pixels> {
- self.physical_size
+ self.logical_size
}
fn title_bar_padding(&self) -> Pixels {
@@ -538,7 +543,7 @@ impl PlatformWindow for WindowsWindow {
let mut lock = state_ptr.state.borrow_mut();
lock.fullscreen_restore_bounds = Bounds {
origin: lock.origin,
- size: lock.physical_size,
+ size: lock.logical_size,
};
let StyleAndBounds {
style,
@@ -555,10 +560,10 @@ impl PlatformWindow for WindowsWindow {
unsafe { GetWindowRect(state_ptr.hwnd, &mut rc) }.log_err();
let _ = lock.fullscreen.insert(StyleAndBounds {
style,
- x: px(rc.left as f32),
- y: px(rc.top as f32),
- cx: px((rc.right - rc.left) as f32),
- cy: px((rc.bottom - rc.top) as f32),
+ x: rc.left,
+ y: rc.top,
+ cx: rc.right - rc.left,
+ cy: rc.bottom - rc.top,
});
let style = style
& !(WS_THICKFRAME
@@ -566,13 +571,13 @@ impl PlatformWindow for WindowsWindow {
| WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
| WS_CAPTION);
- let bounds = lock.display.bounds();
+ let physical_bounds = lock.display.physical_bounds();
StyleAndBounds {
style,
- x: bounds.left(),
- y: bounds.top(),
- cx: bounds.size.width,
- cy: bounds.size.height,
+ x: physical_bounds.left().0,
+ y: physical_bounds.top().0,
+ cx: physical_bounds.size.width.0,
+ cy: physical_bounds.size.height.0,
}
};
drop(lock);
@@ -581,10 +586,10 @@ impl PlatformWindow for WindowsWindow {
SetWindowPos(
state_ptr.hwnd,
HWND::default(),
- x.0 as i32,
- y.0 as i32,
- cx.0 as i32,
- cy.0 as i32,
+ x,
+ y,
+ cx,
+ cy,
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER,
)
}
@@ -837,10 +842,10 @@ impl ClickState {
struct StyleAndBounds {
style: WINDOW_STYLE,
- x: Pixels,
- y: Pixels,
- cx: Pixels,
- cy: Pixels,
+ x: i32,
+ y: i32,
+ cx: i32,
+ cy: i32,
}
fn register_wnd_class(icon_handle: HICON) -> PCWSTR {