| 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 "ash/wm/coordinate_conversion.h" | 5 #include "ash/wm/coordinate_conversion.h" |
| 6 | 6 |
| 7 #include "ash/display/display_controller.h" | 7 #include "ash/display/display_controller.h" |
| 8 #include "ash/screen_ash.h" | 8 #include "ash/screen_ash.h" |
| 9 #include "ash/shell.h" | 9 #include "ash/shell.h" |
| 10 #include "ui/aura/client/screen_position_client.h" | 10 #include "ui/aura/client/screen_position_client.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 | 33 |
| 34 std::pair<aura::RootWindow*, gfx::Point> GetRootWindowRelativeToWindow( | 34 std::pair<aura::RootWindow*, gfx::Point> GetRootWindowRelativeToWindow( |
| 35 aura::Window* window, | 35 aura::Window* window, |
| 36 const gfx::Point& location) { | 36 const gfx::Point& location) { |
| 37 aura::RootWindow* root_window = window->GetRootWindow(); | 37 aura::RootWindow* root_window = window->GetRootWindow(); |
| 38 gfx::Point location_in_root(location); | 38 gfx::Point location_in_root(location); |
| 39 aura::Window::ConvertPointToTarget(window, root_window, &location_in_root); | 39 aura::Window::ConvertPointToTarget(window, root_window, &location_in_root); |
| 40 | 40 |
| 41 #if defined(USE_X11) | 41 #if defined(USE_X11) |
| 42 if (!root_window->ContainsPointInRoot(location_in_root)) { | 42 if (!root_window->ContainsPointInRoot(location_in_root)) { |
| 43 // This is to translate an out of bounds mouse pointer location in | 43 // This conversion is necessary to deal with X's passive input |
| 44 // its root window coordinate into correct screen coordinates. | 44 // grab while dragging window. For example, if we have two |
| 45 // There are two scenarios that a target root window receives an | 45 // displays, say 1000x1000 (primary) and 500x500 (extended one |
| 46 // out of bounds mouse event. | 46 // on the right), and start dragging a window at (999, 123), and |
| 47 // | 47 // then move the pointer to the right, the pointer suddenly |
| 48 // 1) When aura's input is captured by an aura window, and the | 48 // warps to the extended display. The destination is (0, 123) in |
| 49 // mouse pointer is on another root window. Typical example is | 49 // the secondary root window's coordinates, or (1000, 123) in |
| 50 // when you open a menu and move the mouse to another display (which is | 50 // the screen coordinates. However, since the mouse is captured |
| 51 // another root window). X's mouse event is sent to the window | 51 // by X during drag, a weird LocatedEvent, something like (0, 1123) |
| 52 // where mouse is on, but the aura event is sent to the window | 52 // in the *primary* root window's coordinates, is sent to Chrome |
| 53 // that has a capture, which is on a different root window. | 53 // (Remember that in the native X11 world, the two root windows |
| 54 // This is covered in the is_valid block below. | 54 // are always stacked vertically regardless of the display |
| 55 // | 55 // layout in Ash). We need to figure out that (0, 1123) in the |
| 56 // 2) When X's native input is captured by a drag operation. When | 56 // primary root window's coordinates is actually (0, 123) in the |
| 57 // you press a button on a window, X automatically grabs the | 57 // extended root window's coordinates. |
| 58 // mouse input (passive grab | |
| 59 // http://www.x.org/wiki/development/documentation/grabprocessing) | |
| 60 // and keeps sending mouse events to the window where the drag | |
| 61 // operation started until the mouse button is released. This is | |
| 62 // covered in the else block below. | |
| 63 | 58 |
| 64 gfx::Point location_in_screen = location_in_root; | 59 gfx::Point location_in_native(location_in_root); |
| 65 aura::client::ScreenPositionClient* client = | 60 root_window->ConvertPointToNativeScreen(&location_in_native); |
| 66 aura::client::GetScreenPositionClient(root_window); | |
| 67 client->ConvertPointToScreen(root_window, &location_in_screen); | |
| 68 gfx::Display display = | |
| 69 ScreenAsh::FindDisplayContainingPoint(location_in_screen); | |
| 70 if (display.is_valid()) { | |
| 71 // This conversion is necessary to warp the mouse pointer | |
| 72 // correctly while aura's input capture is in effect. In this | |
| 73 // case, the location is already translated relative to the root | |
| 74 // (but it's outside of the root window), so all we have to do | |
| 75 // is to find a root window containing the point in screen | |
| 76 // coordinate. | |
| 77 aura::RootWindow* root = Shell::GetInstance()->display_controller()-> | |
| 78 GetRootWindowForDisplayId(display.id()); | |
| 79 DCHECK(root); | |
| 80 client->ConvertPointFromScreen(root, &location_in_screen); | |
| 81 root_window = root; | |
| 82 location_in_root = location_in_screen; | |
| 83 } else { | |
| 84 // This conversion is necessary to deal with X's passive input | |
| 85 // grab while dragging window. For example, if we have two | |
| 86 // displays, say 1000x1000 (primary) and 500x500 (extended one | |
| 87 // on the right), and start dragging a window at (999, 123), and | |
| 88 // then move the pointer to the right, the pointer suddenly | |
| 89 // warps to the extended display. The destination is (0, 123) in | |
| 90 // the secondary root window's coordinates, or (1000, 123) in | |
| 91 // the screen coordinates. However, since the mouse is captured | |
| 92 // by X during drag, a weird LocatedEvent, something like (0, 1123) | |
| 93 // in the *primary* root window's coordinates, is sent to Chrome | |
| 94 // (Remember that in the native X11 world, the two root windows | |
| 95 // are always stacked vertically regardless of the display | |
| 96 // layout in Ash). We need to figure out that (0, 1123) in the | |
| 97 // primary root window's coordinates is actually (0, 123) in the | |
| 98 // extended root window's coordinates. | |
| 99 | 61 |
| 100 gfx::Point location_in_native(location_in_root); | 62 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
| 101 root_window->ConvertPointToNativeScreen(&location_in_native); | 63 for (size_t i = 0; i < root_windows.size(); ++i) { |
| 102 | 64 const gfx::Rect native_bounds( |
| 103 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); | 65 root_windows[i]->GetHostOrigin(), |
| 104 for (size_t i = 0; i < root_windows.size(); ++i) { | 66 root_windows[i]->GetHostSize()); // in px. |
| 105 const gfx::Rect native_bounds( | 67 if (native_bounds.Contains(location_in_native)) { |
| 106 root_windows[i]->GetHostOrigin(), | 68 root_window = root_windows[i]; |
| 107 root_windows[i]->GetHostSize()); // in px. | 69 location_in_root = location_in_native; |
| 108 if (native_bounds.Contains(location_in_native)) { | 70 root_window->ConvertPointFromNativeScreen(&location_in_root); |
| 109 root_window = root_windows[i]; | 71 break; |
| 110 location_in_root = location_in_native; | |
| 111 root_window->ConvertPointFromNativeScreen(&location_in_root); | |
| 112 break; | |
| 113 } | |
| 114 } | 72 } |
| 115 } | 73 } |
| 116 } | 74 } |
| 117 #else | 75 #else |
| 118 // TODO(yusukes): Support non-X11 platforms if necessary. | 76 // TODO(yusukes): Support non-X11 platforms if necessary. |
| 119 #endif | 77 #endif |
| 120 | 78 |
| 121 return std::make_pair(root_window, location_in_root); | 79 return std::make_pair(root_window, location_in_root); |
| 122 } | 80 } |
| 123 | 81 |
| 124 void ConvertPointToScreen(aura::Window* window, gfx::Point* point) { | 82 void ConvertPointToScreen(aura::Window* window, gfx::Point* point) { |
| 125 aura::client::GetScreenPositionClient(window->GetRootWindow())-> | 83 aura::client::GetScreenPositionClient(window->GetRootWindow())-> |
| 126 ConvertPointToScreen(window, point); | 84 ConvertPointToScreen(window, point); |
| 127 } | 85 } |
| 128 | 86 |
| 129 void ConvertPointFromScreen(aura::Window* window, | 87 void ConvertPointFromScreen(aura::Window* window, |
| 130 gfx::Point* point_in_screen) { | 88 gfx::Point* point_in_screen) { |
| 131 aura::client::GetScreenPositionClient(window->GetRootWindow())-> | 89 aura::client::GetScreenPositionClient(window->GetRootWindow())-> |
| 132 ConvertPointFromScreen(window, point_in_screen); | 90 ConvertPointFromScreen(window, point_in_screen); |
| 133 } | 91 } |
| 134 | 92 |
| 135 } // namespace wm | 93 } // namespace wm |
| 136 } // namespace ash | 94 } // namespace ash |
| OLD | NEW |