Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/display/extended_mouse_warp_controller.h" | 5 #include "ash/display/extended_mouse_warp_controller.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "ash/display/display_manager.h" | 9 #include "ash/display/display_manager.h" |
| 10 #include "ash/display/display_util.h" | 10 #include "ash/display/display_util.h" |
| 11 #include "ash/display/shared_display_edge_indicator.h" | 11 #include "ash/display/shared_display_edge_indicator.h" |
| 12 #include "ash/display/window_tree_host_manager.h" | |
| 12 #include "ash/root_window_controller.h" | 13 #include "ash/root_window_controller.h" |
| 13 #include "ash/screen_util.h" | 14 #include "ash/screen_util.h" |
| 14 #include "ash/shell.h" | 15 #include "ash/shell.h" |
| 15 #include "ui/aura/window.h" | 16 #include "ui/aura/window.h" |
| 16 #include "ui/events/event_utils.h" | 17 #include "ui/events/event_utils.h" |
| 17 #include "ui/gfx/screen.h" | 18 #include "ui/gfx/screen.h" |
| 18 #include "ui/wm/core/coordinate_conversion.h" | 19 #include "ui/wm/core/coordinate_conversion.h" |
| 19 | 20 |
| 20 namespace ash { | 21 namespace ash { |
| 21 | 22 |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 24 // Maximum size on the display edge that initiate snapping phantom window, | 25 // Maximum size on the display edge that initiate snapping phantom window, |
| 25 // from the corner of the display. | 26 // from the corner of the display. |
| 26 const int kMaximumSnapHeight = 16; | 27 const int kMaximumSnapHeight = 16; |
| 27 | 28 |
| 28 // Minimum height of an indicator on the display edge that allows | 29 // Minimum height of an indicator on the display edge that allows |
| 29 // dragging a window. If two displays shares the edge smaller than | 30 // dragging a window. If two displays shares the edge smaller than |
| 30 // this, entire edge will be used as a draggable space. | 31 // this, entire edge will be used as a draggable space. |
| 31 const int kMinimumIndicatorHeight = 200; | 32 const int kMinimumIndicatorHeight = 200; |
| 32 | 33 |
| 33 const int kIndicatorThickness = 1; | 34 const int kIndicatorThickness = 1; |
| 34 | 35 |
| 36 // Helper method that maps a gfx::Display to an aura::Window. | |
| 37 aura::Window* GetRootWindowForDisplayId(int64_t display_id) { | |
| 38 return Shell::GetInstance() | |
| 39 ->window_tree_host_manager() | |
| 40 ->GetRootWindowForDisplayId(display_id); | |
| 41 } | |
| 42 | |
| 43 // Helper method that maps an aura::Window to a gfx::Display. | |
| 44 gfx::Display GetDisplayFromWindow(aura::Window* window) { | |
| 45 return Shell::GetScreen()->GetDisplayNearestWindow(window); | |
| 46 } | |
| 47 | |
| 35 } // namespace | 48 } // namespace |
| 36 | 49 |
| 50 ExtendedMouseWarpController::WarpRegion::WarpRegion( | |
| 51 int64_t a_display_id, | |
| 52 int64_t b_display_id, | |
| 53 const gfx::Rect& a_indicator_bounds, | |
| 54 const gfx::Rect& b_indicator_bounds) | |
| 55 : a_display_id(a_display_id), | |
| 56 b_display_id(b_display_id), | |
| 57 a_indicator_bounds(a_indicator_bounds), | |
| 58 b_indicator_bounds(b_indicator_bounds), | |
| 59 shared_display_edge_indicator(nullptr) { | |
| 60 // Initialize edge bounds from indicator bounds. | |
| 61 aura::Window* a_window = GetRootWindowForDisplayId(a_display_id); | |
| 62 aura::Window* b_window = GetRootWindowForDisplayId(b_display_id); | |
| 63 | |
| 64 AshWindowTreeHost* a_ash_host = GetRootWindowController(a_window)->ash_host(); | |
| 65 AshWindowTreeHost* b_ash_host = GetRootWindowController(b_window)->ash_host(); | |
| 66 | |
| 67 a_edge_bounds_in_native = GetNativeEdgeBounds(a_ash_host, a_indicator_bounds); | |
| 68 b_edge_bounds_in_native = GetNativeEdgeBounds(b_ash_host, b_indicator_bounds); | |
| 69 } | |
| 70 | |
| 71 ExtendedMouseWarpController::WarpRegion::~WarpRegion() {} | |
| 72 | |
| 37 ExtendedMouseWarpController::ExtendedMouseWarpController( | 73 ExtendedMouseWarpController::ExtendedMouseWarpController( |
| 38 aura::Window* drag_source) | 74 aura::Window* drag_source) |
| 39 : drag_source_root_(drag_source), | 75 : drag_source_root_(drag_source), |
| 40 shared_display_edge_indicator_(new SharedDisplayEdgeIndicator), | |
| 41 allow_non_native_event_(false) { | 76 allow_non_native_event_(false) { |
| 42 DisplayLayout::Position position = Shell::GetInstance() | 77 ash::DisplayManager* display_manager = |
| 43 ->display_manager() | 78 Shell::GetInstance()->display_manager(); |
| 44 ->GetCurrentDisplayLayout() | 79 |
| 45 .position; | 80 // For the time being, 3 or more displays are always always laid out |
| 46 // TODO(oshima): Use ComputeBondary instead. | 81 // horizontally, with each display being RIGHT of the previous one. |
| 47 if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) | 82 if (display_manager->GetNumDisplays() > 2) { |
| 48 UpdateHorizontalEdgeBounds(); | 83 for (size_t i = 1; i < display_manager->GetNumDisplays(); ++i) { |
| 49 else | 84 const gfx::Display& left = display_manager->GetDisplayAt(i - 1); |
| 50 UpdateVerticalEdgeBounds(); | 85 const gfx::Display& right = display_manager->GetDisplayAt(i); |
| 51 if (drag_source) { | 86 |
| 52 shared_display_edge_indicator_->Show(src_indicator_bounds_, | 87 AddWarpRegion(CreateVerticalEdgeBounds(left, right, DisplayLayout::RIGHT), |
| 53 dst_indicator_bounds_); | 88 drag_source != nullptr); |
| 89 } | |
| 90 } | |
| 91 | |
| 92 else { | |
|
oshima
2016/01/20 18:35:55
style nit: } else {
jdufault
2016/01/20 23:37:15
Done.
| |
| 93 DisplayLayout::Position position = | |
| 94 display_manager->GetCurrentDisplayLayout().position; | |
| 95 const gfx::Display& a = display_manager->GetDisplayAt(0); | |
| 96 const gfx::Display& b = display_manager->GetDisplayAt(1); | |
| 97 | |
| 98 // TODO(oshima): Use ComputeBondary instead. | |
| 99 if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) | |
| 100 AddWarpRegion(CreateHorizontalEdgeBounds(a, b, position), | |
| 101 drag_source != nullptr); | |
| 102 else | |
| 103 AddWarpRegion(CreateVerticalEdgeBounds(a, b, position), | |
| 104 drag_source != nullptr); | |
| 54 } | 105 } |
| 55 } | 106 } |
| 56 | 107 |
| 57 ExtendedMouseWarpController::~ExtendedMouseWarpController() { | 108 ExtendedMouseWarpController::~ExtendedMouseWarpController() { |
| 58 } | 109 } |
| 59 | 110 |
| 60 bool ExtendedMouseWarpController::WarpMouseCursor(ui::MouseEvent* event) { | 111 bool ExtendedMouseWarpController::WarpMouseCursor(ui::MouseEvent* event) { |
| 61 if (Shell::GetScreen()->GetNumDisplays() <= 1 || !enabled_) | 112 if (Shell::GetScreen()->GetNumDisplays() <= 1 || !enabled_) |
| 62 return false; | 113 return false; |
| 63 | 114 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 90 target->GetHost()->GetBounds().y()); | 141 target->GetHost()->GetBounds().y()); |
| 91 #endif | 142 #endif |
| 92 | 143 |
| 93 return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen, false); | 144 return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen, false); |
| 94 } | 145 } |
| 95 | 146 |
| 96 void ExtendedMouseWarpController::SetEnabled(bool enabled) { | 147 void ExtendedMouseWarpController::SetEnabled(bool enabled) { |
| 97 enabled_ = enabled; | 148 enabled_ = enabled; |
| 98 } | 149 } |
| 99 | 150 |
| 151 void ExtendedMouseWarpController::AddWarpRegion( | |
| 152 scoped_ptr<WarpRegion> warp_region, | |
| 153 bool drag_source) { | |
| 154 if (drag_source) { | |
| 155 warp_region->shared_display_edge_indicator.reset( | |
| 156 new SharedDisplayEdgeIndicator); | |
| 157 warp_region->shared_display_edge_indicator->Show( | |
| 158 warp_region->a_indicator_bounds, warp_region->b_indicator_bounds); | |
| 159 } | |
| 160 | |
| 161 warp_regions_.emplace_back(std::move(warp_region)); | |
| 162 } | |
| 163 | |
| 100 bool ExtendedMouseWarpController::WarpMouseCursorInNativeCoords( | 164 bool ExtendedMouseWarpController::WarpMouseCursorInNativeCoords( |
| 101 const gfx::Point& point_in_native, | 165 const gfx::Point& point_in_native, |
| 102 const gfx::Point& point_in_screen, | 166 const gfx::Point& point_in_screen, |
| 103 bool update_mouse_location_now) { | 167 bool update_mouse_location_now) { |
| 104 bool in_src_edge = src_edge_bounds_in_native_.Contains(point_in_native); | 168 for (const scoped_ptr<WarpRegion>& warp : warp_regions_) { |
| 105 bool in_dst_edge = dst_edge_bounds_in_native_.Contains(point_in_native); | 169 bool in_a_edge = warp->a_edge_bounds_in_native.Contains(point_in_native); |
| 106 if (!in_src_edge && !in_dst_edge) | 170 bool in_b_edge = warp->b_edge_bounds_in_native.Contains(point_in_native); |
| 107 return false; | 171 if (!in_a_edge && !in_b_edge) |
| 172 continue; | |
| 108 | 173 |
| 109 // The mouse must move. | 174 // The mouse must move. |
| 110 aura::Window* src_root = nullptr; | 175 aura::Window* dst_window = GetRootWindowForDisplayId( |
| 111 aura::Window* dst_root = nullptr; | 176 in_a_edge ? warp->b_display_id : warp->a_display_id); |
| 112 GetSrcAndDstRootWindows(&src_root, &dst_root); | 177 AshWindowTreeHost* target_ash_host = |
| 113 AshWindowTreeHost* target_ash_host = | 178 GetRootWindowController(dst_window)->ash_host(); |
| 114 GetRootWindowController(in_src_edge ? dst_root : src_root)->ash_host(); | |
| 115 | 179 |
| 116 MoveCursorTo(target_ash_host, point_in_screen, update_mouse_location_now); | 180 MoveCursorTo(target_ash_host, point_in_screen, update_mouse_location_now); |
| 117 return true; | 181 return true; |
| 182 } | |
| 183 | |
| 184 return false; | |
| 118 } | 185 } |
| 119 | 186 |
| 120 void ExtendedMouseWarpController::UpdateHorizontalEdgeBounds() { | 187 scoped_ptr<ExtendedMouseWarpController::WarpRegion> |
| 121 bool from_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; | 188 ExtendedMouseWarpController::CreateHorizontalEdgeBounds( |
| 122 // GetPrimaryDisplay returns an object on stack, so copy the bounds | 189 const gfx::Display& a, |
| 123 // instead of using reference. | 190 const gfx::Display& b, |
| 124 const gfx::Rect primary_bounds = | 191 DisplayLayout::Position position) { |
| 125 Shell::GetScreen()->GetPrimaryDisplay().bounds(); | 192 bool from_a = a.id() == GetDisplayFromWindow(drag_source_root_).id(); |
| 126 const gfx::Rect secondary_bounds = ScreenUtil::GetSecondaryDisplay().bounds(); | |
| 127 DisplayLayout::Position position = Shell::GetInstance() | |
| 128 ->display_manager() | |
| 129 ->GetCurrentDisplayLayout() | |
| 130 .position; | |
| 131 | 193 |
| 132 src_indicator_bounds_.set_x( | 194 const gfx::Rect& a_bounds = a.bounds(); |
| 133 std::max(primary_bounds.x(), secondary_bounds.x())); | 195 const gfx::Rect& b_bounds = b.bounds(); |
| 134 src_indicator_bounds_.set_width( | 196 |
| 135 std::min(primary_bounds.right(), secondary_bounds.right()) - | 197 gfx::Rect a_indicator_bounds; |
| 136 src_indicator_bounds_.x()); | 198 a_indicator_bounds.set_x(std::max(a_bounds.x(), b_bounds.x())); |
| 137 src_indicator_bounds_.set_height(kIndicatorThickness); | 199 a_indicator_bounds.set_width(std::min(a_bounds.right(), b_bounds.right()) - |
| 138 src_indicator_bounds_.set_y( | 200 a_indicator_bounds.x()); |
| 201 a_indicator_bounds.set_height(kIndicatorThickness); | |
| 202 a_indicator_bounds.set_y( | |
| 139 position == DisplayLayout::TOP | 203 position == DisplayLayout::TOP |
| 140 ? primary_bounds.y() - (from_primary ? 0 : kIndicatorThickness) | 204 ? a_bounds.y() - (from_a ? 0 : kIndicatorThickness) |
| 141 : primary_bounds.bottom() - (from_primary ? kIndicatorThickness : 0)); | 205 : a_bounds.bottom() - (from_a ? kIndicatorThickness : 0)); |
| 142 | 206 |
| 143 dst_indicator_bounds_ = src_indicator_bounds_; | 207 gfx::Rect b_indicator_bounds; |
| 144 dst_indicator_bounds_.set_height(kIndicatorThickness); | 208 b_indicator_bounds = a_indicator_bounds; |
| 145 dst_indicator_bounds_.set_y( | 209 b_indicator_bounds.set_height(kIndicatorThickness); |
| 210 b_indicator_bounds.set_y( | |
| 146 position == DisplayLayout::TOP | 211 position == DisplayLayout::TOP |
| 147 ? primary_bounds.y() - (from_primary ? kIndicatorThickness : 0) | 212 ? a_bounds.y() - (from_a ? kIndicatorThickness : 0) |
| 148 : primary_bounds.bottom() - (from_primary ? 0 : kIndicatorThickness)); | 213 : a_bounds.bottom() - (from_a ? 0 : kIndicatorThickness)); |
| 149 | 214 |
| 150 aura::Window* src_root = nullptr; | 215 return make_scoped_ptr( |
| 151 aura::Window* dst_root = nullptr; | 216 new WarpRegion(a.id(), b.id(), a_indicator_bounds, b_indicator_bounds)); |
| 152 GetSrcAndDstRootWindows(&src_root, &dst_root); | |
| 153 | |
| 154 src_edge_bounds_in_native_ = GetNativeEdgeBounds( | |
| 155 GetRootWindowController(src_root)->ash_host(), src_indicator_bounds_); | |
| 156 dst_edge_bounds_in_native_ = GetNativeEdgeBounds( | |
| 157 GetRootWindowController(dst_root)->ash_host(), dst_indicator_bounds_); | |
| 158 } | 217 } |
| 159 | 218 |
| 160 void ExtendedMouseWarpController::UpdateVerticalEdgeBounds() { | 219 scoped_ptr<ExtendedMouseWarpController::WarpRegion> |
| 220 ExtendedMouseWarpController::CreateVerticalEdgeBounds( | |
| 221 const gfx::Display& a, | |
| 222 const gfx::Display& b, | |
| 223 DisplayLayout::Position position) { | |
| 161 int snap_height = drag_source_root_ ? kMaximumSnapHeight : 0; | 224 int snap_height = drag_source_root_ ? kMaximumSnapHeight : 0; |
| 162 bool in_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; | 225 bool in_a = a.id() == GetDisplayFromWindow(drag_source_root_).id(); |
| 163 // GetPrimaryDisplay returns an object on stack, so copy the bounds | |
| 164 // instead of using reference. | |
| 165 const gfx::Rect primary_bounds = | |
| 166 Shell::GetScreen()->GetPrimaryDisplay().bounds(); | |
| 167 const gfx::Rect secondary_bounds = ScreenUtil::GetSecondaryDisplay().bounds(); | |
| 168 DisplayLayout::Position position = Shell::GetInstance() | |
| 169 ->display_manager() | |
| 170 ->GetCurrentDisplayLayout() | |
| 171 .position; | |
| 172 | 226 |
| 173 int upper_shared_y = std::max(primary_bounds.y(), secondary_bounds.y()); | 227 const gfx::Rect& a_bounds = a.bounds(); |
| 174 int lower_shared_y = | 228 const gfx::Rect& b_bounds = b.bounds(); |
| 175 std::min(primary_bounds.bottom(), secondary_bounds.bottom()); | 229 |
| 230 int upper_shared_y = std::max(a_bounds.y(), b_bounds.y()); | |
| 231 int lower_shared_y = std::min(a_bounds.bottom(), b_bounds.bottom()); | |
| 176 int shared_height = lower_shared_y - upper_shared_y; | 232 int shared_height = lower_shared_y - upper_shared_y; |
| 177 | 233 |
| 178 int dst_x = | 234 gfx::Rect a_indicator_bounds; |
| 179 position == DisplayLayout::LEFT | 235 gfx::Rect b_indicator_bounds; |
| 180 ? primary_bounds.x() - (in_primary ? kIndicatorThickness : 0) | 236 |
| 181 : primary_bounds.right() - (in_primary ? 0 : kIndicatorThickness); | 237 int dst_x = position == DisplayLayout::LEFT |
| 182 dst_indicator_bounds_.SetRect(dst_x, upper_shared_y, kIndicatorThickness, | 238 ? a_bounds.x() - (in_a ? kIndicatorThickness : 0) |
| 183 shared_height); | 239 : a_bounds.right() - (in_a ? 0 : kIndicatorThickness); |
| 240 b_indicator_bounds.SetRect(dst_x, upper_shared_y, kIndicatorThickness, | |
| 241 shared_height); | |
| 184 | 242 |
| 185 // The indicator on the source display. | 243 // The indicator on the source display. |
| 186 src_indicator_bounds_.set_width(kIndicatorThickness); | 244 a_indicator_bounds.set_width(kIndicatorThickness); |
| 187 src_indicator_bounds_.set_x( | 245 a_indicator_bounds.set_x(position == DisplayLayout::LEFT |
| 188 position == DisplayLayout::LEFT | 246 ? a_bounds.x() - (in_a ? 0 : kIndicatorThickness) |
| 189 ? primary_bounds.x() - (in_primary ? 0 : kIndicatorThickness) | 247 : a_bounds.right() - |
| 190 : primary_bounds.right() - (in_primary ? kIndicatorThickness : 0)); | 248 (in_a ? kIndicatorThickness : 0)); |
| 191 | 249 |
| 192 const gfx::Rect& source_bounds = | 250 const gfx::Rect& source_bounds = in_a ? a_bounds : b_bounds; |
| 193 in_primary ? primary_bounds : secondary_bounds; | |
| 194 int upper_indicator_y = source_bounds.y() + snap_height; | 251 int upper_indicator_y = source_bounds.y() + snap_height; |
| 195 int lower_indicator_y = std::min(source_bounds.bottom(), lower_shared_y); | 252 int lower_indicator_y = std::min(source_bounds.bottom(), lower_shared_y); |
| 196 | 253 |
| 197 // This gives a hight that can be used without sacrifying the snap space. | 254 // This gives a hight that can be used without sacrifying the snap space. |
| 198 int available_space = | 255 int available_space = |
| 199 lower_indicator_y - std::max(upper_shared_y, upper_indicator_y); | 256 lower_indicator_y - std::max(upper_shared_y, upper_indicator_y); |
| 200 | 257 |
| 201 if (shared_height < kMinimumIndicatorHeight) { | 258 if (shared_height < kMinimumIndicatorHeight) { |
| 202 // If the shared height is smaller than minimum height, use the | 259 // If the shared height is smaller than minimum height, use the |
| 203 // entire height. | 260 // entire height. |
| 204 upper_indicator_y = upper_shared_y; | 261 upper_indicator_y = upper_shared_y; |
| 205 } else if (available_space < kMinimumIndicatorHeight) { | 262 } else if (available_space < kMinimumIndicatorHeight) { |
| 206 // Snap to the bottom. | 263 // Snap to the bottom. |
| 207 upper_indicator_y = | 264 upper_indicator_y = |
| 208 std::max(upper_shared_y, lower_indicator_y + kMinimumIndicatorHeight); | 265 std::max(upper_shared_y, lower_indicator_y + kMinimumIndicatorHeight); |
| 209 } else { | 266 } else { |
| 210 upper_indicator_y = std::max(upper_indicator_y, upper_shared_y); | 267 upper_indicator_y = std::max(upper_indicator_y, upper_shared_y); |
| 211 } | 268 } |
| 212 src_indicator_bounds_.set_y(upper_indicator_y); | 269 a_indicator_bounds.set_y(upper_indicator_y); |
| 213 src_indicator_bounds_.set_height(lower_indicator_y - upper_indicator_y); | 270 a_indicator_bounds.set_height(lower_indicator_y - upper_indicator_y); |
| 214 | 271 |
| 215 aura::Window* src_root = nullptr; | 272 return make_scoped_ptr( |
| 216 aura::Window* dst_root = nullptr; | 273 new WarpRegion(a.id(), b.id(), a_indicator_bounds, b_indicator_bounds)); |
| 217 GetSrcAndDstRootWindows(&src_root, &dst_root); | |
| 218 | |
| 219 // Native | |
| 220 src_edge_bounds_in_native_ = GetNativeEdgeBounds( | |
| 221 GetRootWindowController(src_root)->ash_host(), src_indicator_bounds_); | |
| 222 dst_edge_bounds_in_native_ = GetNativeEdgeBounds( | |
| 223 GetRootWindowController(dst_root)->ash_host(), dst_indicator_bounds_); | |
| 224 } | |
| 225 | |
| 226 void ExtendedMouseWarpController::GetSrcAndDstRootWindows( | |
| 227 aura::Window** src_root, | |
| 228 aura::Window** dst_root) { | |
| 229 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | |
| 230 *src_root = drag_source_root_ ? drag_source_root_ | |
| 231 : Shell::GetInstance()->GetPrimaryRootWindow(); | |
| 232 *dst_root = root_windows[0] == *src_root ? root_windows[1] : root_windows[0]; | |
| 233 } | 274 } |
| 234 | 275 |
| 235 } // namespace ash | 276 } // namespace ash |
| OLD | NEW |