summaryrefslogtreecommitdiffstats
path: root/media/base/user_input_monitor_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/base/user_input_monitor_linux.cc')
-rw-r--r--media/base/user_input_monitor_linux.cc202
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);
}