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 |