Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(361)

Side by Side Diff: ash/wm/dock/docked_window_layout_manager.cc

Issue 23431009: Windows docking should get triggered by pressing against the screen edge (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Windows docking by pressing against the screen edge (rebase) Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/dock/docked_window_layout_manager.h" 5 #include "ash/wm/dock/docked_window_layout_manager.h"
6 6
7 #include "ash/ash_switches.h"
7 #include "ash/launcher/launcher.h" 8 #include "ash/launcher/launcher.h"
8 #include "ash/screen_ash.h" 9 #include "ash/screen_ash.h"
9 #include "ash/shelf/shelf_layout_manager.h" 10 #include "ash/shelf/shelf_layout_manager.h"
10 #include "ash/shelf/shelf_types.h" 11 #include "ash/shelf/shelf_types.h"
11 #include "ash/shelf/shelf_widget.h" 12 #include "ash/shelf/shelf_widget.h"
12 #include "ash/shell.h" 13 #include "ash/shell.h"
13 #include "ash/shell_window_ids.h" 14 #include "ash/shell_window_ids.h"
14 #include "ash/wm/coordinate_conversion.h" 15 #include "ash/wm/coordinate_conversion.h"
15 #include "ash/wm/window_properties.h" 16 #include "ash/wm/window_properties.h"
16 #include "ash/wm/window_util.h" 17 #include "ash/wm/window_util.h"
18 #include "ash/wm/workspace/snap_types.h"
17 #include "base/auto_reset.h" 19 #include "base/auto_reset.h"
20 #include "base/command_line.h"
18 #include "third_party/skia/include/core/SkColor.h" 21 #include "third_party/skia/include/core/SkColor.h"
19 #include "ui/aura/client/activation_client.h" 22 #include "ui/aura/client/activation_client.h"
20 #include "ui/aura/client/aura_constants.h" 23 #include "ui/aura/client/aura_constants.h"
21 #include "ui/aura/focus_manager.h" 24 #include "ui/aura/focus_manager.h"
22 #include "ui/aura/root_window.h" 25 #include "ui/aura/root_window.h"
23 #include "ui/aura/window.h" 26 #include "ui/aura/window.h"
24 #include "ui/gfx/rect.h" 27 #include "ui/gfx/rect.h"
25 28
26 namespace ash { 29 namespace ash {
27 namespace internal { 30 namespace internal {
28 31
29 // Minimum, maximum width of the dock area and a width of the gap 32 // Minimum, maximum width of the dock area and a width of the gap
33 // static
34 const int DockedWindowLayoutManager::kMaxDockWidth = 360;
35 // static
30 const int DockedWindowLayoutManager::kMinDockWidth = 200; 36 const int DockedWindowLayoutManager::kMinDockWidth = 200;
31 const int DockedWindowLayoutManager::kMaxDockWidth = 450; 37 // static
32 const int DockedWindowLayoutManager::kMinDockGap = 2; 38 const int DockedWindowLayoutManager::kMinDockGap = 2;
33 const int kWindowIdealSpacing = 4;
34 39
35 namespace { 40 namespace {
36 41
37 const SkColor kDockBackgroundColor = SkColorSetARGB(0xff, 0x10, 0x10, 0x10); 42 const SkColor kDockBackgroundColor = SkColorSetARGB(0xff, 0x10, 0x10, 0x10);
38 const float kDockBackgroundOpacity = 0.5f; 43 const float kDockBackgroundOpacity = 0.5f;
39 44
40 class DockedBackgroundWidget : public views::Widget { 45 class DockedBackgroundWidget : public views::Widget {
41 public: 46 public:
42 explicit DockedBackgroundWidget(aura::Window* container) { 47 explicit DockedBackgroundWidget(aura::Window* container) {
43 InitWidget(container); 48 InitWidget(container);
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 } 205 }
201 206
202 void DockedWindowLayoutManager::DockDraggedWindow(aura::Window* window) { 207 void DockedWindowLayoutManager::DockDraggedWindow(aura::Window* window) {
203 OnWindowDocked(window); 208 OnWindowDocked(window);
204 Relayout(); 209 Relayout();
205 } 210 }
206 211
207 void DockedWindowLayoutManager::UndockDraggedWindow() { 212 void DockedWindowLayoutManager::UndockDraggedWindow() {
208 OnWindowUndocked(); 213 OnWindowUndocked();
209 Relayout(); 214 Relayout();
215 UpdateDockBounds();
210 is_dragged_from_dock_ = false; 216 is_dragged_from_dock_ = false;
211 } 217 }
212 218
213 void DockedWindowLayoutManager::FinishDragging() { 219 void DockedWindowLayoutManager::FinishDragging() {
214 DCHECK(dragged_window_); 220 DCHECK(dragged_window_);
215 if (is_dragged_window_docked_) 221 if (is_dragged_window_docked_)
216 OnWindowUndocked(); 222 OnWindowUndocked();
217 DCHECK (!is_dragged_window_docked_); 223 DCHECK (!is_dragged_window_docked_);
218 // Stop observing a window unless it is docked container's child in which 224 // Stop observing a window unless it is docked container's child in which
219 // case it needs to keep being observed after the drag completes. 225 // case it needs to keep being observed after the drag completes.
220 if (dragged_window_->parent() != dock_container_) 226 if (dragged_window_->parent() != dock_container_) {
221 dragged_window_->RemoveObserver(this); 227 dragged_window_->RemoveObserver(this);
228 if (last_active_window_ == dragged_window_)
229 last_active_window_ = NULL;
230 }
222 dragged_window_ = NULL; 231 dragged_window_ = NULL;
232 dragged_bounds_ = gfx::Rect();
223 Relayout(); 233 Relayout();
224 UpdateDockBounds(); 234 UpdateDockBounds();
225 } 235 }
226 236
227 void DockedWindowLayoutManager::SetLauncher(ash::Launcher* launcher) { 237 void DockedWindowLayoutManager::SetLauncher(ash::Launcher* launcher) {
228 DCHECK(!launcher_); 238 DCHECK(!launcher_);
229 DCHECK(!shelf_layout_manager_); 239 DCHECK(!shelf_layout_manager_);
230 launcher_ = launcher; 240 launcher_ = launcher;
231 if (launcher_->shelf_widget()) { 241 if (launcher_->shelf_widget()) {
232 shelf_layout_manager_ = ash::internal::ShelfLayoutManager::ForLauncher( 242 shelf_layout_manager_ = ash::internal::ShelfLayoutManager::ForLauncher(
233 launcher_->shelf_widget()->GetNativeWindow()); 243 launcher_->shelf_widget()->GetNativeWindow());
234 WillChangeVisibilityState(shelf_layout_manager_->visibility_state()); 244 WillChangeVisibilityState(shelf_layout_manager_->visibility_state());
235 shelf_layout_manager_->AddObserver(this); 245 shelf_layout_manager_->AddObserver(this);
236 } 246 }
237 } 247 }
238 248
239 DockedAlignment DockedWindowLayoutManager::GetAlignmentOfWindow( 249 DockedAlignment DockedWindowLayoutManager::GetAlignmentOfWindow(
240 const aura::Window* window) const { 250 const aura::Window* window) const {
241 const gfx::Rect& bounds(window->GetBoundsInScreen()); 251 const gfx::Rect& bounds(window->GetBoundsInScreen());
242 const gfx::Rect docked_bounds = dock_container_->GetBoundsInScreen();
243 252
244 // Do not allow docking if a window is vertically maximized (as is the case 253 // Test overlap with an existing docked area first.
245 // when it is snapped). 254 if (docked_bounds_.Intersects(bounds) &&
246 const gfx::Rect work_area = 255 alignment_ != DOCKED_ALIGNMENT_NONE) {
247 Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area(); 256 // A window is being added to other docked windows (on the same side).
248 if (bounds.y() == work_area.y() && bounds.height() == work_area.height()) 257 return alignment_;
249 return DOCKED_ALIGNMENT_NONE; 258 }
250 259
251 // Do not allow docking on the same side as launcher shelf. 260 const gfx::Rect container_bounds = dock_container_->GetBoundsInScreen();
252 ShelfAlignment shelf_alignment = SHELF_ALIGNMENT_BOTTOM; 261 if (bounds.x() <= container_bounds.x() &&
253 if (launcher_) 262 bounds.right() > container_bounds.x()) {
254 shelf_alignment = launcher_->alignment();
255
256 if (bounds.x() == docked_bounds.x() &&
257 shelf_alignment != SHELF_ALIGNMENT_LEFT) {
258 return DOCKED_ALIGNMENT_LEFT; 263 return DOCKED_ALIGNMENT_LEFT;
259 } 264 } else if (bounds.x() < container_bounds.right() &&
260 if (bounds.right() == docked_bounds.right() && 265 bounds.right() >= container_bounds.right()) {
261 shelf_alignment != SHELF_ALIGNMENT_RIGHT) {
262 return DOCKED_ALIGNMENT_RIGHT; 266 return DOCKED_ALIGNMENT_RIGHT;
263 } 267 }
264 return DOCKED_ALIGNMENT_NONE; 268 return DOCKED_ALIGNMENT_NONE;
265 } 269 }
266 270
267 DockedAlignment DockedWindowLayoutManager::CalculateAlignment() const { 271 DockedAlignment DockedWindowLayoutManager::CalculateAlignment() const {
268 // Find a child that is not being dragged and is not a popup. 272 // Find a child that is not being dragged and is not a popup.
269 // If such exists the current alignment is returned - even if some of the 273 // If such exists the current alignment is returned - even if some of the
270 // children are hidden or minimized (so they can be restored without losing 274 // children are hidden or minimized (so they can be restored without losing
271 // the docked state). 275 // the docked state).
272 for (size_t i = 0; i < dock_container_->children().size(); ++i) { 276 for (size_t i = 0; i < dock_container_->children().size(); ++i) {
273 aura::Window* window(dock_container_->children()[i]); 277 aura::Window* window(dock_container_->children()[i]);
274 if (window != dragged_window_ && 278 if (window != dragged_window_ &&
275 window->type() != aura::client::WINDOW_TYPE_POPUP) { 279 window->type() != aura::client::WINDOW_TYPE_POPUP) {
276 return alignment_; 280 return alignment_;
277 } 281 }
278 } 282 }
279 // No docked windows remain other than possibly the window being dragged. 283 // No docked windows remain other than possibly the window being dragged.
280 // Return |NONE| to indicate that windows may get docked on either side. 284 // Return |NONE| to indicate that windows may get docked on either side.
281 return DOCKED_ALIGNMENT_NONE; 285 return DOCKED_ALIGNMENT_NONE;
282 } 286 }
283 287
288 bool DockedWindowLayoutManager::CanDockWindow(aura::Window* window,
289 SnapType edge) {
290 if (!CommandLine::ForCurrentProcess()->HasSwitch(
291 switches::kAshEnableDockedWindows)) {
292 return false;
293 }
294 // Cannot dock on the other size from an existing dock.
295 const DockedAlignment alignment = CalculateAlignment();
296 if ((edge == SNAP_LEFT && alignment == DOCKED_ALIGNMENT_RIGHT) ||
297 (edge == SNAP_RIGHT && alignment == DOCKED_ALIGNMENT_LEFT)) {
298 return false;
299 }
300
301 // Do not allow docking on the same side as launcher shelf.
302 ShelfAlignment shelf_alignment = SHELF_ALIGNMENT_BOTTOM;
303 if (launcher_)
304 shelf_alignment = launcher_->alignment();
305 if ((edge == SNAP_LEFT && shelf_alignment == SHELF_ALIGNMENT_LEFT) ||
306 (edge == SNAP_RIGHT && shelf_alignment == SHELF_ALIGNMENT_RIGHT)) {
307 return false;
308 }
309 return true;
310 }
311
284 //////////////////////////////////////////////////////////////////////////////// 312 ////////////////////////////////////////////////////////////////////////////////
285 // DockLayoutManager, aura::LayoutManager implementation: 313 // DockLayoutManager, aura::LayoutManager implementation:
286 void DockedWindowLayoutManager::OnWindowResized() { 314 void DockedWindowLayoutManager::OnWindowResized() {
287 Relayout(); 315 Relayout();
288 // When screen resizes update the insets even when dock width or alignment 316 // When screen resizes update the insets even when dock width or alignment
289 // does not change. 317 // does not change.
290 UpdateDockBounds(); 318 UpdateDockBounds();
291 } 319 }
292 320
293 void DockedWindowLayoutManager::OnWindowAddedToLayout(aura::Window* child) { 321 void DockedWindowLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 std::sort(visible_windows.begin(), 585 std::sort(visible_windows.begin(),
558 visible_windows.end(), 586 visible_windows.end(),
559 CompareWindowPos(is_dragged_from_dock_ ? dragged_window_ : NULL, 587 CompareWindowPos(is_dragged_from_dock_ ? dragged_window_ : NULL,
560 delta)); 588 delta));
561 is_dragged_from_dock_ = true; 589 is_dragged_from_dock_ = true;
562 for (aura::Window::Windows::const_iterator iter = visible_windows.begin(); 590 for (aura::Window::Windows::const_iterator iter = visible_windows.begin();
563 iter != visible_windows.end(); ++iter) { 591 iter != visible_windows.end(); ++iter) {
564 aura::Window* window = *iter; 592 aura::Window* window = *iter;
565 gfx::Rect bounds = window->GetBoundsInScreen(); 593 gfx::Rect bounds = window->GetBoundsInScreen();
566 594
595 DockedAlignment alignment = alignment_;
596 if (alignment == DOCKED_ALIGNMENT_NONE && window == dragged_window_) {
597 alignment = GetAlignmentOfWindow(window);
598 if (alignment == DOCKED_ALIGNMENT_NONE)
599 bounds.set_size(gfx::Size());
600 }
601
602 // Restrict width.
603 if (bounds.width() > kMaxDockWidth)
604 bounds.set_width(kMaxDockWidth);
605
567 // Fan out windows evenly distributing the overlap or remaining free space. 606 // Fan out windows evenly distributing the overlap or remaining free space.
568 bounds.set_y(std::max(work_area.y(), 607 bounds.set_y(std::max(work_area.y(),
569 std::min(work_area.bottom() - bounds.height(), 608 std::min(work_area.bottom() - bounds.height(),
570 static_cast<int>(y_pos + 0.5)))); 609 static_cast<int>(y_pos + 0.5))));
571 y_pos += bounds.height() + delta; 610 y_pos += bounds.height() + delta;
572 611
573 // All docked windows other than the one currently dragged remain stuck 612 // All docked windows other than the one currently dragged remain stuck
574 // to the screen edge. 613 // to the screen edge.
575 switch (alignment_) { 614 switch (alignment) {
576 case DOCKED_ALIGNMENT_LEFT: 615 case DOCKED_ALIGNMENT_LEFT:
577 bounds.set_x(dock_bounds.x()); 616 bounds.set_x(dock_bounds.x());
578 break; 617 break;
579 case DOCKED_ALIGNMENT_RIGHT: 618 case DOCKED_ALIGNMENT_RIGHT:
580 bounds.set_x(dock_bounds.right() - bounds.width()); 619 bounds.set_x(dock_bounds.right() - bounds.width());
581 break; 620 break;
582 case DOCKED_ALIGNMENT_NONE: 621 case DOCKED_ALIGNMENT_NONE:
583 break; 622 break;
584 } 623 }
585 if (window == dragged_window_) { 624 if (window == dragged_window_) {
586 dragged_bounds_ = bounds; 625 dragged_bounds_ = bounds;
587 continue; 626 continue;
588 } 627 }
628 // If the following asserts it is probably because not all the children
629 // have been removed when dock was closed.
589 DCHECK_NE(alignment_, DOCKED_ALIGNMENT_NONE); 630 DCHECK_NE(alignment_, DOCKED_ALIGNMENT_NONE);
590 // Keep the dock at least kMinDockWidth when all windows in it overhang. 631 // Keep the dock at least kMinDockWidth when all windows in it overhang.
591 docked_width_ = std::min(kMaxDockWidth, 632 docked_width_ = std::min(kMaxDockWidth,
592 std::max(docked_width_, 633 std::max(docked_width_,
593 bounds.width() > kMaxDockWidth ? 634 bounds.width() > kMaxDockWidth ?
594 kMinDockWidth : bounds.width())); 635 kMinDockWidth : bounds.width()));
595 bounds = ScreenAsh::ConvertRectFromScreen(dock_container_, bounds); 636 bounds = ScreenAsh::ConvertRectFromScreen(dock_container_, bounds);
596 SetChildBoundsDirect(window, bounds); 637 SetChildBoundsDirect(window, bounds);
597 } 638 }
598 UpdateStacking(active_window); 639 UpdateStacking(active_window);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 727
687 void DockedWindowLayoutManager::OnKeyboardBoundsChanging( 728 void DockedWindowLayoutManager::OnKeyboardBoundsChanging(
688 const gfx::Rect& keyboard_bounds) { 729 const gfx::Rect& keyboard_bounds) {
689 // This bounds change will have caused a change to the Shelf which does not 730 // This bounds change will have caused a change to the Shelf which does not
690 // propagate automatically to this class, so manually recalculate bounds. 731 // propagate automatically to this class, so manually recalculate bounds.
691 UpdateDockBounds(); 732 UpdateDockBounds();
692 } 733 }
693 734
694 } // namespace internal 735 } // namespace internal
695 } // namespace ash 736 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/dock/docked_window_layout_manager.h ('k') | ash/wm/dock/docked_window_layout_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698