[fix] prevent duplicate cursors on Windows lock screen

This commit is contained in:
kunkundi
2026-10-09 10:19:20 +08:00
parent 4d65d12add
commit 080b9760e3
3 changed files with 47 additions and 11 deletions
@@ -16,6 +16,8 @@
#include <cstdint>
#include <vector>
#include "secure_desktop_dxgi_cursor_state.h"
namespace crossdesk {
// Owned by the SYSTEM helper's capture thread, after binding its input desktop.
@@ -85,9 +87,8 @@ class SecureDesktopDxgiCapture {
IDXGIOutputDuplication* duplication;
~ReleaseFrame() { duplication->ReleaseFrame(); }
} release{duplication_.Get()};
if (info.LastMouseUpdateTime.QuadPart != 0) {
cursor_embedded_ = !info.PointerPosition.Visible;
}
cursor_state_.Update(info.LastMouseUpdateTime.QuadPart,
info.PointerPosition.Visible != FALSE);
// Pointer-only updates leave the desktop image unchanged.
if (info.LastPresentTime.QuadPart == 0 && !pixels_.empty()) return S_OK;
@@ -134,12 +135,11 @@ class SecureDesktopDxgiCapture {
}
int stride() const { return stride_; }
bool updated() const { return updated_; }
const DXGI_OUTPUT_DESC& output() const { return output_desc_; }
void SetSoftwareCursor(bool software) { cursor_embedded_ = software; }
bool CursorEmbedded(const CURSORINFO& cursor) const {
return cursor_embedded_ && (cursor.flags & CURSOR_SHOWING) != 0 &&
MonitorFromPoint(cursor.ptScreenPos, MONITOR_DEFAULTTONULL) ==
output_desc_.Monitor;
return cursor_state_.IsEmbedded(
(cursor.flags & CURSOR_SHOWING) != 0,
MonitorFromPoint(cursor.ptScreenPos, MONITOR_DEFAULTTONULL) ==
output_desc_.Monitor);
}
private:
@@ -150,7 +150,7 @@ class SecureDesktopDxgiCapture {
DXGI_OUTPUT_DESC output_desc_{};
libyuv::RotationMode rotation_ = libyuv::kRotate0;
int offset_x_ = 0, offset_y_ = 0, stride_ = 0;
bool cursor_embedded_ = false;
SecureDesktopDxgiCursorState cursor_state_;
bool updated_ = false;
std::vector<uint8_t> pixels_;
};
@@ -0,0 +1,38 @@
/*
* @Author: DI JUNKUN
* @Date: 2026-10-09
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _SECURE_DESKTOP_DXGI_CURSOR_STATE_H_
#define _SECURE_DESKTOP_DXGI_CURSOR_STATE_H_
#include <cstdint>
namespace crossdesk {
// Owned by one secure-desktop duplication instance. Desktop-only frames and
// timeouts retain the pointer mode; PointerPosition is undefined without a
// mouse update.
class SecureDesktopDxgiCursorState {
public:
void Update(int64_t last_mouse_update_time, bool separate_pointer_visible) {
if (last_mouse_update_time != 0) {
embedded_ = !separate_pointer_visible;
}
}
bool IsEmbedded(bool system_cursor_visible, bool cursor_on_output) const {
return embedded_ && system_cursor_visible && cursor_on_output;
}
private:
// Secure desktops can composite the cursor without sending pointer-plane
// updates, even on physical displays. Until DXGI explicitly reports a
// separate pointer, do not add another cursor to the frame or controller.
bool embedded_ = true;
};
} // namespace crossdesk
#endif // _SECURE_DESKTOP_DXGI_CURSOR_STATE_H_
@@ -1418,8 +1418,6 @@ struct SecureDesktopCaptureResources {
const HRESULT hr = candidate->Initialize(
request.left, request.top, request.width, request.height);
if (SUCCEEDED(hr)) {
candidate->SetSoftwareCursor(crossdesk::IsUsbmmiddDisplayDevice(
candidate->output().DeviceName));
dxgi = std::move(candidate);
dxgi_started = now;
} else {