| OLD | NEW |
| 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/Xrandr.h> |
| 9 #include <algorithm> | 10 #include <algorithm> |
| 10 | 11 |
| 11 #include "base/message_pump_x.h" | 12 #include "base/message_pump_x.h" |
| 13 #include "base/stl_util.h" |
| 12 #include "ui/aura/cursor.h" | 14 #include "ui/aura/cursor.h" |
| 13 #include "ui/aura/dispatcher_linux.h" | 15 #include "ui/aura/dispatcher_linux.h" |
| 14 #include "ui/aura/env.h" | 16 #include "ui/aura/env.h" |
| 15 #include "ui/aura/event.h" | 17 #include "ui/aura/event.h" |
| 18 #include "ui/aura/monitor.h" |
| 19 #include "ui/aura/monitor_change_observer_x11.h" |
| 16 #include "ui/aura/monitor_manager.h" | 20 #include "ui/aura/monitor_manager.h" |
| 17 #include "ui/aura/root_window.h" | 21 #include "ui/aura/root_window.h" |
| 18 #include "ui/base/keycodes/keyboard_codes.h" | 22 #include "ui/base/keycodes/keyboard_codes.h" |
| 19 #include "ui/base/touch/touch_factory.h" | 23 #include "ui/base/touch/touch_factory.h" |
| 20 #include "ui/base/x/x11_util.h" | 24 #include "ui/base/x/x11_util.h" |
| 21 #include "ui/gfx/compositor/layer.h" | 25 #include "ui/gfx/compositor/layer.h" |
| 22 | 26 |
| 23 using std::max; | 27 using std::max; |
| 24 using std::min; | 28 using std::min; |
| 25 | 29 |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 | 273 |
| 270 } // namespace | 274 } // namespace |
| 271 | 275 |
| 272 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) | 276 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) |
| 273 : root_window_(NULL), | 277 : root_window_(NULL), |
| 274 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), | 278 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), |
| 275 xwindow_(0), | 279 xwindow_(0), |
| 276 x_root_window_(DefaultRootWindow(xdisplay_)), | 280 x_root_window_(DefaultRootWindow(xdisplay_)), |
| 277 current_cursor_(aura::kCursorNull), | 281 current_cursor_(aura::kCursorNull), |
| 278 cursor_shown_(true), | 282 cursor_shown_(true), |
| 279 bounds_(bounds) { | 283 bounds_(bounds), |
| 284 focus_when_shown_(false) { |
| 280 XSetWindowAttributes swa; | 285 XSetWindowAttributes swa; |
| 281 memset(&swa, 0, sizeof(swa)); | 286 memset(&swa, 0, sizeof(swa)); |
| 282 swa.background_pixmap = None; | 287 swa.background_pixmap = None; |
| 283 xwindow_ = XCreateWindow( | 288 xwindow_ = XCreateWindow( |
| 284 xdisplay_, x_root_window_, | 289 xdisplay_, x_root_window_, |
| 285 bounds_.x(), bounds_.y(), bounds_.width(), bounds_.height(), | 290 bounds_.x(), bounds_.y(), bounds_.width(), bounds_.height(), |
| 286 0, // border width | 291 0, // border width |
| 287 CopyFromParent, // depth | 292 CopyFromParent, // depth |
| 288 InputOutput, | 293 InputOutput, |
| 289 CopyFromParent, // visual | 294 CopyFromParent, // visual |
| 290 CWBackPixmap, | 295 CWBackPixmap, |
| 291 &swa); | 296 &swa); |
| 292 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> | 297 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> |
| 293 RootWindowHostCreated(xwindow_, x_root_window_, this); | 298 RootWindowHostCreated(xwindow_, x_root_window_, this); |
| 294 | 299 |
| 295 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | | 300 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | |
| 296 KeyPressMask | KeyReleaseMask | | 301 KeyPressMask | KeyReleaseMask | |
| 297 EnterWindowMask | LeaveWindowMask | | 302 EnterWindowMask | LeaveWindowMask | |
| 298 ExposureMask | VisibilityChangeMask | | 303 ExposureMask | VisibilityChangeMask | |
| 299 StructureNotifyMask | PropertyChangeMask | | 304 StructureNotifyMask | PropertyChangeMask | |
| 300 PointerMotionMask; | 305 PointerMotionMask; |
| 301 XSelectInput(xdisplay_, xwindow_, event_mask); | 306 XSelectInput(xdisplay_, xwindow_, event_mask); |
| 302 XSelectInput(xdisplay_, x_root_window_, StructureNotifyMask); | |
| 303 XFlush(xdisplay_); | 307 XFlush(xdisplay_); |
| 304 | 308 |
| 305 if (base::MessagePumpForUI::HasXInput2()) | 309 if (base::MessagePumpForUI::HasXInput2()) |
| 306 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); | 310 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
| 307 | 311 |
| 308 // Initialize invisible cursor. | 312 // Initialize invisible cursor. |
| 309 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | 313 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 310 XColor black; | 314 XColor black; |
| 311 black.red = black.green = black.blue = 0; | 315 black.red = black.green = black.blue = 0; |
| 312 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_, | 316 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 case ButtonRelease: { | 358 case ButtonRelease: { |
| 355 MouseEvent mouseev(xev); | 359 MouseEvent mouseev(xev); |
| 356 handled = root_window_->DispatchMouseEvent(&mouseev); | 360 handled = root_window_->DispatchMouseEvent(&mouseev); |
| 357 break; | 361 break; |
| 358 } | 362 } |
| 359 case FocusOut: | 363 case FocusOut: |
| 360 if (xev->xfocus.mode != NotifyGrab) | 364 if (xev->xfocus.mode != NotifyGrab) |
| 361 root_window_->SetCapture(NULL); | 365 root_window_->SetCapture(NULL); |
| 362 break; | 366 break; |
| 363 case ConfigureNotify: { | 367 case ConfigureNotify: { |
| 364 if (xev->xconfigure.window == x_root_window_) { | |
| 365 Env::GetInstance()->monitor_manager()->OnNativeMonitorResized( | |
| 366 gfx::Size(xev->xconfigure.width, xev->xconfigure.height)); | |
| 367 handled = true; | |
| 368 break; | |
| 369 } | |
| 370 | |
| 371 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 368 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
| 372 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 369 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
| 373 | 370 |
| 374 // It's possible that the X window may be resized by some other means than | 371 // It's possible that the X window may be resized by some other means than |
| 375 // from within aura (e.g. the X window manager can change the size). Make | 372 // from within aura (e.g. the X window manager can change the size). Make |
| 376 // sure the root window size is maintained properly. | 373 // sure the root window size is maintained properly. |
| 377 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, | 374 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, |
| 378 xev->xconfigure.width, xev->xconfigure.height); | 375 xev->xconfigure.width, xev->xconfigure.height); |
| 379 bool size_changed = bounds_.size() != bounds.size(); | 376 bool size_changed = bounds_.size() != bounds.size(); |
| 380 bounds_ = bounds; | 377 bounds_ = bounds; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 } | 431 } |
| 435 | 432 |
| 436 // If we coalesced an event we need to free its cookie. | 433 // If we coalesced an event we need to free its cookie. |
| 437 if (num_coalesced > 0) | 434 if (num_coalesced > 0) |
| 438 XFreeEventData(xev->xgeneric.display, &last_event.xcookie); | 435 XFreeEventData(xev->xgeneric.display, &last_event.xcookie); |
| 439 break; | 436 break; |
| 440 } | 437 } |
| 441 case MapNotify: { | 438 case MapNotify: { |
| 442 // If there's no window manager running, we need to assign the X input | 439 // If there's no window manager running, we need to assign the X input |
| 443 // focus to our host window. | 440 // focus to our host window. |
| 444 if (!IsWindowManagerPresent()) | 441 if (!IsWindowManagerPresent() && focus_when_shown_) |
| 445 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); | 442 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); |
| 446 handled = true; | 443 handled = true; |
| 447 break; | 444 break; |
| 448 } | 445 } |
| 449 case MappingNotify: { | 446 case MappingNotify: { |
| 450 switch (xev->xmapping.request) { | 447 switch (xev->xmapping.request) { |
| 451 case MappingModifier: | 448 case MappingModifier: |
| 452 case MappingKeyboard: | 449 case MappingKeyboard: |
| 453 XRefreshKeyboardMapping(&xev->xmapping); | 450 XRefreshKeyboardMapping(&xev->xmapping); |
| 454 break; | 451 break; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 476 xev = &last_event; | 473 xev = &last_event; |
| 477 } else { | 474 } else { |
| 478 break; | 475 break; |
| 479 } | 476 } |
| 480 } | 477 } |
| 481 | 478 |
| 482 MouseEvent mouseev(xev); | 479 MouseEvent mouseev(xev); |
| 483 handled = root_window_->DispatchMouseEvent(&mouseev); | 480 handled = root_window_->DispatchMouseEvent(&mouseev); |
| 484 break; | 481 break; |
| 485 } | 482 } |
| 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 } |
| 486 } | 489 } |
| 487 return handled ? base::MessagePumpDispatcher::EVENT_PROCESSED : | 490 return handled ? base::MessagePumpDispatcher::EVENT_PROCESSED : |
| 488 base::MessagePumpDispatcher::EVENT_IGNORED; | 491 base::MessagePumpDispatcher::EVENT_IGNORED; |
| 489 } | 492 } |
| 490 | 493 |
| 491 void RootWindowHostLinux::SetRootWindow(RootWindow* root_window) { | 494 void RootWindowHostLinux::SetRootWindow(RootWindow* root_window) { |
| 492 root_window_ = root_window; | 495 root_window_ = root_window; |
| 493 } | 496 } |
| 494 | 497 |
| 495 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { | 498 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { |
| 496 return xwindow_; | 499 return xwindow_; |
| 497 } | 500 } |
| 498 | 501 |
| 499 void RootWindowHostLinux::Show() { | 502 void RootWindowHostLinux::Show() { |
| 500 XMapWindow(xdisplay_, xwindow_); | 503 XMapWindow(xdisplay_, xwindow_); |
| 501 } | 504 } |
| 502 | 505 |
| 503 void RootWindowHostLinux::ToggleFullScreen() { | 506 void RootWindowHostLinux::ToggleFullScreen() { |
| 504 NOTIMPLEMENTED(); | 507 NOTIMPLEMENTED(); |
| 505 } | 508 } |
| 506 | 509 |
| 507 gfx::Rect RootWindowHostLinux::GetBounds() const { | 510 gfx::Rect RootWindowHostLinux::GetBounds() const { |
| 508 return bounds_; | 511 return bounds_; |
| 509 } | 512 } |
| 510 | 513 |
| 511 void RootWindowHostLinux::SetBounds(const gfx::Rect& bounds) { | 514 void RootWindowHostLinux::SetBounds(const gfx::Rect& bounds) { |
| 512 bool size_changed = bounds_.size() != bounds.size(); | 515 bool size_changed = bounds_.size() != bounds.size(); |
| 513 if (bounds == bounds_) | 516 if (bounds == bounds_) { |
| 517 root_window_->SchedulePaintInRect(root_window_->bounds()); |
| 514 return; | 518 return; |
| 519 } |
| 515 if (bounds.size() != bounds_.size()) | 520 if (bounds.size() != bounds_.size()) |
| 516 XResizeWindow(xdisplay_, xwindow_, bounds.width(), bounds.height()); | 521 XResizeWindow(xdisplay_, xwindow_, bounds.width(), bounds.height()); |
| 517 if (bounds.origin() != bounds_.origin()) | 522 if (bounds.origin() != bounds_.origin()) |
| 518 XMoveWindow(xdisplay_, xwindow_, bounds.x(), bounds.y()); | 523 XMoveWindow(xdisplay_, xwindow_, bounds.x(), bounds.y()); |
| 519 | 524 |
| 520 // Assume that the resize will go through as requested, which should be the | 525 // Assume that the resize will go through as requested, which should be the |
| 521 // case if we're running without a window manager. If there's a window | 526 // case if we're running without a window manager. If there's a window |
| 522 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a | 527 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a |
| 523 // (possibly synthetic) ConfigureNotify about the actual size and correct | 528 // (possibly synthetic) ConfigureNotify about the actual size and correct |
| 524 // |bounds_| later. | 529 // |bounds_| later. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 | 591 |
| 587 void RootWindowHostLinux::UnConfineCursor() { | 592 void RootWindowHostLinux::UnConfineCursor() { |
| 588 XUngrabPointer(xdisplay_, CurrentTime); | 593 XUngrabPointer(xdisplay_, CurrentTime); |
| 589 } | 594 } |
| 590 | 595 |
| 591 void RootWindowHostLinux::MoveCursorTo(const gfx::Point& location) { | 596 void RootWindowHostLinux::MoveCursorTo(const gfx::Point& location) { |
| 592 XWarpPointer(xdisplay_, None, xwindow_, 0, 0, 0, 0, location.x(), | 597 XWarpPointer(xdisplay_, None, xwindow_, 0, 0, 0, 0, location.x(), |
| 593 location.y()); | 598 location.y()); |
| 594 } | 599 } |
| 595 | 600 |
| 601 void RootWindowHostLinux::SetFocusWhenShown(bool focus_when_shown) { |
| 602 static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME"; |
| 603 focus_when_shown_ = focus_when_shown; |
| 604 if (IsWindowManagerPresent() && !focus_when_shown_) { |
| 605 ui::SetIntProperty(xwindow_, |
| 606 k_NET_WM_USER_TIME, |
| 607 k_NET_WM_USER_TIME, |
| 608 0); |
| 609 } |
| 610 } |
| 611 |
| 596 void RootWindowHostLinux::PostNativeEvent( | 612 void RootWindowHostLinux::PostNativeEvent( |
| 597 const base::NativeEvent& native_event) { | 613 const base::NativeEvent& native_event) { |
| 598 DCHECK(xwindow_); | 614 DCHECK(xwindow_); |
| 599 DCHECK(xdisplay_); | 615 DCHECK(xdisplay_); |
| 600 XEvent xevent = *native_event; | 616 XEvent xevent = *native_event; |
| 601 xevent.xany.display = xdisplay_; | 617 xevent.xany.display = xdisplay_; |
| 602 xevent.xany.window = xwindow_; | 618 xevent.xany.window = xwindow_; |
| 603 | 619 |
| 604 switch (xevent.type) { | 620 switch (xevent.type) { |
| 605 case EnterNotify: | 621 case EnterNotify: |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 return new RootWindowHostLinux(bounds); | 662 return new RootWindowHostLinux(bounds); |
| 647 } | 663 } |
| 648 | 664 |
| 649 // static | 665 // static |
| 650 gfx::Size RootWindowHost::GetNativeScreenSize() { | 666 gfx::Size RootWindowHost::GetNativeScreenSize() { |
| 651 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); | 667 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); |
| 652 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 668 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
| 653 } | 669 } |
| 654 | 670 |
| 655 } // namespace aura | 671 } // namespace aura |
| OLD | NEW |