diff options
author | jiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-28 03:43:16 +0000 |
---|---|---|
committer | jiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-28 03:43:16 +0000 |
commit | 2354f76ddf3fbb0ccfa88c611d1d7ad19ada3941 (patch) | |
tree | 6d7d8f1d0cdb3803a0e6db45e1ff5c2797519582 | |
parent | d45dac89d8166feec63932c9b9c91ca967a4e18b (diff) | |
download | chromium_src-2354f76ddf3fbb0ccfa88c611d1d7ad19ada3941.zip chromium_src-2354f76ddf3fbb0ccfa88c611d1d7ad19ada3941.tar.gz chromium_src-2354f76ddf3fbb0ccfa88c611d1d7ad19ada3941.tar.bz2 |
Adds key press detection for Mac by detecting the increase of key down event count in audio callback.
CGEventSourceCounterForEventType does not count auto-repeated key presses, so we get exactly the same behavior as the webrtc impl.
The CGEventSourceCounterForEventType call takes 2-3 microseconds on a Macbook Pro.
BUG=274623
Review URL: https://chromiumcodereview.appspot.com/22801007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@219896 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | media/audio/audio_input_controller.cc | 33 | ||||
-rw-r--r-- | media/audio/audio_input_controller.h | 12 | ||||
-rw-r--r-- | media/base/keyboard_event_counter.cc | 41 | ||||
-rw-r--r-- | media/base/keyboard_event_counter.h | 48 | ||||
-rw-r--r-- | media/base/user_input_monitor.cc | 45 | ||||
-rw-r--r-- | media/base/user_input_monitor.h | 44 | ||||
-rw-r--r-- | media/base/user_input_monitor_linux.cc | 202 | ||||
-rw-r--r-- | media/base/user_input_monitor_mac.cc | 57 | ||||
-rw-r--r-- | media/base/user_input_monitor_mac.mm | 16 | ||||
-rw-r--r-- | media/media.gyp | 6 |
10 files changed, 307 insertions, 197 deletions
diff --git a/media/audio/audio_input_controller.cc b/media/audio/audio_input_controller.cc index f7747b9..d701337 100644 --- a/media/audio/audio_input_controller.cc +++ b/media/audio/audio_input_controller.cc @@ -8,6 +8,7 @@ #include "base/threading/thread_restrictions.h" #include "media/base/limits.h" #include "media/base/scoped_histogram_timer.h" +#include "media/base/user_input_monitor.h" namespace { const int kMaxInputChannels = 2; @@ -46,7 +47,7 @@ AudioInputController::AudioInputController(EventHandler* handler, sync_writer_(sync_writer), max_volume_(0.0), user_input_monitor_(user_input_monitor), - key_pressed_(false) { + prev_key_down_count_(0) { DCHECK(creator_loop_.get()); } @@ -218,6 +219,11 @@ void AudioInputController::DoCreateForStream( state_ = kCreated; handler_->OnCreated(this); + + if (user_input_monitor_) { + user_input_monitor_->EnableKeyPressMonitoring(); + prev_key_down_count_ = user_input_monitor_->GetKeyPressCount(); + } } void AudioInputController::DoRecord() { @@ -240,9 +246,6 @@ void AudioInputController::DoRecord() { stream_->Start(this); handler_->OnRecording(this); - - if (user_input_monitor_) - user_input_monitor_->AddKeyStrokeListener(this); } void AudioInputController::DoClose() { @@ -263,7 +266,7 @@ void AudioInputController::DoClose() { state_ = kClosed; if (user_input_monitor_) - user_input_monitor_->RemoveKeyStrokeListener(this); + user_input_monitor_->DisableKeyPressMonitoring(); } } @@ -330,16 +333,23 @@ void AudioInputController::DoCheckForNoData() { base::Unretained(this))); } -void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, - uint32 size, uint32 hardware_delay_bytes, +void AudioInputController::OnData(AudioInputStream* stream, + const uint8* data, + uint32 size, + uint32 hardware_delay_bytes, double volume) { - bool key_pressed = false; { base::AutoLock auto_lock(lock_); if (state_ != kRecording) return; + } - std::swap(key_pressed, key_pressed_); + bool key_pressed = false; + if (user_input_monitor_) { + size_t current_count = user_input_monitor_->GetKeyPressCount(); + key_pressed = current_count != prev_key_down_count_; + prev_key_down_count_ = current_count; + DVLOG_IF(6, key_pressed) << "Detected keypress."; } // Mark data as active to ensure that the periodic calls to @@ -369,11 +379,6 @@ void AudioInputController::OnError(AudioInputStream* stream) { &AudioInputController::DoReportError, this)); } -void AudioInputController::OnKeyStroke() { - base::AutoLock auto_lock(lock_); - key_pressed_ = true; -} - void AudioInputController::DoStopCloseAndClearStream( base::WaitableEvent* done) { DCHECK(message_loop_->BelongsToCurrentThread()); diff --git a/media/audio/audio_input_controller.h b/media/audio/audio_input_controller.h index 6be4821..6b40459 100644 --- a/media/audio/audio_input_controller.h +++ b/media/audio/audio_input_controller.h @@ -16,7 +16,6 @@ #include "base/timer/timer.h" #include "media/audio/audio_io.h" #include "media/audio/audio_manager_base.h" -#include "media/base/user_input_monitor.h" // An AudioInputController controls an AudioInputStream and records data // from this input stream. The two main methods are Record() and Close() and @@ -73,10 +72,11 @@ // namespace media { +class UserInputMonitor; + class MEDIA_EXPORT AudioInputController : public base::RefCountedThreadSafe<AudioInputController>, - public AudioInputStream::AudioInputCallback, - public UserInputMonitor::KeyStrokeListener { + public AudioInputStream::AudioInputCallback { public: // An event handler that receives events from the AudioInputController. The // following methods are all called on the audio thread. @@ -203,9 +203,6 @@ class MEDIA_EXPORT AudioInputController bool LowLatencyMode() const { return sync_writer_ != NULL; } - // Impl of KeyStrokeListener. - virtual void OnKeyStroke() OVERRIDE; - protected: friend class base::RefCountedThreadSafe<AudioInputController>; @@ -287,8 +284,7 @@ class MEDIA_EXPORT AudioInputController UserInputMonitor* user_input_monitor_; - // True if any key has been pressed after the last OnData call. - bool key_pressed_; + size_t prev_key_down_count_; DISALLOW_COPY_AND_ASSIGN(AudioInputController); }; diff --git a/media/base/keyboard_event_counter.cc b/media/base/keyboard_event_counter.cc new file mode 100644 index 0000000..a4ae109 --- /dev/null +++ b/media/base/keyboard_event_counter.cc @@ -0,0 +1,41 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/keyboard_event_counter.h" + +#include "base/atomicops.h" +#include "base/logging.h" + +namespace media { + +KeyboardEventCounter::KeyboardEventCounter() : total_key_presses_(0) {} + +KeyboardEventCounter::~KeyboardEventCounter() {} + +void KeyboardEventCounter::Reset() { + pressed_keys_.clear(); + total_key_presses_ = 0; +} + +void KeyboardEventCounter::OnKeyboardEvent(ui::EventType event, + ui::KeyboardCode key_code) { + // Updates the pressed keys and the total count of key presses. + if (event == ui::ET_KEY_PRESSED) { + if (pressed_keys_.find(key_code) != pressed_keys_.end()) + return; + pressed_keys_.insert(key_code); + base::subtle::NoBarrier_AtomicIncrement( + reinterpret_cast<base::subtle::AtomicWord*>(&total_key_presses_), 1); + } else { + DCHECK_EQ(ui::ET_KEY_RELEASED, event); + pressed_keys_.erase(key_code); + } +} + +size_t KeyboardEventCounter::GetKeyPressCount() const { + return base::subtle::NoBarrier_Load( + reinterpret_cast<const base::subtle::AtomicWord*>(&total_key_presses_)); +} + +} // namespace media diff --git a/media/base/keyboard_event_counter.h b/media/base/keyboard_event_counter.h new file mode 100644 index 0000000..c82ca59 --- /dev/null +++ b/media/base/keyboard_event_counter.h @@ -0,0 +1,48 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_KEYBOARD_EVENT_COUNTER_H_ +#define MEDIA_BASE_KEYBOARD_EVENT_COUNTER_H_ + +#include <set> + +#include "base/synchronization/lock.h" +#include "ui/base/events/event_constants.h" +#include "ui/base/keycodes/keyboard_codes.h" + +namespace media { + +// This class tracks the total number of keypresses based on the OnKeyboardEvent +// calls it receives from the client. +// Multiple key down events for the same key are counted as one keypress until +// the same key is released. +class KeyboardEventCounter { + public: + KeyboardEventCounter(); + ~KeyboardEventCounter(); + + // Resets the count to 0. Must be called on the same thread as + // OnKeyboardEvent. + void Reset(); + + // Returns the total number of keypresses since its creation or last Reset() + // call. Can be called on any thread. + size_t GetKeyPressCount() const; + + // The client should call this method on key down or key up events. + // Must be called on a single thread. + void OnKeyboardEvent(ui::EventType event, ui::KeyboardCode key_code); + + private: + // The set of keys currently held down. + std::set<ui::KeyboardCode> pressed_keys_; + + size_t total_key_presses_; + + DISALLOW_COPY_AND_ASSIGN(KeyboardEventCounter); +}; + +} // namespace media + +#endif // MEDIA_BASE_KEYBOARD_EVENT_COUNTER_H_ diff --git a/media/base/user_input_monitor.cc b/media/base/user_input_monitor.cc index 8a1f1da..34e07d8 100644 --- a/media/base/user_input_monitor.cc +++ b/media/base/user_input_monitor.cc @@ -16,9 +16,12 @@ scoped_ptr<UserInputMonitor> UserInputMonitor::Create( } #endif // DISABLE_USER_INPUT_MONITOR +UserInputMonitor::UserInputMonitor() + : monitoring_mouse_(false), key_press_counter_references_(0) {} + UserInputMonitor::~UserInputMonitor() { DCHECK(!monitoring_mouse_); - DCHECK(!monitoring_keyboard_); + DCHECK(!key_press_counter_references_); } void UserInputMonitor::AddMouseListener(MouseEventListener* listener) { @@ -30,6 +33,7 @@ void UserInputMonitor::AddMouseListener(MouseEventListener* listener) { DVLOG(2) << "Started mouse monitoring."; } } + void UserInputMonitor::RemoveMouseListener(MouseEventListener* listener) { base::AutoLock auto_lock(lock_); mouse_listeners_.RemoveObserver(listener); @@ -39,49 +43,32 @@ void UserInputMonitor::RemoveMouseListener(MouseEventListener* listener) { DVLOG(2) << "Stopped mouse monitoring."; } } -void UserInputMonitor::AddKeyStrokeListener(KeyStrokeListener* listener) { + +void UserInputMonitor::EnableKeyPressMonitoring() { base::AutoLock auto_lock(lock_); - key_stroke_listeners_.AddObserver(listener); - if (!monitoring_keyboard_) { + ++key_press_counter_references_; + if (key_press_counter_references_ == 1) { StartKeyboardMonitoring(); - monitoring_keyboard_ = true; DVLOG(2) << "Started keyboard monitoring."; } } -void UserInputMonitor::RemoveKeyStrokeListener(KeyStrokeListener* listener) { + +void UserInputMonitor::DisableKeyPressMonitoring() { base::AutoLock auto_lock(lock_); - key_stroke_listeners_.RemoveObserver(listener); - if (!key_stroke_listeners_.might_have_observers()) { + DCHECK_NE(key_press_counter_references_, 0u); + --key_press_counter_references_; + if (key_press_counter_references_ == 0) { StopKeyboardMonitoring(); - monitoring_keyboard_ = false; DVLOG(2) << "Stopped keyboard monitoring."; } } -UserInputMonitor::UserInputMonitor() - : monitoring_mouse_(false), monitoring_keyboard_(false) {} - void UserInputMonitor::OnMouseEvent(const SkIPoint& position) { base::AutoLock auto_lock(lock_); + if (!monitoring_mouse_) + return; FOR_EACH_OBSERVER( MouseEventListener, mouse_listeners_, OnMouseMoved(position)); } -void UserInputMonitor::OnKeyboardEvent(ui::EventType event, - ui::KeyboardCode key_code) { - base::AutoLock auto_lock(lock_); - // Updates the pressed keys and maybe notifies the key_stroke_listeners_. - if (event == ui::ET_KEY_PRESSED) { - if (pressed_keys_.find(key_code) != pressed_keys_.end()) - return; - pressed_keys_.insert(key_code); - DVLOG(6) << "Key stroke detected."; - FOR_EACH_OBSERVER(KeyStrokeListener, key_stroke_listeners_, OnKeyStroke()); - } else { - DCHECK_EQ(ui::ET_KEY_RELEASED, event); - DCHECK(pressed_keys_.find(key_code) != pressed_keys_.end()); - pressed_keys_.erase(key_code); - } -} - } // namespace media diff --git a/media/base/user_input_monitor.h b/media/base/user_input_monitor.h index 9eb82f3..567907c 100644 --- a/media/base/user_input_monitor.h +++ b/media/base/user_input_monitor.h @@ -5,16 +5,10 @@ #ifndef MEDIA_BASE_USER_INPUT_MONITOR_H_ #define MEDIA_BASE_USER_INPUT_MONITOR_H_ -#include <set> - -#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/synchronization/lock.h" #include "media/base/media_export.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/keycodes/keyboard_codes.h" struct SkIPoint; @@ -28,6 +22,8 @@ namespace media { // Thread safe. The thread on which the listenters are called is not guaranteed. // The callers should not perform expensive/blocking tasks in the callback since // it might be called on the browser UI/IO threads. +// The object must outlive the browser UI/IO threads to make sure the callbacks +// will not access a deleted object. class MEDIA_EXPORT UserInputMonitor { public: // The interface to receive mouse movement events. @@ -39,18 +35,8 @@ class MEDIA_EXPORT UserInputMonitor { protected: virtual ~MouseEventListener() {} }; - // The interface to receive key stroke events. - class MEDIA_EXPORT KeyStrokeListener { - public: - // Called when any key is pressed. Called only once until the key is - // released, i.e. holding down a key for a long period will generate one - // callback just when the key is pressed down. - virtual void OnKeyStroke() = 0; - - protected: - virtual ~KeyStrokeListener() {} - }; + UserInputMonitor(); virtual ~UserInputMonitor(); // Creates a platform-specific instance of UserInputMonitor. @@ -65,16 +51,24 @@ class MEDIA_EXPORT UserInputMonitor { // destroyed. void AddMouseListener(MouseEventListener* listener); void RemoveMouseListener(MouseEventListener* listener); - void AddKeyStrokeListener(KeyStrokeListener* listener); - void RemoveKeyStrokeListener(KeyStrokeListener* listener); - protected: - UserInputMonitor(); + // A caller must call EnableKeyPressMonitoring and + // DisableKeyPressMonitoring in pair. + void EnableKeyPressMonitoring(); + void DisableKeyPressMonitoring(); + // Returns the number of keypresses. The starting point from when it is + // counted is not guaranteed, but consistent within the pair of calls of + // EnableKeyPressMonitoring and DisableKeyPressMonitoring. So a caller can + // use the difference between the values returned at two times to get the + // number of keypresses happened within that time period, but should not make + // any assumption on the initial value. + virtual size_t GetKeyPressCount() const = 0; + + protected: // Called by the platform-specific sub-classes to propagate the events to the // listeners. void OnMouseEvent(const SkIPoint& position); - void OnKeyboardEvent(ui::EventType event, ui::KeyboardCode key_code); private: virtual void StartMouseMonitoring() = 0; @@ -84,12 +78,8 @@ class MEDIA_EXPORT UserInputMonitor { base::Lock lock_; ObserverList<MouseEventListener, true> mouse_listeners_; - ObserverList<KeyStrokeListener, true> key_stroke_listeners_; bool monitoring_mouse_; - bool monitoring_keyboard_; - // The set of keys currently held down. Used for convering raw keyboard events - // into KeyStrokeListener callbacks. - std::set<ui::KeyboardCode> pressed_keys_; + size_t key_press_counter_references_; DISALLOW_COPY_AND_ASSIGN(UserInputMonitor); }; 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); } diff --git a/media/base/user_input_monitor_mac.cc b/media/base/user_input_monitor_mac.cc new file mode 100644 index 0000000..3d19134 --- /dev/null +++ b/media/base/user_input_monitor_mac.cc @@ -0,0 +1,57 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/user_input_monitor.h" + +#include <ApplicationServices/ApplicationServices.h> + +namespace media { +namespace { + +class UserInputMonitorMac : public UserInputMonitor { + public: + UserInputMonitorMac(); + virtual ~UserInputMonitorMac(); + + virtual size_t GetKeyPressCount() const OVERRIDE; + + private: + virtual void StartMouseMonitoring() OVERRIDE; + virtual void StopMouseMonitoring() OVERRIDE; + virtual void StartKeyboardMonitoring() OVERRIDE; + virtual void StopKeyboardMonitoring() OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN(UserInputMonitorMac); +}; + +UserInputMonitorMac::UserInputMonitorMac() {} + +UserInputMonitorMac::~UserInputMonitorMac() {} + +size_t UserInputMonitorMac::GetKeyPressCount() const { + // Use |kCGEventSourceStateHIDSystemState| since we only want to count + // hardware generated events. + return CGEventSourceCounterForEventType(kCGEventSourceStateHIDSystemState, + kCGEventKeyDown); +} + +// TODO(jiayl): add the impl. +void UserInputMonitorMac::StartMouseMonitoring() { NOTIMPLEMENTED(); } + +// TODO(jiayl): add the impl. +void UserInputMonitorMac::StopMouseMonitoring() { NOTIMPLEMENTED(); } + +void UserInputMonitorMac::StartKeyboardMonitoring() {} + +void UserInputMonitorMac::StopKeyboardMonitoring() {} + +} // namespace + +scoped_ptr<UserInputMonitor> UserInputMonitor::Create( + const scoped_refptr<base::SingleThreadTaskRunner>& input_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { + return scoped_ptr<UserInputMonitor>(new UserInputMonitorMac()); +} + +} // namespace media diff --git a/media/base/user_input_monitor_mac.mm b/media/base/user_input_monitor_mac.mm deleted file mode 100644 index 4ffad42..0000000 --- a/media/base/user_input_monitor_mac.mm +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/base/user_input_monitor.h" - -namespace media { - -// TODO(jiayl): add the implementation. -scoped_ptr<UserInputMonitor> UserInputMonitor::Create( - const scoped_refptr<base::SingleThreadTaskRunner>& input_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { - return scoped_ptr<UserInputMonitor>(); -} - -} // namespace media diff --git a/media/media.gyp b/media/media.gyp index 6408f4b..5554a28 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -258,6 +258,8 @@ 'base/djb2.h', 'base/filter_collection.cc', 'base/filter_collection.h', + 'base/keyboard_event_counter.cc', + 'base/keyboard_event_counter.h', 'base/media.cc', 'base/media.h', 'base/media_file_checker.cc', @@ -304,7 +306,7 @@ 'base/user_input_monitor.cc', 'base/user_input_monitor.h', 'base/user_input_monitor_linux.cc', - 'base/user_input_monitor_mac.mm', + 'base/user_input_monitor_mac.cc', 'base/user_input_monitor_win.cc', 'base/video_decoder.cc', 'base/video_decoder.h', @@ -687,6 +689,8 @@ 'audio/cras/cras_input.h', 'audio/cras/cras_unified.cc', 'audio/cras/cras_unified.h', + 'base/keyboard_event_counter.cc', + 'base/keyboard_event_counter.h', ], }], ['use_pulseaudio==1', { |