Skip to content

Commit 08f2b41

Browse files
committed
wip
1 parent a4abf48 commit 08f2b41

4 files changed

Lines changed: 68 additions & 28 deletions

File tree

src/platform/win/window.rs

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,36 @@ impl WindowHandle {
8181
}
8282
}
8383

84-
pub fn suggest_scale_factor(&self, _scale_factor: f64) -> Result<()> {
85-
todo!()
84+
pub fn suggest_scale_factor(&self, scale_factor: f64) -> Result<()> {
85+
let Some(hwnd) = self.hwnd.get() else { return Ok(()) };
86+
87+
let current_scale_factor = self.state.scale_factor();
88+
self.state.fallback_scale_factor.set(Some(scale_factor));
89+
90+
if self.state.current_dpi.get().is_some() {
91+
return Ok(());
92+
}
93+
94+
let current_size = self.state.current_size.get();
95+
let new_size = self
96+
.state
97+
.current_size
98+
.get()
99+
.to_logical::<f64>(current_scale_factor)
100+
.to_physical(self.state.scale_factor());
101+
102+
// This call doesn't meaningfully change the scaling factor, ignore the result
103+
if current_size == new_size {
104+
return Ok(());
105+
}
106+
107+
hwnd.resize_and_activate(new_size, None, &self.state.user32)?;
108+
109+
if self.state.current_size.get() == new_size {
110+
Ok(())
111+
} else {
112+
Err(Error::ResizeFailed)
113+
}
86114
}
87115
}
88116

@@ -125,19 +153,21 @@ impl WindowImpl for BaseviewWindow {
125153
// Now we can get the actual dpi of the window.
126154
let dpi = window.get_dpi(&self.window_state.user32)?;
127155

128-
if dpi != window_state.shared.current_dpi.get() {
129-
window_state.shared.current_dpi.set(dpi);
156+
if let Some(dpi) = dpi {
157+
if Some(dpi) != window_state.shared.current_dpi.get() {
158+
window_state.shared.current_dpi.set(Some(dpi));
130159

131-
// We cannot create a window in "logical" pixels, and we can't DPI-scale to physical pixels because we
132-
// have no way to know where the window will end up.
133-
// So, at window creation, we assume a DPI=96, and if it ends up wrong, we resize the window
134-
// to the actual logical size the user desired.
135-
let new_size = self.initial_size.to_physical(dpi.scale_factor());
160+
// We cannot create a window in "logical" pixels, and we can't DPI-scale to physical pixels because we
161+
// have no way to know where the window will end up.
162+
// So, at window creation, we assume a DPI=96, and if it ends up wrong, we resize the window
163+
// to the actual logical size the user desired.
164+
let new_size = self.initial_size.to_physical(dpi.scale_factor());
136165

137-
// Preemptively update so a synchronous WM_SIZE from SetWindowPos below
138-
// doesn't also emit Resized.
139-
window_state.shared.current_size.set(new_size);
140-
window.resize_and_activate(new_size, dpi, &window_state.user32)?;
166+
// Preemptively update so a synchronous WM_SIZE from SetWindowPos below
167+
// doesn't also emit Resized.
168+
window_state.shared.current_size.set(new_size);
169+
window.resize_and_activate(new_size, Some(dpi), &window_state.user32)?;
170+
}
141171
}
142172

143173
let drop_target = ComObject::new(DropTarget::new(Rc::downgrade(window_state), window));
@@ -377,14 +407,14 @@ unsafe fn wnd_proc_inner(
377407
let dpi_ctx = DpiAwarenessContext::new(&window_state.user32).unwrap();
378408
let style = window.get_style().unwrap();
379409
let suggested_rect =
380-
dpi_ctx.nc_area_to_client_area(suggested_nc_rect, style, dpi).unwrap();
410+
dpi_ctx.nc_area_to_client_area(suggested_nc_rect, style, Some(dpi)).unwrap();
381411

382412
let new_size = suggested_rect.size();
383413

384414
let changed = window_state.shared.current_size.get() != new_size
385-
|| window_state.shared.current_dpi.get() != dpi;
415+
|| window_state.shared.current_dpi.get() != Some(dpi);
386416

387-
window_state.shared.current_dpi.replace(dpi);
417+
window_state.shared.current_dpi.replace(Some(dpi));
388418
let previous_size = window_state.shared.current_size.replace(new_size);
389419

390420
// Windows makes us resize the window manually. This however will not send a WM_SIZE event,
@@ -476,7 +506,7 @@ impl WindowHandle {
476506
};
477507

478508
let parent = options.parent.map(|p| p.handle);
479-
let rect = dpi_ctx.client_area_to_nc_area(window_size.into(), style, Dpi::default())?;
509+
let rect = dpi_ctx.client_area_to_nc_area(window_size.into(), style, None)?;
480510

481511
let window = create_window(&title, style, rect.size(), parent, &dpi_ctx, initializer)?;
482512

src/platform/win/window_state.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ impl WindowState {
103103
// `self.window_info` will be modified in response to the `WM_SIZE` event that
104104
// follows the `SetWindowPos()` call
105105
let dpi = self.shared.current_dpi.get();
106-
let new_size = size.to_physical(dpi.scale_factor());
106+
let new_size = size.to_physical(self.shared.scale_factor());
107107

108108
self.hwnd.resize_and_activate(new_size, dpi, &self.user32)?;
109109
Ok(())
@@ -144,7 +144,8 @@ impl WindowState {
144144
pub struct WindowSharedState {
145145
pub is_alive: Cell<bool>,
146146
pub current_size: Cell<PhysicalSize<u32>>,
147-
pub current_dpi: Cell<Dpi>, // None if in non-system scale policy
147+
pub current_dpi: Cell<Option<Dpi>>, // None if Win32 HiDPI isn't supported
148+
pub fallback_scale_factor: Cell<Option<f64>>,
148149

149150
pub user32: ExtendedUser32,
150151
}
@@ -153,8 +154,9 @@ impl WindowSharedState {
153154
pub fn new(current_size: PhysicalSize<u32>, user32: ExtendedUser32) -> Rc<Self> {
154155
Self {
155156
is_alive: true.into(),
156-
current_dpi: Dpi::default().into(),
157+
current_dpi: None.into(),
157158
current_size: current_size.into(),
159+
fallback_scale_factor: None.into(),
158160
user32,
159161
}
160162
.into()
@@ -165,6 +167,10 @@ impl WindowSharedState {
165167
}
166168

167169
pub fn scale_factor(&self) -> f64 {
168-
self.current_dpi.get().scale_factor()
170+
if let Some(dpi) = self.current_dpi.get() {
171+
dpi.scale_factor()
172+
} else {
173+
self.fallback_scale_factor.get().unwrap_or(1.0)
174+
}
169175
}
170176
}

src/wrappers/win32/dpi.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,11 @@ impl<'a> DpiAwarenessContext<'a> {
4242
}
4343

4444
pub fn client_area_to_nc_area(
45-
&self, mut rect: Rect, style: WindowStyle, dpi: Dpi,
45+
&self, mut rect: Rect, style: WindowStyle, dpi: Option<Dpi>,
4646
) -> Result<Rect> {
47-
let Some(adjust_window_rect_ex_for_dpi) = self.user32.adjust_window_rect_ex_for_dpi else {
47+
let (Some(adjust_window_rect_ex_for_dpi), Some(dpi)) =
48+
(self.user32.adjust_window_rect_ex_for_dpi, dpi)
49+
else {
4850
let result = unsafe { AdjustWindowRectEx(&mut rect.0, style.style, 0, style.style_ex) };
4951

5052
if result == 0 {
@@ -67,7 +69,9 @@ impl<'a> DpiAwarenessContext<'a> {
6769
Ok(rect)
6870
}
6971

70-
pub fn nc_area_to_client_area(&self, rect: Rect, style: WindowStyle, dpi: Dpi) -> Result<Rect> {
72+
pub fn nc_area_to_client_area(
73+
&self, rect: Rect, style: WindowStyle, dpi: Option<Dpi>,
74+
) -> Result<Rect> {
7175
let result = self.client_area_to_nc_area(Rect::EMPTY, style, dpi)?;
7276

7377
Ok(Rect(RECT {

src/wrappers/win32/window/handle.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,15 @@ impl HWnd {
8787
})
8888
}
8989

90-
pub fn get_dpi(&self, extended_user32: &ExtendedUser32) -> Result<Dpi> {
90+
pub fn get_dpi(&self, extended_user32: &ExtendedUser32) -> Result<Option<Dpi>> {
9191
let Some(get_dpi_for_window) = extended_user32.get_dpi_for_window else {
92-
return Ok(Dpi::default());
92+
return Ok(None);
9393
};
9494

9595
// SAFETY: This type guarantees the HWND is safe to use.
9696
match unsafe { get_dpi_for_window(self.as_raw()) } {
9797
0 => Err(Error::from_thread()),
98-
dpi => Ok(Dpi(dpi)),
98+
dpi => Ok(Some(Dpi(dpi))),
9999
}
100100
}
101101

@@ -140,7 +140,7 @@ impl HWnd {
140140
}
141141

142142
pub fn resize_and_activate(
143-
&self, client_size: PhysicalSize<u32>, window_dpi: Dpi, user32: &ExtendedUser32,
143+
&self, client_size: PhysicalSize<u32>, window_dpi: Option<Dpi>, user32: &ExtendedUser32,
144144
) -> Result<()> {
145145
let dpi_ctx = DpiAwarenessContext::new(user32)?;
146146
let style = self.get_style()?;

0 commit comments

Comments
 (0)