blob: fc041ef517013e9439ac21e8f66921580d8cabc0 [file] [log] [blame]
sergeyu@chromium.orgaf54d4b2013-10-16 02:42:38 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
12
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +000013#include "webrtc/modules/desktop_capture/desktop_frame.h"
14#include "webrtc/modules/desktop_capture/mouse_cursor.h"
15#include "webrtc/modules/desktop_capture/win/cursor.h"
16#include "webrtc/system_wrappers/interface/logging.h"
sergeyu@chromium.orgaf54d4b2013-10-16 02:42:38 +000017
18namespace webrtc {
19
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +000020class MouseCursorMonitorWin : public MouseCursorMonitor {
21 public:
22 explicit MouseCursorMonitorWin(HWND window);
jiayl@webrtc.org28bd30a2014-01-17 17:19:16 +000023 explicit MouseCursorMonitorWin(ScreenId screen);
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +000024 virtual ~MouseCursorMonitorWin();
25
26 virtual void Init(Callback* callback, Mode mode) OVERRIDE;
27 virtual void Capture() OVERRIDE;
28
29 private:
jiayl@webrtc.org28bd30a2014-01-17 17:19:16 +000030 DesktopRect GetScreenRect();
31
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +000032 HWND window_;
jiayl@webrtc.org28bd30a2014-01-17 17:19:16 +000033 ScreenId screen_;
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +000034
35 Callback* callback_;
36 Mode mode_;
37
38 HDC desktop_dc_;
39
40 HCURSOR last_cursor_;
41};
42
43MouseCursorMonitorWin::MouseCursorMonitorWin(HWND window)
44 : window_(window),
jiayl@webrtc.org28bd30a2014-01-17 17:19:16 +000045 screen_(kInvalidScreenId),
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +000046 callback_(NULL),
47 mode_(SHAPE_AND_POSITION),
48 desktop_dc_(NULL),
49 last_cursor_(NULL) {
50}
51
jiayl@webrtc.org28bd30a2014-01-17 17:19:16 +000052MouseCursorMonitorWin::MouseCursorMonitorWin(ScreenId screen)
53 : window_(NULL),
54 screen_(screen),
55 callback_(NULL),
56 mode_(SHAPE_AND_POSITION),
57 desktop_dc_(NULL),
58 last_cursor_(NULL) {
59 assert(screen >= kFullDesktopScreenId);
60}
61
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +000062MouseCursorMonitorWin::~MouseCursorMonitorWin() {
63 if (desktop_dc_)
64 ReleaseDC(NULL, desktop_dc_);
65}
66
67void MouseCursorMonitorWin::Init(Callback* callback, Mode mode) {
68 assert(!callback_);
69 assert(callback);
70
71 callback_ = callback;
72 mode_ = mode;
73
74 desktop_dc_ = GetDC(NULL);
75}
76
77void MouseCursorMonitorWin::Capture() {
78 assert(callback_);
79
80 CURSORINFO cursor_info;
81 cursor_info.cbSize = sizeof(CURSORINFO);
82 if (!GetCursorInfo(&cursor_info)) {
83 LOG_F(LS_ERROR) << "Unable to get cursor info. Error = " << GetLastError();
84 return;
85 }
86
87 if (last_cursor_ != cursor_info.hCursor) {
88 last_cursor_ = cursor_info.hCursor;
89 // Note that |cursor_info.hCursor| does not need to be freed.
90 scoped_ptr<MouseCursor> cursor(
91 CreateMouseCursorFromHCursor(desktop_dc_, cursor_info.hCursor));
92 if (cursor.get())
93 callback_->OnMouseCursor(cursor.release());
94 }
95
96 if (mode_ != SHAPE_AND_POSITION)
97 return;
98
99 DesktopVector position(cursor_info.ptScreenPos.x, cursor_info.ptScreenPos.y);
100 bool inside = cursor_info.flags == CURSOR_SHOWING;
101
102 if (window_) {
103 RECT rect;
104 if (!GetWindowRect(window_, &rect)) {
105 position.set(0, 0);
106 inside = false;
107 } else {
jiayl@webrtc.org4845e6e2014-02-04 17:49:12 +0000108 if (inside) {
109 HWND windowUnderCursor = WindowFromPoint(cursor_info.ptScreenPos);
110 inside = windowUnderCursor ?
111 (window_ == GetAncestor(windowUnderCursor, GA_ROOT)) : false;
112 }
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +0000113 position = position.subtract(DesktopVector(rect.left, rect.top));
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +0000114 }
jiayl@webrtc.org28bd30a2014-01-17 17:19:16 +0000115 } else {
116 assert(screen_ != kInvalidScreenId);
117 DesktopRect rect = GetScreenRect();
118 if (inside)
119 inside = rect.Contains(position);
120 position = position.subtract(rect.top_left());
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +0000121 }
122
123 callback_->OnMouseCursorPosition(inside ? INSIDE : OUTSIDE, position);
124}
125
jiayl@webrtc.org28bd30a2014-01-17 17:19:16 +0000126DesktopRect MouseCursorMonitorWin::GetScreenRect() {
127 assert(screen_ != kInvalidScreenId);
128 if (screen_ == kFullDesktopScreenId) {
129 return DesktopRect::MakeXYWH(
130 GetSystemMetrics(SM_XVIRTUALSCREEN),
131 GetSystemMetrics(SM_YVIRTUALSCREEN),
132 GetSystemMetrics(SM_CXVIRTUALSCREEN),
133 GetSystemMetrics(SM_CYVIRTUALSCREEN));
134 }
135 DISPLAY_DEVICE device;
136 device.cb = sizeof(device);
137 BOOL result = EnumDisplayDevices(NULL, screen_, &device, 0);
138 if (!result)
139 return DesktopRect();
140
141 DEVMODE device_mode;
142 device_mode.dmSize = sizeof(device_mode);
143 device_mode.dmDriverExtra = 0;
144 result = EnumDisplaySettingsEx(
145 device.DeviceName, ENUM_CURRENT_SETTINGS, &device_mode, 0);
146 if (!result)
147 return DesktopRect();
148
149 return DesktopRect::MakeXYWH(
150 GetSystemMetrics(SM_XVIRTUALSCREEN) + device_mode.dmPosition.x,
151 GetSystemMetrics(SM_YVIRTUALSCREEN) + device_mode.dmPosition.y,
152 device_mode.dmPelsWidth,
153 device_mode.dmPelsHeight);
154}
155
sergeyu@chromium.orgaf54d4b2013-10-16 02:42:38 +0000156MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
157 const DesktopCaptureOptions& options, WindowId window) {
sergeyu@chromium.org2873c4c2013-10-17 19:47:18 +0000158 return new MouseCursorMonitorWin(reinterpret_cast<HWND>(window));
sergeyu@chromium.orgaf54d4b2013-10-16 02:42:38 +0000159}
160
161MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
jiayl@webrtc.orga2c26542014-01-14 18:26:37 +0000162 const DesktopCaptureOptions& options,
163 ScreenId screen) {
jiayl@webrtc.org28bd30a2014-01-17 17:19:16 +0000164 return new MouseCursorMonitorWin(screen);
sergeyu@chromium.orgaf54d4b2013-10-16 02:42:38 +0000165}
166
167} // namespace webrtc