| Index: media/base/user_input_monitor_linux.cc
|
| diff --git a/media/base/user_input_monitor_linux.cc b/media/base/user_input_monitor_linux.cc
|
| index 196b4e7407836319eb72af8b5298d0aebf84bc8e..0a27a6cb982d1b51b6037ad0f1ee61f6b64a97e8 100644
|
| --- a/media/base/user_input_monitor_linux.cc
|
| +++ b/media/base/user_input_monitor_linux.cc
|
| @@ -15,10 +15,13 @@
|
| #include "base/compiler_specific.h"
|
| #include "base/location.h"
|
| #include "base/logging.h"
|
| +#include "base/memory/weak_ptr.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/message_loop/message_pump_libevent.h"
|
| +#include "base/observer_list_threadsafe.h"
|
| #include "base/posix/eintr_wrapper.h"
|
| #include "base/single_thread_task_runner.h"
|
| +#include "base/synchronization/lock.h"
|
| #include "media/base/keyboard_event_counter.h"
|
| #include "third_party/skia/include/core/SkPoint.h"
|
| #include "ui/base/keycodes/keyboard_code_conversion_x.h"
|
| @@ -32,29 +35,51 @@
|
| namespace media {
|
| namespace {
|
|
|
| -class UserInputMonitorLinux : public UserInputMonitor ,
|
| - public base::MessagePumpLibevent::Watcher {
|
| +class UserInputMonitorLinux : public UserInputMonitor {
|
| public:
|
| explicit UserInputMonitorLinux(
|
| const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
|
| virtual ~UserInputMonitorLinux();
|
|
|
| + // Public interface of UserInputMonitor.
|
| + virtual void AddMouseListener(MouseEventListener* listener) OVERRIDE;
|
| + virtual void RemoveMouseListener(MouseEventListener* listener) OVERRIDE;
|
| virtual size_t GetKeyPressCount() const OVERRIDE;
|
|
|
| private:
|
| + // Private interface of UserInputMonitor.
|
| + virtual void StartKeyboardMonitoring() OVERRIDE;
|
| + virtual void StopKeyboardMonitoring() OVERRIDE;
|
| +
|
| + class Core;
|
| + Core* core_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinux);
|
| +};
|
| +
|
| +// This is the actual implementation of event monitoring. It's separated from
|
| +// UserInputMonitorLinux since it needs to be deleted on the IO thread.
|
| +class UserInputMonitorLinux::Core : public base::MessagePumpLibevent::Watcher {
|
| + public:
|
| + explicit Core(
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
|
| + virtual ~Core();
|
| +
|
| + void AddMouseListener(MouseEventListener* listener);
|
| + void RemoveMouseListener(MouseEventListener* listener);
|
| + size_t GetKeyPressCount() const;
|
| + void StartKeyboardMonitoring();
|
| + void StopKeyboardMonitoring();
|
| + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() {
|
| + return io_task_runner_;
|
| + }
|
| +
|
| + private:
|
| enum EventType {
|
| MOUSE_EVENT,
|
| KEYBOARD_EVENT
|
| };
|
|
|
| - virtual void StartMouseMonitoring() OVERRIDE;
|
| - virtual void StopMouseMonitoring() OVERRIDE;
|
| - virtual void StartKeyboardMonitoring() OVERRIDE;
|
| - virtual void StopKeyboardMonitoring() OVERRIDE;
|
| -
|
| - //
|
| - // The following methods must be called on the IO thread.
|
| - //
|
| void StartMonitor(EventType type);
|
| void StopMonitor(EventType type);
|
|
|
| @@ -66,8 +91,10 @@ class UserInputMonitorLinux : public UserInputMonitor ,
|
| void ProcessXEvent(xEvent* event);
|
| static void ProcessReply(XPointer self, XRecordInterceptData* data);
|
|
|
| - // Task runner on which X Window events are received.
|
| + base::Lock lock_;
|
| scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
|
| + scoped_refptr<ObserverListThreadSafe<MouseEventListener> > mouse_listeners_;
|
| + size_t mouse_listeners_count_;
|
|
|
| //
|
| // The following members should only be accessed on the IO thread.
|
| @@ -78,21 +105,26 @@ class UserInputMonitorLinux : public UserInputMonitor ,
|
| XRecordRange* x_record_range_[2];
|
| XRecordContext x_record_context_;
|
| KeyboardEventCounter counter_;
|
| + base::WeakPtrFactory<Core> weak_factory_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinux);
|
| + DISALLOW_COPY_AND_ASSIGN(Core);
|
| };
|
|
|
| -UserInputMonitorLinux::UserInputMonitorLinux(
|
| +UserInputMonitorLinux::Core::Core(
|
| const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
|
| : io_task_runner_(io_task_runner),
|
| + mouse_listeners_(new ObserverListThreadSafe<MouseEventListener>()),
|
| + mouse_listeners_count_(0),
|
| display_(NULL),
|
| x_record_display_(NULL),
|
| - x_record_context_(0) {
|
| + x_record_context_(0),
|
| + weak_factory_(this) {
|
| x_record_range_[0] = NULL;
|
| x_record_range_[1] = NULL;
|
| }
|
|
|
| -UserInputMonitorLinux::~UserInputMonitorLinux() {
|
| +UserInputMonitorLinux::Core::~Core() {
|
| + DCHECK_EQ(0u, mouse_listeners_count_);
|
| DCHECK(!display_);
|
| DCHECK(!x_record_display_);
|
| DCHECK(!x_record_range_[0]);
|
| @@ -100,59 +132,57 @@ UserInputMonitorLinux::~UserInputMonitorLinux() {
|
| DCHECK(!x_record_context_);
|
| }
|
|
|
| -size_t UserInputMonitorLinux::GetKeyPressCount() const {
|
| - return counter_.GetKeyPressCount();
|
| +void UserInputMonitorLinux::Core::AddMouseListener(
|
| + MouseEventListener* listener) {
|
| + mouse_listeners_->AddObserver(listener);
|
| + {
|
| + base::AutoLock auto_lock(lock_);
|
| + mouse_listeners_count_++;
|
| + if (mouse_listeners_count_ == 1) {
|
| + io_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &Core::StartMonitor, weak_factory_.GetWeakPtr(), MOUSE_EVENT));
|
| + DVLOG(2) << "Started mouse monitoring.";
|
| + }
|
| + }
|
| }
|
|
|
| -void UserInputMonitorLinux::StartMouseMonitoring() {
|
| - if (!io_task_runner_->BelongsToCurrentThread()) {
|
| - io_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&UserInputMonitorLinux::StartMonitor,
|
| - base::Unretained(this),
|
| - MOUSE_EVENT));
|
| - return;
|
| +void UserInputMonitorLinux::Core::RemoveMouseListener(
|
| + MouseEventListener* listener) {
|
| + mouse_listeners_->RemoveObserver(listener);
|
| + {
|
| + base::AutoLock auto_lock(lock_);
|
| + mouse_listeners_count_--;
|
| + if (mouse_listeners_count_ == 0) {
|
| + io_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &Core::StopMonitor, weak_factory_.GetWeakPtr(), MOUSE_EVENT));
|
| + DVLOG(2) << "Stopped mouse monitoring.";
|
| + }
|
| }
|
| - StartMonitor(MOUSE_EVENT);
|
| }
|
|
|
| -void UserInputMonitorLinux::StopMouseMonitoring() {
|
| - if (!io_task_runner_->BelongsToCurrentThread()) {
|
| - io_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&UserInputMonitorLinux::StopMonitor,
|
| - base::Unretained(this),
|
| - MOUSE_EVENT));
|
| - return;
|
| - }
|
| - StopMonitor(MOUSE_EVENT);
|
| +size_t UserInputMonitorLinux::Core::GetKeyPressCount() const {
|
| + return counter_.GetKeyPressCount();
|
| }
|
|
|
| -void UserInputMonitorLinux::StartKeyboardMonitoring() {
|
| - if (!io_task_runner_->BelongsToCurrentThread()) {
|
| - io_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&UserInputMonitorLinux::StartMonitor,
|
| - base::Unretained(this),
|
| - KEYBOARD_EVENT));
|
| - return;
|
| - }
|
| - StartMonitor(KEYBOARD_EVENT);
|
| +void UserInputMonitorLinux::Core::StartKeyboardMonitoring() {
|
| + io_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &Core::StartMonitor, weak_factory_.GetWeakPtr(), KEYBOARD_EVENT));
|
| }
|
|
|
| -void UserInputMonitorLinux::StopKeyboardMonitoring() {
|
| - if (!io_task_runner_->BelongsToCurrentThread()) {
|
| - io_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&UserInputMonitorLinux::StopMonitor,
|
| - base::Unretained(this),
|
| - KEYBOARD_EVENT));
|
| - return;
|
| - }
|
| - StopMonitor(KEYBOARD_EVENT);
|
| +void UserInputMonitorLinux::Core::StopKeyboardMonitoring() {
|
| + io_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &Core::StopMonitor, weak_factory_.GetWeakPtr(), KEYBOARD_EVENT));
|
| }
|
|
|
| -void UserInputMonitorLinux::StartMonitor(EventType type) {
|
| +void UserInputMonitorLinux::Core::StartMonitor(EventType type) {
|
| DCHECK(io_task_runner_->BelongsToCurrentThread());
|
|
|
| if (type == KEYBOARD_EVENT)
|
| @@ -222,7 +252,7 @@ void UserInputMonitorLinux::StartMonitor(EventType type) {
|
|
|
| if (!XRecordEnableContextAsync(x_record_display_,
|
| x_record_context_,
|
| - &UserInputMonitorLinux::ProcessReply,
|
| + &Core::ProcessReply,
|
| reinterpret_cast<XPointer>(this))) {
|
| LOG(ERROR) << "XRecordEnableContextAsync failed.";
|
| return;
|
| @@ -248,7 +278,7 @@ void UserInputMonitorLinux::StartMonitor(EventType type) {
|
| OnFileCanReadWithoutBlocking(ConnectionNumber(x_record_display_));
|
| }
|
|
|
| -void UserInputMonitorLinux::StopMonitor(EventType type) {
|
| +void UserInputMonitorLinux::Core::StopMonitor(EventType type) {
|
| DCHECK(io_task_runner_->BelongsToCurrentThread());
|
|
|
| if (x_record_range_[type]) {
|
| @@ -278,7 +308,7 @@ void UserInputMonitorLinux::StopMonitor(EventType type) {
|
| }
|
| }
|
|
|
| -void UserInputMonitorLinux::OnFileCanReadWithoutBlocking(int fd) {
|
| +void UserInputMonitorLinux::Core::OnFileCanReadWithoutBlocking(int fd) {
|
| DCHECK(io_task_runner_->BelongsToCurrentThread());
|
| XEvent event;
|
| // Fetch pending events if any.
|
| @@ -287,16 +317,16 @@ void UserInputMonitorLinux::OnFileCanReadWithoutBlocking(int fd) {
|
| }
|
| }
|
|
|
| -void UserInputMonitorLinux::OnFileCanWriteWithoutBlocking(int fd) {
|
| +void UserInputMonitorLinux::Core::OnFileCanWriteWithoutBlocking(int fd) {
|
| NOTREACHED();
|
| }
|
|
|
| -void UserInputMonitorLinux::ProcessXEvent(xEvent* event) {
|
| +void UserInputMonitorLinux::Core::ProcessXEvent(xEvent* event) {
|
| DCHECK(io_task_runner_->BelongsToCurrentThread());
|
| if (event->u.u.type == MotionNotify) {
|
| SkIPoint position(SkIPoint::Make(event->u.keyButtonPointer.rootX,
|
| event->u.keyButtonPointer.rootY));
|
| - OnMouseEvent(position);
|
| + mouse_listeners_->Notify(&MouseEventListener::OnMouseMoved, position);
|
| } else {
|
| ui::EventType type;
|
| if (event->u.u.type == KeyPress) {
|
| @@ -315,15 +345,48 @@ void UserInputMonitorLinux::ProcessXEvent(xEvent* event) {
|
| }
|
|
|
| // static
|
| -void UserInputMonitorLinux::ProcessReply(XPointer self,
|
| - XRecordInterceptData* data) {
|
| +void UserInputMonitorLinux::Core::ProcessReply(XPointer self,
|
| + XRecordInterceptData* data) {
|
| if (data->category == XRecordFromServer) {
|
| xEvent* event = reinterpret_cast<xEvent*>(data->data);
|
| - reinterpret_cast<UserInputMonitorLinux*>(self)->ProcessXEvent(event);
|
| + reinterpret_cast<Core*>(self)->ProcessXEvent(event);
|
| }
|
| XRecordFreeData(data);
|
| }
|
|
|
| +//
|
| +// Implementation of UserInputMonitorLinux.
|
| +//
|
| +
|
| +UserInputMonitorLinux::UserInputMonitorLinux(
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
|
| + : core_(new Core(io_task_runner)) {}
|
| +
|
| +UserInputMonitorLinux::~UserInputMonitorLinux() {
|
| + if (!core_->io_task_runner()->DeleteSoon(FROM_HERE, core_))
|
| + delete core_;
|
| +}
|
| +
|
| +void UserInputMonitorLinux::AddMouseListener(MouseEventListener* listener) {
|
| + core_->AddMouseListener(listener);
|
| +}
|
| +
|
| +void UserInputMonitorLinux::RemoveMouseListener(MouseEventListener* listener) {
|
| + core_->RemoveMouseListener(listener);
|
| +}
|
| +
|
| +size_t UserInputMonitorLinux::GetKeyPressCount() const {
|
| + return core_->GetKeyPressCount();
|
| +}
|
| +
|
| +void UserInputMonitorLinux::StartKeyboardMonitoring() {
|
| + core_->StartKeyboardMonitoring();
|
| +}
|
| +
|
| +void UserInputMonitorLinux::StopKeyboardMonitoring() {
|
| + core_->StopKeyboardMonitoring();
|
| +}
|
| +
|
| } // namespace
|
|
|
| scoped_ptr<UserInputMonitor> UserInputMonitor::Create(
|
|
|