diff --git a/apps/desktop/src/platform/windows/screen_capturer/secure_desktop_dxgi_capture.h b/apps/desktop/src/platform/windows/screen_capturer/secure_desktop_dxgi_capture.h index 628d9760..305c0b1a 100644 --- a/apps/desktop/src/platform/windows/screen_capturer/secure_desktop_dxgi_capture.h +++ b/apps/desktop/src/platform/windows/screen_capturer/secure_desktop_dxgi_capture.h @@ -16,6 +16,8 @@ #include #include +#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 pixels_; }; diff --git a/apps/desktop/src/platform/windows/screen_capturer/secure_desktop_dxgi_cursor_state.h b/apps/desktop/src/platform/windows/screen_capturer/secure_desktop_dxgi_cursor_state.h new file mode 100644 index 00000000..f9adaaf5 --- /dev/null +++ b/apps/desktop/src/platform/windows/screen_capturer/secure_desktop_dxgi_cursor_state.h @@ -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 + +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_ diff --git a/apps/desktop/src/platform/windows/service/session_helper_main.cpp b/apps/desktop/src/platform/windows/service/session_helper_main.cpp index 848f37be..a0995602 100644 --- a/apps/desktop/src/platform/windows/service/session_helper_main.cpp +++ b/apps/desktop/src/platform/windows/service/session_helper_main.cpp @@ -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 {