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}
This commit is contained in:
zijiehe 2016-05-13 16:41:50 -07:00 committed by Commit bot
parent 3f90087ce8
commit 99f8cd0ae2

View File

@ -11,10 +11,12 @@
#include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
#include <assert.h>
#include <string.h>
#include <memory>
#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<MouseCursor> 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<MouseCursor> cursor(
CreateMouseCursorFromHCursor(desktop_dc_, cursor_info.hCursor));
if (cursor) {
last_cursor_ = cursor_info;
callback_->OnMouseCursor(cursor.release());
}
}
}
if (mode_ != SHAPE_AND_POSITION)