fix: loosen ghost window filter, only block Program Manager
This commit is contained in:
parent
8a873e4923
commit
948f7de3a9
1 changed files with 21 additions and 49 deletions
|
|
@ -8,9 +8,9 @@ mod win_impl {
|
||||||
use super::*;
|
use super::*;
|
||||||
use windows::Win32::Foundation::{BOOL, HWND, LPARAM};
|
use windows::Win32::Foundation::{BOOL, HWND, LPARAM};
|
||||||
use windows::Win32::UI::WindowsAndMessaging::{
|
use windows::Win32::UI::WindowsAndMessaging::{
|
||||||
BringWindowToTop, EnumWindows, GetWindowLongA, GetWindowTextW, IsIconic,
|
BringWindowToTop, EnumWindows, GetAncestor, GetWindowLongA, GetWindowTextW,
|
||||||
IsWindowVisible, SetForegroundWindow, ShowWindow, GWL_EXSTYLE,
|
IsIconic, IsWindowVisible, SetForegroundWindow, ShowWindow, GA_ROOT,
|
||||||
SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, WS_EX_TOOLWINDOW,
|
GWL_EXSTYLE, SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, WS_EX_TOOLWINDOW,
|
||||||
};
|
};
|
||||||
use windows::Win32::UI::Input::KeyboardAndMouse::{
|
use windows::Win32::UI::Input::KeyboardAndMouse::{
|
||||||
keybd_event, KEYEVENTF_KEYUP, VK_MENU,
|
keybd_event, KEYEVENTF_KEYUP, VK_MENU,
|
||||||
|
|
@ -20,26 +20,7 @@ mod win_impl {
|
||||||
};
|
};
|
||||||
use windows::Win32::System::ProcessStatus::GetModuleBaseNameW;
|
use windows::Win32::System::ProcessStatus::GetModuleBaseNameW;
|
||||||
|
|
||||||
/// Process names that are always excluded (ghost/system windows).
|
// No broad blocklists — only explorer's "Program Manager" is filtered.
|
||||||
const GHOST_PROCESSES: &[&str] = &[
|
|
||||||
"textinputhost",
|
|
||||||
"shellexperiencehost",
|
|
||||||
"searchhost",
|
|
||||||
"startmenuexperiencehost",
|
|
||||||
"lockapp",
|
|
||||||
"systemsettings",
|
|
||||||
"widgets",
|
|
||||||
];
|
|
||||||
|
|
||||||
/// Process names excluded unless the window has a "real" (non-empty) title.
|
|
||||||
const GHOST_UNLESS_TITLED: &[&str] = &[
|
|
||||||
"applicationframehost",
|
|
||||||
];
|
|
||||||
|
|
||||||
/// Window titles that are always excluded.
|
|
||||||
const GHOST_TITLES: &[&str] = &[
|
|
||||||
"program manager",
|
|
||||||
];
|
|
||||||
|
|
||||||
unsafe extern "system" fn enum_callback(hwnd: HWND, lparam: LPARAM) -> BOOL {
|
unsafe extern "system" fn enum_callback(hwnd: HWND, lparam: LPARAM) -> BOOL {
|
||||||
let list = &mut *(lparam.0 as *mut Vec<HWND>);
|
let list = &mut *(lparam.0 as *mut Vec<HWND>);
|
||||||
|
|
@ -85,35 +66,16 @@ mod win_impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a window is a ghost/invisible window that should be filtered out.
|
/// Minimal filter: only block explorer's "Program Manager" desktop window.
|
||||||
fn is_ghost_window(hwnd: HWND, title: &str, process_name: &str) -> bool {
|
fn is_ghost_window(_hwnd: HWND, title: &str, process_name: &str) -> bool {
|
||||||
let title_lower = title.to_lowercase();
|
|
||||||
let proc_lower = process_name.to_lowercase();
|
let proc_lower = process_name.to_lowercase();
|
||||||
|
// Only block explorer when title is "Program Manager" or empty
|
||||||
// Exclude by title
|
if proc_lower == "explorer" {
|
||||||
if GHOST_TITLES.iter().any(|&t| title_lower == t) {
|
let t = title.trim();
|
||||||
return true;
|
if t.is_empty() || t.eq_ignore_ascii_case("program manager") {
|
||||||
}
|
|
||||||
|
|
||||||
// Exclude always-ghost processes
|
|
||||||
if GHOST_PROCESSES.iter().any(|&p| proc_lower == p) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exclude ghost-unless-titled processes (title == process name means no real title)
|
|
||||||
if GHOST_UNLESS_TITLED.iter().any(|&p| proc_lower == p) {
|
|
||||||
// If the title is just the process name or very generic, filter it
|
|
||||||
if title_lower == proc_lower || title.trim().is_empty() {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude tool windows (WS_EX_TOOLWINDOW)
|
|
||||||
let ex_style = unsafe { GetWindowLongA(hwnd, GWL_EXSTYLE) } as u32;
|
|
||||||
if ex_style & WS_EX_TOOLWINDOW.0 != 0 {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,11 +93,21 @@ mod win_impl {
|
||||||
if title.is_empty() {
|
if title.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Skip minimized-to-nothing windows (iconic)
|
// Skip minimized windows
|
||||||
let iconic = unsafe { IsIconic(*hwnd).as_bool() };
|
let iconic = unsafe { IsIconic(*hwnd).as_bool() };
|
||||||
if iconic {
|
if iconic {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Skip tool windows
|
||||||
|
let ex_style = unsafe { GetWindowLongA(*hwnd, GWL_EXSTYLE) } as u32;
|
||||||
|
if ex_style & WS_EX_TOOLWINDOW.0 != 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Only keep top-level windows
|
||||||
|
let root = unsafe { GetAncestor(*hwnd, GA_ROOT) };
|
||||||
|
if root != *hwnd {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let process_name = hwnd_process_name(*hwnd).unwrap_or_default();
|
let process_name = hwnd_process_name(*hwnd).unwrap_or_default();
|
||||||
if process_name.is_empty() {
|
if process_name.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue