From 3ae163812569106608f6dc8a938558417bae263d Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 28 Jun 2024 22:36:29 +0800 Subject: [PATCH] fix extracted forground window not foreground (#8521) Signed-off-by: 21pages --- flutter/windows/runner/win32_window.cpp | 23 ++++++++++++ libs/portable/src/main.rs | 48 +++++++++++++++++++------ src/common.rs | 27 +++++++++++++- src/platform/windows.rs | 27 ++++++++++++-- src/ui.rs | 2 ++ 5 files changed, 113 insertions(+), 14 deletions(-) diff --git a/flutter/windows/runner/win32_window.cpp b/flutter/windows/runner/win32_window.cpp index 5c09f6500..2c25f00dd 100644 --- a/flutter/windows/runner/win32_window.cpp +++ b/flutter/windows/runner/win32_window.cpp @@ -5,6 +5,9 @@ #include "resource.h" +#include // for getenv and _putenv +#include // for strcmp + namespace { constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; @@ -143,6 +146,25 @@ bool Win32Window::CreateAndShow(const std::wstring& title, return OnCreate(); } +static void trySetWindowForeground(HWND window) { + char* value = nullptr; + size_t size = 0; + // Use _dupenv_s to safely get the environment variable + _dupenv_s(&value, &size, "SET_FOREGROUND_WINDOW"); + + if (value != nullptr) { + // Correctly compare the value with "1" + if (strcmp(value, "1") == 0) { + // Clear the environment variable + _putenv("SET_FOREGROUND_WINDOW="); + // Set the window to foreground + SetForegroundWindow(window); + } + // Free the duplicated string + free(value); + } +} + // static LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, @@ -156,6 +178,7 @@ LRESULT CALLBACK Win32Window::WndProc(HWND const window, auto that = static_cast(window_struct->lpCreateParams); EnableFullDpiSupportIfAvailable(window); that->window_handle_ = window; + trySetWindowForeground(window); } else if (Win32Window* that = GetThisFromHandle(window)) { return that->MessageHandler(window, message, wparam, lparam); } diff --git a/libs/portable/src/main.rs b/libs/portable/src/main.rs index 48372d68b..7b68d821c 100644 --- a/libs/portable/src/main.rs +++ b/libs/portable/src/main.rs @@ -19,6 +19,8 @@ const APP_METADATA_CONFIG: &str = "meta.toml"; const META_LINE_PREFIX_TIMESTAMP: &str = "timestamp = "; const APP_PREFIX: &str = "rustdesk"; const APPNAME_RUNTIME_ENV_KEY: &str = "RUSTDESK_APPNAME"; +#[cfg(windows)] +const SET_FOREGROUND_WINDOW_ENV_KEY: &str = "SET_FOREGROUND_WINDOW"; fn is_timestamp_matches(dir: &PathBuf, ts: &mut u64) -> bool { let Ok(app_metadata) = std::str::from_utf8(APP_METADATA) else { @@ -57,7 +59,13 @@ fn write_meta(dir: &PathBuf, ts: u64) { } } -fn setup(reader: BinaryReader, dir: Option, clear: bool) -> Option { +fn setup( + reader: BinaryReader, + dir: Option, + clear: bool, + _args: &Vec, + _ui: &mut bool, +) -> Option { let dir = if let Some(dir) = dir { dir } else { @@ -72,6 +80,11 @@ fn setup(reader: BinaryReader, dir: Option, clear: bool) -> Option, clear: bool) -> Option) { +fn execute(path: PathBuf, args: Vec, _ui: bool) { println!("executing {}", path.display()); // setup env let exe = std::env::current_exe().unwrap_or_default(); @@ -97,13 +110,28 @@ fn execute(path: PathBuf, args: Vec) { { use std::os::windows::process::CommandExt; cmd.creation_flags(winapi::um::winbase::CREATE_NO_WINDOW); + if _ui { + cmd.env(SET_FOREGROUND_WINDOW_ENV_KEY, "1"); + } } - cmd.env(APPNAME_RUNTIME_ENV_KEY, exe_name) + let _child = cmd + .env(APPNAME_RUNTIME_ENV_KEY, exe_name) .stdin(Stdio::inherit()) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) - .spawn() - .ok(); + .spawn(); + + #[cfg(windows)] + if _ui { + match _child { + Ok(child) => unsafe { + winapi::um::winuser::AllowSetForegroundWindow(child.id() as u32); + }, + Err(e) => { + eprintln!("{:?}", e); + } + } + } } fn main() { @@ -121,23 +149,21 @@ fn main() { let click_setup = args.is_empty() && arg_exe.to_lowercase().ends_with("install.exe"); let quick_support = args.is_empty() && arg_exe.to_lowercase().ends_with("qs.exe"); - #[cfg(windows)] - if args.is_empty() { - ui::setup(); - } - + let mut ui = false; let reader = BinaryReader::default(); if let Some(exe) = setup( reader, None, click_setup || args.contains(&"--silent-install".to_owned()), + &args, + &mut ui, ) { if click_setup { args = vec!["--install".to_owned()]; } else if quick_support { args = vec!["--quick_support".to_owned()]; } - execute(exe, args); + execute(exe, args, ui); } } diff --git a/src/common.rs b/src/common.rs index 199e0d37f..b7c07e323 100644 --- a/src/common.rs +++ b/src/common.rs @@ -853,7 +853,32 @@ pub fn run_me>(args: Vec) -> std::io::Result>(); + if arg_strs == vec!["--install"] || arg_strs == &["--noinstall"] { + cmd.env(crate::platform::SET_FOREGROUND_WINDOW, "1"); + force_foreground = true; + } + } + let result = cmd.args(&args).spawn(); + match result.as_ref() { + Ok(_child) => + { + #[cfg(windows)] + if force_foreground { + unsafe { winapi::um::winuser::AllowSetForegroundWindow(_child.id() as u32) }; + } + } + Err(err) => log::error!("run_me: {err:?}"), + } + result } #[inline] diff --git a/src/platform/windows.rs b/src/platform/windows.rs index c3cd5567f..93b209839 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -68,6 +68,7 @@ use winreg::RegKey; pub const FLUTTER_RUNNER_WIN32_WINDOW_CLASS: &'static str = "FLUTTER_RUNNER_WIN32_WINDOW"; // main window, install window pub const EXPLORER_EXE: &'static str = "explorer.exe"; +pub const SET_FOREGROUND_WINDOW: &'static str = "SET_FOREGROUND_WINDOW"; pub fn get_focused_display(displays: Vec) -> Option { unsafe { @@ -461,8 +462,18 @@ const SERVICE_TYPE: ServiceType = ServiceType::OWN_PROCESS; extern "C" { fn get_current_session(rdp: BOOL) -> DWORD; - fn LaunchProcessWin(cmd: *const u16, session_id: DWORD, as_user: BOOL, token_pid: &mut DWORD) -> HANDLE; - fn GetSessionUserTokenWin(lphUserToken: LPHANDLE, dwSessionId: DWORD, as_user: BOOL, token_pid: &mut DWORD) -> BOOL; + fn LaunchProcessWin( + cmd: *const u16, + session_id: DWORD, + as_user: BOOL, + token_pid: &mut DWORD, + ) -> HANDLE; + fn GetSessionUserTokenWin( + lphUserToken: LPHANDLE, + dwSessionId: DWORD, + as_user: BOOL, + token_pid: &mut DWORD, + ) -> BOOL; fn selectInputDesktop() -> BOOL; fn inputDesktopSelected() -> BOOL; fn is_windows_server() -> BOOL; @@ -2517,3 +2528,15 @@ fn nt_terminate_process(process_id: DWORD) -> ResultType<()> { } } } + +pub fn try_set_window_foreground(window: HWND) { + let env_key = SET_FOREGROUND_WINDOW; + if let Ok(value) = std::env::var(env_key) { + if value == "1" { + unsafe { + SetForegroundWindow(window); + } + std::env::remove_var(env_key); + } + } +} diff --git a/src/ui.rs b/src/ui.rs index 813f6d7d1..aa36fc578 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -87,6 +87,8 @@ pub fn start(args: &mut [String]) { frame.set_title(&crate::get_app_name()); #[cfg(target_os = "macos")] crate::platform::delegate::make_menubar(frame.get_host(), args.is_empty()); + #[cfg(windows)] + crate::platform::try_set_window_foreground(frame.get_hwnd() as _); let page; if args.len() > 1 && args[0] == "--play" { args[0] = "--connect".to_owned();