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 ee1b7749fd213569d2dbf2db8803a60b0b4b0d06..196b4e7407836319eb72af8b5298d0aebf84bc8e 100644 |
--- a/media/base/user_input_monitor_linux.cc |
+++ b/media/base/user_input_monitor_linux.cc |
@@ -15,12 +15,11 @@ |
#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/posix/eintr_wrapper.h" |
#include "base/single_thread_task_runner.h" |
-#include "base/threading/non_thread_safe.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" |
@@ -31,73 +30,54 @@ |
#include <X11/extensions/record.h> |
namespace media { |
- |
namespace { |
-class UserInputMonitorLinux : public base::NonThreadSafe, |
- public UserInputMonitor { |
+class UserInputMonitorLinux : public UserInputMonitor , |
+ public base::MessagePumpLibevent::Watcher { |
public: |
- UserInputMonitorLinux( |
+ explicit UserInputMonitorLinux( |
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner); |
virtual ~UserInputMonitorLinux(); |
+ virtual size_t GetKeyPressCount() const OVERRIDE; |
+ |
private: |
enum EventType { |
MOUSE_EVENT, |
KEYBOARD_EVENT |
}; |
- // The actual implementation resides in UserInputMonitorLinux::Core class. |
- // Must be called on the io_task_runner thread. |
- class Core : public base::RefCountedThreadSafe<Core>, |
- public base::MessagePumpLibevent::Watcher { |
- public: |
- typedef const base::Callback<void(const SkIPoint&)> MouseCallback; |
- typedef base::Callback<void(ui::EventType event, ui::KeyboardCode key_code)> |
- KeyboardCallback; |
- Core(const MouseCallback& mouse_callback, |
- const KeyboardCallback& keyboard_callback); |
- |
- void StartMonitor(EventType type); |
- void StopMonitor(EventType type); |
- |
- private: |
- friend class base::RefCountedThreadSafe<Core>; |
- virtual ~Core(); |
- |
- // base::MessagePumpLibevent::Watcher interface. |
- virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; |
- virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; |
- |
- // Processes key and mouse events. |
- void ProcessXEvent(xEvent* event); |
- static void ProcessReply(XPointer self, XRecordInterceptData* data); |
- |
- // Used to receive base::MessagePumpLibevent::Watcher events. |
- base::MessagePumpLibevent::FileDescriptorWatcher controller_; |
- |
- Display* display_; |
- Display* x_record_display_; |
- XRecordRange* x_record_range_[2]; |
- XRecordContext x_record_context_; |
- base::Callback<void(const SkIPoint&)> mouse_callback_; |
- base::Callback<void(ui::EventType event, ui::KeyboardCode key_code)> |
- keyboard_callback_; |
- |
- DISALLOW_COPY_AND_ASSIGN(Core); |
- }; |
- |
virtual void StartMouseMonitoring() OVERRIDE; |
virtual void StopMouseMonitoring() OVERRIDE; |
virtual void StartKeyboardMonitoring() OVERRIDE; |
virtual void StopKeyboardMonitoring() OVERRIDE; |
- void OnMouseEvent(const SkIPoint& position); |
- void OnKeyboardEvent(ui::EventType event, ui::KeyboardCode key_code); |
+ // |
+ // The following methods must be called on the IO thread. |
+ // |
+ void StartMonitor(EventType type); |
+ void StopMonitor(EventType type); |
+ |
+ // base::MessagePumpLibevent::Watcher interface. |
+ virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; |
+ virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; |
+ |
+ // Processes key and mouse events. |
+ void ProcessXEvent(xEvent* event); |
+ static void ProcessReply(XPointer self, XRecordInterceptData* data); |
// Task runner on which X Window events are received. |
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; |
- scoped_refptr<Core> core_; |
+ |
+ // |
+ // The following members should only be accessed on the IO thread. |
+ // |
+ base::MessagePumpLibevent::FileDescriptorWatcher controller_; |
+ Display* display_; |
+ Display* x_record_display_; |
+ XRecordRange* x_record_range_[2]; |
+ XRecordContext x_record_context_; |
+ KeyboardEventCounter counter_; |
DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinux); |
}; |
@@ -105,63 +85,79 @@ class UserInputMonitorLinux : public base::NonThreadSafe, |
UserInputMonitorLinux::UserInputMonitorLinux( |
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
: io_task_runner_(io_task_runner), |
- core_(new Core(base::Bind(&UserInputMonitorLinux::OnMouseEvent, |
- base::Unretained(this)), |
- base::Bind(&UserInputMonitorLinux::OnKeyboardEvent, |
- base::Unretained(this)))) {} |
+ display_(NULL), |
+ x_record_display_(NULL), |
+ x_record_context_(0) { |
+ x_record_range_[0] = NULL; |
+ x_record_range_[1] = NULL; |
+} |
-UserInputMonitorLinux::~UserInputMonitorLinux() {} |
+UserInputMonitorLinux::~UserInputMonitorLinux() { |
+ DCHECK(!display_); |
+ DCHECK(!x_record_display_); |
+ DCHECK(!x_record_range_[0]); |
+ DCHECK(!x_record_range_[1]); |
+ DCHECK(!x_record_context_); |
+} |
+ |
+size_t UserInputMonitorLinux::GetKeyPressCount() const { |
+ return counter_.GetKeyPressCount(); |
+} |
void UserInputMonitorLinux::StartMouseMonitoring() { |
- io_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&Core::StartMonitor, core_.get(), MOUSE_EVENT)); |
+ if (!io_task_runner_->BelongsToCurrentThread()) { |
+ io_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&UserInputMonitorLinux::StartMonitor, |
+ base::Unretained(this), |
+ MOUSE_EVENT)); |
+ return; |
+ } |
+ StartMonitor(MOUSE_EVENT); |
} |
void UserInputMonitorLinux::StopMouseMonitoring() { |
- io_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&Core::StopMonitor, core_.get(), MOUSE_EVENT)); |
+ if (!io_task_runner_->BelongsToCurrentThread()) { |
+ io_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&UserInputMonitorLinux::StopMonitor, |
+ base::Unretained(this), |
+ MOUSE_EVENT)); |
+ return; |
+ } |
+ StopMonitor(MOUSE_EVENT); |
} |
void UserInputMonitorLinux::StartKeyboardMonitoring() { |
- io_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&Core::StartMonitor, core_.get(), KEYBOARD_EVENT)); |
+ 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::StopKeyboardMonitoring() { |
- io_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&Core::StopMonitor, core_.get(), KEYBOARD_EVENT)); |
+ 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::OnMouseEvent(const SkIPoint& position) { |
- UserInputMonitor::OnMouseEvent(position); |
-} |
+void UserInputMonitorLinux::StartMonitor(EventType type) { |
+ DCHECK(io_task_runner_->BelongsToCurrentThread()); |
-void UserInputMonitorLinux::OnKeyboardEvent(ui::EventType event, |
- ui::KeyboardCode key_code) { |
- UserInputMonitor::OnKeyboardEvent(event, key_code); |
-} |
+ if (type == KEYBOARD_EVENT) |
+ counter_.Reset(); |
-UserInputMonitorLinux::Core::Core(const MouseCallback& mouse_callback, |
- const KeyboardCallback& keyboard_callback) |
- : display_(NULL), |
- x_record_display_(NULL), |
- x_record_context_(0), |
- mouse_callback_(mouse_callback), |
- keyboard_callback_(keyboard_callback) { |
- x_record_range_[0] = NULL; |
- x_record_range_[1] = NULL; |
-} |
- |
-UserInputMonitorLinux::Core::~Core() { |
- DCHECK(!display_); |
- DCHECK(!x_record_display_); |
- DCHECK(!x_record_range_[0]); |
- DCHECK(!x_record_range_[1]); |
- DCHECK(!x_record_context_); |
-} |
- |
-void UserInputMonitorLinux::Core::StartMonitor(EventType type) { |
- DCHECK(base::MessageLoopForIO::current()); |
// TODO(jamiewalch): We should pass the display in. At that point, since |
// XRecord needs a private connection to the X Server for its data channel |
// and both channels are used from a separate thread, we'll need to duplicate |
@@ -226,7 +222,7 @@ void UserInputMonitorLinux::Core::StartMonitor(EventType type) { |
if (!XRecordEnableContextAsync(x_record_display_, |
x_record_context_, |
- &Core::ProcessReply, |
+ &UserInputMonitorLinux::ProcessReply, |
reinterpret_cast<XPointer>(this))) { |
LOG(ERROR) << "XRecordEnableContextAsync failed."; |
return; |
@@ -252,8 +248,8 @@ void UserInputMonitorLinux::Core::StartMonitor(EventType type) { |
OnFileCanReadWithoutBlocking(ConnectionNumber(x_record_display_)); |
} |
-void UserInputMonitorLinux::Core::StopMonitor(EventType type) { |
- DCHECK(base::MessageLoopForIO::current()); |
+void UserInputMonitorLinux::StopMonitor(EventType type) { |
+ DCHECK(io_task_runner_->BelongsToCurrentThread()); |
if (x_record_range_[type]) { |
XFree(x_record_range_[type]); |
@@ -282,8 +278,8 @@ void UserInputMonitorLinux::Core::StopMonitor(EventType type) { |
} |
} |
-void UserInputMonitorLinux::Core::OnFileCanReadWithoutBlocking(int fd) { |
- DCHECK(base::MessageLoopForIO::current()); |
+void UserInputMonitorLinux::OnFileCanReadWithoutBlocking(int fd) { |
+ DCHECK(io_task_runner_->BelongsToCurrentThread()); |
XEvent event; |
// Fetch pending events if any. |
while (XPending(x_record_display_)) { |
@@ -291,15 +287,16 @@ void UserInputMonitorLinux::Core::OnFileCanReadWithoutBlocking(int fd) { |
} |
} |
-void UserInputMonitorLinux::Core::OnFileCanWriteWithoutBlocking(int fd) { |
+void UserInputMonitorLinux::OnFileCanWriteWithoutBlocking(int fd) { |
NOTREACHED(); |
} |
-void UserInputMonitorLinux::Core::ProcessXEvent(xEvent* event) { |
+void UserInputMonitorLinux::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)); |
- mouse_callback_.Run(position); |
+ OnMouseEvent(position); |
} else { |
ui::EventType type; |
if (event->u.u.type == KeyPress) { |
@@ -308,20 +305,21 @@ void UserInputMonitorLinux::Core::ProcessXEvent(xEvent* event) { |
type = ui::ET_KEY_RELEASED; |
} else { |
NOTREACHED(); |
+ return; |
} |
KeySym key_sym = XkbKeycodeToKeysym(display_, event->u.u.detail, 0, 0); |
ui::KeyboardCode key_code = ui::KeyboardCodeFromXKeysym(key_sym); |
- keyboard_callback_.Run(type, key_code); |
+ counter_.OnKeyboardEvent(type, key_code); |
} |
} |
// static |
-void UserInputMonitorLinux::Core::ProcessReply(XPointer self, |
- XRecordInterceptData* data) { |
+void UserInputMonitorLinux::ProcessReply(XPointer self, |
+ XRecordInterceptData* data) { |
if (data->category == XRecordFromServer) { |
xEvent* event = reinterpret_cast<xEvent*>(data->data); |
- reinterpret_cast<Core*>(self)->ProcessXEvent(event); |
+ reinterpret_cast<UserInputMonitorLinux*>(self)->ProcessXEvent(event); |
} |
XRecordFreeData(data); |
} |