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

Side by Side Diff: ui/aura/root_window_host_linux.cc

Issue 9808010: Keep the mouse cursor within desktop (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 9 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "ui/aura/root_window_host_linux.h" 5 #include "ui/aura/root_window_host_linux.h"
6 6
7 #include <X11/cursorfont.h> 7 #include <X11/cursorfont.h>
8 #include <X11/extensions/XInput2.h> 8 #include <X11/extensions/XInput2.h>
9 #include <X11/extensions/Xfixes.h>
9 #include <X11/extensions/Xrandr.h> 10 #include <X11/extensions/Xrandr.h>
10 #include <algorithm> 11 #include <algorithm>
11 12
12 #include "base/message_pump_x.h" 13 #include "base/message_pump_x.h"
13 #include "base/stl_util.h" 14 #include "base/stl_util.h"
14 #include "ui/aura/cursor.h" 15 #include "ui/aura/cursor.h"
15 #include "ui/aura/dispatcher_linux.h" 16 #include "ui/aura/dispatcher_linux.h"
16 #include "ui/aura/env.h" 17 #include "ui/aura/env.h"
17 #include "ui/aura/event.h" 18 #include "ui/aura/event.h"
18 #include "ui/aura/monitor.h" 19 #include "ui/aura/monitor.h"
19 #include "ui/aura/monitor_change_observer_x11.h"
20 #include "ui/aura/monitor_manager.h" 20 #include "ui/aura/monitor_manager.h"
21 #include "ui/aura/root_window.h" 21 #include "ui/aura/root_window.h"
22 #include "ui/base/keycodes/keyboard_codes.h" 22 #include "ui/base/keycodes/keyboard_codes.h"
23 #include "ui/base/touch/touch_factory.h" 23 #include "ui/base/touch/touch_factory.h"
24 #include "ui/base/x/x11_util.h" 24 #include "ui/base/x/x11_util.h"
25 #include "ui/gfx/compositor/layer.h" 25 #include "ui/gfx/compositor/layer.h"
26 26
27 using std::max; 27 using std::max;
28 using std::min; 28 using std::min;
29 29
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 } // namespace 274 } // namespace
275 275
276 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) 276 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds)
277 : root_window_(NULL), 277 : root_window_(NULL),
278 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), 278 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()),
279 xwindow_(0), 279 xwindow_(0),
280 x_root_window_(DefaultRootWindow(xdisplay_)), 280 x_root_window_(DefaultRootWindow(xdisplay_)),
281 current_cursor_(aura::kCursorNull), 281 current_cursor_(aura::kCursorNull),
282 cursor_shown_(true), 282 cursor_shown_(true),
283 bounds_(bounds), 283 bounds_(bounds),
284 focus_when_shown_(false) { 284 focus_when_shown_(false),
285 pointer_barriers_(NULL) {
285 XSetWindowAttributes swa; 286 XSetWindowAttributes swa;
286 memset(&swa, 0, sizeof(swa)); 287 memset(&swa, 0, sizeof(swa));
287 swa.background_pixmap = None; 288 swa.background_pixmap = None;
288 xwindow_ = XCreateWindow( 289 xwindow_ = XCreateWindow(
289 xdisplay_, x_root_window_, 290 xdisplay_, x_root_window_,
290 bounds_.x(), bounds_.y(), bounds_.width(), bounds_.height(), 291 bounds_.x(), bounds_.y(), bounds_.width(), bounds_.height(),
291 0, // border width 292 0, // border width
292 CopyFromParent, // depth 293 CopyFromParent, // depth
293 InputOutput, 294 InputOutput,
294 CopyFromParent, // visual 295 CopyFromParent, // visual
295 CWBackPixmap, 296 CWBackPixmap,
296 &swa); 297 &swa);
297 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> 298 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())->
298 RootWindowHostCreated(xwindow_, x_root_window_, this); 299 WindowDispatcherCreated(xwindow_, this);
299 300
300 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | 301 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
301 KeyPressMask | KeyReleaseMask | 302 KeyPressMask | KeyReleaseMask |
302 EnterWindowMask | LeaveWindowMask | 303 EnterWindowMask | LeaveWindowMask |
303 ExposureMask | VisibilityChangeMask | 304 ExposureMask | VisibilityChangeMask |
304 StructureNotifyMask | PropertyChangeMask | 305 StructureNotifyMask | PropertyChangeMask |
305 PointerMotionMask; 306 PointerMotionMask;
306 XSelectInput(xdisplay_, xwindow_, event_mask); 307 XSelectInput(xdisplay_, xwindow_, event_mask);
307 XFlush(xdisplay_); 308 XFlush(xdisplay_);
308 309
309 if (base::MessagePumpForUI::HasXInput2()) 310 if (base::MessagePumpForUI::HasXInput2())
310 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); 311 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
311 312
312 // Initialize invisible cursor. 313 // Initialize invisible cursor.
313 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 314 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
314 XColor black; 315 XColor black;
315 black.red = black.green = black.blue = 0; 316 black.red = black.green = black.blue = 0;
316 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_, 317 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_,
317 nodata, 8, 8); 318 nodata, 8, 8);
318 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank, 319 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank,
319 &black, &black, 0, 0); 320 &black, &black, 0, 0);
320 if (RootWindow::hide_host_cursor()) 321 if (RootWindow::hide_host_cursor())
321 XDefineCursor(xdisplay_, x_root_window_, invisible_cursor_); 322 XDefineCursor(xdisplay_, x_root_window_, invisible_cursor_);
322 } 323 }
323 324
324 RootWindowHostLinux::~RootWindowHostLinux() { 325 RootWindowHostLinux::~RootWindowHostLinux() {
325 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> 326 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())->
326 RootWindowHostDestroying(xwindow_, x_root_window_); 327 WindowDispatcherDestroying(xwindow_);
327 XDestroyWindow(xdisplay_, xwindow_); 328 XDestroyWindow(xdisplay_, xwindow_);
328 329
329 // Clears XCursorCache. 330 // Clears XCursorCache.
330 ui::GetXCursor(ui::kCursorClearXCursorCache); 331 ui::GetXCursor(ui::kCursorClearXCursorCache);
331 332
332 XFreeCursor(xdisplay_, invisible_cursor_); 333 XFreeCursor(xdisplay_, invisible_cursor_);
333 } 334 }
334 335
335 base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch( 336 base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch(
336 XEvent* xev) { 337 XEvent* xev) {
(...skipping 23 matching lines...) Expand all
360 handled = root_window_->DispatchMouseEvent(&mouseev); 361 handled = root_window_->DispatchMouseEvent(&mouseev);
361 break; 362 break;
362 } 363 }
363 case FocusOut: 364 case FocusOut:
364 if (xev->xfocus.mode != NotifyGrab) 365 if (xev->xfocus.mode != NotifyGrab)
365 root_window_->SetCapture(NULL); 366 root_window_->SetCapture(NULL);
366 break; 367 break;
367 case ConfigureNotify: { 368 case ConfigureNotify: {
368 DCHECK_EQ(xwindow_, xev->xconfigure.window); 369 DCHECK_EQ(xwindow_, xev->xconfigure.window);
369 DCHECK_EQ(xwindow_, xev->xconfigure.event); 370 DCHECK_EQ(xwindow_, xev->xconfigure.event);
370 371 // Update barrier and mouse location when the root window has
372 // moved/resized.
373 if (pointer_barriers_.get()) {
Daniel Erat 2012/03/23 16:49:16 It looks like you only update if we already had ba
oshima 2012/03/23 18:25:09 This is enabled for root window for primary monito
374 UnConfineCursor();
375 gfx::Point p = root_window_->last_mouse_location();
376 XWarpPointer(xdisplay_, None, xwindow_, 0, 0, 0, 0, p.x(), p.y());
377 ConfineCursorToRootWindow();
378 }
371 // It's possible that the X window may be resized by some other means than 379 // It's possible that the X window may be resized by some other means than
372 // from within aura (e.g. the X window manager can change the size). Make 380 // from within aura (e.g. the X window manager can change the size). Make
373 // sure the root window size is maintained properly. 381 // sure the root window size is maintained properly.
374 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, 382 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
375 xev->xconfigure.width, xev->xconfigure.height); 383 xev->xconfigure.width, xev->xconfigure.height);
376 bool size_changed = bounds_.size() != bounds.size(); 384 bool size_changed = bounds_.size() != bounds.size();
377 bounds_ = bounds; 385 bounds_ = bounds;
378 if (size_changed) 386 if (size_changed)
379 root_window_->OnHostResized(bounds.size()); 387 root_window_->OnHostResized(bounds.size());
380 handled = true; 388 handled = true;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 xev = &last_event; 481 xev = &last_event;
474 } else { 482 } else {
475 break; 483 break;
476 } 484 }
477 } 485 }
478 486
479 MouseEvent mouseev(xev); 487 MouseEvent mouseev(xev);
480 handled = root_window_->DispatchMouseEvent(&mouseev); 488 handled = root_window_->DispatchMouseEvent(&mouseev);
481 break; 489 break;
482 } 490 }
483 default: {
484 // TODO(oshima): We probably should change DispatcherLinux so
485 // that it can directly dispatch the event to montor change
486 // observer.
487 Env::GetInstance()->monitor_change_observer()->Dispatch(xev);
488 }
489 } 491 }
490 return handled ? base::MessagePumpDispatcher::EVENT_PROCESSED : 492 return handled ? base::MessagePumpDispatcher::EVENT_PROCESSED :
491 base::MessagePumpDispatcher::EVENT_IGNORED; 493 base::MessagePumpDispatcher::EVENT_IGNORED;
492 } 494 }
493 495
494 void RootWindowHostLinux::SetRootWindow(RootWindow* root_window) { 496 void RootWindowHostLinux::SetRootWindow(RootWindow* root_window) {
495 root_window_ = root_window; 497 root_window_ = root_window;
496 } 498 }
497 499
498 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { 500 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 &root_return, 573 &root_return,
572 &child_return, 574 &child_return,
573 &root_x_return, &root_y_return, 575 &root_x_return, &root_y_return,
574 &win_x_return, &win_y_return, 576 &win_x_return, &win_y_return,
575 &mask_return); 577 &mask_return);
576 return gfx::Point(max(0, min(bounds_.width(), win_x_return)), 578 return gfx::Point(max(0, min(bounds_.width(), win_x_return)),
577 max(0, min(bounds_.height(), win_y_return))); 579 max(0, min(bounds_.height(), win_y_return)));
578 } 580 }
579 581
580 bool RootWindowHostLinux::ConfineCursorToRootWindow() { 582 bool RootWindowHostLinux::ConfineCursorToRootWindow() {
581 return XGrabPointer(xdisplay_, 583 #if XFIXES_MAJOR >= 5
582 xwindow_, // grab_window 584 if (pointer_barriers_.get())
Daniel Erat 2012/03/23 16:49:16 DCHECK(!pointer_barriers_.get()) instead?
oshima 2012/03/23 18:25:09 I added it. I kept "if" because this isn't critica
583 False, // owner_events 585 return false;
584 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, 586 // Monitors are vertically laid out, so just create barriers at the top and
585 GrabModeAsync, 587 // the bottom.
Daniel Erat 2012/03/23 16:49:16 Can the monitors be different widths? If so, it s
oshima 2012/03/23 18:25:09 There are already barriers on sides.
586 GrabModeAsync, 588 pointer_barriers_.reset(new XID[2]);
587 xwindow_, // confine_to 589 pointer_barriers_[0] = XFixesCreatePointerBarrier(
588 None, // cursor 590 xdisplay_, xwindow_,
589 CurrentTime) == GrabSuccess; 591 0, 0, bounds_.width(), 0, // barrier line
Daniel Erat 2012/03/23 16:49:16 Should you be using bounds_.x() and bounds_.y() he
oshima 2012/03/23 18:25:09 I'm creating barriers relative to xwindow_, so thi
592 BarrierPositiveY,
593 0, NULL); // default device
594 pointer_barriers_[1] = XFixesCreatePointerBarrier(
595 xdisplay_, xwindow_,
596 0, bounds_.height(), bounds_.width(), bounds_.height(), // barrier line
597 BarrierNegativeY,
598 0, NULL); // default device
599 #endif
600 return true;
590 } 601 }
591 602
592 void RootWindowHostLinux::UnConfineCursor() { 603 void RootWindowHostLinux::UnConfineCursor() {
Daniel Erat 2012/03/23 16:49:16 Should probably call this from the d'tor too.
oshima 2012/03/23 18:25:09 Good point. Done.
593 XUngrabPointer(xdisplay_, CurrentTime); 604 #if XFIXES_MAJOR >= 5
605 if (pointer_barriers_.get()) {
606 XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[0]);
607 XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[1]);
608 pointer_barriers_.reset();
609 }
610 #endif
594 } 611 }
595 612
596 void RootWindowHostLinux::MoveCursorTo(const gfx::Point& location) { 613 void RootWindowHostLinux::MoveCursorTo(const gfx::Point& location) {
597 XWarpPointer(xdisplay_, None, xwindow_, 0, 0, 0, 0, location.x(), 614 XWarpPointer(xdisplay_, None, xwindow_, 0, 0, 0, 0, location.x(),
598 location.y()); 615 location.y());
599 } 616 }
600 617
601 void RootWindowHostLinux::SetFocusWhenShown(bool focus_when_shown) { 618 void RootWindowHostLinux::SetFocusWhenShown(bool focus_when_shown) {
602 static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME"; 619 static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME";
603 focus_when_shown_ = focus_when_shown; 620 focus_when_shown_ = focus_when_shown;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 return new RootWindowHostLinux(bounds); 679 return new RootWindowHostLinux(bounds);
663 } 680 }
664 681
665 // static 682 // static
666 gfx::Size RootWindowHost::GetNativeScreenSize() { 683 gfx::Size RootWindowHost::GetNativeScreenSize() {
667 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); 684 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay();
668 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); 685 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
669 } 686 }
670 687
671 } // namespace aura 688 } // namespace aura
OLDNEW
« ui/aura/root_window_host_linux.h ('K') | « ui/aura/root_window_host_linux.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698