| 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);
|
|
|
|
|