summaryrefslogtreecommitdiffstats
path: root/media/base/user_input_monitor_linux.cc
diff options
context:
space:
mode:
authorjiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-14 21:28:11 +0000
committerjiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-14 21:28:11 +0000
commita8399162b23412192248fbb6895d93f09eabc440 (patch)
tree59d494fc77bd8de0a3f532be64a65e92f5935c33 /media/base/user_input_monitor_linux.cc
parent3693a5125ee590c9d6324c6306ec65d48e39feed (diff)
downloadchromium_src-a8399162b23412192248fbb6895d93f09eabc440.zip
chromium_src-a8399162b23412192248fbb6895d93f09eabc440.tar.gz
chromium_src-a8399162b23412192248fbb6895d93f09eabc440.tar.bz2
Adds the UserInputMonitor implementation for Windows.
BUG=274623 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=223223 Review URL: https://chromiumcodereview.appspot.com/23702008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223260 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/user_input_monitor_linux.cc')
-rw-r--r--media/base/user_input_monitor_linux.cc214
1 files changed, 120 insertions, 94 deletions
diff --git a/media/base/user_input_monitor_linux.cc b/media/base/user_input_monitor_linux.cc
index 196b4e7..138de0a 100644
--- a/media/base/user_input_monitor_linux.cc
+++ b/media/base/user_input_monitor_linux.cc
@@ -15,10 +15,12 @@
#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/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,32 +34,28 @@
namespace media {
namespace {
-class UserInputMonitorLinux : public UserInputMonitor ,
- public base::MessagePumpLibevent::Watcher {
+// This is the actual implementation of event monitoring. It's separated from
+// UserInputMonitorLinux since it needs to be deleted on the IO thread.
+class UserInputMonitorLinuxCore
+ : public base::MessagePumpLibevent::Watcher,
+ public base::SupportsWeakPtr<UserInputMonitorLinuxCore> {
public:
- 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
};
- virtual void StartMouseMonitoring() OVERRIDE;
- virtual void StopMouseMonitoring() OVERRIDE;
- virtual void StartKeyboardMonitoring() OVERRIDE;
- virtual void StopKeyboardMonitoring() OVERRIDE;
+ explicit UserInputMonitorLinuxCore(
+ const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
+ const scoped_refptr<UserInputMonitor::MouseListenerList>&
+ mouse_listeners);
+ virtual ~UserInputMonitorLinuxCore();
- //
- // The following methods must be called on the IO thread.
- //
+ size_t GetKeyPressCount() const;
void StartMonitor(EventType type);
void StopMonitor(EventType type);
+ private:
// base::MessagePumpLibevent::Watcher interface.
virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
@@ -66,93 +64,70 @@ class UserInputMonitorLinux : public UserInputMonitor ,
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<ObserverListThreadSafe<UserInputMonitor::MouseEventListener> >
+ mouse_listeners_;
//
// The following members should only be accessed on the IO thread.
//
base::MessagePumpLibevent::FileDescriptorWatcher controller_;
- Display* display_;
+ Display* x_control_display_;
Display* x_record_display_;
XRecordRange* x_record_range_[2];
XRecordContext x_record_context_;
KeyboardEventCounter counter_;
+ DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinuxCore);
+};
+
+class UserInputMonitorLinux : public UserInputMonitor {
+ public:
+ explicit UserInputMonitorLinux(
+ const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
+ virtual ~UserInputMonitorLinux();
+
+ // Public UserInputMonitor overrides.
+ virtual size_t GetKeyPressCount() const OVERRIDE;
+
+ private:
+ // Private UserInputMonitor overrides.
+ virtual void StartKeyboardMonitoring() OVERRIDE;
+ virtual void StopKeyboardMonitoring() OVERRIDE;
+ virtual void StartMouseMonitoring() OVERRIDE;
+ virtual void StopMouseMonitoring() OVERRIDE;
+
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+ UserInputMonitorLinuxCore* core_;
+
DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinux);
};
-UserInputMonitorLinux::UserInputMonitorLinux(
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
+UserInputMonitorLinuxCore::UserInputMonitorLinuxCore(
+ const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
+ const scoped_refptr<UserInputMonitor::MouseListenerList>& mouse_listeners)
: io_task_runner_(io_task_runner),
- display_(NULL),
+ mouse_listeners_(mouse_listeners),
+ x_control_display_(NULL),
x_record_display_(NULL),
x_record_context_(0) {
x_record_range_[0] = NULL;
x_record_range_[1] = NULL;
}
-UserInputMonitorLinux::~UserInputMonitorLinux() {
- DCHECK(!display_);
+UserInputMonitorLinuxCore::~UserInputMonitorLinuxCore() {
+ DCHECK(!x_control_display_);
DCHECK(!x_record_display_);
DCHECK(!x_record_range_[0]);
DCHECK(!x_record_range_[1]);
DCHECK(!x_record_context_);
}
-size_t UserInputMonitorLinux::GetKeyPressCount() const {
+size_t UserInputMonitorLinuxCore::GetKeyPressCount() const {
return counter_.GetKeyPressCount();
}
-void UserInputMonitorLinux::StartMouseMonitoring() {
- 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() {
- 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() {
- 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() {
- 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::StartMonitor(EventType type) {
+void UserInputMonitorLinuxCore::StartMonitor(EventType type) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
if (type == KEYBOARD_EVENT)
@@ -163,19 +138,20 @@ void UserInputMonitorLinux::StartMonitor(EventType type) {
// and both channels are used from a separate thread, we'll need to duplicate
// them with something like the following:
// XOpenDisplay(DisplayString(display));
- if (!display_)
- display_ = XOpenDisplay(NULL);
+ if (!x_control_display_)
+ x_control_display_ = XOpenDisplay(NULL);
if (!x_record_display_)
x_record_display_ = XOpenDisplay(NULL);
- if (!display_ || !x_record_display_) {
+ if (!x_control_display_ || !x_record_display_) {
LOG(ERROR) << "Couldn't open X display";
return;
}
int xr_opcode, xr_event, xr_error;
- if (!XQueryExtension(display_, "RECORD", &xr_opcode, &xr_event, &xr_error)) {
+ if (!XQueryExtension(
+ x_control_display_, "RECORD", &xr_opcode, &xr_event, &xr_error)) {
LOG(ERROR) << "X Record extension not available.";
return;
}
@@ -198,8 +174,8 @@ void UserInputMonitorLinux::StartMonitor(EventType type) {
}
if (x_record_context_) {
- XRecordDisableContext(display_, x_record_context_);
- XFlush(display_);
+ XRecordDisableContext(x_control_display_, x_record_context_);
+ XFlush(x_control_display_);
XRecordFreeContext(x_record_display_, x_record_context_);
x_record_context_ = 0;
}
@@ -222,7 +198,7 @@ void UserInputMonitorLinux::StartMonitor(EventType type) {
if (!XRecordEnableContextAsync(x_record_display_,
x_record_context_,
- &UserInputMonitorLinux::ProcessReply,
+ &UserInputMonitorLinuxCore::ProcessReply,
reinterpret_cast<XPointer>(this))) {
LOG(ERROR) << "XRecordEnableContextAsync failed.";
return;
@@ -248,7 +224,7 @@ void UserInputMonitorLinux::StartMonitor(EventType type) {
OnFileCanReadWithoutBlocking(ConnectionNumber(x_record_display_));
}
-void UserInputMonitorLinux::StopMonitor(EventType type) {
+void UserInputMonitorLinuxCore::StopMonitor(EventType type) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
if (x_record_range_[type]) {
@@ -261,8 +237,8 @@ void UserInputMonitorLinux::StopMonitor(EventType type) {
// Context must be disabled via the control channel because we can't send
// any X protocol traffic over the data channel while it's recording.
if (x_record_context_) {
- XRecordDisableContext(display_, x_record_context_);
- XFlush(display_);
+ XRecordDisableContext(x_control_display_, x_record_context_);
+ XFlush(x_control_display_);
XRecordFreeContext(x_record_display_, x_record_context_);
x_record_context_ = 0;
@@ -271,14 +247,14 @@ void UserInputMonitorLinux::StopMonitor(EventType type) {
XCloseDisplay(x_record_display_);
x_record_display_ = NULL;
}
- if (display_) {
- XCloseDisplay(display_);
- display_ = NULL;
+ if (x_control_display_) {
+ XCloseDisplay(x_control_display_);
+ x_control_display_ = NULL;
}
}
}
-void UserInputMonitorLinux::OnFileCanReadWithoutBlocking(int fd) {
+void UserInputMonitorLinuxCore::OnFileCanReadWithoutBlocking(int fd) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
XEvent event;
// Fetch pending events if any.
@@ -287,16 +263,17 @@ void UserInputMonitorLinux::OnFileCanReadWithoutBlocking(int fd) {
}
}
-void UserInputMonitorLinux::OnFileCanWriteWithoutBlocking(int fd) {
+void UserInputMonitorLinuxCore::OnFileCanWriteWithoutBlocking(int fd) {
NOTREACHED();
}
-void UserInputMonitorLinux::ProcessXEvent(xEvent* event) {
+void UserInputMonitorLinuxCore::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(
+ &UserInputMonitor::MouseEventListener::OnMouseMoved, position);
} else {
ui::EventType type;
if (event->u.u.type == KeyPress) {
@@ -308,22 +285,71 @@ void UserInputMonitorLinux::ProcessXEvent(xEvent* event) {
return;
}
- KeySym key_sym = XkbKeycodeToKeysym(display_, event->u.u.detail, 0, 0);
+ KeySym key_sym =
+ XkbKeycodeToKeysym(x_control_display_, event->u.u.detail, 0, 0);
ui::KeyboardCode key_code = ui::KeyboardCodeFromXKeysym(key_sym);
counter_.OnKeyboardEvent(type, key_code);
}
}
// static
-void UserInputMonitorLinux::ProcessReply(XPointer self,
- XRecordInterceptData* data) {
+void UserInputMonitorLinuxCore::ProcessReply(XPointer self,
+ XRecordInterceptData* data) {
if (data->category == XRecordFromServer) {
xEvent* event = reinterpret_cast<xEvent*>(data->data);
- reinterpret_cast<UserInputMonitorLinux*>(self)->ProcessXEvent(event);
+ reinterpret_cast<UserInputMonitorLinuxCore*>(self)->ProcessXEvent(event);
}
XRecordFreeData(data);
}
+//
+// Implementation of UserInputMonitorLinux.
+//
+
+UserInputMonitorLinux::UserInputMonitorLinux(
+ const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
+ : io_task_runner_(io_task_runner),
+ core_(new UserInputMonitorLinuxCore(io_task_runner, mouse_listeners())) {}
+
+UserInputMonitorLinux::~UserInputMonitorLinux() {
+ if (!io_task_runner_->DeleteSoon(FROM_HERE, core_))
+ delete core_;
+}
+
+size_t UserInputMonitorLinux::GetKeyPressCount() const {
+ return core_->GetKeyPressCount();
+}
+
+void UserInputMonitorLinux::StartKeyboardMonitoring() {
+ io_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&UserInputMonitorLinuxCore::StartMonitor,
+ core_->AsWeakPtr(),
+ UserInputMonitorLinuxCore::KEYBOARD_EVENT));
+}
+
+void UserInputMonitorLinux::StopKeyboardMonitoring() {
+ io_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&UserInputMonitorLinuxCore::StopMonitor,
+ core_->AsWeakPtr(),
+ UserInputMonitorLinuxCore::KEYBOARD_EVENT));
+}
+
+void UserInputMonitorLinux::StartMouseMonitoring() {
+ io_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&UserInputMonitorLinuxCore::StartMonitor,
+ core_->AsWeakPtr(),
+ UserInputMonitorLinuxCore::MOUSE_EVENT));
+}
+
+void UserInputMonitorLinux::StopMouseMonitoring() {
+ io_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&UserInputMonitorLinuxCore::StopMonitor,
+ core_->AsWeakPtr(),
+ UserInputMonitorLinuxCore::MOUSE_EVENT));
+}
+
} // namespace
scoped_ptr<UserInputMonitor> UserInputMonitor::Create(