diff options
Diffstat (limited to 'chromium/ash/wm')
28 files changed, 472 insertions, 911 deletions
diff --git a/chromium/ash/wm/boot_splash_screen_chromeos.cc b/chromium/ash/wm/boot_splash_screen.cc index 00743409ae5..202ebe28eeb 100644 --- a/chromium/ash/wm/boot_splash_screen_chromeos.cc +++ b/chromium/ash/wm/boot_splash_screen.cc @@ -1,12 +1,11 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/wm/boot_splash_screen_chromeos.h" +#include "ash/wm/boot_splash_screen.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/aura/root_window.h" -#include "ui/base/x/x11_util.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_type.h" #include "ui/compositor/scoped_layer_animation_settings.h" @@ -34,9 +33,9 @@ class BootSplashScreen::CopyHostContentLayerDelegate // TODO(derat): Instead of copying the data, use GLX_EXT_texture_from_pixmap // to create a zero-copy texture (when possible): // https://codereview.chromium.org/10543125 - ui::CopyAreaToCanvas(root_window_->GetAcceleratedWidget(), + root_window_->CopyAreaToSkCanvas( gfx::Rect(root_window_->GetHostOrigin(), root_window_->GetHostSize()), - gfx::Point(), canvas); + gfx::Point(), canvas->sk_canvas()); } virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {} diff --git a/chromium/ash/wm/boot_splash_screen_chromeos.h b/chromium/ash/wm/boot_splash_screen.h index e844275ad5f..f56f49fe195 100644 --- a/chromium/ash/wm/boot_splash_screen_chromeos.h +++ b/chromium/ash/wm/boot_splash_screen.h @@ -1,9 +1,9 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_WM_BOOT_SPLASH_SCREEN_CHROMEOS_H_ -#define ASH_WM_BOOT_SPLASH_SCREEN_CHROMEOS_H_ +#ifndef ASH_WM_BOOT_SPLASH_SCREEN_H_ +#define ASH_WM_BOOT_SPLASH_SCREEN_H_ #include <string> @@ -50,4 +50,4 @@ class BootSplashScreen { } // namespace internal } // namespace ash -#endif // ASH_WM_BOOT_SPLASH_SCREEN_CHROMEOS_H_ +#endif // ASH_WM_BOOT_SPLASH_SCREEN_H_ diff --git a/chromium/ash/wm/dock/docked_window_layout_manager.cc b/chromium/ash/wm/dock/docked_window_layout_manager.cc index 1dacf5e9fbd..d73a0ccac7d 100644 --- a/chromium/ash/wm/dock/docked_window_layout_manager.cc +++ b/chromium/ash/wm/dock/docked_window_layout_manager.cc @@ -84,58 +84,10 @@ bool IsUsedByLayout(aura::Window* window) { window->type() != aura::client::WINDOW_TYPE_POPUP); } -// A functor used to sort the windows in order of their center Y position. -// |delta| is a pre-calculated distance from the bottom of one window to the top -// of the next. Its value can be positive (gap) or negative (overlap). -// Half of |delta| is used as a transition point at which windows could ideally -// swap positions. -struct CompareWindowPos { - CompareWindowPos(aura::Window* dragged_window, float delta) - : dragged_window_(dragged_window), - delta_(delta / 2) {} - - bool operator()(const aura::Window* win1, const aura::Window* win2) { - const gfx::Rect win1_bounds = win1->GetBoundsInScreen(); - const gfx::Rect win2_bounds = win2->GetBoundsInScreen(); - // If one of the windows is the |dragged_window_| attempt to make an - // earlier swap between the windows than just based on their centers. - // This is possible if the dragged window is at least as tall as the other - // window. - if (win1 == dragged_window_) - return compare_two_windows(win1_bounds, win2_bounds); - if (win2 == dragged_window_) - return !compare_two_windows(win2_bounds, win1_bounds); - // Otherwise just compare the centers. - return win1_bounds.CenterPoint().y() < win2_bounds.CenterPoint().y(); - } - - // Based on center point tries to deduce where the drag is coming from. - // When dragging from below up the transition point is lower. - // When dragging from above down the transition point is higher. - bool compare_bounds(const gfx::Rect dragged, const gfx::Rect other) { - if (dragged.CenterPoint().y() < other.CenterPoint().y()) - return dragged.CenterPoint().y() < other.y() - delta_; - return dragged.CenterPoint().y() < other.bottom() + delta_; - } - - // Performs comparison both ways and selects stable result. - bool compare_two_windows(const gfx::Rect bounds1, const gfx::Rect bounds2) { - // Try comparing windows in both possible orders and see if the comparison - // is stable. - bool result1 = compare_bounds(bounds1, bounds2); - bool result2 = compare_bounds(bounds2, bounds1); - if (result1 != result2) - return result1; - - // Otherwise it is not possible to be sure that the windows will not bounce. - // In this case just compare the centers. - return bounds1.CenterPoint().y() < bounds2.CenterPoint().y(); - } - - private: - aura::Window* dragged_window_; - float delta_; -}; +bool CompareWindowPos(const aura::Window* win1, const aura::Window* win2) { + return win1->GetTargetBounds().CenterPoint().y() < + win2->GetTargetBounds().CenterPoint().y(); +} } // namespace @@ -146,8 +98,6 @@ DockedWindowLayoutManager::DockedWindowLayoutManager( : dock_container_(dock_container), in_layout_(false), dragged_window_(NULL), - is_dragged_window_docked_(false), - is_dragged_from_dock_(false), launcher_(NULL), shelf_layout_manager_(NULL), shelf_hidden_(false), @@ -189,79 +139,106 @@ void DockedWindowLayoutManager::RemoveObserver( } void DockedWindowLayoutManager::StartDragging(aura::Window* window) { + if (window->parent() != dock_container_) + return; DCHECK(!dragged_window_); dragged_window_ = window; - // Start observing a window unless it is docked container's child in which - // case it is already observed. - if (dragged_window_->parent() != dock_container_) - dragged_window_->AddObserver(this); - is_dragged_from_dock_ = window->parent() == dock_container_; - DCHECK(!is_dragged_window_docked_); -} - -void DockedWindowLayoutManager::DockDraggedWindow(aura::Window* window) { - OnWindowDocked(window); Relayout(); } -void DockedWindowLayoutManager::UndockDraggedWindow() { - OnWindowUndocked(); - Relayout(); - is_dragged_from_dock_ = false; -} - void DockedWindowLayoutManager::FinishDragging() { - DCHECK(dragged_window_); - if (is_dragged_window_docked_) - OnWindowUndocked(); - DCHECK (!is_dragged_window_docked_); - // Stop observing a window unless it is docked container's child in which - // case it needs to keep being observed after the drag completes. - if (dragged_window_->parent() != dock_container_) - dragged_window_->RemoveObserver(this); - dragged_window_ = NULL; + if (!dragged_window_) + return; + + // If this is the first window getting docked - update alignment. + if (alignment_ == DOCKED_ALIGNMENT_NONE) { + alignment_ = AlignmentOfWindow(dragged_window_); + } else { + // There were some docked windows before. Check if the |dragged_window_| + // was the only one remaining and if so possibly switch alignment to + // opposite side. Ignore popups. + bool found_docked_window = false; + for (size_t i = 0; i < dock_container_->children().size(); ++i) { + aura::Window* window(dock_container_->children()[i]); + if (window != dragged_window_ && + window->type() != aura::client::WINDOW_TYPE_POPUP) { + found_docked_window = true; + break; + } + } + if (!found_docked_window) + alignment_ = AlignmentOfWindow(dragged_window_); + } + + // We no longer need to observe |dragged_window_| unless it is added back; + if (dragged_window_) { + if (dragged_window_->parent() != dock_container_) + dragged_window_->RemoveObserver(this); + dragged_window_ = NULL; + } + Relayout(); UpdateDockBounds(); } -void DockedWindowLayoutManager::SetLauncher(ash::Launcher* launcher) { - DCHECK(!launcher_); - DCHECK(!shelf_layout_manager_); - launcher_ = launcher; - if (launcher_->shelf_widget()) { - shelf_layout_manager_ = ash::internal::ShelfLayoutManager::ForLauncher( - launcher_->shelf_widget()->GetNativeWindow()); - WillChangeVisibilityState(shelf_layout_manager_->visibility_state()); - shelf_layout_manager_->AddObserver(this); +// static +bool DockedWindowLayoutManager::ShouldWindowDock(aura::Window* window, + const gfx::Point& location) { + DockedWindowLayoutManager* layout_manager = GetDockLayoutManager(window, + location); + const DockedAlignment alignment = layout_manager->CalculateAlignment(); + const gfx::Rect& bounds(window->GetBoundsInScreen()); + const gfx::Rect docked_bounds = (alignment == DOCKED_ALIGNMENT_NONE) ? + layout_manager->dock_container_->GetBoundsInScreen() : + layout_manager->docked_bounds_; + DockedAlignment dock_edge = DOCKED_ALIGNMENT_NONE; + if (alignment == DOCKED_ALIGNMENT_NONE) { + // Check if the window is touching the edge - it may need to get docked. + dock_edge = layout_manager->AlignmentOfWindow(window); + } else if ((docked_bounds.Intersects(bounds) && + docked_bounds.Contains(location)) || + alignment == layout_manager->AlignmentOfWindow(window)) { + // A window is being added to other docked windows (on the same side). + // Both bounds and pointer location are checked because some drags involve + // sticky edges and so the |location| may be outside of the |bounds|. + // It is also possible that all the docked windows are minimized or hidden + // in which case the dragged window needs to be exactly touching the same + // edge that those docked windows were aligned before they got minimized. + dock_edge = alignment; } -} -DockedAlignment DockedWindowLayoutManager::GetAlignmentOfWindow( - const aura::Window* window) const { - const gfx::Rect& bounds(window->GetBoundsInScreen()); - const gfx::Rect docked_bounds = dock_container_->GetBoundsInScreen(); + // Do not allow docking on the same side as launcher shelf. + if (layout_manager->launcher_ && layout_manager->launcher_->shelf_widget()) { + ShelfAlignment shelf_alignment = + layout_manager->launcher_->shelf_widget()->GetAlignment(); + if ((shelf_alignment == SHELF_ALIGNMENT_LEFT && + dock_edge == DOCKED_ALIGNMENT_LEFT) || + (shelf_alignment == SHELF_ALIGNMENT_RIGHT && + dock_edge == DOCKED_ALIGNMENT_RIGHT)) { + dock_edge = DOCKED_ALIGNMENT_NONE; + } + } // Do not allow docking if a window is vertically maximized (as is the case // when it is snapped). const gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area(); + Shell::GetScreen()->GetDisplayNearestWindow(window).work_area(); if (bounds.y() == work_area.y() && bounds.height() == work_area.height()) - return DOCKED_ALIGNMENT_NONE; + dock_edge = DOCKED_ALIGNMENT_NONE; - // Do not allow docking on the same side as launcher shelf. - ShelfAlignment shelf_alignment = SHELF_ALIGNMENT_BOTTOM; - if (launcher_) - shelf_alignment = launcher_->alignment(); + return dock_edge != DOCKED_ALIGNMENT_NONE; +} - if (bounds.x() == docked_bounds.x() && - shelf_alignment != SHELF_ALIGNMENT_LEFT) { - return DOCKED_ALIGNMENT_LEFT; - } - if (bounds.right() == docked_bounds.right() && - shelf_alignment != SHELF_ALIGNMENT_RIGHT) { - return DOCKED_ALIGNMENT_RIGHT; +void DockedWindowLayoutManager::SetLauncher(ash::Launcher* launcher) { + DCHECK(!launcher_); + DCHECK(!shelf_layout_manager_); + launcher_ = launcher; + if (launcher_->shelf_widget()) { + shelf_layout_manager_ = ash::internal::ShelfLayoutManager::ForLauncher( + launcher_->shelf_widget()->GetNativeWindow()); + WillChangeVisibilityState(shelf_layout_manager_->visibility_state()); + shelf_layout_manager_->AddObserver(this); } - return DOCKED_ALIGNMENT_NONE; } DockedAlignment DockedWindowLayoutManager::CalculateAlignment() const { @@ -285,24 +262,22 @@ DockedAlignment DockedWindowLayoutManager::CalculateAlignment() const { // DockLayoutManager, aura::LayoutManager implementation: void DockedWindowLayoutManager::OnWindowResized() { Relayout(); - // When screen resizes update the insets even when dock width or alignment - // does not change. + // When screen resizes we need to update the insets even when dock width or + // alignment does not change. UpdateDockBounds(); } void DockedWindowLayoutManager::OnWindowAddedToLayout(aura::Window* child) { if (child->type() == aura::client::WINDOW_TYPE_POPUP) return; - // Dragged windows are already observed by StartDragging and do not change - // docked alignment during the drag. - if (child == dragged_window_) - return; + // If this is the first window getting docked - update alignment. - if (alignment_ == DOCKED_ALIGNMENT_NONE) { - alignment_ = GetAlignmentOfWindow(child); - DCHECK(alignment_ != DOCKED_ALIGNMENT_NONE); - } - child->AddObserver(this); + if (alignment_ == DOCKED_ALIGNMENT_NONE) + alignment_ = AlignmentOfWindow(child); + // We need to observe a child unless it is a |dragged_window_| that just got + // added back in which case we are already observing it. + if (child != dragged_window_) + child->AddObserver(this); Relayout(); UpdateDockBounds(); } @@ -310,20 +285,36 @@ void DockedWindowLayoutManager::OnWindowAddedToLayout(aura::Window* child) { void DockedWindowLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { if (child->type() == aura::client::WINDOW_TYPE_POPUP) return; - // Dragged windows are stopped being observed by FinishDragging and do not - // change alignment during the drag. They also cannot be set to be the - // |last_active_window_|. - if (child == dragged_window_) - return; - // If this is the last window, set alignment and maximize the workspace. - if (!IsAnyWindowDocked()) { - alignment_ = DOCKED_ALIGNMENT_NONE; - docked_width_ = 0; + + // Try to find a child that is not a popup and is not being dragged. + bool found_docked_window = false; + for (size_t i = 0; i < dock_container_->children().size(); ++i) { + aura::Window* window(dock_container_->children()[i]); + if (window != dragged_window_ && + window->type() != aura::client::WINDOW_TYPE_POPUP) { + found_docked_window = true; + break; + } } + if (!found_docked_window) + alignment_ = DOCKED_ALIGNMENT_NONE; + + // Keep track of former children if they are dragged as they can be reparented + // temporarily just for the drag. + if (child != dragged_window_) + child->RemoveObserver(this); + if (last_active_window_ == child) last_active_window_ = NULL; - child->RemoveObserver(this); + + // Close the dock and expand workspace work area. Relayout(); + + // When a panel is removed from this layout manager it may still be dragged. + // Delay updating dock and workspace bounds until the drag is completed. This + // preserves the docked area width until the panel drag is finished. + if (child->type() != aura::client::WINDOW_TYPE_PANEL) + UpdateDockBounds(); } void DockedWindowLayoutManager::OnChildWindowVisibilityChanged( @@ -340,8 +331,11 @@ void DockedWindowLayoutManager::OnChildWindowVisibilityChanged( void DockedWindowLayoutManager::SetChildBounds( aura::Window* child, const gfx::Rect& requested_bounds) { - // Whenever one of our windows is moved or resized enforce layout. + // Whenever one of our windows is moved or resized we need to enforce layout. SetChildBoundsDirect(child, requested_bounds); + if (child->type() == aura::client::WINDOW_TYPE_POPUP) + return; + Relayout(); } //////////////////////////////////////////////////////////////////////////////// @@ -394,18 +388,13 @@ void DockedWindowLayoutManager::OnWindowBoundsChanged( aura::Window* window, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds) { - // Only relayout if the dragged window would get docked. - if (window == dragged_window_ && is_dragged_window_docked_) + if (window == dragged_window_) Relayout(); } void DockedWindowLayoutManager::OnWindowDestroying(aura::Window* window) { if (dragged_window_ == window) - FinishDragging(); - DCHECK(!dragged_window_); - DCHECK (!is_dragged_window_docked_); - if (window == last_active_window_) - last_active_window_ = NULL; + dragged_window_ = NULL; } @@ -437,7 +426,7 @@ void DockedWindowLayoutManager::WillChangeVisibilityState( // to allow the full-screen application to use the full screen. // TODO(varkha): ShelfLayoutManager::UpdateVisibilityState sets state to - // SHELF_AUTO_HIDE when in immersive mode. Distinguish this from + // SHELF_AUTO_HIDE when in immersive mode. We need to distinguish this from // when shelf enters auto-hide state based on mouse hover when auto-hide // setting is enabled and hide all windows (immersive mode should hide docked // windows). @@ -473,43 +462,30 @@ void DockedWindowLayoutManager::RestoreWindow(aura::Window* window) { window->Show(); } -void DockedWindowLayoutManager::OnWindowDocked(aura::Window* window) { - DCHECK(!is_dragged_window_docked_); - is_dragged_window_docked_ = true; - - // If there are no other docked windows update alignment. - if (!IsAnyWindowDocked()) - alignment_ = DOCKED_ALIGNMENT_NONE; -} - -void DockedWindowLayoutManager::OnWindowUndocked() { - // If this is the first window getting docked - update alignment. - if (!IsAnyWindowDocked()) - alignment_ = GetAlignmentOfWindow(dragged_window_); - - DCHECK (is_dragged_window_docked_); - is_dragged_window_docked_ = false; -} - -bool DockedWindowLayoutManager::IsAnyWindowDocked() { - return CalculateAlignment() != DOCKED_ALIGNMENT_NONE; +DockedAlignment DockedWindowLayoutManager::AlignmentOfWindow( + const aura::Window* window) const { + const gfx::Rect& bounds(window->GetBoundsInScreen()); + const gfx::Rect docked_bounds = dock_container_->GetBoundsInScreen(); + if (bounds.x() == docked_bounds.x()) + return DOCKED_ALIGNMENT_LEFT; + if (bounds.right() == docked_bounds.right()) + return DOCKED_ALIGNMENT_RIGHT; + return DOCKED_ALIGNMENT_NONE; } void DockedWindowLayoutManager::Relayout() { - if (in_layout_) - return; - if (alignment_ == DOCKED_ALIGNMENT_NONE && !is_dragged_window_docked_) + if (in_layout_ || alignment_ == DOCKED_ALIGNMENT_NONE) return; base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true); - gfx::Rect dock_bounds = dock_container_->GetBoundsInScreen(); + gfx::Rect dock_bounds = dock_container_->bounds(); aura::Window* active_window = NULL; aura::Window::Windows visible_windows; docked_width_ = 0; for (size_t i = 0; i < dock_container_->children().size(); ++i) { aura::Window* window(dock_container_->children()[i]); - if (!IsUsedByLayout(window) || window == dragged_window_) + if (!IsUsedByLayout(window)) continue; // If the shelf is currently hidden (full-screen mode), hide window until @@ -529,14 +505,14 @@ void DockedWindowLayoutManager::Relayout() { visible_windows.push_back(window); } - // Consider docked dragged_window_ when fanning out other child windows. - if (is_dragged_window_docked_) { + // Consider windows that were formerly children of the |dock_container_| + // when fanning out other child windows. + if (dragged_window_ && dragged_window_->parent() != dock_container_) visible_windows.push_back(dragged_window_); - DCHECK(!active_window); - active_window = dragged_window_; - } - // Calculate free space or overlap. + // Sort windows by their center positions and fan out overlapping + // windows. + std::sort(visible_windows.begin(), visible_windows.end(), CompareWindowPos); gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow( dock_container_); const gfx::Rect work_area = display.work_area(); @@ -549,19 +525,15 @@ void DockedWindowLayoutManager::Relayout() { const float delta = (float)available_room / ((available_room > 0 || num_windows <= 1) ? num_windows + 1 : num_windows - 1); - float y_pos = work_area.y() + ((available_room > 0) ? delta : 0); + float y_pos = (available_room > 0) ? delta : 0; - // Sort windows by their center positions and fan out overlapping - // windows. - std::sort(visible_windows.begin(), - visible_windows.end(), - CompareWindowPos(is_dragged_from_dock_ ? dragged_window_ : NULL, - delta)); - is_dragged_from_dock_ = true; for (aura::Window::Windows::const_iterator iter = visible_windows.begin(); iter != visible_windows.end(); ++iter) { aura::Window* window = *iter; - gfx::Rect bounds = window->GetBoundsInScreen(); + gfx::Rect bounds = window->GetTargetBounds(); + // Do not force position of a single window. + if (num_windows == 1) + y_pos = bounds.y(); // Fan out windows evenly distributing the overlap or remaining free space. bounds.set_y(std::max(work_area.y(), @@ -571,27 +543,24 @@ void DockedWindowLayoutManager::Relayout() { // All docked windows other than the one currently dragged remain stuck // to the screen edge. + if (window == dragged_window_) + continue; switch (alignment_) { case DOCKED_ALIGNMENT_LEFT: - bounds.set_x(dock_bounds.x()); + bounds.set_x(0); break; case DOCKED_ALIGNMENT_RIGHT: bounds.set_x(dock_bounds.right() - bounds.width()); break; case DOCKED_ALIGNMENT_NONE: + NOTREACHED() << "Relayout called when dock alignment is 'NONE'"; break; } - if (window == dragged_window_) { - dragged_bounds_ = bounds; - continue; - } - DCHECK_NE(alignment_, DOCKED_ALIGNMENT_NONE); // Keep the dock at least kMinDockWidth when all windows in it overhang. docked_width_ = std::min(kMaxDockWidth, std::max(docked_width_, bounds.width() > kMaxDockWidth ? kMinDockWidth : bounds.width())); - bounds = ScreenAsh::ConvertRectFromScreen(dock_container_, bounds); SetChildBoundsDirect(window, bounds); } UpdateStacking(active_window); @@ -600,7 +569,7 @@ void DockedWindowLayoutManager::Relayout() { void DockedWindowLayoutManager::UpdateDockBounds() { int dock_inset = docked_width_ + (docked_width_ > 0 ? kMinDockGap : 0); gfx::Rect bounds = gfx::Rect( - alignment_ == DOCKED_ALIGNMENT_RIGHT && dock_inset > 0 ? + alignment_ == DOCKED_ALIGNMENT_RIGHT ? dock_container_->bounds().right() - dock_inset: dock_container_->bounds().x(), dock_container_->bounds().y(), @@ -632,7 +601,7 @@ void DockedWindowLayoutManager::UpdateStacking(aura::Window* active_window) { active_window = last_active_window_; } - // Windows are stacked like a deck of cards: + // We want to to stack the windows like a deck of cards: // ,------. // |,------.| // |,------.| @@ -641,7 +610,7 @@ void DockedWindowLayoutManager::UpdateStacking(aura::Window* active_window) { // |`------'| // |`------'| // `------' - // Use the middle of each window to figure out how to stack the window. + // We use the middle of each window to figure out how to stack the window. // This allows us to update the stacking when a window is being dragged around // by the titlebar. std::map<int, aura::Window*> window_ordering; @@ -656,7 +625,7 @@ void DockedWindowLayoutManager::UpdateStacking(aura::Window* active_window) { } int active_center_y = active_window->bounds().CenterPoint().y(); - aura::Window* previous_window = NULL; + aura::Window* previous_window = background_widget_->GetNativeWindow(); for (std::map<int, aura::Window*>::const_iterator it = window_ordering.begin(); it != window_ordering.end() && it->first < active_center_y; ++it) { @@ -676,8 +645,9 @@ void DockedWindowLayoutManager::UpdateStacking(aura::Window* active_window) { if (active_window->parent() == dock_container_) dock_container_->StackChildAtTop(active_window); - if (active_window != dragged_window_) - last_active_window_ = active_window; + if (dragged_window_ && dragged_window_->parent() == dock_container_) + dock_container_->StackChildAtTop(dragged_window_); + last_active_window_ = active_window; } //////////////////////////////////////////////////////////////////////////////// diff --git a/chromium/ash/wm/dock/docked_window_layout_manager.h b/chromium/ash/wm/dock/docked_window_layout_manager.h index a3019aa7175..aa02b343423 100644 --- a/chromium/ash/wm/dock/docked_window_layout_manager.h +++ b/chromium/ash/wm/dock/docked_window_layout_manager.h @@ -50,9 +50,7 @@ class ShelfLayoutManager; // its layout manager to this instance, e.g.: // dock_container->SetLayoutManager( // new DockedWindowLayoutManager(dock_container)); -// -// TODO(varkha): extend BaseLayoutManager instead of LayoutManager to inherit -// common functionality. + class ASH_EXPORT DockedWindowLayoutManager : public aura::LayoutManager, public ash::ShellObserver, @@ -72,35 +70,26 @@ class ASH_EXPORT DockedWindowLayoutManager virtual void RemoveObserver(DockedWindowLayoutManagerObserver* observer); // Called by a DockedWindowResizer to update which window is being dragged. - // Starts observing the window unless it is a child. void StartDragging(aura::Window* window); - - // Called by a DockedWindowResizer when a dragged window is docked. - void DockDraggedWindow(aura::Window* window); - - // Called by a DockedWindowResizer when a dragged window is no longer docked. - void UndockDraggedWindow(); - - // Called by a DockedWindowResizer when a window is no longer being dragged. - // Stops observing the window unless it is a child. void FinishDragging(); + // Returns true if a window is touching the side of the screen except 2 cases: + // when some other windows are already docked on the other side or + // when launcher (shelf) is aligned on the same side. + static bool ShouldWindowDock(aura::Window* window, + const gfx::Point& location); + ash::Launcher* launcher() { return launcher_; } void SetLauncher(ash::Launcher* launcher); - // Calculates if a window is touching the screen edges and returns edge. - DockedAlignment GetAlignmentOfWindow(const aura::Window* window) const; - // Used to snap docked windows to the side of screen during drag. DockedAlignment CalculateAlignment() const; - aura::Window* dock_container() const { return dock_container_; } - // Returns current bounding rectangle of docked windows area. const gfx::Rect& docked_bounds() const { return docked_bounds_; } - // Returns last known coordinates of |dragged_window_| after Relayout. - const gfx::Rect dragged_bounds() const { return dragged_bounds_;} + // Currently dragged window should be able to dock on another screen + aura::Window* dragged_window() const { return dragged_window_;} // aura::LayoutManager: virtual void OnWindowResized() OVERRIDE; @@ -154,14 +143,8 @@ class ASH_EXPORT DockedWindowLayoutManager void MinimizeWindow(aura::Window* window); void RestoreWindow(aura::Window* window); - // Updates docked layout state when a window gets inside the dock. - void OnWindowDocked(aura::Window* window); - - // Updates docked layout state when a window gets outside the dock. - void OnWindowUndocked(); - - // Returns true if there are any windows currently docked. - bool IsAnyWindowDocked(); + // Calculates if a window is touching the screen edges and returns edge. + DockedAlignment AlignmentOfWindow(const aura::Window* window) const; // Called whenever the window layout might change. void Relayout(); @@ -182,21 +165,8 @@ class ASH_EXPORT DockedWindowLayoutManager aura::Window* dock_container_; // Protect against recursive calls to Relayout(). bool in_layout_; - - // A window that is being dragged (whether docked or not). - // Windows are tracked by docked layout manager only if they are docked; - // however we need to know if a window is being dragged in order to avoid - // positioning it or even considering it for layout. + // The docked window being dragged. aura::Window* dragged_window_; - - // True if the window being dragged is currently docked. - bool is_dragged_window_docked_; - - // Previously docked windows use a more relaxed dragging sorting algorithm - // that uses assumption that a window starts being dragged out of position - // that was previously established in Relayout. This allows easier reordering. - bool is_dragged_from_dock_; - // The launcher we are observing for launcher icon changes. Launcher* launcher_; // The shelf layout manager being observed for visibility changes. @@ -210,9 +180,6 @@ class ASH_EXPORT DockedWindowLayoutManager // Last bounds that were sent to observers. gfx::Rect docked_bounds_; - // Target bounds of a docked window being dragged. - gfx::Rect dragged_bounds_; - // Side of the screen that the dock is positioned at. DockedAlignment alignment_; diff --git a/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc b/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc index b2f6ffd9cf4..cf7b476f26a 100644 --- a/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc +++ b/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc @@ -5,7 +5,6 @@ #include "ash/wm/dock/docked_window_layout_manager.h" #include "ash/ash_switches.h" -#include "ash/display/display_controller.h" #include "ash/launcher/launcher.h" #include "ash/launcher/launcher_model.h" #include "ash/root_window_controller.h" @@ -28,7 +27,6 @@ #include "ui/aura/root_window.h" #include "ui/aura/window.h" #include "ui/base/hit_test.h" -#include "ui/gfx/screen.h" #include "ui/views/widget/widget.h" namespace ash { @@ -62,6 +60,11 @@ class DockedWindowLayoutManagerTest DOCKED_EDGE_RIGHT, }; + enum DockedState { + UNDOCKED, + DOCKED, + }; + aura::Window* CreateTestWindow(const gfx::Rect& bounds) { aura::Window* window = CreateTestWindowInShellWithDelegateAndType( NULL, @@ -133,10 +136,12 @@ class DockedWindowLayoutManagerTest // Docked windows are parented by dock container during drags. // All other windows that we are testing here have default container as a // parent. - int CorrectContainerIdDuringDrag() { + int CorrectContainerIdDuringDrag(DockedState is_docked) { if (window_type_ == aura::client::WINDOW_TYPE_PANEL) return internal::kShellWindowId_PanelContainer; - return internal::kShellWindowId_DockedContainer; + if (is_docked == DOCKED) + return internal::kShellWindowId_DockedContainer; + return internal::kShellWindowId_DefaultContainer; } // Test dragging the window vertically (to detach if it is a panel) and then @@ -181,7 +186,7 @@ class DockedWindowLayoutManagerTest // Drag enough to detach since our tests assume panels to be initially // detached. DragMove(0, dy); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); + EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id()); EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x()); EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y()); @@ -203,7 +208,7 @@ class DockedWindowLayoutManagerTest else if (edge == DOCKED_EDGE_RIGHT) dx += window->GetRootWindow()->bounds().right() - initial_bounds.right(); DragMove(dx, window_type_ == aura::client::WINDOW_TYPE_PANEL ? 0 : dy); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); + EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id()); // Release the mouse and the panel should be attached to the dock. DragEnd(); @@ -309,7 +314,7 @@ TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDragging) { scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 202))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 200); + DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100); scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 0, 220, 204))); DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w3.get(), 300); @@ -336,10 +341,9 @@ TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDragging) { EXPECT_LE(abs(overlap2 - overlap3), 1); EXPECT_EQ(0, overlap4); - // Drag w1 below the point where w1 and w2 would swap places. This point is - // half way between the tops of those two windows. Add 1 because w2 is taller. + // Drag w1 below w2. ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w1.get(), 0, 20)); - DragMove(0, (w2->bounds().y() - w1->bounds().y()) / 2 + 1); + DragMove(0, w2->bounds().y() - w1->bounds().y() + 20); // During the drag the windows get rearranged and the top and the bottom // should be clamped by the work area. @@ -360,73 +364,6 @@ TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDragging) { EXPECT_EQ(0, overlap4); } -// Adds three windows in bottom display and tests layout after a drag. -TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDraggingSecondScreen) { - if (!SupportsMultipleDisplays()) - return; - if (!SupportsHostWindowResize()) - return; - - // Create two screen vertical layout. - UpdateDisplay("100+100-600x600,100+700-600x600"); - // Layout the secondary display to the bottom of the primary. - DisplayLayout layout(DisplayLayout::BOTTOM, 0); - ASSERT_GT(Shell::GetScreen()->GetNumDisplays(), 1); - Shell::GetInstance()->display_controller()-> - SetLayoutForCurrentDisplays(layout); - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 600, 201, 201))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 600 + 20); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 600, 210, 202))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 600 + 200); - scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 600, 220, 204))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w3.get(), 600 + 300); - - // All windows should be attached and snapped to the right side of the screen. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(w2->GetRootWindow()->bounds().right(), - w2->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - EXPECT_EQ(w3->GetRootWindow()->bounds().right(), - w3->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w3->parent()->id()); - - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area(); - // Test that the top and bottom windows are clamped in work area and - // that the overlaps between the windows differ at most by a pixel. - int overlap1 = w1->GetBoundsInScreen().y() - work_area.y(); - int overlap2 = w1->GetBoundsInScreen().bottom() - w2->GetBoundsInScreen().y(); - int overlap3 = w2->GetBoundsInScreen().bottom() - w3->GetBoundsInScreen().y(); - int overlap4 = work_area.bottom() - w3->GetBoundsInScreen().bottom(); - EXPECT_EQ(0, overlap1); - EXPECT_LE(abs(overlap2 - overlap3), 1); - EXPECT_EQ(0, overlap4); - - // Drag w1 below the point where w1 and w2 would swap places. This point is - // half way between the tops of those two windows. Add 1 because w2 is taller. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w1.get(), 0, 20)); - DragMove(0, (w2->bounds().y() - w1->bounds().y()) / 2 + 1); - - // During the drag the windows get rearranged and the top and the bottom - // should be clamped by the work area. - EXPECT_EQ(work_area.y(), w2->GetBoundsInScreen().y()); - EXPECT_GT(w1->GetBoundsInScreen().y(), w2->GetBoundsInScreen().y()); - EXPECT_EQ(work_area.bottom(), w3->GetBoundsInScreen().bottom()); - DragEnd(); - - // Test the new windows order and that the overlaps differ at most by a pixel. - overlap1 = w2->GetBoundsInScreen().y() - work_area.y(); - overlap2 = w2->GetBoundsInScreen().bottom() - w1->GetBoundsInScreen().y(); - overlap3 = w1->GetBoundsInScreen().bottom() - w3->GetBoundsInScreen().y(); - overlap4 = work_area.bottom() - w3->GetBoundsInScreen().bottom(); - EXPECT_EQ(0, overlap1); - EXPECT_LE(abs(overlap2 - overlap3), 1); - EXPECT_EQ(0, overlap4); -} - // Tests run twice - on both panels and normal windows INSTANTIATE_TEST_CASE_P(NormalOrPanel, DockedWindowLayoutManagerTest, diff --git a/chromium/ash/wm/dock/docked_window_resizer.cc b/chromium/ash/wm/dock/docked_window_resizer.cc index 3e1ef29b0ad..beae1d13a18 100644 --- a/chromium/ash/wm/dock/docked_window_resizer.cc +++ b/chromium/ash/wm/dock/docked_window_resizer.cc @@ -16,9 +16,7 @@ #include "ash/wm/dock/docked_window_layout_manager.h" #include "ash/wm/property_util.h" #include "ash/wm/window_properties.h" -#include "ash/wm/workspace/magnetism_matcher.h" -#include "ash/wm/workspace/phantom_window_controller.h" -#include "ash/wm/workspace/workspace_window_resizer.h" +#include "ash/wm/workspace_controller.h" #include "base/command_line.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/env.h" @@ -31,18 +29,15 @@ #include "ui/views/widget/widget.h" namespace ash { -namespace internal { namespace { -DockedWindowLayoutManager* GetDockedLayoutManagerAtPoint( - const gfx::Point& point) { - aura::Window* dock_container = Shell::GetContainer( - wm::GetRootWindowAt(point), - kShellWindowId_DockedContainer); - return static_cast<DockedWindowLayoutManager*>( - dock_container->layout_manager()); -} +// Distance in pixels that the cursor must move past an edge for a window +// to move beyond that edge. +const int kStickyDistance = 64; + +// How far in pixels we have to drag to undock a window. +const int kSnapToDockDistance = 32; } // namespace @@ -94,78 +89,37 @@ void DockedWindowResizer::Drag(const gfx::Point& location, int event_flags) { destroyed_ = NULL; if (set_tracked_by_workspace) SetTrackedByWorkspace(GetTarget(), tracked_by_workspace); - - DockedWindowLayoutManager* new_dock_layout = - GetDockedLayoutManagerAtPoint(last_location_); - if (new_dock_layout != dock_layout_) { - // The window is being dragged to a new display. If the previous - // container is the current parent of the window it will be informed of - // the end of drag when the window is reparented, otherwise let the - // previous container know the drag is complete. If we told the - // window's parent that the drag was complete it would begin - // positioning the window. - if (is_docked_) - dock_layout_->UndockDraggedWindow(); - if (dock_layout_ != initial_dock_layout_) - dock_layout_->FinishDragging(); - is_docked_ = false; - dock_layout_ = new_dock_layout; - // The window's initial layout manager already knows that the drag is - // in progress for this window. - if (new_dock_layout != initial_dock_layout_) - new_dock_layout->StartDragging(GetTarget()); - } - - // Show snapping animation when a window touches a screen edge or when - // it is about to get docked. - DockedAlignment new_docked_alignment = GetDraggedWindowAlignment(); - if (new_docked_alignment != DOCKED_ALIGNMENT_NONE) { - if (!is_docked_) { - dock_layout_->DockDraggedWindow(GetTarget()); - is_docked_ = true; - } - UpdateSnapPhantomWindow(); - } else { - if (is_docked_) { - dock_layout_->UndockDraggedWindow(); - is_docked_ = false; - } - // Clear phantom window when a window gets undocked. - snap_phantom_window_controller_.reset(); - } } void DockedWindowResizer::CompleteDrag(int event_flags) { - snap_phantom_window_controller_.reset(); - // Temporarily clear kWindowTrackedByWorkspaceKey for panels so that they // don't get forced into the workspace that may be shrunken because of docked // windows. bool tracked_by_workspace = GetTrackedByWorkspace(GetTarget()); - bool set_tracked_by_workspace = was_docked_; + bool set_tracked_by_workspace = + (was_docked_ && GetTarget()->type() == aura::client::WINDOW_TYPE_PANEL); if (set_tracked_by_workspace) SetTrackedByWorkspace(GetTarget(), false); // The root window can change when dragging into a different screen. next_window_resizer_->CompleteDrag(event_flags); - FinishedDragging(); if (set_tracked_by_workspace) SetTrackedByWorkspace(GetTarget(), tracked_by_workspace); + FinishDragging(); } void DockedWindowResizer::RevertDrag() { - snap_phantom_window_controller_.reset(); - // Temporarily clear kWindowTrackedByWorkspaceKey for panels so that they // don't get forced into the workspace that may be shrunken because of docked // windows. bool tracked_by_workspace = GetTrackedByWorkspace(GetTarget()); - bool set_tracked_by_workspace = was_docked_; + bool set_tracked_by_workspace = + (was_docked_ && GetTarget()->type() == aura::client::WINDOW_TYPE_PANEL); if (set_tracked_by_workspace) SetTrackedByWorkspace(GetTarget(), false); next_window_resizer_->RevertDrag(); - FinishedDragging(); if (set_tracked_by_workspace) SetTrackedByWorkspace(GetTarget(), tracked_by_workspace); + FinishDragging(); } aura::Window* DockedWindowResizer::GetTarget() { @@ -181,57 +135,29 @@ DockedWindowResizer::DockedWindowResizer(WindowResizer* next_window_resizer, : details_(details), next_window_resizer_(next_window_resizer), dock_layout_(NULL), - initial_dock_layout_(NULL), did_move_or_resize_(false), was_docked_(false), - is_docked_(false), destroyed_(NULL) { DCHECK(details_.is_resizable); aura::Window* dock_container = Shell::GetContainer( details.window->GetRootWindow(), - kShellWindowId_DockedContainer); - dock_layout_ = static_cast<DockedWindowLayoutManager*>( + internal::kShellWindowId_DockedContainer); + DCHECK(dock_container->id() == internal::kShellWindowId_DockedContainer); + dock_layout_ = static_cast<internal::DockedWindowLayoutManager*>( dock_container->layout_manager()); - initial_dock_layout_ = dock_layout_; was_docked_ = details.window->parent() == dock_container; - is_docked_ = was_docked_; -} - -DockedAlignment DockedWindowResizer::GetDraggedWindowAlignment() { - aura::Window* window = GetTarget(); - DockedWindowLayoutManager* layout_manager = - GetDockedLayoutManagerAtPoint(last_location_); - const DockedAlignment alignment = layout_manager->CalculateAlignment(); - const gfx::Rect& bounds(window->GetBoundsInScreen()); - - // Check if the window is touching the edge - it may need to get docked. - if (alignment == DOCKED_ALIGNMENT_NONE) - return layout_manager->GetAlignmentOfWindow(window); - - // Both bounds and pointer location are checked because some drags involve - // stickiness at the workspace-to-dock boundary and so the |location| may be - // outside of the |bounds|. - // It is also possible that all the docked windows are minimized or hidden - // in which case the dragged window needs to be exactly touching the same - // edge that those docked windows were aligned before they got minimized. - // TODO(varkha): Consider eliminating sticky behavior on that boundary when - // a pointer enters docked area. - if ((layout_manager->docked_bounds().Intersects(bounds) && - layout_manager->docked_bounds().Contains(last_location_)) || - alignment == layout_manager->GetAlignmentOfWindow(window)) { - // A window is being added to other docked windows (on the same side). - return alignment; - } - return DOCKED_ALIGNMENT_NONE; } bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds, gfx::Point* offset) { aura::Window* dock_container = Shell::GetContainer( wm::GetRootWindowAt(last_location_), - kShellWindowId_DockedContainer); - DockedAlignment dock_alignment = - GetDockedLayoutManagerAtPoint(last_location_)->CalculateAlignment(); + internal::kShellWindowId_DockedContainer); + DCHECK(dock_container->id() == internal::kShellWindowId_DockedContainer); + internal::DockedWindowLayoutManager* dock_layout = + static_cast<internal::DockedWindowLayoutManager*>( + dock_container->layout_manager()); + internal::DockedAlignment dock_alignment = dock_layout->CalculateAlignment(); gfx::Rect dock_bounds = ScreenAsh::ConvertRectFromScreen( GetTarget()->parent(), dock_container->GetBoundsInScreen()); // Windows only snap magnetically when they are close to the edge of the @@ -239,33 +165,23 @@ bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds, // When a window being dragged is the last window that was previously // docked it is still allowed to magnetically snap to either side. bool can_snap = was_docked_ || - (GetDraggedWindowAlignment() != DOCKED_ALIGNMENT_NONE); + internal::DockedWindowLayoutManager::ShouldWindowDock(GetTarget(), + last_location_); if (!can_snap) return false; - // Distance in pixels that the cursor must move past an edge for a window - // to move beyond that edge. Same constant as in WorkspaceWindowResizer - // is used for consistency. - const int kStickyDistance = WorkspaceWindowResizer::kStickyDistancePixels; - - // Short-range magnetism when retaining docked state. Same constant as in - // MagnetismMatcher is used for consistency. - const int kSnapToDockDistance = MagnetismMatcher::kMagneticDistance; - - if (dock_alignment == DOCKED_ALIGNMENT_LEFT || - (dock_alignment == DOCKED_ALIGNMENT_NONE && was_docked_)) { + if (dock_alignment == internal::DOCKED_ALIGNMENT_LEFT || + (dock_alignment == internal::DOCKED_ALIGNMENT_NONE && was_docked_)) { const int distance = bounds.x() - dock_bounds.x(); - if (distance < (was_docked_ ? kSnapToDockDistance : 0) && - distance > -kStickyDistance) { + if (distance < kSnapToDockDistance && distance > -kStickyDistance) { offset->set_x(-distance); return true; } } - if (dock_alignment == DOCKED_ALIGNMENT_RIGHT || - (dock_alignment == DOCKED_ALIGNMENT_NONE && was_docked_)) { + if (dock_alignment == internal::DOCKED_ALIGNMENT_RIGHT || + (dock_alignment == internal::DOCKED_ALIGNMENT_NONE && was_docked_)) { const int distance = dock_bounds.right() - bounds.right(); - if (distance < (was_docked_ ? kSnapToDockDistance : 0) && - distance > -kStickyDistance) { + if (distance < kSnapToDockDistance && distance > -kStickyDistance) { offset->set_x(distance); return true; } @@ -275,54 +191,37 @@ bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds, void DockedWindowResizer::StartedDragging() { // Tell the dock layout manager that we are dragging this window. - // At this point we are not yet animating the window as it may not be - // inside the docked area. dock_layout_->StartDragging(GetTarget()); - // Reparent workspace windows during the drag to elevate them above workspace. - // Other windows for which the DockedWindowResizer is instantiated include - // panels and windows that are already docked. Those do not need reparenting. - if (GetTarget()->type() != aura::client::WINDOW_TYPE_PANEL && - GetTarget()->parent()->id() == kShellWindowId_DefaultContainer) { - // The window is going to be reparented - avoid completing the drag. - GetTarget()->SetProperty(kContinueDragAfterReparent, true); - - // Reparent the window into the docked windows container in order to get it - // on top of other docked windows. - aura::Window* docked_container = Shell::GetContainer( - GetTarget()->GetRootWindow(), - kShellWindowId_DockedContainer); - docked_container->AddChild(GetTarget()); - } - if (is_docked_) - dock_layout_->DockDraggedWindow(GetTarget()); } -void DockedWindowResizer::FinishedDragging() { +void DockedWindowResizer::FinishDragging() { if (!did_move_or_resize_) return; aura::Window* window = GetTarget(); bool should_dock = was_docked_; - const bool attached_panel = - window->type() == aura::client::WINDOW_TYPE_PANEL && - window->GetProperty(kPanelAttachedKey); - // If a window was previously docked then keep it docked if it is resized and - // still aligned at the screen edge. - if ((was_docked_ || - ((details_.bounds_change & WindowResizer::kBoundsChange_Repositions) && - !(details_.bounds_change & WindowResizer::kBoundsChange_Resizes)))) { - should_dock = GetDraggedWindowAlignment() != DOCKED_ALIGNMENT_NONE; + if ((details_.bounds_change & WindowResizer::kBoundsChange_Repositions) && + !(details_.bounds_change & WindowResizer::kBoundsChange_Resizes) && + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAshEnableDockedWindows)) { + const bool attached_panel = + window->type() == aura::client::WINDOW_TYPE_PANEL && + window->GetProperty(internal::kPanelAttachedKey); + should_dock = !attached_panel && + internal::DockedWindowLayoutManager::ShouldWindowDock(window, + last_location_); } - // Check if the window needs to be docked or returned to workspace. - aura::Window* dock_container = Shell::GetContainer( - window->GetRootWindow(), - kShellWindowId_DockedContainer); - if (!attached_panel && - should_dock != (window->parent() == dock_container)) { + // Check if desired docked state is not same as current. + // If not same dock or undock accordingly. + if (should_dock != + (window->parent()->id() == internal::kShellWindowId_DockedContainer)) { if (should_dock) { + aura::Window* dock_container = Shell::GetContainer( + window->GetRootWindow(), + internal::kShellWindowId_DockedContainer); dock_container->AddChild(window); - } else if (window->parent()->id() == kShellWindowId_DockedContainer) { + } else { // Reparent the window back to workspace. // We need to be careful to give SetDefaultParentByRootWindow location in // the right root window (matching the logic in DragWindowResizer) based @@ -336,25 +235,6 @@ void DockedWindowResizer::FinishedDragging() { } } dock_layout_->FinishDragging(); - - // If we started the drag in one root window and moved into another root - // but then canceled the drag we may need to inform the original layout - // manager that the drag is finished. - if (initial_dock_layout_ != dock_layout_) - initial_dock_layout_->FinishDragging(); - is_docked_ = false; -} - -void DockedWindowResizer::UpdateSnapPhantomWindow() { - if (!did_move_or_resize_ || details_.window_component != HTCAPTION) - return; - - if (!snap_phantom_window_controller_) { - snap_phantom_window_controller_.reset( - new PhantomWindowController(GetTarget())); - } - snap_phantom_window_controller_->Show(dock_layout_->dragged_bounds()); } -} // namespace internal -} // namespace ash +} // namespace aura diff --git a/chromium/ash/wm/dock/docked_window_resizer.h b/chromium/ash/wm/dock/docked_window_resizer.h index 41bb4fecd5f..41dd47d5b38 100644 --- a/chromium/ash/wm/dock/docked_window_resizer.h +++ b/chromium/ash/wm/dock/docked_window_resizer.h @@ -5,10 +5,8 @@ #ifndef ASH_WM_DOCK_DOCK_WINDOW_RESIZER_H_ #define ASH_WM_DOCK_DOCK_WINDOW_RESIZER_H_ -#include "ash/wm/dock/dock_types.h" #include "ash/wm/window_resizer.h" #include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" namespace gfx { class Point; @@ -20,10 +18,10 @@ class RootWindow; } namespace ash { -namespace internal { +namespace internal { class DockedWindowLayoutManager; -class PhantomWindowController; +} // DockWindowResizer is used by ToplevelWindowEventFilter to handle dragging, // moving or resizing of a window while it is docked to the side of a screen. @@ -54,12 +52,6 @@ class ASH_EXPORT DockedWindowResizer : public WindowResizer { DockedWindowResizer(WindowResizer* next_window_resizer, const Details& details); - // Returns the side of the screen that the window should dock to or - // DOCKED_ALIGNMENT_NONE when the window is not on a side or when some other - // windows are already docked on the other side or when launcher (shelf) is - // aligned on the same side. - DockedAlignment GetDraggedWindowAlignment(); - // Checks if the provided window bounds should snap to the side of a screen. // If so the offset returned gives the necessary adjustment to snap. bool MaybeSnapToEdge(const gfx::Rect& bounds, gfx::Point* offset); @@ -70,10 +62,7 @@ class ASH_EXPORT DockedWindowResizer : public WindowResizer { // Informs the DockLayoutManager that the drag is complete if it was informed // of the drag start. - void FinishedDragging(); - - // Updates the bounds of the phantom window that is used as a docking hint. - void UpdateSnapPhantomWindow(); + void FinishDragging(); const Details details_; @@ -84,20 +73,13 @@ class ASH_EXPORT DockedWindowResizer : public WindowResizer { // Dock container window. internal::DockedWindowLayoutManager* dock_layout_; - internal::DockedWindowLayoutManager* initial_dock_layout_; // Set to true once Drag() is invoked and the bounds of the window change. bool did_move_or_resize_; - // Gives a preview of where the the window will end up. - scoped_ptr<PhantomWindowController> snap_phantom_window_controller_; - // Set to true if the window that is being dragged was docked before drag. bool was_docked_; - // True if the dragged window is docked during the drag. - bool is_docked_; - // If non-NULL the destructor sets this to true. Used to determine if this has // been deleted. bool* destroyed_; @@ -105,7 +87,6 @@ class ASH_EXPORT DockedWindowResizer : public WindowResizer { DISALLOW_COPY_AND_ASSIGN(DockedWindowResizer); }; -} // namespace internal } // namespace ash #endif // ASH_WM_DOCK_DOCK_WINDOW_RESIZER_H_ diff --git a/chromium/ash/wm/dock/docked_window_resizer_unittest.cc b/chromium/ash/wm/dock/docked_window_resizer_unittest.cc index 49aeca25318..606e6f4f9d7 100644 --- a/chromium/ash/wm/dock/docked_window_resizer_unittest.cc +++ b/chromium/ash/wm/dock/docked_window_resizer_unittest.cc @@ -63,6 +63,11 @@ class DockedWindowResizerTest DOCKED_EDGE_RIGHT, }; + enum DockedState { + UNDOCKED, + DOCKED, + }; + aura::Window* CreateTestWindow(const gfx::Rect& bounds) { aura::Window* window = CreateTestWindowInShellWithDelegateAndType( &delegate_, @@ -140,12 +145,15 @@ class DockedWindowResizerTest } // Panels are parented by panel container during drags. - // All other windows that are tested here are parented by dock container - // during drags. - int CorrectContainerIdDuringDrag() { + // Docked windows are parented by dock container during drags. + // All other windows that we are testing here have default container as a + // parent. + int CorrectContainerIdDuringDrag(DockedState is_docked) { if (window_type_ == aura::client::WINDOW_TYPE_PANEL) return internal::kShellWindowId_PanelContainer; - return internal::kShellWindowId_DockedContainer; + if (is_docked == DOCKED) + return internal::kShellWindowId_DockedContainer; + return internal::kShellWindowId_DefaultContainer; } // Test dragging the window vertically (to detach if it is a panel) and then @@ -190,7 +198,7 @@ class DockedWindowResizerTest // Drag enough to detach since our tests assume panels to be initially // detached. DragMove(0, dy); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); + EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id()); EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x()); EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y()); @@ -212,7 +220,7 @@ class DockedWindowResizerTest else if (edge == DOCKED_EDGE_RIGHT) dx += window->GetRootWindow()->bounds().right() - initial_bounds.right(); DragMove(dx, window_type_ == aura::client::WINDOW_TYPE_PANEL ? 0 : dy); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); + EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id()); // Release the mouse and the panel should be attached to the dock. DragEnd(); @@ -381,10 +389,9 @@ TEST_P(DockedWindowResizerTest, AttachTryDetach) { window->GetBoundsInScreen().right()); EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - // Try to detach by dragging left less than kSnapToDockDistance. - // The window should stay docked. + // Try to detach by dragging left a bit (should stay docked) ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); - DragMove(-4, -10); + DragMove(-10, -10); // Release the mouse and the window should be still attached to the dock. DragEnd(); @@ -393,8 +400,7 @@ TEST_P(DockedWindowResizerTest, AttachTryDetach) { window->GetBoundsInScreen().right()); EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - // Try to detach by dragging left by kSnapToDockDistance or more. - // The window should get undocked. + // Try to detach by dragging left a bit more (should get undocked) ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); DragMove(-32, -10); // Release the mouse and the window should be no longer attached to the dock. @@ -539,7 +545,7 @@ TEST_P(DockedWindowResizerTest, DragAcrossDisplays) { // but not enough to land in the other screen ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); DragMove(70, 0); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); + EXPECT_EQ(CorrectContainerIdDuringDrag(DOCKED), window->parent()->id()); DragEnd(); EXPECT_NE(window->GetRootWindow()->bounds().right(), window->GetBoundsInScreen().right()); @@ -550,7 +556,7 @@ TEST_P(DockedWindowResizerTest, DragAcrossDisplays) { // Move back left - should dock again. ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); DragMove(-70, 0); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); + EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id()); DragEnd(); EXPECT_EQ(window->GetRootWindow()->bounds().right(), window->GetBoundsInScreen().right()); @@ -566,7 +572,7 @@ TEST_P(DockedWindowResizerTest, DragAcrossDisplays) { window->bounds().width()/2 + 10, 0)); DragMove(window->bounds().width()/2 - 5, 0); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); + EXPECT_EQ(CorrectContainerIdDuringDrag(DOCKED), window->parent()->id()); DragEnd(); EXPECT_NE(window->GetRootWindow()->bounds().right(), window->GetBoundsInScreen().right()); @@ -583,7 +589,7 @@ TEST_P(DockedWindowResizerTest, DragAcrossDisplays) { DragMove(window->GetRootWindow()->GetBoundsInScreen().x() - window->GetBoundsInScreen().x(), 0); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); + EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id()); DragEnd(); EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(), window->GetBoundsInScreen().x()); @@ -614,7 +620,7 @@ TEST_P(DockedWindowResizerTest, AttachTwoWindowsDetachOne) EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); EXPECT_EQ(w1->bounds().width(), manager->docked_width_); - DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 100); + DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 50); // Both windows should now be attached and snapped to the right edge. EXPECT_EQ(w2->GetRootWindow()->bounds().right(), w2->GetBoundsInScreen().right()); @@ -721,11 +727,12 @@ TEST_P(DockedWindowResizerTest, AttachWindowMaximizeOther) ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); DragMove(-35, 10); - // Alignment is set to "NONE" when drag starts. - EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_); + // For NORMAL windows alignment is set to "RIGHT" until the drag is completed. + // For PANEL windows alignment is set to "NONE" when drag starts. + EXPECT_EQ(test_panels() ? DOCKED_ALIGNMENT_NONE : DOCKED_ALIGNMENT_RIGHT, + manager->alignment_); // Release the mouse and the window should be no longer attached to the edge. DragEnd(); - EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_); // Dock should get shrunk and desktop should get expanded. EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id()); EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); @@ -817,7 +824,7 @@ TEST_P(DockedWindowResizerTest, AttachOneTestSticky) // Drag w2 by a bit more - it should resist the drag (stuck edges) int start_x = w2->bounds().x(); - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w2.get(), 100, 5)); + ASSERT_NO_FATAL_FAILURE(DragStart(w2.get())); DragMove(-2, 0); // Window should not actually move. EXPECT_EQ(start_x, w2->bounds().x()); @@ -881,7 +888,7 @@ TEST_P(DockedWindowResizerTest, ResizeTwoWindows) EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); EXPECT_EQ(w1->bounds().width(), manager->docked_width_); - DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 100); + DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 50); // Both windows should now be attached and snapped to the right edge. EXPECT_EQ(w2->GetRootWindow()->bounds().right(), w2->GetBoundsInScreen().right()); @@ -1024,11 +1031,12 @@ TEST_P(DockedWindowResizerTest, DragToShelf) // Detach and drag down to shelf. ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); DragMove(-40, 0); - // Alignment is set to "NONE" when drag starts. - EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_); + // For NORMAL windows alignment is set to "RIGHT" until the drag is completed. + // For PANEL windows alignment is set to "NONE" when drag starts. + EXPECT_EQ(test_panels() ? DOCKED_ALIGNMENT_NONE : DOCKED_ALIGNMENT_RIGHT, + manager->alignment_); // Release the mouse and the window should be no longer attached to the edge. DragEnd(); - EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_); // Drag down almost to shelf. A panel will snap, a regular window won't. ShelfWidget* shelf = Launcher::ForPrimaryDisplay()->shelf_widget(); diff --git a/chromium/ash/wm/event_client_impl.cc b/chromium/ash/wm/event_client_impl.cc index 03d4dea0b03..fcdc1b425d3 100644 --- a/chromium/ash/wm/event_client_impl.cc +++ b/chromium/ash/wm/event_client_impl.cc @@ -8,7 +8,6 @@ #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ui/aura/window.h" -#include "ui/keyboard/keyboard_util.h" namespace ash { namespace internal { @@ -22,34 +21,26 @@ EventClientImpl::~EventClientImpl() { bool EventClientImpl::CanProcessEventsWithinSubtree( const aura::Window* window) const { const aura::RootWindow* root_window = window ? window->GetRootWindow() : NULL; - if (!root_window || - !Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked()) { + if (!root_window) return true; - } - - const aura::Window* lock_screen_containers = Shell::GetContainer( - root_window, - kShellWindowId_LockScreenContainersContainer); - const aura::Window* lock_background_containers = Shell::GetContainer( - root_window, - kShellWindowId_LockScreenBackgroundContainer); - const aura::Window* lock_screen_related_containers = Shell::GetContainer( - root_window, - kShellWindowId_LockScreenRelatedContainersContainer); - bool can_process_events = (window->Contains(lock_screen_containers) && - window->Contains(lock_background_containers) && - window->Contains(lock_screen_related_containers)) || - lock_screen_containers->Contains(window) || - lock_background_containers->Contains(window) || - lock_screen_related_containers->Contains(window); - if (keyboard::IsKeyboardEnabled()) { - const aura::Window* virtual_keyboard_container = Shell::GetContainer( + if (Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked()) { + const aura::Window* lock_screen_containers = Shell::GetContainer( + root_window, + kShellWindowId_LockScreenContainersContainer); + const aura::Window* lock_background_containers = Shell::GetContainer( + root_window, + kShellWindowId_LockScreenBackgroundContainer); + const aura::Window* lock_screen_related_containers = Shell::GetContainer( root_window, - kShellWindowId_VirtualKeyboardContainer); - can_process_events |= (window->Contains(virtual_keyboard_container) || - virtual_keyboard_container->Contains(window)); + kShellWindowId_LockScreenRelatedContainersContainer); + return (window->Contains(lock_screen_containers) && + window->Contains(lock_background_containers) && + window->Contains(lock_screen_related_containers)) || + lock_screen_containers->Contains(window) || + lock_background_containers->Contains(window) || + lock_screen_related_containers->Contains(window); } - return can_process_events; + return true; } ui::EventTarget* EventClientImpl::GetToplevelEventTarget() { diff --git a/chromium/ash/wm/frame_painter.h b/chromium/ash/wm/frame_painter.h index e79b012d2e9..38f2fb1e697 100644 --- a/chromium/ash/wm/frame_painter.h +++ b/chromium/ash/wm/frame_painter.h @@ -160,6 +160,8 @@ class ASH_EXPORT FramePainter : public aura::WindowObserver, FRIEND_TEST_ALL_PREFIXES(FramePainterTest, GetHeaderOpacity); FRIEND_TEST_ALL_PREFIXES(FramePainterTest, TitleIconAlignment); FRIEND_TEST_ALL_PREFIXES(FramePainterTest, ChildWindowVisibility); + FRIEND_TEST_ALL_PREFIXES(FramePainterTest, + NoCrashShutdownWithAlwaysOnTopWindow); // Sets the images for a button based on IDs from the |frame_| theme provider. void SetButtonImages(views::ImageButton* button, diff --git a/chromium/ash/wm/frame_painter_unittest.cc b/chromium/ash/wm/frame_painter_unittest.cc index ee9313fcf10..5826be6787d 100644 --- a/chromium/ash/wm/frame_painter_unittest.cc +++ b/chromium/ash/wm/frame_painter_unittest.cc @@ -12,6 +12,7 @@ #include "ash/wm/window_properties.h" #include "ash/wm/window_util.h" #include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" #include "grit/ash_resources.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/client/aura_constants.h" @@ -25,6 +26,7 @@ #include "ui/views/controls/button/image_button.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" +#include "ui/views/widget/widget_observer.h" #include "ui/views/window/non_client_view.h" using ash::FramePainter; @@ -148,6 +150,33 @@ FramePainter* CreateTestPainter(Widget* widget) { return painter; } +// Self-owned manager of the frame painter which deletes the painter and itself +// when its widget is closed. +class FramePainterOwner : views::WidgetObserver { + public: + explicit FramePainterOwner(Widget* widget) + : frame_painter_(CreateTestPainter(widget)) { + widget->AddObserver(this); + } + + virtual ~FramePainterOwner() {} + + FramePainter* frame_painter() { return frame_painter_.get(); } + + private: + virtual void OnWidgetDestroying(Widget* widget) OVERRIDE { + widget->RemoveObserver(this); + // Do not delete directly here, since the task of FramePainter causing + // the crash of crbug.com/273310 may run after this class handles this + // event. + base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); + } + + scoped_ptr<FramePainter> frame_painter_; + + DISALLOW_COPY_AND_ASSIGN(FramePainterOwner); +}; + } // namespace namespace ash { @@ -690,4 +719,33 @@ TEST_F(FramePainterTest, ChildWindowVisibility) { 0)); } +TEST_F(FramePainterTest, NoCrashShutdownWithAlwaysOnTopWindow) { + // Create normal window and an always-on-top window, and leave it as is + // and finish the test, then verify it doesn't cause a crash. See + // crbug.com/273310. Note that those widgets will be deleted at + // RootWindowController::CloseChildWindows(), so this code is memory-safe. + Widget* w1 = new Widget; + Widget::InitParams params1; + params1.context = CurrentContext(); + w1->Init(params1); + FramePainterOwner* o1 = new FramePainterOwner(w1); + FramePainter* p1 = o1->frame_painter(); + w1->SetBounds(gfx::Rect(0, 0, 100, 100)); + w1->Show(); + EXPECT_TRUE(p1->UseSoloWindowHeader()); + + Widget* w2 = new Widget; + Widget::InitParams params2; + params2.context = CurrentContext(); + params2.keep_on_top = true; + w2->Init(params2); + FramePainterOwner* o2 = new FramePainterOwner(w2); + FramePainter* p2 = o2->frame_painter(); + w2->Show(); + EXPECT_FALSE(p1->UseSoloWindowHeader()); + EXPECT_FALSE(p2->UseSoloWindowHeader()); + + // Exit with no resource release. They'll be released at shutdown. +} + } // namespace ash diff --git a/chromium/ash/wm/panels/panel_layout_manager_unittest.cc b/chromium/ash/wm/panels/panel_layout_manager_unittest.cc index 08f53f7aa8b..ca231ce005d 100644 --- a/chromium/ash/wm/panels/panel_layout_manager_unittest.cc +++ b/chromium/ash/wm/panels/panel_layout_manager_unittest.cc @@ -128,8 +128,6 @@ class PanelLayoutManagerTest : public test::AshTestBase { ASSERT_FALSE(icon_bounds.width() == 0 && icon_bounds.height() == 0); gfx::Rect window_bounds = panel->GetBoundsInScreen(); - ASSERT_LT(icon_bounds.width(), window_bounds.width()); - ASSERT_LT(icon_bounds.height(), window_bounds.height()); gfx::Rect launcher_bounds = launcher->shelf_widget()-> GetWindowBoundsInScreen(); ShelfAlignment alignment = GetAlignment(panel->GetRootWindow()); diff --git a/chromium/ash/wm/status_area_layout_manager.cc b/chromium/ash/wm/status_area_layout_manager.cc index d9e0424d240..e17d84e26d2 100644 --- a/chromium/ash/wm/status_area_layout_manager.cc +++ b/chromium/ash/wm/status_area_layout_manager.cc @@ -70,7 +70,7 @@ void StatusAreaLayoutManager::SetChildBounds( void StatusAreaLayoutManager::LayoutStatusArea() { // Shelf layout manager may be already doing layout. - if (shelf_->shelf_layout_manager()->updating_bounds()) + if (shelf_->shelf_layout_manager()->in_layout()) return; base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true); diff --git a/chromium/ash/wm/window_animations.cc b/chromium/ash/wm/window_animations.cc index a3c0ca80621..73deafd75c1 100644 --- a/chromium/ash/wm/window_animations.cc +++ b/chromium/ash/wm/window_animations.cc @@ -295,6 +295,9 @@ class CrossFadeObserver : public ui::CompositorObserver, // Triggers OnImplicitAnimationsCompleted() to be called and deletes us. layer_->GetAnimator()->StopAnimating(); } + virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE { + layer_->GetAnimator()->StopAnimating(); + } // ui::ImplicitAnimationObserver overrides: virtual void OnImplicitAnimationsCompleted() OVERRIDE { diff --git a/chromium/ash/wm/window_resizer.cc b/chromium/ash/wm/window_resizer.cc index 1ea317a1a3f..e312fc179e5 100644 --- a/chromium/ash/wm/window_resizer.cc +++ b/chromium/ash/wm/window_resizer.cc @@ -7,7 +7,6 @@ #include "ash/screen_ash.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" -#include "ash/wm/coordinate_conversion.h" #include "ash/wm/dock/docked_window_layout_manager.h" #include "ash/wm/property_util.h" #include "ash/wm/window_util.h" @@ -181,6 +180,14 @@ gfx::Rect WindowResizer::CalculateBoundsForDrag( return details.initial_bounds_in_parent; gfx::Point location = passed_location; + aura::Window* dock_container = Shell::GetContainer( + details.window->GetRootWindow(), + internal::kShellWindowId_DockedContainer); + DCHECK_EQ(dock_container->id(), internal::kShellWindowId_DockedContainer); + internal::DockedWindowLayoutManager* dock_layout = + static_cast<internal::DockedWindowLayoutManager*>( + dock_container->layout_manager()); + int delta_x = location.x() - details.initial_location_in_parent.x(); int delta_y = location.y() - details.initial_location_in_parent.y(); @@ -199,13 +206,6 @@ gfx::Rect WindowResizer::CalculateBoundsForDrag( if (details.bounds_change & kBoundsChange_Resizes) { gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(details.window).work_area(); - aura::Window* dock_container = Shell::GetContainer( - details.window->GetRootWindow(), - internal::kShellWindowId_DockedContainer); - internal::DockedWindowLayoutManager* dock_layout = - static_cast<internal::DockedWindowLayoutManager*>( - dock_container->layout_manager()); - work_area.Union(dock_layout->docked_bounds()); work_area = ScreenAsh::ConvertRectFromScreen(details.window->parent(), work_area); @@ -265,13 +265,6 @@ gfx::Rect WindowResizer::CalculateBoundsForDrag( ScreenAsh::ConvertRectToScreen(parent, new_bounds); const gfx::Display& display = Shell::GetScreen()->GetDisplayMatching(new_bounds_in_screen); - aura::Window* dock_container = Shell::GetContainer( - wm::GetRootWindowMatching(new_bounds_in_screen), - internal::kShellWindowId_DockedContainer); - internal::DockedWindowLayoutManager* dock_layout = - static_cast<internal::DockedWindowLayoutManager*>( - dock_container->layout_manager()); - gfx::Rect screen_work_area = display.work_area(); screen_work_area.Union(dock_layout->docked_bounds()); screen_work_area.Inset(kMinimumOnScreenArea, 0); diff --git a/chromium/ash/wm/window_selector.cc b/chromium/ash/wm/window_selector.cc index 47e20159572..8e87a95163c 100644 --- a/chromium/ash/wm/window_selector.cc +++ b/chromium/ash/wm/window_selector.cc @@ -361,10 +361,6 @@ void WindowSelector::OnEvent(ui::Event* event) { aura::Window* target = static_cast<aura::Window*>(event->target()); for (size_t i = 0; i < windows_.size(); ++i) { if (windows_[i]->Contains(target)) { - // TODO(flackr): StopPropogation prevents generation of gesture events. - // We should find a better way to prevent events from being delivered to - // the window, perhaps a transparent window in front of the target window - // or using EventClientImpl::CanProcessEventsWithinSubtree. event->StopPropagation(); break; } @@ -385,8 +381,8 @@ void WindowSelector::OnMouseEvent(ui::MouseEvent* event) { HandleSelectionEvent(target); } -void WindowSelector::OnTouchEvent(ui::TouchEvent* event) { - if (event->type() != ui::ET_TOUCH_PRESSED) +void WindowSelector::OnGestureEvent(ui::GestureEvent* event) { + if (event->type() != ui::ET_GESTURE_TAP) return; WindowSelectorWindow* target = GetEventTarget(event); if (!target) diff --git a/chromium/ash/wm/window_selector.h b/chromium/ash/wm/window_selector.h index 9cd1e04fd22..92ed607eabc 100644 --- a/chromium/ash/wm/window_selector.h +++ b/chromium/ash/wm/window_selector.h @@ -64,7 +64,7 @@ class WindowSelector : public ui::EventHandler, // ui::EventHandler: virtual void OnEvent(ui::Event* event) OVERRIDE; virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; + virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; // aura::WindowObserver: virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; diff --git a/chromium/ash/wm/window_util.cc b/chromium/ash/wm/window_util.cc index 67dcd95c4c1..7b8e616aa7e 100644 --- a/chromium/ash/wm/window_util.cc +++ b/chromium/ash/wm/window_util.cc @@ -161,29 +161,29 @@ void SetPreAutoManageWindowBounds(aura::Window* window, new gfx::Rect(bounds)); } -void AdjustBoundsToEnsureMinimumWindowVisibility(const gfx::Rect& work_area, +void AdjustBoundsToEnsureMinimumWindowVisibility(const gfx::Rect& visible_area, gfx::Rect* bounds) { AdjustBoundsToEnsureWindowVisibility( - work_area, kMinimumOnScreenArea, kMinimumOnScreenArea, bounds); + visible_area, kMinimumOnScreenArea, kMinimumOnScreenArea, bounds); } -void AdjustBoundsToEnsureWindowVisibility(const gfx::Rect& work_area, +void AdjustBoundsToEnsureWindowVisibility(const gfx::Rect& visible_area, int min_width, int min_height, gfx::Rect* bounds) { - bounds->set_width(std::min(bounds->width(), work_area.width())); - bounds->set_height(std::min(bounds->height(), work_area.height())); + bounds->set_width(std::min(bounds->width(), visible_area.width())); + bounds->set_height(std::min(bounds->height(), visible_area.height())); - min_width = std::min(min_width, work_area.width()); - min_height = std::min(min_height, work_area.height()); + min_width = std::min(min_width, visible_area.width()); + min_height = std::min(min_height, visible_area.height()); - if (bounds->x() + min_width > work_area.right()) { - bounds->set_x(work_area.right() - min_width); + if (bounds->x() + min_width > visible_area.right()) { + bounds->set_x(visible_area.right() - min_width); } else if (bounds->right() - min_width < 0) { bounds->set_x(min_width - bounds->width()); } - if (bounds->y() + min_height > work_area.bottom()) { - bounds->set_y(work_area.bottom() - min_height); + if (bounds->y() + min_height > visible_area.bottom()) { + bounds->set_y(visible_area.bottom() - min_height); } else if (bounds->bottom() - min_height < 0) { bounds->set_y(min_height - bounds->height()); } diff --git a/chromium/ash/wm/window_util.h b/chromium/ash/wm/window_util.h index 1ffeb7db8a3..659d3e11e2d 100644 --- a/chromium/ash/wm/window_util.h +++ b/chromium/ash/wm/window_util.h @@ -108,16 +108,16 @@ ASH_EXPORT const gfx::Rect* GetPreAutoManageWindowBounds( ASH_EXPORT void SetPreAutoManageWindowBounds(aura::Window* window, const gfx::Rect& bounds); -// Move the given bounds inside the given work area, including a safety margin -// given by |kMinimumOnScreenArea|. +// Move the given bounds inside the given |visible_area|, including a +// safety margin given by |kMinimumOnScreenArea|. ASH_EXPORT void AdjustBoundsToEnsureMinimumWindowVisibility( - const gfx::Rect& work_area, + const gfx::Rect& visible_area, gfx::Rect* bounds); -// Move the given bounds inside the given work area, including a safety margin -// given by |min_width| and |min_height|. +// Move the given bounds inside the given |visible_area|, including a +// safety margin given by |min_width| and |min_height|. ASH_EXPORT void AdjustBoundsToEnsureWindowVisibility( - const gfx::Rect& work_area, + const gfx::Rect& visible_area, int min_width, int min_height, gfx::Rect* bounds); diff --git a/chromium/ash/wm/workspace/phantom_window_controller.cc b/chromium/ash/wm/workspace/phantom_window_controller.cc index 67272c18a39..4287d5b40d0 100644 --- a/chromium/ash/wm/workspace/phantom_window_controller.cc +++ b/chromium/ash/wm/workspace/phantom_window_controller.cc @@ -8,7 +8,6 @@ #include "ash/shell_window_ids.h" #include "ash/wm/coordinate_conversion.h" #include "third_party/skia/include/core/SkCanvas.h" -#include "ui/aura/root_window.h" #include "ui/aura/window.h" #include "ui/base/animation/slide_animation.h" #include "ui/compositor/layer.h" @@ -92,56 +91,25 @@ void EdgePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) { PhantomWindowController::PhantomWindowController(aura::Window* window) : window_(window), phantom_below_window_(NULL), - phantom_widget_(NULL), - phantom_widget_start_(NULL) { + phantom_widget_(NULL) { } PhantomWindowController::~PhantomWindowController() { Hide(); } -void PhantomWindowController::Show(const gfx::Rect& bounds_in_screen) { - if (bounds_in_screen == bounds_in_screen_) +void PhantomWindowController::Show(const gfx::Rect& bounds) { + if (bounds == bounds_) return; - bounds_in_screen_ = bounds_in_screen; - aura::RootWindow* target_root = wm::GetRootWindowMatching(bounds_in_screen); - // Show the phantom at the current bounds of the window. We'll animate to the - // target bounds. If phantom exists, update the start bounds. - if (!phantom_widget_) + bounds_ = bounds; + if (!phantom_widget_) { + // Show the phantom at the bounds of the window. We'll animate to the target + // bounds. start_bounds_ = window_->GetBoundsInScreen(); - else + CreatePhantomWidget(start_bounds_); + } else { start_bounds_ = phantom_widget_->GetWindowBoundsInScreen(); - if (phantom_widget_ && - phantom_widget_->GetNativeWindow()->GetRootWindow() != target_root) { - phantom_widget_->Close(); - phantom_widget_ = NULL; - } - if (!phantom_widget_) - phantom_widget_ = CreatePhantomWidget(target_root, start_bounds_); - - // Create a secondary widget in a second screen if start_bounds_ lie at least - // partially in that other screen. This allows animations to start or restart - // in one root window and progress into another root. - aura::RootWindow* start_root = wm::GetRootWindowMatching(start_bounds_); - if (start_root == target_root) { - Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); - for (size_t i = 0; i < root_windows.size(); ++i) { - if (root_windows[i] != target_root && - root_windows[i]->GetBoundsInScreen().Intersects(start_bounds_)) { - start_root = root_windows[i]; - break; - } - } } - if (phantom_widget_start_ && - (phantom_widget_start_->GetNativeWindow()->GetRootWindow() != start_root - || start_root == target_root)) { - phantom_widget_start_->Close(); - phantom_widget_start_ = NULL; - } - if (!phantom_widget_start_ && start_root != target_root) - phantom_widget_start_ = CreatePhantomWidget(start_root, start_bounds_); - animation_.reset(new ui::SlideAnimation(this)); animation_->SetTweenType(ui::Tween::EASE_IN); const int kAnimationDurationMS = 200; @@ -153,9 +121,6 @@ void PhantomWindowController::Hide() { if (phantom_widget_) phantom_widget_->Close(); phantom_widget_ = NULL; - if (phantom_widget_start_) - phantom_widget_start_->Close(); - phantom_widget_start_ = NULL; } bool PhantomWindowController::IsShowing() const { @@ -164,50 +129,45 @@ bool PhantomWindowController::IsShowing() const { void PhantomWindowController::AnimationProgressed( const ui::Animation* animation) { - const gfx::Rect current_bounds = - animation->CurrentValueBetween(start_bounds_, bounds_in_screen_); - if (phantom_widget_start_) - phantom_widget_start_->SetBounds(current_bounds); - phantom_widget_->SetBounds(current_bounds); + phantom_widget_->SetBounds( + animation->CurrentValueBetween(start_bounds_, bounds_)); } -views::Widget* PhantomWindowController::CreatePhantomWidget( - aura::RootWindow* root_window, - const gfx::Rect& bounds_in_screen) { - views::Widget* phantom_widget = new views::Widget; +void PhantomWindowController::CreatePhantomWidget(const gfx::Rect& bounds) { + DCHECK(!phantom_widget_); + phantom_widget_ = new views::Widget; views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; // PhantomWindowController is used by FrameMaximizeButton to highlight the // launcher button. Put the phantom in the same window as the launcher so that // the phantom is visible. - params.parent = Shell::GetContainer(root_window, + params.parent = Shell::GetContainer(wm::GetRootWindowMatching(bounds), kShellWindowId_ShelfContainer); params.can_activate = false; params.keep_on_top = true; - phantom_widget->set_focus_on_creation(false); - phantom_widget->Init(params); - phantom_widget->SetVisibilityChangedAnimationsEnabled(false); - phantom_widget->GetNativeWindow()->SetName("PhantomWindow"); - phantom_widget->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow); + phantom_widget_->set_focus_on_creation(false); + phantom_widget_->Init(params); + phantom_widget_->SetVisibilityChangedAnimationsEnabled(false); + phantom_widget_->GetNativeWindow()->SetName("PhantomWindow"); + phantom_widget_->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow); views::View* content_view = new views::View; content_view->set_background( views::Background::CreateBackgroundPainter(true, new EdgePainter)); - phantom_widget->SetContentsView(content_view); - phantom_widget->SetBounds(bounds_in_screen); + phantom_widget_->SetContentsView(content_view); + phantom_widget_->SetBounds(bounds); if (phantom_below_window_) - phantom_widget->StackBelow(phantom_below_window_); + phantom_widget_->StackBelow(phantom_below_window_); else - phantom_widget->StackAbove(window_); + phantom_widget_->StackAbove(window_); // Show the widget after all the setups. - phantom_widget->Show(); + phantom_widget_->Show(); // Fade the window in. - ui::Layer* widget_layer = phantom_widget->GetNativeWindow()->layer(); + ui::Layer* widget_layer = phantom_widget_->GetNativeWindow()->layer(); widget_layer->SetOpacity(0); ui::ScopedLayerAnimationSettings scoped_setter(widget_layer->GetAnimator()); widget_layer->SetOpacity(1); - return phantom_widget; } } // namespace internal diff --git a/chromium/ash/wm/workspace/phantom_window_controller.h b/chromium/ash/wm/workspace/phantom_window_controller.h index 5cd40daa2cd..d7622fcc556 100644 --- a/chromium/ash/wm/workspace/phantom_window_controller.h +++ b/chromium/ash/wm/workspace/phantom_window_controller.h @@ -13,7 +13,6 @@ #include "ui/gfx/rect.h" namespace aura { -class RootWindow; class Window; } @@ -36,14 +35,13 @@ class ASH_EXPORT PhantomWindowController : public ui::AnimationDelegate { virtual ~PhantomWindowController(); // Bounds last passed to Show(). - const gfx::Rect& bounds_in_screen() const { return bounds_in_screen_; } + const gfx::Rect& bounds() const { return bounds_; } - // Animates the phantom window towards |bounds_in_screen|. - // Creates two (if start bounds intersect any root window other than the - // root window that matches the target bounds) or one (otherwise) phantom - // widgets to display animated rectangle in each root. + // Shows the phantom window at the specified location (coordinates of the + // parent). If |layer| is non-NULL, it is shown on top of the phantom window. + // |layer| is owned by the caller. // This does not immediately show the window. - void Show(const gfx::Rect& bounds_in_screen); + void Show(const gfx::Rect& bounds); // Hides the phantom. void Hide(); @@ -61,12 +59,12 @@ class ASH_EXPORT PhantomWindowController : public ui::AnimationDelegate { virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; private: - FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomWindowShow); + FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomStyle); - // Creates, shows and returns a phantom widget at |bounds| - // with kShellWindowId_ShelfContainer in |root_window| as a parent. - views::Widget* CreatePhantomWidget(aura::RootWindow* root_window, - const gfx::Rect& bounds_in_screen); + // Creates and shows the |phantom_widget_| at |bounds|. + // |layer| is shown on top of the phantom window if it is non-NULL. + // |layer| is not owned by this object. + void CreatePhantomWidget(const gfx::Rect& bounds); // Window the phantom is placed beneath. aura::Window* window_; @@ -74,24 +72,15 @@ class ASH_EXPORT PhantomWindowController : public ui::AnimationDelegate { // If set, the phantom window should get stacked below this window. aura::Window* phantom_below_window_; - // Initially the bounds of |window_| (in screen coordinates). - // Each time Show() is invoked |start_bounds_| is then reset to the bounds of - // |phantom_widget_| and |bounds_| is set to the value passed into Show(). - // The animation animates between these two values. + // Initially the bounds of |window_|. Each time Show() is invoked + // |start_bounds_| is then reset to the bounds of |phantom_widget_| and + // |bounds_| is set to the value passed into Show(). The animation animates + // between these two values. gfx::Rect start_bounds_; + gfx::Rect bounds_; - // Target bounds of the animation in screen coordinates. - gfx::Rect bounds_in_screen_; - - // The primary phantom representation of the window. It is parented by the - // root window matching the target bounds. views::Widget* phantom_widget_; - // If the animation starts on another display, this is the secondary phantom - // representation of the window used on the initial display, otherwise this is - // NULL. This allows animation to progress from one display into the other. - views::Widget* phantom_widget_start_; - // Used to transition the bounds. scoped_ptr<ui::SlideAnimation> animation_; diff --git a/chromium/ash/wm/workspace/workspace_layout_manager.cc b/chromium/ash/wm/workspace/workspace_layout_manager.cc index 69bcc16069a..0dd9dbf3464 100644 --- a/chromium/ash/wm/workspace/workspace_layout_manager.cc +++ b/chromium/ash/wm/workspace/workspace_layout_manager.cc @@ -48,13 +48,15 @@ void MoveToDisplayForRestore(aura::Window* window) { return; // Move only if the restore bounds is outside of - // the root window. There is no information about in which + // the display. There is no information about in which // display it should be restored, so this is best guess. // TODO(oshima): Restore information should contain the // work area information like WindowResizer does for the // last window location. - if (!window->GetRootWindow()->GetBoundsInScreen().Intersects( - *restore_bounds)) { + gfx::Rect display_area = + Shell::GetScreen()->GetDisplayNearestWindow(window).bounds(); + + if (!display_area.Intersects(*restore_bounds)) { DisplayController* display_controller = Shell::GetInstance()->display_controller(); const gfx::Display& display = @@ -87,14 +89,7 @@ void WorkspaceLayoutManager::SetShelf(internal::ShelfLayoutManager* shelf) { } void WorkspaceLayoutManager::OnWindowAddedToLayout(Window* child) { - // Adjust window bounds in case that the new child is given the bounds that - // is out of the workspace. Exclude the case where bounds is empty - // (this happens when a views::Widget is created), or the window - // is added with the bounds because a user explicitly moved to - // this position (drag and drop for example). - if (!child->bounds().IsEmpty() && - !wm::HasUserChangedWindowPositionOrSize(child)) - AdjustWindowBoundsWhenAdded(child); + AdjustWindowBoundsWhenAdded(child); BaseLayoutManager::OnWindowAddedToLayout(child); UpdateDesktopVisibility(); RearrangeVisibleWindowOnShow(child); @@ -252,6 +247,14 @@ void WorkspaceLayoutManager::AdjustWindowBoundsForWorkAreaChange( void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded( Window* window) { + // Don't adjust window bounds if the bounds are empty as this + // happens when a new views::Widget is created. + // When a window is dragged and dropped onto a different + // root window, the bounds will be updated after they are added + // to the root window. + if (window->bounds().IsEmpty()) + return; + if (!GetTrackedByWorkspace(window)) return; @@ -261,9 +264,14 @@ void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded( gfx::Rect bounds = window->bounds(); int min_width = bounds.width() * kMinimumPercentOnScreenArea; int min_height = bounds.height() * kMinimumPercentOnScreenArea; + // Use entire display instead of workarea because the workarea can + // be further shrunk by the docked area. The logic ensures 30% + // visibility which should be enough to see where the window gets + // moved. + gfx::Rect display_area = + Shell::GetScreen()->GetDisplayNearestWindow(window).bounds(); ash::wm::AdjustBoundsToEnsureWindowVisibility( - work_area_, min_width, min_height, &bounds); - + display_area, min_width, min_height, &bounds); if (window->bounds() != bounds) window->SetBounds(bounds); } diff --git a/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc b/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc index 3dce5b015c9..13cfdea04a3 100644 --- a/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc +++ b/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc @@ -304,6 +304,15 @@ TEST_F(WorkspaceLayoutManagerTest, WindowShouldBeOnScreenWhenAdded) { EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29); EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29); + aura::Window* parent = out_window->parent(); + parent->RemoveChild(out_window.get()); + out_window->SetBounds(gfx::Rect(-200, -200, 200, 200)); + // UserHasChangedWindowPositionOrSize flag shouldn't turn off this behavior. + wm::SetUserHasChangedWindowPositionOrSize(window.get(), true); + parent->AddChild(out_window.get()); + EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29); + EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29); + // Make sure we always make more than 1/3 of the window edge visible even // if the initial bounds intersects with display. window_bounds.SetRect(-150, -150, 200, 200); diff --git a/chromium/ash/wm/workspace/workspace_window_resizer.cc b/chromium/ash/wm/workspace/workspace_window_resizer.cc index 4b8c0aaf7e9..2143e45668b 100644 --- a/chromium/ash/wm/workspace/workspace_window_resizer.cc +++ b/chromium/ash/wm/workspace/workspace_window_resizer.cc @@ -87,13 +87,8 @@ scoped_ptr<WindowResizer> CreateWindowResizer( window_resizer = PanelWindowResizer::Create( window_resizer, window, point_in_parent, window_component, source); } - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshEnableDockedWindows) && - window_resizer && window->parent() && - (window->parent()->id() == internal::kShellWindowId_DefaultContainer || - window->parent()->id() == internal::kShellWindowId_DockedContainer || - window->parent()->id() == internal::kShellWindowId_PanelContainer)) { - window_resizer = internal::DockedWindowResizer::Create( + if (window_resizer) { + window_resizer = DockedWindowResizer::Create( window_resizer, window, point_in_parent, window_component, source); } return make_scoped_ptr<WindowResizer>(window_resizer); @@ -103,6 +98,10 @@ namespace internal { namespace { +// Distance in pixels that the cursor must move past an edge for a window +// to move or resize beyond that edge. +const int kStickyDistancePixels = 64; + // Snapping distance used instead of WorkspaceWindowResizer::kScreenEdgeInset // when resizing a window using touchscreen. const int kScreenEdgeInsetForTouchResize = 32; @@ -117,7 +116,7 @@ bool ShouldStickToEdge(int distance_from_edge, int sticky_size) { distance_from_edge > -sticky_size; } return distance_from_edge < sticky_size && - distance_from_edge > -sticky_size * 2; + distance_from_edge > -sticky_size * 2; } // Returns the coordinate along the secondary axis to snap to. @@ -260,9 +259,6 @@ const int WorkspaceWindowResizer::kMinOnscreenHeight = 32; // static const int WorkspaceWindowResizer::kScreenEdgeInset = 8; -// static -const int WorkspaceWindowResizer::kStickyDistancePixels = 64; - // Represents the width or height of a window with constraints on its minimum // and maximum size. 0 represents a lack of a constraint. class WindowSize { @@ -509,7 +505,7 @@ gfx::Rect WorkspaceWindowResizer::GetFinalBounds( const gfx::Rect& bounds) const { if (snap_phantom_window_controller_.get() && snap_phantom_window_controller_->IsShowing()) { - return snap_phantom_window_controller_->bounds_in_screen(); + return snap_phantom_window_controller_->bounds(); } return bounds; } @@ -750,12 +746,8 @@ void WorkspaceWindowResizer::AdjustBoundsForMainWindow( } if (sticky_size > 0) { - // Possibly stick to edge except when a mouse pointer is outside the - // work area. - if (!(display.work_area().Contains(last_mouse_location_in_screen) && - StickToWorkAreaOnMove(work_area, sticky_size, bounds))) { + if (!StickToWorkAreaOnMove(work_area, sticky_size, bounds)) MagneticallySnapToOtherWindows(bounds); - } } } else if (sticky_size > 0) { MagneticallySnapResizeToOtherWindows(bounds); diff --git a/chromium/ash/wm/workspace/workspace_window_resizer.h b/chromium/ash/wm/workspace/workspace_window_resizer.h index 76176b1a2b4..61f18969cbc 100644 --- a/chromium/ash/wm/workspace/workspace_window_resizer.h +++ b/chromium/ash/wm/workspace/workspace_window_resizer.h @@ -41,10 +41,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { // this close to an edge of the screen it snaps to the edge. static const int kScreenEdgeInset; - // Distance in pixels that the cursor must move past an edge for a window - // to move or resize beyond that edge. - static const int kStickyDistancePixels; - virtual ~WorkspaceWindowResizer(); static WorkspaceWindowResizer* Create( @@ -69,7 +65,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { private: FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, CancelSnapPhantom); FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomSnapMaxSize); - FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomWindowShow); // Type of snapping. enum SnapType { diff --git a/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc b/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc index 8459c54ef5f..a00d0121429 100644 --- a/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc +++ b/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc @@ -30,36 +30,6 @@ #include "ui/gfx/screen.h" #include "ui/views/widget/widget.h" -namespace ui { - -// Class to provide access to SlideAnimation internals for testing. -class SlideAnimation::TestApi { - public: - explicit TestApi(SlideAnimation* animation) : animation_(animation) {} - - void SetStartTime(base::TimeTicks ticks) { - animation_->SetStartTime(ticks); - } - - void Step(base::TimeTicks ticks) { - animation_->Step(ticks); - } - - void RunTillComplete() { - SetStartTime(base::TimeTicks()); - Step(base::TimeTicks() + - base::TimeDelta::FromMilliseconds(animation_->GetSlideDuration())); - EXPECT_EQ(1.0, animation_->GetCurrentValue()); - } - - private: - SlideAnimation* animation_; - - DISALLOW_COPY_AND_ASSIGN(TestApi); -}; - -} - namespace ash { namespace internal { namespace { @@ -200,12 +170,6 @@ class WorkspaceWindowResizerTest : public test::AshTestBase { touch_resize_window_->set_hit_test_bounds_override_inner(mouse_insets); } - // Simulate running the animation. - void RunAnimationTillComplete(ui::SlideAnimation* animation) { - ui::SlideAnimation::TestApi test_api(animation); - test_api.RunTillComplete(); - } - TestWindowDelegate delegate_; TestWindowDelegate delegate2_; TestWindowDelegate delegate3_; @@ -878,12 +842,8 @@ TEST_F(WorkspaceWindowResizerTest, SnapToEdge) { Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()-> SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); window_->SetBounds(gfx::Rect(96, 112, 320, 160)); - // Click 50px to the right so that the mouse pointer does not leave the - // workspace ensuring sticky behavior. scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), - window_->bounds().origin() + gfx::Vector2d(50, 0), - HTCAPTION, + window_.get(), gfx::Point(), HTCAPTION, aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows())); ASSERT_TRUE(resizer.get()); // Move to an x-coordinate of 15, which should not snap. @@ -998,12 +958,8 @@ TEST_F(WorkspaceWindowResizerTestSticky, StickToEdge) { Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()-> SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); window_->SetBounds(gfx::Rect(96, 112, 320, 160)); - // Click 50px to the right so that the mouse pointer does not leave the - // workspace ensuring sticky behavior. scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), - window_->bounds().origin() + gfx::Vector2d(50, 0), - HTCAPTION, + window_.get(), gfx::Point(), HTCAPTION, aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows())); ASSERT_TRUE(resizer.get()); // Move to an x-coordinate of 15, which should not stick. @@ -1038,22 +994,6 @@ TEST_F(WorkspaceWindowResizerTestSticky, StickToEdge) { // No need to test dragging < 0 as we force that to 0. } -// Verifies not sticking to edges when a mouse pointer is outside of work area. -TEST_F(WorkspaceWindowResizerTestSticky, NoStickToEdgeWhenOutside) { - Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()-> - SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - window_->SetBounds(gfx::Rect(96, 112, 320, 160)); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTCAPTION, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows())); - ASSERT_TRUE(resizer.get()); - // Move to an x-coordinate of 15, which should not stick. - resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0); - // Move to -15, should still stick to 0. - resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0); - EXPECT_EQ("-15,112 320x160", window_->bounds().ToString()); -} - // Verifies a resize sticks when dragging TOPLEFT. TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_TOPLEFT) { window_->SetBounds(gfx::Rect(100, 200, 20, 30)); @@ -1865,114 +1805,5 @@ TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_BOTTOM) { EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 100).ToString(), touch_resize_window_->bounds().ToString()); } - -TEST_F(WorkspaceWindowResizerTest, PhantomWindowShow) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("500x400,500x400"); - window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTCAPTION, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows())); - ASSERT_TRUE(resizer.get()); - EXPECT_FALSE(resizer->snap_phantom_window_controller_.get()); - - // The pointer is on the edge but not shared. The snap phantom window - // controller should be non-NULL. - resizer->Drag(CalculateDragPoint(*resizer, 499, 0), 0); - EXPECT_TRUE(resizer->snap_phantom_window_controller_.get()); - PhantomWindowController* phantom_controller( - resizer->snap_phantom_window_controller_.get()); - - // phantom widget only in the left screen. - phantom_controller->Show(gfx::Rect(100, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_FALSE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - - // Move phantom widget into the right screen. Test that 2 widgets got created. - phantom_controller->Show(gfx::Rect(600, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_TRUE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[1], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_start_->GetNativeWindow()-> - GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Move phantom widget only in the right screen. Start widget should close. - phantom_controller->Show(gfx::Rect(700, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_FALSE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[1], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Move phantom widget into the left screen. Start widget should open. - phantom_controller->Show(gfx::Rect(100, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_TRUE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - EXPECT_EQ( - root_windows[1], - phantom_controller->phantom_widget_start_->GetNativeWindow()-> - GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Move phantom widget while in the left screen. Start widget should close. - phantom_controller->Show(gfx::Rect(200, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_FALSE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Move phantom widget spanning both screens with most of the window in the - // right screen. Two widgets are created. - phantom_controller->Show(gfx::Rect(495, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_TRUE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[1], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_start_->GetNativeWindow()-> - GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Move phantom widget back into the left screen. Phantom widgets should swap. - phantom_controller->Show(gfx::Rect(200, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_TRUE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - EXPECT_EQ( - root_windows[1], - phantom_controller->phantom_widget_start_->GetNativeWindow()-> - GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Hide phantom controller. Both widgets should close. - phantom_controller->Hide(); - EXPECT_FALSE(phantom_controller->phantom_widget_); - EXPECT_FALSE(phantom_controller->phantom_widget_start_); -} - } // namespace internal } // namespace ash diff --git a/chromium/ash/wm/workspace_controller.cc b/chromium/ash/wm/workspace_controller.cc index 7fbbda2f7af..e2ee3f5c222 100644 --- a/chromium/ash/wm/workspace_controller.cc +++ b/chromium/ash/wm/workspace_controller.cc @@ -39,6 +39,8 @@ WorkspaceController::WorkspaceController(aura::Window* viewport) event_handler_(new WorkspaceEventHandler(viewport_)) { SetWindowVisibilityAnimationTransition( viewport_, views::corewm::ANIMATE_NONE); + // Do this so when animating out windows don't extend beyond the bounds. + viewport_->layer()->SetMasksToBounds(true); // The layout-manager cannot be created in the initializer list since it // depends on the window to have been initialized. diff --git a/chromium/ash/wm/workspace_controller_unittest.cc b/chromium/ash/wm/workspace_controller_unittest.cc index 7dca75a08ba..f6a4ffb0ef2 100644 --- a/chromium/ash/wm/workspace_controller_unittest.cc +++ b/chromium/ash/wm/workspace_controller_unittest.cc @@ -1118,16 +1118,8 @@ class DragMaximizedNonTrackedWindowObserver } // aura::WindowObserver overrides: - // Counts number of times a window is reparented. Ignores reparenting into and - // from a docked container which is expected when a tab is dragged. virtual void OnWindowHierarchyChanged( const HierarchyChangeParams& params) OVERRIDE { - if ((params.old_parent->id() == kShellWindowId_DefaultContainer && - params.new_parent->id() == kShellWindowId_DockedContainer) || - (params.old_parent->id() == kShellWindowId_DockedContainer && - params.new_parent->id() == kShellWindowId_DefaultContainer)) { - return; - } change_count_++; } |