mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-18 01:46:47 +08:00
[fix] avoid false Windows privacy screen obstruction failures
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "privacy_input_guard.h"
|
||||
#include "privacy_probe_pattern.h"
|
||||
#include "privacy_probe_renderer.h"
|
||||
#include "privacy_window_visibility.h"
|
||||
#include "rd_log.h"
|
||||
|
||||
#ifndef WDA_EXCLUDEFROMCAPTURE
|
||||
@@ -379,6 +380,7 @@ class WindowsPrivacyBackend final : public PrivacyBackend {
|
||||
continue;
|
||||
if (GetWindowRect(above, &bounds) &&
|
||||
IntersectRect(&intersection, &bounds, &w.rect)) {
|
||||
if (IsNonObstructingPrivacyWindow(above, bounds)) continue;
|
||||
char window_class[128]{};
|
||||
DWORD process_id = 0;
|
||||
GetClassNameA(above, window_class, sizeof(window_class));
|
||||
@@ -387,16 +389,19 @@ class WindowsPrivacyBackend final : public PrivacyBackend {
|
||||
if (above != last_obstruction_ ||
|
||||
now - last_obstruction_log_ >= 1000) {
|
||||
LOG_WARN(
|
||||
"Privacy cover obstructed: class={}, process={}; "
|
||||
"Potential privacy cover overlap: class={}, process={}, "
|
||||
"band={}, bounds=({}, {})-({}, {}), exstyle=0x{:x}; "
|
||||
"remote operation paused",
|
||||
window_class, process_id);
|
||||
window_class, process_id, above_band, bounds.left, bounds.top,
|
||||
bounds.right, bounds.bottom,
|
||||
GetWindowLongPtrW(above, GWL_EXSTYLE));
|
||||
last_obstruction_ = above;
|
||||
last_obstruction_log_ = now;
|
||||
}
|
||||
// A higher-band/system window cannot be repaired by raising an
|
||||
// ordinary cover. Retain protection and require explicit recovery.
|
||||
// HWND order cannot prove compositor order, but this window may
|
||||
// display content. Retain protection and require explicit recovery.
|
||||
return {
|
||||
"A system or higher-band window overrides privacy coverage; "
|
||||
"A visible window may overlap privacy coverage; "
|
||||
"remote operation paused. Turn privacy off to recover.",
|
||||
false};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2026-09-11
|
||||
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _PRIVACY_WINDOW_VISIBILITY_H_
|
||||
#define _PRIVACY_WINDOW_VISIBILITY_H_
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
// Called for a visible foreign window whose full bounds intersect a cover.
|
||||
// Inspect it on every check: an OSD helper can grow into a content window.
|
||||
inline bool IsNonObstructingPrivacyWindow(HWND window, const RECT& bounds) {
|
||||
const auto styles = GetWindowLongPtrW(window, GWL_EXSTYLE);
|
||||
if (!(styles & WS_EX_LAYERED)) return false;
|
||||
|
||||
BYTE alpha = 0;
|
||||
DWORD flags = 0;
|
||||
// WS_EX_TRANSPARENT alone does not imply invisible pixels. Likewise,
|
||||
// UpdateLayeredWindow windows can reject this query; failure proves nothing.
|
||||
if (GetLayeredWindowAttributes(window, nullptr, &alpha, &flags) &&
|
||||
(flags & LWA_ALPHA) && alpha == 0)
|
||||
return true;
|
||||
|
||||
constexpr LONG_PTR helper_styles =
|
||||
WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE | WS_EX_TRANSPARENT;
|
||||
const auto width = static_cast<int64_t>(bounds.right) - bounds.left;
|
||||
const auto height = static_cast<int64_t>(bounds.bottom) - bounds.top;
|
||||
// Single-pixel, nonactivating OSD placeholders cannot display meaningful
|
||||
// desktop content. Use the whole window, never its clipped intersection;
|
||||
// larger OSDs and windows with unknown opacity still require coverage checks.
|
||||
return (styles & helper_styles) == helper_styles && width == 1 && height == 1;
|
||||
}
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif // _PRIVACY_WINDOW_VISIBILITY_H_
|
||||
Reference in New Issue
Block a user