| Index: webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm
|
| diff --git a/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm b/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm
|
| index 73d5e028577225796cd38e35e580810cac02ba8b..af63bfdbb4f418baf65382877b40278f7f73ceda 100644
|
| --- a/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm
|
| +++ b/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm
|
| @@ -30,21 +30,26 @@
|
| namespace webrtc {
|
|
|
| namespace {
|
| -// Paint the image, so that we can get a bitmap representation compatible with
|
| -// current context. For example, in the retina display, we are going to get an
|
| -// image with same visual size but underlying pixel size conforms to the retina
|
| -// setting.
|
| -NSImage* PaintInCurrentContext(NSImage* source) {
|
| - NSSize size = [source size];
|
| - NSImage* new_image = [[NSImage alloc] initWithSize:size];
|
| - [new_image lockFocus];
|
| - NSRect frame = NSMakeRect(0, 0, size.width, size.height);
|
| - [source drawInRect:frame
|
| - fromRect:frame
|
| - operation:NSCompositeCopy
|
| - fraction:1.0];
|
| - [new_image unlockFocus];
|
| - return new_image;
|
| +CGImageRef CreateScaledCGImage(CGImageRef image, int width, int height) {
|
| + // Create context, keeping original image properties.
|
| + CGColorSpaceRef colorspace = CGImageGetColorSpace(image);
|
| + CGContextRef context = CGBitmapContextCreate(nullptr,
|
| + width,
|
| + height,
|
| + CGImageGetBitsPerComponent(image),
|
| + width * DesktopFrame::kBytesPerPixel,
|
| + colorspace,
|
| + CGImageGetBitmapInfo(image));
|
| +
|
| + if (!context) return nil;
|
| +
|
| + // Draw image to context, resizing it.
|
| + CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
|
| + // Extract resulting image from context.
|
| + CGImageRef imgRef = CGBitmapContextCreateImage(context);
|
| + CGContextRelease(context);
|
| +
|
| + return imgRef;
|
| }
|
| } // namespace
|
|
|
| @@ -72,7 +77,7 @@ class MouseCursorMonitorMac : public MouseCursorMonitor {
|
| ScreenId screen_id_;
|
| Callback* callback_;
|
| Mode mode_;
|
| - std::unique_ptr<MouseCursor> last_cursor_;
|
| + __strong NSImage* last_cursor_;
|
| rtc::scoped_refptr<FullScreenChromeWindowDetector>
|
| full_screen_chrome_window_detector_;
|
| };
|
| @@ -253,10 +258,9 @@ void MouseCursorMonitorMac::CaptureImage(float scale) {
|
| NSImage* nsimage = [nscursor image];
|
| NSSize nssize = [nsimage size]; // DIP size
|
|
|
| - // For retina screen, we need to paint the cursor in current graphic context
|
| - // to get retina representation.
|
| - if (scale != 1.0)
|
| - nsimage = PaintInCurrentContext(nsimage);
|
| + // No need to caputre cursor image if it's unchanged since last capture.
|
| + if ([[nsimage TIFFRepresentation] isEqual:[last_cursor_ TIFFRepresentation]]) return;
|
| + last_cursor_ = nsimage;
|
|
|
| DesktopSize size(round(nssize.width * scale),
|
| round(nssize.height * scale)); // Pixel size
|
| @@ -271,30 +275,33 @@ void MouseCursorMonitorMac::CaptureImage(float scale) {
|
| if (!cg_image)
|
| return;
|
|
|
| + // Before 10.12, OSX may report 1X cursor on Retina screen. (See
|
| + // crbug.com/632995.) After 10.12, OSX may report 2X cursor on non-Retina
|
| + // screen. (See crbug.com/671436.) So scaling the cursor if needed.
|
| + CGImageRef scaled_cg_image = nil;
|
| + if (CGImageGetWidth(cg_image) != static_cast<size_t>(size.width())) {
|
| + scaled_cg_image = CreateScaledCGImage(cg_image, size.width(), size.height());
|
| + if (scaled_cg_image != nil) {
|
| + cg_image = scaled_cg_image;
|
| + }
|
| + }
|
| if (CGImageGetBitsPerPixel(cg_image) != DesktopFrame::kBytesPerPixel * 8 ||
|
| CGImageGetWidth(cg_image) != static_cast<size_t>(size.width()) ||
|
| CGImageGetBitsPerComponent(cg_image) != 8) {
|
| + if (scaled_cg_image != nil) CGImageRelease(scaled_cg_image);
|
| return;
|
| }
|
|
|
| CGDataProviderRef provider = CGImageGetDataProvider(cg_image);
|
| CFDataRef image_data_ref = CGDataProviderCopyData(provider);
|
| - if (image_data_ref == NULL)
|
| + if (image_data_ref == NULL) {
|
| + if (scaled_cg_image != nil) CGImageRelease(scaled_cg_image);
|
| return;
|
| + }
|
|
|
| const uint8_t* src_data =
|
| reinterpret_cast<const uint8_t*>(CFDataGetBytePtr(image_data_ref));
|
|
|
| - // Compare the cursor with the previous one.
|
| - if (last_cursor_.get() &&
|
| - last_cursor_->image()->size().equals(size) &&
|
| - last_cursor_->hotspot().equals(hotspot) &&
|
| - memcmp(last_cursor_->image()->data(), src_data,
|
| - last_cursor_->image()->stride() * size.height()) == 0) {
|
| - CFRelease(image_data_ref);
|
| - return;
|
| - }
|
| -
|
| // Create a MouseCursor that describes the cursor and pass it to
|
| // the client.
|
| std::unique_ptr<DesktopFrame> image(
|
| @@ -304,10 +311,10 @@ void MouseCursorMonitorMac::CaptureImage(float scale) {
|
| image->CopyPixelsFrom(src_data, src_stride, DesktopRect::MakeSize(size));
|
|
|
| CFRelease(image_data_ref);
|
| + if (scaled_cg_image != nil) CGImageRelease(scaled_cg_image);
|
|
|
| std::unique_ptr<MouseCursor> cursor(
|
| new MouseCursor(image.release(), hotspot));
|
| - last_cursor_.reset(MouseCursor::CopyOf(*cursor));
|
|
|
| callback_->OnMouseCursor(cursor.release());
|
| }
|
|
|