Skip to content

Commit 4c2e747

Browse files
fix(windows) window center doesn't consider taskbar size (#9309)
* Fix window center doesn't consider taskbar size * Clean up * Add change file * Calculate title bar size on initial creation * Comment about not adding in rect.bottom * Tweak comment * Fix center existing window a bit too high * us NSWindow::center on macOS * skip if undecorated
1 parent 1a58cdf commit 4c2e747

3 files changed

Lines changed: 81 additions & 15 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-runtime-wry": patch:bug
3+
---
4+
5+
Fix window centering not taking taskbar into account on Windows

core/tauri-runtime-wry/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ softbuffer = { version = "0.4", default-features = false }
2929

3030
[target."cfg(windows)".dependencies.windows]
3131
version = "0.54"
32-
features = [ "Win32_Foundation" ]
32+
features = [ "Win32_Foundation", "Win32_Graphics_Dwm" ]
3333

3434
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
3535
gtk = { version = "0.18", features = [ "v3_24" ] }

core/tauri-runtime-wry/src/lib.rs

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2642,13 +2642,37 @@ fn handle_user_message<T: UserEvent>(
26422642
}
26432643
// Setters
26442644
WindowMessage::Center => {
2645+
#[cfg(not(target_os = "macos"))]
26452646
if let Some(monitor) = window.current_monitor() {
2646-
let window_size = inner_size(&window, &webviews, has_children);
2647-
let screen_size = monitor.size();
2648-
let monitor_pos = monitor.position();
2649-
let x = (screen_size.width as i32 - window_size.width as i32) / 2 + monitor_pos.x;
2650-
let y = (screen_size.height as i32 - window_size.height as i32) / 2 + monitor_pos.y;
2651-
window.set_outer_position(TaoPhysicalPosition::new(x, y));
2647+
#[allow(unused_mut)]
2648+
let mut window_size = window.outer_size();
2649+
#[cfg(windows)]
2650+
if window.is_decorated() {
2651+
use windows::Win32::Foundation::RECT;
2652+
use windows::Win32::Graphics::Dwm::{
2653+
DwmGetWindowAttribute, DWMWA_EXTENDED_FRAME_BOUNDS,
2654+
};
2655+
let mut rect = RECT::default();
2656+
let result = unsafe {
2657+
DwmGetWindowAttribute(
2658+
HWND(window.hwnd()),
2659+
DWMWA_EXTENDED_FRAME_BOUNDS,
2660+
&mut rect as *mut _ as *mut _,
2661+
std::mem::size_of::<RECT>() as u32,
2662+
)
2663+
};
2664+
if result.is_ok() {
2665+
window_size.height = (rect.bottom - rect.top) as u32;
2666+
}
2667+
}
2668+
window.set_outer_position(calculate_window_center_position(window_size, monitor));
2669+
}
2670+
2671+
#[cfg(target_os = "macos")]
2672+
{
2673+
use cocoa::{appkit::NSWindow, base::id};
2674+
let ns_window: id = window.ns_window() as _;
2675+
unsafe { ns_window.center() };
26522676
}
26532677
}
26542678
WindowMessage::RequestUserAttention(request_type) => {
@@ -3511,18 +3535,29 @@ fn create_window<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
35113535
.inner_size
35123536
.unwrap_or_else(|| TaoPhysicalSize::new(800, 600).into());
35133537
let scale_factor = monitor.scale_factor();
3514-
let window_size = window_builder
3538+
#[allow(unused_mut)]
3539+
let mut window_size = window_builder
35153540
.inner
35163541
.window
35173542
.inner_size_constraints
35183543
.clamp(desired_size, scale_factor)
3519-
.to_logical::<i32>(scale_factor);
3520-
let screen_size = monitor.size().to_logical::<i32>(scale_factor);
3521-
let monitor_pos = monitor.position().to_logical::<i32>(scale_factor);
3522-
let x = (screen_size.width - window_size.width) / 2 + monitor_pos.x;
3523-
let y = (screen_size.height - window_size.height) / 2 + monitor_pos.y;
3524-
3525-
window_builder = window_builder.position(x as f64, y as f64);
3544+
.to_physical::<u32>(scale_factor);
3545+
#[cfg(windows)]
3546+
{
3547+
if window_builder.inner.window.decorations {
3548+
use windows::Win32::UI::WindowsAndMessaging::{AdjustWindowRect, WS_OVERLAPPEDWINDOW};
3549+
let mut rect = windows::Win32::Foundation::RECT::default();
3550+
let result = unsafe { AdjustWindowRect(&mut rect, WS_OVERLAPPEDWINDOW, false) };
3551+
if result.is_ok() {
3552+
window_size.width += (rect.right - rect.left) as u32;
3553+
// rect.bottom is made out of shadow, and we don't care about it
3554+
window_size.height += -rect.top as u32;
3555+
}
3556+
}
3557+
}
3558+
let position = calculate_window_center_position(window_size, monitor);
3559+
let logical_position = position.to_logical::<f64>(scale_factor);
3560+
window_builder = window_builder.position(logical_position.x, logical_position.y);
35263561
}
35273562
}
35283563

@@ -4060,6 +4095,32 @@ fn inner_size(
40604095
window.inner_size()
40614096
}
40624097

4098+
fn calculate_window_center_position(
4099+
window_size: TaoPhysicalSize<u32>,
4100+
target_monitor: MonitorHandle,
4101+
) -> TaoPhysicalPosition<i32> {
4102+
#[cfg(windows)]
4103+
{
4104+
use tao::platform::windows::MonitorHandleExtWindows;
4105+
use windows::Win32::Graphics::Gdi::{GetMonitorInfoW, HMONITOR, MONITORINFO};
4106+
let mut monitor_info = MONITORINFO::default();
4107+
monitor_info.cbSize = std::mem::size_of::<MONITORINFO>() as u32;
4108+
let status = unsafe { GetMonitorInfoW(HMONITOR(target_monitor.hmonitor()), &mut monitor_info) };
4109+
if status.into() {
4110+
let available_width = monitor_info.rcWork.right - monitor_info.rcWork.left;
4111+
let available_height = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
4112+
let x = (available_width - window_size.width as i32) / 2 + monitor_info.rcWork.left;
4113+
let y = (available_height - window_size.height as i32) / 2 + monitor_info.rcWork.top;
4114+
return TaoPhysicalPosition::new(x, y);
4115+
}
4116+
}
4117+
let screen_size = target_monitor.size();
4118+
let monitor_pos = target_monitor.position();
4119+
let x = (screen_size.width as i32 - window_size.width as i32) / 2 + monitor_pos.x;
4120+
let y = (screen_size.height as i32 - window_size.height as i32) / 2 + monitor_pos.y;
4121+
TaoPhysicalPosition::new(x, y)
4122+
}
4123+
40634124
#[cfg(windows)]
40644125
fn clear_window_surface(
40654126
window: &Window,

0 commit comments

Comments
 (0)