Chromium Code Reviews| 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/window_tree_host_x11.h" | 5 #include "ui/aura/window_tree_host_x11.h" |
| 6 | 6 |
| 7 #include <strings.h> | 7 #include <strings.h> |
| 8 #include <X11/cursorfont.h> | 8 #include <X11/cursorfont.h> |
| 9 #include <X11/extensions/Xfixes.h> | 9 #include <X11/extensions/Xfixes.h> |
| 10 #include <X11/extensions/XInput2.h> | 10 #include <X11/extensions/XInput2.h> |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 virtual ~TouchEventCalibrate() { | 142 virtual ~TouchEventCalibrate() { |
| 143 base::MessageLoopForUI::current()->RemoveObserver(this); | 143 base::MessageLoopForUI::current()->RemoveObserver(this); |
| 144 } | 144 } |
| 145 | 145 |
| 146 // Modify the location of the |event|, | 146 // Modify the location of the |event|, |
| 147 // expanding it from |bounds| to (|bounds| + bezels). | 147 // expanding it from |bounds| to (|bounds| + bezels). |
| 148 // Required when touchscreen is bigger than screen (i.e. has bezels), | 148 // Required when touchscreen is bigger than screen (i.e. has bezels), |
| 149 // because we receive events in touchscreen coordinates, | 149 // because we receive events in touchscreen coordinates, |
| 150 // which need to be expanded when converting to screen coordinates, | 150 // which need to be expanded when converting to screen coordinates, |
| 151 // so that location on bezels will be outside of screen area. | 151 // so that location on bezels will be outside of screen area. |
| 152 void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) { | 152 void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) { |
|
sadrul
2014/03/15 19:32:51
Why do we still need this? Shouldn't this be part
ynovikov
2014/03/27 23:35:53
I agree. Originally the second calibration was nee
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Lets do this in a separate CL if necessary.
| |
| 153 #if defined(USE_XI2_MT) | 153 #if defined(USE_XI2_MT) |
| 154 int x = event->x(); | 154 int x = event->x(); |
| 155 int y = event->y(); | 155 int y = event->y(); |
| 156 | 156 |
| 157 if (!left_ && !right_ && !top_ && !bottom_) | 157 if (!left_ && !right_ && !top_ && !bottom_) |
| 158 return; | 158 return; |
| 159 | 159 |
| 160 const int resolution_x = bounds.width(); | 160 const int resolution_x = bounds.width(); |
| 161 const int resolution_y = bounds.height(); | 161 const int resolution_y = bounds.height(); |
| 162 // The "grace area" (10% in this case) is to make it easier for the user to | 162 // The "grace area" (10% in this case) is to make it easier for the user to |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 242 //////////////////////////////////////////////////////////////////////////////// | 242 //////////////////////////////////////////////////////////////////////////////// |
| 243 // WindowTreeHostX11 | 243 // WindowTreeHostX11 |
| 244 | 244 |
| 245 WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds) | 245 WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds) |
| 246 : xdisplay_(gfx::GetXDisplay()), | 246 : xdisplay_(gfx::GetXDisplay()), |
| 247 xwindow_(0), | 247 xwindow_(0), |
| 248 x_root_window_(DefaultRootWindow(xdisplay_)), | 248 x_root_window_(DefaultRootWindow(xdisplay_)), |
| 249 current_cursor_(ui::kCursorNull), | 249 current_cursor_(ui::kCursorNull), |
| 250 window_mapped_(false), | 250 window_mapped_(false), |
| 251 bounds_(bounds), | 251 bounds_(bounds), |
| 252 is_internal_display_(false), | |
| 253 touch_calibrate_(new internal::TouchEventCalibrate), | 252 touch_calibrate_(new internal::TouchEventCalibrate), |
| 254 atom_cache_(xdisplay_, kAtomsToCache) { | 253 atom_cache_(xdisplay_, kAtomsToCache) { |
| 255 XSetWindowAttributes swa; | 254 XSetWindowAttributes swa; |
| 256 memset(&swa, 0, sizeof(swa)); | 255 memset(&swa, 0, sizeof(swa)); |
| 257 swa.background_pixmap = None; | 256 swa.background_pixmap = None; |
| 258 swa.override_redirect = default_override_redirect; | 257 swa.override_redirect = default_override_redirect; |
| 259 xwindow_ = XCreateWindow( | 258 xwindow_ = XCreateWindow( |
| 260 xdisplay_, x_root_window_, | 259 xdisplay_, x_root_window_, |
| 261 bounds.x(), bounds.y(), bounds.width(), bounds.height(), | 260 bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
| 262 0, // border width | 261 0, // border width |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 402 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 401 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
| 403 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 402 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
| 404 // It's possible that the X window may be resized by some other means | 403 // It's possible that the X window may be resized by some other means |
| 405 // than from within aura (e.g. the X window manager can change the | 404 // than from within aura (e.g. the X window manager can change the |
| 406 // size). Make sure the root window size is maintained properly. | 405 // size). Make sure the root window size is maintained properly. |
| 407 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, | 406 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, |
| 408 xev->xconfigure.width, xev->xconfigure.height); | 407 xev->xconfigure.width, xev->xconfigure.height); |
| 409 bool size_changed = bounds_.size() != bounds.size(); | 408 bool size_changed = bounds_.size() != bounds.size(); |
| 410 bool origin_changed = bounds_.origin() != bounds.origin(); | 409 bool origin_changed = bounds_.origin() != bounds.origin(); |
| 411 bounds_ = bounds; | 410 bounds_ = bounds; |
| 412 UpdateIsInternalDisplay(); | |
| 413 // Always update barrier and mouse location because |bounds_| might | 411 // Always update barrier and mouse location because |bounds_| might |
| 414 // have already been updated in |SetBounds|. | 412 // have already been updated in |SetBounds|. |
| 415 if (pointer_barriers_) { | 413 if (pointer_barriers_) { |
| 416 UnConfineCursor(); | 414 UnConfineCursor(); |
| 417 ConfineCursorToRootWindow(); | 415 ConfineCursorToRootWindow(); |
| 418 } | 416 } |
| 419 if (size_changed) | 417 if (size_changed) |
| 420 OnHostResized(bounds.size()); | 418 OnHostResized(bounds.size()); |
| 421 if (origin_changed) | 419 if (origin_changed) |
| 422 OnHostMoved(bounds_.origin()); | 420 OnHostMoved(bounds_.origin()); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 549 } | 547 } |
| 550 if (value_mask) | 548 if (value_mask) |
| 551 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); | 549 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); |
| 552 | 550 |
| 553 // Assume that the resize will go through as requested, which should be the | 551 // Assume that the resize will go through as requested, which should be the |
| 554 // case if we're running without a window manager. If there's a window | 552 // case if we're running without a window manager. If there's a window |
| 555 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a | 553 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a |
| 556 // (possibly synthetic) ConfigureNotify about the actual size and correct | 554 // (possibly synthetic) ConfigureNotify about the actual size and correct |
| 557 // |bounds_| later. | 555 // |bounds_| later. |
| 558 bounds_ = bounds; | 556 bounds_ = bounds; |
| 559 UpdateIsInternalDisplay(); | |
| 560 if (origin_changed) | 557 if (origin_changed) |
| 561 OnHostMoved(bounds.origin()); | 558 OnHostMoved(bounds.origin()); |
| 562 if (size_changed || current_scale != new_scale) { | 559 if (size_changed || current_scale != new_scale) { |
| 563 OnHostResized(bounds.size()); | 560 OnHostResized(bounds.size()); |
| 564 } else { | 561 } else { |
| 565 window()->SchedulePaintInRect(window()->bounds()); | 562 window()->SchedulePaintInRect(window()->bounds()); |
| 566 } | 563 } |
| 567 } | 564 } |
| 568 | 565 |
| 569 gfx::Insets WindowTreeHostX11::GetInsets() const { | 566 gfx::Insets WindowTreeHostX11::GetInsets() const { |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 717 } | 714 } |
| 718 | 715 |
| 719 void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) { | 716 void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) { |
| 720 SetCrOSTapPaused(!show); | 717 SetCrOSTapPaused(!show); |
| 721 } | 718 } |
| 722 | 719 |
| 723 void WindowTreeHostX11::OnWindowInitialized(Window* window) { | 720 void WindowTreeHostX11::OnWindowInitialized(Window* window) { |
| 724 } | 721 } |
| 725 | 722 |
| 726 void WindowTreeHostX11::OnHostInitialized(WindowTreeHost* host) { | 723 void WindowTreeHostX11::OnHostInitialized(WindowTreeHost* host) { |
| 727 // TODO(beng): I'm not sure that this comment makes much sense anymore?? | |
| 728 // UpdateIsInternalDisplay relies on WED's kDisplayIdKey property being set | |
| 729 // available by the time WED::Init is called. (set in | |
| 730 // DisplayManager::CreateRootWindowForDisplay) | |
| 731 // Ready when NotifyHostInitialized is called from WED::Init. | |
| 732 if (host != this) | 724 if (host != this) |
| 733 return; | 725 return; |
| 734 UpdateIsInternalDisplay(); | |
| 735 | 726 |
| 736 // We have to enable Tap-to-click by default because the cursor is set to | 727 // We have to enable Tap-to-click by default because the cursor is set to |
| 737 // visible in Shell::InitRootWindowController. | 728 // visible in Shell::InitRootWindowController. |
| 738 SetCrOSTapPaused(false); | 729 SetCrOSTapPaused(false); |
| 739 } | 730 } |
| 740 | 731 |
| 741 ui::EventProcessor* WindowTreeHostX11::GetEventProcessor() { | 732 ui::EventProcessor* WindowTreeHostX11::GetEventProcessor() { |
| 742 return dispatcher(); | 733 return dispatcher(); |
| 743 } | 734 } |
| 744 | 735 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 755 | 746 |
| 756 ui::EventType type = ui::EventTypeFromNative(xev); | 747 ui::EventType type = ui::EventTypeFromNative(xev); |
| 757 XEvent last_event; | 748 XEvent last_event; |
| 758 int num_coalesced = 0; | 749 int num_coalesced = 0; |
| 759 | 750 |
| 760 switch (type) { | 751 switch (type) { |
| 761 case ui::ET_TOUCH_MOVED: | 752 case ui::ET_TOUCH_MOVED: |
| 762 case ui::ET_TOUCH_PRESSED: | 753 case ui::ET_TOUCH_PRESSED: |
| 763 case ui::ET_TOUCH_CANCELLED: | 754 case ui::ET_TOUCH_CANCELLED: |
| 764 case ui::ET_TOUCH_RELEASED: { | 755 case ui::ET_TOUCH_RELEASED: { |
| 765 #if defined(OS_CHROMEOS) | |
| 766 // Bail out early before generating a ui::TouchEvent if this event | 756 // Bail out early before generating a ui::TouchEvent if this event |
| 767 // is not within the range of this RootWindow. Converting an xevent | 757 // is targeting this RootWindow. |
|
oshima
2014/03/14 21:53:53
then you can do something like
if (GetTouchCalibr
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
I moved TouchCalibrate into DeviceDataManager.
| |
| 768 // to ui::TouchEvent might change the state of the global touch tracking | 758 // Converting an xevent to ui::TouchEvent might change the state of |
| 769 // state, e.g. touch release event can remove the touch id from the | 759 // the global touch tracking state, e.g. touch release event can |
| 770 // record, and doing this multiple time when there are multiple | 760 // remove the touch id from the record, and doing this multiple time |
| 771 // RootWindow will cause problem. So only generate the ui::TouchEvent | 761 // when there are multiple RootWindow will cause problem. So only |
| 772 // when we are sure it belongs to this RootWindow. | 762 // generate the ui::TouchEvent when we are sure it is targeting this |
| 773 if (base::SysInfo::IsRunningOnChromeOS() && | 763 // RootWindow. |
| 774 !bounds_.Contains(ui::EventLocationFromNative(xev))) | 764 if (!IsTouchEventTargetingThisRootWindow(xev)) |
| 775 break; | 765 break; |
| 776 #endif // defined(OS_CHROMEOS) | |
| 777 ui::TouchEvent touchev(xev); | 766 ui::TouchEvent touchev(xev); |
| 778 #if defined(OS_CHROMEOS) | 767 CalibrateTouchEvent(xev, &touchev); |
| 779 if (base::SysInfo::IsRunningOnChromeOS()) { | |
| 780 // X maps the touch-surface to the size of the X root-window. | |
| 781 // In multi-monitor setup, Coordinate Transformation Matrix | |
| 782 // repositions the touch-surface onto part of X root-window | |
| 783 // containing aura root-window corresponding to the touchscreen. | |
| 784 // However, if aura root-window has non-zero origin, | |
| 785 // we need to relocate the event into aura root-window coordinates. | |
| 786 touchev.Relocate(bounds_.origin()); | |
|
ynovikov
2014/03/27 23:35:53
I think this is the only use of Relocate(), could
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Done.
| |
| 787 #if defined(USE_XI2_MT) | |
| 788 if (is_internal_display_) | |
| 789 touch_calibrate_->Calibrate(&touchev, bounds_); | |
| 790 #endif // defined(USE_XI2_MT) | |
| 791 } | |
| 792 #endif // defined(OS_CHROMEOS) | |
| 793 SendEventToProcessor(&touchev); | 768 SendEventToProcessor(&touchev); |
| 794 break; | 769 break; |
| 795 } | 770 } |
| 796 case ui::ET_MOUSE_MOVED: | 771 case ui::ET_MOUSE_MOVED: |
| 797 case ui::ET_MOUSE_DRAGGED: | 772 case ui::ET_MOUSE_DRAGGED: |
| 798 case ui::ET_MOUSE_PRESSED: | 773 case ui::ET_MOUSE_PRESSED: |
| 799 case ui::ET_MOUSE_RELEASED: | 774 case ui::ET_MOUSE_RELEASED: |
| 800 case ui::ET_MOUSE_ENTERED: | 775 case ui::ET_MOUSE_ENTERED: |
| 801 case ui::ET_MOUSE_EXITED: { | 776 case ui::ET_MOUSE_EXITED: { |
| 802 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) { | 777 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 861 // host window, then convert it back to this host window's coordinate. | 836 // host window, then convert it back to this host window's coordinate. |
| 862 screen_position_client->ConvertHostPointToScreen(root_window, &location); | 837 screen_position_client->ConvertHostPointToScreen(root_window, &location); |
| 863 screen_position_client->ConvertPointFromScreen(root_window, &location); | 838 screen_position_client->ConvertPointFromScreen(root_window, &location); |
| 864 ConvertPointToHost(&location); | 839 ConvertPointToHost(&location); |
| 865 event->set_location(location); | 840 event->set_location(location); |
| 866 event->set_root_location(location); | 841 event->set_root_location(location); |
| 867 } | 842 } |
| 868 SendEventToProcessor(event); | 843 SendEventToProcessor(event); |
| 869 } | 844 } |
| 870 | 845 |
| 871 void WindowTreeHostX11::UpdateIsInternalDisplay() { | |
| 872 Window* root_window = window(); | |
| 873 gfx::Screen* screen = gfx::Screen::GetScreenFor(root_window); | |
| 874 gfx::Display display = screen->GetDisplayNearestWindow(root_window); | |
| 875 is_internal_display_ = display.IsInternal(); | |
| 876 } | |
| 877 | |
| 878 void WindowTreeHostX11::SetCrOSTapPaused(bool state) { | 846 void WindowTreeHostX11::SetCrOSTapPaused(bool state) { |
| 879 #if defined(OS_CHROMEOS) | 847 #if defined(OS_CHROMEOS) |
| 880 if (!ui::IsXInput2Available()) | 848 if (!ui::IsXInput2Available()) |
| 881 return; | 849 return; |
| 882 // Temporarily pause tap-to-click when the cursor is hidden. | 850 // Temporarily pause tap-to-click when the cursor is hidden. |
| 883 Atom prop = atom_cache_.GetAtom("Tap Paused"); | 851 Atom prop = atom_cache_.GetAtom("Tap Paused"); |
| 884 unsigned char value = state; | 852 unsigned char value = state; |
| 885 XIDeviceList dev_list = | 853 XIDeviceList dev_list = |
| 886 ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(xdisplay_); | 854 ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(xdisplay_); |
| 887 | 855 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 898 if (result != Success) | 866 if (result != Success) |
| 899 continue; | 867 continue; |
| 900 XFree(data); | 868 XFree(data); |
| 901 XIChangeProperty(xdisplay_, dev_list[i].deviceid, prop, XA_INTEGER, 8, | 869 XIChangeProperty(xdisplay_, dev_list[i].deviceid, prop, XA_INTEGER, 8, |
| 902 PropModeReplace, &value, 1); | 870 PropModeReplace, &value, 1); |
| 903 } | 871 } |
| 904 } | 872 } |
| 905 #endif | 873 #endif |
| 906 } | 874 } |
| 907 | 875 |
| 876 bool WindowTreeHostX11::IsTouchEventTargetingThisRootWindow( | |
| 877 const base::NativeEvent& event) { | |
|
sadrul
2014/03/15 19:32:51
Just use XEvent* here.
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Done.
| |
| 878 #if defined(OS_CHROMEOS) | |
| 879 XEvent* xev = event; | |
| 880 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data); | |
| 881 int64 touch_display_id = | |
| 882 ui::DeviceDataManager::GetInstance()->GetDisplayForTouchDevice( | |
| 883 xiev->deviceid); | |
| 884 // If we don't have record of display id for this touch device, then | |
| 885 // fall backt to check if this touch event is within the bounds of | |
|
sadrul
2014/03/15 19:32:51
*back
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Done.
| |
| 886 // this root window. | |
| 887 if (touch_display_id == gfx::Display::kInvalidDisplayID) { | |
| 888 if (base::SysInfo::IsRunningOnChromeOS() && | |
| 889 !bounds_.Contains(ui::EventLocationFromNative(xev))) | |
|
ynovikov
2014/03/27 23:35:53
As I understand it, this check will be wrong most
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
I am more interested in not regress the 1 monitor
| |
| 890 return false; | |
| 891 // If we do have record of the display id for this touch device, | |
|
sadrul
2014/03/15 19:32:51
I don't think this comment is necessary here.
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Done.
| |
| 892 // then check if this touch display id is associated with this | |
| 893 // root window. | |
| 894 } else if (touch_display_id != display_ids().first && | |
| 895 touch_display_id != display_ids().second) { | |
| 896 return false; | |
| 897 } | |
| 898 #endif // defined(OS_CHROMEOS) | |
| 899 return true; | |
|
sadrul
2014/03/15 19:32:51
non-CHROMEOS case should do the bounds check.
Thi
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
The original code does not do the bounds check in
| |
| 900 } | |
| 901 | |
| 902 void WindowTreeHostX11::CalibrateTouchEvent(const base::NativeEvent& event, | |
| 903 ui::TouchEvent* touchev) { | |
| 904 #if defined(OS_CHROMEOS) && defined(USE_XI2_MT) | |
| 905 XEvent* xev = event; | |
| 906 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data); | |
| 907 int64 touch_display_id = | |
| 908 ui::DeviceDataManager::GetInstance()->GetDisplayForTouchDevice( | |
| 909 xiev->deviceid); | |
| 910 // On ChromeOS, if touch event is from internal display, we need to | |
| 911 // calibrate its location for bezel region. | |
| 912 if (base::SysInfo::IsRunningOnChromeOS() && | |
| 913 touch_display_id == gfx::Display::InternalDisplayId()) { | |
| 914 touch_calibrate_->Calibrate(touchev, bounds_); | |
| 915 } | |
| 916 #endif // defined(OS_CHROMEOS) && defined(USE_XI2_MT) | |
| 917 } | |
| 918 | |
| 908 // static | 919 // static |
| 909 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) { | 920 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) { |
| 910 return new WindowTreeHostX11(bounds); | 921 return new WindowTreeHostX11(bounds); |
| 911 } | 922 } |
| 912 | 923 |
| 913 // static | 924 // static |
| 914 gfx::Size WindowTreeHost::GetNativeScreenSize() { | 925 gfx::Size WindowTreeHost::GetNativeScreenSize() { |
| 915 ::XDisplay* xdisplay = gfx::GetXDisplay(); | 926 ::XDisplay* xdisplay = gfx::GetXDisplay(); |
| 916 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 927 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
| 917 } | 928 } |
| 918 | 929 |
| 919 namespace test { | 930 namespace test { |
| 920 | 931 |
| 921 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { | 932 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { |
| 922 default_override_redirect = override_redirect; | 933 default_override_redirect = override_redirect; |
| 923 } | 934 } |
| 924 | 935 |
| 925 } // namespace test | 936 } // namespace test |
| 926 } // namespace aura | 937 } // namespace aura |
| OLD | NEW |