mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-28 00:33:06 +08:00
[fix] restore remote cursor visibility during Windows privacy screen
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../screen_capturer/dxgi_cursor_state.h"
|
||||||
#include "privacy_cursor_api.h"
|
#include "privacy_cursor_api.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
@@ -105,6 +106,9 @@ bool PrivacyCursorGuard::Start(std::string& error) {
|
|||||||
process_ = child.hProcess;
|
process_ = child.hProcess;
|
||||||
stop_event_ = stop.value;
|
stop_event_ = stop.value;
|
||||||
stop.value = nullptr;
|
stop.value = nullptr;
|
||||||
|
// The helper may hide the pointer before signaling readiness. Track its
|
||||||
|
// entire lifetime, including startup failure and delayed restoration.
|
||||||
|
SharedDxgiCursorState().SetPrivacyCursorHidden(true);
|
||||||
HANDLE startup_events[] = {ready.value, process_};
|
HANDLE startup_events[] = {ready.value, process_};
|
||||||
const DWORD result = WaitForMultipleObjects(2, startup_events, FALSE, 2000);
|
const DWORD result = WaitForMultipleObjects(2, startup_events, FALSE, 2000);
|
||||||
const DWORD ready_error =
|
const DWORD ready_error =
|
||||||
@@ -127,6 +131,7 @@ bool PrivacyCursorGuard::RestoreAfterFailure(std::string& error) {
|
|||||||
return Failed("Restore system cursor after helper failure", error);
|
return Failed("Restore system cursor after helper failure", error);
|
||||||
}
|
}
|
||||||
restore_pending_ = false;
|
restore_pending_ = false;
|
||||||
|
SharedDxgiCursorState().SetPrivacyCursorHidden(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +157,7 @@ bool PrivacyCursorGuard::Stop(std::string& error) {
|
|||||||
CloseHandle(stop_event_);
|
CloseHandle(stop_event_);
|
||||||
stop_event_ = nullptr;
|
stop_event_ = nullptr;
|
||||||
if (code != ERROR_SUCCESS) return RestoreAfterFailure(error);
|
if (code != ERROR_SUCCESS) return RestoreAfterFailure(error);
|
||||||
|
SharedDxgiCursorState().SetPrivacyCursorHidden(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#ifndef CROSSDESK_DXGI_CURSOR_STATE_H_
|
#ifndef CROSSDESK_DXGI_CURSOR_STATE_H_
|
||||||
#define CROSSDESK_DXGI_CURSOR_STATE_H_
|
#define CROSSDESK_DXGI_CURSOR_STATE_H_
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace crossdesk {
|
namespace crossdesk {
|
||||||
|
|
||||||
@@ -18,24 +18,42 @@ class DxgiCursorState {
|
|||||||
// PointerPosition is undefined on desktop-only updates. Retain the last
|
// PointerPosition is undefined on desktop-only updates. Retain the last
|
||||||
// pointer state until DXGI actually reports another pointer update.
|
// pointer state until DXGI actually reports another pointer update.
|
||||||
if (last_mouse_update_time == 0) return;
|
if (last_mouse_update_time == 0) return;
|
||||||
embedded_monitor_.store(separate_pointer_visible ? nullptr : monitor,
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
std::memory_order_relaxed);
|
if (privacy_cursor_hidden_) return;
|
||||||
|
embedded_monitor_ = separate_pointer_visible ? nullptr : monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
embedded_monitor_.store(nullptr, std::memory_order_relaxed);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
embedded_monitor_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPrivacyCursorHidden(bool hidden) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
if (privacy_cursor_hidden_ == hidden) return;
|
||||||
|
privacy_cursor_hidden_ = hidden;
|
||||||
|
// Pointer updates from before/during suppression cannot describe whether
|
||||||
|
// the restored cursor is embedded. Wait for a fresh DXGI pointer update.
|
||||||
|
embedded_monitor_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShouldDrawCursor(bool system_cursor_visible, void* cursor_monitor) const {
|
bool ShouldDrawCursor(bool system_cursor_visible, void* cursor_monitor) const {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
// MagShowSystemCursor(FALSE) hides the local pointer plane without changing
|
||||||
|
// CURSOR_SHOWING. DXGI Visible=false then means hidden, not embedded in the
|
||||||
|
// captured frame. Keep sending the application's cursor to the controller.
|
||||||
|
// CURSOR_SHOWING still takes precedence when the application hides it.
|
||||||
|
if (privacy_cursor_hidden_) return system_cursor_visible;
|
||||||
// A hidden cursor or a pointer on another monitor also makes DXGI report
|
// A hidden cursor or a pointer on another monitor also makes DXGI report
|
||||||
// Visible=false. Only suppress a visible cursor on the captured monitor.
|
// Visible=false. Only suppress a visible cursor on the captured monitor.
|
||||||
return system_cursor_visible &&
|
return system_cursor_visible &&
|
||||||
(!cursor_monitor ||
|
(!cursor_monitor || embedded_monitor_ != cursor_monitor);
|
||||||
embedded_monitor_.load(std::memory_order_relaxed) != cursor_monitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<void*> embedded_monitor_{nullptr};
|
mutable std::mutex mutex_;
|
||||||
|
void* embedded_monitor_ = nullptr;
|
||||||
|
bool privacy_cursor_hidden_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline DxgiCursorState& SharedDxgiCursorState() {
|
inline DxgiCursorState& SharedDxgiCursorState() {
|
||||||
|
|||||||
Reference in New Issue
Block a user