fix extracted forground window not foreground (#8521)
Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
parent
96aff38862
commit
3ae1638125
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
|
#include <cstdlib> // for getenv and _putenv
|
||||||
|
#include <cstring> // for strcmp
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
|
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
|
||||||
@ -143,6 +146,25 @@ bool Win32Window::CreateAndShow(const std::wstring& title,
|
|||||||
return OnCreate();
|
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
|
// static
|
||||||
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
|
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
|
||||||
UINT const message,
|
UINT const message,
|
||||||
@ -156,6 +178,7 @@ LRESULT CALLBACK Win32Window::WndProc(HWND const window,
|
|||||||
auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
|
auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
|
||||||
EnableFullDpiSupportIfAvailable(window);
|
EnableFullDpiSupportIfAvailable(window);
|
||||||
that->window_handle_ = window;
|
that->window_handle_ = window;
|
||||||
|
trySetWindowForeground(window);
|
||||||
} else if (Win32Window* that = GetThisFromHandle(window)) {
|
} else if (Win32Window* that = GetThisFromHandle(window)) {
|
||||||
return that->MessageHandler(window, message, wparam, lparam);
|
return that->MessageHandler(window, message, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ const APP_METADATA_CONFIG: &str = "meta.toml";
|
|||||||
const META_LINE_PREFIX_TIMESTAMP: &str = "timestamp = ";
|
const META_LINE_PREFIX_TIMESTAMP: &str = "timestamp = ";
|
||||||
const APP_PREFIX: &str = "rustdesk";
|
const APP_PREFIX: &str = "rustdesk";
|
||||||
const APPNAME_RUNTIME_ENV_KEY: &str = "RUSTDESK_APPNAME";
|
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 {
|
fn is_timestamp_matches(dir: &PathBuf, ts: &mut u64) -> bool {
|
||||||
let Ok(app_metadata) = std::str::from_utf8(APP_METADATA) else {
|
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<PathBuf>, clear: bool) -> Option<PathBuf> {
|
fn setup(
|
||||||
|
reader: BinaryReader,
|
||||||
|
dir: Option<PathBuf>,
|
||||||
|
clear: bool,
|
||||||
|
_args: &Vec<String>,
|
||||||
|
_ui: &mut bool,
|
||||||
|
) -> Option<PathBuf> {
|
||||||
let dir = if let Some(dir) = dir {
|
let dir = if let Some(dir) = dir {
|
||||||
dir
|
dir
|
||||||
} else {
|
} else {
|
||||||
@ -72,6 +80,11 @@ fn setup(reader: BinaryReader, dir: Option<PathBuf>, clear: bool) -> Option<Path
|
|||||||
|
|
||||||
let mut ts = 0;
|
let mut ts = 0;
|
||||||
if clear || !is_timestamp_matches(&dir, &mut ts) {
|
if clear || !is_timestamp_matches(&dir, &mut ts) {
|
||||||
|
#[cfg(windows)]
|
||||||
|
if _args.is_empty() {
|
||||||
|
*_ui = true;
|
||||||
|
ui::setup();
|
||||||
|
}
|
||||||
std::fs::remove_dir_all(&dir).ok();
|
std::fs::remove_dir_all(&dir).ok();
|
||||||
}
|
}
|
||||||
for file in reader.files.iter() {
|
for file in reader.files.iter() {
|
||||||
@ -85,7 +98,7 @@ fn setup(reader: BinaryReader, dir: Option<PathBuf>, clear: bool) -> Option<Path
|
|||||||
Some(dir.join(&reader.exe))
|
Some(dir.join(&reader.exe))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(path: PathBuf, args: Vec<String>) {
|
fn execute(path: PathBuf, args: Vec<String>, _ui: bool) {
|
||||||
println!("executing {}", path.display());
|
println!("executing {}", path.display());
|
||||||
// setup env
|
// setup env
|
||||||
let exe = std::env::current_exe().unwrap_or_default();
|
let exe = std::env::current_exe().unwrap_or_default();
|
||||||
@ -97,13 +110,28 @@ fn execute(path: PathBuf, args: Vec<String>) {
|
|||||||
{
|
{
|
||||||
use std::os::windows::process::CommandExt;
|
use std::os::windows::process::CommandExt;
|
||||||
cmd.creation_flags(winapi::um::winbase::CREATE_NO_WINDOW);
|
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())
|
.stdin(Stdio::inherit())
|
||||||
.stdout(Stdio::inherit())
|
.stdout(Stdio::inherit())
|
||||||
.stderr(Stdio::inherit())
|
.stderr(Stdio::inherit())
|
||||||
.spawn()
|
.spawn();
|
||||||
.ok();
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
if _ui {
|
||||||
|
match _child {
|
||||||
|
Ok(child) => unsafe {
|
||||||
|
winapi::um::winuser::AllowSetForegroundWindow(child.id() as u32);
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -121,23 +149,21 @@ fn main() {
|
|||||||
let click_setup = args.is_empty() && arg_exe.to_lowercase().ends_with("install.exe");
|
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");
|
let quick_support = args.is_empty() && arg_exe.to_lowercase().ends_with("qs.exe");
|
||||||
|
|
||||||
#[cfg(windows)]
|
let mut ui = false;
|
||||||
if args.is_empty() {
|
|
||||||
ui::setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
let reader = BinaryReader::default();
|
let reader = BinaryReader::default();
|
||||||
if let Some(exe) = setup(
|
if let Some(exe) = setup(
|
||||||
reader,
|
reader,
|
||||||
None,
|
None,
|
||||||
click_setup || args.contains(&"--silent-install".to_owned()),
|
click_setup || args.contains(&"--silent-install".to_owned()),
|
||||||
|
&args,
|
||||||
|
&mut ui,
|
||||||
) {
|
) {
|
||||||
if click_setup {
|
if click_setup {
|
||||||
args = vec!["--install".to_owned()];
|
args = vec!["--install".to_owned()];
|
||||||
} else if quick_support {
|
} else if quick_support {
|
||||||
args = vec!["--quick_support".to_owned()];
|
args = vec!["--quick_support".to_owned()];
|
||||||
}
|
}
|
||||||
execute(exe, args);
|
execute(exe, args, ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -853,7 +853,32 @@ pub fn run_me<T: AsRef<std::ffi::OsStr>>(args: Vec<T>) -> std::io::Result<std::p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let cmd = std::env::current_exe()?;
|
let cmd = std::env::current_exe()?;
|
||||||
return std::process::Command::new(cmd).args(&args).spawn();
|
let mut cmd = std::process::Command::new(cmd);
|
||||||
|
#[cfg(windows)]
|
||||||
|
let mut force_foreground = false;
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
let arg_strs = args
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.as_ref().to_string_lossy())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
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]
|
#[inline]
|
||||||
|
@ -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 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 EXPLORER_EXE: &'static str = "explorer.exe";
|
||||||
|
pub const SET_FOREGROUND_WINDOW: &'static str = "SET_FOREGROUND_WINDOW";
|
||||||
|
|
||||||
pub fn get_focused_display(displays: Vec<DisplayInfo>) -> Option<usize> {
|
pub fn get_focused_display(displays: Vec<DisplayInfo>) -> Option<usize> {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -461,8 +462,18 @@ const SERVICE_TYPE: ServiceType = ServiceType::OWN_PROCESS;
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn get_current_session(rdp: BOOL) -> DWORD;
|
fn get_current_session(rdp: BOOL) -> DWORD;
|
||||||
fn LaunchProcessWin(cmd: *const u16, session_id: DWORD, as_user: BOOL, token_pid: &mut DWORD) -> HANDLE;
|
fn LaunchProcessWin(
|
||||||
fn GetSessionUserTokenWin(lphUserToken: LPHANDLE, dwSessionId: DWORD, as_user: BOOL, token_pid: &mut DWORD) -> BOOL;
|
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 selectInputDesktop() -> BOOL;
|
||||||
fn inputDesktopSelected() -> BOOL;
|
fn inputDesktopSelected() -> BOOL;
|
||||||
fn is_windows_server() -> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -87,6 +87,8 @@ pub fn start(args: &mut [String]) {
|
|||||||
frame.set_title(&crate::get_app_name());
|
frame.set_title(&crate::get_app_name());
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
crate::platform::delegate::make_menubar(frame.get_host(), args.is_empty());
|
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;
|
let page;
|
||||||
if args.len() > 1 && args[0] == "--play" {
|
if args.len() > 1 && args[0] == "--play" {
|
||||||
args[0] = "--connect".to_owned();
|
args[0] = "--connect".to_owned();
|
||||||
|
Loading…
Reference in New Issue
Block a user