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

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: sync 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
« ui/aura/env.cc ('K') | « ui/aura/root_window_host_linux.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_);
328
329 UnConfineCursor();
330
327 XDestroyWindow(xdisplay_, xwindow_); 331 XDestroyWindow(xdisplay_, xwindow_);
328 332
329 // Clears XCursorCache. 333 // Clears XCursorCache.
330 ui::GetXCursor(ui::kCursorClearXCursorCache); 334 ui::GetXCursor(ui::kCursorClearXCursorCache);
331 335
332 XFreeCursor(xdisplay_, invisible_cursor_); 336 XFreeCursor(xdisplay_, invisible_cursor_);
333 } 337 }
334 338
335 base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch( 339 base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch(
336 XEvent* xev) { 340 XEvent* xev) {
(...skipping 23 matching lines...) Expand all
360 handled = root_window_->DispatchMouseEvent(&mouseev); 364 handled = root_window_->DispatchMouseEvent(&mouseev);
361 break; 365 break;
362 } 366 }
363 case FocusOut: 367 case FocusOut:
364 if (xev->xfocus.mode != NotifyGrab) 368 if (xev->xfocus.mode != NotifyGrab)
365 root_window_->SetCapture(NULL); 369 root_window_->SetCapture(NULL);
366 break; 370 break;
367 case ConfigureNotify: { 371 case ConfigureNotify: {
368 DCHECK_EQ(xwindow_, xev->xconfigure.window); 372 DCHECK_EQ(xwindow_, xev->xconfigure.window);
369 DCHECK_EQ(xwindow_, xev->xconfigure.event); 373 DCHECK_EQ(xwindow_, xev->xconfigure.event);
370 374 // Update barrier and mouse location when the root window has
375 // moved/resized.
376 if (pointer_barriers_.get()) {
377 UnConfineCursor();
378 gfx::Point p = root_window_->last_mouse_location();
379 XWarpPointer(xdisplay_, None, xwindow_, 0, 0, 0, 0, p.x(), p.y());
380 ConfineCursorToRootWindow();
381 }
371 // It's possible that the X window may be resized by some other means than 382 // 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 383 // from within aura (e.g. the X window manager can change the size). Make
373 // sure the root window size is maintained properly. 384 // sure the root window size is maintained properly.
374 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, 385 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
375 xev->xconfigure.width, xev->xconfigure.height); 386 xev->xconfigure.width, xev->xconfigure.height);
376 bool size_changed = bounds_.size() != bounds.size(); 387 bool size_changed = bounds_.size() != bounds.size();
377 bounds_ = bounds; 388 bounds_ = bounds;
378 if (size_changed) 389 if (size_changed)
379 root_window_->OnHostResized(bounds.size()); 390 root_window_->OnHostResized(bounds.size());
380 handled = true; 391 handled = true;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 xev = &last_event; 484 xev = &last_event;
474 } else { 485 } else {
475 break; 486 break;
476 } 487 }
477 } 488 }
478 489
479 MouseEvent mouseev(xev); 490 MouseEvent mouseev(xev);
480 handled = root_window_->DispatchMouseEvent(&mouseev); 491 handled = root_window_->DispatchMouseEvent(&mouseev);
481 break; 492 break;
482 } 493 }
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 } 494 }
490 return handled ? base::MessagePumpDispatcher::EVENT_PROCESSED : 495 return handled ? base::MessagePumpDispatcher::EVENT_PROCESSED :
491 base::MessagePumpDispatcher::EVENT_IGNORED; 496 base::MessagePumpDispatcher::EVENT_IGNORED;
492 } 497 }
493 498
494 void RootWindowHostLinux::SetRootWindow(RootWindow* root_window) { 499 void RootWindowHostLinux::SetRootWindow(RootWindow* root_window) {
495 root_window_ = root_window; 500 root_window_ = root_window;
496 } 501 }
497 502
498 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { 503 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 &root_return, 576 &root_return,
572 &child_return, 577 &child_return,
573 &root_x_return, &root_y_return, 578 &root_x_return, &root_y_return,
574 &win_x_return, &win_y_return, 579 &win_x_return, &win_y_return,
575 &mask_return); 580 &mask_return);
576 return gfx::Point(max(0, min(bounds_.width(), win_x_return)), 581 return gfx::Point(max(0, min(bounds_.width(), win_x_return)),
577 max(0, min(bounds_.height(), win_y_return))); 582 max(0, min(bounds_.height(), win_y_return)));
578 } 583 }
579 584
580 bool RootWindowHostLinux::ConfineCursorToRootWindow() { 585 bool RootWindowHostLinux::ConfineCursorToRootWindow() {
581 return XGrabPointer(xdisplay_, 586 #if XFIXES_MAJOR >= 5
582 xwindow_, // grab_window 587 DCHECK(!pointer_barriers_.get());
583 False, // owner_events 588 if (pointer_barriers_.get())
584 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, 589 return false;
585 GrabModeAsync, 590 // Monitors are vertically laid out, so just create barriers at the top and
586 GrabModeAsync, 591 // the bottom.
587 xwindow_, // confine_to 592 pointer_barriers_.reset(new XID[2]);
588 None, // cursor 593 pointer_barriers_[0] = XFixesCreatePointerBarrier(
589 CurrentTime) == GrabSuccess; 594 xdisplay_, xwindow_,
595 0, 0, bounds_.width(), 0, // barrier line
596 BarrierPositiveY,
597 0, NULL); // defult device
598 pointer_barriers_[1] = XFixesCreatePointerBarrier(
599 xdisplay_, xwindow_,
600 0, bounds_.height(), bounds_.width(), bounds_.height(), // barrier line
601 BarrierNegativeY,
602 0, NULL); // defult device
603 #endif
604 return true;
590 } 605 }
591 606
592 void RootWindowHostLinux::UnConfineCursor() { 607 void RootWindowHostLinux::UnConfineCursor() {
593 XUngrabPointer(xdisplay_, CurrentTime); 608 #if XFIXES_MAJOR >= 5
609 if (pointer_barriers_.get()) {
610 XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[0]);
611 XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[1]);
612 pointer_barriers_.reset();
613 }
614 #endif
594 } 615 }
595 616
596 void RootWindowHostLinux::MoveCursorTo(const gfx::Point& location) { 617 void RootWindowHostLinux::MoveCursorTo(const gfx::Point& location) {
597 XWarpPointer(xdisplay_, None, xwindow_, 0, 0, 0, 0, location.x(), 618 XWarpPointer(xdisplay_, None, xwindow_, 0, 0, 0, 0, location.x(),
598 location.y()); 619 location.y());
599 } 620 }
600 621
601 void RootWindowHostLinux::SetFocusWhenShown(bool focus_when_shown) { 622 void RootWindowHostLinux::SetFocusWhenShown(bool focus_when_shown) {
602 static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME"; 623 static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME";
603 focus_when_shown_ = focus_when_shown; 624 focus_when_shown_ = focus_when_shown;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 return new RootWindowHostLinux(bounds); 683 return new RootWindowHostLinux(bounds);
663 } 684 }
664 685
665 // static 686 // static
666 gfx::Size RootWindowHost::GetNativeScreenSize() { 687 gfx::Size RootWindowHost::GetNativeScreenSize() {
667 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); 688 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay();
668 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); 689 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
669 } 690 }
670 691
671 } // namespace aura 692 } // namespace aura
OLDNEW
« ui/aura/env.cc ('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