| 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 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 // Scale the screen area back to the full resolution of the screen. | 194 // Scale the screen area back to the full resolution of the screen. |
| 195 y = (y * resolution_y) / (resolution_y - (bottom_ + top_)); | 195 y = (y * resolution_y) / (resolution_y - (bottom_ + top_)); |
| 196 } | 196 } |
| 197 | 197 |
| 198 // Set the modified coordinate back to the event. | 198 // Set the modified coordinate back to the event. |
| 199 if (event->root_location() == event->location()) { | 199 if (event->root_location() == event->location()) { |
| 200 // Usually those will be equal, | 200 // Usually those will be equal, |
| 201 // if not, I am not sure what the correct value should be. | 201 // if not, I am not sure what the correct value should be. |
| 202 event->set_root_location(gfx::Point(x, y)); | 202 event->set_root_location(gfx::Point(x, y)); |
| 203 } | 203 } |
| 204 |
| 204 event->set_location(gfx::Point(x, y)); | 205 event->set_location(gfx::Point(x, y)); |
| 205 #endif // defined(USE_XI2_MT) | 206 #endif // defined(USE_XI2_MT) |
| 206 } | 207 } |
| 207 | 208 |
| 208 private: | 209 private: |
| 209 // Overridden from base::MessagePumpObserver: | 210 // Overridden from base::MessagePumpObserver: |
| 210 virtual base::EventStatus WillProcessEvent( | 211 virtual base::EventStatus WillProcessEvent( |
| 211 const base::NativeEvent& event) OVERRIDE { | 212 const base::NativeEvent& event) OVERRIDE { |
| 212 #if defined(USE_XI2_MT) | 213 #if defined(USE_XI2_MT) |
| 213 if (event->type == GenericEvent && | 214 if (event->type == GenericEvent && |
| (...skipping 28 matching lines...) Expand all Loading... |
| 242 //////////////////////////////////////////////////////////////////////////////// | 243 //////////////////////////////////////////////////////////////////////////////// |
| 243 // WindowTreeHostX11 | 244 // WindowTreeHostX11 |
| 244 | 245 |
| 245 WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds) | 246 WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds) |
| 246 : xdisplay_(gfx::GetXDisplay()), | 247 : xdisplay_(gfx::GetXDisplay()), |
| 247 xwindow_(0), | 248 xwindow_(0), |
| 248 x_root_window_(DefaultRootWindow(xdisplay_)), | 249 x_root_window_(DefaultRootWindow(xdisplay_)), |
| 249 current_cursor_(ui::kCursorNull), | 250 current_cursor_(ui::kCursorNull), |
| 250 window_mapped_(false), | 251 window_mapped_(false), |
| 251 bounds_(bounds), | 252 bounds_(bounds), |
| 252 is_internal_display_(false), | |
| 253 touch_calibrate_(new internal::TouchEventCalibrate), | 253 touch_calibrate_(new internal::TouchEventCalibrate), |
| 254 atom_cache_(xdisplay_, kAtomsToCache) { | 254 atom_cache_(xdisplay_, kAtomsToCache) { |
| 255 XSetWindowAttributes swa; | 255 XSetWindowAttributes swa; |
| 256 memset(&swa, 0, sizeof(swa)); | 256 memset(&swa, 0, sizeof(swa)); |
| 257 swa.background_pixmap = None; | 257 swa.background_pixmap = None; |
| 258 swa.override_redirect = default_override_redirect; | 258 swa.override_redirect = default_override_redirect; |
| 259 xwindow_ = XCreateWindow( | 259 xwindow_ = XCreateWindow( |
| 260 xdisplay_, x_root_window_, | 260 xdisplay_, x_root_window_, |
| 261 bounds.x(), bounds.y(), bounds.width(), bounds.height(), | 261 bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
| 262 0, // border width | 262 0, // border width |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 402 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
| 403 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 403 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
| 404 // It's possible that the X window may be resized by some other means | 404 // 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 | 405 // than from within aura (e.g. the X window manager can change the |
| 406 // size). Make sure the root window size is maintained properly. | 406 // size). Make sure the root window size is maintained properly. |
| 407 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, | 407 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, |
| 408 xev->xconfigure.width, xev->xconfigure.height); | 408 xev->xconfigure.width, xev->xconfigure.height); |
| 409 bool size_changed = bounds_.size() != bounds.size(); | 409 bool size_changed = bounds_.size() != bounds.size(); |
| 410 bool origin_changed = bounds_.origin() != bounds.origin(); | 410 bool origin_changed = bounds_.origin() != bounds.origin(); |
| 411 bounds_ = bounds; | 411 bounds_ = bounds; |
| 412 UpdateIsInternalDisplay(); | |
| 413 // Always update barrier and mouse location because |bounds_| might | 412 // Always update barrier and mouse location because |bounds_| might |
| 414 // have already been updated in |SetBounds|. | 413 // have already been updated in |SetBounds|. |
| 415 if (pointer_barriers_) { | 414 if (pointer_barriers_) { |
| 416 UnConfineCursor(); | 415 UnConfineCursor(); |
| 417 ConfineCursorToRootWindow(); | 416 ConfineCursorToRootWindow(); |
| 418 } | 417 } |
| 419 if (size_changed) | 418 if (size_changed) |
| 420 OnHostResized(bounds.size()); | 419 OnHostResized(bounds.size()); |
| 421 if (origin_changed) | 420 if (origin_changed) |
| 422 OnHostMoved(bounds_.origin()); | 421 OnHostMoved(bounds_.origin()); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 } | 548 } |
| 550 if (value_mask) | 549 if (value_mask) |
| 551 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); | 550 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); |
| 552 | 551 |
| 553 // Assume that the resize will go through as requested, which should be the | 552 // 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 | 553 // 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 | 554 // 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 | 555 // (possibly synthetic) ConfigureNotify about the actual size and correct |
| 557 // |bounds_| later. | 556 // |bounds_| later. |
| 558 bounds_ = bounds; | 557 bounds_ = bounds; |
| 559 UpdateIsInternalDisplay(); | |
| 560 if (origin_changed) | 558 if (origin_changed) |
| 561 OnHostMoved(bounds.origin()); | 559 OnHostMoved(bounds.origin()); |
| 562 if (size_changed || current_scale != new_scale) { | 560 if (size_changed || current_scale != new_scale) { |
| 563 OnHostResized(bounds.size()); | 561 OnHostResized(bounds.size()); |
| 564 } else { | 562 } else { |
| 565 window()->SchedulePaintInRect(window()->bounds()); | 563 window()->SchedulePaintInRect(window()->bounds()); |
| 566 } | 564 } |
| 567 } | 565 } |
| 568 | 566 |
| 569 gfx::Insets WindowTreeHostX11::GetInsets() const { | 567 gfx::Insets WindowTreeHostX11::GetInsets() const { |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 } | 715 } |
| 718 | 716 |
| 719 void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) { | 717 void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) { |
| 720 SetCrOSTapPaused(!show); | 718 SetCrOSTapPaused(!show); |
| 721 } | 719 } |
| 722 | 720 |
| 723 void WindowTreeHostX11::OnWindowInitialized(Window* window) { | 721 void WindowTreeHostX11::OnWindowInitialized(Window* window) { |
| 724 } | 722 } |
| 725 | 723 |
| 726 void WindowTreeHostX11::OnHostInitialized(WindowTreeHost* host) { | 724 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) | 725 if (host != this) |
| 733 return; | 726 return; |
| 734 UpdateIsInternalDisplay(); | |
| 735 | 727 |
| 736 // We have to enable Tap-to-click by default because the cursor is set to | 728 // We have to enable Tap-to-click by default because the cursor is set to |
| 737 // visible in Shell::InitRootWindowController. | 729 // visible in Shell::InitRootWindowController. |
| 738 SetCrOSTapPaused(false); | 730 SetCrOSTapPaused(false); |
| 739 } | 731 } |
| 740 | 732 |
| 741 ui::EventProcessor* WindowTreeHostX11::GetEventProcessor() { | 733 ui::EventProcessor* WindowTreeHostX11::GetEventProcessor() { |
| 742 return dispatcher(); | 734 return dispatcher(); |
| 743 } | 735 } |
| 744 | 736 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 755 | 747 |
| 756 ui::EventType type = ui::EventTypeFromNative(xev); | 748 ui::EventType type = ui::EventTypeFromNative(xev); |
| 757 XEvent last_event; | 749 XEvent last_event; |
| 758 int num_coalesced = 0; | 750 int num_coalesced = 0; |
| 759 | 751 |
| 760 switch (type) { | 752 switch (type) { |
| 761 case ui::ET_TOUCH_MOVED: | 753 case ui::ET_TOUCH_MOVED: |
| 762 case ui::ET_TOUCH_PRESSED: | 754 case ui::ET_TOUCH_PRESSED: |
| 763 case ui::ET_TOUCH_CANCELLED: | 755 case ui::ET_TOUCH_CANCELLED: |
| 764 case ui::ET_TOUCH_RELEASED: { | 756 case ui::ET_TOUCH_RELEASED: { |
| 765 #if defined(OS_CHROMEOS) | |
| 766 // Bail out early before generating a ui::TouchEvent if this event | 757 // Bail out early before generating a ui::TouchEvent if this event |
| 767 // is not within the range of this RootWindow. Converting an xevent | 758 // is targeting this RootWindow. |
| 768 // to ui::TouchEvent might change the state of the global touch tracking | 759 // 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 | 760 // the global touch tracking state, e.g. touch release event can |
| 770 // record, and doing this multiple time when there are multiple | 761 // remove the touch id from the record, and doing this multiple time |
| 771 // RootWindow will cause problem. So only generate the ui::TouchEvent | 762 // when there are multiple RootWindow will cause problem. So only |
| 772 // when we are sure it belongs to this RootWindow. | 763 // generate the ui::TouchEvent when we are sure it is targeting this |
| 773 if (base::SysInfo::IsRunningOnChromeOS() && | 764 // RootWindow. |
| 774 !bounds_.Contains(ui::EventLocationFromNative(xev))) | 765 if (!IsTouchEventTargetingThisRootWindow(xev)) |
| 775 break; | 766 break; |
| 776 #endif // defined(OS_CHROMEOS) | |
| 777 ui::TouchEvent touchev(xev); | 767 ui::TouchEvent touchev(xev); |
| 778 #if defined(OS_CHROMEOS) | 768 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()); | |
| 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); | 769 SendEventToProcessor(&touchev); |
| 794 break; | 770 break; |
| 795 } | 771 } |
| 796 case ui::ET_MOUSE_MOVED: | 772 case ui::ET_MOUSE_MOVED: |
| 797 case ui::ET_MOUSE_DRAGGED: | 773 case ui::ET_MOUSE_DRAGGED: |
| 798 case ui::ET_MOUSE_PRESSED: | 774 case ui::ET_MOUSE_PRESSED: |
| 799 case ui::ET_MOUSE_RELEASED: | 775 case ui::ET_MOUSE_RELEASED: |
| 800 case ui::ET_MOUSE_ENTERED: | 776 case ui::ET_MOUSE_ENTERED: |
| 801 case ui::ET_MOUSE_EXITED: { | 777 case ui::ET_MOUSE_EXITED: { |
| 802 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) { | 778 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. | 837 // host window, then convert it back to this host window's coordinate. |
| 862 screen_position_client->ConvertHostPointToScreen(root_window, &location); | 838 screen_position_client->ConvertHostPointToScreen(root_window, &location); |
| 863 screen_position_client->ConvertPointFromScreen(root_window, &location); | 839 screen_position_client->ConvertPointFromScreen(root_window, &location); |
| 864 ConvertPointToHost(&location); | 840 ConvertPointToHost(&location); |
| 865 event->set_location(location); | 841 event->set_location(location); |
| 866 event->set_root_location(location); | 842 event->set_root_location(location); |
| 867 } | 843 } |
| 868 SendEventToProcessor(event); | 844 SendEventToProcessor(event); |
| 869 } | 845 } |
| 870 | 846 |
| 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) { | 847 void WindowTreeHostX11::SetCrOSTapPaused(bool state) { |
| 879 #if defined(OS_CHROMEOS) | 848 #if defined(OS_CHROMEOS) |
| 880 if (!ui::IsXInput2Available()) | 849 if (!ui::IsXInput2Available()) |
| 881 return; | 850 return; |
| 882 // Temporarily pause tap-to-click when the cursor is hidden. | 851 // Temporarily pause tap-to-click when the cursor is hidden. |
| 883 Atom prop = atom_cache_.GetAtom("Tap Paused"); | 852 Atom prop = atom_cache_.GetAtom("Tap Paused"); |
| 884 unsigned char value = state; | 853 unsigned char value = state; |
| 885 XIDeviceList dev_list = | 854 XIDeviceList dev_list = |
| 886 ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(xdisplay_); | 855 ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(xdisplay_); |
| 887 | 856 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 898 if (result != Success) | 867 if (result != Success) |
| 899 continue; | 868 continue; |
| 900 XFree(data); | 869 XFree(data); |
| 901 XIChangeProperty(xdisplay_, dev_list[i].deviceid, prop, XA_INTEGER, 8, | 870 XIChangeProperty(xdisplay_, dev_list[i].deviceid, prop, XA_INTEGER, 8, |
| 902 PropModeReplace, &value, 1); | 871 PropModeReplace, &value, 1); |
| 903 } | 872 } |
| 904 } | 873 } |
| 905 #endif | 874 #endif |
| 906 } | 875 } |
| 907 | 876 |
| 877 bool WindowTreeHostX11::IsTouchEventTargetingThisRootWindow( |
| 878 const base::NativeEvent& event) { |
| 879 #if defined(OS_CHROMEOS) |
| 880 XEvent* xev = event; |
| 881 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
| 882 int64 touch_display_id = |
| 883 ui::DeviceDataManager::GetInstance()->GetDisplayForTouchDevice( |
| 884 xiev->deviceid); |
| 885 // If we don't have record of display id for this touch device, then |
| 886 // fall backt to check if this touch event is within the bounds of |
| 887 // this root window. |
| 888 if (touch_display_id == gfx::Display::kInvalidDisplayID) { |
| 889 if (base::SysInfo::IsRunningOnChromeOS() && |
| 890 !bounds_.Contains(ui::EventLocationFromNative(xev))) |
| 891 return false; |
| 892 // If we do have record of the display id for this touch device, |
| 893 // then check if this touch display id is associated with this |
| 894 // root window. |
| 895 } else if (touch_display_id != display_ids().first && |
| 896 touch_display_id != display_ids().second) { |
| 897 return false; |
| 898 } |
| 899 #endif // defined(OS_CHROMEOS) |
| 900 return true; |
| 901 } |
| 902 |
| 903 void WindowTreeHostX11::CalibrateTouchEvent(const base::NativeEvent& event, |
| 904 ui::TouchEvent* touchev) { |
| 905 #if defined(OS_CHROMEOS) && defined(USE_XI2_MT) |
| 906 XEvent* xev = event; |
| 907 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
| 908 int64 touch_display_id = |
| 909 ui::DeviceDataManager::GetInstance()->GetDisplayForTouchDevice( |
| 910 xiev->deviceid); |
| 911 // On ChromeOS, if touch event is from internal display, we need to |
| 912 // calibrate its location for bezel region. |
| 913 if (base::SysInfo::IsRunningOnChromeOS() && |
| 914 touch_display_id == gfx::Display::InternalDisplayId()) { |
| 915 touch_calibrate_->Calibrate(touchev, bounds_); |
| 916 } |
| 917 #endif // defined(OS_CHROMEOS) && defined(USE_XI2_MT) |
| 918 } |
| 919 |
| 908 // static | 920 // static |
| 909 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) { | 921 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) { |
| 910 return new WindowTreeHostX11(bounds); | 922 return new WindowTreeHostX11(bounds); |
| 911 } | 923 } |
| 912 | 924 |
| 913 // static | 925 // static |
| 914 gfx::Size WindowTreeHost::GetNativeScreenSize() { | 926 gfx::Size WindowTreeHost::GetNativeScreenSize() { |
| 915 ::XDisplay* xdisplay = gfx::GetXDisplay(); | 927 ::XDisplay* xdisplay = gfx::GetXDisplay(); |
| 916 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 928 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
| 917 } | 929 } |
| 918 | 930 |
| 919 namespace test { | 931 namespace test { |
| 920 | 932 |
| 921 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { | 933 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { |
| 922 default_override_redirect = override_redirect; | 934 default_override_redirect = override_redirect; |
| 923 } | 935 } |
| 924 | 936 |
| 925 } // namespace test | 937 } // namespace test |
| 926 } // namespace aura | 938 } // namespace aura |
| OLD | NEW |