Desktop: Fix resize helper window Z-order and attach to parent console on Windows (#3572)
* Desktop: Fix helper window zorder on Windows * Attach to parent console if launched from a terminal * Workaround for a Windows-specific exception that occurs when `app` is dropped
This commit is contained in:
parent
fafc687d84
commit
bd1f7eefdb
|
|
@ -55,6 +55,7 @@ windows = { version = "0.58.0", features = [
|
||||||
"Win32_Graphics_Gdi",
|
"Win32_Graphics_Gdi",
|
||||||
"Win32_System_LibraryLoader",
|
"Win32_System_LibraryLoader",
|
||||||
"Win32_System_Com",
|
"Win32_System_Com",
|
||||||
|
"Win32_System_Console",
|
||||||
"Win32_UI_Controls",
|
"Win32_UI_Controls",
|
||||||
"Win32_UI_WindowsAndMessaging",
|
"Win32_UI_WindowsAndMessaging",
|
||||||
"Win32_UI_HiDpi",
|
"Win32_UI_HiDpi",
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,14 @@ pub fn start() {
|
||||||
let mut app = App::new(Box::new(cef_context), cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, cli.files);
|
let mut app = App::new(Box::new(cef_context), cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, cli.files);
|
||||||
|
|
||||||
event_loop.run_app(&mut app).unwrap();
|
event_loop.run_app(&mut app).unwrap();
|
||||||
|
|
||||||
|
// Workaround for a Windows-specific exception that occurs when `app` is dropped.
|
||||||
|
// The issue causes the window to hang for a few seconds before closing.
|
||||||
|
// Appears to be related to CEF object destruction order.
|
||||||
|
// Calling `exit` bypasses rust teardown and lets Windows perform process cleanup.
|
||||||
|
// TODO: Identify and fix the underlying CEF shutdown issue so this workaround can be removed.
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_helper() {
|
pub fn start_helper() {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use windows::Win32::System::Com::{COINIT_APARTMENTTHREADED, CoInitializeEx};
|
use windows::Win32::System::Com::{COINIT_APARTMENTTHREADED, CoInitializeEx};
|
||||||
|
use windows::Win32::System::Console::{ATTACH_PARENT_PROCESS, AttachConsole};
|
||||||
use windows::Win32::UI::Shell::SetCurrentProcessExplicitAppUserModelID;
|
use windows::Win32::UI::Shell::SetCurrentProcessExplicitAppUserModelID;
|
||||||
use windows::core::HSTRING;
|
use windows::core::HSTRING;
|
||||||
use winit::event_loop::ActiveEventLoop;
|
use winit::event_loop::ActiveEventLoop;
|
||||||
|
|
@ -13,6 +14,12 @@ pub(super) struct NativeWindowImpl {
|
||||||
|
|
||||||
impl super::NativeWindow for NativeWindowImpl {
|
impl super::NativeWindow for NativeWindowImpl {
|
||||||
fn init() {
|
fn init() {
|
||||||
|
// Attach to parent console if launched from a terminal (no-op otherwise)
|
||||||
|
unsafe {
|
||||||
|
let _ = AttachConsole(ATTACH_PARENT_PROCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set stable app ID
|
||||||
let app_id = HSTRING::from(APP_ID);
|
let app_id = HSTRING::from(APP_ID);
|
||||||
unsafe {
|
unsafe {
|
||||||
let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED).ok();
|
let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED).ok();
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ impl NativeWindowHandle {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
None,
|
main,
|
||||||
None,
|
None,
|
||||||
HINSTANCE(std::ptr::null_mut()),
|
HINSTANCE(std::ptr::null_mut()),
|
||||||
// Pass the main window's HWND to WM_NCCREATE so the helper can store it.
|
// Pass the main window's HWND to WM_NCCREATE so the helper can store it.
|
||||||
|
|
@ -118,7 +118,7 @@ impl NativeWindowHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force window update
|
// Force window update
|
||||||
let _ = unsafe { SetWindowPos(main, None, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER) };
|
let _ = unsafe { SetWindowPos(main, None, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE) };
|
||||||
|
|
||||||
native_handle
|
native_handle
|
||||||
}
|
}
|
||||||
|
|
@ -325,20 +325,20 @@ unsafe fn position_helper(main: HWND, helper: HWND) {
|
||||||
let w = (r.right - r.left) + RESIZE_BAND_THICKNESS * 2;
|
let w = (r.right - r.left) + RESIZE_BAND_THICKNESS * 2;
|
||||||
let h = (r.bottom - r.top) + RESIZE_BAND_THICKNESS * 2;
|
let h = (r.bottom - r.top) + RESIZE_BAND_THICKNESS * 2;
|
||||||
|
|
||||||
let _ = unsafe { SetWindowPos(helper, main, x, y, w, h, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING) };
|
let _ = unsafe { SetWindowPos(helper, main, x, y, w, h, SWP_NOACTIVATE | SWP_NOSENDCHANGING) };
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn calculate_hit(helper: HWND, lparam: LPARAM) -> u32 {
|
unsafe fn calculate_hit(helper: HWND, lparam: LPARAM) -> u32 {
|
||||||
let x = (lparam.0 & 0xFFFF) as i16 as u32;
|
let x = (lparam.0 & 0xFFFF) as i16 as i32;
|
||||||
let y = ((lparam.0 >> 16) & 0xFFFF) as i16 as u32;
|
let y = ((lparam.0 >> 16) & 0xFFFF) as i16 as i32;
|
||||||
|
|
||||||
let mut r = RECT::default();
|
let mut r = RECT::default();
|
||||||
let _ = unsafe { GetWindowRect(helper, &mut r) };
|
let _ = unsafe { GetWindowRect(helper, &mut r) };
|
||||||
|
|
||||||
let on_top = y < (r.top + RESIZE_BAND_THICKNESS) as u32;
|
let on_top = y < (r.top + RESIZE_BAND_THICKNESS) as i32;
|
||||||
let on_right = x >= (r.right - RESIZE_BAND_THICKNESS) as u32;
|
let on_right = x >= (r.right - RESIZE_BAND_THICKNESS) as i32;
|
||||||
let on_bottom = y >= (r.bottom - RESIZE_BAND_THICKNESS) as u32;
|
let on_bottom = y >= (r.bottom - RESIZE_BAND_THICKNESS) as i32;
|
||||||
let on_left = x < (r.left + RESIZE_BAND_THICKNESS) as u32;
|
let on_left = x < (r.left + RESIZE_BAND_THICKNESS) as i32;
|
||||||
|
|
||||||
match (on_top, on_right, on_bottom, on_left) {
|
match (on_top, on_right, on_bottom, on_left) {
|
||||||
(true, _, _, true) => HTTOPLEFT,
|
(true, _, _, true) => HTTOPLEFT,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue