diff options
Diffstat (limited to 'media/base/user_input_monitor_linux.cc')
-rw-r--r-- | media/base/user_input_monitor_linux.cc | 202 |
1 files changed, 100 insertions, 102 deletions
diff --git a/media/base/user_input_monitor_linux.cc b/media/base/user_input_monitor_linux.cc index ee1b774..196b4e7 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); } |