Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(897)

Unified Diff: content/browser/media/capture/cursor_renderer_mac.mm

Issue 2553763002: Fix cursor missing in tabCapture on OSX Sierra (Closed)
Patch Set: address comments Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/media/capture/cursor_renderer_mac.mm
diff --git a/content/browser/media/capture/cursor_renderer_mac.mm b/content/browser/media/capture/cursor_renderer_mac.mm
index c7c85f6ea087b229f33fcb3aea86dde3febeafb7..62a00fa33acf0f1e2450c29f71863e94c9b257b4 100644
--- a/content/browser/media/capture/cursor_renderer_mac.mm
+++ b/content/browser/media/capture/cursor_renderer_mac.mm
@@ -4,189 +4,122 @@
#include "content/browser/media/capture/cursor_renderer_mac.h"
-#include <ApplicationServices/ApplicationServices.h>
#include <Cocoa/Cocoa.h>
#include <CoreFoundation/CoreFoundation.h>
-#include <stdint.h>
-
-#include <cmath>
+#include "base/bind.h"
#include "base/logging.h"
+#include "base/mac/mac_util.h"
+#include "base/memory/ptr_util.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "ui/gfx/image/image.h"
+
+@implementation CursorRendererMouseTracker
+
+- (instancetype)initWithView:(NSView*)nsView {
+ if ((self = [super init])) {
+ NSTrackingAreaOptions trackingOptions =
+ NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited |
+ NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect;
+ trackingArea_.reset([[CrTrackingArea alloc] initWithRect:NSZeroRect
+ options:trackingOptions
+ owner:self
+ userInfo:nil]);
+ [nsView addTrackingArea:trackingArea_.get()];
+ capturedView_ = nsView;
+ }
+ return self;
+}
-namespace content {
+- (void)stopTracking {
+ if (trackingArea_.get()) {
+ [capturedView_ removeTrackingArea:trackingArea_.get()];
miu 2017/01/05 01:26:57 It seems possible for |capturedView_| could someti
braveyao 2017/01/05 22:34:49 Done.
+ trackingArea_.reset();
+ }
+}
-namespace {
+- (void)registerMouseInteractionObserver:(const base::Closure&)observer {
+ mouseInteractionObserver_ = observer;
+}
-// RGBA format on cursor bitmap
-const int kBytesPerPixel = 4;
+- (void)mouseMoved:(NSEvent*)theEvent {
+ mouseInteractionObserver_.Run();
+}
-inline int clip_byte(int x) {
- return std::max(0, std::min(x, 255));
+- (void)mouseEntered:(NSEvent*)theEvent {
+ mouseInteractionObserver_.Run();
}
-inline int alpha_blend(int alpha, int src, int dst) {
- return (src * alpha + dst * (255 - alpha)) / 255;
+- (void)mouseExited:(NSEvent*)theEvent {
}
-} // namespace
+@end
+
+namespace content {
// static
std::unique_ptr<CursorRenderer> CursorRenderer::Create(gfx::NativeView view) {
- return std::unique_ptr<CursorRenderer>(new CursorRendererMac(view));
+ return base::MakeUnique<CursorRendererMac>(view);
}
-CursorRendererMac::CursorRendererMac(NSView* view)
- : view_(view), weak_factory_(this) {
- Clear();
+CursorRendererMac::CursorRendererMac(gfx::NativeView view)
+ : CursorRenderer(view, kCursorEnabledOnMouseMovement), view_(view) {
+ mouse_tracker_.reset([[CursorRendererMouseTracker alloc] initWithView:view]);
+ [mouse_tracker_ registerMouseInteractionObserver:
+ base::Bind(&CursorRendererMac::OnMouseEvent, base::Unretained(this))];
}
-CursorRendererMac::~CursorRendererMac() {}
+CursorRendererMac::~CursorRendererMac() {
+ [mouse_tracker_ stopTracking];
+}
-base::WeakPtr<CursorRenderer> CursorRendererMac::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
+bool CursorRendererMac::IsCapturedViewActive() {
+ if (![[view_ window] isKeyWindow]) {
+ return false;
+ }
+ return true;
}
-void CursorRendererMac::Clear() {
- last_cursor_data_.reset();
- last_cursor_width_ = 0;
- last_cursor_height_ = 0;
- last_mouse_location_x_ = 0;
- last_mouse_location_y_ = 0;
- last_mouse_movement_timestamp_ = base::TimeTicks();
+gfx::Size CursorRendererMac::GetCapturedViewSize() {
+ NSRect frame_rect = [view_ bounds];
+ return gfx::Size(frame_rect.size.width, frame_rect.size.height);
}
-// Polls mouse cursor location and image and returns whether the mouse
-// cursor should be rendered on the frame.
-bool CursorRendererMac::SnapshotCursorState(const gfx::Rect& region_in_frame) {
+gfx::Point CursorRendererMac::GetCursorPositionInView() {
// Mouse location in window co-ordinates.
NSPoint mouse_window_location =
[view_ window].mouseLocationOutsideOfEventStream;
- // Mouse location with respect to the web contents.
- NSPoint mouse_tab_location =
+ // Mouse location with respect to the view within the window.
+ NSPoint mouse_view_location =
[view_ convertPoint:mouse_window_location fromView:nil];
- // Mouse co-ordinates directly comparable against frame co-ordinates
- // after translation.
- if (mouse_tab_location.x < 0 || mouse_tab_location.y < 0 ||
- mouse_tab_location.x > region_in_frame.width() ||
- mouse_tab_location.y > region_in_frame.height()) {
- VLOG(2) << "Mouse outside content region";
- return false;
- }
-
- if (![[view_ window] isKeyWindow]) {
- VLOG(2) << "Window currently inactive";
- return false;
- }
+ // Invert y coordinate to unify with Aura.
+ gfx::Point cursor_position_in_view(
+ mouse_view_location.x,
+ GetCapturedViewSize().height() - mouse_view_location.y);
- if ((base::TimeTicks::Now() - last_mouse_movement_timestamp_).InSeconds() >
- MAX_IDLE_TIME_SECONDS &&
- std::abs(mouse_tab_location.x - last_mouse_location_x_) <
- MIN_MOVEMENT_PIXELS &&
- std::abs(mouse_tab_location.y - last_mouse_location_y_) <
- MIN_MOVEMENT_PIXELS) {
- VLOG(2) << "No mouse movement in a while";
- return false;
- }
+ return cursor_position_in_view;
+}
- // Mouse cursor position within the frame.
- cursor_position_in_frame_ =
- gfx::Point(region_in_frame.x() + mouse_tab_location.x,
- region_in_frame.y() + mouse_tab_location.y);
+gfx::NativeCursor CursorRendererMac::GetLastKnownCursor() {
+ // Grab system cursor.
+ return [NSCursor currentSystemCursor];
+}
+SkBitmap CursorRendererMac::GetLastKnownCursorImage(gfx::Point* hot_point) {
// Grab system cursor.
NSCursor* nscursor = [NSCursor currentSystemCursor];
- NSPoint nshotspot = [nscursor hotSpot];
NSImage* nsimage = [nscursor image];
- NSSize nssize = [nsimage size];
-
- // The cursor co-ordinates in the window and the video frame co-ordinates are
- // inverted along y-axis. We render the cursor inverse vertically on the
- // frame. Hence the inversion on hotspot offset here.
- cursor_position_in_frame_.Offset(-nshotspot.x,
- -(nssize.height - nshotspot.y));
- last_cursor_width_ = nssize.width;
- last_cursor_height_ = nssize.height;
-
- CGImageRef cg_image =
- [nsimage CGImageForProposedRect:NULL context:nil hints:nil];
- if (!cg_image)
- return false;
-
- if (CGImageGetBitsPerPixel(cg_image) != kBytesPerPixel * 8 ||
- CGImageGetBytesPerRow(cg_image) !=
- static_cast<size_t>(kBytesPerPixel * nssize.width) ||
- CGImageGetBitsPerComponent(cg_image) != 8) {
- return false;
- }
+ NSPoint nshotspot = [nscursor hotSpot];
- CGDataProviderRef provider = CGImageGetDataProvider(cg_image);
- CFDataRef image_data_ref = CGDataProviderCopyData(provider);
- if (!image_data_ref)
- return false;
- last_cursor_data_.reset(image_data_ref, base::scoped_policy::ASSUME);
-
- if (std::abs(mouse_tab_location.x - last_mouse_location_x_) >
- MIN_MOVEMENT_PIXELS ||
- std::abs(mouse_tab_location.y - last_mouse_location_y_) >
- MIN_MOVEMENT_PIXELS) {
- last_mouse_movement_timestamp_ = base::TimeTicks::Now();
- last_mouse_location_x_ = mouse_tab_location.x;
- last_mouse_location_y_ = mouse_tab_location.y;
- }
- return true;
+ *hot_point = gfx::Point(nshotspot.x, nshotspot.y);
+ return skia::NSImageToSkBitmapWithColorSpace(
+ nsimage, /*is_opaque=*/false, base::mac::GetSystemColorSpace());
}
-// Helper function to composite a RGBA cursor bitmap on a YUV420 video frame.
-void CursorRendererMac::RenderOnVideoFrame(
- const scoped_refptr<media::VideoFrame>& target) const {
- DCHECK(target);
- DCHECK(last_cursor_data_);
- const uint8_t* cursor_data_ =
- reinterpret_cast<const uint8_t*>(CFDataGetBytePtr(last_cursor_data_));
-
- gfx::Rect visible_rect = target->visible_rect();
- gfx::Rect rect =
- gfx::IntersectRects(gfx::Rect(last_cursor_width_, last_cursor_height_) +
- gfx::Vector2d(cursor_position_in_frame_.x(),
- cursor_position_in_frame_.y()),
- visible_rect);
-
- for (int y = rect.y() + 1; y <= rect.bottom(); ++y) {
- int cursor_y = rect.bottom() - y;
- int inverted_y = visible_rect.bottom() - y;
- uint8_t* yplane =
- target->data(media::VideoFrame::kYPlane) +
- inverted_y * target->row_bytes(media::VideoFrame::kYPlane);
- uint8_t* uplane =
- target->data(media::VideoFrame::kUPlane) +
- (inverted_y / 2) * target->row_bytes(media::VideoFrame::kUPlane);
- uint8_t* vplane =
- target->data(media::VideoFrame::kVPlane) +
- (inverted_y / 2) * target->row_bytes(media::VideoFrame::kVPlane);
- for (int x = rect.x(); x < rect.right(); ++x) {
- int cursor_x = x - rect.x();
- int byte_pos = cursor_y * last_cursor_width_ * kBytesPerPixel +
- cursor_x * kBytesPerPixel;
- int color_r = cursor_data_[byte_pos];
- int color_g = cursor_data_[byte_pos + 1];
- int color_b = cursor_data_[byte_pos + 2];
- int alpha = cursor_data_[byte_pos + 3];
- int color_y = clip_byte(
- ((color_r * 66 + color_g * 129 + color_b * 25 + 128) >> 8) + 16);
- yplane[x] = alpha_blend(alpha, color_y, yplane[x]);
-
- // Only sample U and V at even coordinates.
- if ((x % 2 == 0) && (y % 2 == 0)) {
- int color_u = clip_byte(
- ((color_r * -38 + color_g * -74 + color_b * 112 + 128) >> 8) + 128);
- int color_v = clip_byte(
- ((color_r * 112 + color_g * -94 + color_b * -18 + 128) >> 8) + 128);
- uplane[x / 2] = alpha_blend(alpha, color_u, uplane[x / 2]);
- vplane[x / 2] = alpha_blend(alpha, color_v, vplane[x / 2]);
- }
- }
- }
+void CursorRendererMac::OnMouseEvent() {
+ // Update cursor movement info to CursorRenderer.
+ OnMouseMoved(GetCursorPositionInView(), base::TimeTicks::Now());
}
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698