Revert "Remove mouse cursor capturer from the ScreenCapturer interface"
This reverts commit 0adc4953512ee0a57cf7f3c0591b024c2316554a. It broke FYI bots TBR=sergeyu@chromium.org Review URL: https://webrtc-codereview.appspot.com/27649004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7364 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
1fced0f2aa
commit
6138f0f89d
@ -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",
|
||||
|
@ -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",
|
||||
|
36
webrtc/modules/desktop_capture/mouse_cursor_shape.h
Normal file
36
webrtc/modules/desktop_capture/mouse_cursor_shape.h
Normal file
@ -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 <string>
|
||||
|
||||
#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_
|
@ -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<Screen> 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;
|
||||
|
@ -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<DesktopConfigurationMonitor> 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<const char*>(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<MouseCursorShape> 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.
|
||||
|
@ -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_
|
||||
|
@ -37,6 +37,7 @@ class ScreenCapturerTest : public testing::Test {
|
||||
|
||||
protected:
|
||||
scoped_ptr<ScreenCapturer> 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())
|
||||
|
@ -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<const XFixesCursorNotifyEvent*>(&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<MouseCursorShape> 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<uint32_t*>(&*(cursor->data.begin()));
|
||||
uint32_t* dst_end = dst + (img->width * img->height);
|
||||
while (dst < dst_end) {
|
||||
*dst++ = static_cast<uint32_t>(*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()));
|
||||
|
@ -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<MouseCursor> cursor_image(
|
||||
CreateMouseCursorFromHCursor(desktop_dc_, cursor_info.hCursor));
|
||||
if (!cursor_image.get())
|
||||
return;
|
||||
|
||||
scoped_ptr<MouseCursorShape> 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
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <windows.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/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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user