Chromium Code Reviews| 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..18687cfa434e063dff64f77f035a198869192c8f 100644 |
| --- a/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm |
| +++ b/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm |
| @@ -30,21 +30,27 @@ |
| 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(NULL, |
| + width, |
| + height, |
| + CGImageGetBitsPerComponent(image), |
| + width * 4, |
| + colorspace, |
| + CGImageGetBitmapInfo(image)); |
| + |
| + if (context == NULL) 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 +78,7 @@ class MouseCursorMonitorMac : public MouseCursorMonitor { |
| ScreenId screen_id_; |
| Callback* callback_; |
| Mode mode_; |
| - std::unique_ptr<MouseCursor> last_cursor_; |
| + NSImage* last_cursor_; |
| rtc::scoped_refptr<FullScreenChromeWindowDetector> |
| full_screen_chrome_window_detector_; |
| }; |
| @@ -253,10 +259,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); |
| + if([[nsimage TIFFRepresentation] isEqual: [last_cursor_ TIFFRepresentation]]) |
| + return; |
| + last_cursor_ = nsimage; |
|
erikchen
2017/05/30 22:34:31
You need to retain last_cursor_, and also release
erikchen
2017/05/30 23:18:27
ah, this is arc code. You should modify line 81 to
braveyao1
2017/05/31 22:55:05
Done.
Really good to know!
|
| DesktopSize size(round(nssize.width * scale), |
| round(nssize.height * scale)); // Pixel size |
| @@ -271,6 +276,17 @@ 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()); |
|
erikchen
2017/05/30 22:34:31
every early return e.g. 293, 299, etc. needs to re
braveyao1
2017/05/31 22:55:05
Done.
Sorry for forgetting these.
|
| + 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) { |
| @@ -285,16 +301,6 @@ void MouseCursorMonitorMac::CaptureImage(float scale) { |
| 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 +310,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()); |
| } |
| @@ -317,10 +323,11 @@ MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( |
| return new MouseCursorMonitorMac(options, window, kInvalidScreenId); |
| } |
| +// ScreenCapture already contains current cursor in the captured frame on OSX. |
| MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( |
| const DesktopCaptureOptions& options, |
| ScreenId screen) { |
| - return new MouseCursorMonitorMac(options, kCGNullWindowID, screen); |
| + return nil; |
| } |
| } // namespace webrtc |