| 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/Xfixes.h> | 8 #include <X11/extensions/Xfixes.h> |
| 9 #include <X11/extensions/XInput2.h> | 9 #include <X11/extensions/XInput2.h> |
| 10 #include <X11/extensions/Xrandr.h> | 10 #include <X11/extensions/Xrandr.h> |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 namespace aura { | 44 namespace aura { |
| 45 | 45 |
| 46 namespace { | 46 namespace { |
| 47 | 47 |
| 48 // Standard Linux mouse buttons for going back and forward. | 48 // Standard Linux mouse buttons for going back and forward. |
| 49 const int kBackMouseButton = 8; | 49 const int kBackMouseButton = 8; |
| 50 const int kForwardMouseButton = 9; | 50 const int kForwardMouseButton = 9; |
| 51 | 51 |
| 52 const int kAnimatedCursorFrameDelayMs = 25; | 52 const int kAnimatedCursorFrameDelayMs = 25; |
| 53 | 53 |
| 54 // These are the same values that are used to calibrate touch events in |
| 55 // |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc). |
| 56 // TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605) |
| 57 const int kXRootWindowPaddingLeft = 40; |
| 58 const int kXRootWindowPaddingRight = 40; |
| 59 const int kXRootWindowPaddingBottom = 30; |
| 60 const int kXRootWindowPaddingTop = 0; |
| 61 |
| 54 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__"; | 62 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__"; |
| 55 | 63 |
| 56 const char* kAtomsToCache[] = { | 64 const char* kAtomsToCache[] = { |
| 57 "WM_DELETE_WINDOW", | 65 "WM_DELETE_WINDOW", |
| 58 "_NET_WM_PING", | 66 "_NET_WM_PING", |
| 59 "_NET_WM_PID", | 67 "_NET_WM_PID", |
| 60 "WM_S0", | 68 "WM_S0", |
| 61 NULL | 69 NULL |
| 62 }; | 70 }; |
| 63 | 71 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 } else { | 269 } else { |
| 262 // This isn't an event we want so free its cookie data. | 270 // This isn't an event we want so free its cookie data. |
| 263 XFreeEventData(display, &next_event.xcookie); | 271 XFreeEventData(display, &next_event.xcookie); |
| 264 } | 272 } |
| 265 } | 273 } |
| 266 break; | 274 break; |
| 267 } | 275 } |
| 268 return num_coalesed; | 276 return num_coalesed; |
| 269 } | 277 } |
| 270 | 278 |
| 279 void SelectEventsForRootWindow() { |
| 280 XIEventMask evmask; |
| 281 unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {}; |
| 282 memset(mask, 0, sizeof(mask)); |
| 283 |
| 284 XISetMask(mask, XI_HierarchyChanged); |
| 285 |
| 286 XISetMask(mask, XI_KeyPress); |
| 287 XISetMask(mask, XI_KeyRelease); |
| 288 |
| 289 #if defined(USE_XI2_MT) |
| 290 XISetMask(mask, XI_TouchBegin); |
| 291 XISetMask(mask, XI_TouchUpdate); |
| 292 XISetMask(mask, XI_TouchEnd); |
| 293 #endif |
| 294 XISetMask(mask, XI_ButtonPress); |
| 295 XISetMask(mask, XI_ButtonRelease); |
| 296 XISetMask(mask, XI_Motion); |
| 297 |
| 298 evmask.deviceid = XIAllDevices; |
| 299 evmask.mask_len = sizeof(mask); |
| 300 evmask.mask = mask; |
| 301 |
| 302 Display* display = ui::GetXDisplay(); |
| 303 ::Window root_window = ui::GetX11RootWindow(); |
| 304 XISelectEvents(display, root_window, &evmask, 1); |
| 305 |
| 306 // Receive resize events for the root-window so |x_root_bounds_| can be |
| 307 // updated. |
| 308 XSelectInput(display, root_window, StructureNotifyMask); |
| 309 } |
| 310 |
| 271 // We emulate Windows' WM_KEYDOWN and WM_CHAR messages. WM_CHAR events are only | 311 // We emulate Windows' WM_KEYDOWN and WM_CHAR messages. WM_CHAR events are only |
| 272 // generated for certain keys; see | 312 // generated for certain keys; see |
| 273 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx. Per | 313 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx. Per |
| 274 // discussion on http://crbug.com/108480, char events should furthermore not be | 314 // discussion on http://crbug.com/108480, char events should furthermore not be |
| 275 // generated for Tab, Escape, and Backspace. | 315 // generated for Tab, Escape, and Backspace. |
| 276 bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) { | 316 bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) { |
| 277 if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) || | 317 if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) || |
| 278 (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) || | 318 (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) || |
| 279 (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) { | 319 (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) { |
| 280 return true; | 320 return true; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 xwindow_ = XCreateWindow( | 564 xwindow_ = XCreateWindow( |
| 525 xdisplay_, x_root_window_, | 565 xdisplay_, x_root_window_, |
| 526 bounds.x(), bounds.y(), bounds.width(), bounds.height(), | 566 bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
| 527 0, // border width | 567 0, // border width |
| 528 CopyFromParent, // depth | 568 CopyFromParent, // depth |
| 529 InputOutput, | 569 InputOutput, |
| 530 CopyFromParent, // visual | 570 CopyFromParent, // visual |
| 531 CWBackPixmap, | 571 CWBackPixmap, |
| 532 &swa); | 572 &swa); |
| 533 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); | 573 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); |
| 574 base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this); |
| 534 | 575 |
| 535 prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this)); | 576 prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this)); |
| 536 | 577 |
| 537 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | | 578 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | |
| 538 KeyPressMask | KeyReleaseMask | | 579 KeyPressMask | KeyReleaseMask | |
| 539 EnterWindowMask | LeaveWindowMask | | 580 EnterWindowMask | LeaveWindowMask | |
| 540 ExposureMask | VisibilityChangeMask | | 581 ExposureMask | VisibilityChangeMask | |
| 541 StructureNotifyMask | PropertyChangeMask | | 582 StructureNotifyMask | PropertyChangeMask | |
| 542 PointerMotionMask; | 583 PointerMotionMask; |
| 543 XSelectInput(xdisplay_, xwindow_, event_mask); | 584 XSelectInput(xdisplay_, xwindow_, event_mask); |
| 544 XFlush(xdisplay_); | 585 XFlush(xdisplay_); |
| 545 | 586 |
| 546 if (base::MessagePumpForUI::HasXInput2()) | 587 if (base::MessagePumpForUI::HasXInput2()) |
| 547 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); | 588 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
| 548 | 589 |
| 590 SelectEventsForRootWindow(); |
| 591 |
| 592 // Get the initial size of the X root window. |
| 593 XWindowAttributes attrs; |
| 594 XGetWindowAttributes(xdisplay_, x_root_window_, &attrs); |
| 595 x_root_bounds_.SetRect(attrs.x, attrs.y, attrs.width, attrs.height); |
| 596 |
| 549 // Initialize invisible cursor. | 597 // Initialize invisible cursor. |
| 550 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | 598 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 551 XColor black; | 599 XColor black; |
| 552 black.red = black.green = black.blue = 0; | 600 black.red = black.green = black.blue = 0; |
| 553 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_, | 601 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_, |
| 554 nodata, 8, 8); | 602 nodata, 8, 8); |
| 555 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank, | 603 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank, |
| 556 &black, &black, 0, 0); | 604 &black, &black, 0, 0); |
| 557 XFreePixmap(xdisplay_, blank); | 605 XFreePixmap(xdisplay_, blank); |
| 558 | 606 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 586 // window to broadcast. | 634 // window to broadcast. |
| 587 // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting. | 635 // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting. |
| 588 static int root_window_number = 0; | 636 static int root_window_number = 0; |
| 589 std::string name = StringPrintf("aura_root_%d", root_window_number++); | 637 std::string name = StringPrintf("aura_root_%d", root_window_number++); |
| 590 XStoreName(xdisplay_, xwindow_, name.c_str()); | 638 XStoreName(xdisplay_, xwindow_, name.c_str()); |
| 591 XRRSelectInput(xdisplay_, x_root_window_, | 639 XRRSelectInput(xdisplay_, x_root_window_, |
| 592 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); | 640 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); |
| 593 } | 641 } |
| 594 | 642 |
| 595 RootWindowHostLinux::~RootWindowHostLinux() { | 643 RootWindowHostLinux::~RootWindowHostLinux() { |
| 644 base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this); |
| 596 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); | 645 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); |
| 597 | 646 |
| 598 UnConfineCursor(); | 647 UnConfineCursor(); |
| 599 | 648 |
| 600 XDestroyWindow(xdisplay_, xwindow_); | 649 XDestroyWindow(xdisplay_, xwindow_); |
| 601 | 650 |
| 602 // Clears XCursorCache. | 651 // Clears XCursorCache. |
| 603 ui::GetXCursor(ui::kCursorClearXCursorCache); | 652 ui::GetXCursor(ui::kCursorClearXCursorCache); |
| 604 | 653 |
| 605 XFreeCursor(xdisplay_, invisible_cursor_); | 654 XFreeCursor(xdisplay_, invisible_cursor_); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 case ButtonRelease: { | 690 case ButtonRelease: { |
| 642 ui::MouseEvent mouseev(xev); | 691 ui::MouseEvent mouseev(xev); |
| 643 delegate_->OnHostMouseEvent(&mouseev); | 692 delegate_->OnHostMouseEvent(&mouseev); |
| 644 break; | 693 break; |
| 645 } | 694 } |
| 646 case FocusOut: | 695 case FocusOut: |
| 647 if (xev->xfocus.mode != NotifyGrab) | 696 if (xev->xfocus.mode != NotifyGrab) |
| 648 delegate_->OnHostLostCapture(); | 697 delegate_->OnHostLostCapture(); |
| 649 break; | 698 break; |
| 650 case ConfigureNotify: { | 699 case ConfigureNotify: { |
| 651 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 700 if (xev->xconfigure.window == xwindow_) { |
| 652 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 701 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
| 653 // It's possible that the X window may be resized by some other means than | 702 // It's possible that the X window may be resized by some other means |
| 654 // from within aura (e.g. the X window manager can change the size). Make | 703 // than from within aura (e.g. the X window manager can change the |
| 655 // sure the root window size is maintained properly. | 704 // size). Make sure the root window size is maintained properly. |
| 656 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, | 705 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, |
| 657 xev->xconfigure.width, xev->xconfigure.height); | 706 xev->xconfigure.width, xev->xconfigure.height); |
| 658 bool size_changed = bounds_.size() != bounds.size(); | 707 bool size_changed = bounds_.size() != bounds.size(); |
| 659 bool origin_changed = bounds_.origin() != bounds.origin(); | 708 bool origin_changed = bounds_.origin() != bounds.origin(); |
| 660 bounds_ = bounds; | 709 bounds_ = bounds; |
| 661 // Update barrier and mouse location when the root window has | 710 // Update barrier and mouse location when the root window has |
| 662 // moved/resized. | 711 // moved/resized. |
| 663 if (pointer_barriers_.get() && (size_changed || origin_changed)) { | 712 if (pointer_barriers_.get() && (size_changed || origin_changed)) { |
| 664 UnConfineCursor(); | 713 UnConfineCursor(); |
| 665 RootWindow* root = delegate_->AsRootWindow(); | 714 RootWindow* root = delegate_->AsRootWindow(); |
| 666 client::ScreenPositionClient* client = | 715 client::ScreenPositionClient* client = |
| 667 client::GetScreenPositionClient(root); | 716 client::GetScreenPositionClient(root); |
| 668 if (client) { | 717 if (client) { |
| 669 gfx::Point p = gfx::Screen::GetCursorScreenPoint(); | 718 gfx::Point p = gfx::Screen::GetCursorScreenPoint(); |
| 670 client->ConvertPointFromScreen(root, &p); | 719 client->ConvertPointFromScreen(root, &p); |
| 671 if (root->ContainsPoint(p)) { | 720 if (root->ContainsPoint(p)) { |
| 672 root->ConvertPointToNativeScreen(&p); | 721 root->ConvertPointToNativeScreen(&p); |
| 673 XWarpPointer( | 722 XWarpPointer( |
| 674 xdisplay_, None, x_root_window_, 0, 0, 0, 0, p.x(), p.y()); | 723 xdisplay_, None, x_root_window_, 0, 0, 0, 0, p.x(), p.y()); |
| 724 } |
| 675 } | 725 } |
| 726 ConfineCursorToRootWindow(); |
| 676 } | 727 } |
| 677 ConfineCursorToRootWindow(); | 728 if (size_changed) |
| 729 delegate_->OnHostResized(bounds.size()); |
| 730 if (origin_changed) |
| 731 delegate_->OnHostMoved(bounds_.origin()); |
| 732 } else { |
| 733 DCHECK_EQ(x_root_window_, xev->xconfigure.event); |
| 734 DCHECK_EQ(x_root_window_, xev->xconfigure.window); |
| 735 x_root_bounds_.SetRect(xev->xconfigure.x, xev->xconfigure.y, |
| 736 xev->xconfigure.width, xev->xconfigure.height); |
| 678 } | 737 } |
| 679 if (size_changed) | |
| 680 delegate_->OnHostResized(bounds.size()); | |
| 681 if (origin_changed) | |
| 682 delegate_->OnHostMoved(bounds_.origin()); | |
| 683 break; | 738 break; |
| 684 } | 739 } |
| 685 case GenericEvent: { | 740 case GenericEvent: { |
| 686 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); | 741 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); |
| 687 if (!factory->ShouldProcessXI2Event(xev)) | 742 if (!factory->ShouldProcessXI2Event(xev)) |
| 688 break; | 743 break; |
| 689 | 744 |
| 690 ui::EventType type = ui::EventTypeFromNative(xev); | 745 ui::EventType type = ui::EventTypeFromNative(xev); |
| 691 XEvent last_event; | 746 XEvent last_event; |
| 692 int num_coalesced = 0; | 747 int num_coalesced = 0; |
| 693 | 748 |
| 694 switch (type) { | 749 switch (type) { |
| 695 case ui::ET_TOUCH_MOVED: | 750 case ui::ET_TOUCH_MOVED: |
| 696 num_coalesced = CoalescePendingMotionEvents(xev, &last_event); | 751 num_coalesced = CoalescePendingMotionEvents(xev, &last_event); |
| 697 if (num_coalesced > 0) | 752 if (num_coalesced > 0) |
| 698 xev = &last_event; | 753 xev = &last_event; |
| 699 // fallthrough | 754 // fallthrough |
| 700 case ui::ET_TOUCH_PRESSED: | 755 case ui::ET_TOUCH_PRESSED: |
| 701 case ui::ET_TOUCH_RELEASED: { | 756 case ui::ET_TOUCH_RELEASED: { |
| 702 ui::TouchEvent touchev(xev); | 757 ui::TouchEvent touchev(xev); |
| 758 // X maps the touch-surface to the size of the X root-window. In |
| 759 // multi-monitor setup, the X root-window size is a combination of |
| 760 // both the monitor sizes. So it is necessary to remap the location of |
| 761 // the event from the X root-window to the X host-window for the aura |
| 762 // root-window. |
| 763 touchev.CalibrateLocation(x_root_bounds_.size(), bounds_.size()); |
| 764 if (!bounds_.Contains(touchev.location())) { |
| 765 // This might still be in the bezel region. |
| 766 gfx::Rect expanded(bounds_); |
| 767 expanded.Inset(-kXRootWindowPaddingLeft, |
| 768 -kXRootWindowPaddingTop, |
| 769 -kXRootWindowPaddingRight, |
| 770 -kXRootWindowPaddingBottom); |
| 771 if (!expanded.Contains(touchev.location())) |
| 772 break; |
| 773 } |
| 703 delegate_->OnHostTouchEvent(&touchev); | 774 delegate_->OnHostTouchEvent(&touchev); |
| 704 break; | 775 break; |
| 705 } | 776 } |
| 706 case ui::ET_MOUSE_MOVED: | 777 case ui::ET_MOUSE_MOVED: |
| 707 case ui::ET_MOUSE_DRAGGED: | 778 case ui::ET_MOUSE_DRAGGED: |
| 708 case ui::ET_MOUSE_PRESSED: | 779 case ui::ET_MOUSE_PRESSED: |
| 709 case ui::ET_MOUSE_RELEASED: | 780 case ui::ET_MOUSE_RELEASED: |
| 710 case ui::ET_MOUSE_ENTERED: | 781 case ui::ET_MOUSE_ENTERED: |
| 711 case ui::ET_MOUSE_EXITED: { | 782 case ui::ET_MOUSE_EXITED: { |
| 712 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) { | 783 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) { |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1136 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); | 1207 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); |
| 1137 } | 1208 } |
| 1138 | 1209 |
| 1139 // static | 1210 // static |
| 1140 gfx::Size RootWindowHost::GetNativeScreenSize() { | 1211 gfx::Size RootWindowHost::GetNativeScreenSize() { |
| 1141 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 1212 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
| 1142 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 1213 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
| 1143 } | 1214 } |
| 1144 | 1215 |
| 1145 } // namespace aura | 1216 } // namespace aura |
| OLD | NEW |