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

Side by Side Diff: remoting/host/event_executor_linux.cc

Issue 6489031: Run event executor on the ui thread to remove the need to explicitly XFlush() the XTest calls. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Removed unused gtk dependency. Created 9 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "remoting/host/event_executor_linux.h" 5 #include "remoting/host/event_executor_linux.h"
6 6
7 #include <X11/Xlib.h> 7 #include <X11/Xlib.h>
8 #include <X11/keysym.h> 8 #include <X11/keysym.h>
9 #include <X11/extensions/XTest.h> 9 #include <X11/extensions/XTest.h>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/message_loop.h" 12 #include "base/message_loop.h"
13 #include "base/task.h" 13 #include "base/task.h"
14 #include "remoting/proto/internal.pb.h" 14 #include "remoting/proto/internal.pb.h"
15 15
16 // TODO(jamiewalch): Class to ensure that XFlush is called regardless of what
17 // fields are set in the MouseEvent. It's not worth refactoring HandleMouse to
18 // avoid the early returns because calling XFlush is not really the correct
19 // way of flushing the XTest requests; instead we should dispatch the requests
20 // to a suitable UI thread.
21 namespace {
22 class ScopedXFlusher {
23 public:
24 explicit ScopedXFlusher(Display* display)
25 : display_(display), needs_flush_(false) {
26 }
27
28 ~ScopedXFlusher() {
29 if (needs_flush_)
30 XFlush(display_);
31 }
32
33 void SignalFlush() {
34 needs_flush_ = true;
35 }
36
37 private:
38 Display* display_;
39 bool needs_flush_;
40 };
41 }
42
43 namespace remoting { 16 namespace remoting {
44 17
45 using protocol::MouseEvent; 18 using protocol::MouseEvent;
46 using protocol::KeyEvent; 19 using protocol::KeyEvent;
47 20
48 static int MouseButtonToX11ButtonNumber( 21 static int MouseButtonToX11ButtonNumber(
49 protocol::MouseEvent::MouseButton button) { 22 protocol::MouseEvent::MouseButton button) {
50 switch (button) { 23 switch (button) {
51 case MouseEvent::BUTTON_LEFT: 24 case MouseEvent::BUTTON_LEFT:
52 return 1; 25 return 1;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 static int ChromotocolKeycodeToX11Keysym(int32_t keycode) { 195 static int ChromotocolKeycodeToX11Keysym(int32_t keycode) {
223 if (keycode < 0 || keycode > 255) { 196 if (keycode < 0 || keycode > 255) {
224 return -1; 197 return -1;
225 } 198 }
226 199
227 return kPepperToX11Keysym[keycode]; 200 return kPepperToX11Keysym[keycode];
228 } 201 }
229 202
230 class EventExecutorLinuxPimpl { 203 class EventExecutorLinuxPimpl {
231 public: 204 public:
232 explicit EventExecutorLinuxPimpl(EventExecutorLinux* executor); 205 explicit EventExecutorLinuxPimpl(EventExecutorLinux* executor,
206 Display* display);
233 ~EventExecutorLinuxPimpl(); 207 ~EventExecutorLinuxPimpl();
234 208
235 bool Init(); // TODO(ajwong): Do we really want this to be synchronous? 209 bool Init(); // TODO(ajwong): Do we really want this to be synchronous?
236 210
237 void HandleMouse(const MouseEvent* message); 211 void HandleMouse(const MouseEvent* message);
238 void HandleKey(const KeyEvent* key_event); 212 void HandleKey(const KeyEvent* key_event);
239 213
240 private: 214 private:
241 void DeinitXlib(); 215 void DeinitXlib();
242 216
243 // Reference to containing class so we can access friend functions. 217 // Reference to containing class so we can access friend functions.
244 // Not owned. 218 // Not owned.
245 EventExecutorLinux* executor_; 219 EventExecutorLinux* executor_;
246 220
247 // X11 graphics context. 221 // X11 graphics context.
248 Display* display_; 222 Display* display_;
249 Window root_window_; 223 Window root_window_;
250 int width_; 224 int width_;
251 int height_; 225 int height_;
252 226
253 int test_event_base_; 227 int test_event_base_;
254 int test_error_base_; 228 int test_error_base_;
255 }; 229 };
256 230
257 EventExecutorLinuxPimpl::EventExecutorLinuxPimpl(EventExecutorLinux* executor) 231 EventExecutorLinuxPimpl::EventExecutorLinuxPimpl(EventExecutorLinux* executor,
232 Display* display)
258 : executor_(executor), 233 : executor_(executor),
259 display_(NULL), 234 display_(display),
260 root_window_(BadValue), 235 root_window_(BadValue),
261 width_(0), 236 width_(0),
262 height_(0) { 237 height_(0) {
263 } 238 }
264 239
265 EventExecutorLinuxPimpl::~EventExecutorLinuxPimpl() { 240 EventExecutorLinuxPimpl::~EventExecutorLinuxPimpl() {
266 DeinitXlib(); 241 DeinitXlib();
267 } 242 }
268 243
269 bool EventExecutorLinuxPimpl::Init() { 244 bool EventExecutorLinuxPimpl::Init() {
270 // TODO(ajwong): We should specify the display string we are attaching to
271 // in the constructor.
272 display_ = XOpenDisplay(NULL);
273 if (!display_) { 245 if (!display_) {
274 LOG(ERROR) << "Unable to open display"; 246 LOG(ERROR) << "Unable to open display";
275 return false; 247 return false;
276 } 248 }
277 249
278 root_window_ = RootWindow(display_, DefaultScreen(display_)); 250 root_window_ = RootWindow(display_, DefaultScreen(display_));
279 if (root_window_ == BadValue) { 251 if (root_window_ == BadValue) {
280 LOG(ERROR) << "Unable to get the root window"; 252 LOG(ERROR) << "Unable to get the root window";
281 DeinitXlib(); 253 DeinitXlib();
282 return false; 254 return false;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 if (keycode == 0) { 294 if (keycode == 0) {
323 LOG(WARNING) << "Ignoring undefined keysym: " << keysym 295 LOG(WARNING) << "Ignoring undefined keysym: " << keysym
324 << " for key: " << key_event->keycode(); 296 << " for key: " << key_event->keycode();
325 return; 297 return;
326 } 298 }
327 299
328 VLOG(3) << "Got pepper key: " << key_event->keycode() 300 VLOG(3) << "Got pepper key: " << key_event->keycode()
329 << " sending keysym: " << keysym 301 << " sending keysym: " << keysym
330 << " to keycode: " << keycode; 302 << " to keycode: " << keycode;
331 XTestFakeKeyEvent(display_, keycode, key_event->pressed(), CurrentTime); 303 XTestFakeKeyEvent(display_, keycode, key_event->pressed(), CurrentTime);
332
333 // TODO(jamiewalch): Get rid of this once we're dispatching to the UI thread.
334 XFlush(display_);
335 } 304 }
336 305
337 void EventExecutorLinuxPimpl::HandleMouse(const MouseEvent* event) { 306 void EventExecutorLinuxPimpl::HandleMouse(const MouseEvent* event) {
338 ScopedXFlusher flusher(display_);
339 if (event->has_x() && event->has_y()) { 307 if (event->has_x() && event->has_y()) {
340 if (event->x() < 0 || event->y() < 0 || 308 if (event->x() < 0 || event->y() < 0 ||
341 event->x() > width_ || event->y() > height_) { 309 event->x() > width_ || event->y() > height_) {
342 // A misbehaving client may send these. Drop events that are out of range. 310 // A misbehaving client may send these. Drop events that are out of range.
343 // TODO(ajwong): How can we log this sanely? We don't want to DOS the 311 // TODO(ajwong): How can we log this sanely? We don't want to DOS the
344 // server with a misbehaving client by logging like crazy. 312 // server with a misbehaving client by logging like crazy.
345 return; 313 return;
346 } 314 }
347 315
348 VLOG(3) << "Moving mouse to " << event->x() 316 VLOG(3) << "Moving mouse to " << event->x()
349 << "," << event->y(); 317 << "," << event->y();
350 flusher.SignalFlush();
351 XTestFakeMotionEvent(display_, DefaultScreen(display_), 318 XTestFakeMotionEvent(display_, DefaultScreen(display_),
352 event->x(), event->y(), 319 event->x(), event->y(),
353 CurrentTime); 320 CurrentTime);
354 } 321 }
355 322
356 if (event->has_button() && event->has_button_down()) { 323 if (event->has_button() && event->has_button_down()) {
357 int button_number = MouseButtonToX11ButtonNumber(event->button()); 324 int button_number = MouseButtonToX11ButtonNumber(event->button());
358 325
359 if (button_number < 0) { 326 if (button_number < 0) {
360 LOG(WARNING) << "Ignoring unknown button type: " 327 LOG(WARNING) << "Ignoring unknown button type: "
361 << event->button(); 328 << event->button();
362 return; 329 return;
363 } 330 }
364 331
365 VLOG(3) << "Button " << event->button() 332 VLOG(3) << "Button " << event->button()
366 << " received, sending down " << button_number; 333 << " received, sending down " << button_number;
367 flusher.SignalFlush();
368 XTestFakeButtonEvent(display_, button_number, event->button_down(), 334 XTestFakeButtonEvent(display_, button_number, event->button_down(),
369 CurrentTime); 335 CurrentTime);
370 } 336 }
371 337
372 if (event->has_wheel_offset_x() && event->has_wheel_offset_y()) { 338 if (event->has_wheel_offset_x() && event->has_wheel_offset_y()) {
373 NOTIMPLEMENTED() << "No scroll wheel support yet."; 339 NOTIMPLEMENTED() << "No scroll wheel support yet.";
374 } 340 }
375 } 341 }
376 342
377 void EventExecutorLinuxPimpl::DeinitXlib() { 343 void EventExecutorLinuxPimpl::DeinitXlib() {
378 // TODO(ajwong): We should expose a "close" or "shutdown" method. 344 // TODO(ajwong): We should expose a "close" or "shutdown" method.
379 if (display_) { 345 if (display_) {
380 if (!XCloseDisplay(display_)) { 346 if (!XCloseDisplay(display_)) {
381 LOG(ERROR) << "Unable to close the Xlib Display."; 347 LOG(ERROR) << "Unable to close the Xlib Display.";
382 } 348 }
383 display_ = NULL; 349 display_ = NULL;
384 } 350 }
385 } 351 }
386 352
387 EventExecutorLinux::EventExecutorLinux( 353 EventExecutorLinux::EventExecutorLinux(
388 MessageLoop* message_loop, Capturer* capturer) 354 MessageLoopForUI* message_loop, Capturer* capturer)
389 : message_loop_(message_loop), 355 : message_loop_(message_loop),
390 capturer_(capturer), 356 capturer_(capturer),
391 pimpl_(new EventExecutorLinuxPimpl(this)) { 357 pimpl_(new EventExecutorLinuxPimpl(this, message_loop->get_display())) {
392 CHECK(pimpl_->Init()); 358 CHECK(pimpl_->Init());
393 } 359 }
394 360
395 EventExecutorLinux::~EventExecutorLinux() { 361 EventExecutorLinux::~EventExecutorLinux() {
396 } 362 }
397 363
398 void EventExecutorLinux::InjectKeyEvent(const KeyEvent* event, Task* done) { 364 void EventExecutorLinux::InjectKeyEvent(const KeyEvent* event, Task* done) {
399 if (MessageLoop::current() != message_loop_) { 365 if (MessageLoop::current() != message_loop_) {
400 message_loop_->PostTask( 366 message_loop_->PostTask(
401 FROM_HERE, 367 FROM_HERE,
(...skipping 13 matching lines...) Expand all
415 FROM_HERE, 381 FROM_HERE,
416 NewRunnableMethod(this, &EventExecutorLinux::InjectMouseEvent, 382 NewRunnableMethod(this, &EventExecutorLinux::InjectMouseEvent,
417 event, done)); 383 event, done));
418 return; 384 return;
419 } 385 }
420 pimpl_->HandleMouse(event); 386 pimpl_->HandleMouse(event);
421 done->Run(); 387 done->Run();
422 delete done; 388 delete done;
423 } 389 }
424 390
425 protocol::InputStub* CreateEventExecutor(MessageLoop* message_loop, 391 protocol::InputStub* CreateEventExecutor(MessageLoopForUI* message_loop,
426 Capturer* capturer) { 392 Capturer* capturer) {
427 return new EventExecutorLinux(message_loop, capturer); 393 return new EventExecutorLinux(message_loop, capturer);
428 } 394 }
429 395
430 } // namespace remoting 396 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698