diff --git a/webrtc/modules/desktop_capture/BUILD.gn b/webrtc/modules/desktop_capture/BUILD.gn index 9067177165..2a1eedd1e0 100644 --- a/webrtc/modules/desktop_capture/BUILD.gn +++ b/webrtc/modules/desktop_capture/BUILD.gn @@ -48,6 +48,7 @@ source_set("desktop_capture") { "mouse_cursor_monitor.h", "mouse_cursor_monitor_mac.mm", "mouse_cursor_monitor_win.cc", + "mouse_cursor_shape.h", "screen_capture_frame_queue.cc", "screen_capture_frame_queue.h", "screen_capturer.cc", diff --git a/webrtc/modules/desktop_capture/desktop_capture.gypi b/webrtc/modules/desktop_capture/desktop_capture.gypi index 1b702f27ee..df6c4bcf59 100644 --- a/webrtc/modules/desktop_capture/desktop_capture.gypi +++ b/webrtc/modules/desktop_capture/desktop_capture.gypi @@ -51,6 +51,7 @@ "mouse_cursor_monitor_mac.mm", "mouse_cursor_monitor_win.cc", "mouse_cursor_monitor_x11.cc", + "mouse_cursor_shape.h", "screen_capture_frame_queue.cc", "screen_capture_frame_queue.h", "screen_capturer.cc", diff --git a/webrtc/modules/desktop_capture/mouse_cursor_shape.h b/webrtc/modules/desktop_capture/mouse_cursor_shape.h new file mode 100644 index 0000000000..e759cf2edc --- /dev/null +++ b/webrtc/modules/desktop_capture/mouse_cursor_shape.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_MOUSE_CURSOR_SHAPE_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_MOUSE_CURSOR_SHAPE_H_ + +#include + +#include "webrtc/modules/desktop_capture/desktop_geometry.h" + +namespace webrtc { + +// Type used to return mouse cursor shape from video capturers. +// +// TODO(sergeyu): Remove this type and use MouseCursor instead. +struct MouseCursorShape { + // Size of the cursor in screen pixels. + DesktopSize size; + + // Coordinates of the cursor hotspot relative to upper-left corner. + DesktopVector hotspot; + + // Cursor pixmap data in 32-bit BGRA format. + std::string data; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_MOUSE_CURSOR_SHAPE_H_ diff --git a/webrtc/modules/desktop_capture/screen_capturer.h b/webrtc/modules/desktop_capture/screen_capturer.h index ab074f1db5..a8d40a72ef 100644 --- a/webrtc/modules/desktop_capture/screen_capturer.h +++ b/webrtc/modules/desktop_capture/screen_capturer.h @@ -21,6 +21,7 @@ namespace webrtc { class DesktopCaptureOptions; +struct MouseCursorShape; // Class used to capture video frames asynchronously. // @@ -49,6 +50,21 @@ class ScreenCapturer : public DesktopCapturer { }; typedef std::vector ScreenList; + // Provides callbacks used by the capturer to pass captured video frames and + // mouse cursor shapes to the processing pipeline. + // + // TODO(sergeyu): Move cursor shape capturing to a separate class because it's + // unrelated. + class MouseShapeObserver { + public: + // Called when the cursor shape has changed. Must take ownership of + // |cursor_shape|. + virtual void OnCursorShapeChanged(MouseCursorShape* cursor_shape) = 0; + + protected: + virtual ~MouseShapeObserver() {} + }; + virtual ~ScreenCapturer() {} // Creates platform-specific capturer. @@ -68,6 +84,11 @@ class ScreenCapturer : public DesktopCapturer { static ScreenCapturer* CreateWithDisableAero(bool disable_aero); #endif // defined(WEBRTC_WIN) + // Called at the beginning of a capturing session. |mouse_shape_observer| must + // remain valid until the capturer is destroyed. + virtual void SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) = 0; + // Get the list of screens (not containing kFullDesktopScreenId). Returns // false in case of a failure. virtual bool GetScreenList(ScreenList* screens) = 0; diff --git a/webrtc/modules/desktop_capture/screen_capturer_mac.mm b/webrtc/modules/desktop_capture/screen_capturer_mac.mm index d4200e23e7..effe7ebff0 100644 --- a/webrtc/modules/desktop_capture/screen_capturer_mac.mm +++ b/webrtc/modules/desktop_capture/screen_capturer_mac.mm @@ -28,6 +28,7 @@ #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h" #include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h" #include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h" +#include "webrtc/modules/desktop_capture/mouse_cursor_shape.h" #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" #include "webrtc/system_wrappers/interface/logging.h" @@ -199,10 +200,14 @@ class ScreenCapturerMac : public ScreenCapturer { virtual void Start(Callback* callback) OVERRIDE; virtual void Capture(const DesktopRegion& region) OVERRIDE; virtual void SetExcludedWindow(WindowId window) OVERRIDE; + virtual void SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) OVERRIDE; virtual bool GetScreenList(ScreenList* screens) OVERRIDE; virtual bool SelectScreen(ScreenId id) OVERRIDE; private: + void CaptureCursor(); + void GlBlitFast(const DesktopFrame& frame, const DesktopRegion& region); void GlBlitSlow(const DesktopFrame& frame); @@ -234,6 +239,7 @@ class ScreenCapturerMac : public ScreenCapturer { DesktopFrame* CreateFrame(); Callback* callback_; + MouseShapeObserver* mouse_shape_observer_; CGLContextObj cgl_context_; ScopedPixelBufferObject pixel_buffer_object_; @@ -258,6 +264,9 @@ class ScreenCapturerMac : public ScreenCapturer { // recently captured screen. ScreenCapturerHelper helper_; + // The last cursor that we sent to the client. + MouseCursorShape last_cursor_; + // Contains an invalid region from the previous capture. DesktopRegion last_invalid_region_; @@ -309,6 +318,7 @@ class InvertedDesktopFrame : public DesktopFrame { ScreenCapturerMac::ScreenCapturerMac( scoped_refptr desktop_config_monitor) : callback_(NULL), + mouse_shape_observer_(NULL), cgl_context_(NULL), current_display_(0), dip_to_pixel_scale_(1.0f), @@ -448,6 +458,9 @@ void ScreenCapturerMac::Capture(const DesktopRegion& region_to_capture) { // and accessing display structures. desktop_config_monitor_->Unlock(); + // Capture the current cursor shape and notify |callback_| if it has changed. + CaptureCursor(); + new_frame->set_capture_time_ms( (TickTime::Now() - capture_start_time).Milliseconds()); callback_->OnCaptureCompleted(new_frame); @@ -457,6 +470,13 @@ void ScreenCapturerMac::SetExcludedWindow(WindowId window) { excluded_window_ = window; } +void ScreenCapturerMac::SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) { + assert(!mouse_shape_observer_); + assert(mouse_shape_observer); + mouse_shape_observer_ = mouse_shape_observer; +} + bool ScreenCapturerMac::GetScreenList(ScreenList* screens) { assert(screens->size() == 0); if (rtc::GetOSVersionName() < rtc::kMacOSLion) { @@ -498,6 +518,61 @@ bool ScreenCapturerMac::SelectScreen(ScreenId id) { return true; } +void ScreenCapturerMac::CaptureCursor() { + if (!mouse_shape_observer_) + return; + + NSCursor* cursor = [NSCursor currentSystemCursor]; + if (cursor == nil) + return; + + NSImage* nsimage = [cursor image]; + NSPoint hotspot = [cursor hotSpot]; + NSSize size = [nsimage size]; + CGImageRef image = [nsimage CGImageForProposedRect:NULL + context:nil + hints:nil]; + if (image == nil) + return; + + if (CGImageGetBitsPerPixel(image) != 32 || + CGImageGetBytesPerRow(image) != (size.width * 4) || + CGImageGetBitsPerComponent(image) != 8) { + return; + } + + CGDataProviderRef provider = CGImageGetDataProvider(image); + CFDataRef image_data_ref = CGDataProviderCopyData(provider); + if (image_data_ref == NULL) + return; + + const char* cursor_src_data = + reinterpret_cast(CFDataGetBytePtr(image_data_ref)); + int data_size = CFDataGetLength(image_data_ref); + + // Create a MouseCursorShape that describes the cursor and pass it to + // the client. + scoped_ptr cursor_shape(new MouseCursorShape()); + cursor_shape->size.set(size.width, size.height); + cursor_shape->hotspot.set(hotspot.x, hotspot.y); + cursor_shape->data.assign(cursor_src_data, cursor_src_data + data_size); + + CFRelease(image_data_ref); + + // Compare the current cursor with the last one we sent to the client. If + // they're the same, then don't bother sending the cursor again. + if (last_cursor_.size.equals(cursor_shape->size) && + last_cursor_.hotspot.equals(cursor_shape->hotspot) && + last_cursor_.data == cursor_shape->data) { + return; + } + + // Record the last cursor image that we sent to the client. + last_cursor_ = *cursor_shape; + + mouse_shape_observer_->OnCursorShapeChanged(cursor_shape.release()); +} + void ScreenCapturerMac::GlBlitFast(const DesktopFrame& frame, const DesktopRegion& region) { // Clip to the size of our current screen. diff --git a/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h b/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h index 373e66f7bd..aa0e808eb6 100644 --- a/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h +++ b/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h @@ -12,6 +12,7 @@ #define WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_MOCK_OBJECTS_H_ #include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/modules/desktop_capture/mouse_cursor_shape.h" #include "webrtc/modules/desktop_capture/screen_capturer.h" namespace webrtc { @@ -23,6 +24,8 @@ class MockScreenCapturer : public ScreenCapturer { MOCK_METHOD1(Start, void(Callback* callback)); MOCK_METHOD1(Capture, void(const DesktopRegion& region)); + MOCK_METHOD1(SetMouseShapeObserver, void( + MouseShapeObserver* mouse_shape_observer)); MOCK_METHOD1(GetScreenList, bool(ScreenList* screens)); MOCK_METHOD1(SelectScreen, bool(ScreenId id)); @@ -42,6 +45,24 @@ class MockScreenCapturerCallback : public ScreenCapturer::Callback { DISALLOW_COPY_AND_ASSIGN(MockScreenCapturerCallback); }; +class MockMouseShapeObserver : public ScreenCapturer::MouseShapeObserver { + public: + MockMouseShapeObserver() {} + virtual ~MockMouseShapeObserver() {} + + void OnCursorShapeChanged(MouseCursorShape* cursor_shape) OVERRIDE { + OnCursorShapeChangedPtr(cursor_shape); + delete cursor_shape; + } + + MOCK_METHOD1(OnCursorShapeChangedPtr, + void(MouseCursorShape* cursor_shape)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockMouseShapeObserver); +}; + + } // namespace webrtc #endif // WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_MOCK_OBJECTS_H_ diff --git a/webrtc/modules/desktop_capture/screen_capturer_unittest.cc b/webrtc/modules/desktop_capture/screen_capturer_unittest.cc index 1a4b9cfc2d..50ff7a2853 100644 --- a/webrtc/modules/desktop_capture/screen_capturer_unittest.cc +++ b/webrtc/modules/desktop_capture/screen_capturer_unittest.cc @@ -37,6 +37,7 @@ class ScreenCapturerTest : public testing::Test { protected: scoped_ptr capturer_; + MockMouseShapeObserver mouse_observer_; MockScreenCapturerCallback callback_; }; @@ -68,6 +69,7 @@ TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) { } TEST_F(ScreenCapturerTest, StartCapturer) { + capturer_->SetMouseShapeObserver(&mouse_observer_); capturer_->Start(&callback_); } @@ -76,6 +78,8 @@ TEST_F(ScreenCapturerTest, Capture) { DesktopFrame* frame = NULL; EXPECT_CALL(callback_, OnCaptureCompleted(_)) .WillOnce(SaveArg<0>(&frame)); + EXPECT_CALL(mouse_observer_, OnCursorShapeChangedPtr(_)) + .Times(AnyNumber()); EXPECT_CALL(callback_, CreateSharedMemory(_)) .Times(AnyNumber()) @@ -108,6 +112,8 @@ TEST_F(ScreenCapturerTest, UseSharedBuffers) { DesktopFrame* frame = NULL; EXPECT_CALL(callback_, OnCaptureCompleted(_)) .WillOnce(SaveArg<0>(&frame)); + EXPECT_CALL(mouse_observer_, OnCursorShapeChangedPtr(_)) + .Times(AnyNumber()); EXPECT_CALL(callback_, CreateSharedMemory(_)) .Times(AnyNumber()) diff --git a/webrtc/modules/desktop_capture/screen_capturer_x11.cc b/webrtc/modules/desktop_capture/screen_capturer_x11.cc index 0064faa587..4d07d98c62 100644 --- a/webrtc/modules/desktop_capture/screen_capturer_x11.cc +++ b/webrtc/modules/desktop_capture/screen_capturer_x11.cc @@ -21,6 +21,7 @@ #include "webrtc/modules/desktop_capture/desktop_capture_options.h" #include "webrtc/modules/desktop_capture/desktop_frame.h" #include "webrtc/modules/desktop_capture/differ.h" +#include "webrtc/modules/desktop_capture/mouse_cursor_shape.h" #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h" @@ -54,6 +55,8 @@ class ScreenCapturerLinux : public ScreenCapturer, virtual void Capture(const DesktopRegion& region) OVERRIDE; // ScreenCapturer interface. + virtual void SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) OVERRIDE; virtual bool GetScreenList(ScreenList* screens) OVERRIDE; virtual bool SelectScreen(ScreenId id) OVERRIDE; @@ -65,6 +68,9 @@ class ScreenCapturerLinux : public ScreenCapturer, void InitXDamage(); + // Capture the cursor image and notify the delegate if it was captured. + void CaptureCursor(); + // Capture screen pixels to the current buffer in the queue. In the DAMAGE // case, the ScreenCapturerHelper already holds the list of invalid rectangles // from HandleXEvent(). In the non-DAMAGE case, this captures the @@ -87,6 +93,7 @@ class ScreenCapturerLinux : public ScreenCapturer, DesktopCaptureOptions options_; Callback* callback_; + MouseShapeObserver* mouse_shape_observer_; // X11 graphics context. GC gc_; @@ -126,6 +133,7 @@ class ScreenCapturerLinux : public ScreenCapturer, ScreenCapturerLinux::ScreenCapturerLinux() : callback_(NULL), + mouse_shape_observer_(NULL), gc_(NULL), root_window_(BadValue), has_xfixes_(false), @@ -145,6 +153,10 @@ ScreenCapturerLinux::~ScreenCapturerLinux() { options_.x_display()->RemoveEventHandler( damage_event_base_ + XDamageNotify, this); } + if (has_xfixes_) { + options_.x_display()->RemoveEventHandler( + xfixes_event_base_ + XFixesCursorNotify, this); + } DeinitXlib(); } @@ -184,6 +196,14 @@ bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) { return false; } + if (has_xfixes_) { + // Register for changes to the cursor shape. + XFixesSelectCursorInput(display(), root_window_, + XFixesDisplayCursorNotifyMask); + options_.x_display()->AddEventHandler( + xfixes_event_base_ + XFixesCursorNotify, this); + } + if (options_.use_update_notifications()) { InitXDamage(); } @@ -284,6 +304,14 @@ void ScreenCapturerLinux::Capture(const DesktopRegion& region) { callback_->OnCaptureCompleted(result); } +void ScreenCapturerLinux::SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) { + DCHECK(!mouse_shape_observer_); + DCHECK(mouse_shape_observer); + + mouse_shape_observer_ = mouse_shape_observer; +} + bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) { DCHECK(screens->size() == 0); // TODO(jiayl): implement screen enumeration. @@ -309,10 +337,50 @@ bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) { } else if (event.type == ConfigureNotify) { ScreenConfigurationChanged(); return true; + } else if (has_xfixes_ && + event.type == xfixes_event_base_ + XFixesCursorNotify) { + const XFixesCursorNotifyEvent* cursor_event = + reinterpret_cast(&event); + if (cursor_event->window == root_window_ && + cursor_event->subtype == XFixesDisplayCursorNotify) { + CaptureCursor(); + } + // Always return false for cursor notifications, because there might be + // other listeners for these for the same window. + return false; } return false; } +void ScreenCapturerLinux::CaptureCursor() { + DCHECK(has_xfixes_); + + XFixesCursorImage* img = XFixesGetCursorImage(display()); + if (!img) { + return; + } + + scoped_ptr cursor(new MouseCursorShape()); + cursor->size = DesktopSize(img->width, img->height); + cursor->hotspot = DesktopVector(img->xhot, img->yhot); + + int total_bytes = cursor->size.width ()* cursor->size.height() * + DesktopFrame::kBytesPerPixel; + cursor->data.resize(total_bytes); + + // Xlib stores 32-bit data in longs, even if longs are 64-bits long. + unsigned long* src = img->pixels; + uint32_t* dst = reinterpret_cast(&*(cursor->data.begin())); + uint32_t* dst_end = dst + (img->width * img->height); + while (dst < dst_end) { + *dst++ = static_cast(*src++); + } + XFree(img); + + if (mouse_shape_observer_) + mouse_shape_observer_->OnCursorShapeChanged(cursor.release()); +} + DesktopFrame* ScreenCapturerLinux::CaptureScreen() { DesktopFrame* frame = queue_.current_frame()->Share(); assert(x_server_pixel_buffer_.window_size().equals(frame->size())); diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.cc b/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.cc index e6c0605c5e..dc10eceb78 100644 --- a/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.cc +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.cc @@ -38,6 +38,7 @@ const wchar_t kDwmapiLibraryName[] = L"dwmapi.dll"; ScreenCapturerWinGdi::ScreenCapturerWinGdi(const DesktopCaptureOptions& options) : callback_(NULL), + mouse_shape_observer_(NULL), current_screen_id_(kFullDesktopScreenId), desktop_dc_(NULL), memory_dc_(NULL), @@ -130,6 +131,18 @@ void ScreenCapturerWinGdi::Capture(const DesktopRegion& region) { frame->set_capture_time_ms( (TickTime::Now() - capture_start_time).Milliseconds()); callback_->OnCaptureCompleted(frame); + + // Check for cursor shape update. + if (mouse_shape_observer_) + CaptureCursor(); +} + +void ScreenCapturerWinGdi::SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) { + assert(!mouse_shape_observer_); + assert(mouse_shape_observer); + + mouse_shape_observer_ = mouse_shape_observer; } bool ScreenCapturerWinGdi::GetScreenList(ScreenList* screens) { @@ -266,4 +279,48 @@ bool ScreenCapturerWinGdi::CaptureImage() { return true; } +void ScreenCapturerWinGdi::CaptureCursor() { + assert(mouse_shape_observer_); + + CURSORINFO cursor_info; + cursor_info.cbSize = sizeof(CURSORINFO); + if (!GetCursorInfo(&cursor_info)) { + LOG_F(LS_ERROR) << "Unable to get cursor info. Error = " << GetLastError(); + return; + } + + // Note that |cursor_info.hCursor| does not need to be freed. + scoped_ptr cursor_image( + CreateMouseCursorFromHCursor(desktop_dc_, cursor_info.hCursor)); + if (!cursor_image.get()) + return; + + scoped_ptr cursor(new MouseCursorShape); + cursor->hotspot = cursor_image->hotspot(); + cursor->size = cursor_image->image()->size(); + uint8_t* current_row = cursor_image->image()->data(); + for (int y = 0; y < cursor_image->image()->size().height(); ++y) { + cursor->data.append(current_row, + current_row + cursor_image->image()->size().width() * + DesktopFrame::kBytesPerPixel); + current_row += cursor_image->image()->stride(); + } + + // Compare the current cursor with the last one we sent to the client. If + // they're the same, then don't bother sending the cursor again. + if (last_cursor_.size.equals(cursor->size) && + last_cursor_.hotspot.equals(cursor->hotspot) && + last_cursor_.data == cursor->data) { + return; + } + + LOG(LS_VERBOSE) << "Sending updated cursor: " << cursor->size.width() << "x" + << cursor->size.height(); + + // Record the last cursor image that we sent to the client. + last_cursor_ = *cursor; + + mouse_shape_observer_->OnCursorShapeChanged(cursor.release()); +} + } // namespace webrtc diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h b/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h index 2d48182f7d..2db87d097c 100644 --- a/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h @@ -15,6 +15,7 @@ #include +#include "webrtc/modules/desktop_capture/mouse_cursor_shape.h" #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" #include "webrtc/modules/desktop_capture/win/scoped_thread_desktop.h" @@ -23,6 +24,7 @@ namespace webrtc { class Differ; +class MouseShapeObserver; // ScreenCapturerWinGdi captures 32bit RGB using GDI. // @@ -35,6 +37,8 @@ class ScreenCapturerWinGdi : public ScreenCapturer { // Overridden from ScreenCapturer: virtual void Start(Callback* callback) OVERRIDE; virtual void Capture(const DesktopRegion& region) OVERRIDE; + virtual void SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) OVERRIDE; virtual bool GetScreenList(ScreenList* screens) OVERRIDE; virtual bool SelectScreen(ScreenId id) OVERRIDE; @@ -52,6 +56,7 @@ class ScreenCapturerWinGdi : public ScreenCapturer { void CaptureCursor(); Callback* callback_; + MouseShapeObserver* mouse_shape_observer_; ScreenId current_screen_id_; std::wstring current_device_key_; @@ -59,6 +64,11 @@ class ScreenCapturerWinGdi : public ScreenCapturer { // recently captured screen. ScreenCapturerHelper helper_; + // Snapshot of the last cursor bitmap we sent to the client. This is used + // to diff against the current cursor so we only send a cursor-change + // message when the shape has changed. + MouseCursorShape last_cursor_; + ScopedThreadDesktop desktop_; // GDI resources used for screen capture. diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.cc b/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.cc index e0c91997af..042cb937ac 100644 --- a/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.cc +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.cc @@ -166,6 +166,11 @@ void ScreenCapturerWinMagnifier::Capture(const DesktopRegion& region) { callback_->OnCaptureCompleted(frame); } +void ScreenCapturerWinMagnifier::SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) { + assert(false); // NOTREACHED(); +} + bool ScreenCapturerWinMagnifier::GetScreenList(ScreenList* screens) { return webrtc::GetScreenList(screens); } diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h b/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h index 11278dd50d..b6d559083e 100644 --- a/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h @@ -28,6 +28,7 @@ namespace webrtc { class DesktopFrame; class DesktopRect; class Differ; +class MouseShapeObserver; // Captures the screen using the Magnification API to support window exclusion. // Each capturer must run on a dedicated thread because it uses thread local @@ -45,6 +46,8 @@ class ScreenCapturerWinMagnifier : public ScreenCapturer { // Overridden from ScreenCapturer: virtual void Start(Callback* callback) OVERRIDE; virtual void Capture(const DesktopRegion& region) OVERRIDE; + virtual void SetMouseShapeObserver( + MouseShapeObserver* mouse_shape_observer) OVERRIDE; virtual bool GetScreenList(ScreenList* screens) OVERRIDE; virtual bool SelectScreen(ScreenId id) OVERRIDE; virtual void SetExcludedWindow(WindowId window) OVERRIDE;