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

Unified Diff: media/base/user_input_monitor_linux.cc

Issue 23702008: Adds the UserInputMonitor implementation for Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 3 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: 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..76369f182d06c442d1a065730e6d7778e34848b2 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,60 +132,51 @@ 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) {
+ StartMonitor(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) {
+ StopMonitor(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;
- }
+void UserInputMonitorLinux::Core::StartKeyboardMonitoring() {
StartMonitor(KEYBOARD_EVENT);
}
-void UserInputMonitorLinux::StopKeyboardMonitoring() {
+void UserInputMonitorLinux::Core::StopKeyboardMonitoring() {
+ StopMonitor(KEYBOARD_EVENT);
+}
+
+void UserInputMonitorLinux::Core::StartMonitor(EventType type) {
if (!io_task_runner_->BelongsToCurrentThread()) {
io_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&UserInputMonitorLinux::StopMonitor,
- base::Unretained(this),
- KEYBOARD_EVENT));
+ base::Bind(&Core::StartMonitor, weak_factory_.GetWeakPtr(), type));
return;
}
- StopMonitor(KEYBOARD_EVENT);
-}
-
-void UserInputMonitorLinux::StartMonitor(EventType type) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
if (type == KEYBOARD_EVENT)
counter_.Reset();
@@ -222,7 +245,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,8 +271,13 @@ void UserInputMonitorLinux::StartMonitor(EventType type) {
OnFileCanReadWithoutBlocking(ConnectionNumber(x_record_display_));
}
-void UserInputMonitorLinux::StopMonitor(EventType type) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
+void UserInputMonitorLinux::Core::StopMonitor(EventType type) {
+ if (!io_task_runner_->BelongsToCurrentThread()) {
+ io_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&Core::StopMonitor, weak_factory_.GetWeakPtr(), type));
+ return;
+ }
if (x_record_range_[type]) {
XFree(x_record_range_[type]);
@@ -278,7 +306,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 +315,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 +343,42 @@ 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(
DaleCurtis 2013/09/06 21:51:08 Blank line between each method.
jiayl 2013/09/06 22:43:30 Done.
+ 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(

Powered by Google App Engine
This is Rietveld 408576698