summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorisheriff <isheriff@chromium.org>2016-03-25 18:11:38 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-26 01:12:54 +0000
commit76bb611f077321a06f5df9a22e414bb99722c479 (patch)
treef82e2c8fbfc6fc0f2ce8661e56a6de20d0e8bc1d
parent934f67a68da2054e526e13648c5452e2cf79c211 (diff)
downloadchromium_src-76bb611f077321a06f5df9a22e414bb99722c479.zip
chromium_src-76bb611f077321a06f5df9a22e414bb99722c479.tar.gz
chromium_src-76bb611f077321a06f5df9a22e414bb99722c479.tar.bz2
cast: Add window activity tracker for mac
This adds window activity detector for mac which enables the following features to be enabled on tab mirroring: - Low latency interactive mode will be turned on when user is interactive with non-animating content - Frame subscriber will enable frame capture in response to mouse events resulting in smooth rendering of mouse while mirroring BUG=567735 Review URL: https://codereview.chromium.org/1835493002 Cr-Commit-Position: refs/heads/master@{#383431}
-rw-r--r--content/browser/media/capture/cursor_renderer.h2
-rw-r--r--content/browser/media/capture/cursor_renderer_aura.cc6
-rw-r--r--content/browser/media/capture/cursor_renderer_mac.mm5
-rw-r--r--content/browser/media/capture/web_contents_video_capture_device.cc153
-rw-r--r--content/browser/media/capture/window_activity_tracker.cc54
-rw-r--r--content/browser/media/capture/window_activity_tracker.h31
-rw-r--r--content/browser/media/capture/window_activity_tracker_aura.cc46
-rw-r--r--content/browser/media/capture/window_activity_tracker_aura.h15
-rw-r--r--content/browser/media/capture/window_activity_tracker_mac.h62
-rw-r--r--content/browser/media/capture/window_activity_tracker_mac.mm81
-rw-r--r--content/content_browser.gypi3
11 files changed, 314 insertions, 144 deletions
diff --git a/content/browser/media/capture/cursor_renderer.h b/content/browser/media/capture/cursor_renderer.h
index 7416413..7d3536a 100644
--- a/content/browser/media/capture/cursor_renderer.h
+++ b/content/browser/media/capture/cursor_renderer.h
@@ -21,6 +21,8 @@ namespace content {
// will listen to mouse events.
class CONTENT_EXPORT CursorRenderer {
public:
+ static scoped_ptr<CursorRenderer> Create(gfx::NativeView view);
+
virtual ~CursorRenderer() {}
// Clears the cursor state being tracked. Called when there is a need to
diff --git a/content/browser/media/capture/cursor_renderer_aura.cc b/content/browser/media/capture/cursor_renderer_aura.cc
index 2b446e0..e5d3fc2 100644
--- a/content/browser/media/capture/cursor_renderer_aura.cc
+++ b/content/browser/media/capture/cursor_renderer_aura.cc
@@ -35,6 +35,12 @@ inline int alpha_blend(int alpha, int src, int dst) {
} // namespace
+// static
+scoped_ptr<CursorRenderer> CursorRenderer::Create(gfx::NativeWindow window) {
+ return scoped_ptr<CursorRenderer>(
+ new CursorRendererAura(window, kCursorEnabledOnMouseMovement));
+}
+
CursorRendererAura::CursorRendererAura(
aura::Window* window,
CursorDisplaySetting cursor_display_setting)
diff --git a/content/browser/media/capture/cursor_renderer_mac.mm b/content/browser/media/capture/cursor_renderer_mac.mm
index 05c3fdd..bf382bf 100644
--- a/content/browser/media/capture/cursor_renderer_mac.mm
+++ b/content/browser/media/capture/cursor_renderer_mac.mm
@@ -30,6 +30,11 @@ inline int alpha_blend(int alpha, int src, int dst) {
} // namespace
+// static
+scoped_ptr<CursorRenderer> CursorRenderer::Create(gfx::NativeView view) {
+ return scoped_ptr<CursorRenderer>(new CursorRendererMac(view));
+}
+
CursorRendererMac::CursorRendererMac(NSView* view)
: view_(view), weak_factory_(this) {
Clear();
diff --git a/content/browser/media/capture/web_contents_video_capture_device.cc b/content/browser/media/capture/web_contents_video_capture_device.cc
index 03895dd..73ba6c5 100644
--- a/content/browser/media/capture/web_contents_video_capture_device.cc
+++ b/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -93,13 +93,6 @@
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/size_conversions.h"
-#if defined(USE_AURA)
-#include "content/browser/media/capture/cursor_renderer_aura.h"
-#include "content/browser/media/capture/window_activity_tracker_aura.h"
-#elif defined(OS_MACOSX)
-#include "content/browser/media/capture/cursor_renderer_mac.h"
-#endif
-
namespace content {
namespace {
@@ -199,10 +192,10 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
// autonomously on some other thread.
class ContentCaptureSubscription {
public:
- typedef base::Callback<
- void(const base::TimeTicks&,
- const scoped_refptr<media::VideoFrame>&,
- const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&)>
+ typedef base::Callback<void(
+ const base::TimeTicks&,
+ const scoped_refptr<media::VideoFrame>&,
+ const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&)>
CaptureCallback;
// Create a subscription. Whenever a manual capture is required, the
@@ -360,8 +353,8 @@ bool FrameSubscriber::ShouldCaptureFrame(
base::TimeTicks present_time,
scoped_refptr<media::VideoFrame>* storage,
DeliverFrameCallback* deliver_frame_cb) {
- TRACE_EVENT1("gpu.capture", "FrameSubscriber::ShouldCaptureFrame",
- "instance", this);
+ TRACE_EVENT1("gpu.capture", "FrameSubscriber::ShouldCaptureFrame", "instance",
+ this);
media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
@@ -438,19 +431,11 @@ ContentCaptureSubscription::ContentCaptureSubscription(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderWidgetHostView* const view = source.GetView();
-// TODO(isheriff): Implement activity tracker on mac.
-// https://crbug.com/567735
-#if defined(USE_AURA)
- if (view) {
- cursor_renderer_.reset(new content::CursorRendererAura(
- view->GetNativeView(), kCursorEnabledOnMouseMovement));
- window_activity_tracker_.reset(
- new content::WindowActivityTrackerAura(view->GetNativeView()));
- }
-#elif defined(OS_MACOSX)
+#if defined(USE_AURA) || defined(OS_MACOSX)
if (view) {
- cursor_renderer_.reset(
- new content::CursorRendererMac(view->GetNativeView()));
+ cursor_renderer_ = CursorRenderer::Create(view->GetNativeView());
+ window_activity_tracker_ =
+ WindowActivityTracker::Create(view->GetNativeView());
}
#endif
timer_subscriber_.reset(new FrameSubscriber(
@@ -536,12 +521,10 @@ void RenderVideoFrame(
SkAutoLockPixels locker(input);
// Sanity-check the captured bitmap.
- if (input.empty() ||
- !input.readyToDraw() ||
- input.colorType() != kN32_SkColorType ||
- input.width() < 2 || input.height() < 2) {
- DVLOG(1) << "input unacceptable (size="
- << input.getSize()
+ if (input.empty() || !input.readyToDraw() ||
+ input.colorType() != kN32_SkColorType || input.width() < 2 ||
+ input.height() < 2) {
+ DVLOG(1) << "input unacceptable (size=" << input.getSize()
<< ", ready=" << input.readyToDraw()
<< ", colorType=" << input.colorType() << ')';
return;
@@ -572,11 +555,10 @@ void RenderVideoFrame(
method = skia::ImageOperations::RESIZE_BOX;
}
- TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture",
- "Capture", output.get(), "Scale");
- scaled_bitmap = skia::ImageOperations::Resize(input, method,
- region_in_frame.width(),
- region_in_frame.height());
+ TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", "Capture", output.get(),
+ "Scale");
+ scaled_bitmap = skia::ImageOperations::Resize(
+ input, method, region_in_frame.width(), region_in_frame.height());
} else {
scaled_bitmap = input;
}
@@ -585,10 +567,9 @@ void RenderVideoFrame(
{
// Align to 2x2 pixel boundaries, as required by
// media::CopyRGBToVideoFrame().
- const gfx::Rect region_in_yv12_frame(region_in_frame.x() & ~1,
- region_in_frame.y() & ~1,
- region_in_frame.width() & ~1,
- region_in_frame.height() & ~1);
+ const gfx::Rect region_in_yv12_frame(
+ region_in_frame.x() & ~1, region_in_frame.y() & ~1,
+ region_in_frame.width() & ~1, region_in_frame.height() & ~1);
if (region_in_yv12_frame.IsEmpty())
return;
@@ -604,9 +585,7 @@ void RenderVideoFrame(
}
VideoFrameDeliveryLog::VideoFrameDeliveryLog()
- : last_frame_rate_log_time_(),
- count_frames_rendered_(0) {
-}
+ : last_frame_rate_log_time_(), count_frames_rendered_(0) {}
void VideoFrameDeliveryLog::ChronicleFrameDelivery(base::TimeTicks frame_time) {
// Log frame rate, if verbose logging is turned on.
@@ -619,11 +598,9 @@ void VideoFrameDeliveryLog::ChronicleFrameDelivery(base::TimeTicks frame_time) {
++count_frames_rendered_;
const base::TimeDelta elapsed = frame_time - last_frame_rate_log_time_;
if (elapsed >= kFrameRateLogInterval) {
- const double measured_fps =
- count_frames_rendered_ / elapsed.InSecondsF();
- UMA_HISTOGRAM_COUNTS(
- "TabCapture.FrameRate",
- static_cast<int>(measured_fps));
+ const double measured_fps = count_frames_rendered_ / elapsed.InSecondsF();
+ UMA_HISTOGRAM_COUNTS("TabCapture.FrameRate",
+ static_cast<int>(measured_fps));
VLOG(1) << "Current measured frame rate for "
<< "WebContentsVideoCaptureDevice is " << measured_fps << " FPS.";
last_frame_rate_log_time_ = frame_time;
@@ -641,8 +618,8 @@ WebContentsCaptureMachine::WebContentsCaptureMachine(
tracker_(new WebContentsTracker(true)),
auto_throttling_enabled_(enable_auto_throttling),
weak_ptr_factory_(this) {
- DVLOG(1) << "Created WebContentsCaptureMachine for "
- << render_process_id << ':' << main_render_frame_id
+ DVLOG(1) << "Created WebContentsCaptureMachine for " << render_process_id
+ << ':' << main_render_frame_id
<< (auto_throttling_enabled_ ? " with auto-throttling enabled" : "");
}
@@ -659,12 +636,9 @@ void WebContentsCaptureMachine::Start(
const base::Callback<void(bool)> callback) {
// Starts the capture machine asynchronously.
BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
+ BrowserThread::UI, FROM_HERE,
base::Bind(&WebContentsCaptureMachine::InternalStart,
- base::Unretained(this),
- oracle_proxy,
- params),
+ base::Unretained(this), oracle_proxy, params),
callback);
}
@@ -699,11 +673,9 @@ bool WebContentsCaptureMachine::InternalStart(
void WebContentsCaptureMachine::Stop(const base::Closure& callback) {
// Stops the capture machine asynchronously.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(
- &WebContentsCaptureMachine::InternalStop,
- base::Unretained(this),
- callback));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&WebContentsCaptureMachine::InternalStop,
+ base::Unretained(this), callback));
}
void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) {
@@ -727,9 +699,8 @@ void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) {
// to the thread pool used for blocking operations.
if (render_thread_) {
BrowserThread::PostBlockingPoolTask(
- FROM_HERE,
- base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_),
- callback));
+ FROM_HERE, base::Bind(&DeleteOnWorkerThread,
+ base::Passed(&render_thread_), callback));
}
}
@@ -753,29 +724,28 @@ void WebContentsCaptureMachine::Capture(
last_view_size_ = view_size;
// Measure the number of kilopixels.
- UMA_HISTOGRAM_COUNTS_10000(
- "TabCapture.ViewChangeKiloPixels",
- view_size.width() * view_size.height() / 1024);
+ UMA_HISTOGRAM_COUNTS_10000("TabCapture.ViewChangeKiloPixels",
+ view_size.width() * view_size.height() / 1024);
}
if (view->CanCopyToVideoFrame()) {
view->CopyFromCompositingSurfaceToVideoFrame(
- gfx::Rect(view_size),
- target,
+ gfx::Rect(view_size), target,
base::Bind(&WebContentsCaptureMachine::
- DidCopyFromCompositingSurfaceToVideoFrame,
- weak_ptr_factory_.GetWeakPtr(),
- start_time, deliver_frame_cb));
+ DidCopyFromCompositingSurfaceToVideoFrame,
+ weak_ptr_factory_.GetWeakPtr(), start_time,
+ deliver_frame_cb));
} else {
- const gfx::Size fitted_size = view_size.IsEmpty() ? gfx::Size() :
- media::ComputeLetterboxRegion(target->visible_rect(), view_size).size();
+ const gfx::Size fitted_size =
+ view_size.IsEmpty()
+ ? gfx::Size()
+ : media::ComputeLetterboxRegion(target->visible_rect(), view_size)
+ .size();
rwh->CopyFromBackingStore(
gfx::Rect(),
fitted_size, // Size here is a request not always honored.
base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore,
- weak_ptr_factory_.GetWeakPtr(),
- start_time,
- target,
+ weak_ptr_factory_.GetWeakPtr(), start_time, target,
deliver_frame_cb),
kN32_SkColorType);
}
@@ -801,18 +771,17 @@ gfx::Size WebContentsCaptureMachine::ComputeOptimalViewSize() const {
// issues caused by "one pixel stretching" and/or odd-to-even dimension
// scaling, and to improve the performance of consumers of the captured
// video.
- const auto HasIntendedAspectRatio =
- [](const gfx::Size& size, int width_units, int height_units) {
+ const auto HasIntendedAspectRatio = [](
+ const gfx::Size& size, int width_units, int height_units) {
const int a = height_units * size.width();
const int b = width_units * size.height();
const int percentage_diff = 100 * std::abs((a - b)) / b;
return percentage_diff <= 1; // Effectively, anything strictly <2%.
};
- const auto RoundToExactAspectRatio =
- [](const gfx::Size& size, int width_step, int height_step) {
- const int adjusted_height =
- std::max(size.height() - (size.height() % height_step),
- height_step);
+ const auto RoundToExactAspectRatio = [](const gfx::Size& size,
+ int width_step, int height_step) {
+ const int adjusted_height = std::max(
+ size.height() - (size.height() % height_step), height_step);
DCHECK_EQ((adjusted_height * width_step) % height_step, 0);
return gfx::Size(adjusted_height * width_step / height_step,
adjusted_height);
@@ -865,8 +834,8 @@ void WebContentsCaptureMachine::DidCopyFromBackingStore(
"Render");
render_thread_->task_runner()->PostTask(
FROM_HERE, media::BindToCurrentLoop(
- base::Bind(&RenderVideoFrame, bitmap, target,
- base::Bind(deliver_frame_cb, start_time))));
+ base::Bind(&RenderVideoFrame, bitmap, target,
+ base::Bind(deliver_frame_cb, start_time))));
} else {
// Capture can fail due to transient issues, so just skip this frame.
DVLOG(1) << "CopyFromBackingStore failed; skipping frame.";
@@ -920,9 +889,9 @@ void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) {
if (!had_subscription && tracker_->web_contents())
tracker_->web_contents()->IncrementCapturerCount(ComputeOptimalViewSize());
- subscription_.reset(new ContentCaptureSubscription(*rwh, oracle_proxy_,
- base::Bind(&WebContentsCaptureMachine::Capture,
- weak_ptr_factory_.GetWeakPtr())));
+ subscription_.reset(new ContentCaptureSubscription(
+ *rwh, oracle_proxy_, base::Bind(&WebContentsCaptureMachine::Capture,
+ weak_ptr_factory_.GetWeakPtr())));
}
void WebContentsCaptureMachine::UpdateCaptureSize() {
@@ -955,10 +924,10 @@ WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
int main_render_frame_id,
bool enable_auto_throttling)
: core_(new media::ScreenCaptureDeviceCore(
- scoped_ptr<media::VideoCaptureMachine>(new WebContentsCaptureMachine(
- render_process_id,
- main_render_frame_id,
- enable_auto_throttling)))) {}
+ scoped_ptr<media::VideoCaptureMachine>(
+ new WebContentsCaptureMachine(render_process_id,
+ main_render_frame_id,
+ enable_auto_throttling)))) {}
WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying.";
diff --git a/content/browser/media/capture/window_activity_tracker.cc b/content/browser/media/capture/window_activity_tracker.cc
new file mode 100644
index 0000000..394792d
--- /dev/null
+++ b/content/browser/media/capture/window_activity_tracker.cc
@@ -0,0 +1,54 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/window_activity_tracker.h"
+
+#include "base/time/time.h"
+
+namespace content {
+
+namespace {
+
+// The time period within which a triggered UI event is considered
+// currently active.
+const int kTimePeriodUiEventMicros = 100000; // 100 ms
+
+// Minimum number of user interactions before we consider the user to be in
+// interactive mode. The goal is to prevent user interactions to launch
+// animated content from causing target playout time flip-flop.
+const int kMinUserInteractions = 5;
+
+} // namespace
+
+WindowActivityTracker::WindowActivityTracker() {
+ Reset();
+}
+
+WindowActivityTracker::~WindowActivityTracker() {}
+
+bool WindowActivityTracker::IsUiInteractionActive() const {
+ return ui_events_count_ > kMinUserInteractions;
+}
+
+void WindowActivityTracker::RegisterMouseInteractionObserver(
+ const base::Closure& observer) {
+ mouse_interaction_observer_ = observer;
+}
+
+void WindowActivityTracker::Reset() {
+ ui_events_count_ = 0;
+ last_time_ui_event_detected_ = base::TimeTicks();
+}
+
+void WindowActivityTracker::OnMouseActivity() {
+ if (!mouse_interaction_observer_.is_null())
+ mouse_interaction_observer_.Run();
+ if (base::TimeTicks::Now() - last_time_ui_event_detected_ >
+ base::TimeDelta::FromMicroseconds(kTimePeriodUiEventMicros)) {
+ ui_events_count_++;
+ }
+ last_time_ui_event_detected_ = base::TimeTicks::Now();
+}
+
+} // namespace content
diff --git a/content/browser/media/capture/window_activity_tracker.h b/content/browser/media/capture/window_activity_tracker.h
index d7b8d0f..7bdef1e 100644
--- a/content/browser/media/capture/window_activity_tracker.h
+++ b/content/browser/media/capture/window_activity_tracker.h
@@ -5,9 +5,11 @@
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_WINDOW_ACTIVITY_TRACKER_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_WINDOW_ACTIVITY_TRACKER_H_
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "ui/gfx/native_widget_types.h"
namespace content {
@@ -15,20 +17,39 @@ namespace content {
// whether the user is actively interacting with UI.
class CONTENT_EXPORT WindowActivityTracker {
public:
- virtual ~WindowActivityTracker() {}
+ static scoped_ptr<WindowActivityTracker> Create(gfx::NativeView view);
+
+ WindowActivityTracker();
+ virtual ~WindowActivityTracker();
// Returns true if UI interaction is active.
- virtual bool IsUiInteractionActive() const = 0;
+ bool IsUiInteractionActive() const;
// Reports on every mouse movement activity on the window.
- virtual void RegisterMouseInteractionObserver(
- const base::Closure& observer) {}
+ void RegisterMouseInteractionObserver(const base::Closure& observer);
// Resets any previous UI activity tracked.
- virtual void Reset() = 0;
+ void Reset();
// Returns a weak pointer.
virtual base::WeakPtr<WindowActivityTracker> GetWeakPtr() = 0;
+
+ protected:
+ void OnMouseActivity();
+
+ private:
+ // The last time a UI event was detected.
+ base::TimeTicks last_time_ui_event_detected_;
+
+ // Runs on any mouse interaction from user.
+ base::Closure mouse_interaction_observer_;
+
+ // The number of UI events detected so far. In case of continuous events
+ // such as mouse movement, a single continuous movement is treated
+ // as one event.
+ int ui_events_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowActivityTracker);
};
} // namespace content
diff --git a/content/browser/media/capture/window_activity_tracker_aura.cc b/content/browser/media/capture/window_activity_tracker_aura.cc
index 035c0ca..bc139aa 100644
--- a/content/browser/media/capture/window_activity_tracker_aura.cc
+++ b/content/browser/media/capture/window_activity_tracker_aura.cc
@@ -11,21 +11,15 @@
namespace content {
-namespace {
-// The time period within which a triggered UI event is considered
-// currently active.
-const int kTimePeriodUiEventMicros = 100000; // 100 ms
-
-// Minimum number of user interactions before we consider the user to be in
-// interactive mode. The goal is to prevent user interactions to launch
-// animated content from causing target playout time flip-flop.
-const int kMinUserInteractions = 5;
-} // namespace
+// static
+scoped_ptr<WindowActivityTracker> WindowActivityTracker::Create(
+ gfx::NativeView window) {
+ return scoped_ptr<WindowActivityTracker>(
+ new WindowActivityTrackerAura(window));
+}
WindowActivityTrackerAura::WindowActivityTrackerAura(aura::Window* window)
: window_(window),
- last_time_ui_event_detected_(base::TimeTicks()),
- ui_events_count_(0),
weak_factory_(this) {
if (window_) {
window_->AddObserver(this);
@@ -44,28 +38,16 @@ base::WeakPtr<WindowActivityTracker> WindowActivityTrackerAura::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
-bool WindowActivityTrackerAura::IsUiInteractionActive() const {
- return ui_events_count_ > kMinUserInteractions;
-}
-
-void WindowActivityTrackerAura::RegisterMouseInteractionObserver(
- const base::Closure& observer) {
- mouse_interaction_observer_ = observer;
-}
-
-void WindowActivityTrackerAura::Reset() {
- ui_events_count_ = 0;
- last_time_ui_event_detected_ = base::TimeTicks();
-}
-
void WindowActivityTrackerAura::OnEvent(ui::Event* event) {
- if (!mouse_interaction_observer_.is_null() && event->IsMouseEvent())
- mouse_interaction_observer_.Run();
- if (base::TimeTicks::Now() - last_time_ui_event_detected_ >
- base::TimeDelta::FromMicroseconds(kTimePeriodUiEventMicros)) {
- ui_events_count_++;
+ switch (event->type()) {
+ case ui::ET_MOUSE_PRESSED:
+ case ui::ET_MOUSE_RELEASED:
+ case ui::ET_MOUSE_MOVED:
+ WindowActivityTracker::OnMouseActivity();
+ break;
+ default:
+ break;
}
- last_time_ui_event_detected_ = base::TimeTicks::Now();
}
void WindowActivityTrackerAura::OnWindowDestroying(aura::Window* window) {
diff --git a/content/browser/media/capture/window_activity_tracker_aura.h b/content/browser/media/capture/window_activity_tracker_aura.h
index 48a277f..be5f29c 100644
--- a/content/browser/media/capture/window_activity_tracker_aura.h
+++ b/content/browser/media/capture/window_activity_tracker_aura.h
@@ -24,10 +24,6 @@ class CONTENT_EXPORT WindowActivityTrackerAura : public WindowActivityTracker,
explicit WindowActivityTrackerAura(aura::Window* window);
~WindowActivityTrackerAura() final;
- // WindowActivityTracker overrides.
- bool IsUiInteractionActive() const final;
- void RegisterMouseInteractionObserver(const base::Closure& observer) final;
- void Reset() final;
base::WeakPtr<WindowActivityTracker> GetWeakPtr() final;
private:
@@ -39,17 +35,6 @@ class CONTENT_EXPORT WindowActivityTrackerAura : public WindowActivityTracker,
aura::Window* window_;
- // The last time a UI event was detected.
- base::TimeTicks last_time_ui_event_detected_;
-
- // Runs on mouse movement or mouse cursor changes.
- base::Closure mouse_interaction_observer_;
-
- // The number of UI events detected so far. In case of continuous events
- // such as mouse movement, a single continuous movement is treated
- // as one event.
- int ui_events_count_;
-
base::WeakPtrFactory<WindowActivityTrackerAura> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(WindowActivityTrackerAura);
diff --git a/content/browser/media/capture/window_activity_tracker_mac.h b/content/browser/media/capture/window_activity_tracker_mac.h
new file mode 100644
index 0000000..64c91a0
--- /dev/null
+++ b/content/browser/media/capture/window_activity_tracker_mac.h
@@ -0,0 +1,62 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_WINDOW_ACTIVITY_TRACKER_MAC_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_WINDOW_ACTIVITY_TRACKER_MAC_H_
+
+#import <AppKit/AppKit.h>
+#import <CoreFoundation/CoreFoundation.h>
+
+#include "base/callback.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/media/capture/window_activity_tracker.h"
+#include "content/common/content_export.h"
+#include "ui/base/cocoa/tracking_area.h"
+#include "ui/gfx/native_widget_types.h"
+
+@interface MouseTracker : NSObject {
+ @private
+ ui::ScopedCrTrackingArea trackingArea_;
+
+ // The view on which mouse movement is detected.
+ NSView* nsView_;
+
+ // Runs on any mouse interaction from user.
+ base::Closure mouseInteractionObserver_;
+}
+
+- (instancetype)initWithView:(NSView*)nsView;
+
+// Register an observer for mouse interaction.
+- (void)registerMouseInteractionObserver:(const base::Closure&)observer;
+
+@end
+
+namespace content {
+
+// Tracks UI events and makes a decision on whether the user has been
+// actively interacting with a specified window.
+class CONTENT_EXPORT WindowActivityTrackerMac : public WindowActivityTracker {
+ public:
+ explicit WindowActivityTrackerMac(NSView* view);
+ ~WindowActivityTrackerMac() final;
+
+ base::WeakPtr<WindowActivityTracker> GetWeakPtr() final;
+
+ private:
+ void OnMouseActivity();
+
+ NSView* const view_;
+ base::scoped_nsobject<MouseTracker> mouse_tracker_;
+
+ base::WeakPtrFactory<WindowActivityTrackerMac> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowActivityTrackerMac);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_WINDOW_ACTIVITY_TRACKER_MAC_H_
diff --git a/content/browser/media/capture/window_activity_tracker_mac.mm b/content/browser/media/capture/window_activity_tracker_mac.mm
new file mode 100644
index 0000000..3b71cd6
--- /dev/null
+++ b/content/browser/media/capture/window_activity_tracker_mac.mm
@@ -0,0 +1,81 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/window_activity_tracker_mac.h"
+
+#include <AppKit/AppKit.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "base/bind.h"
+#include "ui/base/cocoa/tracking_area.h"
+
+@implementation MouseTracker
+
+- (instancetype)initWithView:(NSView*)nsView {
+ self = [super init];
+ // TODO(isheriff): why are there no pressed/released events ?
+ NSTrackingAreaOptions trackingOptions =
+ NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited |
+ NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect;
+ trackingArea_.reset([[CrTrackingArea alloc] initWithRect:NSZeroRect
+ options:trackingOptions
+ owner:self
+ userInfo:nil]);
+ [nsView addTrackingArea:trackingArea_.get()];
+ nsView_ = nsView;
+ return self;
+}
+
+- (void)stopTracking {
+ if (trackingArea_.get()) {
+ [nsView_ removeTrackingArea:trackingArea_.get()];
+ trackingArea_.reset();
+ }
+}
+
+- (void)registerMouseInteractionObserver:(const base::Closure&)observer {
+ mouseInteractionObserver_ = observer;
+}
+
+- (void)mouseMoved:(NSEvent*)theEvent {
+ mouseInteractionObserver_.Run();
+}
+
+- (void)mouseEntered:(NSEvent*)theEvent {
+}
+
+- (void)mouseExited:(NSEvent*)theEvent {
+}
+
+@end
+
+namespace content {
+
+// static
+scoped_ptr<WindowActivityTracker> WindowActivityTracker::Create(
+ gfx::NativeView view) {
+ return scoped_ptr<WindowActivityTracker>(new WindowActivityTrackerMac(view));
+}
+
+WindowActivityTrackerMac::WindowActivityTrackerMac(NSView* view)
+ : view_(view), weak_factory_(this) {
+ mouse_tracker_.reset([[MouseTracker alloc] initWithView:view]);
+ [mouse_tracker_ registerMouseInteractionObserver:
+ base::Bind(&WindowActivityTrackerMac::OnMouseActivity,
+ base::Unretained(this))];
+}
+
+WindowActivityTrackerMac::~WindowActivityTrackerMac() {
+ [mouse_tracker_ stopTracking];
+}
+
+void WindowActivityTrackerMac::OnMouseActivity() {
+ WindowActivityTracker::OnMouseActivity();
+}
+
+base::WeakPtr<WindowActivityTracker> WindowActivityTrackerMac::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+} // namespace content
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index b359e05a8..63dd939 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1066,9 +1066,12 @@
'browser/media/capture/web_contents_tracker.h',
'browser/media/capture/web_contents_video_capture_device.cc',
'browser/media/capture/web_contents_video_capture_device.h',
+ 'browser/media/capture/window_activity_tracker.cc',
'browser/media/capture/window_activity_tracker.h',
'browser/media/capture/window_activity_tracker_aura.cc',
'browser/media/capture/window_activity_tracker_aura.h',
+ 'browser/media/capture/window_activity_tracker_mac.mm',
+ 'browser/media/capture/window_activity_tracker_mac.h',
'browser/media/media_internals.cc',
'browser/media/media_internals.h',
'browser/media/media_internals_handler.cc',