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 5d6a9b0089c6ddbff18ce7db4b6083b65eab70ba..e07abdcef2c05b971de83279c0785bd5089bd1a2 100644 |
| --- a/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm |
| +++ b/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm |
| @@ -30,6 +30,21 @@ |
| namespace webrtc { |
| +namespace { |
| +NSImage* PaintInCurrentContext(NSImage* source, NSSize new_size) { |
|
Sergey Ulanov
2016/09/20 22:53:22
Add a comment to explain why we need this function
qiangchen
2016/09/21 16:38:31
Done.
|
| + NSImage* new_image = [[[NSImage alloc] initWithSize:new_size] autorelease]; |
| + [source setSize:new_size]; |
| + [new_image lockFocus]; |
| + NSRect frame = NSMakeRect(0, 0, new_size.width, new_size.height); |
| + [source drawInRect:frame |
| + fromRect:frame |
| + operation:NSCompositeCopy |
| + fraction:1.0]; |
| + [new_image unlockFocus]; |
| + return new_image; |
| +} |
| +} |
|
Sergey Ulanov
2016/09/20 22:53:22
// namespace
qiangchen
2016/09/21 16:38:32
Done.
|
| + |
| class MouseCursorMonitorMac : public MouseCursorMonitor { |
| public: |
| MouseCursorMonitorMac(const DesktopCaptureOptions& options, |
| @@ -47,7 +62,7 @@ class MouseCursorMonitorMac : public MouseCursorMonitor { |
| void DisplaysReconfigured(CGDirectDisplayID display, |
| CGDisplayChangeSummaryFlags flags); |
| - void CaptureImage(); |
| + void CaptureImage(float scale); |
| rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_; |
| CGWindowID window_id_; |
| @@ -91,11 +106,6 @@ void MouseCursorMonitorMac::Init(Callback* callback, Mode mode) { |
| void MouseCursorMonitorMac::Capture() { |
| assert(callback_); |
| - CaptureImage(); |
| - |
| - if (mode_ != SHAPE_AND_POSITION) |
| - return; |
| - |
| CursorState state = INSIDE; |
| CGEventRef event = CGEventCreate(NULL); |
| @@ -113,12 +123,18 @@ void MouseCursorMonitorMac::Capture() { |
| // 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) { |
| + it != configuration.displays.end(); ++it) { |
| if (it->bounds.Contains(position)) { |
| scale = it->dip_to_pixel_scale; |
| break; |
| } |
| } |
| + |
| + CaptureImage(scale); |
| + |
| + if (mode_ != SHAPE_AND_POSITION) |
| + return; |
| + |
| // 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. |
| @@ -228,24 +244,32 @@ void MouseCursorMonitorMac::Capture() { |
| callback_->OnMouseCursorPosition(state, position); |
| } |
| -void MouseCursorMonitorMac::CaptureImage() { |
| +void MouseCursorMonitorMac::CaptureImage(float scale) { |
| NSCursor* nscursor = [NSCursor currentSystemCursor]; |
| NSImage* nsimage = [nscursor image]; |
| - NSSize nssize = [nsimage size]; |
| - DesktopSize size(nssize.width, nssize.height); |
| + 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, nssize); |
|
Sergey Ulanov
2016/09/20 22:53:22
Do we need to nssize here? the function can just c
qiangchen
2016/09/21 16:38:31
Done.
Originally, I thought we need to plug in ns
|
| + |
| + DesktopSize size(round(nssize.width * scale), |
| + round(nssize.height * scale)); // Pixel size |
| NSPoint nshotspot = [nscursor hotSpot]; |
| DesktopVector hotspot( |
| - std::max(0, std::min(size.width(), static_cast<int>(nshotspot.x))), |
| - std::max(0, std::min(size.height(), static_cast<int>(nshotspot.y)))); |
| + std::max(0, |
| + std::min(size.width(), static_cast<int>(nshotspot.x * scale))), |
| + std::max(0, |
| + std::min(size.height(), static_cast<int>(nshotspot.y * scale)))); |
| CGImageRef cg_image = |
| [nsimage CGImageForProposedRect:NULL context:nil hints:nil]; |
| if (!cg_image) |
| return; |
| if (CGImageGetBitsPerPixel(cg_image) != DesktopFrame::kBytesPerPixel * 8 || |
| - CGImageGetBytesPerRow(cg_image) != |
| - static_cast<size_t>(DesktopFrame::kBytesPerPixel * size.width()) || |
| + CGImageGetWidth(cg_image) != static_cast<size_t>(size.width()) || |
| CGImageGetBitsPerComponent(cg_image) != 8) { |
| return; |
| } |
| @@ -272,8 +296,17 @@ void MouseCursorMonitorMac::CaptureImage() { |
| // the client. |
| std::unique_ptr<DesktopFrame> image( |
| new BasicDesktopFrame(DesktopSize(size.width(), size.height()))); |
| - memcpy(image->data(), src_data, |
| - size.width() * size.height() * DesktopFrame::kBytesPerPixel); |
| + |
| + int src_stride = CGImageGetBytesPerRow(cg_image); |
| + int dst_stride = size.width() * DesktopFrame::kBytesPerPixel; |
| + if (src_stride == dst_stride) { |
| + memcpy(image->data(), src_data, size.height() * src_stride); |
| + } else { |
| + for (int y = 0; y < size.height(); y++) { |
|
Sergey Ulanov
2016/09/20 22:53:22
Use CopyPixelsFrom() here?
qiangchen
2016/09/21 16:38:32
Done.
|
| + memcpy(image->data() + y * dst_stride, src_data + y * src_stride, |
| + dst_stride); |
| + } |
| + } |
| CFRelease(image_data_ref); |