Skip to content

Commit

Permalink
fix(windows) window center doesn't consider taskbar size (#9309)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Legend-Master authored Apr 2, 2024
1 parent 1a58cdf commit 4c2e747
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changes/fix-window-center-work-area.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri-runtime-wry": patch:bug
---

Fix window centering not taking taskbar into account on Windows
2 changes: 1 addition & 1 deletion core/tauri-runtime-wry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ softbuffer = { version = "0.4", default-features = false }

[target."cfg(windows)".dependencies.windows]
version = "0.54"
features = [ "Win32_Foundation" ]
features = [ "Win32_Foundation", "Win32_Graphics_Dwm" ]

[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
gtk = { version = "0.18", features = [ "v3_24" ] }
Expand Down
89 changes: 75 additions & 14 deletions core/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2642,13 +2642,37 @@ fn handle_user_message<T: UserEvent>(
}
// Setters
WindowMessage::Center => {
#[cfg(not(target_os = "macos"))]
if let Some(monitor) = window.current_monitor() {
let window_size = inner_size(&window, &webviews, has_children);
let screen_size = monitor.size();
let monitor_pos = monitor.position();
let x = (screen_size.width as i32 - window_size.width as i32) / 2 + monitor_pos.x;
let y = (screen_size.height as i32 - window_size.height as i32) / 2 + monitor_pos.y;
window.set_outer_position(TaoPhysicalPosition::new(x, y));
#[allow(unused_mut)]
let mut window_size = window.outer_size();
#[cfg(windows)]
if window.is_decorated() {
use windows::Win32::Foundation::RECT;
use windows::Win32::Graphics::Dwm::{
DwmGetWindowAttribute, DWMWA_EXTENDED_FRAME_BOUNDS,
};
let mut rect = RECT::default();
let result = unsafe {
DwmGetWindowAttribute(
HWND(window.hwnd()),
DWMWA_EXTENDED_FRAME_BOUNDS,
&mut rect as *mut _ as *mut _,
std::mem::size_of::<RECT>() as u32,
)
};
if result.is_ok() {
window_size.height = (rect.bottom - rect.top) as u32;
}
}
window.set_outer_position(calculate_window_center_position(window_size, monitor));
}

#[cfg(target_os = "macos")]
{
use cocoa::{appkit::NSWindow, base::id};
let ns_window: id = window.ns_window() as _;
unsafe { ns_window.center() };
}
}
WindowMessage::RequestUserAttention(request_type) => {
Expand Down Expand Up @@ -3511,18 +3535,29 @@ fn create_window<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
.inner_size
.unwrap_or_else(|| TaoPhysicalSize::new(800, 600).into());
let scale_factor = monitor.scale_factor();
let window_size = window_builder
#[allow(unused_mut)]
let mut window_size = window_builder
.inner
.window
.inner_size_constraints
.clamp(desired_size, scale_factor)
.to_logical::<i32>(scale_factor);
let screen_size = monitor.size().to_logical::<i32>(scale_factor);
let monitor_pos = monitor.position().to_logical::<i32>(scale_factor);
let x = (screen_size.width - window_size.width) / 2 + monitor_pos.x;
let y = (screen_size.height - window_size.height) / 2 + monitor_pos.y;

window_builder = window_builder.position(x as f64, y as f64);
.to_physical::<u32>(scale_factor);
#[cfg(windows)]
{
if window_builder.inner.window.decorations {
use windows::Win32::UI::WindowsAndMessaging::{AdjustWindowRect, WS_OVERLAPPEDWINDOW};
let mut rect = windows::Win32::Foundation::RECT::default();
let result = unsafe { AdjustWindowRect(&mut rect, WS_OVERLAPPEDWINDOW, false) };
if result.is_ok() {
window_size.width += (rect.right - rect.left) as u32;
// rect.bottom is made out of shadow, and we don't care about it
window_size.height += -rect.top as u32;
}
}
}
let position = calculate_window_center_position(window_size, monitor);
let logical_position = position.to_logical::<f64>(scale_factor);
window_builder = window_builder.position(logical_position.x, logical_position.y);
}
}

Expand Down Expand Up @@ -4060,6 +4095,32 @@ fn inner_size(
window.inner_size()
}

fn calculate_window_center_position(
window_size: TaoPhysicalSize<u32>,
target_monitor: MonitorHandle,
) -> TaoPhysicalPosition<i32> {
#[cfg(windows)]
{
use tao::platform::windows::MonitorHandleExtWindows;
use windows::Win32::Graphics::Gdi::{GetMonitorInfoW, HMONITOR, MONITORINFO};
let mut monitor_info = MONITORINFO::default();
monitor_info.cbSize = std::mem::size_of::<MONITORINFO>() as u32;
let status = unsafe { GetMonitorInfoW(HMONITOR(target_monitor.hmonitor()), &mut monitor_info) };
if status.into() {
let available_width = monitor_info.rcWork.right - monitor_info.rcWork.left;
let available_height = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
let x = (available_width - window_size.width as i32) / 2 + monitor_info.rcWork.left;
let y = (available_height - window_size.height as i32) / 2 + monitor_info.rcWork.top;
return TaoPhysicalPosition::new(x, y);
}
}
let screen_size = target_monitor.size();
let monitor_pos = target_monitor.position();
let x = (screen_size.width as i32 - window_size.width as i32) / 2 + monitor_pos.x;
let y = (screen_size.height as i32 - window_size.height as i32) / 2 + monitor_pos.y;
TaoPhysicalPosition::new(x, y)
}

#[cfg(windows)]
fn clear_window_surface(
window: &Window,
Expand Down

0 comments on commit 4c2e747

Please sign in to comment.