Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(607)

Side by Side Diff: media/base/user_input_monitor_linux.cc

Issue 2391673002: Use FileDescriptorWatcher in UserInputMonitorLinuxCore. (Closed)
Patch Set: CR liberato #15 Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | media/base/user_input_monitor_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/base/user_input_monitor.h" 5 #include "media/base/user_input_monitor.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <sys/select.h> 8 #include <sys/select.h>
9 #include <unistd.h> 9 #include <unistd.h>
10 #define XK_MISCELLANY 10 #define XK_MISCELLANY
11 #include <X11/keysymdef.h> 11 #include <X11/keysymdef.h>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/callback.h" 14 #include "base/callback.h"
15 #include "base/compiler_specific.h" 15 #include "base/compiler_specific.h"
16 #include "base/files/file_descriptor_watcher_posix.h"
16 #include "base/location.h" 17 #include "base/location.h"
17 #include "base/logging.h" 18 #include "base/logging.h"
18 #include "base/macros.h" 19 #include "base/macros.h"
19 #include "base/memory/ptr_util.h" 20 #include "base/memory/ptr_util.h"
20 #include "base/message_loop/message_loop.h" 21 #include "base/message_loop/message_loop.h"
21 #include "base/message_loop/message_pump_libevent.h"
22 #include "base/single_thread_task_runner.h" 22 #include "base/single_thread_task_runner.h"
23 #include "base/synchronization/lock.h" 23 #include "base/synchronization/lock.h"
24 #include "media/base/keyboard_event_counter.h" 24 #include "media/base/keyboard_event_counter.h"
25 #include "third_party/skia/include/core/SkPoint.h" 25 #include "third_party/skia/include/core/SkPoint.h"
26 #include "ui/events/keycodes/keyboard_code_conversion_x.h" 26 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
27 #include "ui/gfx/x/x11_types.h" 27 #include "ui/gfx/x/x11_types.h"
28 28
29 // These includes need to be later than dictated by the style guide due to 29 // These includes need to be later than dictated by the style guide due to
30 // Xlib header pollution, specifically the min, max, and Status macros. 30 // Xlib header pollution, specifically the min, max, and Status macros.
31 #include <X11/XKBlib.h> 31 #include <X11/XKBlib.h>
32 #include <X11/Xlibint.h> 32 #include <X11/Xlibint.h>
33 #include <X11/extensions/record.h> 33 #include <X11/extensions/record.h>
34 34
35 namespace media { 35 namespace media {
36 namespace { 36 namespace {
37 37
38 // This is the actual implementation of event monitoring. It's separated from 38 // This is the actual implementation of event monitoring. It's separated from
39 // UserInputMonitorLinux since it needs to be deleted on the IO thread. 39 // UserInputMonitorLinux since it needs to be deleted on the IO thread.
40 class UserInputMonitorLinuxCore 40 class UserInputMonitorLinuxCore
41 : public base::MessagePumpLibevent::Watcher, 41 : public base::SupportsWeakPtr<UserInputMonitorLinuxCore>,
42 public base::SupportsWeakPtr<UserInputMonitorLinuxCore>,
43 public base::MessageLoop::DestructionObserver { 42 public base::MessageLoop::DestructionObserver {
44 public: 43 public:
45 enum EventType { 44 enum EventType {
46 MOUSE_EVENT, 45 MOUSE_EVENT,
47 KEYBOARD_EVENT 46 KEYBOARD_EVENT
48 }; 47 };
49 48
50 explicit UserInputMonitorLinuxCore( 49 explicit UserInputMonitorLinuxCore(
51 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, 50 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
52 const scoped_refptr<UserInputMonitor::MouseListenerList>& 51 const scoped_refptr<UserInputMonitor::MouseListenerList>&
53 mouse_listeners); 52 mouse_listeners);
54 ~UserInputMonitorLinuxCore() override; 53 ~UserInputMonitorLinuxCore() override;
55 54
56 // DestructionObserver overrides. 55 // DestructionObserver overrides.
57 void WillDestroyCurrentMessageLoop() override; 56 void WillDestroyCurrentMessageLoop() override;
58 57
59 size_t GetKeyPressCount() const; 58 size_t GetKeyPressCount() const;
60 void StartMonitor(EventType type); 59 void StartMonitor(EventType type);
61 void StopMonitor(EventType type); 60 void StopMonitor(EventType type);
62 61
63 private: 62 private:
64 // base::MessagePumpLibevent::Watcher interface. 63 void OnXEvent();
65 void OnFileCanReadWithoutBlocking(int fd) override;
66 void OnFileCanWriteWithoutBlocking(int fd) override;
67 64
68 // Processes key and mouse events. 65 // Processes key and mouse events.
69 void ProcessXEvent(xEvent* event); 66 void ProcessXEvent(xEvent* event);
70 static void ProcessReply(XPointer self, XRecordInterceptData* data); 67 static void ProcessReply(XPointer self, XRecordInterceptData* data);
71 68
72 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; 69 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
73 scoped_refptr<base::ObserverListThreadSafe< 70 scoped_refptr<base::ObserverListThreadSafe<
74 UserInputMonitor::MouseEventListener>> mouse_listeners_; 71 UserInputMonitor::MouseEventListener>> mouse_listeners_;
75 72
76 // 73 //
77 // The following members should only be accessed on the IO thread. 74 // The following members should only be accessed on the IO thread.
78 // 75 //
79 base::MessagePumpLibevent::FileDescriptorWatcher controller_; 76 std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_;
80 Display* x_control_display_; 77 Display* x_control_display_;
81 Display* x_record_display_; 78 Display* x_record_display_;
82 XRecordRange* x_record_range_[2]; 79 XRecordRange* x_record_range_[2];
83 XRecordContext x_record_context_; 80 XRecordContext x_record_context_;
84 KeyboardEventCounter counter_; 81 KeyboardEventCounter counter_;
85 82
86 DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinuxCore); 83 DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinuxCore);
87 }; 84 };
88 85
89 class UserInputMonitorLinux : public UserInputMonitor { 86 class UserInputMonitorLinux : public UserInputMonitor {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 if (!XRecordEnableContextAsync(x_record_display_, 211 if (!XRecordEnableContextAsync(x_record_display_,
215 x_record_context_, 212 x_record_context_,
216 &UserInputMonitorLinuxCore::ProcessReply, 213 &UserInputMonitorLinuxCore::ProcessReply,
217 reinterpret_cast<XPointer>(this))) { 214 reinterpret_cast<XPointer>(this))) {
218 LOG(ERROR) << "XRecordEnableContextAsync failed."; 215 LOG(ERROR) << "XRecordEnableContextAsync failed.";
219 StopMonitor(type); 216 StopMonitor(type);
220 return; 217 return;
221 } 218 }
222 219
223 if (!x_record_range_[0] || !x_record_range_[1]) { 220 if (!x_record_range_[0] || !x_record_range_[1]) {
224 // Register OnFileCanReadWithoutBlocking() to be called every time there is 221 // Register OnXEvent() to be called every time there is something to read
225 // something to read from |x_record_display_|. 222 // from |x_record_display_|.
226 base::MessageLoopForIO* message_loop = base::MessageLoopForIO::current(); 223 watch_controller_ = base::FileDescriptorWatcher::WatchReadable(
227 int result = 224 ConnectionNumber(x_record_display_),
228 message_loop->WatchFileDescriptor(ConnectionNumber(x_record_display_), 225 base::Bind(&UserInputMonitorLinuxCore::OnXEvent,
229 true, 226 base::Unretained(this)));
230 base::MessageLoopForIO::WATCH_READ,
231 &controller_,
232 this);
233 if (!result) {
234 LOG(ERROR) << "Failed to create X record task.";
235 StopMonitor(type);
236 return;
237 }
238 227
239 // Start observing message loop destruction if we start monitoring the first 228 // Start observing message loop destruction if we start monitoring the first
240 // event. 229 // event.
241 base::MessageLoop::current()->AddDestructionObserver(this); 230 base::MessageLoop::current()->AddDestructionObserver(this);
242 } 231 }
243 232
244 // Fetch pending events if any. 233 // Fetch pending events if any.
245 OnFileCanReadWithoutBlocking(ConnectionNumber(x_record_display_)); 234 OnXEvent();
246 } 235 }
247 236
248 void UserInputMonitorLinuxCore::StopMonitor(EventType type) { 237 void UserInputMonitorLinuxCore::StopMonitor(EventType type) {
249 DCHECK(io_task_runner_->BelongsToCurrentThread()); 238 DCHECK(io_task_runner_->BelongsToCurrentThread());
250 239
251 if (x_record_range_[type]) { 240 if (x_record_range_[type]) {
252 XFree(x_record_range_[type]); 241 XFree(x_record_range_[type]);
253 x_record_range_[type] = NULL; 242 x_record_range_[type] = NULL;
254 } 243 }
255 if (x_record_range_[0] || x_record_range_[1]) 244 if (x_record_range_[0] || x_record_range_[1])
256 return; 245 return;
257 246
258 // Context must be disabled via the control channel because we can't send 247 // Context must be disabled via the control channel because we can't send
259 // any X protocol traffic over the data channel while it's recording. 248 // any X protocol traffic over the data channel while it's recording.
260 if (x_record_context_) { 249 if (x_record_context_) {
261 XRecordDisableContext(x_control_display_, x_record_context_); 250 XRecordDisableContext(x_control_display_, x_record_context_);
262 XFlush(x_control_display_); 251 XFlush(x_control_display_);
263 XRecordFreeContext(x_record_display_, x_record_context_); 252 XRecordFreeContext(x_record_display_, x_record_context_);
264 x_record_context_ = 0; 253 x_record_context_ = 0;
265 254
266 controller_.StopWatchingFileDescriptor(); 255 watch_controller_.reset();
267 } 256 }
268 if (x_record_display_) { 257 if (x_record_display_) {
269 XCloseDisplay(x_record_display_); 258 XCloseDisplay(x_record_display_);
270 x_record_display_ = NULL; 259 x_record_display_ = NULL;
271 } 260 }
272 if (x_control_display_) { 261 if (x_control_display_) {
273 XCloseDisplay(x_control_display_); 262 XCloseDisplay(x_control_display_);
274 x_control_display_ = NULL; 263 x_control_display_ = NULL;
275 } 264 }
276 // Stop observing message loop destruction if no event is being monitored. 265 // Stop observing message loop destruction if no event is being monitored.
277 base::MessageLoop::current()->RemoveDestructionObserver(this); 266 base::MessageLoop::current()->RemoveDestructionObserver(this);
278 } 267 }
279 268
280 void UserInputMonitorLinuxCore::OnFileCanReadWithoutBlocking(int fd) { 269 void UserInputMonitorLinuxCore::OnXEvent() {
281 DCHECK(io_task_runner_->BelongsToCurrentThread()); 270 DCHECK(io_task_runner_->BelongsToCurrentThread());
282 XEvent event; 271 XEvent event;
283 // Fetch pending events if any. 272 // Fetch pending events if any.
284 while (XPending(x_record_display_)) { 273 while (XPending(x_record_display_)) {
285 XNextEvent(x_record_display_, &event); 274 XNextEvent(x_record_display_, &event);
286 } 275 }
287 } 276 }
288 277
289 void UserInputMonitorLinuxCore::OnFileCanWriteWithoutBlocking(int fd) {
290 NOTREACHED();
291 }
292
293 void UserInputMonitorLinuxCore::ProcessXEvent(xEvent* event) { 278 void UserInputMonitorLinuxCore::ProcessXEvent(xEvent* event) {
294 DCHECK(io_task_runner_->BelongsToCurrentThread()); 279 DCHECK(io_task_runner_->BelongsToCurrentThread());
295 if (event->u.u.type == MotionNotify) { 280 if (event->u.u.type == MotionNotify) {
296 SkIPoint position(SkIPoint::Make(event->u.keyButtonPointer.rootX, 281 SkIPoint position(SkIPoint::Make(event->u.keyButtonPointer.rootX,
297 event->u.keyButtonPointer.rootY)); 282 event->u.keyButtonPointer.rootY));
298 mouse_listeners_->Notify( 283 mouse_listeners_->Notify(
299 FROM_HERE, &UserInputMonitor::MouseEventListener::OnMouseMoved, 284 FROM_HERE, &UserInputMonitor::MouseEventListener::OnMouseMoved,
300 position); 285 position);
301 } else { 286 } else {
302 ui::EventType type; 287 ui::EventType type;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 361
377 } // namespace 362 } // namespace
378 363
379 std::unique_ptr<UserInputMonitor> UserInputMonitor::Create( 364 std::unique_ptr<UserInputMonitor> UserInputMonitor::Create(
380 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, 365 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
381 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { 366 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) {
382 return base::WrapUnique(new UserInputMonitorLinux(io_task_runner)); 367 return base::WrapUnique(new UserInputMonitorLinux(io_task_runner));
383 } 368 }
384 369
385 } // namespace media 370 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | media/base/user_input_monitor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698