| 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/workspace/workspace_window_resizer.h" | 5 #include "ash/wm/workspace/workspace_window_resizer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 | 9 |
| 10 #include "ash/display/display_controller.h" | 10 #include "ash/display/display_controller.h" |
| 11 #include "ash/display/mouse_cursor_event_filter.h" | 11 #include "ash/display/mouse_cursor_event_filter.h" |
| 12 #include "ash/screen_ash.h" | 12 #include "ash/screen_ash.h" |
| 13 #include "ash/shell.h" | 13 #include "ash/shell.h" |
| 14 #include "ash/wm/coordinate_conversion.h" | 14 #include "ash/wm/coordinate_conversion.h" |
| 15 #include "ash/wm/cursor_manager.h" | 15 #include "ash/wm/cursor_manager.h" |
| 16 #include "ash/wm/property_util.h" | 16 #include "ash/wm/property_util.h" |
| 17 #include "ash/wm/window_util.h" | 17 #include "ash/wm/window_util.h" |
| 18 #include "ash/wm/workspace/phantom_window_controller.h" | 18 #include "ash/wm/workspace/phantom_window_controller.h" |
| 19 #include "ash/wm/workspace/snap_sizer.h" | 19 #include "ash/wm/workspace/snap_sizer.h" |
| 20 #include "ui/aura/client/aura_constants.h" | 20 #include "ui/aura/client/aura_constants.h" |
| 21 #include "ui/aura/root_window.h" | 21 #include "ui/aura/root_window.h" |
| 22 #include "ui/aura/window.h" | 22 #include "ui/aura/window.h" |
| 23 #include "ui/aura/window_delegate.h" | 23 #include "ui/aura/window_delegate.h" |
| 24 #include "ui/base/hit_test.h" | 24 #include "ui/base/hit_test.h" |
| 25 #include "ui/compositor/layer.h" | 25 #include "ui/compositor/layer.h" |
| 26 #include "ui/compositor/scoped_layer_animation_settings.h" | |
| 27 #include "ui/gfx/screen.h" | 26 #include "ui/gfx/screen.h" |
| 28 #include "ui/gfx/transform.h" | 27 #include "ui/gfx/transform.h" |
| 29 | 28 |
| 30 namespace ash { | 29 namespace ash { |
| 31 namespace internal { | 30 namespace internal { |
| 32 | 31 |
| 33 namespace { | 32 namespace { |
| 34 | 33 |
| 35 // Duration of the animation when snapping the window into place. | 34 // Duration of the animation when snapping the window into place. |
| 36 const int kSnapDurationMS = 100; | 35 const int kSnapDurationMS = 100; |
| 37 | 36 |
| 38 // The maximum opacity of the drag phantom window. | 37 // The maximum opacity of the drag phantom window. |
| 39 const float kMaxOpacity = 0.8f; | 38 const float kMaxOpacity = 0.8f; |
| 40 | 39 |
| 41 // Returns true if should snap to the edge. | 40 // Returns true if should snap to the edge. |
| 42 bool ShouldSnapToEdge(int distance_from_edge, int grid_size) { | 41 bool ShouldSnapToEdge(int distance_from_edge, int grid_size) { |
| 43 return distance_from_edge <= grid_size / 2 && | 42 return distance_from_edge < grid_size && |
| 44 distance_from_edge > -grid_size * 2; | 43 distance_from_edge > -grid_size * 2; |
| 45 } | 44 } |
| 46 | 45 |
| 47 // Returns true if Ash has more than one root window. | 46 // Returns true if Ash has more than one root window. |
| 48 bool HasSecondaryRootWindow() { | 47 bool HasSecondaryRootWindow() { |
| 49 return Shell::GetAllRootWindows().size() > 1; | 48 return Shell::GetAllRootWindows().size() > 1; |
| 50 } | 49 } |
| 51 | 50 |
| 52 // When there are two root windows, returns one of the root windows which is not | 51 // When there are two root windows, returns one of the root windows which is not |
| 53 // |root_window|. Returns NULL if only one root window exists. | 52 // |root_window|. Returns NULL if only one root window exists. |
| 54 aura::RootWindow* GetAnotherRootWindow(aura::RootWindow* root_window) { | 53 aura::RootWindow* GetAnotherRootWindow(aura::RootWindow* root_window) { |
| 55 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); | 54 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
| 56 if (root_windows.size() < 2) | 55 if (root_windows.size() < 2) |
| 57 return NULL; | 56 return NULL; |
| 58 DCHECK_EQ(2U, root_windows.size()); | 57 DCHECK_EQ(2U, root_windows.size()); |
| 59 if (root_windows[0] == root_window) | 58 if (root_windows[0] == root_window) |
| 60 return root_windows[1]; | 59 return root_windows[1]; |
| 61 return root_windows[0]; | 60 return root_windows[0]; |
| 62 } | 61 } |
| 63 | 62 |
| 64 } // namespace | 63 } // namespace |
| 65 | 64 |
| 66 // static | 65 // static |
| 67 const int WorkspaceWindowResizer::kMinOnscreenSize = 20; | 66 const int WorkspaceWindowResizer::kMinOnscreenSize = 20; |
| 68 | 67 |
| 69 // static | 68 // static |
| 70 const int WorkspaceWindowResizer::kMinOnscreenHeight = 32; | 69 const int WorkspaceWindowResizer::kMinOnscreenHeight = 32; |
| 71 | 70 |
| 71 // static |
| 72 const int WorkspaceWindowResizer::kScreenEdgeInset = 8; |
| 73 |
| 72 WorkspaceWindowResizer::~WorkspaceWindowResizer() { | 74 WorkspaceWindowResizer::~WorkspaceWindowResizer() { |
| 73 Shell* shell = Shell::GetInstance(); | 75 Shell* shell = Shell::GetInstance(); |
| 74 shell->mouse_cursor_filter()->set_mouse_warp_mode( | 76 shell->mouse_cursor_filter()->set_mouse_warp_mode( |
| 75 MouseCursorEventFilter::WARP_ALWAYS); | 77 MouseCursorEventFilter::WARP_ALWAYS); |
| 76 shell->mouse_cursor_filter()->HideSharedEdgeIndicator(); | 78 shell->mouse_cursor_filter()->HideSharedEdgeIndicator(); |
| 77 shell->cursor_manager()->UnlockCursor(); | 79 shell->cursor_manager()->UnlockCursor(); |
| 78 | 80 |
| 79 // Delete phantom controllers first so that they will never see the deleted | 81 // Delete phantom controllers first so that they will never see the deleted |
| 80 // |layer_|. | 82 // |layer_|. |
| 81 snap_phantom_window_controller_.reset(); | 83 snap_phantom_window_controller_.reset(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 109 &location_in_parent); | 111 &location_in_parent); |
| 110 last_mouse_location_ = location_in_parent; | 112 last_mouse_location_ = location_in_parent; |
| 111 | 113 |
| 112 // Do not use |location| below this point, use |location_in_parent| instead. | 114 // Do not use |location| below this point, use |location_in_parent| instead. |
| 113 // When the pointer is on |window()->GetRootWindow()|, |location| and | 115 // When the pointer is on |window()->GetRootWindow()|, |location| and |
| 114 // |location_in_parent| have the same value and both of them are in | 116 // |location_in_parent| have the same value and both of them are in |
| 115 // |window()->parent()|'s coordinates, but once the pointer enters the | 117 // |window()->parent()|'s coordinates, but once the pointer enters the |
| 116 // other root window, you will see an unexpected value on the former. See | 118 // other root window, you will see an unexpected value on the former. See |
| 117 // comments in wm::GetRootWindowRelativeToWindow() for details. | 119 // comments in wm::GetRootWindowRelativeToWindow() for details. |
| 118 | 120 |
| 119 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? | 121 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? 0 : kScreenEdgeInset; |
| 120 0 : ash::Shell::GetInstance()->GetGridSize(); | |
| 121 gfx::Rect bounds = // in |window()->parent()|'s coordinates. | 122 gfx::Rect bounds = // in |window()->parent()|'s coordinates. |
| 122 CalculateBoundsForDrag(details_, location_in_parent, grid_size); | 123 CalculateBoundsForDrag(details_, location_in_parent); |
| 123 | 124 |
| 124 if (wm::IsWindowNormal(window())) | 125 if (wm::IsWindowNormal(window())) |
| 125 AdjustBoundsForMainWindow(&bounds, grid_size); | 126 AdjustBoundsForMainWindow(&bounds, grid_size); |
| 126 if (bounds != window()->bounds()) { | 127 if (bounds != window()->bounds()) { |
| 127 if (!did_move_or_resize_) | 128 if (!did_move_or_resize_) |
| 128 RestackWindows(); | 129 RestackWindows(); |
| 129 did_move_or_resize_ = true; | 130 did_move_or_resize_ = true; |
| 130 } | 131 } |
| 131 | 132 |
| 132 const bool in_original_root = (window()->GetRootWindow() == current_root); | 133 const bool in_original_root = (window()->GetRootWindow() == current_root); |
| 133 // Hide a phantom window for snapping if the cursor is in another root window. | 134 // Hide a phantom window for snapping if the cursor is in another root window. |
| 134 if (in_original_root) | 135 if (in_original_root) |
| 135 UpdateSnapPhantomWindow(location_in_parent, bounds, grid_size); | 136 UpdateSnapPhantomWindow(location_in_parent, bounds); |
| 136 else | 137 else |
| 137 snap_phantom_window_controller_.reset(); | 138 snap_phantom_window_controller_.reset(); |
| 138 | 139 |
| 139 if (!attached_windows_.empty()) | 140 if (!attached_windows_.empty()) |
| 140 LayoutAttachedWindows(bounds, grid_size); | 141 LayoutAttachedWindows(bounds); |
| 141 if (bounds != window()->bounds()) { | 142 if (bounds != window()->bounds()) { |
| 142 bool destroyed = false; | 143 bool destroyed = false; |
| 143 destroyed_ = &destroyed; | 144 destroyed_ = &destroyed; |
| 144 window()->SetBounds(bounds); | 145 window()->SetBounds(bounds); |
| 145 if (destroyed) | 146 if (destroyed) |
| 146 return; | 147 return; |
| 147 destroyed_ = NULL; | 148 destroyed_ = NULL; |
| 148 } | 149 } |
| 149 // Show a phantom window for dragging in another root window. | 150 // Show a phantom window for dragging in another root window. |
| 150 if (HasSecondaryRootWindow()) | 151 if (HasSecondaryRootWindow()) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 161 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 162 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
| 162 return; | 163 return; |
| 163 | 164 |
| 164 if (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE) { | 165 if (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE) { |
| 165 if (!GetRestoreBoundsInScreen(window())) | 166 if (!GetRestoreBoundsInScreen(window())) |
| 166 SetRestoreBoundsInParent(window(), details_.initial_bounds); | 167 SetRestoreBoundsInParent(window(), details_.initial_bounds); |
| 167 window()->SetBounds(snap_sizer_->target_bounds()); | 168 window()->SetBounds(snap_sizer_->target_bounds()); |
| 168 return; | 169 return; |
| 169 } | 170 } |
| 170 | 171 |
| 171 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? | 172 gfx::Rect bounds(GetFinalBounds(window()->bounds())); |
| 172 0 : ash::Shell::GetInstance()->GetGridSize(); | |
| 173 gfx::Rect bounds(GetFinalBounds(window()->bounds(), grid_size)); | |
| 174 | 173 |
| 175 // Check if the destination is another display. | 174 // Check if the destination is another display. |
| 176 gfx::Point last_mouse_location_in_screen = last_mouse_location_; | 175 gfx::Point last_mouse_location_in_screen = last_mouse_location_; |
| 177 wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen); | 176 wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen); |
| 178 const gfx::Display dst_display = | 177 const gfx::Display dst_display = |
| 179 gfx::Screen::GetDisplayNearestPoint(last_mouse_location_in_screen); | 178 gfx::Screen::GetDisplayNearestPoint(last_mouse_location_in_screen); |
| 180 | 179 |
| 181 if (dst_display.id() != | 180 if (dst_display.id() != |
| 182 gfx::Screen::GetDisplayNearestWindow(window()->GetRootWindow()).id()) { | 181 gfx::Screen::GetDisplayNearestWindow(window()->GetRootWindow()).id()) { |
| 183 // Don't animate when moving to another display. | 182 // Don't animate when moving to another display. |
| 184 const gfx::Rect dst_bounds = | 183 const gfx::Rect dst_bounds = |
| 185 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds); | 184 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds); |
| 186 window()->SetBoundsInScreen(dst_bounds, dst_display); | 185 window()->SetBoundsInScreen(dst_bounds, dst_display); |
| 187 return; | |
| 188 } | 186 } |
| 189 | |
| 190 if (grid_size <= 1 || bounds == window()->bounds()) | |
| 191 return; | |
| 192 | |
| 193 if (bounds.size() != window()->bounds().size()) { | |
| 194 // Don't attempt to animate a size change. | |
| 195 window()->SetBounds(bounds); | |
| 196 return; | |
| 197 } | |
| 198 | |
| 199 ui::ScopedLayerAnimationSettings scoped_setter( | |
| 200 window()->layer()->GetAnimator()); | |
| 201 // Use a small duration since the grid is small. | |
| 202 scoped_setter.SetTransitionDuration( | |
| 203 base::TimeDelta::FromMilliseconds(kSnapDurationMS)); | |
| 204 window()->SetBounds(bounds); | |
| 205 } | 187 } |
| 206 | 188 |
| 207 void WorkspaceWindowResizer::RevertDrag() { | 189 void WorkspaceWindowResizer::RevertDrag() { |
| 208 window()->layer()->SetOpacity(details_.initial_opacity); | 190 window()->layer()->SetOpacity(details_.initial_opacity); |
| 209 drag_phantom_window_controller_.reset(); | 191 drag_phantom_window_controller_.reset(); |
| 210 snap_phantom_window_controller_.reset(); | 192 snap_phantom_window_controller_.reset(); |
| 211 Shell::GetInstance()->mouse_cursor_filter()->HideSharedEdgeIndicator(); | 193 Shell::GetInstance()->mouse_cursor_filter()->HideSharedEdgeIndicator(); |
| 212 | 194 |
| 213 if (!did_move_or_resize_) | 195 if (!did_move_or_resize_) |
| 214 return; | 196 return; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 | 254 |
| 273 // Only support attaching to the right/bottom. | 255 // Only support attaching to the right/bottom. |
| 274 DCHECK(attached_windows_.empty() || | 256 DCHECK(attached_windows_.empty() || |
| 275 (details.window_component == HTRIGHT || | 257 (details.window_component == HTRIGHT || |
| 276 details.window_component == HTBOTTOM)); | 258 details.window_component == HTBOTTOM)); |
| 277 | 259 |
| 278 // TODO: figure out how to deal with window going off the edge. | 260 // TODO: figure out how to deal with window going off the edge. |
| 279 | 261 |
| 280 // Calculate sizes so that we can maintain the ratios if we need to resize. | 262 // Calculate sizes so that we can maintain the ratios if we need to resize. |
| 281 int total_available = 0; | 263 int total_available = 0; |
| 282 int grid_size = ash::Shell::GetInstance()->GetGridSize(); | |
| 283 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 264 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 284 gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); | 265 gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); |
| 285 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); | 266 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); |
| 286 initial_size_.push_back(initial_size); | 267 initial_size_.push_back(initial_size); |
| 287 // If current size is smaller than the min, use the current size as the min. | 268 // If current size is smaller than the min, use the current size as the min. |
| 288 // This way we don't snap on resize. | 269 // This way we don't snap on resize. |
| 289 int min_size = std::min(initial_size, | 270 int min_size = std::min(initial_size, |
| 290 std::max(PrimaryAxisSize(min), kMinOnscreenSize)); | 271 std::max(PrimaryAxisSize(min), kMinOnscreenSize)); |
| 291 // Make sure the min size falls on the grid. | |
| 292 if (grid_size > 1 && min_size % grid_size != 0) | |
| 293 min_size = (min_size / grid_size + 1) * grid_size; | |
| 294 min_size_.push_back(min_size); | 272 min_size_.push_back(min_size); |
| 295 total_min_ += min_size; | 273 total_min_ += min_size; |
| 296 total_initial_size_ += initial_size; | 274 total_initial_size_ += initial_size; |
| 297 total_available += std::max(min_size, initial_size) - min_size; | 275 total_available += std::max(min_size, initial_size) - min_size; |
| 298 } | 276 } |
| 299 | 277 |
| 300 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 278 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 301 expand_fraction_.push_back( | 279 expand_fraction_.push_back( |
| 302 static_cast<float>(initial_size_[i]) / | 280 static_cast<float>(initial_size_[i]) / |
| 303 static_cast<float>(total_initial_size_)); | 281 static_cast<float>(total_initial_size_)); |
| 304 if (total_initial_size_ != total_min_) { | 282 if (total_initial_size_ != total_min_) { |
| 305 compress_fraction_.push_back( | 283 compress_fraction_.push_back( |
| 306 static_cast<float>(initial_size_[i] - min_size_[i]) / | 284 static_cast<float>(initial_size_[i] - min_size_[i]) / |
| 307 static_cast<float>(total_available)); | 285 static_cast<float>(total_available)); |
| 308 } else { | 286 } else { |
| 309 compress_fraction_.push_back(0.0f); | 287 compress_fraction_.push_back(0.0f); |
| 310 } | 288 } |
| 311 } | 289 } |
| 312 } | 290 } |
| 313 | 291 |
| 314 gfx::Rect WorkspaceWindowResizer::GetFinalBounds( | 292 gfx::Rect WorkspaceWindowResizer::GetFinalBounds( |
| 315 const gfx::Rect& bounds, | 293 const gfx::Rect& bounds) const { |
| 316 int grid_size) const { | |
| 317 if (snap_phantom_window_controller_.get() && | 294 if (snap_phantom_window_controller_.get() && |
| 318 snap_phantom_window_controller_->IsShowing()) { | 295 snap_phantom_window_controller_->IsShowing()) { |
| 319 return snap_phantom_window_controller_->bounds(); | 296 return snap_phantom_window_controller_->bounds(); |
| 320 } | 297 } |
| 321 return AdjustBoundsToGrid(bounds, grid_size); | 298 return bounds; |
| 322 } | 299 } |
| 323 | 300 |
| 324 void WorkspaceWindowResizer::LayoutAttachedWindows( | 301 void WorkspaceWindowResizer::LayoutAttachedWindows( |
| 325 const gfx::Rect& bounds, | 302 const gfx::Rect& bounds) { |
| 326 int grid_size) { | |
| 327 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); | 303 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); |
| 328 std::vector<int> sizes; | 304 std::vector<int> sizes; |
| 329 CalculateAttachedSizes( | 305 CalculateAttachedSizes( |
| 330 PrimaryAxisSize(details_.initial_bounds.size()), | 306 PrimaryAxisSize(details_.initial_bounds.size()), |
| 331 PrimaryAxisSize(bounds.size()), | 307 PrimaryAxisSize(bounds.size()), |
| 332 PrimaryAxisCoordinate(bounds.right(), bounds.bottom()), | 308 PrimaryAxisCoordinate(bounds.right(), bounds.bottom()), |
| 333 PrimaryAxisCoordinate(work_area.right(), work_area.bottom()), | 309 PrimaryAxisCoordinate(work_area.right(), work_area.bottom()), |
| 334 grid_size, | |
| 335 &sizes); | 310 &sizes); |
| 336 DCHECK_EQ(attached_windows_.size(), sizes.size()); | 311 DCHECK_EQ(attached_windows_.size(), sizes.size()); |
| 337 int last = PrimaryAxisCoordinate(bounds.right(), bounds.bottom()); | 312 int last = PrimaryAxisCoordinate(bounds.right(), bounds.bottom()); |
| 338 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 313 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 339 gfx::Rect attached_bounds(attached_windows_[i]->bounds()); | 314 gfx::Rect attached_bounds(attached_windows_[i]->bounds()); |
| 340 if (details_.window_component == HTRIGHT) { | 315 if (details_.window_component == HTRIGHT) { |
| 341 attached_bounds.set_x(last); | 316 attached_bounds.set_x(last); |
| 342 attached_bounds.set_width(sizes[i]); | 317 attached_bounds.set_width(sizes[i]); |
| 343 } else { | 318 } else { |
| 344 attached_bounds.set_y(last); | 319 attached_bounds.set_y(last); |
| 345 attached_bounds.set_height(sizes[i]); | 320 attached_bounds.set_height(sizes[i]); |
| 346 } | 321 } |
| 347 attached_windows_[i]->SetBounds(attached_bounds); | 322 attached_windows_[i]->SetBounds(attached_bounds); |
| 348 last += sizes[i]; | 323 last += sizes[i]; |
| 349 } | 324 } |
| 350 } | 325 } |
| 351 | 326 |
| 352 void WorkspaceWindowResizer::CalculateAttachedSizes( | 327 void WorkspaceWindowResizer::CalculateAttachedSizes( |
| 353 int initial_size, | 328 int initial_size, |
| 354 int current_size, | 329 int current_size, |
| 355 int start, | 330 int start, |
| 356 int end, | 331 int end, |
| 357 int grid_size, | |
| 358 std::vector<int>* sizes) const { | 332 std::vector<int>* sizes) const { |
| 359 sizes->clear(); | 333 sizes->clear(); |
| 360 if (current_size < initial_size) { | 334 if (current_size < initial_size) { |
| 361 // If the primary window is sized smaller, resize the attached windows. | 335 // If the primary window is sized smaller, resize the attached windows. |
| 362 int current = start; | 336 int current = start; |
| 363 int delta = initial_size - current_size; | 337 int delta = initial_size - current_size; |
| 364 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 338 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 365 int next = AlignToGrid( | 339 int next = current + initial_size_[i] + expand_fraction_[i] * delta; |
| 366 current + initial_size_[i] + expand_fraction_[i] * delta, | 340 if (i + 1 == attached_windows_.size()) |
| 367 grid_size); | 341 next = start + total_initial_size_ + (initial_size - current_size); |
| 368 if (i == attached_windows_.size()) | |
| 369 next = end; | |
| 370 sizes->push_back(next - current); | 342 sizes->push_back(next - current); |
| 371 current = next; | 343 current = next; |
| 372 } | 344 } |
| 373 } else if (start <= end - total_initial_size_) { | 345 } else if (start <= end - total_initial_size_) { |
| 374 // All the windows fit at their initial size; tile them horizontally. | 346 // All the windows fit at their initial size; tile them horizontally. |
| 375 for (size_t i = 0; i < attached_windows_.size(); ++i) | 347 for (size_t i = 0; i < attached_windows_.size(); ++i) |
| 376 sizes->push_back(initial_size_[i]); | 348 sizes->push_back(initial_size_[i]); |
| 377 } else { | 349 } else { |
| 378 DCHECK_NE(total_initial_size_, total_min_); | 350 DCHECK_NE(total_initial_size_, total_min_); |
| 379 int delta = total_initial_size_ - (end - start); | 351 int delta = total_initial_size_ - (end - start); |
| 380 int current = start; | 352 int current = start; |
| 381 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 353 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 382 int size = initial_size_[i] - | 354 int size = initial_size_[i] - |
| 383 static_cast<int>(compress_fraction_[i] * delta); | 355 static_cast<int>(compress_fraction_[i] * delta); |
| 384 size = AlignToGrid(size, grid_size); | 356 if (i + 1 == attached_windows_.size()) |
| 385 if (i == attached_windows_.size()) | |
| 386 size = end - current; | 357 size = end - current; |
| 387 current += size; | 358 current += size; |
| 388 sizes->push_back(size); | 359 sizes->push_back(size); |
| 389 } | 360 } |
| 390 } | 361 } |
| 391 } | 362 } |
| 392 | 363 |
| 393 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( | 364 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( |
| 394 gfx::Rect* bounds, int grid_size) const { | 365 gfx::Rect* bounds, |
| 366 int grid_size) const { |
| 395 // Always keep kMinOnscreenHeight on the bottom except when an extended | 367 // Always keep kMinOnscreenHeight on the bottom except when an extended |
| 396 // display is available and a window is being dragged. | 368 // display is available and a window is being dragged. |
| 397 gfx::Rect work_area( | 369 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); |
| 398 ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); | 370 int max_y = work_area.bottom() - kMinOnscreenHeight; |
| 399 int max_y = AlignToGridRoundUp(work_area.bottom() - kMinOnscreenHeight, | |
| 400 grid_size); | |
| 401 if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && | 371 if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && |
| 402 bounds->y() > max_y) { | 372 bounds->y() > max_y) { |
| 403 bounds->set_y(max_y); | 373 bounds->set_y(max_y); |
| 404 } | 374 } |
| 405 | 375 |
| 406 // Don't allow dragging above the top of the display except when an extended | 376 // Don't allow dragging above the top of the display except when an extended |
| 407 // display is available and a window is being dragged. | 377 // display is available and a window is being dragged. |
| 408 if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && | 378 if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && |
| 409 bounds->y() <= work_area.y()) { | 379 bounds->y() <= work_area.y()) { |
| 410 bounds->set_y(work_area.y()); | 380 bounds->set_y(work_area.y()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 423 DCHECK_EQ(HTBOTTOM, details_.window_component); | 393 DCHECK_EQ(HTBOTTOM, details_.window_component); |
| 424 bounds->set_height(std::min(bounds->height(), | 394 bounds->set_height(std::min(bounds->height(), |
| 425 work_area.bottom() - total_min_ - bounds->y())); | 395 work_area.bottom() - total_min_ - bounds->y())); |
| 426 } | 396 } |
| 427 } | 397 } |
| 428 | 398 |
| 429 void WorkspaceWindowResizer::SnapToWorkAreaEdges( | 399 void WorkspaceWindowResizer::SnapToWorkAreaEdges( |
| 430 const gfx::Rect& work_area, | 400 const gfx::Rect& work_area, |
| 431 gfx::Rect* bounds, | 401 gfx::Rect* bounds, |
| 432 int grid_size) const { | 402 int grid_size) const { |
| 433 int left_edge = AlignToGridRoundUp(work_area.x(), grid_size); | 403 int left_edge = work_area.x(); |
| 434 int right_edge = AlignToGridRoundDown(work_area.right(), grid_size); | 404 int right_edge = work_area.right(); |
| 435 int top_edge = AlignToGridRoundUp(work_area.y(), grid_size); | 405 int top_edge = work_area.y(); |
| 436 int bottom_edge = AlignToGridRoundDown(work_area.bottom(), | 406 int bottom_edge = work_area.bottom(); |
| 437 grid_size); | |
| 438 if (ShouldSnapToEdge(bounds->x() - left_edge, grid_size)) { | 407 if (ShouldSnapToEdge(bounds->x() - left_edge, grid_size)) { |
| 439 bounds->set_x(left_edge); | 408 bounds->set_x(left_edge); |
| 440 } else if (ShouldSnapToEdge(right_edge - bounds->right(), | 409 } else if (ShouldSnapToEdge(right_edge - bounds->right(), |
| 441 grid_size)) { | 410 grid_size)) { |
| 442 bounds->set_x(right_edge - bounds->width()); | 411 bounds->set_x(right_edge - bounds->width()); |
| 443 } | 412 } |
| 444 if (ShouldSnapToEdge(bounds->y() - top_edge, grid_size)) { | 413 if (ShouldSnapToEdge(bounds->y() - top_edge, grid_size)) { |
| 445 bounds->set_y(top_edge); | 414 bounds->set_y(top_edge); |
| 446 } else if (ShouldSnapToEdge(bottom_edge - bounds->bottom(), grid_size) && | 415 } else if (ShouldSnapToEdge(bottom_edge - bounds->bottom(), grid_size) && |
| 447 bounds->height() < (bottom_edge - top_edge)) { | 416 bounds->height() < (bottom_edge - top_edge)) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 } | 488 } |
| 520 drag_phantom_window_controller_->SetOpacity(phantom_opacity); | 489 drag_phantom_window_controller_->SetOpacity(phantom_opacity); |
| 521 window()->layer()->SetOpacity(window_opacity); | 490 window()->layer()->SetOpacity(window_opacity); |
| 522 } else { | 491 } else { |
| 523 drag_phantom_window_controller_.reset(); | 492 drag_phantom_window_controller_.reset(); |
| 524 window()->layer()->SetOpacity(1.0f); | 493 window()->layer()->SetOpacity(1.0f); |
| 525 } | 494 } |
| 526 } | 495 } |
| 527 | 496 |
| 528 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, | 497 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, |
| 529 const gfx::Rect& bounds, | 498 const gfx::Rect& bounds) { |
| 530 int grid_size) { | |
| 531 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 499 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
| 532 return; | 500 return; |
| 533 | 501 |
| 534 SnapType last_type = snap_type_; | 502 SnapType last_type = snap_type_; |
| 535 snap_type_ = GetSnapType(location); | 503 snap_type_ = GetSnapType(location); |
| 536 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { | 504 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { |
| 537 snap_phantom_window_controller_.reset(); | 505 snap_phantom_window_controller_.reset(); |
| 538 snap_sizer_.reset(); | 506 snap_sizer_.reset(); |
| 539 if (snap_type_ == SNAP_NONE) | 507 if (snap_type_ == SNAP_NONE) |
| 540 return; | 508 return; |
| 541 } | 509 } |
| 542 if (!snap_sizer_.get()) { | 510 if (!snap_sizer_.get()) { |
| 543 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT_EDGE) ? | 511 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT_EDGE) ? |
| 544 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; | 512 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; |
| 545 snap_sizer_.reset( | 513 snap_sizer_.reset(new SnapSizer(window(), location, edge)); |
| 546 new SnapSizer(window(), location, edge, grid_size)); | |
| 547 } else { | 514 } else { |
| 548 snap_sizer_->Update(location); | 515 snap_sizer_->Update(location); |
| 549 } | 516 } |
| 550 if (!snap_phantom_window_controller_.get()) { | 517 if (!snap_phantom_window_controller_.get()) { |
| 551 snap_phantom_window_controller_.reset( | 518 snap_phantom_window_controller_.reset( |
| 552 new PhantomWindowController(window())); | 519 new PhantomWindowController(window())); |
| 553 } | 520 } |
| 554 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( | 521 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( |
| 555 window()->parent(), snap_sizer_->target_bounds()), NULL); | 522 window()->parent(), snap_sizer_->target_bounds()), NULL); |
| 556 } | 523 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 gfx::Rect layer_bounds = layer_->bounds(); | 582 gfx::Rect layer_bounds = layer_->bounds(); |
| 616 layer_bounds.set_origin(gfx::Point(0, 0)); | 583 layer_bounds.set_origin(gfx::Point(0, 0)); |
| 617 layer_->SetBounds(layer_bounds); | 584 layer_->SetBounds(layer_bounds); |
| 618 layer_->SetVisible(false); | 585 layer_->SetVisible(false); |
| 619 // Detach it from the current container. | 586 // Detach it from the current container. |
| 620 layer_->parent()->Remove(layer_); | 587 layer_->parent()->Remove(layer_); |
| 621 } | 588 } |
| 622 | 589 |
| 623 } // namespace internal | 590 } // namespace internal |
| 624 } // namespace ash | 591 } // namespace ash |
| OLD | NEW |