From 1af5ea05384e2bebc0a1ae6fc57e8789778b8ef4 Mon Sep 17 00:00:00 2001 From: "jiayl@webrtc.org" Date: Sat, 1 Feb 2014 02:03:24 +0000 Subject: [PATCH] Implement single monitor capture on Mac. BUG=2787, 2824 TESTED=MacBook Pro Retina with an external monitor; verified changing display configuration while capturing; add/remove monitor while capturing; verified cursor position. R=sergeyu@chromium.org Review URL: https://webrtc-codereview.appspot.com/7479004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5471 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../desktop_capture/desktop_capture.gypi | 2 + .../desktop_capture/desktop_capture_types.h | 6 +- .../mac/desktop_configuration.h | 4 + .../mac/desktop_configuration.mm | 34 ++- .../desktop_capture/mac/osx_version.cc | 54 +++++ .../modules/desktop_capture/mac/osx_version.h | 16 ++ .../mouse_cursor_monitor_mac.mm | 81 ++++++-- .../desktop_capture/screen_capturer_mac.mm | 194 +++++++++++------- 8 files changed, 284 insertions(+), 107 deletions(-) create mode 100644 webrtc/modules/desktop_capture/mac/osx_version.cc create mode 100644 webrtc/modules/desktop_capture/mac/osx_version.h diff --git a/webrtc/modules/desktop_capture/desktop_capture.gypi b/webrtc/modules/desktop_capture/desktop_capture.gypi index 7834d21dc8..9463257ce9 100644 --- a/webrtc/modules/desktop_capture/desktop_capture.gypi +++ b/webrtc/modules/desktop_capture/desktop_capture.gypi @@ -38,6 +38,8 @@ "mac/desktop_configuration.mm", "mac/desktop_configuration_monitor.h", "mac/desktop_configuration_monitor.cc", + "mac/osx_version.h", + "mac/osx_version.cc", "mac/scoped_pixel_buffer_object.cc", "mac/scoped_pixel_buffer_object.h", "mouse_cursor.cc", diff --git a/webrtc/modules/desktop_capture/desktop_capture_types.h b/webrtc/modules/desktop_capture/desktop_capture_types.h index 0ad199cc61..3e41796553 100644 --- a/webrtc/modules/desktop_capture/desktop_capture_types.h +++ b/webrtc/modules/desktop_capture/desktop_capture_types.h @@ -26,7 +26,11 @@ typedef intptr_t WindowId; const WindowId kNullWindowId = 0; -typedef int ScreenId; +// Type used to identify screens on the desktop. Values are platform-specific: +// - On Windows: integer display device index. +// - On OSX: CGDirectDisplayID cast to intptr_t. +// - On Linux (with X11): TBD. +typedef intptr_t ScreenId; // The screen id corresponds to all screen combined together. const ScreenId kFullDesktopScreenId = -1; diff --git a/webrtc/modules/desktop_capture/mac/desktop_configuration.h b/webrtc/modules/desktop_capture/mac/desktop_configuration.h index 80a155d8a9..031d92de2a 100644 --- a/webrtc/modules/desktop_capture/mac/desktop_configuration.h +++ b/webrtc/modules/desktop_capture/mac/desktop_configuration.h @@ -55,6 +55,10 @@ struct MacDesktopConfiguration { // Returns true if the given desktop configuration equals this one. bool Equals(const MacDesktopConfiguration& other); + // Returns the pointer to the display configuration with the specified id. + const MacDisplayConfiguration* FindDisplayConfigurationById( + CGDirectDisplayID id); + // Bounds of the desktop in Density-Independent Pixels (DIPs). DesktopRect bounds; diff --git a/webrtc/modules/desktop_capture/mac/desktop_configuration.mm b/webrtc/modules/desktop_capture/mac/desktop_configuration.mm index 5dac409ca8..838973e42b 100644 --- a/webrtc/modules/desktop_capture/mac/desktop_configuration.mm +++ b/webrtc/modules/desktop_capture/mac/desktop_configuration.mm @@ -110,15 +110,8 @@ MacDesktopConfiguration MacDesktopConfiguration::GetCurrent(Origin origin) { MacDisplayConfiguration display_config = GetConfigurationForScreen([screens objectAtIndex: i]); - // Handling mixed-DPI is hard, so we only return displays that match the - // "primary" display's DPI. The primary display is always the first in the - // list returned by [NSScreen screens]. - if (i == 0) { + if (i == 0) desktop_config.dip_to_pixel_scale = display_config.dip_to_pixel_scale; - } else if (desktop_config.dip_to_pixel_scale != - display_config.dip_to_pixel_scale) { - continue; - } // Cocoa uses bottom-up coordinates, so if the caller wants top-down then // we need to invert the positions of secondary monitors relative to the @@ -126,8 +119,16 @@ MacDesktopConfiguration MacDesktopConfiguration::GetCurrent(Origin origin) { if (i > 0 && origin == TopLeftOrigin) { InvertRectYOrigin(desktop_config.displays[0].bounds, &display_config.bounds); - InvertRectYOrigin(desktop_config.displays[0].pixel_bounds, - &display_config.pixel_bounds); + // |display_bounds| is density dependent, so we need to convert the + // primay monitor's position into the secondary monitor's density context. + float scaling_factor = display_config.dip_to_pixel_scale / + desktop_config.displays[0].dip_to_pixel_scale; + DesktopRect primary_bounds = DesktopRect::MakeLTRB( + desktop_config.displays[0].pixel_bounds.left() * scaling_factor, + desktop_config.displays[0].pixel_bounds.top() * scaling_factor, + desktop_config.displays[0].pixel_bounds.right() * scaling_factor, + desktop_config.displays[0].pixel_bounds.bottom() * scaling_factor); + InvertRectYOrigin(primary_bounds, &display_config.pixel_bounds); } // Add the display to the configuration. @@ -143,7 +144,6 @@ MacDesktopConfiguration MacDesktopConfiguration::GetCurrent(Origin origin) { return desktop_config; } - // For convenience of comparing MacDisplayConfigurations in // MacDesktopConfiguration::Equals. bool operator==(const MacDisplayConfiguration& left, @@ -161,4 +161,16 @@ bool MacDesktopConfiguration::Equals(const MacDesktopConfiguration& other) { displays == other.displays; } +// Finds the display configuration with the specified id. +const MacDisplayConfiguration* +MacDesktopConfiguration::FindDisplayConfigurationById( + CGDirectDisplayID id) { + for (MacDisplayConfigurations::const_iterator it = displays.begin(); + it != displays.end(); ++it) { + if (it->id == id) + return &(*it); + } + return NULL; +} + } // namespace webrtc diff --git a/webrtc/modules/desktop_capture/mac/osx_version.cc b/webrtc/modules/desktop_capture/mac/osx_version.cc new file mode 100644 index 0000000000..7466f20342 --- /dev/null +++ b/webrtc/modules/desktop_capture/mac/osx_version.cc @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014 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. + */ + +#include + +#include "webrtc/system_wrappers/interface/logging.h" + +namespace webrtc { + +namespace { + +int GetDarwinVersion() { + struct utsname uname_info; + if (uname(&uname_info) != 0) { + LOG(LS_ERROR) << "uname failed"; + return 0; + } + + if (strcmp(uname_info.sysname, "Darwin") != 0) + return 0; + + char* dot; + int result = strtol(uname_info.release, &dot, 10); + if (*dot != '.') { + LOG(LS_ERROR) << "Failed to parse version"; + return 0; + } + + return result; +} + +} // namespace + +bool IsOSLionOrLater() { + static int darwin_version = GetDarwinVersion(); + + // Verify that the version has been parsed correctly. + if (darwin_version < 6) { + LOG_F(LS_ERROR) << "Invalid Darwin version: " << darwin_version; + abort(); + } + + // Darwin major version 11 corresponds to OSX 10.7. + return darwin_version >= 11; +} + +} // namespace webrtc diff --git a/webrtc/modules/desktop_capture/mac/osx_version.h b/webrtc/modules/desktop_capture/mac/osx_version.h new file mode 100644 index 0000000000..0ba49a4e69 --- /dev/null +++ b/webrtc/modules/desktop_capture/mac/osx_version.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2014 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. + */ + +namespace webrtc { + +// Returns true if the OS version >= OSX 10.7. +bool IsOSLionOrLater(); + +} // namespace webrtc diff --git a/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm b/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm index 25d7e7aaa6..e880633819 100644 --- a/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm +++ b/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm @@ -17,8 +17,11 @@ #include "webrtc/modules/desktop_capture/desktop_capture_options.h" #include "webrtc/modules/desktop_capture/desktop_frame.h" +#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/osx_version.h" #include "webrtc/modules/desktop_capture/mouse_cursor.h" +#include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/scoped_refptr.h" @@ -27,31 +30,44 @@ namespace webrtc { class MouseCursorMonitorMac : public MouseCursorMonitor { public: MouseCursorMonitorMac(const DesktopCaptureOptions& options, - CGWindowID window_id); + CGWindowID window_id, + ScreenId screen_id); virtual ~MouseCursorMonitorMac(); virtual void Init(Callback* callback, Mode mode) OVERRIDE; virtual void Capture() OVERRIDE; private: + static void DisplaysReconfiguredCallback(CGDirectDisplayID display, + CGDisplayChangeSummaryFlags flags, + void *user_parameter); + void DisplaysReconfigured(CGDirectDisplayID display, + CGDisplayChangeSummaryFlags flags); + void CaptureImage(); scoped_refptr configuration_monitor_; CGWindowID window_id_; - + ScreenId screen_id_; Callback* callback_; Mode mode_; - scoped_ptr last_cursor_; }; MouseCursorMonitorMac::MouseCursorMonitorMac( const DesktopCaptureOptions& options, - CGWindowID window_id) + CGWindowID window_id, + ScreenId screen_id) : configuration_monitor_(options.configuration_monitor()), window_id_(window_id), + screen_id_(screen_id), callback_(NULL), mode_(SHAPE_AND_POSITION) { + assert(window_id == kCGNullWindowID || screen_id == kInvalidScreenId); + if (screen_id != kInvalidScreenId && !IsOSLionOrLater()) { + // Single screen capture is not supported on pre OS X 10.7. + screen_id_ = kFullDesktopScreenId; + } } MouseCursorMonitorMac::~MouseCursorMonitorMac() {} @@ -80,6 +96,21 @@ void MouseCursorMonitorMac::Capture() { DesktopVector position(gc_position.x, gc_position.y); + configuration_monitor_->Lock(); + MacDesktopConfiguration configuration = + configuration_monitor_->desktop_configuration(); + configuration_monitor_->Unlock(); + float scale = 1.0f; + + // Find the dpi to physical pixel scale for the screen where the mouse cursor + // is. + for (MacDisplayConfigurations::iterator it = configuration.displays.begin(); + it != configuration.displays.end(); ++it) { + if (it->bounds.Contains(position)) { + scale = it->dip_to_pixel_scale; + break; + } + } // If we are capturing cursor for a specific window then we need to figure out // if the current mouse position is covered by another window and also adjust // |position| to make it relative to the window origin. @@ -142,10 +173,8 @@ void MouseCursorMonitorMac::Capture() { } } } - CFRelease(window_array); } - if (!found_window) { // If we failed to get list of windows or the window wasn't in the list // pretend that the cursor is outside the window. This can happen, e.g. if @@ -153,17 +182,32 @@ void MouseCursorMonitorMac::Capture() { state = OUTSIDE; position.set(-1, -1); } + } else { + assert(screen_id_ >= kFullDesktopScreenId); + if (screen_id_ != kFullDesktopScreenId) { + // For single screen capturing, convert the position to relative to the + // target screen. + const MacDisplayConfiguration* config = + configuration.FindDisplayConfigurationById( + static_cast(screen_id_)); + if (config) { + if (!config->pixel_bounds.Contains(position)) + state = OUTSIDE; + position = position.subtract(config->bounds.top_left()); + } else { + // The target screen is no longer valid. + state = OUTSIDE; + position.set(-1, -1); + } + } else { + position.subtract(configuration.bounds.top_left()); + } + } + if (state == INSIDE) { + // Convert Density Independent Pixel to physical pixel. + position = DesktopVector(round(position.x() * scale), + round(position.y() * scale)); } - - // Convert Density Independent Pixel to physical pixel. - configuration_monitor_->Lock(); - float scale = - configuration_monitor_->desktop_configuration().dip_to_pixel_scale; - configuration_monitor_->Unlock(); - - position = DesktopVector(round(position.x() * scale), - round(position.y() * scale)); - callback_->OnMouseCursorPosition(state, position); } @@ -221,16 +265,15 @@ void MouseCursorMonitorMac::CaptureImage() { callback_->OnMouseCursor(cursor.release()); } - MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( const DesktopCaptureOptions& options, WindowId window) { - return new MouseCursorMonitorMac(options, window); + return new MouseCursorMonitorMac(options, window, kInvalidScreenId); } MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( const DesktopCaptureOptions& options, ScreenId screen) { - return new MouseCursorMonitorMac(options, kCGNullWindowID); + return new MouseCursorMonitorMac(options, kCGNullWindowID, screen); } } // namespace webrtc diff --git a/webrtc/modules/desktop_capture/screen_capturer_mac.mm b/webrtc/modules/desktop_capture/screen_capturer_mac.mm index 46118dd722..100309f896 100644 --- a/webrtc/modules/desktop_capture/screen_capturer_mac.mm +++ b/webrtc/modules/desktop_capture/screen_capturer_mac.mm @@ -19,7 +19,6 @@ #include #include #include -#include #include "webrtc/modules/desktop_capture/desktop_capture_options.h" #include "webrtc/modules/desktop_capture/desktop_frame.h" @@ -27,6 +26,7 @@ #include "webrtc/modules/desktop_capture/desktop_region.h" #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/osx_version.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" @@ -87,39 +87,6 @@ void CopyRect(const uint8_t* src_plane, } } -int GetDarwinVersion() { - struct utsname uname_info; - if (uname(&uname_info) != 0) { - LOG(LS_ERROR) << "uname failed"; - return 0; - } - - if (strcmp(uname_info.sysname, "Darwin") != 0) - return 0; - - char* dot; - int result = strtol(uname_info.release, &dot, 10); - if (*dot != '.') { - LOG(LS_ERROR) << "Failed to parse version"; - return 0; - } - - return result; -} - -bool IsOSLionOrLater() { - static int darwin_version = GetDarwinVersion(); - - // Verify that the version has been parsed correctly. - if (darwin_version < 6) { - LOG_F(LS_ERROR) << "Invalid Darwin version: " << darwin_version; - abort(); - } - - // Darwin major version 11 corresponds to OSX 10.7. - return darwin_version >= 11; -} - // A class to perform video frame capturing for mac. class ScreenCapturerMac : public ScreenCapturer { public: @@ -145,7 +112,8 @@ class ScreenCapturerMac : public ScreenCapturer { void GlBlitSlow(const DesktopFrame& frame); void CgBlitPreLion(const DesktopFrame& frame, const DesktopRegion& region); - void CgBlitPostLion(const DesktopFrame& frame, + // Returns false if the selected screen is no longer valid. + bool CgBlitPostLion(const DesktopFrame& frame, const DesktopRegion& region); // Called when the screen configuration is changed. @@ -167,6 +135,8 @@ class ScreenCapturerMac : public ScreenCapturer { void *user_parameter); void ReleaseBuffers(); + DesktopFrame* CreateFrame(); + Callback* callback_; MouseShapeObserver* mouse_shape_observer_; @@ -176,6 +146,19 @@ class ScreenCapturerMac : public ScreenCapturer { // Queue of the frames buffers. ScreenCaptureFrameQueue queue_; + // Current display configuration. + MacDesktopConfiguration desktop_config_; + + // Currently selected display, or 0 if the full desktop is selected. On OS X + // 10.6 and before, this is always 0. + CGDirectDisplayID current_display_; + + // The physical pixel bounds of the current screen. + DesktopRect screen_pixel_bounds_; + + // The dip to physical pixel scale of the current screen. + float dip_to_pixel_scale_; + // A thread-safe list of invalid rectangles, and the size of the most // recently captured screen. ScreenCapturerHelper helper_; @@ -189,10 +172,6 @@ class ScreenCapturerMac : public ScreenCapturer { // Monitoring display reconfiguration. scoped_refptr desktop_config_monitor_; - // The desktop configuration obtained from desktop_config_monitor_ the last - // time of capturing. - MacDesktopConfiguration desktop_config_; - // Power management assertion to prevent the screen from sleeping. IOPMAssertionID power_assertion_id_display_; @@ -233,24 +212,13 @@ class InvertedDesktopFrame : public DesktopFrame { DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame); }; -DesktopFrame* CreateFrame( - const MacDesktopConfiguration& desktop_config) { - - DesktopSize size(desktop_config.pixel_bounds.width(), - desktop_config.pixel_bounds.height()); - scoped_ptr frame(new BasicDesktopFrame(size)); - - frame->set_dpi(DesktopVector( - kStandardDPI * desktop_config.dip_to_pixel_scale, - kStandardDPI * desktop_config.dip_to_pixel_scale)); - return frame.release(); -} - 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), desktop_config_monitor_(desktop_config_monitor), power_assertion_id_display_(kIOPMNullAssertionID), power_assertion_id_user_(kIOPMNullAssertionID), @@ -282,6 +250,9 @@ bool ScreenCapturerMac::Init() { if (!RegisterRefreshAndMoveHandlers()) { return false; } + desktop_config_monitor_->Lock(); + desktop_config_ = desktop_config_monitor_->desktop_configuration(); + desktop_config_monitor_->Unlock(); ScreenConfigurationChanged(); return true; } @@ -346,7 +317,7 @@ void ScreenCapturerMac::Capture( // Note that we can't reallocate other buffers at this point, since the caller // may still be reading from them. if (!queue_.current_frame()) - queue_.ReplaceCurrentFrame(CreateFrame(desktop_config_)); + queue_.ReplaceCurrentFrame(CreateFrame()); DesktopFrame* current_frame = queue_.current_frame(); @@ -354,7 +325,10 @@ void ScreenCapturerMac::Capture( if (IsOSLionOrLater()) { // Lion requires us to use their new APIs for doing screen capture. These // APIS currently crash on 10.6.8 if there is no monitor attached. - CgBlitPostLion(*current_frame, region); + if (!CgBlitPostLion(*current_frame, region)) { + callback_->OnCaptureCompleted(NULL); + return; + } } else if (cgl_context_) { flip = true; if (pixel_buffer_object_.get() != 0) { @@ -397,15 +371,42 @@ void ScreenCapturerMac::SetMouseShapeObserver( bool ScreenCapturerMac::GetScreenList(ScreenList* screens) { assert(screens->size() == 0); - // TODO(jiayl): implement screen enumeration. - Screen default_screen; - default_screen.id = 0; - screens->push_back(default_screen); + if (!IsOSLionOrLater()) { + // Single monitor cast is not supported on pre OS X 10.7. + Screen screen; + screen.id = kFullDesktopScreenId; + screens->push_back(screen); + return true; + } + + for (MacDisplayConfigurations::iterator it = desktop_config_.displays.begin(); + it != desktop_config_.displays.end(); ++it) { + Screen screen; + screen.id = static_cast(it->id); + screens->push_back(screen); + } return true; } bool ScreenCapturerMac::SelectScreen(ScreenId id) { - // TODO(jiayl): implement screen selection. + if (!IsOSLionOrLater()) { + // Ignore the screen selection on unsupported OS. + assert(!current_display_); + return id == kFullDesktopScreenId; + } + + if (id == kFullDesktopScreenId) { + current_display_ = 0; + } else { + const MacDisplayConfiguration* config = + desktop_config_.FindDisplayConfigurationById( + static_cast(id)); + if (!config) + return false; + current_display_ = config->id; + } + + ScreenConfigurationChanged(); return true; } @@ -602,7 +603,7 @@ void ScreenCapturerMac::CgBlitPreLion(const DesktopFrame& frame, } } -void ScreenCapturerMac::CgBlitPostLion(const DesktopFrame& frame, +bool ScreenCapturerMac::CgBlitPostLion(const DesktopFrame& frame, const DesktopRegion& region) { // Copy the entire contents of the previous capture buffer, to capture over. // TODO(wez): Get rid of this as per crbug.com/145064, or implement @@ -613,13 +614,37 @@ void ScreenCapturerMac::CgBlitPostLion(const DesktopFrame& frame, frame.stride() * frame.size().height()); } - for (size_t i = 0; i < desktop_config_.displays.size(); ++i) { - const MacDisplayConfiguration& display_config = desktop_config_.displays[i]; + MacDisplayConfigurations displays_to_capture; + if (current_display_) { + // Capturing a single screen. Note that the screen id may change when + // screens are added or removed. + const MacDisplayConfiguration* config = + desktop_config_.FindDisplayConfigurationById(current_display_); + if (config) { + displays_to_capture.push_back(*config); + } else { + LOG(LS_ERROR) << "The selected screen cannot be found for capturing."; + return false; + } + } else { + // Capturing the whole desktop. + displays_to_capture = desktop_config_.displays; + } + for (size_t i = 0; i < displays_to_capture.size(); ++i) { + const MacDisplayConfiguration& display_config = displays_to_capture[i]; + + // Capturing mixed-DPI on one surface is hard, so we only return displays + // that match the "primary" display's DPI. The primary display is always + // the first in the list. + if (i > 0 && display_config.dip_to_pixel_scale != + displays_to_capture[0].dip_to_pixel_scale) { + continue; + } // Determine the display's position relative to the desktop, in pixels. DesktopRect display_bounds = display_config.pixel_bounds; - display_bounds.Translate(-desktop_config_.pixel_bounds.left(), - -desktop_config_.pixel_bounds.top()); + display_bounds.Translate(-screen_pixel_bounds_.left(), + -screen_pixel_bounds_.top()); // Determine which parts of the blit region, if any, lay within the monitor. DesktopRegion copy_region = region; @@ -662,9 +687,20 @@ void ScreenCapturerMac::CgBlitPostLion(const DesktopFrame& frame, CFRelease(data); CFRelease(image); } + return true; } void ScreenCapturerMac::ScreenConfigurationChanged() { + if (current_display_) { + const MacDisplayConfiguration* config = + desktop_config_.FindDisplayConfigurationById(current_display_); + screen_pixel_bounds_ = config ? config->pixel_bounds : DesktopRect(); + dip_to_pixel_scale_ = config ? config->dip_to_pixel_scale : 1.0f; + } else { + screen_pixel_bounds_ = desktop_config_.pixel_bounds; + dip_to_pixel_scale_ = desktop_config_.dip_to_pixel_scale; + } + // Release existing buffers, which will be of the wrong size. ReleaseBuffers(); @@ -672,7 +708,7 @@ void ScreenCapturerMac::ScreenConfigurationChanged() { helper_.ClearInvalidRegion(); // Re-mark the entire desktop as dirty. - helper_.InvalidateScreen(desktop_config_.pixel_bounds.size()); + helper_.InvalidateScreen(screen_pixel_bounds_.size()); // Make sure the frame buffers will be reallocated. queue_.Reset(); @@ -753,8 +789,8 @@ void ScreenCapturerMac::ScreenConfigurationChanged() { (*cgl_set_full_screen_)(cgl_context_); CGLSetCurrentContext(cgl_context_); - size_t buffer_size = desktop_config_.pixel_bounds.width() * - desktop_config_.pixel_bounds.height() * + size_t buffer_size = screen_pixel_bounds_.width() * + screen_pixel_bounds_.height() * sizeof(uint32_t); pixel_buffer_object_.Init(cgl_context_, buffer_size); } @@ -786,20 +822,17 @@ void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() { void ScreenCapturerMac::ScreenRefresh(CGRectCount count, const CGRect* rect_array) { - if (desktop_config_.pixel_bounds.is_empty()) + if (screen_pixel_bounds_.is_empty()) return; DesktopRegion region; - + DesktopVector translate_vector = + DesktopVector().subtract(screen_pixel_bounds_.top_left()); for (CGRectCount i = 0; i < count; ++i) { // Convert from Density-Independent Pixel to physical pixel coordinates. - DesktopRect rect = - ScaleAndRoundCGRect(rect_array[i], desktop_config_.dip_to_pixel_scale); - + DesktopRect rect = ScaleAndRoundCGRect(rect_array[i], dip_to_pixel_scale_); // Translate from local desktop to capturer framebuffer coordinates. - rect.Translate(-desktop_config_.pixel_bounds.left(), - -desktop_config_.pixel_bounds.top()); - + rect.Translate(translate_vector); region.AddRect(rect); } @@ -824,7 +857,7 @@ void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count, void* user_parameter) { ScreenCapturerMac* capturer = reinterpret_cast(user_parameter); - if (capturer->desktop_config_.pixel_bounds.is_empty()) + if (capturer->screen_pixel_bounds_.is_empty()) capturer->ScreenConfigurationChanged(); capturer->ScreenRefresh(count, rect_array); } @@ -839,6 +872,15 @@ void ScreenCapturerMac::ScreenUpdateMoveCallback( capturer->ScreenUpdateMove(delta, count, rect_array); } +DesktopFrame* ScreenCapturerMac::CreateFrame() { + scoped_ptr frame( + new BasicDesktopFrame(screen_pixel_bounds_.size())); + + frame->set_dpi(DesktopVector(kStandardDPI * dip_to_pixel_scale_, + kStandardDPI * dip_to_pixel_scale_)); + return frame.release(); +} + } // namespace // static