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..6e079b6662f262c9a1eb90e6f0a74f78c5de7cd3 100644 |
--- a/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm |
+++ b/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm |
@@ -30,6 +30,25 @@ |
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] autorelease]; |
+ [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; |
+} |
+} // namespace |
+ |
class MouseCursorMonitorMac : public MouseCursorMonitor { |
public: |
MouseCursorMonitorMac(const DesktopCaptureOptions& options, |
@@ -47,7 +66,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 +110,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 +127,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 +248,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); |
+ |
+ 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 +300,9 @@ 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); |
+ image->CopyPixelsFrom(src_data, src_stride, DesktopRect::MakeSize(size)); |
CFRelease(image_data_ref); |