From 99f8cd0ae2f05c24410ddd6b2d9ea3d56f1fec5f Mon Sep 17 00:00:00 2001 From: zijiehe Date: Fri, 13 May 2016 16:41:50 -0700 Subject: [PATCH] CURSORINFO.flags should be checked before capturing its bitmap BUG=566178, 428886 Review-Url: https://codereview.webrtc.org/1959863002 Cr-Commit-Position: refs/heads/master@{#12739} --- .../mouse_cursor_monitor_win.cc | 56 +++++++++++++++---- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/webrtc/modules/desktop_capture/mouse_cursor_monitor_win.cc b/webrtc/modules/desktop_capture/mouse_cursor_monitor_win.cc index 204bb00b16..479a39a021 100644 --- a/webrtc/modules/desktop_capture/mouse_cursor_monitor_win.cc +++ b/webrtc/modules/desktop_capture/mouse_cursor_monitor_win.cc @@ -11,10 +11,12 @@ #include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h" #include +#include #include #include "webrtc/modules/desktop_capture/desktop_frame.h" +#include "webrtc/modules/desktop_capture/desktop_geometry.h" #include "webrtc/modules/desktop_capture/mouse_cursor.h" #include "webrtc/modules/desktop_capture/win/cursor.h" #include "webrtc/modules/desktop_capture/win/window_capture_utils.h" @@ -22,6 +24,17 @@ namespace webrtc { +namespace { + +bool IsSameCursorShape(const CURSORINFO& left, const CURSORINFO& right) { + // If the cursors are not showing, we do not care the hCursor handle. + return left.flags == right.flags && + (left.flags != CURSOR_SHOWING || + left.hCursor == right.hCursor); +} + +} // namespace + class MouseCursorMonitorWin : public MouseCursorMonitor { public: explicit MouseCursorMonitorWin(HWND window); @@ -45,7 +58,8 @@ class MouseCursorMonitorWin : public MouseCursorMonitor { HDC desktop_dc_; - HCURSOR last_cursor_; + // The last CURSORINFO (converted to MouseCursor) we have sent to the client. + CURSORINFO last_cursor_; }; MouseCursorMonitorWin::MouseCursorMonitorWin(HWND window) @@ -53,8 +67,8 @@ MouseCursorMonitorWin::MouseCursorMonitorWin(HWND window) screen_(kInvalidScreenId), callback_(NULL), mode_(SHAPE_AND_POSITION), - desktop_dc_(NULL), - last_cursor_(NULL) { + desktop_dc_(NULL) { + memset(&last_cursor_, 0, sizeof(CURSORINFO)); } MouseCursorMonitorWin::MouseCursorMonitorWin(ScreenId screen) @@ -62,9 +76,9 @@ MouseCursorMonitorWin::MouseCursorMonitorWin(ScreenId screen) screen_(screen), callback_(NULL), mode_(SHAPE_AND_POSITION), - desktop_dc_(NULL), - last_cursor_(NULL) { + desktop_dc_(NULL) { assert(screen >= kFullDesktopScreenId); + memset(&last_cursor_, 0, sizeof(CURSORINFO)); } MouseCursorMonitorWin::~MouseCursorMonitorWin() { @@ -92,13 +106,31 @@ void MouseCursorMonitorWin::Capture() { return; } - if (last_cursor_ != cursor_info.hCursor) { - last_cursor_ = cursor_info.hCursor; - // Note that |cursor_info.hCursor| does not need to be freed. - std::unique_ptr cursor( - CreateMouseCursorFromHCursor(desktop_dc_, cursor_info.hCursor)); - if (cursor.get()) - callback_->OnMouseCursor(cursor.release()); + if (!IsSameCursorShape(cursor_info, last_cursor_)) { + if (cursor_info.flags == CURSOR_SUPPRESSED) { + // The cursor is intentionally hidden now, send an empty bitmap. + last_cursor_ = cursor_info; + callback_->OnMouseCursor(new MouseCursor( + new BasicDesktopFrame(DesktopSize()), DesktopVector())); + } else { + // According to MSDN https://goo.gl/u6gyuC, HCURSOR instances returned by + // functions other than CreateCursor do not need to be actively destroyed. + // And CloseHandle function (https://goo.gl/ja5ycW) does not close a + // cursor, so assume a HCURSOR does not need to be closed. + if (cursor_info.flags == 0) { + // Host machine does not have a hardware mouse attached, we will send a + // default one instead. + // Note, Windows automatically caches cursor resource, so we do not need + // to cache the result of LoadCursor. + cursor_info.hCursor = LoadCursor(nullptr, IDC_ARROW); + } + std::unique_ptr cursor( + CreateMouseCursorFromHCursor(desktop_dc_, cursor_info.hCursor)); + if (cursor) { + last_cursor_ = cursor_info; + callback_->OnMouseCursor(cursor.release()); + } + } } if (mode_ != SHAPE_AND_POSITION)