diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/ash/wm | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/ash/wm')
229 files changed, 0 insertions, 51891 deletions
diff --git a/chromium/ash/wm/always_on_top_controller.cc b/chromium/ash/wm/always_on_top_controller.cc deleted file mode 100644 index 44776feb313..00000000000 --- a/chromium/ash/wm/always_on_top_controller.cc +++ /dev/null @@ -1,72 +0,0 @@ -// 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/always_on_top_controller.h" - -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" - -namespace ash { -namespace internal { - -AlwaysOnTopController::AlwaysOnTopController() - : always_on_top_container_(NULL) { -} - -AlwaysOnTopController::~AlwaysOnTopController() { - if (always_on_top_container_) - always_on_top_container_->RemoveObserver(this); -} - -void AlwaysOnTopController::SetAlwaysOnTopContainer( - aura::Window* always_on_top_container) { - // Container should be empty. - DCHECK(always_on_top_container->children().empty()); - - // We are not handling any containers yet. - DCHECK(always_on_top_container_ == NULL); - - always_on_top_container_ = always_on_top_container; - always_on_top_container_->AddObserver(this); -} - -aura::Window* AlwaysOnTopController::GetContainer(aura::Window* window) const { - DCHECK(always_on_top_container_); - if (window->GetProperty(aura::client::kAlwaysOnTopKey)) - return always_on_top_container_; - return Shell::GetContainer(always_on_top_container_->GetRootWindow(), - kShellWindowId_DefaultContainer); -} - -void AlwaysOnTopController::OnWindowAdded(aura::Window* child) { - // Observe direct child of the containers. - if (child->parent() == always_on_top_container_) - child->AddObserver(this); -} - -void AlwaysOnTopController::OnWillRemoveWindow(aura::Window* child) { - child->RemoveObserver(this); -} - -void AlwaysOnTopController::OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) { - if (key == aura::client::kAlwaysOnTopKey) { - DCHECK(window->type() == aura::client::WINDOW_TYPE_NORMAL || - window->type() == aura::client::WINDOW_TYPE_POPUP); - aura::Window* container = GetContainer(window); - if (window->parent() != container) - container->AddChild(window); - } -} - -void AlwaysOnTopController::OnWindowDestroyed(aura::Window* window) { - if (window == always_on_top_container_) - always_on_top_container_ = NULL; -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/always_on_top_controller.h b/chromium/ash/wm/always_on_top_controller.h deleted file mode 100644 index 57fbf99e171..00000000000 --- a/chromium/ash/wm/always_on_top_controller.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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_ALWAYS_ON_TOP_CONTROLLER_H_ -#define ASH_WM_ALWAYS_ON_TOP_CONTROLLER_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/aura/window_observer.h" - -namespace aura { -class Window; -} - -namespace ash { -namespace internal { - -// AlwaysOnTopController puts window into proper containers based on its -// 'AlwaysOnTop' property. That is, putting a window into the worskpace -// container if its "AlwaysOnTop" property is false. Otherwise, put it in -// |always_on_top_container_|. -class AlwaysOnTopController : public aura::WindowObserver { - public: - AlwaysOnTopController(); - virtual ~AlwaysOnTopController(); - - // Sets the container for always on top windows. - void SetAlwaysOnTopContainer(aura::Window* always_on_top_container); - - // Gets container for given |window| based on its "AlwaysOnTop" property. - aura::Window* GetContainer(aura::Window* window) const; - - private: - // Overridden from aura::WindowObserver: - virtual void OnWindowAdded(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindow(aura::Window* child) OVERRIDE; - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE; - virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; - - aura::Window* always_on_top_container_; - - DISALLOW_COPY_AND_ASSIGN(AlwaysOnTopController); -}; - -} // namepsace internal -} // namepsace ash - -#endif // ASH_WM_ALWAYS_ON_TOP_CONTROLLER_H_ diff --git a/chromium/ash/wm/app_list_controller.cc b/chromium/ash/wm/app_list_controller.cc deleted file mode 100644 index 2f0ce0420f3..00000000000 --- a/chromium/ash/wm/app_list_controller.cc +++ /dev/null @@ -1,439 +0,0 @@ -// 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/app_list_controller.h" - -#include "ash/ash_switches.h" -#include "ash/launcher/launcher.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/shell_delegate.h" -#include "ash/shell_window_ids.h" -#include "base/command_line.h" -#include "ui/app_list/app_list_constants.h" -#include "ui/app_list/pagination_model.h" -#include "ui/app_list/views/app_list_view.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/events/event.h" -#include "ui/gfx/transform_util.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -namespace { - -// Duration for show/hide animation in milliseconds. -const int kAnimationDurationMs = 200; - -// Offset in pixels to animation away/towards the launcher. -const int kAnimationOffset = 8; - -// The maximum shift in pixels when over-scroll happens. -const int kMaxOverScrollShift = 48; - -// The minimal anchor position offset to make sure that the bubble is still on -// the screen with 8 pixels spacing on the left / right. This constant is a -// result of minimal bubble arrow sizes and offsets. -const int kMinimalAnchorPositionOffset = 57; - -ui::Layer* GetLayer(views::Widget* widget) { - return widget->GetNativeView()->layer(); -} - -// Gets arrow location based on shelf alignment. -views::BubbleBorder::Arrow GetBubbleArrow(aura::Window* window) { - DCHECK(Shell::HasInstance()); - return ShelfLayoutManager::ForLauncher(window)-> - SelectValueForShelfAlignment( - views::BubbleBorder::BOTTOM_CENTER, - views::BubbleBorder::LEFT_CENTER, - views::BubbleBorder::RIGHT_CENTER, - views::BubbleBorder::TOP_CENTER); -} - -// Offset given |rect| towards shelf. -gfx::Rect OffsetTowardsShelf(const gfx::Rect& rect, views::Widget* widget) { - DCHECK(Shell::HasInstance()); - ShelfAlignment shelf_alignment = Shell::GetInstance()->GetShelfAlignment( - widget->GetNativeView()->GetRootWindow()); - gfx::Rect offseted(rect); - switch (shelf_alignment) { - case SHELF_ALIGNMENT_BOTTOM: - offseted.Offset(0, kAnimationOffset); - break; - case SHELF_ALIGNMENT_LEFT: - offseted.Offset(-kAnimationOffset, 0); - break; - case SHELF_ALIGNMENT_RIGHT: - offseted.Offset(kAnimationOffset, 0); - break; - case SHELF_ALIGNMENT_TOP: - offseted.Offset(0, -kAnimationOffset); - break; - } - - return offseted; -} - -// Using |button_bounds|, determine the anchor offset so that the bubble gets -// shown above the shelf (used for the alternate shelf theme). -gfx::Vector2d GetAnchorPositionOffsetToShelf( - const gfx::Rect& button_bounds, views::Widget* widget) { - DCHECK(Shell::HasInstance()); - ShelfAlignment shelf_alignment = Shell::GetInstance()->GetShelfAlignment( - widget->GetNativeView()->GetRootWindow()); - gfx::Point anchor(button_bounds.CenterPoint()); - switch (shelf_alignment) { - case SHELF_ALIGNMENT_TOP: - case SHELF_ALIGNMENT_BOTTOM: - if (base::i18n::IsRTL()) { - int screen_width = widget->GetWorkAreaBoundsInScreen().width(); - return gfx::Vector2d( - std::min(screen_width - kMinimalAnchorPositionOffset - anchor.x(), - 0), 0); - } - return gfx::Vector2d( - std::max(kMinimalAnchorPositionOffset - anchor.x(), 0), 0); - case SHELF_ALIGNMENT_LEFT: - return gfx::Vector2d( - 0, std::max(kMinimalAnchorPositionOffset - anchor.y(), 0)); - case SHELF_ALIGNMENT_RIGHT: - return gfx::Vector2d( - 0, std::max(kMinimalAnchorPositionOffset - anchor.y(), 0)); - default: - NOTREACHED(); - return gfx::Vector2d(); - } -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// AppListController, public: - -AppListController::AppListController() - : pagination_model_(new app_list::PaginationModel), - is_visible_(false), - view_(NULL), - should_snap_back_(false) { - Shell::GetInstance()->AddShellObserver(this); - pagination_model_->AddObserver(this); -} - -AppListController::~AppListController() { - // Ensures app list view goes before the controller since pagination model - // lives in the controller and app list view would access it on destruction. - if (view_ && view_->GetWidget()) - view_->GetWidget()->CloseNow(); - - Shell::GetInstance()->RemoveShellObserver(this); - pagination_model_->RemoveObserver(this); -} - -void AppListController::SetVisible(bool visible, aura::Window* window) { - if (visible == is_visible_) - return; - - is_visible_ = visible; - - // App list needs to know the new shelf layout in order to calculate its - // UI layout when AppListView visibility changes. - Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()-> - UpdateAutoHideState(); - - if (view_) { - // Our widget is currently active. When the animation completes we'll hide - // the widget, changing activation. If a menu is shown before the animation - // completes then the activation change triggers the menu to close. By - // deactivating now we ensure there is no activation change when the - // animation completes and any menus stay open. - if (!visible) - view_->GetWidget()->Deactivate(); - ScheduleAnimation(); - } else if (is_visible_) { - // AppListModel and AppListViewDelegate are owned by AppListView. They - // will be released with AppListView on close. - app_list::AppListView* view = new app_list::AppListView( - Shell::GetInstance()->delegate()->CreateAppListViewDelegate()); - aura::Window* root_window = window->GetRootWindow(); - aura::Window* container = GetRootWindowController(root_window)-> - GetContainer(kShellWindowId_AppListContainer); - if (ash::switches::UseAlternateShelfLayout()) { - gfx::Rect applist_button_bounds = Launcher::ForWindow(container)-> - GetAppListButtonView()->GetBoundsInScreen(); - // We need the location of the button within the local screen. - applist_button_bounds = ash::ScreenAsh::ConvertRectFromScreen( - root_window, - applist_button_bounds); - view->InitAsBubbleAttachedToAnchor( - container, - pagination_model_.get(), - Launcher::ForWindow(container)->GetAppListButtonView(), - GetAnchorPositionOffsetToShelf(applist_button_bounds, - Launcher::ForWindow(container)->GetAppListButtonView()-> - GetWidget()), - GetBubbleArrow(container), - true /* border_accepts_events */); - view->SetArrowPaintType(views::BubbleBorder::PAINT_NONE); - } else { - view->InitAsBubbleAttachedToAnchor( - container, - pagination_model_.get(), - Launcher::ForWindow(container)->GetAppListButtonView(), - gfx::Vector2d(), - GetBubbleArrow(container), - true /* border_accepts_events */); - } - SetView(view); - // By setting us as DnD recipient, the app list knows that we can - // handle items. - if (!CommandLine::ForCurrentProcess()->HasSwitch( - ash::switches::kAshDisableDragAndDropAppListToLauncher)) { - SetDragAndDropHostOfCurrentAppList( - Launcher::ForWindow(window)->GetDragAndDropHostForAppList()); - } - } - // Update applist button status when app list visibility is changed. - Launcher::ForWindow(window)->GetAppListButtonView()->SchedulePaint(); -} - -bool AppListController::IsVisible() const { - return view_ && view_->GetWidget()->IsVisible(); -} - -aura::Window* AppListController::GetWindow() { - return is_visible_ && view_ ? view_->GetWidget()->GetNativeWindow() : NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -// AppListController, private: - -void AppListController::SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host) { - if (view_ && is_visible_) - view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); -} - -void AppListController::SetView(app_list::AppListView* view) { - DCHECK(view_ == NULL); - DCHECK(is_visible_); - - view_ = view; - views::Widget* widget = view_->GetWidget(); - widget->AddObserver(this); - Shell::GetInstance()->AddPreTargetHandler(this); - Launcher::ForWindow(widget->GetNativeWindow())->AddIconObserver(this); - widget->GetNativeView()->GetRootWindow()->AddObserver(this); - aura::client::GetFocusClient(widget->GetNativeView())->AddObserver(this); - - view_->ShowWhenReady(); -} - -void AppListController::ResetView() { - if (!view_) - return; - - views::Widget* widget = view_->GetWidget(); - widget->RemoveObserver(this); - GetLayer(widget)->GetAnimator()->RemoveObserver(this); - Shell::GetInstance()->RemovePreTargetHandler(this); - Launcher::ForWindow(widget->GetNativeWindow())->RemoveIconObserver(this); - widget->GetNativeView()->GetRootWindow()->RemoveObserver(this); - aura::client::GetFocusClient(widget->GetNativeView())->RemoveObserver(this); - view_ = NULL; -} - -void AppListController::ScheduleAnimation() { - // Stop observing previous animation. - StopObservingImplicitAnimations(); - - views::Widget* widget = view_->GetWidget(); - ui::Layer* layer = GetLayer(widget); - layer->GetAnimator()->StopAnimating(); - - gfx::Rect target_bounds; - if (is_visible_) { - target_bounds = widget->GetWindowBoundsInScreen(); - widget->SetBounds(OffsetTowardsShelf(target_bounds, widget)); - } else { - target_bounds = OffsetTowardsShelf(widget->GetWindowBoundsInScreen(), - widget); - } - - ui::ScopedLayerAnimationSettings animation(layer->GetAnimator()); - animation.SetTransitionDuration( - base::TimeDelta::FromMilliseconds( - is_visible_ ? 0 : kAnimationDurationMs)); - animation.AddObserver(this); - - layer->SetOpacity(is_visible_ ? 1.0 : 0.0); - widget->SetBounds(target_bounds); -} - -void AppListController::ProcessLocatedEvent(ui::LocatedEvent* event) { - // If the event happened on a menu, then the event should not close the app - // list. - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (target) { - RootWindowController* root_controller = - GetRootWindowController(target->GetRootWindow()); - if (root_controller) { - aura::Window* menu_container = root_controller->GetContainer( - ash::internal::kShellWindowId_MenuContainer); - if (menu_container->Contains(target)) - return; - aura::Window* keyboard_container = root_controller->GetContainer( - ash::internal::kShellWindowId_VirtualKeyboardContainer); - if (keyboard_container->Contains(target)) - return; - } - } - - if (view_ && is_visible_) { - aura::Window* window = view_->GetWidget()->GetNativeView(); - gfx::Point window_local_point(event->root_location()); - aura::Window::ConvertPointToTarget(window->GetRootWindow(), - window, - &window_local_point); - // Use HitTest to respect the hit test mask of the bubble. - if (!window->HitTest(window_local_point)) - SetVisible(false, window); - } -} - -void AppListController::UpdateBounds() { - if (view_ && is_visible_) - view_->UpdateBounds(); -} - -//////////////////////////////////////////////////////////////////////////////// -// AppListController, aura::EventFilter implementation: - -void AppListController::OnMouseEvent(ui::MouseEvent* event) { - if (event->type() == ui::ET_MOUSE_PRESSED) - ProcessLocatedEvent(event); -} - -void AppListController::OnGestureEvent(ui::GestureEvent* event) { - if (event->type() == ui::ET_GESTURE_TAP_DOWN) - ProcessLocatedEvent(event); -} - -//////////////////////////////////////////////////////////////////////////////// -// AppListController, aura::FocusObserver implementation: - -void AppListController::OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) { - if (view_ && is_visible_) { - aura::Window* applist_window = view_->GetWidget()->GetNativeView(); - aura::Window* applist_container = applist_window->parent(); - - if (applist_container->Contains(lost_focus) && - (!gained_focus || !applist_container->Contains(gained_focus))) { - SetVisible(false, applist_window); - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// AppListController, aura::WindowObserver implementation: -void AppListController::OnWindowBoundsChanged(aura::Window* root, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - UpdateBounds(); -} - -//////////////////////////////////////////////////////////////////////////////// -// AppListController, ui::ImplicitAnimationObserver implementation: - -void AppListController::OnImplicitAnimationsCompleted() { - if (is_visible_ ) - view_->GetWidget()->Activate(); - else - view_->GetWidget()->Close(); -} - -//////////////////////////////////////////////////////////////////////////////// -// AppListController, views::WidgetObserver implementation: - -void AppListController::OnWidgetDestroying(views::Widget* widget) { - DCHECK(view_->GetWidget() == widget); - if (is_visible_) - SetVisible(false, widget->GetNativeView()); - ResetView(); -} - -//////////////////////////////////////////////////////////////////////////////// -// AppListController, ShellObserver implementation: -void AppListController::OnShelfAlignmentChanged(aura::Window* root_window) { - if (view_) - view_->SetBubbleArrow(GetBubbleArrow(view_->GetWidget()->GetNativeView())); -} - -//////////////////////////////////////////////////////////////////////////////// -// AppListController, ShelfIconObserver implementation: - -void AppListController::OnShelfIconPositionsChanged() { - UpdateBounds(); -} - -//////////////////////////////////////////////////////////////////////////////// -// AppListController, PaginationModelObserver implementation: - -void AppListController::TotalPagesChanged() { -} - -void AppListController::SelectedPageChanged(int old_selected, - int new_selected) { -} - -void AppListController::TransitionStarted() { -} - -void AppListController::TransitionChanged() { - // |view_| could be NULL when app list is closed with a running transition. - if (!view_) - return; - - const app_list::PaginationModel::Transition& transition = - pagination_model_->transition(); - if (pagination_model_->is_valid_page(transition.target_page)) - return; - - views::Widget* widget = view_->GetWidget(); - ui::LayerAnimator* widget_animator = GetLayer(widget)->GetAnimator(); - if (!pagination_model_->IsRevertingCurrentTransition()) { - // Update cached |view_bounds_| if it is the first over-scroll move and - // widget does not have running animations. - if (!should_snap_back_ && !widget_animator->is_animating()) - view_bounds_ = widget->GetWindowBoundsInScreen(); - - const int current_page = pagination_model_->selected_page(); - const int dir = transition.target_page > current_page ? -1 : 1; - - const double progress = 1.0 - pow(1.0 - transition.progress, 4); - const int shift = kMaxOverScrollShift * progress * dir; - - gfx::Rect shifted(view_bounds_); - shifted.set_x(shifted.x() + shift); - widget->SetBounds(shifted); - should_snap_back_ = true; - } else if (should_snap_back_) { - should_snap_back_ = false; - ui::ScopedLayerAnimationSettings animation(widget_animator); - animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds( - app_list::kOverscrollPageTransitionDurationMs)); - widget->SetBounds(view_bounds_); - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/app_list_controller.h b/chromium/ash/wm/app_list_controller.h deleted file mode 100644 index 2e4175839ed..00000000000 --- a/chromium/ash/wm/app_list_controller.h +++ /dev/null @@ -1,145 +0,0 @@ -// 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_APP_LIST_CONTROLLER_H_ -#define ASH_WM_APP_LIST_CONTROLLER_H_ - -#include "ash/shelf/shelf_icon_observer.h" -#include "ash/shell_observer.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/timer/timer.h" -#include "ui/app_list/pagination_model_observer.h" -#include "ui/aura/client/focus_change_observer.h" -#include "ui/aura/window_observer.h" -#include "ui/compositor/layer_animation_observer.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/rect.h" -#include "ui/views/widget/widget_observer.h" - -namespace app_list { -class ApplicationDragAndDropHost; -class AppListView; -class PaginationModel; -} - -namespace ui { -class LocatedEvent; -} - -namespace ash { -namespace test { -class AppListControllerTestApi; -} - -namespace internal { - -// AppListController is a controller that manages app list UI for shell. -// It creates AppListView and schedules showing/hiding animation. -// While the UI is visible, it monitors things such as app list widget's -// activation state and desktop mouse click to auto dismiss the UI. -class AppListController : public ui::EventHandler, - public aura::client::FocusChangeObserver, - public aura::WindowObserver, - public ui::ImplicitAnimationObserver, - public views::WidgetObserver, - public ShellObserver, - public ShelfIconObserver, - public app_list::PaginationModelObserver { - public: - AppListController(); - virtual ~AppListController(); - - // Show/hide app list window. The |window| is used to deterime in - // which display (in which the |window| exists) the app list should - // be shown. - void SetVisible(bool visible, aura::Window* window); - - // Whether app list window is visible (shown or being shown). - bool IsVisible() const; - - // Returns target visibility. This differs from IsVisible() if an animation - // is ongoing. - bool GetTargetVisibility() const { return is_visible_; } - - // Returns app list window or NULL if it is not visible. - aura::Window* GetWindow(); - - // Returns app list view or NULL if it is not visible. - app_list::AppListView* GetView() { return view_; } - - private: - friend class test::AppListControllerTestApi; - - // If |drag_and_drop_host| is not NULL it will be called upon drag and drop - // operations outside the application list. - void SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host); - - // Sets the app list view and attempts to show it. - void SetView(app_list::AppListView* view); - - // Forgets the view. - void ResetView(); - - // Starts show/hide animation. - void ScheduleAnimation(); - - void ProcessLocatedEvent(ui::LocatedEvent* event); - - // Makes app list bubble update its bounds. - void UpdateBounds(); - - // ui::EventHandler overrides: - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - // aura::client::FocusChangeObserver overrides: - virtual void OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) OVERRIDE; - - // aura::WindowObserver overrides: - virtual void OnWindowBoundsChanged(aura::Window* root, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - - // ui::ImplicitAnimationObserver overrides: - virtual void OnImplicitAnimationsCompleted() OVERRIDE; - - // views::WidgetObserver overrides: - virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; - - // ShellObserver overrides: - virtual void OnShelfAlignmentChanged(aura::Window* root_window) OVERRIDE; - - // ShelfIconObserver overrides: - virtual void OnShelfIconPositionsChanged() OVERRIDE; - - // app_list::PaginationModelObserver overrides: - virtual void TotalPagesChanged() OVERRIDE; - virtual void SelectedPageChanged(int old_selected, int new_selected) OVERRIDE; - virtual void TransitionStarted() OVERRIDE; - virtual void TransitionChanged() OVERRIDE; - - scoped_ptr<app_list::PaginationModel> pagination_model_; - - // Whether we should show or hide app list widget. - bool is_visible_; - - // The AppListView this class manages, owned by its widget. - app_list::AppListView* view_; - - // Cached bounds of |view_| for snapping back animation after over-scroll. - gfx::Rect view_bounds_; - - // Whether should schedule snap back animation. - bool should_snap_back_; - - DISALLOW_COPY_AND_ASSIGN(AppListController); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_APP_LIST_CONTROLLER_H_ diff --git a/chromium/ash/wm/app_list_controller_unittest.cc b/chromium/ash/wm/app_list_controller_unittest.cc deleted file mode 100644 index 5d370489334..00000000000 --- a/chromium/ash/wm/app_list_controller_unittest.cc +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 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/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/test_shell_delegate.h" -#include "ash/wm/window_util.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" - -namespace ash { - -typedef test::AshTestBase AppListControllerTest; - -// Tests that app launcher hides when focus moves to a normal window. -TEST_F(AppListControllerTest, HideOnFocusOut) { - Shell::GetInstance()->ToggleAppList(NULL); - EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); - - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0)); - wm::ActivateWindow(window.get()); - - EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility()); -} - -// Tests that app launcher remains visible when focus is moved to a different -// window in kShellWindowId_AppListContainer. -TEST_F(AppListControllerTest, RemainVisibleWhenFocusingToApplistContainer) { - Shell::GetInstance()->ToggleAppList(NULL); - EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); - - aura::Window* applist_container = Shell::GetContainer( - Shell::GetPrimaryRootWindow(), - internal::kShellWindowId_AppListContainer); - scoped_ptr<aura::Window> window( - aura::test::CreateTestWindowWithId(0, applist_container)); - wm::ActivateWindow(window.get()); - - EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); -} - -} // namespace ash diff --git a/chromium/ash/wm/ash_focus_rules.cc b/chromium/ash/wm/ash_focus_rules.cc deleted file mode 100644 index 453436df730..00000000000 --- a/chromium/ash/wm/ash_focus_rules.cc +++ /dev/null @@ -1,168 +0,0 @@ -// 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/ash_focus_rules.h" - -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/window_state.h" -#include "ui/aura/window.h" - -namespace ash { -namespace wm { -namespace { - -// These are the list of container ids of containers which may contain windows -// that need to be activated in the order that they should be activated. -const int kWindowContainerIds[] = { - internal::kShellWindowId_OverlayContainer, - internal::kShellWindowId_LockSystemModalContainer, - internal::kShellWindowId_SettingBubbleContainer, - internal::kShellWindowId_LockScreenContainer, - internal::kShellWindowId_SystemModalContainer, - internal::kShellWindowId_AlwaysOnTopContainer, - internal::kShellWindowId_AppListContainer, - internal::kShellWindowId_DefaultContainer, - - // Docked, panel, launcher and status are intentionally checked after other - // containers even though these layers are higher. The user expects their - // windows to be focused before these elements. - internal::kShellWindowId_DockedContainer, - internal::kShellWindowId_PanelContainer, - internal::kShellWindowId_ShelfContainer, - internal::kShellWindowId_StatusContainer, -}; - -bool BelongsToContainerWithEqualOrGreaterId(const aura::Window* window, - int container_id) { - for (; window; window = window->parent()) { - if (window->id() >= container_id) - return true; - } - return false; -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// AshFocusRules, public: - -AshFocusRules::AshFocusRules() { -} - -AshFocusRules::~AshFocusRules() { -} - -//////////////////////////////////////////////////////////////////////////////// -// AshFocusRules, views::corewm::FocusRules: - -bool AshFocusRules::SupportsChildActivation(aura::Window* window) const { - if (window->id() == internal::kShellWindowId_DefaultContainer) - return true; - - for (size_t i = 0; i < arraysize(kWindowContainerIds); i++) { - if (window->id() == kWindowContainerIds[i]) - return true; - } - return false; -} - -bool AshFocusRules::IsWindowConsideredVisibleForActivation( - aura::Window* window) const { - if (BaseFocusRules::IsWindowConsideredVisibleForActivation(window)) - return true; - - // Minimized windows are hidden in their minimized state, but they can always - // be activated. - if (wm::GetWindowState(window)->IsMinimized()) - return true; - - return window->TargetVisibility() && (window->parent()->id() == - internal::kShellWindowId_DefaultContainer || window->parent()->id() == - internal::kShellWindowId_LockScreenContainer); -} - -bool AshFocusRules::CanActivateWindow(aura::Window* window) const { - // Clearing activation is always permissible. - if (!window) - return true; - - if (!BaseFocusRules::CanActivateWindow(window)) - return false; - - if (Shell::GetInstance()->IsSystemModalWindowOpen()) { - return BelongsToContainerWithEqualOrGreaterId( - window, internal::kShellWindowId_SystemModalContainer); - } - - return true; -} - -aura::Window* AshFocusRules::GetNextActivatableWindow( - aura::Window* ignore) const { - DCHECK(ignore); - - int starting_container_index = 0; - // If the container of the window losing focus is in the list, start from that - // container. - aura::Window* root = ignore->GetRootWindow(); - if (!root) - root = Shell::GetTargetRootWindow(); - int container_count = static_cast<int>(arraysize(kWindowContainerIds)); - for (int i = 0; ignore && i < container_count; i++) { - aura::Window* container = Shell::GetContainer(root, kWindowContainerIds[i]); - if (container && container->Contains(ignore)) { - starting_container_index = i; - break; - } - } - - // Look for windows to focus in |ignore|'s container. If none are found, we - // look in all the containers in front of |ignore|'s container, then all - // behind. - aura::Window* window = NULL; - for (int i = starting_container_index; !window && i < container_count; i++) - window = GetTopmostWindowToActivateForContainerIndex(i, ignore); - if (!window && starting_container_index > 0) { - for (int i = starting_container_index - 1; !window && i >= 0; i--) - window = GetTopmostWindowToActivateForContainerIndex(i, ignore); - } - return window; -} - -//////////////////////////////////////////////////////////////////////////////// -// AshFocusRules, private: - -aura::Window* AshFocusRules::GetTopmostWindowToActivateForContainerIndex( - int index, - aura::Window* ignore) const { - aura::Window* window = NULL; - aura::Window* root = ignore ? ignore->GetRootWindow() : NULL; - aura::Window::Windows containers = Shell::GetContainersFromAllRootWindows( - kWindowContainerIds[index], root); - for (aura::Window::Windows::const_iterator iter = containers.begin(); - iter != containers.end() && !window; ++iter) { - window = GetTopmostWindowToActivateInContainer((*iter), ignore); - } - return window; -} - -aura::Window* AshFocusRules::GetTopmostWindowToActivateInContainer( - aura::Window* container, - aura::Window* ignore) const { - for (aura::Window::Windows::const_reverse_iterator i = - container->children().rbegin(); - i != container->children().rend(); - ++i) { - WindowState* window_state = GetWindowState(*i); - if (*i != ignore && - window_state->CanActivate() && - !window_state->IsMinimized()) - return *i; - } - return NULL; -} - -} // namespace wm -} // namespace ash diff --git a/chromium/ash/wm/ash_focus_rules.h b/chromium/ash/wm/ash_focus_rules.h deleted file mode 100644 index f53a70b33a6..00000000000 --- a/chromium/ash/wm/ash_focus_rules.h +++ /dev/null @@ -1,43 +0,0 @@ -// 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_ASH_FOCUS_RULES_H_ -#define ASH_WM_ASH_FOCUS_RULES_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/views/corewm/base_focus_rules.h" - -namespace ash { -namespace wm { - -class ASH_EXPORT AshFocusRules : public views::corewm::BaseFocusRules { - public: - AshFocusRules(); - virtual ~AshFocusRules(); - - private: - // Overridden from views::corewm::BaseFocusRules: - virtual bool SupportsChildActivation(aura::Window* window) const OVERRIDE; - virtual bool IsWindowConsideredVisibleForActivation( - aura::Window* window) const OVERRIDE; - virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE; - virtual aura::Window* GetNextActivatableWindow( - aura::Window* ignore) const OVERRIDE; - - aura::Window* GetTopmostWindowToActivateForContainerIndex( - int index, - aura::Window* ignore) const; - aura::Window* GetTopmostWindowToActivateInContainer( - aura::Window* container, - aura::Window* ignore) const; - - DISALLOW_COPY_AND_ASSIGN(AshFocusRules); -}; - -} // namespace wm -} // namespace ash - -#endif // ASH_WM_ASH_FOCUS_RULES_H_ diff --git a/chromium/ash/wm/ash_native_cursor_manager.cc b/chromium/ash/wm/ash_native_cursor_manager.cc deleted file mode 100644 index d31579280d1..00000000000 --- a/chromium/ash/wm/ash_native_cursor_manager.cc +++ /dev/null @@ -1,135 +0,0 @@ -// 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/ash_native_cursor_manager.h" - -#include "ash/display/display_controller.h" -#include "ash/display/mirror_window_controller.h" -#include "ash/shell.h" -#include "ash/wm/image_cursors.h" -#include "base/logging.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/base/cursor/cursor.h" - -namespace ash { -namespace { - -void SetCursorOnAllRootWindows(gfx::NativeCursor cursor) { - aura::Window::Windows root_windows = - Shell::GetInstance()->GetAllRootWindows(); - for (aura::Window::Windows::iterator iter = root_windows.begin(); - iter != root_windows.end(); ++iter) - (*iter)->GetDispatcher()->SetCursor(cursor); -#if defined(OS_CHROMEOS) - Shell::GetInstance()->display_controller()-> - mirror_window_controller()->SetMirroredCursor(cursor); -#endif -} - -void NotifyCursorVisibilityChange(bool visible) { - aura::Window::Windows root_windows = - Shell::GetInstance()->GetAllRootWindows(); - for (aura::Window::Windows::iterator iter = root_windows.begin(); - iter != root_windows.end(); ++iter) - (*iter)->GetDispatcher()->OnCursorVisibilityChanged(visible); -#if defined(OS_CHROMEOS) - Shell::GetInstance()->display_controller()->mirror_window_controller()-> - SetMirroredCursorVisibility(visible); -#endif -} - -void NotifyMouseEventsEnableStateChange(bool enabled) { - aura::Window::Windows root_windows = - Shell::GetInstance()->GetAllRootWindows(); - for (aura::Window::Windows::iterator iter = root_windows.begin(); - iter != root_windows.end(); ++iter) - (*iter)->GetDispatcher()->OnMouseEventsEnableStateChanged(enabled); - // Mirror window never process events. -} - -} // namespace - -AshNativeCursorManager::AshNativeCursorManager() - : image_cursors_(new ImageCursors) { -} - -AshNativeCursorManager::~AshNativeCursorManager() { -} - -void AshNativeCursorManager::SetDisplay( - const gfx::Display& display, - views::corewm::NativeCursorManagerDelegate* delegate) { - if (image_cursors_->SetDisplay(display)) - SetCursor(delegate->GetCursor(), delegate); -} - -void AshNativeCursorManager::SetCursor( - gfx::NativeCursor cursor, - views::corewm::NativeCursorManagerDelegate* delegate) { - gfx::NativeCursor new_cursor = cursor; - image_cursors_->SetPlatformCursor(&new_cursor); - new_cursor.set_device_scale_factor( - image_cursors_->GetDisplay().device_scale_factor()); - - delegate->CommitCursor(new_cursor); - - if (delegate->IsCursorVisible()) - SetCursorOnAllRootWindows(new_cursor); -} - -void AshNativeCursorManager::SetCursorSet( - ui::CursorSetType cursor_set, - views::corewm::NativeCursorManagerDelegate* delegate) { - image_cursors_->SetCursorSet(cursor_set); - delegate->CommitCursorSet(cursor_set); - - // Sets the cursor to reflect the scale change immediately. - if (delegate->IsCursorVisible()) - SetCursor(delegate->GetCursor(), delegate); -} - -void AshNativeCursorManager::SetScale( - float scale, - views::corewm::NativeCursorManagerDelegate* delegate) { - image_cursors_->SetScale(scale); - delegate->CommitScale(scale); - - // Sets the cursor to reflect the scale change immediately. - SetCursor(delegate->GetCursor(), delegate); -} - -void AshNativeCursorManager::SetVisibility( - bool visible, - views::corewm::NativeCursorManagerDelegate* delegate) { - delegate->CommitVisibility(visible); - - if (visible) { - SetCursor(delegate->GetCursor(), delegate); - } else { - gfx::NativeCursor invisible_cursor(ui::kCursorNone); - image_cursors_->SetPlatformCursor(&invisible_cursor); - SetCursorOnAllRootWindows(invisible_cursor); - } - - NotifyCursorVisibilityChange(visible); -} - -void AshNativeCursorManager::SetMouseEventsEnabled( - bool enabled, - views::corewm::NativeCursorManagerDelegate* delegate) { - delegate->CommitMouseEventsEnabled(enabled); - - if (enabled) { - aura::Env::GetInstance()->set_last_mouse_location( - disabled_cursor_location_); - } else { - disabled_cursor_location_ = aura::Env::GetInstance()->last_mouse_location(); - } - - SetVisibility(delegate->IsCursorVisible(), delegate); - NotifyMouseEventsEnableStateChange(enabled); -} - -} // namespace ash diff --git a/chromium/ash/wm/ash_native_cursor_manager.h b/chromium/ash/wm/ash_native_cursor_manager.h deleted file mode 100644 index f307b1663d7..00000000000 --- a/chromium/ash/wm/ash_native_cursor_manager.h +++ /dev/null @@ -1,69 +0,0 @@ -// 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_ASH_NATIVE_CURSOR_MANAGER_H_ -#define ASH_WM_ASH_NATIVE_CURSOR_MANAGER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string16.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gfx/point.h" -#include "ui/views/corewm/native_cursor_manager.h" -#include "ui/views/corewm/native_cursor_manager_delegate.h" - -namespace ash { - -namespace test { -class CursorManagerTestApi; -} - -class ImageCursors; - -// This does the ash-specific setting of cursor details like cursor -// visibility. It communicates back with the CursorManager through the -// NativeCursorManagerDelegate interface, which receives messages about what -// changes were acted on. -class ASH_EXPORT AshNativeCursorManager - : public views::corewm::NativeCursorManager { - public: - AshNativeCursorManager(); - virtual ~AshNativeCursorManager(); - - private: - friend class test::CursorManagerTestApi; - - // Overridden from views::corewm::NativeCursorManager: - virtual void SetDisplay( - const gfx::Display& display, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; - virtual void SetCursor( - gfx::NativeCursor cursor, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; - virtual void SetVisibility( - bool visible, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; - virtual void SetScale( - float scale, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; - virtual void SetCursorSet( - ui::CursorSetType cursor_set, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; - virtual void SetMouseEventsEnabled( - bool enabled, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; - - // The cursor location where the cursor was disabled. - gfx::Point disabled_cursor_location_; - - scoped_ptr<ImageCursors> image_cursors_; - - DISALLOW_COPY_AND_ASSIGN(AshNativeCursorManager); -}; - -} // namespace ash - -#endif // ASH_WM_ASH_NATIVE_CURSOR_MANAGER_H_ diff --git a/chromium/ash/wm/ash_native_cursor_manager_interactive_uitest.cc b/chromium/ash/wm/ash_native_cursor_manager_interactive_uitest.cc deleted file mode 100644 index 19e3bc4e04b..00000000000 --- a/chromium/ash/wm/ash_native_cursor_manager_interactive_uitest.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2013 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/ash_native_cursor_manager.h" - -#include "ash/display/display_info.h" -#include "ash/display/display_manager.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/cursor_manager_test_api.h" -#include "base/run_loop.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/base/test/ui_controls.h" - -#if defined(USE_X11) -#include <X11/Xlib.h> - -#include "base/message_loop/message_pump_x11.h" -#endif - -namespace ash { - -using views::corewm::CursorManager; -typedef test::AshTestBase AshNativeCursorManagerTest; - -namespace { - -internal::DisplayInfo CreateDisplayInfo(int64 id, - const gfx::Rect& bounds, - float device_scale_factor) { - internal::DisplayInfo info(id, "", false); - info.SetBounds(bounds); - info.set_device_scale_factor(device_scale_factor); - return info; -} - -void MoveMouseSync(aura::Window* window, int x, int y) { -#if defined(USE_X11) - XWarpPointer(base::MessagePumpX11::GetDefaultXDisplay(), - None, - window->GetDispatcher()->host()->GetAcceleratedWidget(), - 0, 0, 0, 0, - x, y); -#endif - // Send and wait for a key event to make sure that mouse - // events are fully processed. - base::RunLoop loop; - ui_controls::SendKeyPressNotifyWhenDone( - window, - ui::VKEY_SPACE, - false, - false, - false, - false, - loop.QuitClosure()); - loop.Run(); -} - -} // namespace - -#if defined(USE_X11) -#define MAYBE_CursorChangeOnEnterNotify CursorChangeOnEnterNotify -#else -#define MAYBE_CursorChangeOnEnterNotify DISABLED_CursorChangeOnEnterNotify -#endif - -TEST_F(AshNativeCursorManagerTest, MAYBE_CursorChangeOnEnterNotify) { - CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager(); - test::CursorManagerTestApi test_api(cursor_manager); - - internal::DisplayManager* display_manager = - Shell::GetInstance()->display_manager(); - internal::DisplayInfo display_info1 = - CreateDisplayInfo(10, gfx::Rect(0, 0, 500, 300), 1.0f); - internal::DisplayInfo display_info2 = - CreateDisplayInfo(20, gfx::Rect(500, 0, 500, 300), 2.0f); - std::vector<internal::DisplayInfo> display_info_list; - display_info_list.push_back(display_info1); - display_info_list.push_back(display_info2); - display_manager->OnNativeDisplaysChanged(display_info_list); - - MoveMouseSync(Shell::GetAllRootWindows()[0], 10, 10); - EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); - - MoveMouseSync(Shell::GetAllRootWindows()[0], 600, 10); - EXPECT_EQ(2.0f, test_api.GetDisplay().device_scale_factor()); -} - -} // namespace ash diff --git a/chromium/ash/wm/ash_native_cursor_manager_unittest.cc b/chromium/ash/wm/ash_native_cursor_manager_unittest.cc deleted file mode 100644 index 6ca1bf2b3ec..00000000000 --- a/chromium/ash/wm/ash_native_cursor_manager_unittest.cc +++ /dev/null @@ -1,206 +0,0 @@ -// 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/ash_native_cursor_manager.h" - -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/cursor_manager_test_api.h" -#include "ash/wm/image_cursors.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/gfx/screen.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#include "ui/base/cursor/cursor_loader_win.h" -#endif - -using views::corewm::CursorManager; - -namespace ash { -namespace test { - -namespace { - -// A delegate for recording a mouse event location. -class MouseEventLocationDelegate : public aura::test::TestWindowDelegate { - public: - MouseEventLocationDelegate() {} - virtual ~MouseEventLocationDelegate() {} - - gfx::Point GetMouseEventLocationAndReset() { - gfx::Point p = mouse_event_location_; - mouse_event_location_.SetPoint(-100, -100); - return p; - } - - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { - mouse_event_location_ = event->location(); - event->SetHandled(); - } - - private: - gfx::Point mouse_event_location_; - - DISALLOW_COPY_AND_ASSIGN(MouseEventLocationDelegate); -}; - -} // namespace - -typedef test::AshTestBase AshNativeCursorManagerTest; - -TEST_F(AshNativeCursorManagerTest, LockCursor) { - CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager(); - CursorManagerTestApi test_api(cursor_manager); - gfx::Display display(0); -#if defined(OS_WIN) - ui::CursorLoaderWin::SetCursorResourceModule(L"ash_unittests.exe"); -#endif - cursor_manager->SetCursor(ui::kCursorCopy); - EXPECT_EQ(ui::kCursorCopy, test_api.GetCurrentCursor().native_type()); - display.set_device_scale_factor(2.0f); - display.set_rotation(gfx::Display::ROTATE_90); - cursor_manager->SetScale(2.5f); - cursor_manager->SetDisplay(display); - EXPECT_EQ(2.5f, test_api.GetCurrentScale()); - EXPECT_EQ(2.0f, test_api.GetDisplay().device_scale_factor()); - EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet()); - EXPECT_EQ(gfx::Display::ROTATE_90, test_api.GetDisplay().rotation()); - EXPECT_TRUE(test_api.GetCurrentCursor().platform()); - - cursor_manager->LockCursor(); - EXPECT_TRUE(cursor_manager->IsCursorLocked()); - - // Cursor type does not change while cursor is locked. - EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet()); - cursor_manager->SetCursorSet(ui::CURSOR_SET_NORMAL); - EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet()); - cursor_manager->SetCursorSet(ui::CURSOR_SET_LARGE); - EXPECT_EQ(ui::CURSOR_SET_LARGE, test_api.GetCurrentCursorSet()); - cursor_manager->SetCursorSet(ui::CURSOR_SET_NORMAL); - EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet()); - - // Cusror scale does change even while cursor is locked. - EXPECT_EQ(2.5f, test_api.GetCurrentScale()); - cursor_manager->SetScale(1.f); - EXPECT_EQ(1.f, test_api.GetCurrentScale()); - cursor_manager->SetScale(1.5f); - EXPECT_EQ(1.5f, test_api.GetCurrentScale()); - - // Cursor type does not change while cursor is locked. - cursor_manager->SetCursor(ui::kCursorPointer); - EXPECT_EQ(ui::kCursorCopy, test_api.GetCurrentCursor().native_type()); - - // Device scale factor and rotation do change even while cursor is locked. - display.set_device_scale_factor(1.0f); - display.set_rotation(gfx::Display::ROTATE_180); - cursor_manager->SetDisplay(display); - EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); - EXPECT_EQ(gfx::Display::ROTATE_180, test_api.GetDisplay().rotation()); - - cursor_manager->UnlockCursor(); - EXPECT_FALSE(cursor_manager->IsCursorLocked()); - - // Cursor type changes to the one specified while cursor is locked. - EXPECT_EQ(1.5f, test_api.GetCurrentScale()); - EXPECT_EQ(ui::kCursorPointer, test_api.GetCurrentCursor().native_type()); - EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); - EXPECT_TRUE(test_api.GetCurrentCursor().platform()); -} - -TEST_F(AshNativeCursorManagerTest, SetCursor) { - CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager(); - CursorManagerTestApi test_api(cursor_manager); -#if defined(OS_WIN) - ui::CursorLoaderWin::SetCursorResourceModule(L"ash_unittests.exe"); -#endif - cursor_manager->SetCursor(ui::kCursorCopy); - EXPECT_EQ(ui::kCursorCopy, test_api.GetCurrentCursor().native_type()); - EXPECT_TRUE(test_api.GetCurrentCursor().platform()); - cursor_manager->SetCursor(ui::kCursorPointer); - EXPECT_EQ(ui::kCursorPointer, test_api.GetCurrentCursor().native_type()); - EXPECT_TRUE(test_api.GetCurrentCursor().platform()); -} - -TEST_F(AshNativeCursorManagerTest, SetCursorSet) { - CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager(); - CursorManagerTestApi test_api(cursor_manager); - - EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet()); - - cursor_manager->SetCursorSet(ui::CURSOR_SET_NORMAL); - EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet()); - - cursor_manager->SetCursorSet(ui::CURSOR_SET_LARGE); - EXPECT_EQ(ui::CURSOR_SET_LARGE, test_api.GetCurrentCursorSet()); - - cursor_manager->SetCursorSet(ui::CURSOR_SET_NORMAL); - EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet()); -} - -TEST_F(AshNativeCursorManagerTest, SetScale) { - CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager(); - CursorManagerTestApi test_api(cursor_manager); - - EXPECT_EQ(1.f, test_api.GetCurrentScale()); - - cursor_manager->SetScale(2.5f); - EXPECT_EQ(2.5f, test_api.GetCurrentScale()); - - cursor_manager->SetScale(1.f); - EXPECT_EQ(1.f, test_api.GetCurrentScale()); -} - -TEST_F(AshNativeCursorManagerTest, SetDeviceScaleFactorAndRotation) { - CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager(); - CursorManagerTestApi test_api(cursor_manager); - - gfx::Display display(0); - display.set_device_scale_factor(2.0f); - cursor_manager->SetDisplay(display); - EXPECT_EQ(2.0f, test_api.GetDisplay().device_scale_factor()); - EXPECT_EQ(gfx::Display::ROTATE_0, test_api.GetDisplay().rotation()); - - display.set_device_scale_factor(1.0f); - display.set_rotation(gfx::Display::ROTATE_270); - cursor_manager->SetDisplay(display); - EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); - EXPECT_EQ(gfx::Display::ROTATE_270, test_api.GetDisplay().rotation()); -} - -TEST_F(AshNativeCursorManagerTest, DisabledQueryMouseLocation) { - aura::Window* root_window = Shell::GetInstance()->GetPrimaryRootWindow(); -#if defined(OS_WIN) - if (base::win::GetVersion() < base::win::VERSION_WIN8) - return; - // On Windows 8 the ASH environment has two processes, the viewer process - // which runs in Windows 8 mode and the browser process. The initialization - // happens when the viewer process connects to the browser channel and sends - // the initial IPC message. - RunAllPendingInMessageLoop(); -#endif - root_window->MoveCursorTo(gfx::Point(10, 10)); -#if defined(OS_WIN) - // The MoveCursor operation on Windows 8 is implemented in the viewer process - // which is notified by an IPC message to perform the MoveCursor operation. - // We need to ensure that the IPC is delivered to the viewer process and it - // the ACK is sent back from the viewer indicating that the operation - // completed. - Sleep(100); - RunAllPendingInMessageLoop(); -#endif - aura::WindowEventDispatcher* dispatcher = root_window->GetDispatcher(); - gfx::Point mouse_location; - EXPECT_TRUE(dispatcher->host()->QueryMouseLocation(&mouse_location)); - EXPECT_EQ("10,10", mouse_location.ToString()); - Shell::GetInstance()->cursor_manager()->DisableMouseEvents(); - EXPECT_FALSE(dispatcher->host()->QueryMouseLocation(&mouse_location)); - EXPECT_EQ("0,0", mouse_location.ToString()); -} - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/base_layout_manager.cc b/chromium/ash/wm/base_layout_manager.cc deleted file mode 100644 index 5070654ae8d..00000000000 --- a/chromium/ash/wm/base_layout_manager.cc +++ /dev/null @@ -1,281 +0,0 @@ -// 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/base_layout_manager.h" - -#include "ash/screen_ash.h" -#include "ash/session_state_delegate.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_properties.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/workspace_window_resizer.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/base/ui_base_types.h" -#include "ui/compositor/layer.h" -#include "ui/gfx/screen.h" -#include "ui/views/corewm/corewm_switches.h" -#include "ui/views/corewm/window_util.h" - -namespace ash { -namespace internal { - -///////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, public: - -BaseLayoutManager::BaseLayoutManager(aura::Window* root_window) - : root_window_(root_window) { - Shell::GetInstance()->activation_client()->AddObserver(this); - Shell::GetInstance()->AddShellObserver(this); - root_window_->AddObserver(this); -} - -BaseLayoutManager::~BaseLayoutManager() { - if (root_window_) - root_window_->RemoveObserver(this); - for (WindowSet::const_iterator i = windows_.begin(); i != windows_.end(); ++i) - (*i)->RemoveObserver(this); - Shell::GetInstance()->RemoveShellObserver(this); - Shell::GetInstance()->activation_client()->RemoveObserver(this); -} - -// static -gfx::Rect BaseLayoutManager::BoundsWithScreenEdgeVisible( - aura::Window* window, - const gfx::Rect& restore_bounds) { - gfx::Rect max_bounds = - ash::ScreenAsh::GetMaximizedWindowBoundsInParent(window); - // If the restore_bounds are more than 1 grid step away from the size the - // window would be when maximized, inset it. - max_bounds.Inset(ash::internal::WorkspaceWindowResizer::kScreenEdgeInset, - ash::internal::WorkspaceWindowResizer::kScreenEdgeInset); - if (restore_bounds.Contains(max_bounds)) - return max_bounds; - return restore_bounds; -} - -///////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, aura::LayoutManager overrides: - -void BaseLayoutManager::OnWindowResized() { -} - -void BaseLayoutManager::OnWindowAddedToLayout(aura::Window* child) { - windows_.insert(child); - child->AddObserver(this); - wm::WindowState* window_state = wm::GetWindowState(child); - window_state->AddObserver(this); - - // Only update the bounds if the window has a show state that depends on the - // workspace area. - if (window_state->IsMaximizedOrFullscreen()) - UpdateBoundsFromShowState(window_state); -} - -void BaseLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { - windows_.erase(child); - child->RemoveObserver(this); - wm::GetWindowState(child)->RemoveObserver(this); -} - -void BaseLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { -} - -void BaseLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) { - wm::WindowState* window_state = wm::GetWindowState(child); - // Attempting to show a minimized window. Unminimize it. - if (visible && window_state->IsMinimized()) - window_state->Unminimize(); -} - -void BaseLayoutManager::SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) { - gfx::Rect child_bounds(requested_bounds); - wm::WindowState* window_state = wm::GetWindowState(child); - // Some windows rely on this to set their initial bounds. - if (window_state->IsMaximized()) - child_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent(child); - else if (window_state->IsFullscreen()) - child_bounds = ScreenAsh::GetDisplayBoundsInParent(child); - SetChildBoundsDirect(child, child_bounds); -} - -///////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, aura::WindowObserver overrides: - -void BaseLayoutManager::OnWindowDestroying(aura::Window* window) { - if (root_window_ == window) { - root_window_->RemoveObserver(this); - root_window_ = NULL; - } -} - -void BaseLayoutManager::OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - if (root_window_ == window) - AdjustAllWindowsBoundsForWorkAreaChange(ADJUST_WINDOW_DISPLAY_SIZE_CHANGED); -} - -////////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, aura::client::ActivationChangeObserver implementation: - -void BaseLayoutManager::OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) { - wm::WindowState* window_state = wm::GetWindowState(gained_active); - if (window_state && window_state->IsMinimized() && - !gained_active->IsVisible()) { - window_state->Unminimize(); - DCHECK(!window_state->IsMinimized()); - } -} - -///////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, ash::ShellObserver overrides: - -void BaseLayoutManager::OnDisplayWorkAreaInsetsChanged() { - AdjustAllWindowsBoundsForWorkAreaChange( - ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED); -} - -///////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, ash::wm::WindowStateObserver overrides: - -void BaseLayoutManager::OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType old_type) { - ui::WindowShowState old_state = ToWindowShowState(old_type); - ui::WindowShowState new_state = window_state->GetShowState(); - - if (old_state != new_state && old_state != ui::SHOW_STATE_MINIMIZED && - !window_state->HasRestoreBounds() && - ((new_state == ui::SHOW_STATE_MAXIMIZED && - old_state != ui::SHOW_STATE_FULLSCREEN) || - (new_state == ui::SHOW_STATE_FULLSCREEN && - old_state != ui::SHOW_STATE_MAXIMIZED))) { - window_state->SetRestoreBoundsInParent(window_state->window()->bounds()); - } - - UpdateBoundsFromShowState(window_state); - ShowStateChanged(window_state, old_state); -} - -////////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, protected: - -void BaseLayoutManager::ShowStateChanged( - wm::WindowState* window_state, - ui::WindowShowState last_show_state) { - if (window_state->IsMinimized()) { - if (last_show_state == ui::SHOW_STATE_MINIMIZED) - return; - - // Save the previous show state so that we can correctly restore it. - window_state->window()->SetProperty(aura::client::kRestoreShowStateKey, - last_show_state); - views::corewm::SetWindowVisibilityAnimationType( - window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); - - // Hide the window. - window_state->window()->Hide(); - // Activate another window. - if (window_state->IsActive()) - window_state->Deactivate(); - } else if ((window_state->window()->TargetVisibility() || - last_show_state == ui::SHOW_STATE_MINIMIZED) && - !window_state->window()->layer()->visible()) { - // The layer may be hidden if the window was previously minimized. Make - // sure it's visible. - window_state->window()->Show(); - if (last_show_state == ui::SHOW_STATE_MINIMIZED && - !window_state->IsMaximizedOrFullscreen()) { - window_state->set_always_restores_to_restore_bounds(false); - } - } -} - -void BaseLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange( - AdjustWindowReason reason) { - // Don't do any adjustments of the insets while we are in screen locked mode. - // This would happen if the launcher was auto hidden before the login screen - // was shown and then gets shown when the login screen gets presented. - if (reason == ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED && - Shell::GetInstance()->session_state_delegate()->IsScreenLocked()) - return; - - // If a user plugs an external display into a laptop running Aura the - // display size will change. Maximized windows need to resize to match. - // We also do this when developers running Aura on a desktop manually resize - // the host window. - // We also need to do this when the work area insets changes. - for (WindowSet::const_iterator it = windows_.begin(); - it != windows_.end(); - ++it) { - AdjustWindowBoundsForWorkAreaChange(wm::GetWindowState(*it), reason); - } -} - -void BaseLayoutManager::AdjustWindowBoundsForWorkAreaChange( - wm::WindowState* window_state, - AdjustWindowReason reason) { - aura::Window* window = window_state->window(); - if (window_state->IsMaximized()) { - SetChildBoundsDirect( - window, ScreenAsh::GetMaximizedWindowBoundsInParent(window)); - } else if (window_state->IsFullscreen()) { - SetChildBoundsDirect( - window, ScreenAsh::GetDisplayBoundsInParent(window)); - } else { - // The work area may be smaller than the full screen. - gfx::Rect display_rect = - ScreenAsh::GetDisplayWorkAreaBoundsInParent(window); - // Put as much of the window as possible within the display area. - gfx::Rect bounds = window->bounds(); - bounds.AdjustToFit(display_rect); - window->SetBounds(bounds); - } -} - -////////////////////////////////////////////////////////////////////////////// -// BaseLayoutManager, private: - -void BaseLayoutManager::UpdateBoundsFromShowState( - wm::WindowState* window_state) { - aura::Window* window = window_state->window(); - switch (window_state->GetShowState()) { - case ui::SHOW_STATE_DEFAULT: - case ui::SHOW_STATE_NORMAL: { - if (window_state->HasRestoreBounds()) { - gfx::Rect bounds_in_parent = window_state->GetRestoreBoundsInParent(); - SetChildBoundsDirect(window, - BoundsWithScreenEdgeVisible(window, - bounds_in_parent)); - } - window_state->ClearRestoreBounds(); - break; - } - - case ui::SHOW_STATE_MAXIMIZED: - SetChildBoundsDirect( - window, ScreenAsh::GetMaximizedWindowBoundsInParent(window)); - break; - - case ui::SHOW_STATE_FULLSCREEN: - // Don't animate the full-screen window transition. - // TODO(jamescook): Use animation here. Be sure the lock screen works. - SetChildBoundsDirect(window, - ScreenAsh::GetDisplayBoundsInParent(window)); - break; - - default: - break; - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/base_layout_manager.h b/chromium/ash/wm/base_layout_manager.h deleted file mode 100644 index 6f74e4c8f94..00000000000 --- a/chromium/ash/wm/base_layout_manager.h +++ /dev/null @@ -1,128 +0,0 @@ -// 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_BASE_LAYOUT_MANAGER_H_ -#define ASH_WM_BASE_LAYOUT_MANAGER_H_ - -#include <set> - -#include "ash/ash_export.h" -#include "ash/shell_observer.h" -#include "ash/wm/window_state_observer.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/aura/client/activation_change_observer.h" -#include "ui/aura/layout_manager.h" -#include "ui/aura/window_observer.h" -#include "ui/base/ui_base_types.h" -#include "ui/events/event_handler.h" - -namespace aura { -class Window; -} - -namespace ash { -namespace wm { -class WindowState; -} - -namespace internal { - -// BaseLayoutManager is the simplest possible implementation for a window -// layout manager. It listens for changes to kShowStateKey and resizes the -// window appropriately. Subclasses should be sure to invoke the base class -// for adding and removing windows, otherwise show state will not be tracked -// properly. -class ASH_EXPORT BaseLayoutManager - : public aura::LayoutManager, - public aura::WindowObserver, - public aura::client::ActivationChangeObserver, - public ShellObserver, - public wm::WindowStateObserver { - public: - typedef std::set<aura::Window*> WindowSet; - - explicit BaseLayoutManager(aura::Window* root_window); - virtual ~BaseLayoutManager(); - - const WindowSet& windows() const { return windows_; } - - // Given a |window| and tentative |restore_bounds|, returns new bounds that - // ensure that at least a few pixels of the screen background are visible - // outside the edges of the window. - static gfx::Rect BoundsWithScreenEdgeVisible(aura::Window* window, - const gfx::Rect& restore_bounds); - - // aura::LayoutManager overrides: - virtual void OnWindowResized() OVERRIDE; - virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; - virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; - virtual void OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) OVERRIDE; - virtual void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) OVERRIDE; - - // aura::WindowObserver overrides: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - virtual void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - - // aura::client::ActivationChangeObserver overrides: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE; - - // ash::ShellObserver overrides: - virtual void OnDisplayWorkAreaInsetsChanged() OVERRIDE; - - // wm::WindowStateObserver overrides: - virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType type) OVERRIDE; - - protected: - enum AdjustWindowReason { - ADJUST_WINDOW_DISPLAY_SIZE_CHANGED, - ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED, - }; - - // Invoked from OnWindowPropertyChanged() if |kShowStateKey| changes. - virtual void ShowStateChanged(wm::WindowState* window_state, - ui::WindowShowState last_show_state); - - // Adjusts the window's bounds when the display area changes for given - // window. This happens when the display size, work area insets or - // the display on which the window exists has changed. - // If this is called for a display size change (i.e. |reason| - // is ADJUST_WINDOW_DISPLAY_SIZE_CHANGED), the non-maximized/non-fullscreen - // windows are readjusted to make sure the window is completely within the - // display region. Otherwise, it makes sure at least some parts of the window - // is on display. - virtual void AdjustAllWindowsBoundsForWorkAreaChange( - AdjustWindowReason reason); - - // Adjusts the sizes of the specific window in respond to a screen change or - // display-area size change. - virtual void AdjustWindowBoundsForWorkAreaChange( - wm::WindowState* window_state, - AdjustWindowReason reason); - - aura::Window* root_window() { return root_window_; } - - private: - // Update window bounds based on a change in show state. - void UpdateBoundsFromShowState(wm::WindowState* controller); - - // Set of windows we're listening to. - WindowSet windows_; - - aura::Window* root_window_; - - DISALLOW_COPY_AND_ASSIGN(BaseLayoutManager); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_BASE_LAYOUT_MANAGER_H_ diff --git a/chromium/ash/wm/base_layout_manager_unittest.cc b/chromium/ash/wm/base_layout_manager_unittest.cc deleted file mode 100644 index 9f4b9ed12fe..00000000000 --- a/chromium/ash/wm/base_layout_manager_unittest.cc +++ /dev/null @@ -1,313 +0,0 @@ -// 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/base_layout_manager.h" - -#include "ash/screen_ash.h" -#include "ash/session_state_delegate.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/workspace_window_resizer.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/base/ui_base_types.h" -#include "ui/gfx/insets.h" -#include "ui/gfx/screen.h" - -namespace ash { - -namespace { - -class BaseLayoutManagerTest : public test::AshTestBase { - public: - BaseLayoutManagerTest() {} - virtual ~BaseLayoutManagerTest() {} - - virtual void SetUp() OVERRIDE { - test::AshTestBase::SetUp(); - UpdateDisplay("800x600"); - aura::Window* default_container = Shell::GetContainer( - Shell::GetPrimaryRootWindow(), - internal::kShellWindowId_DefaultContainer); - default_container->SetLayoutManager(new internal::BaseLayoutManager( - Shell::GetPrimaryRootWindow())); - } - - aura::Window* CreateTestWindow(const gfx::Rect& bounds) { - return CreateTestWindowInShellWithBounds(bounds); - } - - private: - DISALLOW_COPY_AND_ASSIGN(BaseLayoutManagerTest); -}; - -// Tests normal->maximize->normal. -TEST_F(BaseLayoutManagerTest, Maximize) { - gfx::Rect bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - // Maximized window fills the work area, not the whole display. - EXPECT_EQ( - ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), - window->bounds().ToString()); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); -} - -// Tests normal->minimize->normal. -TEST_F(BaseLayoutManagerTest, Minimize) { - gfx::Rect bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - // Note: Currently minimize doesn't do anything except set the state. - // See crbug.com/104571. - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); -} - -// A WindowDelegate which sets the focus when the window -// becomes visible. -class FocusDelegate : public aura::test::TestWindowDelegate { - public: - FocusDelegate() - : window_(NULL), - show_state_(ui::SHOW_STATE_END) { - } - virtual ~FocusDelegate() {} - - void set_window(aura::Window* window) { window_ = window; } - - // aura::test::TestWindowDelegate overrides: - virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE { - if (window_) { - if (visible) - window_->Focus(); - show_state_ = window_->GetProperty(aura::client::kShowStateKey); - } - } - - ui::WindowShowState GetShowStateAndReset() { - ui::WindowShowState ret = show_state_; - show_state_ = ui::SHOW_STATE_END; - return ret; - } - - private: - aura::Window* window_; - ui::WindowShowState show_state_; - - DISALLOW_COPY_AND_ASSIGN(FocusDelegate); -}; - -// Make sure that the window's show state is correct in -// |WindowDelegate::OnWindowTargetVisibilityChanged|, and setting -// focus in this callback doesn't cause DCHECK error. See -// crbug.com/168383. -TEST_F(BaseLayoutManagerTest, FocusDuringUnminimize) { - FocusDelegate delegate; - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate( - &delegate, 0, gfx::Rect(100, 100, 100, 100))); - delegate.set_window(window.get()); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - EXPECT_FALSE(window->IsVisible()); - EXPECT_EQ(ui::SHOW_STATE_MINIMIZED, delegate.GetShowStateAndReset()); - window->Show(); - EXPECT_TRUE(window->IsVisible()); - EXPECT_EQ(ui::SHOW_STATE_DEFAULT, delegate.GetShowStateAndReset()); -} - -// Tests maximized window size during root window resize. -TEST_F(BaseLayoutManagerTest, MaximizeRootWindowResize) { - gfx::Rect bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - gfx::Rect initial_work_area_bounds = - ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()); - EXPECT_EQ(initial_work_area_bounds.ToString(), window->bounds().ToString()); - // Enlarge the root window. We should still match the work area size. - UpdateDisplay("900x700"); - EXPECT_EQ( - ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), - window->bounds().ToString()); - EXPECT_NE( - initial_work_area_bounds.ToString(), - ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString()); -} - -// Tests normal->fullscreen->normal. -TEST_F(BaseLayoutManagerTest, Fullscreen) { - gfx::Rect bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - // Fullscreen window fills the whole display. - EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).bounds().ToString(), - window->bounds().ToString()); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); -} - -// Tests fullscreen window size during root window resize. -TEST_F(BaseLayoutManagerTest, FullscreenRootWindowResize) { - gfx::Rect bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - // Fullscreen window fills the whole display. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).bounds().ToString(), - window->bounds().ToString()); - // Enlarge the root window. We should still match the display size. - UpdateDisplay("800x600"); - EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).bounds().ToString(), - window->bounds().ToString()); -} - -// Tests that when the screen gets smaller the windows aren't bigger than -// the screen. -TEST_F(BaseLayoutManagerTest, RootWindowResizeShrinksWindows) { - scoped_ptr<aura::Window> window( - CreateTestWindow(gfx::Rect(10, 20, 500, 400))); - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - // Invariant: Window is smaller than work area. - EXPECT_LE(window->bounds().width(), work_area.width()); - EXPECT_LE(window->bounds().height(), work_area.height()); - - // Make the root window narrower than our window. - UpdateDisplay("300x400"); - work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - EXPECT_LE(window->bounds().width(), work_area.width()); - EXPECT_LE(window->bounds().height(), work_area.height()); - - // Make the root window shorter than our window. - UpdateDisplay("300x200"); - work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - EXPECT_LE(window->bounds().width(), work_area.width()); - EXPECT_LE(window->bounds().height(), work_area.height()); - - // Enlarging the root window does not change the window bounds. - gfx::Rect old_bounds = window->bounds(); - UpdateDisplay("800x600"); - EXPECT_EQ(old_bounds.width(), window->bounds().width()); - EXPECT_EQ(old_bounds.height(), window->bounds().height()); -} - -// Tests that a maximized window with too-large restore bounds will be restored -// to smaller than the full work area. -TEST_F(BaseLayoutManagerTest, BoundsWithScreenEdgeVisible) { - // Create a window with bounds that fill the screen. - gfx::Rect bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds(); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - // Maximize it, which writes the old bounds to restore bounds. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - // Restore it. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - // It should have the default maximized window bounds, inset by the grid size. - int grid_size = internal::WorkspaceWindowResizer::kScreenEdgeInset; - gfx::Rect max_bounds = - ash::ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()); - max_bounds.Inset(grid_size, grid_size); - EXPECT_EQ(max_bounds.ToString(), window->bounds().ToString()); -} - -// Verifies maximizing sets the restore bounds, and restoring -// restores the bounds. -TEST_F(BaseLayoutManagerTest, MaximizeSetsRestoreBounds) { - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - // Maximize it, which will keep the previous restore bounds. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_EQ("1,2 3x4", window_state->GetRestoreBoundsInParent().ToString()); - - // Restore it, which should restore bounds and reset restore bounds. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ("1,2 3x4", window->bounds().ToString()); - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Verifies maximizing keeps the restore bounds if set. -TEST_F(BaseLayoutManagerTest, MaximizeResetsRestoreBounds) { - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->SetRestoreBoundsInParent(gfx::Rect(10, 11, 12, 13)); - - // Maximize it, which will keep the previous restore bounds. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_EQ("10,11 12x13", window_state->GetRestoreBoundsInParent().ToString()); -} - -// Verifies that the restore bounds do not get reset when restoring to a -// maximzied state from a minimized state. -TEST_F(BaseLayoutManagerTest, BoundsAfterRestoringToMaximizeFromMinimize) { - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); - gfx::Rect bounds(10, 15, 25, 35); - window->SetBounds(bounds); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - // Maximize it, which should reset restore bounds. - window_state->Maximize(); - EXPECT_EQ(bounds.ToString(), - window_state->GetRestoreBoundsInParent().ToString()); - - // Minimize the window. The restore bounds should not change. - window_state->Minimize(); - EXPECT_EQ(bounds.ToString(), - window_state->GetRestoreBoundsInParent().ToString()); - - // Show the window again. The window should be maximized, and the restore - // bounds should not change. - window->Show(); - EXPECT_EQ(bounds.ToString(), - window_state->GetRestoreBoundsInParent().ToString()); - EXPECT_TRUE(window_state->IsMaximized()); - - window_state->Restore(); - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); -} - -// Verify if the window is not resized during screen lock. See: crbug.com/173127 -TEST_F(BaseLayoutManagerTest, NotResizeWhenScreenIsLocked) { - SetCanLockScreen(true); - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); - // window with AlwaysOnTop will be managed by BaseLayoutManager. - window->SetProperty(aura::client::kAlwaysOnTopKey, true); - window->Show(); - - internal::ShelfLayoutManager* shelf = - internal::ShelfLayoutManager::ForLauncher(window.get()); - shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - - window->SetBounds(ScreenAsh::GetMaximizedWindowBoundsInParent(window.get())); - gfx::Rect window_bounds = window->bounds(); - EXPECT_EQ( - ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), - window_bounds.ToString()); - - Shell::GetInstance()->session_state_delegate()->LockScreen(); - shelf->UpdateVisibilityState(); - EXPECT_NE( - ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), - window_bounds.ToString()); - - Shell::GetInstance()->session_state_delegate()->UnlockScreen(); - shelf->UpdateVisibilityState(); - EXPECT_EQ(window_bounds.ToString(), window->bounds().ToString()); -} - -} // namespace -} // namespace ash diff --git a/chromium/ash/wm/boot_splash_screen_chromeos.cc b/chromium/ash/wm/boot_splash_screen_chromeos.cc deleted file mode 100644 index ca862fa6218..00000000000 --- a/chromium/ash/wm/boot_splash_screen_chromeos.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2013 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 "third_party/skia/include/core/SkBitmap.h" -#include "ui/aura/root_window.h" -#include "ui/aura/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" -#include "ui/gfx/canvas.h" - -namespace ash { -namespace internal { - -// ui::LayerDelegate that copies the aura host window's content to a ui::Layer. -class BootSplashScreen::CopyHostContentLayerDelegate - : public ui::LayerDelegate { - public: - explicit CopyHostContentLayerDelegate(aura::RootWindow* root_window) - : root_window_(root_window) { - } - - virtual ~CopyHostContentLayerDelegate() {} - - // ui::LayerDelegate overrides: - virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE { - // It'd be safer to copy the area to a canvas in the constructor and then - // copy from that canvas to this one here, but this appears to work (i.e. we - // only call this before we draw our first frame) and it saves us an extra - // copy. - // 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_->host()->GetAcceleratedWidget(), - root_window_->host()->GetBounds(), gfx::Point(), canvas); - } - - virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {} - - virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE { - return base::Closure(); - } - - private: - aura::RootWindow* root_window_; // not owned - - DISALLOW_COPY_AND_ASSIGN(CopyHostContentLayerDelegate); -}; - -BootSplashScreen::BootSplashScreen(aura::RootWindow* root_window) - : layer_delegate_(new CopyHostContentLayerDelegate(root_window)), - layer_(new ui::Layer(ui::LAYER_TEXTURED)) { - layer_->set_delegate(layer_delegate_.get()); - - ui::Layer* root_layer = root_window->window()->layer(); - layer_->SetBounds(gfx::Rect(root_layer->bounds().size())); - root_layer->Add(layer_.get()); - root_layer->StackAtTop(layer_.get()); -} - -BootSplashScreen::~BootSplashScreen() { -} - -void BootSplashScreen::StartHideAnimation(base::TimeDelta duration) { - ui::ScopedLayerAnimationSettings settings(layer_->GetAnimator()); - settings.SetTransitionDuration(duration); - settings.SetPreemptionStrategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); - layer_->SetOpacity(0.0f); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/boot_splash_screen_chromeos.h b/chromium/ash/wm/boot_splash_screen_chromeos.h deleted file mode 100644 index e844275ad5f..00000000000 --- a/chromium/ash/wm/boot_splash_screen_chromeos.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2013 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_ - -#include <string> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" - -namespace aura { -class RootWindow; -} - -namespace ui { -class Layer; -class LayerDelegate; -} - -namespace ash { -namespace internal { - -// BootSplashScreen manages a ui::Layer, stacked at the top of the root layer's -// children, that displays a copy of the initial contents of the host window. -// This allows us to continue displaying the Chrome OS boot splash screen (which -// is displayed before Ash starts) after the compositor has taken over so we can -// animate the transition between the splash screen and the login screen. -class BootSplashScreen { - public: - explicit BootSplashScreen(aura::RootWindow* root_window); - ~BootSplashScreen(); - - // Begins animating |layer_|'s opacity to 0 over |duration|. - void StartHideAnimation(base::TimeDelta duration); - - private: - class CopyHostContentLayerDelegate; - - // Copies the host window's content to |layer_|. - scoped_ptr<CopyHostContentLayerDelegate> layer_delegate_; - - scoped_ptr<ui::Layer> layer_; - - DISALLOW_COPY_AND_ASSIGN(BootSplashScreen); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_BOOT_SPLASH_SCREEN_CHROMEOS_H_ diff --git a/chromium/ash/wm/caption_buttons/alternate_frame_size_button.cc b/chromium/ash/wm/caption_buttons/alternate_frame_size_button.cc deleted file mode 100644 index 24f9a0ad90b..00000000000 --- a/chromium/ash/wm/caption_buttons/alternate_frame_size_button.cc +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2013 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/caption_buttons/alternate_frame_size_button.h" - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/shell.h" -#include "ash/touch/touch_uma.h" -#include "ash/wm/window_state.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "ui/gfx/vector2d.h" -#include "ui/views/widget/widget.h" - -namespace { - -// The default delay between the user pressing the size button and the buttons -// adjacent to the size button morphing into buttons for snapping left and -// right. -const int kSetButtonsToSnapModeDelayMs = 150; - -// The amount that a user can overshoot the snap left / snap right button and -// keep the snap left / snap right button pressed. -const int kPressedHitBoundsExpandX = 200; -const int kPressedHitBoundsExpandY = 50; - -} // namespace - -namespace ash { - -AlternateFrameSizeButton::AlternateFrameSizeButton( - views::ButtonListener* listener, - views::Widget* frame, - AlternateFrameSizeButtonDelegate* delegate) - : FrameCaptionButton(listener, CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE), - frame_(frame), - delegate_(delegate), - set_buttons_to_snap_mode_delay_ms_(kSetButtonsToSnapModeDelayMs), - in_snap_mode_(false), - snap_type_(SNAP_NONE) { -} - -AlternateFrameSizeButton::~AlternateFrameSizeButton() { -} - -bool AlternateFrameSizeButton::OnMousePressed(const ui::MouseEvent& event) { - // The minimize and close buttons are set to snap left and right when snapping - // is enabled. Do not enable snapping if the minimize button is not visible. - // The close button is always visible. - if (IsTriggerableEvent(event) && - !in_snap_mode_ && - delegate_->IsMinimizeButtonVisible()) { - StartSetButtonsToSnapModeTimer(event); - } - FrameCaptionButton::OnMousePressed(event); - return true; -} - -bool AlternateFrameSizeButton::OnMouseDragged(const ui::MouseEvent& event) { - UpdatePressedButton(event); - FrameCaptionButton::OnMouseDragged(event); - return true; -} - -void AlternateFrameSizeButton::OnMouseReleased(const ui::MouseEvent& event) { - if (!IsTriggerableEvent(event) || !CommitSnap(event)) - FrameCaptionButton::OnMouseReleased(event); -} - -void AlternateFrameSizeButton::OnMouseCaptureLost() { - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); - FrameCaptionButton::OnMouseCaptureLost(); -} - -void AlternateFrameSizeButton::OnGestureEvent(ui::GestureEvent* event) { - if (event->details().touch_points() > 1) { - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); - return; - } - - if (event->type() == ui::ET_GESTURE_TAP_DOWN) { - StartSetButtonsToSnapModeTimer(*event); - // Go through FrameCaptionButton's handling so that the button gets pressed. - FrameCaptionButton::OnGestureEvent(event); - return; - } - - if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN || - event->type() == ui::ET_GESTURE_SCROLL_UPDATE) { - UpdatePressedButton(*event); - event->SetHandled(); - return; - } - - if (event->type() == ui::ET_GESTURE_TAP || - event->type() == ui::ET_GESTURE_SCROLL_END || - event->type() == ui::ET_SCROLL_FLING_START || - event->type() == ui::ET_GESTURE_END) { - if (CommitSnap(*event)) { - if (event->type() == ui::ET_GESTURE_TAP) { - TouchUMA::GetInstance()->RecordGestureAction( - TouchUMA::GESTURE_FRAMEMAXIMIZE_TAP); - } - event->SetHandled(); - return; - } - } - - FrameCaptionButton::OnGestureEvent(event); -} - -void AlternateFrameSizeButton::StartSetButtonsToSnapModeTimer( - const ui::LocatedEvent& event) { - set_buttons_to_snap_mode_timer_event_location_ = event.location(); - if (set_buttons_to_snap_mode_delay_ms_ == 0) { - SetButtonsToSnapMode(); - } else { - set_buttons_to_snap_mode_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(set_buttons_to_snap_mode_delay_ms_), - this, - &AlternateFrameSizeButton::SetButtonsToSnapMode); - } -} - -void AlternateFrameSizeButton::SetButtonsToSnapMode() { - if (in_snap_mode_) - return; - in_snap_mode_ = true; - delegate_->SetButtonIcons(CAPTION_BUTTON_ICON_LEFT_SNAPPED, - CAPTION_BUTTON_ICON_RIGHT_SNAPPED, - AlternateFrameSizeButtonDelegate::ANIMATE_YES); -} - -void AlternateFrameSizeButton::UpdatePressedButton( - const ui::LocatedEvent& event) { - if (!in_snap_mode_) { - // Set the buttons adjacent to the size button to snap left and right early - // if the user drags past the drag threshold. - // |set_buttons_to_snap_mode_timer_| is checked to avoid entering the snap - // mode as a result of an unsupported drag type (e.g. only the right mouse - // button is pressed). - gfx::Vector2d delta( - event.location() - set_buttons_to_snap_mode_timer_event_location_); - if (!set_buttons_to_snap_mode_timer_.IsRunning() || - !views::View::ExceededDragThreshold(delta)) { - return; - } - SetButtonsToSnapMode(); - } - - gfx::Point event_location_in_screen(event.location()); - views::View::ConvertPointToScreen(this, &event_location_in_screen); - - gfx::Insets pressed_button_hittest_insets(-kPressedHitBoundsExpandY, - -kPressedHitBoundsExpandX, - -kPressedHitBoundsExpandY, - -kPressedHitBoundsExpandX); - const FrameCaptionButton* pressed_button = delegate_->PressButtonAt( - event_location_in_screen, pressed_button_hittest_insets); - snap_type_ = SNAP_NONE; - if (pressed_button) { - switch (pressed_button->icon()) { - case CAPTION_BUTTON_ICON_LEFT_SNAPPED: - snap_type_ = SNAP_LEFT; - break; - case CAPTION_BUTTON_ICON_RIGHT_SNAPPED: - snap_type_ = SNAP_RIGHT; - break; - case CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE: - // snap_type_ = SNAP_NONE - break; - case CAPTION_BUTTON_ICON_MINIMIZE: - case CAPTION_BUTTON_ICON_CLOSE: - NOTREACHED(); - break; - } - } -} - -bool AlternateFrameSizeButton::CommitSnap(const ui::LocatedEvent& event) { - // The position of |event| may be different than the position of the previous - // event. - UpdatePressedButton(event); - - if (in_snap_mode_ && - (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { - using internal::SnapSizer; - SnapSizer::SnapWindow(ash::wm::GetWindowState(frame_->GetNativeWindow()), - snap_type_ == SNAP_LEFT ? - SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE); - ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( - snap_type_ == SNAP_LEFT ? - ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT : - ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT); - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_NO); - return true; - } - SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); - return false; -} - -void AlternateFrameSizeButton::SetButtonsToNormalMode( - AlternateFrameSizeButtonDelegate::Animate animate) { - in_snap_mode_ = false; - snap_type_ = SNAP_NONE; - set_buttons_to_snap_mode_timer_.Stop(); - delegate_->SetButtonsToNormal(animate); -} - -} // namespace ash diff --git a/chromium/ash/wm/caption_buttons/alternate_frame_size_button.h b/chromium/ash/wm/caption_buttons/alternate_frame_size_button.h deleted file mode 100644 index 586eabbeb99..00000000000 --- a/chromium/ash/wm/caption_buttons/alternate_frame_size_button.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2013 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_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_H_ -#define ASH_WM_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/alternate_frame_size_button_delegate.h" -#include "ash/wm/caption_buttons/frame_caption_button.h" -#include "ash/wm/workspace/snap_types.h" -#include "base/timer/timer.h" - -namespace views { -class Widget; -} - -namespace ash { -class AlternateFrameSizeButtonDelegate; - -// The maximize/restore button when using the alternate button style. -// When the mouse is pressed over the size button or the size button is touched: -// - The minimize and close buttons are set to snap left and snap right -// respectively. -// - The pressed button is updated during the drag to reflect the button -// underneath the mouse cursor. (The size button is potentially unpressed). -// When the drag terminates, the action for the pressed button is executed. -// For the sake of simplicity, the size button is the event handler for a click -// starting on the size button and the entire drag (including when the size -// button is unpressed). -class ASH_EXPORT AlternateFrameSizeButton : public FrameCaptionButton { - public: - AlternateFrameSizeButton(views::ButtonListener* listener, - views::Widget* frame, - AlternateFrameSizeButtonDelegate* delegate); - - virtual ~AlternateFrameSizeButton(); - - // views::CustomButton overrides: - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseCaptureLost() OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - void set_delay_to_set_buttons_to_snap_mode(int delay_ms) { - set_buttons_to_snap_mode_delay_ms_ = delay_ms; - } - - private: - // Starts |set_buttons_to_snap_mode_timer_|. - void StartSetButtonsToSnapModeTimer(const ui::LocatedEvent& event); - - // Sets the buttons adjacent to the size button to snap left and right. - void SetButtonsToSnapMode(); - - // Updates the pressed button based on |event_location|. - void UpdatePressedButton(const ui::LocatedEvent& event); - - // Snaps |frame_| according to |snap_type_|. Returns true if |frame_| was - // snapped. - bool CommitSnap(const ui::LocatedEvent& event); - - // Sets the buttons adjacent to the size button to minimize and close again. - // Clears any state set while snapping was enabled. |animate| indicates - // whether the buttons should animate back to their original icons. - void SetButtonsToNormalMode( - AlternateFrameSizeButtonDelegate::Animate animate); - - // Widget that the size button acts on. - views::Widget* frame_; - - // Not owned. - AlternateFrameSizeButtonDelegate* delegate_; - - // Location of the event which started |set_buttons_to_snap_mode_timer_| in - // view coordinates. - gfx::Point set_buttons_to_snap_mode_timer_event_location_; - - // The delay between the user pressing the size button and the buttons - // adjacent to the size button morphing into buttons for snapping left and - // right. - int set_buttons_to_snap_mode_delay_ms_; - - base::OneShotTimer<AlternateFrameSizeButton> set_buttons_to_snap_mode_timer_; - - // Whether the buttons adjacent to the size button snap the window left and - // right. - bool in_snap_mode_; - - // The action of the currently pressed button. If |snap_type_| == SNAP_NONE, - // the size button's default action is run when clicked. - SnapType snap_type_; - - DISALLOW_COPY_AND_ASSIGN(AlternateFrameSizeButton); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_H_ diff --git a/chromium/ash/wm/caption_buttons/alternate_frame_size_button_delegate.h b/chromium/ash/wm/caption_buttons/alternate_frame_size_button_delegate.h deleted file mode 100644 index c1472b21bf1..00000000000 --- a/chromium/ash/wm/caption_buttons/alternate_frame_size_button_delegate.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2013 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_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_DELEGATE_H_ -#define ASH_WM_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_DELEGATE_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/caption_button_types.h" - -namespace gfx { -class Insets; -class Point; -} - -namespace ash { -class FrameCaptionButton; - -// Delegate interface for AlternateFrameSizeButton. -class ASH_EXPORT AlternateFrameSizeButtonDelegate { - public: - enum Animate { - ANIMATE_YES, - ANIMATE_NO - }; - - // Returns whether the minimize button is visible. - virtual bool IsMinimizeButtonVisible() const = 0; - - // Reset the caption button views::Button::ButtonState back to normal. If - // |animate| is ANIMATE_YES, the buttons will crossfade back to their - // original icons. - virtual void SetButtonsToNormal(Animate animate) = 0; - - // Sets the minimize and close button icons. The buttons will crossfade to - // their new icons if |animate| is ANIMATE_YES. - virtual void SetButtonIcons(CaptionButtonIcon left_button_action, - CaptionButtonIcon right_button_action, - Animate animate) = 0; - - // Presses the button at |position_in_screen| and unpresses any other pressed - // caption buttons. - // |pressed_button_hittest_insets| indicates how much the hittest insets for - // the currently pressed button should be expanded if no button was found at - // |position_in_screen| using the normal button hittest insets. - // Returns the button which was pressed. - virtual const FrameCaptionButton* PressButtonAt( - const gfx::Point& position_in_screen, - const gfx::Insets& pressed_button_hittest_insets) const = 0; - - protected: - virtual ~AlternateFrameSizeButtonDelegate() {} -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_ALTERNATE_FRAME_SIZE_BUTTON_DELEGATE_H_ diff --git a/chromium/ash/wm/caption_buttons/alternate_frame_size_button_unittest.cc b/chromium/ash/wm/caption_buttons/alternate_frame_size_button_unittest.cc deleted file mode 100644 index 75c0f50604b..00000000000 --- a/chromium/ash/wm/caption_buttons/alternate_frame_size_button_unittest.cc +++ /dev/null @@ -1,367 +0,0 @@ -// Copyright 2013 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/caption_buttons/alternate_frame_size_button.h" - -#include "ash/ash_switches.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/caption_buttons/frame_caption_button.h" -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/window_state.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "base/command_line.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/window.h" -#include "ui/events/gestures/gesture_configuration.h" -#include "ui/gfx/display.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -namespace test { - -namespace { - -class TestWidgetDelegate : public views::WidgetDelegateView { - public: - TestWidgetDelegate() {} - virtual ~TestWidgetDelegate() {} - - // Overridden from views::WidgetDelegate: - virtual views::View* GetContentsView() OVERRIDE { - return this; - } - virtual bool CanResize() const OVERRIDE { - return true; - } - virtual bool CanMaximize() const OVERRIDE { - return true; - } - - ash::FrameCaptionButtonContainerView* caption_button_container() { - return caption_button_container_; - } - - private: - // Overridden from views::View: - virtual void Layout() OVERRIDE { - caption_button_container_->Layout(); - - // Right align the caption button container. - gfx::Size preferred_size = caption_button_container_->GetPreferredSize(); - caption_button_container_->SetBounds(width() - preferred_size.width(), 0, - preferred_size.width(), preferred_size.height()); - } - - virtual void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) OVERRIDE { - if (details.is_add && details.child == this) { - caption_button_container_ = new FrameCaptionButtonContainerView( - GetWidget(), FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - AddChildView(caption_button_container_); - } - } - - // Not owned. - ash::FrameCaptionButtonContainerView* caption_button_container_; - - DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); -}; - -} // namespace - -class AlternateFrameSizeButtonTest : public AshTestBase { - public: - AlternateFrameSizeButtonTest() {} - virtual ~AlternateFrameSizeButtonTest() {} - - // Returns the center point of |view| in screen coordinates. - gfx::Point CenterPointInScreen(views::View* view) { - return view->GetBoundsInScreen().CenterPoint(); - } - - // Returns true if the window is snapped to |edge|. - bool IsSnapped(internal::SnapSizer::Edge edge) const { - ash::wm::WindowShowType show_type = window_state()->window_show_type(); - if (edge == internal::SnapSizer::LEFT_EDGE) - return show_type == ash::wm::SHOW_TYPE_LEFT_SNAPPED; - else - return show_type == ash::wm::SHOW_TYPE_RIGHT_SNAPPED; - } - - // Returns true if all three buttons are in the normal state. - bool AllButtonsInNormalState() const { - return minimize_button_->state() == views::Button::STATE_NORMAL && - size_button_->state() == views::Button::STATE_NORMAL && - close_button_->state() == views::Button::STATE_NORMAL; - } - - // Creates a widget with |delegate|. The returned widget takes ownership of - // |delegate|. - views::Widget* CreateWidget(views::WidgetDelegate* delegate) { - views::Widget* widget = new views::Widget; - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.context = CurrentContext(); - params.delegate = delegate; - params.bounds = gfx::Rect(10, 10, 100, 100); - widget->Init(params); - widget->Show(); - return widget; - } - - // AshTestBase overrides: - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - - CommandLine* command_line = CommandLine::ForCurrentProcess(); - command_line->AppendSwitch( - switches::kAshEnableAlternateFrameCaptionButtonStyle); - CHECK(!command_line->HasSwitch(switches::kAshMultipleSnapWindowWidths)); - - TestWidgetDelegate* delegate = new TestWidgetDelegate(); - window_state_ = ash::wm::GetWindowState( - CreateWidget(delegate)->GetNativeWindow()); - - FrameCaptionButtonContainerView::TestApi test( - delegate->caption_button_container()); - - minimize_button_ = test.minimize_button(); - size_button_ = test.size_button(); - static_cast<AlternateFrameSizeButton*>( - size_button_)->set_delay_to_set_buttons_to_snap_mode(0); - close_button_ = test.close_button(); - } - - ash::wm::WindowState* window_state() { return window_state_; } - const ash::wm::WindowState* window_state() const { return window_state_; } - - FrameCaptionButton* minimize_button() { return minimize_button_; } - FrameCaptionButton* size_button() { return size_button_; } - FrameCaptionButton* close_button() { return close_button_; } - - private: - // Not owned. - ash::wm::WindowState* window_state_; - FrameCaptionButton* minimize_button_; - FrameCaptionButton* size_button_; - FrameCaptionButton* close_button_; - - DISALLOW_COPY_AND_ASSIGN(AlternateFrameSizeButtonTest); -}; - -// Tests that pressing the left mouse button or tapping down on the size button -// puts the button into the pressed state. -TEST_F(AlternateFrameSizeButtonTest, PressedState) { - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_EQ(views::Button::STATE_NORMAL, size_button()->state()); - - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressTouchId(3); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - generator.ReleaseTouchId(3); - RunAllPendingInMessageLoop(); - EXPECT_EQ(views::Button::STATE_NORMAL, size_button()->state()); -} - -// Tests that clicking on the size button toggles between the maximized and -// normal state. -TEST_F(AlternateFrameSizeButtonTest, ClickSizeButtonTogglesMaximize) { - EXPECT_FALSE(window_state()->IsMaximized()); - - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.ClickLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window_state()->IsMaximized()); - - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.ClickLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window_state()->IsMaximized()); - - generator.GestureTapAt(CenterPointInScreen(size_button())); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window_state()->IsMaximized()); - - generator.GestureTapAt(CenterPointInScreen(size_button())); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window_state()->IsMaximized()); -} - -// Test that clicking + dragging to a button adjacent to the size button snaps -// the window left or right. -TEST_F(AlternateFrameSizeButtonTest, ButtonDrag) { - EXPECT_TRUE(window_state()->IsNormalShowState()); - EXPECT_FALSE(window_state()->IsSnapped()); - - // 1) Test by dragging the mouse. - // Snap right. - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - generator.MoveMouseTo(CenterPointInScreen(close_button())); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsSnapped(internal::SnapSizer::RIGHT_EDGE)); - - // Snap left. - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - generator.MoveMouseTo(CenterPointInScreen(minimize_button())); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsSnapped(internal::SnapSizer::LEFT_EDGE)); - - // 2) Test with scroll gestures. - // Snap right. - generator.GestureScrollSequence( - CenterPointInScreen(size_button()), - CenterPointInScreen(close_button()), - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsSnapped(internal::SnapSizer::RIGHT_EDGE)); - - // Snap left. - generator.GestureScrollSequence( - CenterPointInScreen(size_button()), - CenterPointInScreen(minimize_button()), - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsSnapped(internal::SnapSizer::LEFT_EDGE)); - - // 3) Test with tap gestures. - const int touch_default_radius = - ui::GestureConfiguration::default_radius(); - ui::GestureConfiguration::set_default_radius(0); - // Snap right. - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressMoveAndReleaseTouchTo(CenterPointInScreen(close_button())); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsSnapped(internal::SnapSizer::RIGHT_EDGE)); - // Snap left. - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressMoveAndReleaseTouchTo(CenterPointInScreen(minimize_button())); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsSnapped(internal::SnapSizer::LEFT_EDGE)); - ui::GestureConfiguration::set_default_radius(touch_default_radius); -} - -// Test that clicking, dragging, and overshooting the minimize button a bit -// horizontally still snaps the window left. -TEST_F(AlternateFrameSizeButtonTest, SnapLeftOvershootMinimize) { - EXPECT_TRUE(window_state()->IsNormalShowState()); - EXPECT_FALSE(window_state()->IsSnapped()); - - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - - generator.PressLeftButton(); - // Move to the minimize button. - generator.MoveMouseTo(CenterPointInScreen(minimize_button())); - // Overshoot the minimize button. - generator.MoveMouseBy(-minimize_button()->width(), 0); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsSnapped(internal::SnapSizer::LEFT_EDGE)); -} - -// Test that right clicking the size button has no effect. -TEST_F(AlternateFrameSizeButtonTest, RightMouseButton) { - EXPECT_TRUE(window_state()->IsNormalShowState()); - EXPECT_FALSE(window_state()->IsSnapped()); - - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressRightButton(); - generator.ReleaseRightButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window_state()->IsNormalShowState()); - EXPECT_FALSE(window_state()->IsSnapped()); -} - -// Test that upon releasing the mouse button after having pressed the size -// button -// - The state of all the caption buttons is reset. -// - The icon displayed by all of the caption buttons is reset. -TEST_F(AlternateFrameSizeButtonTest, ResetButtonsAfterClick) { - EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); - EXPECT_TRUE(AllButtonsInNormalState()); - - // Pressing the size button should result in the size button being pressed and - // the minimize and close button icons changing. - aura::test::EventGenerator& generator = GetEventGenerator(); - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state()); - EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon()); - - // Dragging the mouse over the minimize button should press the minimize - // button and the minimize and close button icons should stay changed. - generator.MoveMouseTo(CenterPointInScreen(minimize_button())); - EXPECT_EQ(views::Button::STATE_PRESSED, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, size_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state()); - EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon()); - - // Release the mouse, snapping the window left. - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsSnapped(internal::SnapSizer::LEFT_EDGE)); - - // None of the buttons should stay pressed and the buttons should have their - // regular icons. - EXPECT_TRUE(AllButtonsInNormalState()); - EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); - - // Repeat test but release button where it does not affect the window's state - // because the code path is different. - generator.MoveMouseTo(CenterPointInScreen(size_button())); - generator.PressLeftButton(); - EXPECT_EQ(views::Button::STATE_NORMAL, minimize_button()->state()); - EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state()); - EXPECT_EQ(views::Button::STATE_NORMAL, close_button()->state()); - EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon()); - - const gfx::Rect& kWorkAreaBoundsInScreen = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - generator.MoveMouseTo(kWorkAreaBoundsInScreen.bottom_left()); - - // None of the buttons should be pressed because we are really far away from - // any of the caption buttons. The minimize and close button icons should - // be changed because the mouse is pressed. - EXPECT_TRUE(AllButtonsInNormalState()); - EXPECT_EQ(CAPTION_BUTTON_ICON_LEFT_SNAPPED, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, close_button()->icon()); - - // Release the mouse. The window should stay snapped left. - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsSnapped(internal::SnapSizer::LEFT_EDGE)); - - // The buttons should stay unpressed and the buttons should now have their - // regular icons. - EXPECT_TRUE(AllButtonsInNormalState()); - EXPECT_EQ(CAPTION_BUTTON_ICON_MINIMIZE, minimize_button()->icon()); - EXPECT_EQ(CAPTION_BUTTON_ICON_CLOSE, close_button()->icon()); -} - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/caption_buttons/bubble_contents_button_row.cc b/chromium/ash/wm/caption_buttons/bubble_contents_button_row.cc deleted file mode 100644 index 6eb9062599e..00000000000 --- a/chromium/ash/wm/caption_buttons/bubble_contents_button_row.cc +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2013 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/caption_buttons/bubble_contents_button_row.h" - -#include "ash/wm/caption_buttons/maximize_bubble_controller.h" -#include "ash/wm/caption_buttons/maximize_bubble_controller_bubble.h" -#include "grit/ash_resources.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/layout/box_layout.h" - - -namespace ash { - -// BubbleDialogButton --------------------------------------------------------- - -// The image button gets overridden to be able to capture mouse hover events. -// The constructor also assigns all button states and adds |this| as a child of -// |button_row|. -class BubbleDialogButton : public views::ImageButton { - public: - explicit BubbleDialogButton(BubbleContentsButtonRow* button_row, - int normal_image, - int hovered_image, - int pressed_image); - virtual ~BubbleDialogButton(); - - // views::ImageButton: - virtual void OnMouseCaptureLost() OVERRIDE; - virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; - - private: - // The creating class which needs to get notified in case of a hover event. - BubbleContentsButtonRow* button_row_; - - DISALLOW_COPY_AND_ASSIGN(BubbleDialogButton); -}; - -BubbleDialogButton::BubbleDialogButton( - BubbleContentsButtonRow* button_row, - int normal_image, - int hovered_image, - int pressed_image) - : views::ImageButton(button_row), - button_row_(button_row) { - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - SetImage(views::CustomButton::STATE_NORMAL, - rb.GetImageSkiaNamed(normal_image)); - SetImage(views::CustomButton::STATE_HOVERED, - rb.GetImageSkiaNamed(hovered_image)); - SetImage(views::CustomButton::STATE_PRESSED, - rb.GetImageSkiaNamed(pressed_image)); - button_row->AddChildView(this); -} - -BubbleDialogButton::~BubbleDialogButton() { -} - -void BubbleDialogButton::OnMouseCaptureLost() { - button_row_->ButtonHovered(NULL); - views::ImageButton::OnMouseCaptureLost(); -} - -void BubbleDialogButton::OnMouseEntered(const ui::MouseEvent& event) { - button_row_->ButtonHovered(this); - views::ImageButton::OnMouseEntered(event); -} - -void BubbleDialogButton::OnMouseExited(const ui::MouseEvent& event) { - button_row_->ButtonHovered(NULL); - views::ImageButton::OnMouseExited(event); -} - -bool BubbleDialogButton::OnMouseDragged(const ui::MouseEvent& event) { - if (!button_row_->bubble()->controller()) - return false; - - // Remove the phantom window when we leave the button. - gfx::Point screen_location(event.location()); - View::ConvertPointToScreen(this, &screen_location); - if (!GetBoundsInScreen().Contains(screen_location)) - button_row_->ButtonHovered(NULL); - else - button_row_->ButtonHovered(this); - - // Pass the event on to the normal handler. - return views::ImageButton::OnMouseDragged(event); -} - - -// BubbleContentsButtonRow ---------------------------------------------------- - -BubbleContentsButtonRow::BubbleContentsButtonRow( - MaximizeBubbleControllerBubble* bubble) - : bubble_(bubble), - left_button_(NULL), - minimize_button_(NULL), - right_button_(NULL) { - SetLayoutManager(new views::BoxLayout( - views::BoxLayout::kHorizontal, 0, 0, - MaximizeBubbleControllerBubble::kLayoutSpacing)); - set_background(views::Background::CreateSolidBackground( - MaximizeBubbleControllerBubble::kBubbleBackgroundColor)); - - if (base::i18n::IsRTL()) { - AddMaximizeRightButton(); - AddMinimizeButton(); - AddMaximizeLeftButton(); - } else { - AddMaximizeLeftButton(); - AddMinimizeButton(); - AddMaximizeRightButton(); - } -} - -BubbleContentsButtonRow::~BubbleContentsButtonRow() { -} - -void BubbleContentsButtonRow::ButtonPressed(views::Button* sender, - const ui::Event& event) { - // While shutting down, the connection to the owner might already be broken. - if (!bubble_->controller()) - return; - if (sender == left_button_) { - bubble_->controller()->OnButtonClicked( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_LEFT) ? - SNAP_RESTORE : SNAP_LEFT); - } else if (sender == minimize_button_) { - bubble_->controller()->OnButtonClicked(SNAP_MINIMIZE); - } else { - DCHECK(sender == right_button_); - bubble_->controller()->OnButtonClicked( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_RIGHT) ? - SNAP_RESTORE : SNAP_RIGHT); - } -} - -void BubbleContentsButtonRow::ButtonHovered(BubbleDialogButton* sender) { - // While shutting down, the connection to the owner might already be broken. - if (!bubble_->controller()) - return; - if (sender == left_button_) { - bubble_->controller()->OnButtonHover( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_LEFT) ? - SNAP_RESTORE : SNAP_LEFT); - } else if (sender == minimize_button_) { - bubble_->controller()->OnButtonHover(SNAP_MINIMIZE); - } else if (sender == right_button_) { - bubble_->controller()->OnButtonHover( - (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_RIGHT) ? - SNAP_RESTORE : SNAP_RIGHT); - } else { - bubble_->controller()->OnButtonHover(SNAP_NONE); - } -} - -views::CustomButton* BubbleContentsButtonRow::GetButtonForUnitTest( - SnapType state) { - switch (state) { - case SNAP_LEFT: - return left_button_; - case SNAP_MINIMIZE: - return minimize_button_; - case SNAP_RIGHT: - return right_button_; - default: - NOTREACHED(); - return NULL; - } -} - -void BubbleContentsButtonRow::AddMaximizeLeftButton() { - if (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_LEFT) { - left_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_LEFT_RESTORE, - IDR_AURA_WINDOW_POSITION_LEFT_RESTORE_H, - IDR_AURA_WINDOW_POSITION_LEFT_RESTORE_P); - } else { - left_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_LEFT, - IDR_AURA_WINDOW_POSITION_LEFT_H, - IDR_AURA_WINDOW_POSITION_LEFT_P); - } -} - -void BubbleContentsButtonRow::AddMaximizeRightButton() { - if (bubble_->controller()->maximize_type() == FRAME_STATE_SNAP_RIGHT) { - right_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE, - IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE_H, - IDR_AURA_WINDOW_POSITION_RIGHT_RESTORE_P); - } else { - right_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_RIGHT, - IDR_AURA_WINDOW_POSITION_RIGHT_H, - IDR_AURA_WINDOW_POSITION_RIGHT_P); - } -} - -void BubbleContentsButtonRow::AddMinimizeButton() { - minimize_button_ = new BubbleDialogButton( - this, - IDR_AURA_WINDOW_POSITION_MIDDLE, - IDR_AURA_WINDOW_POSITION_MIDDLE_H, - IDR_AURA_WINDOW_POSITION_MIDDLE_P); -} - -} // namespace ash diff --git a/chromium/ash/wm/caption_buttons/bubble_contents_button_row.h b/chromium/ash/wm/caption_buttons/bubble_contents_button_row.h deleted file mode 100644 index 5f6e8d15ee7..00000000000 --- a/chromium/ash/wm/caption_buttons/bubble_contents_button_row.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2013 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_CAPTION_BUTTONS_BUBBLE_CONTENTS_BUTTON_ROW_H_ -#define ASH_WM_CAPTION_BUTTONS_BUBBLE_CONTENTS_BUTTON_ROW_H_ - -#include "ash/wm/workspace/snap_types.h" -#include "ui/views/controls/button/button.h" - -namespace views { -class CustomButton; -} - -namespace ash { - -class BubbleDialogButton; -class MaximizeBubbleControllerBubble; - -// A class that creates all buttons and puts them into a view. -class BubbleContentsButtonRow : public views::View, - public views::ButtonListener { - public: - explicit BubbleContentsButtonRow(MaximizeBubbleControllerBubble* bubble); - virtual ~BubbleContentsButtonRow(); - - // views::ButtonListener: - virtual void ButtonPressed(views::Button* sender, - const ui::Event& event) OVERRIDE; - - // Called from BubbleDialogButton. - void ButtonHovered(BubbleDialogButton* sender); - - // Added for unit test: Retrieve the button for an action. - // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - MaximizeBubbleControllerBubble* bubble() { return bubble_; } - - private: - // Functions to add the left and right maximize / restore buttons. - void AddMaximizeLeftButton(); - void AddMaximizeRightButton(); - void AddMinimizeButton(); - - // The owning object which gets notifications. - MaximizeBubbleControllerBubble* bubble_; - - // The created buttons for our menu. - BubbleDialogButton* left_button_; - BubbleDialogButton* minimize_button_; - BubbleDialogButton* right_button_; - - DISALLOW_COPY_AND_ASSIGN(BubbleContentsButtonRow); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_BUBBLE_CONTENTS_BUTTON_ROW_H_ diff --git a/chromium/ash/wm/caption_buttons/caption_button_types.h b/chromium/ash/wm/caption_buttons/caption_button_types.h deleted file mode 100644 index b34a8615083..00000000000 --- a/chromium/ash/wm/caption_buttons/caption_button_types.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 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_CAPTION_BUTTONS_CAPTION_BUTTON_TYPES_H_ -#define ASH_WM_CAPTION_BUTTONS_CAPTION_BUTTON_TYPES_H_ - -namespace ash { - -// These are the types of maximization we know. -enum MaximizeBubbleFrameState { - FRAME_STATE_NONE = 0, - FRAME_STATE_FULL = 1, // This is the full maximized state. - FRAME_STATE_SNAP_LEFT = 2, - FRAME_STATE_SNAP_RIGHT = 3 -}; - -// These are the icon types that a caption button can have. The size button's -// action (SnapType) can be different from its icon. -enum CaptionButtonIcon { - CAPTION_BUTTON_ICON_MINIMIZE, - CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, - CAPTION_BUTTON_ICON_CLOSE, - CAPTION_BUTTON_ICON_LEFT_SNAPPED, - CAPTION_BUTTON_ICON_RIGHT_SNAPPED, -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_CAPTION_BUTTON_TYPES_H_ diff --git a/chromium/ash/wm/caption_buttons/frame_caption_button.cc b/chromium/ash/wm/caption_buttons/frame_caption_button.cc deleted file mode 100644 index 5a6a8356831..00000000000 --- a/chromium/ash/wm/caption_buttons/frame_caption_button.cc +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2013 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/caption_buttons/frame_caption_button.h" - -#include "grit/ash_resources.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/animation/slide_animation.h" -#include "ui/gfx/canvas.h" - -namespace ash { - -namespace { - -// The duration of the crossfade animation when swapping the button's icon. -const int kCrossfadeDurationMs = 200; - -} // namespace - -// static -const char FrameCaptionButton::kViewClassName[] = "FrameCaptionButton"; - -FrameCaptionButton::FrameCaptionButton(views::ButtonListener* listener, - CaptionButtonIcon icon) - : ImageButton(listener), - icon_(icon), - style_(STYLE_SHORT_RESTORED), - last_paint_scale_(1.0f), - animation_(new gfx::SlideAnimation(this)) { - animation_->Reset(1); - UpdateImages(); -} - -FrameCaptionButton::~FrameCaptionButton() { -} - -void FrameCaptionButton::SetIcon(CaptionButtonIcon icon, Animate animate) { - if (icon_ == icon) - return; - - if (animate == ANIMATE_YES) { - gfx::Canvas canvas(size(), last_paint_scale_, false); - OnPaint(&canvas); - crossfade_image_ = gfx::ImageSkia(canvas.ExtractImageRep()); - - icon_ = icon; - UpdateImages(); - - animation_->Reset(0); - animation_->SetSlideDuration(kCrossfadeDurationMs); - animation_->Show(); - } else { - animation_->Reset(1); - icon_ = icon; - UpdateImages(); - } -} - -void FrameCaptionButton::SetStyle(Style style) { - if (style_ == style) - return; - animation_->Reset(1); - style_ = style; - UpdateImages(); -} - -const char* FrameCaptionButton::GetClassName() const { - return kViewClassName; -} - -void FrameCaptionButton::OnPaint(gfx::Canvas* canvas) { - last_paint_scale_ = canvas->image_scale(); - int alpha = static_cast<int>(animation_->GetCurrentValue() * 255); - int crossfade_alpha = 255 - alpha; - if (crossfade_alpha > 0 && !crossfade_image_.isNull()) { - gfx::Canvas composed_canvas(size(), last_paint_scale_, false); - SkPaint paint; - paint.setAlpha(crossfade_alpha); - paint.setXfermodeMode(SkXfermode::kPlus_Mode); - composed_canvas.DrawImageInt(crossfade_image_, 0, 0, paint); - paint.setAlpha(alpha); - ImageButton::OnPaint(&composed_canvas); - - canvas->DrawImageInt( - gfx::ImageSkia(composed_canvas.ExtractImageRep()), 0, 0); - } else { - ImageButton::OnPaint(canvas); - } -} - -void FrameCaptionButton::OnGestureEvent(ui::GestureEvent* event) { - // ImageButton does not become pressed when the user drags off and then back - // onto the button. Make FrameCaptionButton pressed in this case because this - // behavior is more consistent with AlternateFrameSizeButton. - if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN || - event->type() == ui::ET_GESTURE_SCROLL_UPDATE) { - if (HitTestPoint(event->location())) { - SetState(STATE_PRESSED); - RequestFocus(); - event->StopPropagation(); - } else { - SetState(STATE_NORMAL); - } - } else if (event->type() == ui::ET_GESTURE_SCROLL_END) { - if (HitTestPoint(event->location())) { - SetState(STATE_HOVERED); - NotifyClick(*event); - event->StopPropagation(); - } - } - ImageButton::OnGestureEvent(event); -} - -void FrameCaptionButton::StateChanged() { - if (state_ == STATE_HOVERED || state_ == STATE_PRESSED) - animation_->Reset(1); -} - -void FrameCaptionButton::UpdateImages() { - switch (icon_) { - case CAPTION_BUTTON_ICON_MINIMIZE: - SetImages(IDR_AURA_WINDOW_MINIMIZE_SHORT, - IDR_AURA_WINDOW_MINIMIZE_SHORT_H, - IDR_AURA_WINDOW_MINIMIZE_SHORT_P); - break; - case CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE: - case CAPTION_BUTTON_ICON_LEFT_SNAPPED: - case CAPTION_BUTTON_ICON_RIGHT_SNAPPED: - if (style_ == STYLE_SHORT_MAXIMIZED_OR_FULLSCREEN) { - SetImages(IDR_AURA_WINDOW_MAXIMIZED_RESTORE2, - IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_H, - IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_P); - } else if (style_ == STYLE_SHORT_RESTORED) { - SetImages(IDR_AURA_WINDOW_MAXIMIZED_RESTORE, - IDR_AURA_WINDOW_MAXIMIZED_RESTORE_H, - IDR_AURA_WINDOW_MAXIMIZED_RESTORE_P); - } else { - SetImages(IDR_AURA_WINDOW_MAXIMIZE, - IDR_AURA_WINDOW_MAXIMIZE_H, - IDR_AURA_WINDOW_MAXIMIZE_P); - } - break; - case CAPTION_BUTTON_ICON_CLOSE: - if (style_ == STYLE_SHORT_MAXIMIZED_OR_FULLSCREEN) { - SetImages(IDR_AURA_WINDOW_MAXIMIZED_CLOSE2, - IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_H, - IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_P); - } else if (style_ == STYLE_SHORT_RESTORED) { - SetImages(IDR_AURA_WINDOW_MAXIMIZED_CLOSE, - IDR_AURA_WINDOW_MAXIMIZED_CLOSE_H, - IDR_AURA_WINDOW_MAXIMIZED_CLOSE_P); - } else { - SetImages(IDR_AURA_WINDOW_CLOSE, - IDR_AURA_WINDOW_CLOSE_H, - IDR_AURA_WINDOW_CLOSE_P); - } - break; - } - - SchedulePaint(); -} - -void FrameCaptionButton::SetImages(int normal_image_id, - int hot_image_id, - int pushed_image_id) { - ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance(); - SetImage(STATE_NORMAL, resource_bundle.GetImageSkiaNamed(normal_image_id)); - SetImage(STATE_HOVERED, resource_bundle.GetImageSkiaNamed(hot_image_id)); - SetImage(STATE_PRESSED, resource_bundle.GetImageSkiaNamed(pushed_image_id)); -} - -void FrameCaptionButton::AnimationProgressed(const gfx::Animation* animation) { - SchedulePaint(); -} - -} // namespace ash diff --git a/chromium/ash/wm/caption_buttons/frame_caption_button.h b/chromium/ash/wm/caption_buttons/frame_caption_button.h deleted file mode 100644 index 61ed922241b..00000000000 --- a/chromium/ash/wm/caption_buttons/frame_caption_button.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2013 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_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_H_ -#define ASH_WM_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/caption_button_types.h" -#include "base/memory/scoped_ptr.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/views/controls/button/image_button.h" - -namespace gfx { -class SlideAnimation; -} - -namespace ash { - -// Base class for the window caption buttons (minimize, maximize, restore, -// close). -class ASH_EXPORT FrameCaptionButton : public views::ImageButton { - public: - enum Animate { - ANIMATE_YES, - ANIMATE_NO - }; - - enum Style { - // Restored tabbed browser windows. - STYLE_TALL_RESTORED, - - // All other restored windows. - STYLE_SHORT_RESTORED, - - // Maximized or fullscreen windows. - STYLE_SHORT_MAXIMIZED_OR_FULLSCREEN - }; - - static const char kViewClassName[]; - - FrameCaptionButton(views::ButtonListener* listener, CaptionButtonIcon icon); - virtual ~FrameCaptionButton(); - - // Sets the button's icon. If |animate| is ANIMATE_YES, the button crossfades - // to the new icon. - void SetIcon(CaptionButtonIcon icon, Animate animate); - - // Sets the button's style. The transition to the new style is not animated. - void SetStyle(Style style); - - // views::View overrides: - virtual const char* GetClassName() const OVERRIDE; - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; - - CaptionButtonIcon icon() const { - return icon_; - } - - protected: - // views::CustomButton overrides: - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - virtual void StateChanged() OVERRIDE; - - private: - // Updates the button's images based on the current icon and style. - void UpdateImages(); - - // Sets the button's images based on the given ids. - void SetImages(int normal_image_id, int hot_image_id, int pushed_image_id); - - // gfx::AnimationDelegate override: - virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; - - // The button's current icon. - CaptionButtonIcon icon_; - - // The button's current style. - Style style_; - - // The scale at which the button was previously painted. - float last_paint_scale_; - - // The image to crossfade from. - gfx::ImageSkia crossfade_image_; - - scoped_ptr<gfx::SlideAnimation> animation_; - - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButton); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_H_ diff --git a/chromium/ash/wm/caption_buttons/frame_caption_button_container_view.cc b/chromium/ash/wm/caption_buttons/frame_caption_button_container_view.cc deleted file mode 100644 index 1ac3a2625ae..00000000000 --- a/chromium/ash/wm/caption_buttons/frame_caption_button_container_view.cc +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2013 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/caption_buttons/frame_caption_button_container_view.h" - -#include "ash/ash_switches.h" -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/shell.h" -#include "ash/wm/caption_buttons/alternate_frame_size_button.h" -#include "ash/wm/caption_buttons/frame_caption_button.h" -#include "ash/wm/caption_buttons/frame_maximize_button.h" -#include "grit/ash_resources.h" -#include "grit/ui_strings.h" // Accessibility names -#include "ui/base/hit_test.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/insets.h" -#include "ui/gfx/point.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { - -namespace { - -// The distance between buttons. -const int kDistanceBetweenButtons = -1; - -// Converts |point| from |src| to |dst| and hittests against |dst|. -bool ConvertPointToViewAndHitTest(const views::View* src, - const views::View* dst, - const gfx::Point& point) { - gfx::Point converted(point); - views::View::ConvertPointToTarget(src, dst, &converted); - return dst->HitTestPoint(converted); -} - -} // namespace - -// static -const char FrameCaptionButtonContainerView::kViewClassName[] = - "FrameCaptionButtonContainerView"; - -FrameCaptionButtonContainerView::FrameCaptionButtonContainerView( - views::Widget* frame, - MinimizeAllowed minimize_allowed) - : frame_(frame), - header_style_(HEADER_STYLE_SHORT), - minimize_button_(NULL), - size_button_(NULL), - close_button_(NULL) { - bool alternate_style = switches::UseAlternateFrameCaptionButtonStyle(); - - // Insert the buttons left to right. - minimize_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_MINIMIZE); - minimize_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE)); - // Hide |minimize_button_| when using the non-alternate button style because - // |size_button_| is capable of minimizing in this case. - minimize_button_->SetVisible( - minimize_allowed == MINIMIZE_ALLOWED && - (alternate_style || !frame_->widget_delegate()->CanMaximize())); - AddChildView(minimize_button_); - - if (alternate_style) - size_button_ = new AlternateFrameSizeButton(this, frame, this); - else - size_button_ = new FrameMaximizeButton(this, frame); - size_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE)); - size_button_->SetVisible(frame_->widget_delegate()->CanMaximize()); - AddChildView(size_button_); - - close_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_CLOSE); - close_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); - AddChildView(close_button_); - - button_separator_ = ui::ResourceBundle::GetSharedInstance().GetImageNamed( - IDR_AURA_WINDOW_BUTTON_SEPARATOR).AsImageSkia(); -} - -FrameCaptionButtonContainerView::~FrameCaptionButtonContainerView() { -} - -FrameMaximizeButton* -FrameCaptionButtonContainerView::GetOldStyleSizeButton() { - return switches::UseAlternateFrameCaptionButtonStyle() ? - NULL : static_cast<FrameMaximizeButton*>(size_button_); -} - -void FrameCaptionButtonContainerView::ResetWindowControls() { - SetButtonsToNormal(ANIMATE_NO); -} - -int FrameCaptionButtonContainerView::NonClientHitTest( - const gfx::Point& point) const { - if (close_button_->visible() && - ConvertPointToViewAndHitTest(this, close_button_, point)) { - return HTCLOSE; - } else if (size_button_->visible() && - ConvertPointToViewAndHitTest(this, size_button_, point)) { - return HTMAXBUTTON; - } else if (minimize_button_->visible() && - ConvertPointToViewAndHitTest(this, minimize_button_, point)) { - return HTMINBUTTON; - } - return HTNOWHERE; -} - -gfx::Size FrameCaptionButtonContainerView::GetPreferredSize() { - int width = 0; - bool first_visible = true; - for (int i = 0; i < child_count(); ++i) { - views::View* child = child_at(i); - if (!child->visible()) - continue; - - width += child_at(i)->GetPreferredSize().width(); - if (!first_visible) - width += kDistanceBetweenButtons; - first_visible = false; - } - return gfx::Size(width, close_button_->GetPreferredSize().height()); -} - -void FrameCaptionButtonContainerView::Layout() { - FrameCaptionButton::Style style = FrameCaptionButton::STYLE_SHORT_RESTORED; - if (header_style_ == HEADER_STYLE_SHORT) { - if (frame_->IsMaximized() || frame_->IsFullscreen()) - style = FrameCaptionButton::STYLE_SHORT_MAXIMIZED_OR_FULLSCREEN; - // Else: FrameCaptionButton::STYLE_SHORT_RESTORED; - } else { - style = FrameCaptionButton::STYLE_TALL_RESTORED; - } - - minimize_button_->SetStyle(style); - size_button_->SetStyle(style); - close_button_->SetStyle(style); - - int x = 0; - for (int i = 0; i < child_count(); ++i) { - views::View* child = child_at(i); - if (!child->visible()) - continue; - - gfx::Size size = child->GetPreferredSize(); - child->SetBounds(x, 0, size.width(), size.height()); - x += size.width() + kDistanceBetweenButtons; - } -} - -const char* FrameCaptionButtonContainerView::GetClassName() const { - return kViewClassName; -} - -void FrameCaptionButtonContainerView::OnPaint(gfx::Canvas* canvas) { - views::View::OnPaint(canvas); - - // The alternate button style does not paint the button separator. - if (!switches::UseAlternateFrameCaptionButtonStyle()) { - // We should have at most two visible buttons. The button separator is - // always painted underneath the close button regardless of whether a - // button other than the close button is visible. - gfx::Rect divider(close_button_->bounds().origin(), - button_separator_.size()); - canvas->DrawImageInt(button_separator_, - GetMirroredXForRect(divider), - divider.y()); - } -} - -void FrameCaptionButtonContainerView::ButtonPressed(views::Button* sender, - const ui::Event& event) { - // When shift-clicking, slow down animations for visual debugging. - // We used to do this via an event filter that looked for the shift key being - // pressed but this interfered with several normal keyboard shortcuts. - scoped_ptr<ui::ScopedAnimationDurationScaleMode> slow_duration_mode; - if (event.IsShiftDown()) { - slow_duration_mode.reset(new ui::ScopedAnimationDurationScaleMode( - ui::ScopedAnimationDurationScaleMode::SLOW_DURATION)); - } - - // Abort any animations of the button icons. - SetButtonsToNormal(ANIMATE_NO); - - ash::UserMetricsAction action = - ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MINIMIZE; - if (sender == minimize_button_) { - frame_->Minimize(); - } else if (sender == size_button_) { - if (frame_->IsFullscreen()) { // Can be clicked in immersive fullscreen. - frame_->SetFullscreen(false); - action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_EXIT_FULLSCREEN; - } else if (frame_->IsMaximized()) { - frame_->Restore(); - action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE; - } else { - frame_->Maximize(); - action = ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE; - } - } else if(sender == close_button_) { - frame_->Close(); - action = ash::UMA_WINDOW_CLOSE_BUTTON_CLICK; - } else { - return; - } - ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction(action); -} - -bool FrameCaptionButtonContainerView::IsMinimizeButtonVisible() const { - return minimize_button_->visible(); -} - -void FrameCaptionButtonContainerView::SetButtonsToNormal(Animate animate) { - SetButtonIcons(CAPTION_BUTTON_ICON_MINIMIZE, CAPTION_BUTTON_ICON_CLOSE, - animate); - minimize_button_->SetState(views::Button::STATE_NORMAL); - size_button_->SetState(views::Button::STATE_NORMAL); - close_button_->SetState(views::Button::STATE_NORMAL); -} - -void FrameCaptionButtonContainerView::SetButtonIcons( - CaptionButtonIcon minimize_button_icon, - CaptionButtonIcon close_button_icon, - Animate animate) { - FrameCaptionButton::Animate fcb_animate = (animate == ANIMATE_YES) ? - FrameCaptionButton::ANIMATE_YES : FrameCaptionButton::ANIMATE_NO; - minimize_button_->SetIcon(minimize_button_icon, fcb_animate); - close_button_->SetIcon(close_button_icon, fcb_animate); -} - -const FrameCaptionButton* -FrameCaptionButtonContainerView::PressButtonAt( - const gfx::Point& position_in_screen, - const gfx::Insets& pressed_hittest_outer_insets) const { - DCHECK(switches::UseAlternateFrameCaptionButtonStyle()); - gfx::Point position(position_in_screen); - views::View::ConvertPointFromScreen(this, &position); - - FrameCaptionButton* buttons[] = { - close_button_, size_button_, minimize_button_ - }; - FrameCaptionButton* pressed_button = NULL; - for (size_t i = 0; i < arraysize(buttons); ++i) { - FrameCaptionButton* button = buttons[i]; - if (!button->visible()) - continue; - - if (button->state() == views::Button::STATE_PRESSED) { - gfx::Rect expanded_bounds = button->bounds(); - expanded_bounds.Inset(pressed_hittest_outer_insets); - if (expanded_bounds.Contains(position)) { - pressed_button = button; - // Do not break in order to give preference to buttons which are - // closer to |position_in_screen| than the currently pressed button. - // TODO(pkotwicz): Make the caption buttons not overlap. - } - } else if (ConvertPointToViewAndHitTest(this, button, position)) { - pressed_button = button; - break; - } - } - - for (size_t i = 0; i < arraysize(buttons); ++i) { - buttons[i]->SetState(buttons[i] == pressed_button ? - views::Button::STATE_PRESSED : views::Button::STATE_NORMAL); - } - return pressed_button; -} - -} // namespace ash diff --git a/chromium/ash/wm/caption_buttons/frame_caption_button_container_view.h b/chromium/ash/wm/caption_buttons/frame_caption_button_container_view.h deleted file mode 100644 index 4fd663b5d70..00000000000 --- a/chromium/ash/wm/caption_buttons/frame_caption_button_container_view.h +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2013 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_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_ -#define ASH_WM_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/alternate_frame_size_button_delegate.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/views/controls/button/button.h" -#include "ui/views/view.h" - -namespace views { -class Widget; -} - -namespace ash { -class FrameCaptionButton; -class FrameMaximizeButton; - -// Container view for the frame caption buttons. It performs the appropriate -// action when a caption button is clicked. -class ASH_EXPORT FrameCaptionButtonContainerView - : public views::View, - public views::ButtonListener, - public AlternateFrameSizeButtonDelegate { - public: - static const char kViewClassName[]; - - // Whether the frame can be minimized (either via the maximize/restore button - // or via a dedicated button). - enum MinimizeAllowed { - MINIMIZE_ALLOWED, - MINIMIZE_DISALLOWED - }; - enum HeaderStyle { - // Default. - HEADER_STYLE_SHORT, - - // Restored tabbed browser windows. - HEADER_STYLE_TALL - }; - - // |frame| is the views::Widget that the caption buttons act on. - // |minimize_allowed| indicates whether the frame can be minimized (either via - // the maximize/restore button or via a dedicated button). - FrameCaptionButtonContainerView(views::Widget* frame, - MinimizeAllowed minimize_allowed); - virtual ~FrameCaptionButtonContainerView(); - - // For testing. - class TestApi { - public: - explicit TestApi(FrameCaptionButtonContainerView* container_view) - : container_view_(container_view) { - } - - FrameCaptionButton* minimize_button() const { - return container_view_->minimize_button_; - } - - FrameCaptionButton* size_button() const { - return container_view_->size_button_; - } - - FrameCaptionButton* close_button() const { - return container_view_->close_button_; - } - - private: - FrameCaptionButtonContainerView* container_view_; - - DISALLOW_COPY_AND_ASSIGN(TestApi); - }; - - // Returns the size button if using the old caption button style, returns NULL - // otherwise. - FrameMaximizeButton* GetOldStyleSizeButton(); - - // Tell the window controls to reset themselves to the normal state. - void ResetWindowControls(); - - // Determines the window HT* code for the caption button at |point|. Returns - // HTNOWHERE if |point| is not over any of the caption buttons. |point| must - // be in the coordinates of the FrameCaptionButtonContainerView. - int NonClientHitTest(const gfx::Point& point) const; - - // Sets the header style. - void set_header_style(HeaderStyle header_style) { - header_style_ = header_style; - } - - // views::View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual void Layout() OVERRIDE; - virtual const char* GetClassName() const OVERRIDE; - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; - - private: - friend class FrameCaptionButtonContainerViewTest; - - // views::ButtonListener override: - virtual void ButtonPressed(views::Button* sender, - const ui::Event& event) OVERRIDE; - - // AlternateFrameSizeButton::Delegate overrides: - virtual bool IsMinimizeButtonVisible() const OVERRIDE; - virtual void SetButtonsToNormal(Animate animate) OVERRIDE; - virtual void SetButtonIcons(CaptionButtonIcon minimize_button_icon, - CaptionButtonIcon close_button_icon, - Animate animate) OVERRIDE; - virtual const FrameCaptionButton* PressButtonAt( - const gfx::Point& position_in_screen, - const gfx::Insets& pressed_hittest_outer_insets) const OVERRIDE; - - // The widget that the buttons act on. - views::Widget* frame_; - - // The close button separator. - gfx::ImageSkia button_separator_; - - HeaderStyle header_style_; - - // The buttons. In the normal button style, at most one of |minimize_button_| - // and |size_button_| is visible. - FrameCaptionButton* minimize_button_; - FrameCaptionButton* size_button_; - FrameCaptionButton* close_button_; - - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerView); -}; - -} // namesapace ash - -#endif // ASH_WM_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_ diff --git a/chromium/ash/wm/caption_buttons/frame_caption_button_container_view_unittest.cc b/chromium/ash/wm/caption_buttons/frame_caption_button_container_view_unittest.cc deleted file mode 100644 index 589123125e9..00000000000 --- a/chromium/ash/wm/caption_buttons/frame_caption_button_container_view_unittest.cc +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2013 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/caption_buttons/frame_caption_button_container_view.h" - -#include "ash/ash_switches.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/caption_buttons/frame_caption_button.h" -#include "base/command_line.h" -#include "grit/ash_resources.h" -#include "ui/aura/root_window.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/views/border.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { - -namespace { - -class TestWidgetDelegate : public views::WidgetDelegateView { - public: - TestWidgetDelegate(bool can_maximize) : can_maximize_(can_maximize) { - } - virtual ~TestWidgetDelegate() { - } - - virtual bool CanMaximize() const OVERRIDE { - return can_maximize_; - } - - private: - bool can_maximize_; - - DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); -}; - -} // namespace - -class FrameCaptionButtonContainerViewTest : public ash::test::AshTestBase { - public: - enum MaximizeAllowed { - MAXIMIZE_ALLOWED, - MAXIMIZE_DISALLOWED - }; - - FrameCaptionButtonContainerViewTest() { - } - - virtual ~FrameCaptionButtonContainerViewTest() { - } - - // Creates a widget which allows maximizing based on |maximize_allowed|. - // The caller takes ownership of the returned widget. - views::Widget* CreateTestWidget( - MaximizeAllowed maximize_allowed) WARN_UNUSED_RESULT { - views::Widget* widget = new views::Widget; - views::Widget::InitParams params; - params.delegate = new TestWidgetDelegate( - maximize_allowed == MAXIMIZE_ALLOWED); - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.context = CurrentContext(); - widget->Init(params); - return widget; - } - - // Tests that |leftmost| and |rightmost| are at |container|'s edges. - bool CheckButtonsAtEdges(FrameCaptionButtonContainerView* container, - const ash::FrameCaptionButton& leftmost, - const ash::FrameCaptionButton& rightmost) { - gfx::Rect expected(container->GetPreferredSize()); - - gfx::Rect container_size(container->GetPreferredSize()); - if (leftmost.y() == rightmost.y() && - leftmost.height() == rightmost.height() && - leftmost.x() == expected.x() && - leftmost.y() == expected.y() && - leftmost.height() == expected.height() && - rightmost.bounds().right() == expected.right()) { - return true; - } - - LOG(ERROR) << "Buttons " << leftmost.bounds().ToString() << " " - << rightmost.bounds().ToString() << " not at edges of " - << expected.ToString(); - return false; - } - - // Returns true if the images for |button|'s states match the passed in ids. - bool ImagesMatch(ash::FrameCaptionButton* button, - int normal_image_id, - int hovered_image_id, - int pressed_image_id) { - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - gfx::ImageSkia* normal = rb.GetImageSkiaNamed(normal_image_id); - gfx::ImageSkia* hovered = rb.GetImageSkiaNamed(hovered_image_id); - gfx::ImageSkia* pressed = rb.GetImageSkiaNamed(pressed_image_id); - using views::Button; - gfx::ImageSkia actual_normal = button->GetImage(Button::STATE_NORMAL); - gfx::ImageSkia actual_hovered = button->GetImage(Button::STATE_HOVERED); - gfx::ImageSkia actual_pressed = button->GetImage(Button::STATE_PRESSED); - return actual_normal.BackedBySameObjectAs(*normal) && - actual_hovered.BackedBySameObjectAs(*hovered) && - actual_pressed.BackedBySameObjectAs(*pressed); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTest); -}; - -class FrameCaptionButtonContainerViewTestOldStyle - : public FrameCaptionButtonContainerViewTest { - public: - FrameCaptionButtonContainerViewTestOldStyle() { - } - - virtual ~FrameCaptionButtonContainerViewTestOldStyle() { - } - - virtual void SetUp() OVERRIDE { - FrameCaptionButtonContainerViewTest::SetUp(); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshDisableAlternateFrameCaptionButtonStyle); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTestOldStyle); -}; - -// Test how the allowed actions affect which caption buttons are visible. -TEST_F(FrameCaptionButtonContainerViewTestOldStyle, ButtonVisibility) { - // The minimize button should be hidden when both minimizing and maximizing - // are allowed because the size button can do both. - scoped_ptr<views::Widget> widget_can_maximize( - CreateTestWidget(MAXIMIZE_ALLOWED)); - FrameCaptionButtonContainerView container1(widget_can_maximize.get(), - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - container1.Layout(); - FrameCaptionButtonContainerView::TestApi t1(&container1); - EXPECT_FALSE(t1.minimize_button()->visible()); - EXPECT_TRUE(t1.size_button()->visible()); - EXPECT_TRUE(t1.close_button()->visible()); - EXPECT_TRUE(CheckButtonsAtEdges( - &container1, *t1.size_button(), *t1.close_button())); - - // The minimize button should be visible when minimizing is allowed but - // maximizing is disallowed. - scoped_ptr<views::Widget> widget_cannot_maximize( - CreateTestWidget(MAXIMIZE_DISALLOWED)); - FrameCaptionButtonContainerView container2(widget_cannot_maximize.get(), - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - container2.Layout(); - FrameCaptionButtonContainerView::TestApi t2(&container2); - EXPECT_TRUE(t2.minimize_button()->visible()); - EXPECT_FALSE(t2.size_button()->visible()); - EXPECT_TRUE(t2.close_button()->visible()); - EXPECT_TRUE(CheckButtonsAtEdges( - &container2, *t2.minimize_button(), *t2.close_button())); - - // Neither the minimize button nor the size button should be visible when - // neither minimizing nor maximizing are allowed. - FrameCaptionButtonContainerView container3(widget_cannot_maximize.get(), - FrameCaptionButtonContainerView::MINIMIZE_DISALLOWED); - container3.Layout(); - FrameCaptionButtonContainerView::TestApi t3(&container3); - EXPECT_FALSE(t3.minimize_button()->visible()); - EXPECT_FALSE(t3.size_button()->visible()); - EXPECT_TRUE(t3.close_button()->visible()); - EXPECT_TRUE(CheckButtonsAtEdges( - &container3, *t3.close_button(), *t3.close_button())); -} - -// Test how the header style affects which images are used for the buttons. -TEST_F(FrameCaptionButtonContainerViewTestOldStyle, HeaderStyle) { - scoped_ptr<views::Widget> widget(CreateTestWidget(MAXIMIZE_ALLOWED)); - FrameCaptionButtonContainerView container(widget.get(), - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - FrameCaptionButtonContainerView::TestApi t(&container); - - // Tall header style. - container.set_header_style( - FrameCaptionButtonContainerView::HEADER_STYLE_TALL); - container.Layout(); - EXPECT_TRUE(ImagesMatch(t.size_button(), - IDR_AURA_WINDOW_MAXIMIZE, - IDR_AURA_WINDOW_MAXIMIZE_H, - IDR_AURA_WINDOW_MAXIMIZE_P)); - EXPECT_TRUE(ImagesMatch(t.close_button(), - IDR_AURA_WINDOW_CLOSE, - IDR_AURA_WINDOW_CLOSE_H, - IDR_AURA_WINDOW_CLOSE_P)); - - // Short header style. - container.set_header_style( - FrameCaptionButtonContainerView::HEADER_STYLE_SHORT); - container.Layout(); - EXPECT_TRUE(ImagesMatch(t.size_button(), - IDR_AURA_WINDOW_MAXIMIZED_RESTORE, - IDR_AURA_WINDOW_MAXIMIZED_RESTORE_H, - IDR_AURA_WINDOW_MAXIMIZED_RESTORE_P)); - EXPECT_TRUE(ImagesMatch(t.close_button(), - IDR_AURA_WINDOW_MAXIMIZED_CLOSE, - IDR_AURA_WINDOW_MAXIMIZED_CLOSE_H, - IDR_AURA_WINDOW_MAXIMIZED_CLOSE_P)); - - // Maximized short header style. - widget->Maximize(); - container.Layout(); - EXPECT_TRUE(ImagesMatch(t.size_button(), - IDR_AURA_WINDOW_MAXIMIZED_RESTORE2, - IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_H, - IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_P)); - EXPECT_TRUE(ImagesMatch(t.close_button(), - IDR_AURA_WINDOW_MAXIMIZED_CLOSE2, - IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_H, - IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_P)); - - // The buttons are visible during a reveal of the top-of-window views in - // immersive fullscreen. They should use the same images as maximized. - widget->SetFullscreen(true); - container.Layout(); - EXPECT_TRUE(ImagesMatch(t.size_button(), - IDR_AURA_WINDOW_MAXIMIZED_RESTORE2, - IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_H, - IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_P)); - EXPECT_TRUE(ImagesMatch(t.close_button(), - IDR_AURA_WINDOW_MAXIMIZED_CLOSE2, - IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_H, - IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_P)); -} - -class FrameCaptionButtonContainerViewTestAlternateStyle - : public FrameCaptionButtonContainerViewTest { - public: - FrameCaptionButtonContainerViewTestAlternateStyle() { - } - - virtual ~FrameCaptionButtonContainerViewTestAlternateStyle() { - } - - virtual void SetUp() OVERRIDE { - FrameCaptionButtonContainerViewTest::SetUp(); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshEnableAlternateFrameCaptionButtonStyle); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTestAlternateStyle); -}; - -// Test how the alternate button style affects which buttons are visible in the -// default case. -TEST_F(FrameCaptionButtonContainerViewTestAlternateStyle, ButtonVisibility) { - // Using the alternate caption button style is dependant on all snapped - // windows being 50% of the screen's width. - if (!switches::UseAlternateFrameCaptionButtonStyle()) - return; - - // Both the minimize button and the maximize button should be visible when - // both minimizing and maximizing are allowed when using the alternate - // button style. - scoped_ptr<views::Widget> widget_can_maximize( - CreateTestWidget(MAXIMIZE_ALLOWED)); - FrameCaptionButtonContainerView container(widget_can_maximize.get(), - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - container.Layout(); - FrameCaptionButtonContainerView::TestApi t(&container); - EXPECT_TRUE(t.minimize_button()->visible()); - EXPECT_TRUE(t.size_button()->visible()); - EXPECT_TRUE(t.close_button()->visible()); - EXPECT_TRUE(CheckButtonsAtEdges( - &container, *t.minimize_button(), *t.close_button())); -} - -} // namespace ash diff --git a/chromium/ash/wm/caption_buttons/frame_maximize_button.cc b/chromium/ash/wm/caption_buttons/frame_maximize_button.cc deleted file mode 100644 index d2f24f01d90..00000000000 --- a/chromium/ash/wm/caption_buttons/frame_maximize_button.cc +++ /dev/null @@ -1,591 +0,0 @@ -// Copyright 2013 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/caption_buttons/frame_maximize_button.h" - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/touch/touch_uma.h" -#include "ash/wm/caption_buttons/frame_maximize_button_observer.h" -#include "ash/wm/caption_buttons/maximize_bubble_controller.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_state.h" -#include "ash/wm/workspace/phantom_window_controller.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "grit/ash_strings.h" -#include "ui/aura/window.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/events/event.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" -#include "ui/views/window/non_client_view.h" - -using ash::internal::SnapSizer; - -namespace ash { - -namespace { - -// Delay before forcing an update of the snap location. -const int kUpdateDelayMS = 400; - -// The delay of the bubble appearance. -const int kBubbleAppearanceDelayMS = 500; - -// The minimum sanp size in percent of the screen width. -const int kMinSnapSizePercent = 50; -} - -// EscapeEventFilter is installed on the RootWindow to track when the escape key -// is pressed. We use an EventFilter for this as the FrameMaximizeButton -// normally does not get focus. -class FrameMaximizeButton::EscapeEventFilter : public ui::EventHandler { - public: - explicit EscapeEventFilter(FrameMaximizeButton* button); - virtual ~EscapeEventFilter(); - - // EventFilter overrides: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - - private: - FrameMaximizeButton* button_; - - DISALLOW_COPY_AND_ASSIGN(EscapeEventFilter); -}; - -FrameMaximizeButton::EscapeEventFilter::EscapeEventFilter( - FrameMaximizeButton* button) - : button_(button) { - Shell::GetInstance()->AddPreTargetHandler(this); -} - -FrameMaximizeButton::EscapeEventFilter::~EscapeEventFilter() { - Shell::GetInstance()->RemovePreTargetHandler(this); -} - -void FrameMaximizeButton::EscapeEventFilter::OnKeyEvent( - ui::KeyEvent* event) { - if (event->type() == ui::ET_KEY_PRESSED && - event->key_code() == ui::VKEY_ESCAPE) { - button_->Cancel(false); - } -} - -// FrameMaximizeButton --------------------------------------------------------- - -FrameMaximizeButton::FrameMaximizeButton(views::ButtonListener* listener, - views::Widget* frame) - : FrameCaptionButton(listener, CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE), - frame_(frame), - observing_frame_(false), - is_snap_enabled_(false), - exceeded_drag_threshold_(false), - press_is_gesture_(false), - snap_type_(SNAP_NONE), - bubble_appearance_delay_ms_(kBubbleAppearanceDelayMS) { - // TODO(sky): nuke this. It's temporary while we don't have good images. - SetImageAlignment(ALIGN_LEFT, ALIGN_BOTTOM); -} - -FrameMaximizeButton::~FrameMaximizeButton() { - // Before the window gets destroyed, the maximizer dialog needs to be shut - // down since it would otherwise call into a deleted object. - maximizer_.reset(); - if (observing_frame_) - OnWindowDestroying(frame_->GetNativeWindow()); -} - -void FrameMaximizeButton::AddObserver(FrameMaximizeButtonObserver* observer) { - observer_list_.AddObserver(observer); -} - -void FrameMaximizeButton::RemoveObserver( - FrameMaximizeButtonObserver* observer) { - observer_list_.RemoveObserver(observer); -} - -void FrameMaximizeButton::SnapButtonHovered(SnapType type) { - // Make sure to only show hover operations when no button is pressed and - // a similar snap operation in progress does not get re-applied. - if (is_snap_enabled_ || (type == snap_type_ && snap_sizer_)) - return; - // Prime the mouse location with the center of the (local) button. - press_location_ = gfx::Point(width() / 2, height() / 2); - // Then get an adjusted mouse position to initiate the effect. - gfx::Point location = press_location_; - switch (type) { - case SNAP_LEFT: - location.set_x(location.x() - width()); - break; - case SNAP_RIGHT: - location.set_x(location.x() + width()); - break; - case SNAP_MINIMIZE: - location.set_y(location.y() + height()); - break; - case SNAP_RESTORE: - // Simulate a mouse button move over the according button. - if (GetMaximizeBubbleFrameState() == FRAME_STATE_SNAP_LEFT) - location.set_x(location.x() - width()); - else if (GetMaximizeBubbleFrameState() == FRAME_STATE_SNAP_RIGHT) - location.set_x(location.x() + width()); - break; - case SNAP_MAXIMIZE: - break; - case SNAP_NONE: - Cancel(true); - return; - default: - // We should not come here. - NOTREACHED(); - } - // Note: There is no hover with touch - we can therefore pass false for touch - // operations. - UpdateSnap(location, true, false); -} - -void FrameMaximizeButton::ExecuteSnapAndCloseMenu(SnapType snap_type) { - // We can come here with no snap type set in case that the mouse opened the - // maximize button and a touch event "touched" a button. - if (snap_type_ == SNAP_NONE) - SnapButtonHovered(snap_type); - - Cancel(true); - // Tell our menu to close. - maximizer_.reset(); - snap_type_ = snap_type; - // Since Snap might destroy |this|, but the snap_sizer needs to be destroyed, - // The ownership of the snap_sizer is taken now. - scoped_ptr<SnapSizer> snap_sizer(snap_sizer_.release()); - Snap(snap_sizer.get()); -} - -void FrameMaximizeButton::OnMaximizeBubbleShown(views::Widget* bubble) { - FOR_EACH_OBSERVER(FrameMaximizeButtonObserver, - observer_list_, - OnMaximizeBubbleShown(bubble)); -} - -void FrameMaximizeButton::DestroyMaximizeMenu() { - Cancel(false); -} - -void FrameMaximizeButton::OnWindowBoundsChanged( - aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - Cancel(false); -} - -void FrameMaximizeButton::OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) { - Cancel(false); -} - -void FrameMaximizeButton::OnWindowDestroying(aura::Window* window) { - maximizer_.reset(); - if (observing_frame_) { - CHECK_EQ(frame_->GetNativeWindow(), window); - frame_->GetNativeWindow()->RemoveObserver(this); - frame_->RemoveObserver(this); - observing_frame_ = false; - } -} - -void FrameMaximizeButton::OnWidgetActivationChanged(views::Widget* widget, - bool active) { - // Upon losing focus, the bubble menu and the phantom window should hide. - if (!active) - Cancel(false); -} - -bool FrameMaximizeButton::OnMousePressed(const ui::MouseEvent& event) { - // If we are already in a mouse click / drag operation, a second button down - // call will cancel (this addresses crbug.com/143755). - if (is_snap_enabled_) { - Cancel(false); - } else { - is_snap_enabled_ = event.IsOnlyLeftMouseButton(); - if (is_snap_enabled_) - ProcessStartEvent(event); - } - ImageButton::OnMousePressed(event); - return true; -} - -void FrameMaximizeButton::OnMouseEntered(const ui::MouseEvent& event) { - ImageButton::OnMouseEntered(event); - if (!maximizer_) { - DCHECK(GetWidget()); - if (!observing_frame_) { - observing_frame_ = true; - frame_->GetNativeWindow()->AddObserver(this); - frame_->AddObserver(this); - } - maximizer_.reset(new MaximizeBubbleController( - this, - GetMaximizeBubbleFrameState(), - bubble_appearance_delay_ms_)); - } -} - -void FrameMaximizeButton::OnMouseExited(const ui::MouseEvent& event) { - ImageButton::OnMouseExited(event); - // Remove the bubble menu when the button is not pressed and the mouse is not - // within the bubble. - if (!is_snap_enabled_ && maximizer_) { - if (maximizer_->GetBubbleWindow()) { - gfx::Point screen_location = Shell::GetScreen()->GetCursorScreenPoint(); - if (!maximizer_->GetBubbleWindow()->GetBoundsInScreen().Contains( - screen_location)) { - maximizer_.reset(); - // Make sure that all remaining snap hover states get removed. - SnapButtonHovered(SNAP_NONE); - } - } else { - // The maximize dialog does not show up immediately after creating the - // |maximizer_|. Destroy the dialog therefore before it shows up. - maximizer_.reset(); - } - } -} - -bool FrameMaximizeButton::OnMouseDragged(const ui::MouseEvent& event) { - if (is_snap_enabled_) - ProcessUpdateEvent(event); - return ImageButton::OnMouseDragged(event); -} - -void FrameMaximizeButton::OnMouseReleased(const ui::MouseEvent& event) { - maximizer_.reset(); - bool snap_was_enabled = is_snap_enabled_; - if (!ProcessEndEvent(event) && snap_was_enabled) - ImageButton::OnMouseReleased(event); - // At this point |this| might be already destroyed. -} - -void FrameMaximizeButton::OnMouseCaptureLost() { - Cancel(false); - ImageButton::OnMouseCaptureLost(); -} - -void FrameMaximizeButton::OnGestureEvent(ui::GestureEvent* event) { - if (event->type() == ui::ET_GESTURE_TAP_DOWN) { - is_snap_enabled_ = true; - ProcessStartEvent(*event); - event->SetHandled(); - return; - } - - if (event->type() == ui::ET_GESTURE_TAP || - (event->type() == ui::ET_GESTURE_SCROLL_END && is_snap_enabled_) || - event->type() == ui::ET_SCROLL_FLING_START) { - // The position of the event may have changed from the previous event (both - // for TAP and SCROLL_END). So it is necessary to update the snap-state for - // the current event. - ProcessUpdateEvent(*event); - if (event->type() == ui::ET_GESTURE_TAP) { - snap_type_ = SnapTypeForLocation(event->location()); - TouchUMA::GetInstance()->RecordGestureAction( - TouchUMA::GESTURE_FRAMEMAXIMIZE_TAP); - } - ProcessEndEvent(*event); - event->SetHandled(); - return; - } - - if (is_snap_enabled_) { - if (event->type() == ui::ET_GESTURE_END && - event->details().touch_points() == 1) { - // The position of the event may have changed from the previous event. So - // it is necessary to update the snap-state for the current event. - ProcessUpdateEvent(*event); - snap_type_ = SnapTypeForLocation(event->location()); - ProcessEndEvent(*event); - event->SetHandled(); - return; - } - - if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE || - event->type() == ui::ET_GESTURE_SCROLL_BEGIN) { - ProcessUpdateEvent(*event); - event->SetHandled(); - return; - } - } - - ImageButton::OnGestureEvent(event); -} - -void FrameMaximizeButton::SetVisible(bool visible) { - views::View::SetVisible(visible); -} - -void FrameMaximizeButton::ProcessStartEvent(const ui::LocatedEvent& event) { - DCHECK(is_snap_enabled_); - // Prepare the help menu. - if (!maximizer_) { - maximizer_.reset(new MaximizeBubbleController( - this, - GetMaximizeBubbleFrameState(), - bubble_appearance_delay_ms_)); - } else { - // If the menu did not show up yet, we delay it even a bit more. - maximizer_->DelayCreation(); - } - snap_sizer_.reset(NULL); - InstallEventFilter(); - snap_type_ = SNAP_NONE; - press_location_ = event.location(); - press_is_gesture_ = event.IsGestureEvent(); - exceeded_drag_threshold_ = false; - update_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kUpdateDelayMS), - this, - &FrameMaximizeButton::UpdateSnapFromEventLocation); -} - -void FrameMaximizeButton::ProcessUpdateEvent(const ui::LocatedEvent& event) { - DCHECK(is_snap_enabled_); - if (!exceeded_drag_threshold_) { - exceeded_drag_threshold_ = views::View::ExceededDragThreshold( - event.location() - press_location_); - } - if (exceeded_drag_threshold_) - UpdateSnap(event.location(), false, event.IsGestureEvent()); -} - -bool FrameMaximizeButton::ProcessEndEvent(const ui::LocatedEvent& event) { - update_timer_.Stop(); - UninstallEventFilter(); - bool should_snap = is_snap_enabled_; - is_snap_enabled_ = false; - - // Remove our help bubble. - maximizer_.reset(); - - if (!should_snap || snap_type_ == SNAP_NONE) - return false; - - SetState(views::CustomButton::STATE_NORMAL); - // SetState will not call SchedulePaint() if state was already set to - // STATE_NORMAL during a drag. - SchedulePaint(); - phantom_window_.reset(); - // Since Snap might destroy |this|, but the snap_sizer needs to be destroyed, - // The ownership of the snap_sizer is taken now. - scoped_ptr<SnapSizer> snap_sizer(snap_sizer_.release()); - Snap(snap_sizer.get()); - return true; -} - -void FrameMaximizeButton::Cancel(bool keep_menu_open) { - if (!keep_menu_open) { - maximizer_.reset(); - UninstallEventFilter(); - is_snap_enabled_ = false; - snap_sizer_.reset(); - } - phantom_window_.reset(); - snap_type_ = SNAP_NONE; - update_timer_.Stop(); - SchedulePaint(); -} - -void FrameMaximizeButton::InstallEventFilter() { - if (escape_event_filter_) - return; - - escape_event_filter_.reset(new EscapeEventFilter(this)); -} - -void FrameMaximizeButton::UninstallEventFilter() { - escape_event_filter_.reset(NULL); -} - -void FrameMaximizeButton::UpdateSnapFromEventLocation() { - // If the drag threshold has been exceeded the snap location is up to date. - if (exceeded_drag_threshold_) - return; - exceeded_drag_threshold_ = true; - UpdateSnap(press_location_, false, press_is_gesture_); -} - -void FrameMaximizeButton::UpdateSnap(const gfx::Point& location, - bool select_default, - bool is_touch) { - SnapType type = SnapTypeForLocation(location); - if (type == snap_type_) { - if (snap_sizer_) { - snap_sizer_->Update(LocationForSnapSizer(location)); - phantom_window_->Show(ScreenAsh::ConvertRectToScreen( - frame_->GetNativeView()->parent(), - snap_sizer_->target_bounds())); - } - return; - } - - snap_type_ = type; - snap_sizer_.reset(); - SchedulePaint(); - - if (snap_type_ == SNAP_NONE) { - phantom_window_.reset(); - return; - } - - if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) { - SnapSizer::Edge snap_edge = snap_type_ == SNAP_LEFT ? - SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; - SnapSizer::InputType input_type = - is_touch ? SnapSizer::TOUCH_MAXIMIZE_BUTTON_INPUT : - SnapSizer::OTHER_INPUT; - snap_sizer_.reset(new SnapSizer( - wm::GetWindowState(frame_->GetNativeWindow()), - LocationForSnapSizer(location), - snap_edge, - input_type)); - if (select_default) - snap_sizer_->SelectDefaultSizeAndDisableResize(); - } - if (!phantom_window_) { - phantom_window_.reset(new internal::PhantomWindowController( - frame_->GetNativeWindow())); - } - if (maximizer_) { - phantom_window_->set_phantom_below_window(maximizer_->GetBubbleWindow()); - maximizer_->SetSnapType(snap_type_); - } - phantom_window_->Show( - ScreenBoundsForType(snap_type_, *snap_sizer_.get())); -} - -SnapType FrameMaximizeButton::SnapTypeForLocation( - const gfx::Point& location) const { - MaximizeBubbleFrameState maximize_type = GetMaximizeBubbleFrameState(); - gfx::Vector2d delta(location - press_location_); - if (!views::View::ExceededDragThreshold(delta)) - return maximize_type != FRAME_STATE_FULL ? SNAP_MAXIMIZE : SNAP_RESTORE; - if (delta.x() < 0 && delta.y() > delta.x() && delta.y() < -delta.x()) - return maximize_type == FRAME_STATE_SNAP_LEFT ? SNAP_RESTORE : SNAP_LEFT; - if (delta.x() > 0 && delta.y() > -delta.x() && delta.y() < delta.x()) - return maximize_type == FRAME_STATE_SNAP_RIGHT ? SNAP_RESTORE : SNAP_RIGHT; - if (delta.y() > 0) - return SNAP_MINIMIZE; - return maximize_type != FRAME_STATE_FULL ? SNAP_MAXIMIZE : SNAP_RESTORE; -} - -gfx::Rect FrameMaximizeButton::ScreenBoundsForType( - SnapType type, - const SnapSizer& snap_sizer) const { - aura::Window* window = frame_->GetNativeWindow(); - switch (type) { - case SNAP_LEFT: - case SNAP_RIGHT: - return ScreenAsh::ConvertRectToScreen(window->parent(), - snap_sizer.target_bounds()); - case SNAP_MAXIMIZE: - return ScreenAsh::ConvertRectToScreen( - window->parent(), - ScreenAsh::GetMaximizedWindowBoundsInParent(window)); - case SNAP_MINIMIZE: { - gfx::Rect rect = GetMinimizeAnimationTargetBoundsInScreen(window); - if (!rect.IsEmpty()) { - // PhantomWindowController insets slightly, outset it so the phantom - // doesn't appear inset. - rect.Inset(-8, -8); - } - return rect; - } - case SNAP_RESTORE: { - wm::WindowState* window_state = wm::GetWindowState(window); - return window_state->HasRestoreBounds() ? - window_state->GetRestoreBoundsInScreen() : - frame_->GetWindowBoundsInScreen(); - } - case SNAP_NONE: - NOTREACHED(); - } - return gfx::Rect(); -} - -gfx::Point FrameMaximizeButton::LocationForSnapSizer( - const gfx::Point& location) const { - gfx::Point result(location); - views::View::ConvertPointToScreen(this, &result); - return result; -} - -void FrameMaximizeButton::Snap(SnapSizer* snap_sizer) { - Shell* shell = Shell::GetInstance(); - switch (snap_type_) { - case SNAP_LEFT: - case SNAP_RIGHT: { - snap_sizer->SnapWindowToTargetBounds(); - shell->metrics()->RecordUserMetricsAction( - snap_type_ == SNAP_LEFT ? - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT : - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT); - break; - } - case SNAP_MAXIMIZE: - frame_->Maximize(); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE); - break; - case SNAP_MINIMIZE: - frame_->Minimize(); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_MINIMIZE); - break; - case SNAP_RESTORE: - frame_->Restore(); - shell->metrics()->RecordUserMetricsAction( - UMA_WINDOW_MAXIMIZE_BUTTON_RESTORE); - break; - case SNAP_NONE: - NOTREACHED(); - } -} - -MaximizeBubbleFrameState -FrameMaximizeButton::GetMaximizeBubbleFrameState() const { - wm::WindowState* window_state = - wm::GetWindowState(frame_->GetNativeWindow()); - // When there are no restore bounds, we are in normal mode. - if (!window_state->HasRestoreBounds()) - return FRAME_STATE_NONE; - // The normal maximized test can be used. - if (frame_->IsMaximized()) - return FRAME_STATE_FULL; - // For Left/right maximize we need to check the dimensions. - gfx::Rect bounds = frame_->GetWindowBoundsInScreen(); - gfx::Rect screen = Shell::GetScreen()->GetDisplayNearestWindow( - frame_->GetNativeView()).work_area(); - if (bounds.width() < (screen.width() * kMinSnapSizePercent) / 100) - return FRAME_STATE_NONE; - // We might still have a horizontally filled window at this point which we - // treat as no special state. - if (bounds.y() != screen.y() || bounds.height() != screen.height()) - return FRAME_STATE_NONE; - - // We have to be in a maximize mode at this point. - if (bounds.x() == screen.x()) - return FRAME_STATE_SNAP_LEFT; - if (bounds.right() == screen.right()) - return FRAME_STATE_SNAP_RIGHT; - // If we come here, it is likely caused by the fact that the - // "VerticalResizeDoubleClick" stored a restore rectangle. In that case - // we allow all maximize operations (and keep the restore rectangle). - return FRAME_STATE_NONE; -} - -} // namespace ash diff --git a/chromium/ash/wm/caption_buttons/frame_maximize_button.h b/chromium/ash/wm/caption_buttons/frame_maximize_button.h deleted file mode 100644 index a1bb991a98f..00000000000 --- a/chromium/ash/wm/caption_buttons/frame_maximize_button.h +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2013 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_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_H_ -#define ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/caption_button_types.h" -#include "ash/wm/caption_buttons/frame_caption_button.h" -#include "ash/wm/workspace/snap_types.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "base/timer/timer.h" -#include "ui/aura/window_observer.h" -#include "ui/views/widget/widget_observer.h" - -namespace views { -class Widget; -} - -namespace ash { -class FrameMaximizeButtonObserver; - -namespace internal { -class PhantomWindowController; -class SnapSizer; -} - -class MaximizeBubbleController; - -// Button used for the maximize control on the frame. Handles snapping logic. -class ASH_EXPORT FrameMaximizeButton : public FrameCaptionButton, - public views::WidgetObserver, - public aura::WindowObserver { - public: - FrameMaximizeButton(views::ButtonListener* listener, - views::Widget* frame); - virtual ~FrameMaximizeButton(); - - void AddObserver(FrameMaximizeButtonObserver* observer); - void RemoveObserver(FrameMaximizeButtonObserver* observer); - - // Updates |snap_type_| based on a a given snap type. This is used by - // external hover events from the button menu. - void SnapButtonHovered(SnapType type); - - // The user clicked the |type| button and the action needs to be performed, - // which will at the same time close the window. - void ExecuteSnapAndCloseMenu(SnapType type); - - // Called by the MaximizeBubbleController when the maximize bubble is shown. - void OnMaximizeBubbleShown(views::Widget* bubble); - - // Remove the maximize menu from the screen (and destroy it). - void DestroyMaximizeMenu(); - - // Returns true when the user clicks and drags the button. - bool is_snap_enabled() const { return is_snap_enabled_; } - - // WindowObserver overrides: - virtual void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - // WidgetObserver overrides: - virtual void OnWidgetActivationChanged(views::Widget* widget, - bool active) OVERRIDE; - - // ImageButton overrides: - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseCaptureLost() OVERRIDE; - - // ui::EventHandler overrides: - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - // views::View overwrite: - virtual void SetVisible(bool visible) OVERRIDE; - - // Unit test overwrite: Change the UI delay used for the bubble show up. - void set_bubble_appearance_delay_ms(int bubble_appearance_delay_ms) { - bubble_appearance_delay_ms_ = bubble_appearance_delay_ms; - } - - // Unit test accessor for the maximize bubble. - MaximizeBubbleController* maximizer() { return maximizer_.get(); } - - // Unit test to see if phantom window is open. - bool phantom_window_open() { return phantom_window_.get() != NULL; } - - private: - class EscapeEventFilter; - - // Initializes the snap-gesture based on the event. This should only be called - // when the event is confirmed to have started a snap gesture. - void ProcessStartEvent(const ui::LocatedEvent& event); - - // Updates the snap-state based on the current event. This should only be - // called after the snap gesture has already started. - void ProcessUpdateEvent(const ui::LocatedEvent& event); - - // Returns true if the window was snapped. Returns false otherwise. - bool ProcessEndEvent(const ui::LocatedEvent& event); - - // Cancels snap behavior. If |keep_menu_open| is set, a possibly opened - // bubble help will remain open. - void Cancel(bool keep_menu_open); - - // Installs/uninstalls an EventFilter to track when escape is pressed. - void InstallEventFilter(); - void UninstallEventFilter(); - - // Updates the snap position from the event location. This is invoked by - // |update_timer_|. - void UpdateSnapFromEventLocation(); - - // Updates |snap_type_| based on a mouse drag. If |select_default| is set, - // the single button click default setting of the snap sizer should be used. - // Set |is_touch| to true to make touch snapping at the corners possible. - void UpdateSnap(const gfx::Point& location, - bool select_default, - bool is_touch); - - // Returns the type of snap based on the specified location. - SnapType SnapTypeForLocation(const gfx::Point& location) const; - - // Returns the bounds of the resulting window for the specified type. - gfx::Rect ScreenBoundsForType(SnapType type, - const internal::SnapSizer& snap_sizer) const; - - // Converts location to screen coordinates and returns it. These are the - // coordinates used by the SnapSizer. - gfx::Point LocationForSnapSizer(const gfx::Point& location) const; - - // Snaps the window to the current snap position. - void Snap(internal::SnapSizer* snap_sizer); - - // Determine the maximize type of this window. - MaximizeBubbleFrameState GetMaximizeBubbleFrameState() const; - - // Widget that the maximize button acts on. This is different than the widget - // which contains the button in the case of AppNonClientFrameViewAsh. - views::Widget* frame_; - - // True if we have put observers on |frame_|. - bool observing_frame_; - - // Renders the snap position. - scoped_ptr<internal::PhantomWindowController> phantom_window_; - - // Is snapping enabled? Set on press so that in drag we know whether we - // should show the snap locations. - bool is_snap_enabled_; - - // Did the user drag far enough to trigger snapping? - bool exceeded_drag_threshold_; - - // Location of the press. - gfx::Point press_location_; - - // True if the press was triggered by a gesture/touch. - bool press_is_gesture_; - - // Current snap type. - SnapType snap_type_; - - scoped_ptr<internal::SnapSizer> snap_sizer_; - - scoped_ptr<EscapeEventFilter> escape_event_filter_; - - base::OneShotTimer<FrameMaximizeButton> update_timer_; - - scoped_ptr<MaximizeBubbleController> maximizer_; - - // The delay of the bubble appearance. - int bubble_appearance_delay_ms_; - - ObserverList<FrameMaximizeButtonObserver> observer_list_; - - DISALLOW_COPY_AND_ASSIGN(FrameMaximizeButton); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_H_ diff --git a/chromium/ash/wm/caption_buttons/frame_maximize_button_observer.h b/chromium/ash/wm/caption_buttons/frame_maximize_button_observer.h deleted file mode 100644 index 1962f60416c..00000000000 --- a/chromium/ash/wm/caption_buttons/frame_maximize_button_observer.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 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_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_ -#define ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_ - -#include "ash/ash_export.h" - -namespace views { -class Widget; -} - -namespace ash { - -class ASH_EXPORT FrameMaximizeButtonObserver { - public: - virtual ~FrameMaximizeButtonObserver() {} - - // Called when the maximize button's help bubble is shown. - virtual void OnMaximizeBubbleShown(views::Widget* bubble) = 0; -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_ diff --git a/chromium/ash/wm/caption_buttons/frame_maximize_button_unittest.cc b/chromium/ash/wm/caption_buttons/frame_maximize_button_unittest.cc deleted file mode 100644 index c0fd2a0a8a9..00000000000 --- a/chromium/ash/wm/caption_buttons/frame_maximize_button_unittest.cc +++ /dev/null @@ -1,878 +0,0 @@ -// Copyright 2013 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/caption_buttons/frame_maximize_button.h" - -#include "ash/ash_switches.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/caption_buttons/maximize_bubble_controller.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "base/command_line.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/window.h" -#include "ui/events/event_utils.h" -#include "ui/events/gestures/gesture_configuration.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -namespace test { - -namespace { - -class CancelCallbackHandler { - public: - CancelCallbackHandler(int update_events_before_cancel, - FrameMaximizeButton* maximize_button) : - update_events_before_cancel_(update_events_before_cancel), - maximize_button_(maximize_button) {} - virtual ~CancelCallbackHandler() {} - - void CountedCancelCallback(ui::EventType event_type, - const gfx::Vector2dF& pos) { - if (event_type == ui::ET_GESTURE_SCROLL_UPDATE && - !(--update_events_before_cancel_)) { - // Make sure that we are in the middle of a resizing operation, cancel it - // and then test that it is exited. - EXPECT_TRUE(maximize_button_->is_snap_enabled()); - maximize_button_->DestroyMaximizeMenu(); - EXPECT_FALSE(maximize_button_->is_snap_enabled()); - } - } - - private: - // When this counter reaches 0, the gesture maximize action gets cancelled. - int update_events_before_cancel_; - - // The maximize button which needs to get informed of the gesture termination. - FrameMaximizeButton* maximize_button_; - - DISALLOW_COPY_AND_ASSIGN(CancelCallbackHandler); -}; - -class TestWidgetDelegate : public views::WidgetDelegateView { - public: - TestWidgetDelegate() {} - virtual ~TestWidgetDelegate() {} - - // views::WidgetDelegate overrides: - virtual views::View* GetContentsView() OVERRIDE { - return this; - } - virtual bool CanResize() const OVERRIDE { - return true; - } - virtual bool CanMaximize() const OVERRIDE { - return true; - } - - ash::FrameCaptionButtonContainerView* caption_button_container() { - return caption_button_container_; - } - - private: - // Overridden from views::View: - virtual void Layout() OVERRIDE { - caption_button_container_->Layout(); - - // Right align the caption button container. - gfx::Size preferred_size = caption_button_container_->GetPreferredSize(); - caption_button_container_->SetBounds(width() - preferred_size.width(), 0, - preferred_size.width(), preferred_size.height()); - } - - virtual void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) OVERRIDE { - if (details.is_add && details.child == this) { - caption_button_container_ = new FrameCaptionButtonContainerView( - GetWidget(), FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - AddChildView(caption_button_container_); - } - } - - // Not owned. - ash::FrameCaptionButtonContainerView* caption_button_container_; - - DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); -}; - -} // namespace - -class FrameMaximizeButtonTest : public ash::test::AshTestBase { - public: - FrameMaximizeButtonTest() {} - virtual ~FrameMaximizeButtonTest() {} - - // The returned widget takes ownership of |delegate|. - views::Widget* CreateWidget(views::WidgetDelegate* delegate) { - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - views::Widget* widget = new views::Widget; - params.context = CurrentContext(); - params.delegate = delegate; - params.bounds = gfx::Rect(10, 10, 100, 100); - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - widget->Init(params); - widget->Show(); - return widget; - } - - void CloseWidget() { - if (widget_) - widget_->CloseNow(); - widget_ = NULL; - } - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshDisableAlternateFrameCaptionButtonStyle); - - TestWidgetDelegate* delegate = new TestWidgetDelegate(); - widget_ = CreateWidget(delegate); - FrameCaptionButtonContainerView* caption_button_container = - delegate->caption_button_container(); - - FrameCaptionButtonContainerView::TestApi test(caption_button_container); - maximize_button_ = static_cast<FrameMaximizeButton*>( - test.size_button()); - } - - virtual void TearDown() OVERRIDE { - CloseWidget(); - AshTestBase::TearDown(); - } - - views::Widget* widget() { return widget_; } - - FrameMaximizeButton* maximize_button() { return maximize_button_; } - - private: - views::Widget* widget_; - FrameMaximizeButton* maximize_button_; - - DISALLOW_COPY_AND_ASSIGN(FrameMaximizeButtonTest); -}; - -// Tests that clicking on the resize-button toggles between maximize and normal -// state. -TEST_F(FrameMaximizeButtonTest, ResizeButtonToggleMaximize) { - wm::WindowState* window_state = - wm::GetWindowState(widget()->GetNativeWindow()); - views::View* view = maximize_button(); - gfx::Point center = view->GetBoundsInScreen().CenterPoint(); - - aura::test::EventGenerator generator( - window_state->window()->GetRootWindow(), center); - - EXPECT_FALSE(window_state->IsMaximized()); - - generator.ClickLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window_state->IsMaximized()); - - center = view->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(center); - generator.ClickLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window_state->IsMaximized()); - - generator.GestureTapAt(view->GetBoundsInScreen().CenterPoint()); - EXPECT_TRUE(window_state->IsMaximized()); - - generator.GestureTapAt(view->GetBoundsInScreen().CenterPoint()); - EXPECT_FALSE(window_state->IsMaximized()); - - generator.GestureTapDownAndUp(view->GetBoundsInScreen().CenterPoint()); - EXPECT_TRUE(window_state->IsMaximized()); - - generator.GestureTapDownAndUp(view->GetBoundsInScreen().CenterPoint()); - EXPECT_FALSE(window_state->IsMaximized()); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_ResizeButtonDrag DISABLED_ResizeButtonDrag -#else -#define MAYBE_ResizeButtonDrag ResizeButtonDrag -#endif - -// Tests that click+dragging on the resize-button tiles or minimizes the window. -TEST_F(FrameMaximizeButtonTest, MAYBE_ResizeButtonDrag) { - aura::Window* window = widget()->GetNativeWindow(); - views::View* view = maximize_button(); - gfx::Point center = view->GetBoundsInScreen().CenterPoint(); - - aura::test::EventGenerator generator(window->GetRootWindow(), center); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_TRUE(window_state->IsNormalShowState()); - - // Snap right. - { - generator.PressLeftButton(); - generator.MoveMouseBy(10, 0); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - internal::SnapSizer sizer(window_state, center, - internal::SnapSizer::RIGHT_EDGE, - internal::SnapSizer::OTHER_INPUT); - EXPECT_EQ(sizer.target_bounds().ToString(), window->bounds().ToString()); - } - - // Snap left. - { - center = view->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(center); - generator.PressLeftButton(); - generator.MoveMouseBy(-10, 0); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - internal::SnapSizer sizer(window_state, center, - internal::SnapSizer::LEFT_EDGE, - internal::SnapSizer::OTHER_INPUT); - EXPECT_EQ(sizer.target_bounds().ToString(), window->bounds().ToString()); - } - - // Minimize. - { - center = view->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(center); - generator.PressLeftButton(); - generator.MoveMouseBy(0, 10); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - - EXPECT_TRUE(window_state->IsMinimized()); - } - - window_state->Restore(); - - // Now test the same behaviour for gesture events. - - // Snap right. - { - center = view->GetBoundsInScreen().CenterPoint(); - gfx::Point end = center; - end.Offset(80, 0); - generator.GestureScrollSequence(center, end, - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - // This is a short resizing distance and different touch behavior - // applies which leads in half of the screen being used. - EXPECT_EQ("400,0 400x553", window->bounds().ToString()); - } - - // Snap left. - { - center = view->GetBoundsInScreen().CenterPoint(); - gfx::Point end = center; - end.Offset(-80, 0); - generator.GestureScrollSequence(center, end, - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - internal::SnapSizer sizer(window_state, center, - internal::SnapSizer::LEFT_EDGE, - internal::SnapSizer::OTHER_INPUT); - EXPECT_EQ(sizer.target_bounds().ToString(), window->bounds().ToString()); - } - - // Minimize. - { - center = view->GetBoundsInScreen().CenterPoint(); - gfx::Point end = center; - end.Offset(0, 40); - generator.GestureScrollSequence(center, end, - base::TimeDelta::FromMilliseconds(100), - 3); - RunAllPendingInMessageLoop(); - - EXPECT_TRUE(window_state->IsMinimized()); - } - - // Test with gesture events. -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_TouchDragResizeCloseToCornerDiffersFromMouse \ - DISABLED_TouchDragResizeCloseToCornerDiffersFromMouse -#else -#define MAYBE_TouchDragResizeCloseToCornerDiffersFromMouse \ - TouchDragResizeCloseToCornerDiffersFromMouse -#endif - -// Tests Left/Right snapping with resize button touch dragging - which should -// trigger dependent on the available drag distance. -TEST_F(FrameMaximizeButtonTest, - MAYBE_TouchDragResizeCloseToCornerDiffersFromMouse) { - // The test is uninteresting when windows can only be snapped to a single - // width because snapping the window via mouse and touch results in the same - // final bounds. - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshMultipleSnapWindowWidths)) { - return; - } - - aura::Window* window = widget()->GetNativeWindow(); - views::View* view = maximize_button(); - - gfx::Rect work_area = widget()->GetWorkAreaBoundsInScreen(); - gfx::Rect bounds = window->bounds(); - bounds.set_x(work_area.width() - bounds.width()); - widget()->SetBounds(bounds); - - gfx::Point start_point = view->GetBoundsInScreen().CenterPoint(); - // We want to move all the way to the right (the few pixels we have). - gfx::Point end_point = gfx::Point(work_area.width(), start_point.y()); - - aura::test::EventGenerator generator(window->GetRootWindow(), start_point); - wm::WindowState* window_state = wm::GetWindowState(window); - - EXPECT_TRUE(window_state->IsNormalShowState()); - - // Snap right with a touch drag. - generator.GestureScrollSequence(start_point, - end_point, - base::TimeDelta::FromMilliseconds(100), - 10); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - gfx::Rect touch_result = window->bounds(); - EXPECT_NE(bounds.ToString(), touch_result.ToString()); - - // Set the position back to where it was before and re-try with a mouse. - widget()->SetBounds(bounds); - - generator.MoveMouseTo(start_point); - generator.PressLeftButton(); - generator.MoveMouseTo(end_point, 10); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - gfx::Rect mouse_result = window->bounds(); - - // The difference between the two operations should be that the mouse - // operation should have just started to resize and the touch operation is - // already all the way down to the smallest possible size. - EXPECT_NE(mouse_result.ToString(), touch_result.ToString()); - EXPECT_GT(mouse_result.width(), touch_result.width()); -} - -// Test that closing the (browser) window with an opened balloon does not -// crash the system. In other words: Make sure that shutting down the frame -// destroys the opened balloon in an orderly fashion. -TEST_F(FrameMaximizeButtonTest, MaximizeButtonExternalShutDown) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalShowState()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Even though the widget is closing the bubble menu should not crash upon - // its delayed destruction. - CloseWidget(); -} - -// Test that maximizing the browser after hovering in does not crash the system -// when the observer gets removed in the bubble destruction process. -TEST_F(FrameMaximizeButtonTest, MaximizeOnHoverThenClick) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalShowState()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - generator.ClickLeftButton(); - EXPECT_TRUE(wm::GetWindowState(window)->IsMaximized()); -} - -// Test that hovering over a button in the balloon dialog will show the phantom -// window. Moving then away from the button will hide it again. Then check that -// pressing and dragging the button itself off the button will also release the -// phantom window. -TEST_F(FrameMaximizeButtonTest, MaximizeLeftButtonDragOut) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalShowState()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Move the mouse over the left maximize button. - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); - - generator.MoveMouseTo(left_max_pos); - // Expect the phantom window to be open. - EXPECT_TRUE(maximize_button->phantom_window_open()); - - // Move away to see the window being destroyed. - generator.MoveMouseTo(off_pos); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move back over the button. - generator.MoveMouseTo(button_pos); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - - // Press button and drag out of dialog. - generator.PressLeftButton(); - generator.MoveMouseTo(off_pos); - generator.ReleaseLeftButton(); - - // Check that the phantom window is also gone. - EXPECT_FALSE(maximize_button->phantom_window_open()); -} - -// Test that clicking a button in the maximizer bubble (in this case the -// maximize left button) will do the requested action. -TEST_F(FrameMaximizeButtonTest, MaximizeLeftByButton) { - aura::Window* window = widget()->GetNativeWindow(); - - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalShowState()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Move the mouse over the left maximize button. - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - generator.ClickLeftButton(); - - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_FALSE(window_state->IsMinimized()); - internal::SnapSizer sizer(window_state, button_pos, - internal::SnapSizer::LEFT_EDGE, - internal::SnapSizer::OTHER_INPUT); - sizer.SelectDefaultSizeAndDisableResize(); - EXPECT_EQ(sizer.target_bounds().ToString(), window->bounds().ToString()); -} - -// Test that the activation focus does not change when the bubble gets shown. -TEST_F(FrameMaximizeButtonTest, MaximizeKeepFocus) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalShowState()); - - aura::Window* active = - aura::client::GetFocusClient(window)->GetFocusedWindow(); - - // Move the mouse cursor over the button to bring up the maximizer bubble. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Check that the focused window is still the same. - EXPECT_EQ(active, aura::client::GetFocusClient(window)->GetFocusedWindow()); -} - -TEST_F(FrameMaximizeButtonTest, MaximizeTap) { - aura::Window* window = widget()->GetNativeWindow(); - aura::Window* root_window = window->GetRootWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - - const int touch_default_radius = - ui::GestureConfiguration::default_radius(); - ui::GestureConfiguration::set_default_radius(0); - - aura::WindowEventDispatcher* dispatcher = root_window->GetDispatcher(); - const int kTouchId = 2; - ui::TouchEvent press(ui::ET_TOUCH_PRESSED, - button_pos, - kTouchId, - ui::EventTimeForNow()); - dispatcher->AsRootWindowHostDelegate()->OnHostTouchEvent(&press); - - button_pos.Offset(9, 8); - ui::TouchEvent release( - ui::ET_TOUCH_RELEASED, - button_pos, - kTouchId, - press.time_stamp() + base::TimeDelta::FromMilliseconds(50)); - dispatcher->AsRootWindowHostDelegate()->OnHostTouchEvent(&release); - - ui::GestureConfiguration::set_default_radius(touch_default_radius); -} - -// Test that only the left button will activate the maximize button. -TEST_F(FrameMaximizeButtonTest, OnlyLeftButtonMaximizes) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_TRUE(window_state->IsNormalShowState()); - EXPECT_FALSE(window_state->IsMaximized()); - - // Move the mouse cursor over the button. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // After pressing the left button the button should get triggered. - generator.PressLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(maximize_button->is_snap_enabled()); - EXPECT_FALSE(window_state->IsMaximized()); - - // Pressing the right button then should cancel the operation. - generator.PressRightButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(maximize_button->maximizer()); - - // After releasing the second button the window shouldn't be maximized. - generator.ReleaseRightButton(); - generator.ReleaseLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window_state->IsMaximized()); - - // Second experiment: Starting with right should also not trigger. - generator.MoveMouseTo(off_pos); - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Pressing first the right button should not activate. - generator.PressRightButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(maximize_button->is_snap_enabled()); - - // Pressing then additionally the left button shouldn't activate either. - generator.PressLeftButton(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(maximize_button->is_snap_enabled()); - generator.ReleaseRightButton(); - generator.ReleaseLeftButton(); - EXPECT_FALSE(window_state->IsMaximized()); -} - -// Click a button of window maximize functionality. -// If |snap_type| is SNAP_NONE the FrameMaximizeButton gets clicked, otherwise -// the associated snap button. -// |Window| is the window which owns the maximize button. -// |maximize_button| is the FrameMaximizeButton which controls the window. -void ClickMaxButton( - ash::FrameMaximizeButton* maximize_button, - aura::Window* window, - SnapType snap_type) { - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - generator.MoveMouseTo(off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - // Move the mouse cursor over the button. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - - if (snap_type != SNAP_NONE) { - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(snap_type)->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - } - // After pressing the left button the button should get triggered. - generator.ClickLeftButton(); - EXPECT_FALSE(maximize_button->maximizer()); -} - -// Test that the restore from left/right maximize is properly done. -TEST_F(FrameMaximizeButtonTest, MaximizeLeftRestore) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - ClickMaxButton(maximize_button, window, SNAP_LEFT); - wm::WindowState* window_state = wm::GetWindowState(window); - // The window should not be maximized. - EXPECT_FALSE(window_state->IsMaximized()); - // But the bounds should be different. - gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(0, new_bounds.x()); - EXPECT_EQ(0, new_bounds.y()); - - // Now click the same button again to see that it restores. - ClickMaxButton(maximize_button, window, SNAP_LEFT); - // But the bounds should be restored. - new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(new_bounds.x(), initial_bounds.x()); - EXPECT_EQ(new_bounds.y(), initial_bounds.x()); - EXPECT_EQ(new_bounds.width(), initial_bounds.width()); - EXPECT_EQ(new_bounds.height(), initial_bounds.height()); - // Make sure that there is no restore rectangle left. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Maximize, left/right maximize and then restore should works. -TEST_F(FrameMaximizeButtonTest, MaximizeMaximizeLeftRestore) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - ClickMaxButton(maximize_button, window, SNAP_NONE); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_TRUE(window_state->IsMaximized()); - - ClickMaxButton(maximize_button, window, SNAP_LEFT); - EXPECT_FALSE(window_state->IsMaximized()); - gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(0, new_bounds.x()); - EXPECT_EQ(0, new_bounds.y()); - - // Now click the same button again to see that it restores. - ClickMaxButton(maximize_button, window, SNAP_LEFT); - RunAllPendingInMessageLoop(); - // But the bounds should be restored. - new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(new_bounds.x(), initial_bounds.x()); - EXPECT_EQ(new_bounds.y(), initial_bounds.x()); - EXPECT_EQ(new_bounds.width(), initial_bounds.width()); - EXPECT_EQ(new_bounds.height(), initial_bounds.height()); - // Make sure that there is no restore rectangle left. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Left/right maximize, maximize and then restore should work. -TEST_F(FrameMaximizeButtonTest, MaximizeSnapLeftRestore) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - ClickMaxButton(maximize_button, window, SNAP_LEFT); - - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_FALSE(window_state->IsMaximized()); - - ClickMaxButton(maximize_button, window, SNAP_NONE); - EXPECT_TRUE(window_state->IsMaximized()); - - ClickMaxButton(maximize_button, window, SNAP_NONE); - EXPECT_FALSE(window_state->IsMaximized()); - gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); - EXPECT_EQ(new_bounds.x(), initial_bounds.x()); - EXPECT_EQ(new_bounds.y(), initial_bounds.x()); - EXPECT_EQ(new_bounds.width(), initial_bounds.width()); - EXPECT_EQ(new_bounds.height(), initial_bounds.height()); - // Make sure that there is no restore rectangle left. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Test that minimizing the window per keyboard closes the maximize bubble. -TEST_F(FrameMaximizeButtonTest, MinimizePerKeyClosesBubble) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - generator.MoveMouseTo(off_pos); - EXPECT_FALSE(maximize_button->maximizer()); - - // Move the mouse cursor over the maximize button. - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // We simulate the keystroke by calling minimizeWindow directly. - wm::WindowState* window_state = wm::GetWindowState(window); - window_state->Minimize(); - - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_FALSE(maximize_button->maximizer()); -} - -// Tests that dragging down on the maximize button minimizes the window. -TEST_F(FrameMaximizeButtonTest, MaximizeButtonDragDownMinimizes) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - - wm::WindowState* window_state = wm::GetWindowState(window); - // Drag down on a maximized window. - window_state->Maximize(); - EXPECT_TRUE(window_state->IsMaximized()); - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x(), button_pos.y() + 100); - - aura::test::EventGenerator generator(window->GetRootWindow()); - generator.GestureScrollSequence(button_pos, off_pos, - base::TimeDelta::FromMilliseconds(0), 1); - - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_FALSE(maximize_button->maximizer()); - - // Drag down on a restored window. - window_state->Restore(); - - button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - off_pos = gfx::Point(button_pos.x(), button_pos.y() + 200); - generator.GestureScrollSequence(button_pos, off_pos, - base::TimeDelta::FromMilliseconds(10), 1); - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_FALSE(maximize_button->maximizer()); -} - -// Tests that dragging Left and pressing ESC does properly abort. -TEST_F(FrameMaximizeButtonTest, MaximizeButtonDragLeftEscapeExits) { - aura::Window* window = widget()->GetNativeWindow(); - gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() - button_pos.x() / 2, button_pos.y()); - - const int kGestureSteps = 10; - CancelCallbackHandler cancel_handler(kGestureSteps / 2, maximize_button); - aura::test::EventGenerator generator(window->GetRootWindow()); - generator.GestureScrollSequenceWithCallback( - button_pos, - off_pos, - base::TimeDelta::FromMilliseconds(0), - kGestureSteps, - base::Bind(&CancelCallbackHandler::CountedCancelCallback, - base::Unretained(&cancel_handler))); - - // Check that there was no size change. - EXPECT_EQ(widget()->GetWindowBoundsInScreen().size().ToString(), - initial_bounds.size().ToString()); - // Check that there is no phantom window left open. - EXPECT_FALSE(maximize_button->phantom_window_open()); -} - -// Test that hovering over a button in the maximizer bubble and switching -// activation without moving the mouse properly aborts. -TEST_F(FrameMaximizeButtonTest, LossOfActivationWhileMaximizeBubbleOpenAborts) { - aura::Window* window = widget()->GetNativeWindow(); - ash::FrameMaximizeButton* maximize_button = - FrameMaximizeButtonTest::maximize_button(); - maximize_button->set_bubble_appearance_delay_ms(0); - - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalShowState()); - EXPECT_TRUE(widget()->IsActive()); - - // Move the mouse over the maximize button in order to bring up the maximizer - // bubble. - gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); - gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); - aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); - generator.MoveMouseTo(button_pos); - EXPECT_TRUE(maximize_button->maximizer()); - - // Hover the mouse over the left maximize button in the maximizer bubble to - // show the phantom window. - gfx::Point left_max_pos = maximize_button->maximizer()-> - GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); - generator.MoveMouseTo(left_max_pos); - EXPECT_TRUE(maximize_button->phantom_window_open()); - - // Change activation by creating a new window. This could be done via an - // accelerator. The root window takes ownership of |just_created|. - views::Widget* just_created = views::Widget::CreateWindowWithContextAndBounds( - NULL, widget()->GetNativeWindow(), gfx::Rect(100, 100)); - just_created->Show(); - just_created->Activate(); - EXPECT_FALSE(widget()->IsActive()); - - // Test that we have properly reset the state of the now inactive window. - EXPECT_FALSE(maximize_button->maximizer()); - EXPECT_FALSE(maximize_button->phantom_window_open()); - EXPECT_TRUE(wm::GetWindowState(window)->IsNormalShowState()); - EXPECT_EQ(initial_bounds.ToString(), window->GetBoundsInScreen().ToString()); -} - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/caption_buttons/maximize_bubble_controller.cc b/chromium/ash/wm/caption_buttons/maximize_bubble_controller.cc deleted file mode 100644 index f01d0e22783..00000000000 --- a/chromium/ash/wm/caption_buttons/maximize_bubble_controller.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2013 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/caption_buttons/maximize_bubble_controller.h" - -#include "ash/wm/caption_buttons/frame_maximize_button.h" -#include "ash/wm/caption_buttons/maximize_bubble_controller_bubble.h" -#include "base/timer/timer.h" - - -namespace ash { - -MaximizeBubbleController::MaximizeBubbleController( - FrameMaximizeButton* frame_maximize_button, - MaximizeBubbleFrameState maximize_type, - int appearance_delay_ms) - : frame_maximize_button_(frame_maximize_button), - bubble_(NULL), - maximize_type_(maximize_type), - snap_type_for_creation_(SNAP_NONE), - appearance_delay_ms_(appearance_delay_ms) { - // Create the task which will create the bubble delayed. - base::OneShotTimer<MaximizeBubbleController>* new_timer = - new base::OneShotTimer<MaximizeBubbleController>(); - // Note: Even if there was no delay time given, we need to have a timer. - new_timer->Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds( - appearance_delay_ms_ ? appearance_delay_ms_ : 10), - this, - &MaximizeBubbleController::CreateBubble); - timer_.reset(new_timer); - if (!appearance_delay_ms_) - CreateBubble(); -} - -MaximizeBubbleController::~MaximizeBubbleController() { - // Note: The destructor only gets initiated through the owner. - timer_.reset(); - if (bubble_) { - bubble_->ControllerRequestsCloseAndDelete(); - bubble_ = NULL; - } -} - -void MaximizeBubbleController::SetSnapType(SnapType snap_type) { - if (bubble_) { - bubble_->SetSnapType(snap_type); - } else { - // The bubble has not been created yet. This can occur if bubble creation is - // delayed. - snap_type_for_creation_ = snap_type; - } -} - -aura::Window* MaximizeBubbleController::GetBubbleWindow() { - return bubble_ ? bubble_->GetBubbleWindow() : NULL; -} - -void MaximizeBubbleController::DelayCreation() { - if (timer_.get() && timer_->IsRunning()) - timer_->Reset(); -} - -void MaximizeBubbleController::OnButtonClicked(SnapType snap_type) { - frame_maximize_button_->ExecuteSnapAndCloseMenu(snap_type); -} - -void MaximizeBubbleController::OnButtonHover(SnapType snap_type) { - frame_maximize_button_->SnapButtonHovered(snap_type); -} - -views::CustomButton* MaximizeBubbleController::GetButtonForUnitTest( - SnapType state) { - return bubble_ ? bubble_->GetButtonForUnitTest(state) : NULL; -} - -void MaximizeBubbleController::RequestDestructionThroughOwner() { - // Tell the parent to destroy us (if this didn't happen yet). - if (timer_) { - timer_.reset(NULL); - // Informs the owner that the menu is gone and requests |this| destruction. - frame_maximize_button_->DestroyMaximizeMenu(); - // Note: After this call |this| is destroyed. - } -} - -void MaximizeBubbleController::CreateBubble() { - if (!bubble_) { - bubble_ = new MaximizeBubbleControllerBubble(this, appearance_delay_ms_, - snap_type_for_creation_); - frame_maximize_button_->OnMaximizeBubbleShown(bubble_->GetWidget()); - } - - timer_->Stop(); -} - -} // namespace ash diff --git a/chromium/ash/wm/caption_buttons/maximize_bubble_controller.h b/chromium/ash/wm/caption_buttons/maximize_bubble_controller.h deleted file mode 100644 index 53a07dd2955..00000000000 --- a/chromium/ash/wm/caption_buttons/maximize_bubble_controller.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2013 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_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_H_ -#define ASH_WM_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "ash/wm/caption_buttons/caption_button_types.h" -#include "ash/wm/workspace/snap_types.h" -#include "base/memory/scoped_ptr.h" - -namespace aura { -class Window; -} - -namespace base { -class Timer; -} - -namespace views { -class CustomButton; -} - -namespace ash { - -class FrameMaximizeButton; -class MaximizeBubbleControllerBubble; - -// A class which shows a helper UI for the maximize button after a delay. -class ASH_EXPORT MaximizeBubbleController { - public: - MaximizeBubbleController(FrameMaximizeButton* frame_maximize_button, - MaximizeBubbleFrameState maximize_type, - int appearance_delay_ms); - // Called from the outside to destroy the interface to the UI visuals. - // The visuals will then delete when possible (maybe asynchronously). - virtual ~MaximizeBubbleController(); - - // Update the UI visuals to reflect the previewed |snap_type| snapping state. - void SetSnapType(SnapType snap_type); - - // To achieve proper Z-sorting with the snap animation, this window will be - // presented above the phantom window. - aura::Window* GetBubbleWindow(); - - // Reset the delay of the menu creation (if it was not created yet). - void DelayCreation(); - - // Called to tell the owning FrameMaximizeButton that a button was clicked. - void OnButtonClicked(SnapType snap_type); - - // Called to tell the the owning FrameMaximizeButton that the hover status - // for a button has changed. |snap_type| can be either SNAP_LEFT, SNAP_RIGHT, - // SNAP_MINIMIZE or SNAP_NONE. - void OnButtonHover(SnapType snap_type); - - // Get the owning FrameMaximizeButton. - FrameMaximizeButton* frame_maximize_button() { - return frame_maximize_button_; - } - - // The status of the associated window: Maximized or normal. - MaximizeBubbleFrameState maximize_type() const { return maximize_type_; } - - // A unit test function to return buttons of the sub menu. |state| can be - // either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - // Called from the the Bubble class to destroy itself: It tells the owning - // object that it will destroy itself asynchronously. The owner will then - // destroy |this|. - void RequestDestructionThroughOwner(); - - private: - // The function which creates the bubble once the delay is elapsed. - void CreateBubble(); - - // The owning button which is also the anchor for the menu. - FrameMaximizeButton* frame_maximize_button_; - - // The bubble menu. - MaximizeBubbleControllerBubble* bubble_; - - // The current maximize state of the owning window. - const MaximizeBubbleFrameState maximize_type_; - - // The snap type with which the bubble is created. This is needed because the - // creation of the bubble can be delayed and SetSnapType() may be called - // before the bubble is created. - SnapType snap_type_for_creation_; - - // The timer for the delayed creation of the menu. - scoped_ptr<base::Timer> timer_; - - // The appearance delay in ms (delay and fade in & fade out delay). - const int appearance_delay_ms_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleController); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_H_ diff --git a/chromium/ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc b/chromium/ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc deleted file mode 100644 index d109a419265..00000000000 --- a/chromium/ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc +++ /dev/null @@ -1,498 +0,0 @@ -// Copyright 2013 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/caption_buttons/maximize_bubble_controller_bubble.h" - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/caption_buttons/bubble_contents_button_row.h" -#include "ash/wm/caption_buttons/frame_maximize_button.h" -#include "ash/wm/caption_buttons/maximize_bubble_controller.h" -#include "grit/ash_strings.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/animation/animation.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/path.h" -#include "ui/views/bubble/bubble_frame_view.h" -#include "ui/views/controls/label.h" -#include "ui/views/layout/box_layout.h" -#include "ui/views/mouse_watcher.h" - - -namespace ash { - -// BubbleContentsView --------------------------------------------------------- - -// A class which creates the content of the bubble: The buttons, and the label. -class BubbleContentsView : public views::View { - public: - BubbleContentsView(MaximizeBubbleControllerBubble* bubble, - SnapType initial_snap_type); - virtual ~BubbleContentsView(); - - // Set the label content to reflect the currently selected |snap_type|. - // This function can be executed through the frame maximize button as well as - // through hover operations. - void SetSnapType(SnapType snap_type); - - // Added for unit test: Retrieve the button for an action. - // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - private: - // The owning class. - MaximizeBubbleControllerBubble* bubble_; - - // The object which owns all the buttons. - BubbleContentsButtonRow* buttons_view_; - - // The label object which shows the user the selected action. - views::Label* label_view_; - - DISALLOW_COPY_AND_ASSIGN(BubbleContentsView); -}; - -BubbleContentsView::BubbleContentsView( - MaximizeBubbleControllerBubble* bubble, - SnapType initial_snap_type) - : bubble_(bubble), - buttons_view_(NULL), - label_view_(NULL) { - SetLayoutManager(new views::BoxLayout( - views::BoxLayout::kVertical, 0, 0, - MaximizeBubbleControllerBubble::kLayoutSpacing)); - set_background(views::Background::CreateSolidBackground( - MaximizeBubbleControllerBubble::kBubbleBackgroundColor)); - - buttons_view_ = new BubbleContentsButtonRow(bubble); - AddChildView(buttons_view_); - - label_view_ = new views::Label(); - SetSnapType(initial_snap_type); - label_view_->SetBackgroundColor( - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - const SkColor kBubbleTextColor = SK_ColorWHITE; - label_view_->SetEnabledColor(kBubbleTextColor); - const int kLabelSpacing = 4; - label_view_->set_border(views::Border::CreateEmptyBorder( - kLabelSpacing, 0, kLabelSpacing, 0)); - AddChildView(label_view_); -} - -BubbleContentsView::~BubbleContentsView() { -} - -// Set the label content to reflect the currently selected |snap_type|. -// This function can be executed through the frame maximize button as well as -// through hover operations. -void BubbleContentsView::SetSnapType(SnapType snap_type) { - if (!bubble_->controller()) - return; - - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - int id = 0; - switch (snap_type) { - case SNAP_LEFT: - id = IDS_ASH_SNAP_WINDOW_LEFT; - break; - case SNAP_RIGHT: - id = IDS_ASH_SNAP_WINDOW_RIGHT; - break; - case SNAP_MAXIMIZE: - DCHECK_NE(FRAME_STATE_FULL, bubble_->controller()->maximize_type()); - id = IDS_ASH_MAXIMIZE_WINDOW; - break; - case SNAP_MINIMIZE: - id = IDS_ASH_MINIMIZE_WINDOW; - break; - case SNAP_RESTORE: - DCHECK_NE(FRAME_STATE_NONE, bubble_->controller()->maximize_type()); - id = IDS_ASH_RESTORE_WINDOW; - break; - default: - // If nothing is selected, we automatically select the click operation. - id = bubble_->controller()->maximize_type() == FRAME_STATE_FULL ? - IDS_ASH_RESTORE_WINDOW : IDS_ASH_MAXIMIZE_WINDOW; - break; - } - label_view_->SetText(rb.GetLocalizedString(id)); -} - -views::CustomButton* BubbleContentsView::GetButtonForUnitTest(SnapType state) { - return buttons_view_->GetButtonForUnitTest(state); -} - - -// MaximizeBubbleBorder ------------------------------------------------------- - -namespace { - -const int kLineWidth = 1; -const int kArrowHeight = 10; -const int kArrowWidth = 20; - -} // namespace - -class MaximizeBubbleBorder : public views::BubbleBorder { - public: - MaximizeBubbleBorder(views::View* content_view, views::View* anchor); - - virtual ~MaximizeBubbleBorder() {} - - // Get the mouse active area of the window. - void GetMask(gfx::Path* mask); - - // views::BubbleBorder: - virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to, - const gfx::Size& contents_size) const OVERRIDE; - virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE; - virtual gfx::Size GetMinimumSize() const OVERRIDE; - - private: - // Note: Animations can continue after then main window frame was destroyed. - // To avoid this problem, the owning screen metrics get extracted upon - // creation. - gfx::Size anchor_size_; - gfx::Point anchor_screen_origin_; - views::View* content_view_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleBorder); -}; - -MaximizeBubbleBorder::MaximizeBubbleBorder(views::View* content_view, - views::View* anchor) - : views::BubbleBorder( - views::BubbleBorder::TOP_RIGHT, views::BubbleBorder::NO_SHADOW, - MaximizeBubbleControllerBubble::kBubbleBackgroundColor), - anchor_size_(anchor->size()), - anchor_screen_origin_(0, 0), - content_view_(content_view) { - views::View::ConvertPointToScreen(anchor, &anchor_screen_origin_); - set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); -} - -void MaximizeBubbleBorder::GetMask(gfx::Path* mask) { - gfx::Insets inset = GetInsets(); - // Note: Even though the tip could be added as activatable, it is left out - // since it would not change the action behavior in any way plus it makes - // more sense to keep the focus on the underlying button for clicks. - int left = inset.left() - kLineWidth; - int right = inset.left() + content_view_->width() + kLineWidth; - int top = inset.top() - kLineWidth; - int bottom = inset.top() + content_view_->height() + kLineWidth; - mask->moveTo(left, top); - mask->lineTo(right, top); - mask->lineTo(right, bottom); - mask->lineTo(left, bottom); - mask->lineTo(left, top); - mask->close(); -} - -gfx::Rect MaximizeBubbleBorder::GetBounds( - const gfx::Rect& position_relative_to, - const gfx::Size& contents_size) const { - gfx::Size border_size(contents_size); - gfx::Insets insets = GetInsets(); - border_size.Enlarge(insets.width(), insets.height()); - - // Position the bubble to center the box on the anchor. - int x = (anchor_size_.width() - border_size.width()) / 2; - // Position the bubble under the anchor, overlapping the arrow with it. - int y = anchor_size_.height() - insets.top(); - - gfx::Point view_origin(x + anchor_screen_origin_.x(), - y + anchor_screen_origin_.y()); - - return gfx::Rect(view_origin, border_size); -} - -void MaximizeBubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) { - gfx::Insets inset = GetInsets(); - - // Draw the border line around everything. - int y = inset.top(); - // Top - canvas->FillRect(gfx::Rect(inset.left(), - y - kLineWidth, - content_view_->width(), - kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - // Bottom - canvas->FillRect(gfx::Rect(inset.left(), - y + content_view_->height(), - content_view_->width(), - kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - // Left - canvas->FillRect(gfx::Rect(inset.left() - kLineWidth, - y - kLineWidth, - kLineWidth, - content_view_->height() + 2 * kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - // Right - canvas->FillRect(gfx::Rect(inset.left() + content_view_->width(), - y - kLineWidth, - kLineWidth, - content_view_->height() + 2 * kLineWidth), - MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - - // Draw the arrow afterwards covering the border. - SkPath path; - path.incReserve(4); - // The center of the tip should be in the middle of the button. - int tip_x = inset.left() + content_view_->width() / 2; - int left_base_x = tip_x - kArrowWidth / 2; - int left_base_y = y; - int tip_y = left_base_y - kArrowHeight; - path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); - path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); - path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), - SkIntToScalar(left_base_y)); - - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(MaximizeBubbleControllerBubble::kBubbleBackgroundColor); - canvas->DrawPath(path, paint); -} - -gfx::Size MaximizeBubbleBorder::GetMinimumSize() const { - return gfx::Size(kLineWidth * 2 + kArrowWidth, - std::max(kLineWidth, kArrowHeight) + kLineWidth); -} - - -// BubbleMouseWatcherHost ----------------------------------------------------- - -// The mouse watcher host which makes sure that the bubble does not get closed -// while the mouse cursor is over the maximize button or the balloon content. -// Note: This object gets destroyed when the MouseWatcher gets destroyed. -class BubbleMouseWatcherHost: public views::MouseWatcherHost { - public: - explicit BubbleMouseWatcherHost(MaximizeBubbleControllerBubble* bubble); - virtual ~BubbleMouseWatcherHost(); - - // views::MouseWatcherHost: - virtual bool Contains(const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type) OVERRIDE; - private: - MaximizeBubbleControllerBubble* bubble_; - - DISALLOW_COPY_AND_ASSIGN(BubbleMouseWatcherHost); -}; - -BubbleMouseWatcherHost::BubbleMouseWatcherHost( - MaximizeBubbleControllerBubble* bubble) - : bubble_(bubble) { -} - -BubbleMouseWatcherHost::~BubbleMouseWatcherHost() { -} - -bool BubbleMouseWatcherHost::Contains( - const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type) { - return bubble_->Contains(screen_point, type); -} - - -// MaximizeBubbleControllerBubble --------------------------------------------- - -// static -const SkColor MaximizeBubbleControllerBubble::kBubbleBackgroundColor = - 0xFF141414; -const int MaximizeBubbleControllerBubble::kLayoutSpacing = -1; - -MaximizeBubbleControllerBubble::MaximizeBubbleControllerBubble( - MaximizeBubbleController* owner, - int appearance_delay_ms, - SnapType initial_snap_type) - : views::BubbleDelegateView(owner->frame_maximize_button(), - views::BubbleBorder::TOP_RIGHT), - shutting_down_(false), - owner_(owner), - bubble_widget_(NULL), - contents_view_(NULL), - bubble_border_(NULL), - appearance_delay_ms_(appearance_delay_ms) { - set_margins(gfx::Insets()); - - // The window needs to be owned by the root so that the SnapSizer does not - // cover it upon animation. - aura::Window* parent = Shell::GetContainer( - Shell::GetTargetRootWindow(), - internal::kShellWindowId_ShelfContainer); - set_parent_window(parent); - - set_notify_enter_exit_on_child(true); - set_adjust_if_offscreen(false); - SetPaintToLayer(true); - set_color(kBubbleBackgroundColor); - set_close_on_deactivate(false); - set_background( - views::Background::CreateSolidBackground(kBubbleBackgroundColor)); - - SetLayoutManager(new views::BoxLayout( - views::BoxLayout::kVertical, 0, 0, kLayoutSpacing)); - - contents_view_ = new BubbleContentsView(this, initial_snap_type); - AddChildView(contents_view_); - - // Note that the returned widget has an observer which points to our - // functions. - bubble_widget_ = views::BubbleDelegateView::CreateBubble(this); - bubble_widget_->set_focus_on_creation(false); - - SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); - bubble_widget_->non_client_view()->frame_view()->set_background(NULL); - - bubble_border_ = new MaximizeBubbleBorder(this, GetAnchorView()); - GetBubbleFrameView()->SetBubbleBorder(bubble_border_); - GetBubbleFrameView()->set_background(NULL); - - // Recalculate size with new border. - SizeToContents(); - - if (!appearance_delay_ms_) - GetWidget()->Show(); - else - StartFade(true); - - ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( - ash::UMA_WINDOW_MAXIMIZE_BUTTON_SHOW_BUBBLE); - - mouse_watcher_.reset(new views::MouseWatcher( - new BubbleMouseWatcherHost(this), - this)); - mouse_watcher_->Start(); -} - -MaximizeBubbleControllerBubble::~MaximizeBubbleControllerBubble() { -} - -aura::Window* MaximizeBubbleControllerBubble::GetBubbleWindow() { - return bubble_widget_ ? bubble_widget_->GetNativeWindow() : NULL; -} - -gfx::Rect MaximizeBubbleControllerBubble::GetAnchorRect() { - if (!owner_) - return gfx::Rect(); - - gfx::Rect anchor_rect = - owner_->frame_maximize_button()->GetBoundsInScreen(); - return anchor_rect; -} - -void MaximizeBubbleControllerBubble::AnimationProgressed( - const gfx::Animation* animation) { - // First do everything needed for the fade by calling the base function. - BubbleDelegateView::AnimationProgressed(animation); - // When fading in we are done. - if (!shutting_down_) - return; - // Upon fade out an additional shift is required. - const int kBubbleAnimationOffsetY = 5; - int shift = animation->CurrentValueBetween(kBubbleAnimationOffsetY, 0); - gfx::Rect rect = initial_position_; - - rect.set_y(rect.y() + shift); - bubble_widget_->GetNativeWindow()->SetBounds(rect); -} - -bool MaximizeBubbleControllerBubble::CanActivate() const { - return false; -} - -bool MaximizeBubbleControllerBubble::WidgetHasHitTestMask() const { - return bubble_border_ != NULL; -} - -void MaximizeBubbleControllerBubble::GetWidgetHitTestMask( - gfx::Path* mask) const { - DCHECK(mask); - DCHECK(bubble_border_); - bubble_border_->GetMask(mask); -} - -void MaximizeBubbleControllerBubble::MouseMovedOutOfHost() { - if (!owner_ || shutting_down_) - return; - // When we leave the bubble, we might be still be in gesture mode or over - // the maximize button. So only close if none of the other cases apply. - if (!owner_->frame_maximize_button()->is_snap_enabled()) { - gfx::Point screen_location = Shell::GetScreen()->GetCursorScreenPoint(); - if (!owner_->frame_maximize_button()->GetBoundsInScreen().Contains( - screen_location)) { - owner_->RequestDestructionThroughOwner(); - } - } -} - -bool MaximizeBubbleControllerBubble::Contains( - const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type) { - if (!owner_ || shutting_down_) - return false; - bool inside_button = - owner_->frame_maximize_button()->GetBoundsInScreen().Contains( - screen_point); - if (!owner_->frame_maximize_button()->is_snap_enabled() && inside_button) { - SetSnapType(controller()->maximize_type() == FRAME_STATE_FULL ? - SNAP_RESTORE : SNAP_MAXIMIZE); - return true; - } - // Check if either a gesture is taking place (=> bubble stays no matter what - // the mouse does) or the mouse is over the maximize button or the bubble - // content. - return (owner_->frame_maximize_button()->is_snap_enabled() || - inside_button || - contents_view_->GetBoundsInScreen().Contains(screen_point)); -} - -gfx::Size MaximizeBubbleControllerBubble::GetPreferredSize() { - return contents_view_->GetPreferredSize(); -} - -void MaximizeBubbleControllerBubble::OnWidgetDestroying(views::Widget* widget) { - if (bubble_widget_ == widget) { - mouse_watcher_->Stop(); - - if (owner_) { - // If the bubble destruction was triggered by some other external - // influence then ourselves, the owner needs to be informed that the menu - // is gone. - shutting_down_ = true; - owner_->RequestDestructionThroughOwner(); - owner_ = NULL; - } - } - BubbleDelegateView::OnWidgetDestroying(widget); -} - -void MaximizeBubbleControllerBubble::ControllerRequestsCloseAndDelete() { - // This only gets called from the owning base class once it is deleted. - if (shutting_down_) - return; - shutting_down_ = true; - owner_ = NULL; - - // Close the widget asynchronously after the hide animation is finished. - initial_position_ = bubble_widget_->GetNativeWindow()->bounds(); - if (!appearance_delay_ms_) - bubble_widget_->CloseNow(); - else - StartFade(false); -} - -void MaximizeBubbleControllerBubble::SetSnapType(SnapType snap_type) { - if (contents_view_) - contents_view_->SetSnapType(snap_type); -} - -views::CustomButton* MaximizeBubbleControllerBubble::GetButtonForUnitTest( - SnapType state) { - return contents_view_->GetButtonForUnitTest(state); -} - -} // namespace ash diff --git a/chromium/ash/wm/caption_buttons/maximize_bubble_controller_bubble.h b/chromium/ash/wm/caption_buttons/maximize_bubble_controller_bubble.h deleted file mode 100644 index dfb25efa08c..00000000000 --- a/chromium/ash/wm/caption_buttons/maximize_bubble_controller_bubble.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2013 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_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_BUBBLE_H_ -#define ASH_WM_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_BUBBLE_H_ - -#include "ash/wm/workspace/snap_types.h" -#include "ui/views/bubble/bubble_delegate.h" -#include "ui/views/mouse_watcher.h" - -namespace views { -class CustomButton; -} - -namespace ash { - -class BubbleContentsView; -class MaximizeBubbleBorder; -class MaximizeBubbleController; - -// The class which creates and manages the bubble menu element. -// It creates a 'bubble border' and the content accordingly. -// Note: Since the SnapSizer will show animations on top of the maximize button -// this menu gets created as a separate window and the SnapSizer will be -// created underneath this window. -class MaximizeBubbleControllerBubble : public views::BubbleDelegateView, - public views::MouseWatcherListener { - public: - static const SkColor kBubbleBackgroundColor; - static const int kLayoutSpacing; // The spacing between two buttons. - - MaximizeBubbleControllerBubble(MaximizeBubbleController* owner, - int appearance_delay_ms, - SnapType initial_snap_type); - virtual ~MaximizeBubbleControllerBubble(); - - // The window of the menu under which the SnapSizer will get created. - aura::Window* GetBubbleWindow(); - - // Overridden from views::BubbleDelegateView. - virtual gfx::Rect GetAnchorRect() OVERRIDE; - virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; - virtual bool CanActivate() const OVERRIDE; - - // Overridden from views::WidgetDelegateView. - virtual bool WidgetHasHitTestMask() const OVERRIDE; - virtual void GetWidgetHitTestMask(gfx::Path* mask) const OVERRIDE; - - // Implementation of MouseWatcherListener. - virtual void MouseMovedOutOfHost() OVERRIDE; - - // Implementation of MouseWatcherHost. - virtual bool Contains(const gfx::Point& screen_point, - views::MouseWatcherHost::MouseEventType type); - - // Overridden from views::View. - virtual gfx::Size GetPreferredSize() OVERRIDE; - - // Overridden from views::Widget::Observer. - virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; - - // Called from the controller class to indicate that the menu should get - // destroyed. - virtual void ControllerRequestsCloseAndDelete(); - - // Called from the owning class to change the menu content to the given - // |snap_type| so that the user knows what is selected. - void SetSnapType(SnapType snap_type); - - // Get the owning MaximizeBubbleController. This might return NULL in case - // of an asynchronous shutdown. - MaximizeBubbleController* controller() const { return owner_; } - - // Added for unit test: Retrieve the button for an action. - // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE. - views::CustomButton* GetButtonForUnitTest(SnapType state); - - private: - // True if the shut down has been initiated. - bool shutting_down_; - - // Our owning class. - MaximizeBubbleController* owner_; - - // The widget which contains our menu and the bubble border. - views::Widget* bubble_widget_; - - // The content accessor of the menu. - BubbleContentsView* contents_view_; - - // The bubble border. - MaximizeBubbleBorder* bubble_border_; - - // The rectangle before the animation starts. - gfx::Rect initial_position_; - - // The mouse watcher which takes care of out of window hover events. - scoped_ptr<views::MouseWatcher> mouse_watcher_; - - // The fade delay - if 0 it will show / hide immediately. - const int appearance_delay_ms_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleControllerBubble); -}; - -} // namespace ash - -#endif // ASH_WM_CAPTION_BUTTONS_MAXIMIZE_BUBBLE_CONTROLLER_BUBBLE_H_ diff --git a/chromium/ash/wm/coordinate_conversion.cc b/chromium/ash/wm/coordinate_conversion.cc deleted file mode 100644 index 448bd0fcbef..00000000000 --- a/chromium/ash/wm/coordinate_conversion.cc +++ /dev/null @@ -1,46 +0,0 @@ -// 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/coordinate_conversion.h" - -#include "ash/display/display_controller.h" -#include "ash/shell.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/gfx/display.h" -#include "ui/gfx/point.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/screen.h" - -namespace ash { -namespace wm { - -aura::Window* GetRootWindowAt(const gfx::Point& point) { - const gfx::Display& display = - Shell::GetScreen()->GetDisplayNearestPoint(point); - DCHECK(display.is_valid()); - // TODO(yusukes): Move coordinate_conversion.cc and .h to ui/aura/ once - // GetRootWindowForDisplayId() is moved to aura::Env. - return Shell::GetInstance()->display_controller()-> - GetRootWindowForDisplayId(display.id()); -} - -aura::Window* GetRootWindowMatching(const gfx::Rect& rect) { - const gfx::Display& display = Shell::GetScreen()->GetDisplayMatching(rect); - return Shell::GetInstance()->display_controller()-> - GetRootWindowForDisplayId(display.id()); -} - -void ConvertPointToScreen(aura::Window* window, gfx::Point* point) { - aura::client::GetScreenPositionClient(window->GetRootWindow())-> - ConvertPointToScreen(window, point); -} - -void ConvertPointFromScreen(aura::Window* window, - gfx::Point* point_in_screen) { - aura::client::GetScreenPositionClient(window->GetRootWindow())-> - ConvertPointFromScreen(window, point_in_screen); -} - -} // namespace wm -} // namespace ash diff --git a/chromium/ash/wm/coordinate_conversion.h b/chromium/ash/wm/coordinate_conversion.h deleted file mode 100644 index f5c1af8d20f..00000000000 --- a/chromium/ash/wm/coordinate_conversion.h +++ /dev/null @@ -1,43 +0,0 @@ -// 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_COORDINATE_CONVERSION_H_ -#define ASH_WM_COORDINATE_CONVERSION_H_ - -#include "ash/ash_export.h" - -namespace aura { -class Window; -} // namespace gfx - -namespace gfx { -class Point; -class Rect; -} // namespace gfx - -namespace ash { -namespace wm { - -// Returns the RootWindow at |point| in the virtual screen coordinates. -// Returns NULL if the root window does not exist at the given -// point. -ASH_EXPORT aura::Window* GetRootWindowAt(const gfx::Point& point); - -// Returns the RootWindow that shares the most area with |rect| in -// the virtual scren coordinates. -ASH_EXPORT aura::Window* GetRootWindowMatching(const gfx::Rect& rect); - -// Converts the |point| from a given |window|'s coordinates into the screen -// coordinates. -ASH_EXPORT void ConvertPointToScreen(aura::Window* window, gfx::Point* point); - -// Converts the |point| from the screen coordinates to a given |window|'s -// coordinates. -ASH_EXPORT void ConvertPointFromScreen(aura::Window* window, - gfx::Point* point_in_screen); - -} // namespace wm -} // namespace ash - -#endif // ASH_WM_COORDINATE_CONVERSION_H_ diff --git a/chromium/ash/wm/custom_frame_view_ash.cc b/chromium/ash/wm/custom_frame_view_ash.cc deleted file mode 100644 index 5617bd4006c..00000000000 --- a/chromium/ash/wm/custom_frame_view_ash.cc +++ /dev/null @@ -1,502 +0,0 @@ -// 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/custom_frame_view_ash.h" - -#include "ash/ash_switches.h" -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/caption_buttons/frame_maximize_button.h" -#include "ash/wm/caption_buttons/frame_maximize_button_observer.h" -#include "ash/wm/frame_border_hit_test_controller.h" -#include "ash/wm/header_painter.h" -#include "ash/wm/immersive_fullscreen_controller.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_state_delegate.h" -#include "base/command_line.h" -#include "grit/ash_resources.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/size.h" -#include "ui/views/view.h" -#include "ui/views/widget/native_widget_aura.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" -#include "ui/views/widget/widget_deletion_observer.h" - -namespace { - -const gfx::Font& GetTitleFont() { - static gfx::Font* title_font = NULL; - if (!title_font) - title_font = new gfx::Font(views::NativeWidgetAura::GetWindowTitleFont()); - return *title_font; -} - -/////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAshWindowStateDelegate - -// Handles a user's fullscreen request (Shift+F4/F4). Puts the window into -// immersive fullscreen if the kAshEnableImmersiveFullscreenForAllWindows -// flag is set. -class CustomFrameViewAshWindowStateDelegate - : public ash::wm::WindowStateDelegate, - public ash::wm::WindowStateObserver, - public aura::WindowObserver { - public: - CustomFrameViewAshWindowStateDelegate( - ash::wm::WindowState* window_state, - ash::CustomFrameViewAsh* custom_frame_view) - : window_state_(NULL) { -#if defined(OS_CHROMEOS) - // TODO(pkotwicz): Investigate if immersive fullscreen can be enabled for - // Windows Ash. - if (CommandLine::ForCurrentProcess()->HasSwitch( - ash::switches::kAshEnableImmersiveFullscreenForAllWindows)) { - immersive_fullscreen_controller_.reset( - new ash::ImmersiveFullscreenController); - custom_frame_view->InitImmersiveFullscreenControllerForView( - immersive_fullscreen_controller_.get()); - - // Add a window state observer to exit fullscreen properly in case - // fullscreen is exited without going through - // WindowState::ToggleFullscreen(). This is the case when exiting - // immersive fullscreen via the "Restore" window control. - // TODO(pkotwicz): This is a hack. Remove ASAP. http://crbug.com/319048 - window_state_ = window_state; - window_state_->AddObserver(this); - window_state_->window()->AddObserver(this); - } -#endif - } - virtual ~CustomFrameViewAshWindowStateDelegate() { - if (window_state_) { - window_state_->RemoveObserver(this); - window_state_->window()->RemoveObserver(this); - } - } - private: - // Overridden from ash::wm::WindowStateDelegate: - virtual bool ToggleFullscreen(ash::wm::WindowState* window_state) OVERRIDE { - bool enter_fullscreen = !window_state->IsFullscreen(); - if (enter_fullscreen) { - window_state->window()->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - } else { - window_state->Restore(); - } - if (immersive_fullscreen_controller_) { - immersive_fullscreen_controller_->SetEnabled( - ash::ImmersiveFullscreenController::WINDOW_TYPE_OTHER, - enter_fullscreen); - } - return true; - } - // Overridden from aura::WindowObserver: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { - window_state_->RemoveObserver(this); - window_state_->window()->RemoveObserver(this); - window_state_ = NULL; - } - // Overridden from ash::wm::WindowStateObserver: - virtual void OnWindowShowTypeChanged( - ash::wm::WindowState* window_state, - ash::wm::WindowShowType old_type) OVERRIDE { - if (!window_state->IsFullscreen() && - !window_state->IsMinimized() && - immersive_fullscreen_controller_.get() && - immersive_fullscreen_controller_->IsEnabled()) { - immersive_fullscreen_controller_->SetEnabled( - ash::ImmersiveFullscreenController::WINDOW_TYPE_OTHER, - false); - } - } - - ash::wm::WindowState* window_state_; - scoped_ptr<ash::ImmersiveFullscreenController> - immersive_fullscreen_controller_; - - DISALLOW_COPY_AND_ASSIGN(CustomFrameViewAshWindowStateDelegate); -}; - -} // namespace - -namespace ash { - -/////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh::HeaderView - -// View which paints the header. It slides off and on screen in immersive -// fullscreen. -class CustomFrameViewAsh::HeaderView - : public views::View, - public ImmersiveFullscreenController::Delegate, - public FrameMaximizeButtonObserver { - public: - // |frame| is the widget that the caption buttons act on. - explicit HeaderView(views::Widget* frame); - virtual ~HeaderView(); - - // Schedules a repaint for the entire title. - void SchedulePaintForTitle(); - - // Tells the window controls to reset themselves to the normal state. - void ResetWindowControls(); - - // Returns the amount of the view's pixels which should be on screen. - int GetPreferredOnScreenHeight() const; - - // Returns the view's preferred height. - int GetPreferredHeight() const; - - // Returns the view's minimum width. - int GetMinimumWidth() const; - - // views::View overrides: - virtual void Layout() OVERRIDE; - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; - - // Sets whether the header should be painted as active. - void set_paint_as_active(bool paint_as_active) { - paint_as_active_ = paint_as_active; - } - - HeaderPainter* header_painter() { - return header_painter_.get(); - } - - private: - // ImmersiveFullscreenController::Delegate overrides: - virtual void OnImmersiveRevealStarted() OVERRIDE; - virtual void OnImmersiveRevealEnded() OVERRIDE; - virtual void OnImmersiveFullscreenExited() OVERRIDE; - virtual void SetVisibleFraction(double visible_fraction) OVERRIDE; - virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const OVERRIDE; - - // FrameMaximizeButtonObserver overrides: - virtual void OnMaximizeBubbleShown(views::Widget* bubble) OVERRIDE; - - // The widget that the caption buttons act on. - views::Widget* frame_; - - // Helper for painting the header. - scoped_ptr<HeaderPainter> header_painter_; - - // View which contains the window caption buttons. - FrameCaptionButtonContainerView* caption_button_container_; - - // The maximize bubble widget. |maximize_bubble_| may be non-NULL but have - // been already destroyed. - views::Widget* maximize_bubble_; - - // Keeps track of whether |maximize_bubble_| is still alive. - scoped_ptr<views::WidgetDeletionObserver> maximize_bubble_lifetime_observer_; - - // Whether the header should be painted as active. - bool paint_as_active_; - - // The fraction of the header's height which is visible while in fullscreen. - // This value is meaningless when not in fullscreen. - double fullscreen_visible_fraction_; - - DISALLOW_COPY_AND_ASSIGN(HeaderView); -}; - -CustomFrameViewAsh::HeaderView::HeaderView(views::Widget* frame) - : frame_(frame), - header_painter_(new ash::HeaderPainter), - caption_button_container_(NULL), - maximize_bubble_(NULL), - paint_as_active_(false), - fullscreen_visible_fraction_(0) { - // Unfortunately, there is no views::WidgetDelegate::CanMinimize(). Assume - // that the window frame can be minimized if it can be maximized. - FrameCaptionButtonContainerView::MinimizeAllowed minimize_allowed = - frame_->widget_delegate()->CanMaximize() ? - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED : - FrameCaptionButtonContainerView::MINIMIZE_DISALLOWED; - caption_button_container_ = new FrameCaptionButtonContainerView(frame_, - minimize_allowed); - AddChildView(caption_button_container_); - FrameMaximizeButton* frame_maximize_button = - caption_button_container_->GetOldStyleSizeButton(); - if (frame_maximize_button) - frame_maximize_button->AddObserver(this); - - header_painter_->Init(frame_, this, NULL, caption_button_container_); -} - -CustomFrameViewAsh::HeaderView::~HeaderView() { - FrameMaximizeButton* frame_maximize_button = - caption_button_container_->GetOldStyleSizeButton(); - if (frame_maximize_button) - frame_maximize_button->RemoveObserver(this); -} - -void CustomFrameViewAsh::HeaderView::SchedulePaintForTitle() { - header_painter_->SchedulePaintForTitle(GetTitleFont()); -} - -void CustomFrameViewAsh::HeaderView::ResetWindowControls() { - caption_button_container_->ResetWindowControls(); -} - -int CustomFrameViewAsh::HeaderView::GetPreferredOnScreenHeight() const { - if (frame_->IsFullscreen()) { - return static_cast<int>( - GetPreferredHeight() * fullscreen_visible_fraction_); - } - return GetPreferredHeight(); -} - -int CustomFrameViewAsh::HeaderView::GetPreferredHeight() const { - // Reserve enough space to see the buttons and the separator line. - return caption_button_container_->bounds().bottom() + - header_painter_->HeaderContentSeparatorSize(); -} - -int CustomFrameViewAsh::HeaderView::GetMinimumWidth() const { - return header_painter_->GetMinimumHeaderWidth(); -} - -void CustomFrameViewAsh::HeaderView::Layout() { - header_painter_->LayoutHeader(true); - header_painter_->set_header_height(GetPreferredHeight()); -} - -void CustomFrameViewAsh::HeaderView::OnPaint(gfx::Canvas* canvas) { - int theme_image_id = 0; - if (frame_->IsMaximized() || frame_->IsFullscreen()) - theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_MINIMAL; - else if (paint_as_active_) - theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_ACTIVE; - else - theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_INACTIVE; - - header_painter_->PaintHeader( - canvas, - paint_as_active_ ? HeaderPainter::ACTIVE : HeaderPainter::INACTIVE, - theme_image_id, - 0); - header_painter_->PaintTitleBar(canvas, GetTitleFont()); - header_painter_->PaintHeaderContentSeparator(canvas); -} - -void CustomFrameViewAsh::HeaderView::OnImmersiveRevealStarted() { - fullscreen_visible_fraction_ = 0; - SetPaintToLayer(true); - parent()->Layout(); -} - -void CustomFrameViewAsh::HeaderView::OnImmersiveRevealEnded() { - fullscreen_visible_fraction_ = 0; - SetPaintToLayer(false); - parent()->Layout(); -} - -void CustomFrameViewAsh::HeaderView::OnImmersiveFullscreenExited() { - fullscreen_visible_fraction_ = 0; - SetPaintToLayer(false); - parent()->Layout(); -} - -void CustomFrameViewAsh::HeaderView::SetVisibleFraction( - double visible_fraction) { - if (fullscreen_visible_fraction_ != visible_fraction) { - fullscreen_visible_fraction_ = visible_fraction; - parent()->Layout(); - } -} - -std::vector<gfx::Rect> -CustomFrameViewAsh::HeaderView::GetVisibleBoundsInScreen() const { - // TODO(pkotwicz): Implement views::View::ConvertRectToScreen(). - gfx::Rect visible_bounds(GetVisibleBounds()); - gfx::Point visible_origin_in_screen(visible_bounds.origin()); - views::View::ConvertPointToScreen(this, &visible_origin_in_screen); - std::vector<gfx::Rect> bounds_in_screen; - bounds_in_screen.push_back( - gfx::Rect(visible_origin_in_screen, visible_bounds.size())); - if (maximize_bubble_lifetime_observer_.get() && - maximize_bubble_lifetime_observer_->IsWidgetAlive()) { - bounds_in_screen.push_back(maximize_bubble_->GetWindowBoundsInScreen()); - } - return bounds_in_screen; -} - -void CustomFrameViewAsh::HeaderView::OnMaximizeBubbleShown( - views::Widget* bubble) { - maximize_bubble_ = bubble; - maximize_bubble_lifetime_observer_.reset( - new views::WidgetDeletionObserver(bubble)); -} - -/////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh::OverlayView - -// View which takes up the entire widget and contains the HeaderView. HeaderView -// is a child of OverlayView to avoid creating a larger texture than necessary -// when painting the HeaderView to its own layer. -class CustomFrameViewAsh::OverlayView : public views::View { - public: - explicit OverlayView(HeaderView* header_view); - virtual ~OverlayView(); - - // views::View override: - virtual void Layout() OVERRIDE; - virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; - - private: - HeaderView* header_view_; - - DISALLOW_COPY_AND_ASSIGN(OverlayView); -}; - -CustomFrameViewAsh::OverlayView::OverlayView(HeaderView* header_view) - : header_view_(header_view) { - AddChildView(header_view); -} - -CustomFrameViewAsh::OverlayView::~OverlayView() { -} - -void CustomFrameViewAsh::OverlayView::Layout() { - int onscreen_height = header_view_->GetPreferredOnScreenHeight(); - if (onscreen_height == 0) { - header_view_->SetVisible(false); - } else { - int height = header_view_->GetPreferredHeight(); - header_view_->SetBounds(0, onscreen_height - height, width(), height); - header_view_->SetVisible(true); - } -} - -bool CustomFrameViewAsh::OverlayView::HitTestRect(const gfx::Rect& rect) const { - // Grab events in the header view. Return false for other events so that they - // can be handled by the client view. - return header_view_->HitTestRect(rect); -} - -//////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh, public: - -// static -const char CustomFrameViewAsh::kViewClassName[] = "CustomFrameViewAsh"; - -CustomFrameViewAsh::CustomFrameViewAsh(views::Widget* frame) - : frame_(frame), - header_view_(new HeaderView(frame)), - frame_border_hit_test_controller_( - new FrameBorderHitTestController(frame_)) { - // |header_view_| is set as the non client view's overlay view so that it can - // overlay the web contents in immersive fullscreen. - frame->non_client_view()->SetOverlayView(new OverlayView(header_view_)); - - // A delegate for a more complex way of fullscreening the window may already - // be set. This is the case for packaged apps. - wm::WindowState* window_state = wm::GetWindowState(frame->GetNativeWindow()); - if (!window_state->HasDelegate()) { - window_state->SetDelegate(scoped_ptr<wm::WindowStateDelegate>( - new CustomFrameViewAshWindowStateDelegate( - window_state, this)).Pass()); - } -} - -CustomFrameViewAsh::~CustomFrameViewAsh() { -} - -void CustomFrameViewAsh::InitImmersiveFullscreenControllerForView( - ImmersiveFullscreenController* immersive_fullscreen_controller) { - immersive_fullscreen_controller->Init(header_view_, frame_, header_view_); -} - -//////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh, views::NonClientFrameView overrides: - -gfx::Rect CustomFrameViewAsh::GetBoundsForClientView() const { - int top_height = NonClientTopBorderHeight(); - return HeaderPainter::GetBoundsForClientView(top_height, bounds()); -} - -gfx::Rect CustomFrameViewAsh::GetWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const { - int top_height = NonClientTopBorderHeight(); - return HeaderPainter::GetWindowBoundsForClientBounds(top_height, - client_bounds); -} - -int CustomFrameViewAsh::NonClientHitTest(const gfx::Point& point) { - return FrameBorderHitTestController::NonClientHitTest(this, - header_view_->header_painter(), point); -} - -void CustomFrameViewAsh::GetWindowMask(const gfx::Size& size, - gfx::Path* window_mask) { - // No window masks in Aura. -} - -void CustomFrameViewAsh::ResetWindowControls() { - header_view_->ResetWindowControls(); -} - -void CustomFrameViewAsh::UpdateWindowIcon() { -} - -void CustomFrameViewAsh::UpdateWindowTitle() { - header_view_->SchedulePaintForTitle(); -} - -//////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh, views::View overrides: - -gfx::Size CustomFrameViewAsh::GetPreferredSize() { - gfx::Size pref = frame_->client_view()->GetPreferredSize(); - gfx::Rect bounds(0, 0, pref.width(), pref.height()); - return frame_->non_client_view()->GetWindowBoundsForClientBounds( - bounds).size(); -} - -const char* CustomFrameViewAsh::GetClassName() const { - return kViewClassName; -} - -gfx::Size CustomFrameViewAsh::GetMinimumSize() { - gfx::Size min_client_view_size(frame_->client_view()->GetMinimumSize()); - return gfx::Size( - std::max(header_view_->GetMinimumWidth(), min_client_view_size.width()), - NonClientTopBorderHeight() + min_client_view_size.height()); -} - -gfx::Size CustomFrameViewAsh::GetMaximumSize() { - return frame_->client_view()->GetMaximumSize(); -} - -void CustomFrameViewAsh::SchedulePaintInRect(const gfx::Rect& r) { - // The HeaderView is not a child of CustomFrameViewAsh. Redirect the paint to - // HeaderView instead. - header_view_->set_paint_as_active(ShouldPaintAsActive()); - header_view_->SchedulePaint(); -} - -bool CustomFrameViewAsh::HitTestRect(const gfx::Rect& rect) const { - // NonClientView hit tests the NonClientFrameView first instead of going in - // z-order. Return false so that events get to the OverlayView. - return false; -} - -views::View* CustomFrameViewAsh::GetHeaderView() { - return header_view_; -} - -//////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh, private: - -int CustomFrameViewAsh::NonClientTopBorderHeight() const { - return frame_->IsFullscreen() ? 0 : header_view_->GetPreferredHeight(); -} - -} // namespace ash diff --git a/chromium/ash/wm/custom_frame_view_ash.h b/chromium/ash/wm/custom_frame_view_ash.h deleted file mode 100644 index 8242b246856..00000000000 --- a/chromium/ash/wm/custom_frame_view_ash.h +++ /dev/null @@ -1,90 +0,0 @@ -// 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_CUSTOM_FRAME_VIEW_ASH_H_ -#define ASH_WM_CUSTOM_FRAME_VIEW_ASH_H_ - -#include "ash/ash_export.h" -#include "base/memory/scoped_ptr.h" -#include "ui/views/window/non_client_view.h" - -namespace ash { -class FrameBorderHitTestController; -class HeaderPainter; -class ImmersiveFullscreenController; -} -namespace gfx { -class Font; -} -namespace views { -class Widget; -} - -namespace ash { - -// A NonClientFrameView used for packaged apps, dialogs and other non-browser -// windows. It supports immersive fullscreen. When in immersive fullscreen, the -// client view takes up the entire widget and the window header is an overlay. -// The window header overlay slides onscreen when the user hovers the mouse at -// the top of the screen. See also views::CustomFrameView and -// BrowserNonClientFrameViewAsh. -class ASH_EXPORT CustomFrameViewAsh : public views::NonClientFrameView { - public: - // Internal class name. - static const char kViewClassName[]; - - explicit CustomFrameViewAsh(views::Widget* frame); - virtual ~CustomFrameViewAsh(); - - // Inits |immersive_fullscreen_controller| so that the controller reveals - // and hides |header_view_| in immersive fullscreen. - // CustomFrameViewAsh does not take ownership of - // |immersive_fullscreen_controller|. - void InitImmersiveFullscreenControllerForView( - ImmersiveFullscreenController* immersive_fullscreen_controller); - - // views::NonClientFrameView overrides: - virtual gfx::Rect GetBoundsForClientView() const OVERRIDE; - virtual gfx::Rect GetWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const OVERRIDE; - virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE; - virtual void GetWindowMask(const gfx::Size& size, - gfx::Path* window_mask) OVERRIDE; - virtual void ResetWindowControls() OVERRIDE; - virtual void UpdateWindowIcon() OVERRIDE; - virtual void UpdateWindowTitle() OVERRIDE; - - // views::View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual const char* GetClassName() const OVERRIDE; - virtual gfx::Size GetMinimumSize() OVERRIDE; - virtual gfx::Size GetMaximumSize() OVERRIDE; - virtual void SchedulePaintInRect(const gfx::Rect& r) OVERRIDE; - virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; - - // Get the view of the header. - views::View* GetHeaderView(); - - private: - class OverlayView; - - // Height from top of window to top of client area. - int NonClientTopBorderHeight() const; - - // Not owned. - views::Widget* frame_; - - // View which contains the title and window controls. - class HeaderView; - HeaderView* header_view_; - - // Updates the hittest bounds overrides based on the window show type. - scoped_ptr<FrameBorderHitTestController> frame_border_hit_test_controller_; - - DISALLOW_COPY_AND_ASSIGN(CustomFrameViewAsh); -}; - -} // namespace ash - -#endif // ASH_WM_CUSTOM_FRAME_VIEW_ASH_H_ diff --git a/chromium/ash/wm/default_window_resizer.cc b/chromium/ash/wm/default_window_resizer.cc deleted file mode 100644 index 41bc1fdd328..00000000000 --- a/chromium/ash/wm/default_window_resizer.cc +++ /dev/null @@ -1,72 +0,0 @@ -// 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/default_window_resizer.h" - -#include "ash/shell.h" -#include "ash/wm/window_state.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/env.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_types.h" -#include "ui/gfx/screen.h" - -namespace ash { - -DefaultWindowResizer::~DefaultWindowResizer() { - ash::Shell::GetInstance()->cursor_manager()->UnlockCursor(); -} - -// static -DefaultWindowResizer* -DefaultWindowResizer::Create(aura::Window* window, - const gfx::Point& location, - int window_component, - aura::client::WindowMoveSource source) { - Details details(window, location, window_component, source); - return details.is_resizable ? new DefaultWindowResizer(details) : NULL; -} - -void DefaultWindowResizer::Drag(const gfx::Point& location, int event_flags) { - gfx::Rect bounds(CalculateBoundsForDrag(details_, location)); - if (bounds != details_.window->bounds()) { - if (!did_move_or_resize_ && !details_.restore_bounds.IsEmpty()) - wm::GetWindowState(details_.window)->ClearRestoreBounds(); - did_move_or_resize_ = true; - details_.window->SetBounds(bounds); - } -} - -void DefaultWindowResizer::CompleteDrag(int event_flags) { -} - -void DefaultWindowResizer::RevertDrag() { - if (!did_move_or_resize_) - return; - - details_.window->SetBounds(details_.initial_bounds_in_parent); - - if (!details_.restore_bounds.IsEmpty()) - wm::GetWindowState(details_.window)->SetRestoreBoundsInScreen( - details_.restore_bounds); -} - -aura::Window* DefaultWindowResizer::GetTarget() { - return details_.window; -} - -const gfx::Point& DefaultWindowResizer::GetInitialLocation() const { - return details_.initial_location_in_parent; -} - -DefaultWindowResizer::DefaultWindowResizer(const Details& details) - : details_(details), - did_move_or_resize_(false) { - DCHECK(details_.is_resizable); - ash::Shell::GetInstance()->cursor_manager()->LockCursor(); -} - -} // namespace aura diff --git a/chromium/ash/wm/default_window_resizer.h b/chromium/ash/wm/default_window_resizer.h deleted file mode 100644 index 621acd39f3b..00000000000 --- a/chromium/ash/wm/default_window_resizer.h +++ /dev/null @@ -1,55 +0,0 @@ -// 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_DEFAULT_WINDOW_RESIZER_H_ -#define ASH_WM_DEFAULT_WINDOW_RESIZER_H_ - -#include "ash/wm/window_resizer.h" -#include "base/compiler_specific.h" - -namespace ash { - -// WindowResizer is used by ToplevelWindowEventFilter to handle dragging, moving -// or resizing a window. All coordinates passed to this are in the parent -// windows coordiantes. -class ASH_EXPORT DefaultWindowResizer : public WindowResizer { - public: - virtual ~DefaultWindowResizer(); - - // Creates a new DefaultWindowResizer. The caller takes ownership of the - // returned object. Returns NULL if not resizable. - static DefaultWindowResizer* Create(aura::Window* window, - const gfx::Point& location, - int window_component, - aura::client::WindowMoveSource source); - - // Returns true if the drag will result in changing the window in anyway. - bool is_resizable() const { return details_.is_resizable; } - - bool changed_size() const { - return !(details_.bounds_change & kBoundsChange_Repositions); - } - aura::Window* target_window() const { return details_.window; } - - // WindowResizer: - virtual void Drag(const gfx::Point& location, int event_flags) OVERRIDE; - virtual void CompleteDrag(int event_flags) OVERRIDE; - virtual void RevertDrag() OVERRIDE; - virtual aura::Window* GetTarget() OVERRIDE; - virtual const gfx::Point& GetInitialLocation() const OVERRIDE; - - private: - explicit DefaultWindowResizer(const Details& details); - - const Details details_; - - // Set to true once Drag() is invoked and the bounds of the window change. - bool did_move_or_resize_; - - DISALLOW_COPY_AND_ASSIGN(DefaultWindowResizer); -}; - -} // namespace aura - -#endif // ASH_WM_DEFAULT_WINDOW_RESIZER_H_ diff --git a/chromium/ash/wm/dock/OWNERS b/chromium/ash/wm/dock/OWNERS deleted file mode 100644 index 55fd0c2bc27..00000000000 --- a/chromium/ash/wm/dock/OWNERS +++ /dev/null @@ -1 +0,0 @@ -varkha@chromium.org diff --git a/chromium/ash/wm/dock/dock_types.h b/chromium/ash/wm/dock/dock_types.h deleted file mode 100644 index e2ebaab1f75..00000000000 --- a/chromium/ash/wm/dock/dock_types.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2013 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_DOCK_DOCK_TYPES_H_ -#define ASH_WM_DOCK_DOCK_TYPES_H_ - -namespace ash { - -namespace internal { - -// Possible values of which side of the screen the windows are docked at. -// This is used by DockedwindowLayoutManager and DockedWindowResizer to -// implement docking behavior including magnetism while dragging windows into -// or out of the docked windows area. -enum DockedAlignment { - // No docked windows. - DOCKED_ALIGNMENT_NONE, - - // Some windows are already docked on the left side of the screen. - DOCKED_ALIGNMENT_LEFT, - - // Some windows are already docked on the right side of the screen. - DOCKED_ALIGNMENT_RIGHT, -}; - -// User action recorded for use in UMA histograms. -enum DockedAction { - DOCKED_ACTION_NONE, // Regular drag of undocked window. Not recorded. - DOCKED_ACTION_DOCK, // Dragged and docked a window. - DOCKED_ACTION_UNDOCK, // Dragged and undocked a window. - DOCKED_ACTION_RESIZE, // Resized a docked window. - DOCKED_ACTION_REORDER, // Possibly reordered docked windows. - DOCKED_ACTION_EVICT, // A docked window could not stay docked. - DOCKED_ACTION_MAXIMIZE, // Maximized a docked window. - DOCKED_ACTION_MINIMIZE, // Minimized a docked window. - DOCKED_ACTION_RESTORE, // Restored a docked window that was minimized. - DOCKED_ACTION_CLOSE, // Closed a window while it was docked. - DOCKED_ACTION_COUNT, // Maximum value of this enum for histograms use. -}; - -// Event source for the docking user action (when known). -enum DockedActionSource { - DOCKED_ACTION_SOURCE_UNKNOWN, - DOCKED_ACTION_SOURCE_MOUSE, - DOCKED_ACTION_SOURCE_TOUCH, - - // Maximum value of this enum for histograms use. - DOCKED_ACTION_SOURCE_COUNT, -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_DOCK_DOCK_TYPES_H_ diff --git a/chromium/ash/wm/dock/docked_window_layout_manager.cc b/chromium/ash/wm/dock/docked_window_layout_manager.cc deleted file mode 100644 index 3298f05602f..00000000000 --- a/chromium/ash/wm/dock/docked_window_layout_manager.cc +++ /dev/null @@ -1,1240 +0,0 @@ -// Copyright (c) 2013 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/dock/docked_window_layout_manager.h" - -#include "ash/ash_switches.h" -#include "ash/launcher/launcher.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_types.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_properties.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace_controller.h" -#include "base/auto_reset.h" -#include "base/command_line.h" -#include "base/metrics/histogram.h" -#include "grit/ash_resources.h" -#include "third_party/skia/include/core/SkColor.h" -#include "third_party/skia/include/core/SkPaint.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/client/window_tree_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/image/image_skia_operations.h" -#include "ui/gfx/rect.h" -#include "ui/views/background.h" - -namespace ash { -namespace internal { - -// Minimum, maximum width of the dock area and a width of the gap -// static -const int DockedWindowLayoutManager::kMaxDockWidth = 360; -// static -const int DockedWindowLayoutManager::kMinDockWidth = 200; -// static -const int DockedWindowLayoutManager::kMinDockGap = 2; -// static -const int DockedWindowLayoutManager::kIdealWidth = 250; -const int kMinimumHeight = 250; -const int kSlideDurationMs = 120; -const int kFadeDurationMs = 60; -const int kMinimizeDurationMs = 720; - -class DockedBackgroundWidget : public views::Widget, - public internal::BackgroundAnimatorDelegate { - public: - explicit DockedBackgroundWidget(aura::Window* container) - : alignment_(DOCKED_ALIGNMENT_NONE), - background_animator_(this, 0, kLauncherBackgroundAlpha), - alpha_(0), - opaque_background_(ui::LAYER_SOLID_COLOR) { - InitWidget(container); - } - - // Sets widget bounds and sizes opaque background layer to fill the widget. - void SetBackgroundBounds(const gfx::Rect bounds, DockedAlignment alignment) { - SetBounds(bounds); - opaque_background_.SetBounds(gfx::Rect(bounds.size())); - alignment_ = alignment; - } - - // Sets the docked area background type and starts transition animation. - void SetPaintsBackground( - ShelfBackgroundType background_type, - BackgroundAnimatorChangeType change_type) { - float target_opacity = - (background_type == SHELF_BACKGROUND_MAXIMIZED) ? 1.0f : 0.0f; - scoped_ptr<ui::ScopedLayerAnimationSettings> opaque_background_animation; - if (change_type != BACKGROUND_CHANGE_IMMEDIATE) { - opaque_background_animation.reset(new ui::ScopedLayerAnimationSettings( - opaque_background_.GetAnimator())); - opaque_background_animation->SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kTimeToSwitchBackgroundMs)); - } - opaque_background_.SetOpacity(target_opacity); - - // TODO(varkha): use ui::Layer on both opaque_background and normal - // background retire background_animator_ at all. It would be simpler. - // See also ShelfWidget::SetPaintsBackground. - background_animator_.SetPaintsBackground( - background_type != SHELF_BACKGROUND_DEFAULT, - change_type); - SchedulePaintInRect(gfx::Rect(GetWindowBoundsInScreen().size())); - } - - // views::Widget: - virtual void OnNativeWidgetPaint(gfx::Canvas* canvas) OVERRIDE { - const gfx::ImageSkia& launcher_background( - alignment_ == DOCKED_ALIGNMENT_LEFT ? - launcher_background_left_ : launcher_background_right_); - gfx::Rect rect = gfx::Rect(GetWindowBoundsInScreen().size()); - SkPaint paint; - paint.setAlpha(alpha_); - canvas->DrawImageInt( - launcher_background, - 0, 0, launcher_background.width(), launcher_background.height(), - alignment_ == DOCKED_ALIGNMENT_LEFT ? - rect.width() - launcher_background.width() : 0, 0, - launcher_background.width(), rect.height(), - false, - paint); - canvas->DrawImageInt( - launcher_background, - alignment_ == DOCKED_ALIGNMENT_LEFT ? - 0 : launcher_background.width() - 1, 0, - 1, launcher_background.height(), - alignment_ == DOCKED_ALIGNMENT_LEFT ? - 0 : launcher_background.width(), 0, - rect.width() - launcher_background.width(), rect.height(), - false, - paint); - } - - // BackgroundAnimatorDelegate: - virtual void UpdateBackground(int alpha) OVERRIDE { - alpha_ = alpha; - SchedulePaintInRect(gfx::Rect(GetWindowBoundsInScreen().size())); - } - - private: - void InitWidget(aura::Window* parent) { - views::Widget::InitParams params; - params.type = views::Widget::InitParams::TYPE_POPUP; - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.can_activate = false; - params.keep_on_top = false; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = parent; - params.accept_events = false; - set_focus_on_creation(false); - Init(params); - GetNativeWindow()->SetProperty(internal::kStayInSameRootWindowKey, true); - opaque_background_.SetColor(SK_ColorBLACK); - opaque_background_.SetBounds(gfx::Rect(GetWindowBoundsInScreen().size())); - opaque_background_.SetOpacity(0.0f); - GetNativeWindow()->layer()->Add(&opaque_background_); - Hide(); - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - gfx::ImageSkia launcher_background = - *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_BACKGROUND); - launcher_background_left_ = gfx::ImageSkiaOperations::CreateRotatedImage( - launcher_background, SkBitmapOperations::ROTATION_90_CW); - launcher_background_right_ = gfx::ImageSkiaOperations::CreateRotatedImage( - launcher_background, SkBitmapOperations::ROTATION_270_CW); - } - - DockedAlignment alignment_; - - // The animator for the background transitions. - internal::BackgroundAnimator background_animator_; - - // The alpha to use for drawing image assets covering the docked background. - int alpha_; - - // Solid black background that can be made fully opaque. - ui::Layer opaque_background_; - - // Backgrounds created from shelf background by 90 or 270 degree rotation. - gfx::ImageSkia launcher_background_left_; - gfx::ImageSkia launcher_background_right_; - - DISALLOW_COPY_AND_ASSIGN(DockedBackgroundWidget); -}; - -namespace { - -// Returns true if a window is a popup or a transient child. -bool IsPopupOrTransient(const aura::Window* window) { - return (window->type() == aura::client::WINDOW_TYPE_POPUP || - window->transient_parent()); -} - -// Certain windows (minimized, hidden or popups) do not matter to docking. -bool IsUsedByLayout(const aura::Window* window) { - return (window->IsVisible() && - !wm::GetWindowState(window)->IsMinimized() && - !IsPopupOrTransient(window)); -} - -void UndockWindow(aura::Window* window) { - gfx::Rect previous_bounds = window->bounds(); - aura::Window* old_parent = window->parent(); - aura::client::ParentWindowWithContext(window, window, gfx::Rect()); - if (window->parent() != old_parent) - wm::ReparentTransientChildrenOfChild(window, old_parent, window->parent()); - // Start maximize or fullscreen (affecting packaged apps) animation from - // previous window bounds. - window->layer()->SetBounds(previous_bounds); -} - -// Returns width that is as close as possible to |target_width| while being -// consistent with docked min and max restrictions and respects the |window|'s -// minimum and maximum size. -int GetWindowWidthCloseTo(const aura::Window* window, int target_width) { - if (!wm::GetWindowState(window)->CanResize()) { - DCHECK_LE(window->bounds().width(), - DockedWindowLayoutManager::kMaxDockWidth); - return window->bounds().width(); - } - int width = std::max(DockedWindowLayoutManager::kMinDockWidth, - std::min(target_width, - DockedWindowLayoutManager::kMaxDockWidth)); - if (window->delegate()) { - if (window->delegate()->GetMinimumSize().width() != 0) - width = std::max(width, window->delegate()->GetMinimumSize().width()); - if (window->delegate()->GetMaximumSize().width() != 0) - width = std::min(width, window->delegate()->GetMaximumSize().width()); - } - DCHECK_LE(width, DockedWindowLayoutManager::kMaxDockWidth); - return width; -} - -// Returns height that is as close as possible to |target_height| while -// respecting the |window|'s minimum and maximum size. -int GetWindowHeightCloseTo(const aura::Window* window, int target_height) { - if (!wm::GetWindowState(window)->CanResize()) - return window->bounds().height(); - int minimum_height = kMinimumHeight; - int maximum_height = 0; - const aura::WindowDelegate* delegate(window->delegate()); - if (delegate) { - if (delegate->GetMinimumSize().height() != 0) { - minimum_height = std::max(kMinimumHeight, - delegate->GetMinimumSize().height()); - } - if (delegate->GetMaximumSize().height() != 0) - maximum_height = delegate->GetMaximumSize().height(); - } - if (minimum_height) - target_height = std::max(target_height, minimum_height); - if (maximum_height) - target_height = std::min(target_height, maximum_height); - return target_height; -} - -// A functor used to sort the windows in order of their minimum height. -struct CompareMinimumHeight { - bool operator()(WindowWithHeight win1, WindowWithHeight win2) { - return GetWindowHeightCloseTo(win1.window(), 0) < - GetWindowHeightCloseTo(win2.window(), 0); - } -}; - -// 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()(WindowWithHeight window_with_height1, - WindowWithHeight window_with_height2) { - // Use target coordinates since animations may be active when windows are - // reordered. - aura::Window* win1(window_with_height1.window()); - aura::Window* win2(window_with_height2.window()); - gfx::Rect win1_bounds = ScreenAsh::ConvertRectToScreen( - win1->parent(), win1->GetTargetBounds()); - gfx::Rect win2_bounds = ScreenAsh::ConvertRectToScreen( - win2->parent(), win2->GetTargetBounds()); - win1_bounds.set_height(window_with_height1.height_); - win2_bounds.set_height(window_with_height2.height_); - // 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_; -}; - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// A class that observes launcher shelf for bounds changes. -class DockedWindowLayoutManager::ShelfWindowObserver : public WindowObserver { - public: - explicit ShelfWindowObserver( - DockedWindowLayoutManager* docked_layout_manager) - : docked_layout_manager_(docked_layout_manager) { - DCHECK(docked_layout_manager_->launcher()->shelf_widget()); - docked_layout_manager_->launcher()->shelf_widget()->GetNativeView() - ->AddObserver(this); - } - - virtual ~ShelfWindowObserver() { - if (docked_layout_manager_->launcher() && - docked_layout_manager_->launcher()->shelf_widget()) - docked_layout_manager_->launcher()->shelf_widget()->GetNativeView() - ->RemoveObserver(this); - } - - // aura::WindowObserver: - virtual void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE { - shelf_bounds_in_screen_ = ScreenAsh::ConvertRectToScreen( - window->parent(), new_bounds); - docked_layout_manager_->OnShelfBoundsChanged(); - } - - const gfx::Rect& shelf_bounds_in_screen() const { - return shelf_bounds_in_screen_; - } - - private: - DockedWindowLayoutManager* docked_layout_manager_; - gfx::Rect shelf_bounds_in_screen_; - - DISALLOW_COPY_AND_ASSIGN(ShelfWindowObserver); -}; - -//////////////////////////////////////////////////////////////////////////////// -// DockedWindowLayoutManager public implementation: -DockedWindowLayoutManager::DockedWindowLayoutManager( - aura::Window* dock_container, WorkspaceController* workspace_controller) - : dock_container_(dock_container), - in_layout_(false), - dragged_window_(NULL), - is_dragged_window_docked_(false), - is_dragged_from_dock_(false), - launcher_(NULL), - workspace_controller_(workspace_controller), - in_fullscreen_(workspace_controller_->GetWindowState() == - WORKSPACE_WINDOW_STATE_FULL_SCREEN), - docked_width_(0), - alignment_(DOCKED_ALIGNMENT_NONE), - last_active_window_(NULL), - last_action_time_(base::Time::Now()), - background_widget_(new DockedBackgroundWidget(dock_container_)) { - DCHECK(dock_container); - aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())-> - AddObserver(this); - Shell::GetInstance()->AddShellObserver(this); -} - -DockedWindowLayoutManager::~DockedWindowLayoutManager() { - Shutdown(); -} - -void DockedWindowLayoutManager::Shutdown() { - if (launcher_ && launcher_->shelf_widget()) { - ShelfLayoutManager* shelf_layout_manager = ShelfLayoutManager::ForLauncher( - launcher_->shelf_widget()->GetNativeWindow()); - shelf_layout_manager->RemoveObserver(this); - shelf_observer_.reset(); - } - launcher_ = NULL; - for (size_t i = 0; i < dock_container_->children().size(); ++i) { - aura::Window* child = dock_container_->children()[i]; - child->RemoveObserver(this); - wm::GetWindowState(child)->RemoveObserver(this); - } - aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())-> - RemoveObserver(this); - Shell::GetInstance()->RemoveShellObserver(this); -} - -void DockedWindowLayoutManager::AddObserver( - DockedWindowLayoutManagerObserver* observer) { - observer_list_.AddObserver(observer); -} - -void DockedWindowLayoutManager::RemoveObserver( - DockedWindowLayoutManagerObserver* observer) { - observer_list_.RemoveObserver(observer); -} - -void DockedWindowLayoutManager::StartDragging(aura::Window* window) { - DCHECK(!dragged_window_); - dragged_window_ = window; - DCHECK(!IsPopupOrTransient(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); - wm::GetWindowState(dragged_window_)->AddObserver(this); - } - is_dragged_from_dock_ = window->parent() == dock_container_; - DCHECK(!is_dragged_window_docked_); -} - -void DockedWindowLayoutManager::DockDraggedWindow(aura::Window* window) { - DCHECK(!IsPopupOrTransient(window)); - OnDraggedWindowDocked(window); - Relayout(); -} - -void DockedWindowLayoutManager::UndockDraggedWindow() { - DCHECK(!IsPopupOrTransient(dragged_window_)); - OnDraggedWindowUndocked(); - Relayout(); - UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED); - is_dragged_from_dock_ = false; -} - -void DockedWindowLayoutManager::FinishDragging(DockedAction action, - DockedActionSource source) { - DCHECK(dragged_window_); - DCHECK(!IsPopupOrTransient(dragged_window_)); - if (is_dragged_window_docked_) - OnDraggedWindowUndocked(); - 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); - wm::GetWindowState(dragged_window_)->RemoveObserver(this); - if (last_active_window_ == dragged_window_) - last_active_window_ = NULL; - } else { - // A window is no longer dragged and is a child. - // When a window becomes a child at drag start this is - // the only opportunity we will have to enforce a window - // count limit so do it here. - MaybeMinimizeChildrenExcept(dragged_window_); - } - dragged_window_ = NULL; - dragged_bounds_ = gfx::Rect(); - Relayout(); - UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED); - RecordUmaAction(action, source); -} - -void DockedWindowLayoutManager::SetLauncher(ash::Launcher* launcher) { - DCHECK(!launcher_); - launcher_ = launcher; - if (launcher_->shelf_widget()) { - ShelfLayoutManager* shelf_layout_manager = ShelfLayoutManager::ForLauncher( - launcher_->shelf_widget()->GetNativeWindow()); - shelf_layout_manager->AddObserver(this); - shelf_observer_.reset(new ShelfWindowObserver(this)); - } -} - -DockedAlignment DockedWindowLayoutManager::GetAlignmentOfWindow( - const aura::Window* window) const { - const gfx::Rect& bounds(window->GetBoundsInScreen()); - - // Test overlap with an existing docked area first. - if (docked_bounds_.Intersects(bounds) && - alignment_ != DOCKED_ALIGNMENT_NONE) { - // A window is being added to other docked windows (on the same side). - return alignment_; - } - - const gfx::Rect container_bounds = dock_container_->GetBoundsInScreen(); - if (bounds.x() <= container_bounds.x() && - bounds.right() > container_bounds.x()) { - return DOCKED_ALIGNMENT_LEFT; - } else if (bounds.x() < container_bounds.right() && - bounds.right() >= container_bounds.right()) { - return DOCKED_ALIGNMENT_RIGHT; - } - return DOCKED_ALIGNMENT_NONE; -} - -DockedAlignment DockedWindowLayoutManager::CalculateAlignment() const { - // Find a child that is not being dragged and is not a popup. - // If such exists the current alignment is returned - even if some of the - // children are hidden or minimized (so they can be restored without losing - // the docked state). - for (size_t i = 0; i < dock_container_->children().size(); ++i) { - aura::Window* window(dock_container_->children()[i]); - if (window != dragged_window_ && !IsPopupOrTransient(window)) - return alignment_; - } - // No docked windows remain other than possibly the window being dragged. - // Return |NONE| to indicate that windows may get docked on either side. - return DOCKED_ALIGNMENT_NONE; -} - -bool DockedWindowLayoutManager::CanDockWindow(aura::Window* window, - SnapType edge) { - if (!switches::UseDockedWindows()) - return false; - // Don't allow interactive docking of windows with transient parents such as - // modal browser dialogs. - if (IsPopupOrTransient(window)) - return false; - // If a window is wide and cannot be resized down to maximum width allowed - // then it cannot be docked. - // TODO(varkha). Prevent windows from changing size programmatically while - // they are docked. The size will take effect only once a window is undocked. - // See http://crbug.com/307792. - if (window->bounds().width() > kMaxDockWidth && - (!wm::GetWindowState(window)->CanResize() || - (window->delegate() && - window->delegate()->GetMinimumSize().width() != 0 && - window->delegate()->GetMinimumSize().width() > kMaxDockWidth))) { - return false; - } - // If a window is tall and cannot be resized down to maximum height allowed - // then it cannot be docked. - const gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area(); - if (GetWindowHeightCloseTo(window, work_area.height() - 2 * kMinDockGap) > - work_area.height() - 2 * kMinDockGap) { - return false; - } - // Cannot dock on the other size from an existing dock. - const DockedAlignment alignment = CalculateAlignment(); - if ((edge == SNAP_LEFT && alignment == DOCKED_ALIGNMENT_RIGHT) || - (edge == SNAP_RIGHT && alignment == DOCKED_ALIGNMENT_LEFT)) { - return false; - } - // Do not allow docking on the same side as launcher shelf. - ShelfAlignment shelf_alignment = SHELF_ALIGNMENT_BOTTOM; - if (launcher_) - shelf_alignment = launcher_->alignment(); - if ((edge == SNAP_LEFT && shelf_alignment == SHELF_ALIGNMENT_LEFT) || - (edge == SNAP_RIGHT && shelf_alignment == SHELF_ALIGNMENT_RIGHT)) { - return false; - } - return true; -} - -void DockedWindowLayoutManager::OnShelfBoundsChanged() { - Relayout(); - UpdateDockBounds(DockedWindowLayoutManagerObserver::DISPLAY_INSETS_CHANGED); -} - -//////////////////////////////////////////////////////////////////////////////// -// DockedWindowLayoutManager, aura::LayoutManager implementation: -void DockedWindowLayoutManager::OnWindowResized() { - MaybeMinimizeChildrenExcept(dragged_window_); - Relayout(); - // When screen resizes update the insets even when dock width or alignment - // does not change. - UpdateDockBounds(DockedWindowLayoutManagerObserver::DISPLAY_RESIZED); -} - -void DockedWindowLayoutManager::OnWindowAddedToLayout(aura::Window* child) { - if (IsPopupOrTransient(child)) - 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); - } - MaybeMinimizeChildrenExcept(child); - child->AddObserver(this); - wm::GetWindowState(child)->AddObserver(this); - Relayout(); - UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED); -} - -void DockedWindowLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { - if (IsPopupOrTransient(child)) - 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; - UpdateDockedWidth(0); - } - if (last_active_window_ == child) - last_active_window_ = NULL; - child->RemoveObserver(this); - wm::GetWindowState(child)->RemoveObserver(this); - Relayout(); - UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED); -} - -void DockedWindowLayoutManager::OnChildWindowVisibilityChanged( - aura::Window* child, - bool visible) { - if (IsPopupOrTransient(child)) - return; - if (visible) - wm::GetWindowState(child)->Restore(); - Relayout(); - UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED); -} - -void DockedWindowLayoutManager::SetChildBounds( - aura::Window* child, - const gfx::Rect& requested_bounds) { - // Whenever one of our windows is moved or resized enforce layout. - SetChildBoundsDirect(child, requested_bounds); - if (IsPopupOrTransient(child)) - return; - ShelfLayoutManager* shelf_layout = internal::ShelfLayoutManager::ForLauncher( - dock_container_); - if (shelf_layout) - shelf_layout->UpdateVisibilityState(); -} - -//////////////////////////////////////////////////////////////////////////////// -// DockedWindowLayoutManager, ash::ShellObserver implementation: - -void DockedWindowLayoutManager::OnDisplayWorkAreaInsetsChanged() { - Relayout(); - UpdateDockBounds(DockedWindowLayoutManagerObserver::DISPLAY_INSETS_CHANGED); - MaybeMinimizeChildrenExcept(dragged_window_); -} - -void DockedWindowLayoutManager::OnFullscreenStateChanged( - bool is_fullscreen, aura::Window* root_window) { - if (dock_container_->GetRootWindow() != root_window) - return; - // Entering fullscreen mode (including immersive) hides docked windows. - in_fullscreen_ = workspace_controller_->GetWindowState() == - WORKSPACE_WINDOW_STATE_FULL_SCREEN; - { - // prevent Relayout from getting called multiple times during this - base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true); - // Use a copy of children array because a call to MinimizeDockedWindow or - // RestoreDockedWindow can change order. - aura::Window::Windows children(dock_container_->children()); - for (aura::Window::Windows::const_iterator iter = children.begin(); - iter != children.end(); ++iter) { - aura::Window* window(*iter); - if (IsPopupOrTransient(window)) - continue; - wm::WindowState* window_state = wm::GetWindowState(window); - if (in_fullscreen_) { - if (window->IsVisible()) - MinimizeDockedWindow(window_state); - } else { - if (!window_state->IsMinimized()) - RestoreDockedWindow(window_state); - } - } - } - Relayout(); - UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED); -} - -void DockedWindowLayoutManager::OnShelfAlignmentChanged( - aura::Window* root_window) { - if (dock_container_->GetRootWindow() != root_window) - return; - - if (!launcher_ || !launcher_->shelf_widget()) - return; - - if (alignment_ == DOCKED_ALIGNMENT_NONE) - return; - - // Do not allow launcher and dock on the same side. Switch side that - // the dock is attached to and move all dock windows to that new side. - ShelfAlignment shelf_alignment = launcher_->shelf_widget()->GetAlignment(); - if (alignment_ == DOCKED_ALIGNMENT_LEFT && - shelf_alignment == SHELF_ALIGNMENT_LEFT) { - alignment_ = DOCKED_ALIGNMENT_RIGHT; - } else if (alignment_ == DOCKED_ALIGNMENT_RIGHT && - shelf_alignment == SHELF_ALIGNMENT_RIGHT) { - alignment_ = DOCKED_ALIGNMENT_LEFT; - } - Relayout(); - UpdateDockBounds(DockedWindowLayoutManagerObserver::SHELF_ALIGNMENT_CHANGED); -} - -///////////////////////////////////////////////////////////////////////////// -// DockedWindowLayoutManager, ShelfLayoutManagerObserver implementation: -void DockedWindowLayoutManager::OnBackgroundUpdated( - ShelfBackgroundType background_type, - BackgroundAnimatorChangeType change_type) { - background_widget_->SetPaintsBackground(background_type, change_type); -} - -///////////////////////////////////////////////////////////////////////////// -// DockedWindowLayoutManager, WindowStateObserver implementation: - -void DockedWindowLayoutManager::OnWindowShowTypeChanged( - wm::WindowState* window_state, - wm::WindowShowType old_type) { - aura::Window* window = window_state->window(); - if (IsPopupOrTransient(window)) - return; - // The window property will still be set, but no actual change will occur - // until OnFullscreenStateChange is called when exiting fullscreen. - if (in_fullscreen_) - return; - if (window_state->IsMinimized()) { - MinimizeDockedWindow(window_state); - } else if (window_state->IsMaximizedOrFullscreen() || - window_state->IsSnapped()) { - if (window != dragged_window_) { - UndockWindow(window); - RecordUmaAction(DOCKED_ACTION_MAXIMIZE, DOCKED_ACTION_SOURCE_UNKNOWN); - } - } else if (old_type == wm::SHOW_TYPE_MINIMIZED) { - RestoreDockedWindow(window_state); - } -} - -///////////////////////////////////////////////////////////////////////////// -// DockedWindowLayoutManager, WindowObserver implementation: - -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_) - Relayout(); -} - -void DockedWindowLayoutManager::OnWindowVisibilityChanging( - aura::Window* window, bool visible) { - if (IsPopupOrTransient(window)) - return; - int animation_type = views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT; - if (visible) { - animation_type = views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_DROP; - views::corewm::SetWindowVisibilityAnimationDuration( - window, base::TimeDelta::FromMilliseconds(kFadeDurationMs)); - } else if (wm::GetWindowState(window)->IsMinimized()) { - animation_type = WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE; - } - views::corewm::SetWindowVisibilityAnimationType(window, animation_type); -} - -void DockedWindowLayoutManager::OnWindowDestroying(aura::Window* window) { - if (dragged_window_ == window) { - FinishDragging(DOCKED_ACTION_NONE, DOCKED_ACTION_SOURCE_UNKNOWN); - DCHECK(!dragged_window_); - DCHECK (!is_dragged_window_docked_); - } - if (window == last_active_window_) - last_active_window_ = NULL; - RecordUmaAction(DOCKED_ACTION_CLOSE, DOCKED_ACTION_SOURCE_UNKNOWN); -} - - -//////////////////////////////////////////////////////////////////////////////// -// DockedWindowLayoutManager, aura::client::ActivationChangeObserver -// implementation: - -void DockedWindowLayoutManager::OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) { - if (gained_active && IsPopupOrTransient(gained_active)) - return; - // Ignore if the window that is not managed by this was activated. - aura::Window* ancestor = NULL; - for (aura::Window* parent = gained_active; - parent; parent = parent->parent()) { - if (parent->parent() == dock_container_) { - ancestor = parent; - break; - } - } - if (ancestor) - UpdateStacking(ancestor); -} - -//////////////////////////////////////////////////////////////////////////////// -// DockedWindowLayoutManager private implementation: - -void DockedWindowLayoutManager::MaybeMinimizeChildrenExcept( - aura::Window* child) { - // Minimize any windows that don't fit without overlap. - const gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area(); - int available_room = work_area.height() - kMinDockGap; - if (child) - available_room -= (GetWindowHeightCloseTo(child, 0) + kMinDockGap); - // Use a copy of children array because a call to Minimize can change order. - aura::Window::Windows children(dock_container_->children()); - aura::Window::Windows::const_reverse_iterator iter = children.rbegin(); - while (iter != children.rend()) { - aura::Window* window(*iter++); - if (window == child || !IsUsedByLayout(window)) - continue; - int room_needed = GetWindowHeightCloseTo(window, 0) + kMinDockGap; - if (available_room > room_needed) { - available_room -= room_needed; - } else { - // Slow down minimizing animations. Lock duration so that it is not - // overridden by other ScopedLayerAnimationSettings down the stack. - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kMinimizeDurationMs)); - settings.LockTransitionDuration(); - wm::GetWindowState(window)->Minimize(); - } - } -} - -void DockedWindowLayoutManager::MinimizeDockedWindow( - wm::WindowState* window_state) { - DCHECK(!IsPopupOrTransient(window_state->window())); - window_state->window()->Hide(); - if (window_state->IsActive()) - window_state->Deactivate(); - RecordUmaAction(DOCKED_ACTION_MINIMIZE, DOCKED_ACTION_SOURCE_UNKNOWN); -} - -void DockedWindowLayoutManager::RestoreDockedWindow( - wm::WindowState* window_state) { - aura::Window* window = window_state->window(); - DCHECK(!IsPopupOrTransient(window)); - // Always place restored window at the bottom shuffling the other windows up. - // TODO(varkha): add a separate container for docked windows to keep track - // of ordering. - gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow( - dock_container_); - const gfx::Rect work_area = display.work_area(); - - // Evict the window if it can no longer be docked because of its height. - if (!CanDockWindow(window, SNAP_NONE)) { - UndockWindow(window); - RecordUmaAction(DOCKED_ACTION_EVICT, DOCKED_ACTION_SOURCE_UNKNOWN); - return; - } - gfx::Rect bounds(window->bounds()); - bounds.set_y(work_area.bottom()); - window->SetBounds(bounds); - window->Show(); - MaybeMinimizeChildrenExcept(window); - RecordUmaAction(DOCKED_ACTION_RESTORE, DOCKED_ACTION_SOURCE_UNKNOWN); -} - -void DockedWindowLayoutManager::RecordUmaAction(DockedAction action, - DockedActionSource source) { - if (action == DOCKED_ACTION_NONE) - return; - UMA_HISTOGRAM_ENUMERATION("Ash.Dock.Action", action, DOCKED_ACTION_COUNT); - UMA_HISTOGRAM_ENUMERATION("Ash.Dock.ActionSource", source, - DOCKED_ACTION_SOURCE_COUNT); - base::Time time_now = base::Time::Now(); - base::TimeDelta time_between_use = time_now - last_action_time_; - UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.Dock.TimeBetweenUse", - time_between_use.InSeconds(), - 1, - base::TimeDelta::FromHours(10).InSeconds(), - 100); - last_action_time_ = time_now; - int docked_all_count = 0; - int docked_visible_count = 0; - int docked_panels_count = 0; - int large_windows_count = 0; - for (size_t i = 0; i < dock_container_->children().size(); ++i) { - const aura::Window* window(dock_container_->children()[i]); - if (IsPopupOrTransient(window)) - continue; - docked_all_count++; - if (!IsUsedByLayout(window)) - continue; - docked_visible_count++; - if (window->type() == aura::client::WINDOW_TYPE_PANEL) - docked_panels_count++; - const wm::WindowState* window_state = wm::GetWindowState(window); - if (window_state->HasRestoreBounds()) { - const gfx::Rect restore_bounds = window_state->GetRestoreBoundsInScreen(); - if (restore_bounds.width() > kMaxDockWidth) - large_windows_count++; - } - } - UMA_HISTOGRAM_COUNTS_100("Ash.Dock.ItemsAll", docked_all_count); - UMA_HISTOGRAM_COUNTS_100("Ash.Dock.ItemsLarge", large_windows_count); - UMA_HISTOGRAM_COUNTS_100("Ash.Dock.ItemsPanels", docked_panels_count); - UMA_HISTOGRAM_COUNTS_100("Ash.Dock.ItemsVisible", docked_visible_count); -} - -void DockedWindowLayoutManager::UpdateDockedWidth(int width) { - if (docked_width_ == width) - return; - docked_width_ = width; - UMA_HISTOGRAM_COUNTS_10000("Ash.Dock.Width", docked_width_); -} - -void DockedWindowLayoutManager::OnDraggedWindowDocked(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::OnDraggedWindowUndocked() { - // 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; -} - -void DockedWindowLayoutManager::Relayout() { - if (in_layout_) - return; - if (alignment_ == DOCKED_ALIGNMENT_NONE && !is_dragged_window_docked_) - return; - base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true); - - gfx::Rect dock_bounds = dock_container_->GetBoundsInScreen(); - aura::Window* active_window = NULL; - std::vector<WindowWithHeight> visible_windows; - for (size_t i = 0; i < dock_container_->children().size(); ++i) { - aura::Window* window(dock_container_->children()[i]); - - if (!IsUsedByLayout(window) || window == dragged_window_) - continue; - - // If the shelf is currently hidden (full-screen mode), hide window until - // full-screen mode is exited. - if (in_fullscreen_) { - // The call to Hide does not set the minimize property, so the window will - // be restored when the shelf becomes visible again. - window->Hide(); - continue; - } - if (window->HasFocus() || - window->Contains( - aura::client::GetFocusClient(window)->GetFocusedWindow())) { - DCHECK(!active_window); - active_window = window; - } - visible_windows.push_back(WindowWithHeight(window)); - } - // Consider docked dragged_window_ when fanning out other child windows. - if (is_dragged_window_docked_) { - visible_windows.push_back(WindowWithHeight(dragged_window_)); - DCHECK(!active_window); - active_window = dragged_window_; - } - - // Position docked windows as well as the window being dragged. - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area(); - if (shelf_observer_) - work_area.Subtract(shelf_observer_->shelf_bounds_in_screen()); - int available_room = CalculateWindowHeightsAndRemainingRoom(work_area, - &visible_windows); - FanOutChildren(work_area, - CalculateIdealWidth(visible_windows), - available_room, - &visible_windows); - - // After the first Relayout allow the windows to change their order easier - // since we know they are docked. - is_dragged_from_dock_ = true; - UpdateStacking(active_window); -} - -int DockedWindowLayoutManager::CalculateWindowHeightsAndRemainingRoom( - const gfx::Rect work_area, - std::vector<WindowWithHeight>* visible_windows) { - int available_room = work_area.height() - kMinDockGap; - int remaining_windows = visible_windows->size(); - - // Sort windows by their minimum heights and calculate target heights. - std::sort(visible_windows->begin(), visible_windows->end(), - CompareMinimumHeight()); - // Distribute the free space among the docked windows. Since the windows are - // sorted (tall windows first) we can now assume that any window which - // required more space than the current window will have already been - // accounted for previously in this loop, so we can safely give that window - // its proportional share of the remaining space. - for (std::vector<WindowWithHeight>::reverse_iterator iter = - visible_windows->rbegin(); - iter != visible_windows->rend(); ++iter) { - iter->height_ = GetWindowHeightCloseTo( - iter->window(), available_room / remaining_windows - kMinDockGap); - available_room -= (iter->height_ + kMinDockGap); - remaining_windows--; - } - return available_room; -} - -int DockedWindowLayoutManager::CalculateIdealWidth( - const std::vector<WindowWithHeight>& visible_windows) { - int smallest_max_width = kMaxDockWidth; - int largest_min_width = kMinDockWidth; - // Ideal width of the docked area is as close to kIdealWidth as possible - // while still respecting the minimum and maximum width restrictions on the - // individual docked windows as well as the width that was possibly set by a - // user (which needs to be preserved when dragging and rearranging windows). - for (std::vector<WindowWithHeight>::const_iterator iter = - visible_windows.begin(); - iter != visible_windows.end(); ++iter) { - const aura::Window* window = iter->window(); - int min_window_width = window->bounds().width(); - int max_window_width = min_window_width; - if (!wm::GetWindowState(window)->bounds_changed_by_user()) { - min_window_width = GetWindowWidthCloseTo(window, kMinDockWidth); - max_window_width = GetWindowWidthCloseTo(window, kMaxDockWidth); - } - largest_min_width = std::max(largest_min_width, min_window_width); - smallest_max_width = std::min(smallest_max_width, max_window_width); - } - int ideal_width = std::max(largest_min_width, - std::min(smallest_max_width, kIdealWidth)); - // Restrict docked area width regardless of window restrictions. - ideal_width = std::max(std::min(ideal_width, kMaxDockWidth), kMinDockWidth); - return ideal_width; -} - -void DockedWindowLayoutManager::FanOutChildren( - const gfx::Rect& work_area, - int ideal_docked_width, - int available_room, - std::vector<WindowWithHeight>* visible_windows) { - gfx::Rect dock_bounds = dock_container_->GetBoundsInScreen(); - - // Calculate initial vertical offset and the gap or overlap between windows. - const int num_windows = visible_windows->size(); - const float delta = kMinDockGap + (float)available_room / - ((available_room > 0 || num_windows <= 1) ? - num_windows + 1 : num_windows - 1); - float y_pos = work_area.y() + ((delta > 0) ? delta : kMinDockGap); - - // Docked area is shown only if there is at least one non-dragged visible - // docked window. - int new_width = ideal_docked_width; - if (visible_windows->empty() || - (visible_windows->size() == 1 && - (*visible_windows)[0].window() == dragged_window_)) { - new_width = 0; - } - UpdateDockedWidth(new_width); - // 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)); - for (std::vector<WindowWithHeight>::iterator iter = visible_windows->begin(); - iter != visible_windows->end(); ++iter) { - aura::Window* window = iter->window(); - gfx::Rect bounds = ScreenAsh::ConvertRectToScreen( - window->parent(), window->GetTargetBounds()); - // A window is extended or shrunk to be as close as possible to the ideal - // docked area width. Windows that were resized by a user are kept at their - // existing size. - // This also enforces the min / max restrictions on the docked area width. - bounds.set_width(GetWindowWidthCloseTo( - window, - wm::GetWindowState(window)->bounds_changed_by_user() ? - bounds.width() : ideal_docked_width)); - DCHECK_LE(bounds.width(), ideal_docked_width); - - DockedAlignment alignment = alignment_; - if (alignment == DOCKED_ALIGNMENT_NONE && window == dragged_window_) { - alignment = GetAlignmentOfWindow(window); - if (alignment == DOCKED_ALIGNMENT_NONE) - bounds.set_size(gfx::Size()); - } - - // Fan out windows evenly distributing the overlap or remaining free space. - bounds.set_height(iter->height_); - bounds.set_y(std::max(work_area.y(), - std::min(work_area.bottom() - bounds.height(), - static_cast<int>(y_pos + 0.5)))); - y_pos += bounds.height() + delta; - - // All docked windows other than the one currently dragged remain stuck - // to the screen edge (flush with the edge or centered in the dock area). - switch (alignment) { - case DOCKED_ALIGNMENT_LEFT: - bounds.set_x(dock_bounds.x() + - (ideal_docked_width - bounds.width()) / 2); - break; - case DOCKED_ALIGNMENT_RIGHT: - bounds.set_x(dock_bounds.right() - - (ideal_docked_width + bounds.width()) / 2); - break; - case DOCKED_ALIGNMENT_NONE: - break; - } - if (window == dragged_window_) { - dragged_bounds_ = bounds; - continue; - } - // If the following asserts it is probably because not all the children - // have been removed when dock was closed. - DCHECK_NE(alignment_, DOCKED_ALIGNMENT_NONE); - bounds = ScreenAsh::ConvertRectFromScreen(dock_container_, bounds); - if (bounds != window->GetTargetBounds()) { - ui::Layer* layer = window->layer(); - ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator()); - slide_settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - slide_settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kSlideDurationMs)); - SetChildBoundsDirect(window, bounds); - } - } -} - -void DockedWindowLayoutManager::UpdateDockBounds( - DockedWindowLayoutManagerObserver::Reason reason) { - int dock_inset = docked_width_ + (docked_width_ > 0 ? kMinDockGap : 0); - const gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area(); - gfx::Rect bounds = gfx::Rect( - alignment_ == DOCKED_ALIGNMENT_RIGHT && dock_inset > 0 ? - dock_container_->bounds().right() - dock_inset: - dock_container_->bounds().x(), - dock_container_->bounds().y(), - dock_inset, - work_area.height()); - docked_bounds_ = bounds + - dock_container_->GetBoundsInScreen().OffsetFromOrigin(); - FOR_EACH_OBSERVER( - DockedWindowLayoutManagerObserver, - observer_list_, - OnDockBoundsChanging(bounds, reason)); - // Show or hide background for docked area. - gfx::Rect background_bounds(docked_bounds_); - if (shelf_observer_) - background_bounds.Subtract(shelf_observer_->shelf_bounds_in_screen()); - background_widget_->SetBackgroundBounds(background_bounds, alignment_); - if (docked_width_ > 0) - background_widget_->Show(); - else - background_widget_->Hide(); -} - -void DockedWindowLayoutManager::UpdateStacking(aura::Window* active_window) { - if (!active_window) { - if (!last_active_window_) - return; - active_window = last_active_window_; - } - - // Windows are stacked like a deck of cards: - // ,------. - // |,------.| - // |,------.| - // | active | - // | window | - // |`------'| - // |`------'| - // `------' - // 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; - for (aura::Window::Windows::const_iterator it = - dock_container_->children().begin(); - it != dock_container_->children().end(); ++it) { - if (!IsUsedByLayout(*it) || - ((*it) == dragged_window_ && !is_dragged_window_docked_)) { - continue; - } - gfx::Rect bounds = (*it)->bounds(); - window_ordering.insert(std::make_pair(bounds.y() + bounds.height() / 2, - *it)); - } - int active_center_y = active_window->bounds().CenterPoint().y(); - - aura::Window* previous_window = NULL; - for (std::map<int, aura::Window*>::const_iterator it = - window_ordering.begin(); - it != window_ordering.end() && it->first < active_center_y; ++it) { - if (previous_window) - dock_container_->StackChildAbove(it->second, previous_window); - previous_window = it->second; - } - for (std::map<int, aura::Window*>::const_reverse_iterator it = - window_ordering.rbegin(); - it != window_ordering.rend() && it->first > active_center_y; ++it) { - if (previous_window) - dock_container_->StackChildAbove(it->second, previous_window); - previous_window = it->second; - } - - if (previous_window && active_window->parent() == dock_container_) - dock_container_->StackChildAbove(active_window, previous_window); - if (active_window != dragged_window_) - last_active_window_ = active_window; -} - -//////////////////////////////////////////////////////////////////////////////// -// keyboard::KeyboardControllerObserver implementation: - -void DockedWindowLayoutManager::OnKeyboardBoundsChanging( - const gfx::Rect& keyboard_bounds) { - // This bounds change will have caused a change to the Shelf which does not - // propagate automatically to this class, so manually recalculate bounds. - Relayout(); - UpdateDockBounds(DockedWindowLayoutManagerObserver::KEYBOARD_BOUNDS_CHANGING); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/dock/docked_window_layout_manager.h b/chromium/ash/wm/dock/docked_window_layout_manager.h deleted file mode 100644 index 8894bed42fa..00000000000 --- a/chromium/ash/wm/dock/docked_window_layout_manager.h +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright (c) 2013 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_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_H_ -#define ASH_WM_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_H_ - -#include "ash/ash_export.h" -#include "ash/shelf/shelf_layout_manager_observer.h" -#include "ash/shell_observer.h" -#include "ash/wm/dock/dock_types.h" -#include "ash/wm/dock/docked_window_layout_manager_observer.h" -#include "ash/wm/window_state_observer.h" -#include "ash/wm/workspace/snap_types.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "base/time/time.h" -#include "ui/aura/client/activation_change_observer.h" -#include "ui/aura/layout_manager.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/rect.h" -#include "ui/keyboard/keyboard_controller_observer.h" - -namespace aura { -class Window; -} - -namespace gfx { -class Point; -} - -namespace views { -class Widget; -} - -namespace ash { -class Launcher; - -namespace internal { -class DockedBackgroundWidget; -class DockedWindowLayoutManagerObserver; -class DockedWindowResizerTest; -class ShelfLayoutManager; -class WorkspaceController; - -struct WindowWithHeight { - explicit WindowWithHeight(aura::Window* window) : - window_(window), - height_(window->bounds().height()) { } - aura::Window* window() { return window_; } - const aura::Window* window() const { return window_; } - aura::Window* window_; - int height_; -}; - -// DockedWindowLayoutManager is responsible for organizing windows when they are -// docked to the side of a screen. It is associated with a specific container -// window (i.e. kShellWindowId_DockContainer) and controls the layout of any -// windows added to that container. -// -// The constructor takes a |dock_container| argument which is expected to set -// 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, - public aura::WindowObserver, - public aura::client::ActivationChangeObserver, - public keyboard::KeyboardControllerObserver, - public ShelfLayoutManagerObserver, - public wm::WindowStateObserver { - public: - // Maximum width of the docked windows area. - static const int kMaxDockWidth; - - // Minimum width of the docked windows area. - static const int kMinDockWidth; - - DockedWindowLayoutManager(aura::Window* dock_container, - WorkspaceController* workspace_controller); - virtual ~DockedWindowLayoutManager(); - - // Disconnects observers before container windows get destroyed. - void Shutdown(); - - // Management of the observer list. - virtual void AddObserver(DockedWindowLayoutManagerObserver* observer); - 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. - // Records |action| by |source| in UMA. - void FinishDragging(DockedAction action, DockedActionSource source); - - 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; - - // Returns true when a window can be docked. Windows cannot be docked at the - // edge used by the launcher shelf or the edge opposite from existing dock. - bool CanDockWindow(aura::Window* window, SnapType edge); - - 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_;} - - // Returns true if currently dragged window is docked at the screen edge. - bool is_dragged_window_docked() const { return is_dragged_window_docked_; } - - // Updates docked layout when launcher shelf bounds change. - void OnShelfBoundsChanged(); - - // aura::LayoutManager: - virtual void OnWindowResized() OVERRIDE; - virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {} - virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; - virtual void OnChildWindowVisibilityChanged(aura::Window* child, - bool visibile) OVERRIDE; - virtual void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) OVERRIDE; - - // ash::ShellObserver: - virtual void OnDisplayWorkAreaInsetsChanged() OVERRIDE; - virtual void OnFullscreenStateChanged(bool is_fullscreen, - aura::Window* root_window) OVERRIDE; - virtual void OnShelfAlignmentChanged(aura::Window* root_window) OVERRIDE; - - // ShelfLayoutManagerObserver: - virtual void OnBackgroundUpdated( - ShelfBackgroundType background_type, - BackgroundAnimatorChangeType change_type) OVERRIDE; - - // wm::WindowStateObserver: - virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType old_type) OVERRIDE; - - // aura::WindowObserver: - virtual void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - virtual void OnWindowVisibilityChanging(aura::Window* window, - bool visible) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - // aura::client::ActivationChangeObserver: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE; - - private: - class ShelfWindowObserver; - friend class DockedWindowLayoutManagerTest; - friend class DockedWindowResizerTest; - - // Width of the gap between the docked windows and a workspace. - static const int kMinDockGap; - - // Ideal (starting) width of the dock. - static const int kIdealWidth; - - // Keep at most kMaxVisibleWindows visible in the dock and minimize the rest - // (except for |child|). - void MaybeMinimizeChildrenExcept(aura::Window* child); - - // Minimize / restore window and relayout. - void MinimizeDockedWindow(wm::WindowState* window_state); - void RestoreDockedWindow(wm::WindowState* window_state); - - // Record user-initiated |action| by |source| in UMA metrics. - void RecordUmaAction(DockedAction action, DockedActionSource source); - - // Updates |docked_width_| and UMA histograms. - void UpdateDockedWidth(int width); - - // Updates docked layout state when a window gets inside the dock. - void OnDraggedWindowDocked(aura::Window* window); - - // Updates docked layout state when a window gets outside the dock. - void OnDraggedWindowUndocked(); - - // Returns true if there are any windows currently docked. - bool IsAnyWindowDocked(); - - // Called whenever the window layout might change. - void Relayout(); - - // Calculates target heights (and fills it in |visible_windows| array) such - // that the vertical space is fairly distributed among the windows taking - // into account their minimum and maximum size. Returns free vertical space - // (positive value) that remains after resizing all windows or deficit - // (negative value) if not all the windows fit. - int CalculateWindowHeightsAndRemainingRoom( - const gfx::Rect work_area, - std::vector<WindowWithHeight>* visible_windows); - - // Calculate ideal width for the docked area. It will get used to adjust the - // dragged window or other windows as necessary. - int CalculateIdealWidth(const std::vector<WindowWithHeight>& visible_windows); - - // Fan out windows evenly distributing the overlap or remaining free space. - // Adjust the widths of the windows trying to make them all same. If this - // is not possible, center the windows in the docked area. - void FanOutChildren(const gfx::Rect& work_area, - int ideal_docked_width, - int available_room, - std::vector<WindowWithHeight>* visible_windows); - - // Updates |docked_bounds_| and workspace insets when bounds of docked windows - // area change. Passing |reason| to observers allows selectively skipping - // notifications. - void UpdateDockBounds(DockedWindowLayoutManagerObserver::Reason reason); - - // Called whenever the window stacking order needs to be updated (e.g. focus - // changes or a window is moved). - void UpdateStacking(aura::Window* active_window); - - // keyboard::KeyboardControllerObserver: - virtual void OnKeyboardBoundsChanging( - const gfx::Rect& keyboard_bounds) OVERRIDE; - - // Parent window associated with this layout manager. - 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. - 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 to respond to launcher alignment changes. - Launcher* launcher_; - - // Workspace controller that can be checked for fullscreen mode. - WorkspaceController* workspace_controller_; - // Tracks if any window in the same root window is in fullscreen mode. - bool in_fullscreen_; - // Current width of the dock. - int docked_width_; - - // 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_; - - // The last active window. Used to maintain stacking order even if no windows - // are currently focused. - aura::Window* last_active_window_; - - // Timestamp of the last user-initiated action that changed docked state. - // Used in UMA metrics. - base::Time last_action_time_; - - // Observes launcher shelf for bounds changes. - scoped_ptr<ShelfWindowObserver> shelf_observer_; - - // Widget used to paint a background for the docked area. - scoped_ptr<DockedBackgroundWidget> background_widget_; - - // Observers of dock bounds changes. - ObserverList<DockedWindowLayoutManagerObserver> observer_list_; - - DISALLOW_COPY_AND_ASSIGN(DockedWindowLayoutManager); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_H_ diff --git a/chromium/ash/wm/dock/docked_window_layout_manager_observer.h b/chromium/ash/wm/dock/docked_window_layout_manager_observer.h deleted file mode 100644 index f5297533c9f..00000000000 --- a/chromium/ash/wm/dock/docked_window_layout_manager_observer.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2013 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 UI_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_OBSERVER_H_ -#define UI_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_OBSERVER_H_ - -#include "ash/ash_export.h" - -namespace gfx { -class Rect; -} - -namespace ash { -namespace internal { - -// Observers to the DockedWindowLayoutManager are notified of significant -// events that occur with the docked windows, such as the bounds change. -class ASH_EXPORT DockedWindowLayoutManagerObserver { - public: - // Reason for notification. Allows selectively ignoring notifications to - // prevent a notification loop. - enum Reason { - CHILD_CHANGED, - DISPLAY_RESIZED, - DISPLAY_INSETS_CHANGED, - SHELF_ALIGNMENT_CHANGED, - KEYBOARD_BOUNDS_CHANGING - }; - // Called after the dock bounds are changed. - virtual void OnDockBoundsChanging(const gfx::Rect& new_bounds, - Reason reason) = 0; - - protected: - virtual ~DockedWindowLayoutManagerObserver() {} -}; - -} // namespace internal -} // namespace ash - -#endif // UI_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_OBSERVER_H_ diff --git a/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc b/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc deleted file mode 100644 index 54e642a3086..00000000000 --- a/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc +++ /dev/null @@ -1,819 +0,0 @@ -// Copyright (c) 2013 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/dock/docked_window_layout_manager.h" - -#include "ash/ash_switches.h" -#include "ash/launcher/launcher.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_model.h" -#include "ash/shelf/shelf_types.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/launcher_test_api.h" -#include "ash/test/shelf_view_test_api.h" -#include "ash/test/shell_test_api.h" -#include "ash/test/test_shelf_delegate.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/panels/panel_layout_manager.h" -#include "ash/wm/window_resizer.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/basictypes.h" -#include "base/command_line.h" -#include "base/strings/string_number_conversions.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_window_delegate.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 { -namespace internal { - -class DockedWindowLayoutManagerTest - : public test::AshTestBase, - public testing::WithParamInterface<aura::client::WindowType> { - public: - DockedWindowLayoutManagerTest() : window_type_(GetParam()) {} - virtual ~DockedWindowLayoutManagerTest() {} - - virtual void SetUp() OVERRIDE { - CommandLine::ForCurrentProcess()->AppendSwitch( - ash::switches::kAshEnableDockedWindows); - AshTestBase::SetUp(); - UpdateDisplay("600x600"); - ASSERT_TRUE(test::TestShelfDelegate::instance()); - - shelf_view_test_.reset(new test::ShelfViewTestAPI( - test::LauncherTestAPI(Launcher::ForPrimaryDisplay()).shelf_view())); - shelf_view_test_->SetAnimationDuration(1); - } - - protected: - enum DockedEdge { - DOCKED_EDGE_NONE, - DOCKED_EDGE_LEFT, - DOCKED_EDGE_RIGHT, - }; - - int min_dock_gap() const { return DockedWindowLayoutManager::kMinDockGap; } - int ideal_width() const { return DockedWindowLayoutManager::kIdealWidth; } - int docked_width(const DockedWindowLayoutManager* layout_manager) const { - return layout_manager->docked_width_; - } - - aura::Window* CreateTestWindow(const gfx::Rect& bounds) { - aura::Window* window = CreateTestWindowInShellWithDelegateAndType( - NULL, window_type_, 0, bounds); - if (window_type_ == aura::client::WINDOW_TYPE_PANEL) { - test::TestShelfDelegate* shelf_delegate = - test::TestShelfDelegate::instance(); - shelf_delegate->AddLauncherItem(window); - PanelLayoutManager* manager = - static_cast<PanelLayoutManager*>(GetPanelContainer(window)-> - layout_manager()); - manager->Relayout(); - } - return window; - } - - aura::Window* CreateTestWindowWithDelegate( - const gfx::Rect& bounds, - aura::test::TestWindowDelegate* delegate) { - aura::Window* window = CreateTestWindowInShellWithDelegateAndType( - delegate, window_type_, 0, bounds); - if (window_type_ == aura::client::WINDOW_TYPE_PANEL) { - test::TestShelfDelegate* shelf_delegate = - test::TestShelfDelegate::instance(); - shelf_delegate->AddLauncherItem(window); - PanelLayoutManager* manager = - static_cast<PanelLayoutManager*>(GetPanelContainer(window)-> - layout_manager()); - manager->Relayout(); - } - return window; - } - - aura::Window* GetPanelContainer(aura::Window* panel) { - return Shell::GetContainer(panel->GetRootWindow(), - internal::kShellWindowId_PanelContainer); - } - - static WindowResizer* CreateSomeWindowResizer( - aura::Window* window, - const gfx::Point& point_in_parent, - int window_component) { - return CreateWindowResizer( - window, - point_in_parent, - window_component, - aura::client::WINDOW_MOVE_SOURCE_MOUSE).release(); - } - - void DragStart(aura::Window* window) { - DragStartAtOffsetFromwindowOrigin(window, 0, 0); - } - - void DragStartAtOffsetFromwindowOrigin(aura::Window* window, - int dx, int dy) { - initial_location_in_parent_ = - window->bounds().origin() + gfx::Vector2d(dx, dy); - resizer_.reset(CreateSomeWindowResizer(window, - initial_location_in_parent_, - HTCAPTION)); - ASSERT_TRUE(resizer_.get()); - } - - void DragMove(int dx, int dy) { - resizer_->Drag(initial_location_in_parent_ + gfx::Vector2d(dx, dy), 0); - } - - void DragEnd() { - resizer_->CompleteDrag(0); - resizer_.reset(); - } - - void DragRevert() { - resizer_->RevertDrag(); - resizer_.reset(); - } - - // Panels are parented by panel container during drags. - // 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() { - if (window_type_ == aura::client::WINDOW_TYPE_PANEL) - return internal::kShellWindowId_PanelContainer; - return internal::kShellWindowId_DockedContainer; - } - - // Test dragging the window vertically (to detach if it is a panel) and then - // horizontally to the edge with an added offset from the edge of |dx|. - void DragRelativeToEdge(DockedEdge edge, - aura::Window* window, - int dx) { - DragVerticallyAndRelativeToEdge( - edge, - window, - dx, - window_type_ == aura::client::WINDOW_TYPE_PANEL ? -100 : 20); - } - - void DragToVerticalPositionAndToEdge(DockedEdge edge, - aura::Window* window, - int y) { - DragToVerticalPositionRelativeToEdge(edge, window, 0, y); - } - - void DragToVerticalPositionRelativeToEdge(DockedEdge edge, - aura::Window* window, - int dx, - int y) { - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - DragVerticallyAndRelativeToEdge(edge, window, dx, y - initial_bounds.y()); - } - - // Detach if our window is a panel, then drag it vertically by |dy| and - // horizontally to the edge with an added offset from the edge of |dx|. - void DragVerticallyAndRelativeToEdge(DockedEdge edge, - aura::Window* window, - int dx, int dy) { - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - // avoid snap by clicking away from the border - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(window, 25, 5)); - - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(window).work_area(); - gfx::Point initial_location_in_screen = initial_location_in_parent_; - wm::ConvertPointToScreen(window->parent(), &initial_location_in_screen); - // Drag the window left or right to the edge (or almost to it). - if (edge == DOCKED_EDGE_LEFT) - dx += work_area.x() - initial_location_in_screen.x(); - else if (edge == DOCKED_EDGE_RIGHT) - dx += work_area.right() - 1 - initial_location_in_screen.x(); - DragMove(dx, dy); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); - // Release the mouse and the panel should be attached to the dock. - DragEnd(); - - // x-coordinate can get adjusted by snapping or sticking. - // y-coordinate could be changed by possible automatic layout if docked. - if (window->parent()->id() != internal::kShellWindowId_DockedContainer && - !wm::GetWindowState(window)->HasRestoreBounds()) { - EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y()); - } - } - - private: - scoped_ptr<WindowResizer> resizer_; - scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_; - aura::client::WindowType window_type_; - - // Location at start of the drag in |window->parent()|'s coordinates. - gfx::Point initial_location_in_parent_; - - DISALLOW_COPY_AND_ASSIGN(DockedWindowLayoutManagerTest); -}; - -// Tests that a created window is successfully added to the dock -// layout manager. -TEST_P(DockedWindowLayoutManagerTest, AddOneWindow) { - if (!SupportsHostWindowResize()) - return; - - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); - - // The window should be attached and docked at the right edge. - // Its width should shrink or grow to ideal width. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(ideal_width(), window->bounds().width()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); -} - -// Tests that with a window docked on the left the auto-placing logic in -// RearrangeVisibleWindowOnShow places windows flush with work area edges. -TEST_P(DockedWindowLayoutManagerTest, AutoPlacingLeft) { - if (!SupportsHostWindowResize()) - return; - - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 0); - - // The window should be attached and snapped to the right side of the screen. - EXPECT_EQ(window->GetRootWindow()->bounds().x(), - window->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - DockedWindowLayoutManager* manager = static_cast<DockedWindowLayoutManager*>( - window->parent()->layout_manager()); - - // Create two additional windows and test their auto-placement - scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1)); - gfx::Rect desktop_area = window1->parent()->bounds(); - wm::GetWindowState(window1.get())->set_window_position_managed(true); - window1->Hide(); - window1->SetBounds(gfx::Rect(250, 32, 231, 320)); - window1->Show(); - // |window1| should be centered in work area. - EXPECT_EQ(base::IntToString( - docked_width(manager) + min_dock_gap() + - (desktop_area.width() - docked_width(manager) - - min_dock_gap() - window1->bounds().width()) / 2) + - ",32 231x320", window1->bounds().ToString()); - - scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(2)); - wm::GetWindowState(window2.get())->set_window_position_managed(true); - // To avoid any auto window manager changes due to SetBounds, the window - // gets first hidden and then shown again. - window2->Hide(); - window2->SetBounds(gfx::Rect(250, 48, 150, 300)); - window2->Show(); - - // |window1| should be flush left and |window2| flush right. - EXPECT_EQ( - base::IntToString(docked_width(manager) + min_dock_gap()) + - ",32 231x320", window1->bounds().ToString()); - EXPECT_EQ( - base::IntToString( - desktop_area.width() - window2->bounds().width()) + - ",48 150x300", window2->bounds().ToString()); -} - -// Tests that with a window docked on the right the auto-placing logic in -// RearrangeVisibleWindowOnShow places windows flush with work area edges. -TEST_P(DockedWindowLayoutManagerTest, AutoPlacingRight) { - if (!SupportsHostWindowResize()) - return; - - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); - - // The window should be attached and snapped to the right side of the screen. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - DockedWindowLayoutManager* manager = static_cast<DockedWindowLayoutManager*>( - window->parent()->layout_manager()); - - // Create two additional windows and test their auto-placement - scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1)); - gfx::Rect desktop_area = window1->parent()->bounds(); - wm::GetWindowState(window1.get())->set_window_position_managed(true); - window1->Hide(); - window1->SetBounds(gfx::Rect(16, 32, 231, 320)); - window1->Show(); - - // |window1| should be centered in work area. - EXPECT_EQ(base::IntToString( - (desktop_area.width() - docked_width(manager) - - min_dock_gap() - window1->bounds().width()) / 2) + - ",32 231x320", window1->bounds().ToString()); - - scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(2)); - wm::GetWindowState(window2.get())->set_window_position_managed(true); - // To avoid any auto window manager changes due to SetBounds, the window - // gets first hidden and then shown again. - window2->Hide(); - window2->SetBounds(gfx::Rect(32, 48, 256, 512)); - window2->Show(); - - // |window1| should be flush left and |window2| flush right. - EXPECT_EQ("0,32 231x320", window1->bounds().ToString()); - EXPECT_EQ( - base::IntToString( - desktop_area.width() - window2->bounds().width() - - docked_width(manager) - min_dock_gap()) + - ",48 256x512", window2->bounds().ToString()); -} - -// Tests that with a window docked on the right the auto-placing logic in -// RearrangeVisibleWindowOnShow places windows flush with work area edges. -// Test case for the secondary screen. -TEST_P(DockedWindowLayoutManagerTest, AutoPlacingRightSecondScreen) { - if (!SupportsMultipleDisplays() || !SupportsHostWindowResize()) - return; - - // Create two screen layout. - UpdateDisplay("600x600,600x600"); - - gfx::Rect bounds(600, 0, 201, 201); - scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); - // Drag pointer to the right edge of the second screen. - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); - - // The window should be attached and snapped to the right side of the screen. - EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - DockedWindowLayoutManager* manager = static_cast<DockedWindowLayoutManager*>( - window->parent()->layout_manager()); - - // Create two additional windows and test their auto-placement - bounds = gfx::Rect(616, 32, 231, 320); - scoped_ptr<aura::Window> window1( - CreateTestWindowInShellWithDelegate(NULL, 1, bounds)); - gfx::Rect desktop_area = window1->parent()->bounds(); - wm::GetWindowState(window1.get())->set_window_position_managed(true); - window1->Hide(); - window1->Show(); - - // |window1| should be centered in work area. - EXPECT_EQ(base::IntToString( - 600 + (desktop_area.width() - docked_width(manager) - - min_dock_gap() - window1->bounds().width()) / 2) + - ",32 231x320", window1->GetBoundsInScreen().ToString()); - - bounds = gfx::Rect(632, 48, 256, 512); - scoped_ptr<aura::Window> window2( - CreateTestWindowInShellWithDelegate(NULL, 2, bounds)); - wm::GetWindowState(window2.get())->set_window_position_managed(true); - // To avoid any auto window manager changes due to SetBounds, the window - // gets first hidden and then shown again. - window2->Hide(); - window2->Show(); - - // |window1| should be flush left and |window2| flush right. - EXPECT_EQ("600,32 231x320", window1->GetBoundsInScreen().ToString()); - EXPECT_EQ( - base::IntToString( - 600 + desktop_area.width() - window2->bounds().width() - - docked_width(manager) - min_dock_gap()) + - ",48 256x512", window2->GetBoundsInScreen().ToString()); -} - -// Adds two windows and tests that the gaps are evenly distributed. -TEST_P(DockedWindowLayoutManagerTest, AddTwoWindows) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 202))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 300); - - // The 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()); - - // Test that the gaps differ at most by a single pixel. - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area(); - int gap1 = w1->GetBoundsInScreen().y(); - int gap2 = w2->GetBoundsInScreen().y() - w1->GetBoundsInScreen().bottom(); - int gap3 = work_area.bottom() - w2->GetBoundsInScreen().bottom(); - EXPECT_NEAR(gap1, min_dock_gap(), 1); - EXPECT_NEAR(gap2, min_dock_gap(), 1); - EXPECT_NEAR(gap3, min_dock_gap(), 1); -} - -// Adds two non-overlapping windows and tests layout after a drag. -TEST_P(DockedWindowLayoutManagerTest, TwoWindowsDragging) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 202))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 300); - - // The 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()); - - // Drag w2 above w1. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w2.get(), 0, 20)); - DragMove(0, -w2->bounds().height() / 2 - min_dock_gap() - 1); - DragEnd(); - - // Test the new windows order and that the gaps differ at most by a pixel. - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area(); - int gap1 = w2->GetBoundsInScreen().y() - work_area.y(); - int gap2 = w1->GetBoundsInScreen().y() - w2->GetBoundsInScreen().bottom(); - int gap3 = work_area.bottom() - w1->GetBoundsInScreen().bottom(); - EXPECT_NEAR(gap1, min_dock_gap(), 1); - EXPECT_NEAR(gap2, min_dock_gap(), 1); - EXPECT_NEAR(gap3, min_dock_gap(), 1); -} - -// Adds three overlapping windows and tests layout after a drag. -TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDragging) { - if (!SupportsHostWindowResize()) - return; - UpdateDisplay("600x1000"); - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 310))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 310))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 500); - scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 0, 220, 310))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w3.get(), 600); - - // 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()); - - // Test that the top and bottom windows are clamped in work area and - // that the gaps between the windows differ at most by a pixel. - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area(); - int gap1 = w1->GetBoundsInScreen().y() - work_area.y(); - int gap2 = w2->GetBoundsInScreen().y() - w1->GetBoundsInScreen().bottom(); - int gap3 = w3->GetBoundsInScreen().y() - w2->GetBoundsInScreen().bottom(); - int gap4 = work_area.bottom() - w3->GetBoundsInScreen().bottom(); - EXPECT_NEAR(gap1, min_dock_gap(), 1); - EXPECT_NEAR(gap2, min_dock_gap(), 1); - EXPECT_NEAR(gap3, min_dock_gap(), 1); - EXPECT_NEAR(gap4, min_dock_gap(), 1); - - // Drag w1 below the point where w1 and w2 would swap places. This point is - // half way between the tops of those two windows. - // A bit more vertical drag is needed to account for a window bounds changing - // to its restore bounds during the drag. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w1.get(), 0, 20)); - DragMove(0, min_dock_gap() + w2->bounds().height() / 2 + 10); - - // During the drag the windows get rearranged and the top and the bottom - // should be limited by the work area + |kMinDockGap|. - EXPECT_EQ(min_dock_gap(), w2->GetBoundsInScreen().y()); - EXPECT_GT(w1->GetBoundsInScreen().y(), w2->GetBoundsInScreen().y()); - EXPECT_EQ(min_dock_gap(), - work_area.bottom() - w3->GetBoundsInScreen().bottom()); - DragEnd(); - - // Test the new windows order and that the gaps differ at most by a pixel. - gap1 = w2->GetBoundsInScreen().y() - work_area.y(); - gap2 = w1->GetBoundsInScreen().y() - w2->GetBoundsInScreen().bottom(); - gap3 = w3->GetBoundsInScreen().y() - w1->GetBoundsInScreen().bottom(); - gap4 = work_area.bottom() - w3->GetBoundsInScreen().bottom(); - EXPECT_NEAR(gap1, min_dock_gap(), 1); - EXPECT_NEAR(gap2, min_dock_gap(), 1); - EXPECT_NEAR(gap3, min_dock_gap(), 1); - EXPECT_NEAR(gap4, min_dock_gap(), 1); -} - -// Adds three windows in bottom display and tests layout after a drag. -TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDraggingSecondScreen) { - if (!SupportsMultipleDisplays() || !SupportsHostWindowResize()) - return; - - // Create two screen vertical layout. - UpdateDisplay("600x1000,600x1000"); - // Layout the secondary display to the bottom of the primary. - DisplayLayout layout(DisplayLayout::BOTTOM, 0); - ASSERT_GT(Shell::GetScreen()->GetNumDisplays(), 1); - Shell::GetInstance()->display_manager()-> - SetLayoutForCurrentDisplays(layout); - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 1000, 201, 310))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 1000 + 20); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 1000, 210, 310))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 1000 + 500); - scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 1000, 220, 310))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w3.get(), 1000 + 600); - - // 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 gap1 = w1->GetBoundsInScreen().y() - work_area.y(); - int gap2 = w2->GetBoundsInScreen().y() - w1->GetBoundsInScreen().bottom(); - int gap3 = w3->GetBoundsInScreen().y() - w2->GetBoundsInScreen().bottom(); - int gap4 = work_area.bottom() - w3->GetBoundsInScreen().bottom(); - EXPECT_NEAR(gap1, min_dock_gap(), 1); - EXPECT_NEAR(gap2, min_dock_gap(), 1); - EXPECT_NEAR(gap3, min_dock_gap(), 1); - EXPECT_NEAR(gap4, min_dock_gap(), 1); - - // Drag w1 below the point where w1 and w2 would swap places. This point is - // half way between the tops of those two windows. - // A bit more vertical drag is needed to account for a window bounds changing - // to its restore bounds during the drag. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w1.get(), 0, 20)); - DragMove(0, min_dock_gap() + w2->bounds().height() / 2 + 10); - - // During the drag the windows get rearranged and the top and the bottom - // should be limited by the work area + |kMinDockGap|. - EXPECT_EQ(work_area.y() + min_dock_gap(), w2->GetBoundsInScreen().y()); - EXPECT_GT(w1->GetBoundsInScreen().y(), w2->GetBoundsInScreen().y()); - EXPECT_EQ(min_dock_gap(), - work_area.bottom() - w3->GetBoundsInScreen().bottom()); - DragEnd(); - - // Test the new windows order and that the overlaps differ at most by a pixel. - gap1 = w2->GetBoundsInScreen().y() - work_area.y(); - gap2 = w1->GetBoundsInScreen().y() - w2->GetBoundsInScreen().bottom(); - gap3 = w3->GetBoundsInScreen().y() - w1->GetBoundsInScreen().bottom(); - gap4 = work_area.bottom() - w3->GetBoundsInScreen().bottom(); - EXPECT_NEAR(gap1, min_dock_gap(), 1); - EXPECT_NEAR(gap2, min_dock_gap(), 1); - EXPECT_NEAR(gap3, min_dock_gap(), 1); - EXPECT_NEAR(gap4, min_dock_gap(), 1); -} - -// Tests that a second window added to the dock is resized to match. -TEST_P(DockedWindowLayoutManagerTest, TwoWindowsWidthNew) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 280, 202))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // The first window should get resized to ideal width. - EXPECT_EQ(ideal_width(), w1->bounds().width()); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 300); - // The second window should get resized to the existing dock. - EXPECT_EQ(ideal_width(), w2->bounds().width()); -} - -// Tests that a first non-resizable window added to the dock is not resized. -TEST_P(DockedWindowLayoutManagerTest, TwoWindowsWidthNonResizableFirst) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - w1->SetProperty(aura::client::kCanResizeKey, false); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 280, 202))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // The first window should not get resized. - EXPECT_EQ(201, w1->bounds().width()); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 300); - // The second window should get resized to the first window's width. - EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); -} - -// Tests that a second non-resizable window added to the dock is not resized. -TEST_P(DockedWindowLayoutManagerTest, TwoWindowsWidthNonResizableSecond) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 280, 202))); - w2->SetProperty(aura::client::kCanResizeKey, false); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // The first window should get resized to ideal width. - EXPECT_EQ(ideal_width(), w1->bounds().width()); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 300); - // The second window should not get resized. - EXPECT_EQ(280, w2->bounds().width()); - - // The first window should get resized again - to match the second window. - EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); -} - -// Test that restrictions on minimum and maximum width of windows are honored. -TEST_P(DockedWindowLayoutManagerTest, TwoWindowsWidthRestrictions) { - if (!SupportsHostWindowResize()) - return; - - aura::test::TestWindowDelegate delegate1; - delegate1.set_maximum_size(gfx::Size(240, 0)); - scoped_ptr<aura::Window> w1(CreateTestWindowWithDelegate( - gfx::Rect(0, 0, 201, 201), &delegate1)); - aura::test::TestWindowDelegate delegate2; - delegate2.set_minimum_size(gfx::Size(260, 0)); - scoped_ptr<aura::Window> w2(CreateTestWindowWithDelegate( - gfx::Rect(0, 0, 280, 202), &delegate2)); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // The first window should get resized to its maximum width. - EXPECT_EQ(240, w1->bounds().width()); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 300); - // The second window should get resized to its minimum width. - EXPECT_EQ(260, w2->bounds().width()); - - // The first window should be centered relative to the second. - EXPECT_EQ(w1->bounds().CenterPoint().x(), w2->bounds().CenterPoint().x()); -} - -// Test that restrictions on minimum width of windows are honored. -TEST_P(DockedWindowLayoutManagerTest, WidthMoreThanMax) { - if (!SupportsHostWindowResize()) - return; - - aura::test::TestWindowDelegate delegate; - delegate.set_minimum_size(gfx::Size(400, 0)); - scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( - gfx::Rect(0, 0, 400, 201), &delegate)); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, window.get(), 20); - - // Secondary drag ensures that we are testing the minimum size restriction - // and not just failure to get past the tiling step in SnapSizer. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(window.get(), - 25, 5)); - DragMove(150,0); - DragEnd(); - - // The window should not get docked even though it is dragged past the edge. - EXPECT_NE(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_NE(internal::kShellWindowId_DockedContainer, window->parent()->id()); -} - -// Docks three windows and tests that the very first window gets minimized. -TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsMinimize) { - if (!SupportsHostWindowResize()) - return; - - 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); - scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 0, 220, 204))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w3.get(), 300); - - // The last two windows should be attached and snapped to the right edge. - 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()); - - // The first window should get minimized but parented by the dock container. - EXPECT_TRUE(wm::GetWindowState(w1.get())->IsMinimized()); - EXPECT_TRUE(wm::GetWindowState(w2.get())->IsNormalShowState()); - EXPECT_TRUE(wm::GetWindowState(w3.get())->IsNormalShowState()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); -} - -// Docks up to three windows and tests that they split vertical space. -TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsSplitHeightEvenly) { - if (!SupportsHostWindowResize()) - return; - - UpdateDisplay("600x1000"); - 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); - - // The two windows should be attached and snapped to the right edge. - 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()); - - // The two windows should be same size vertically and almost 1/2 of work area. - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area(); - EXPECT_NEAR(w1->GetBoundsInScreen().height(), - w2->GetBoundsInScreen().height(), - 1); - EXPECT_NEAR(work_area.height() / 2, w1->GetBoundsInScreen().height(), - min_dock_gap() * 2); - - // Create and dock the third window. - scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 0, 220, 204))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w3.get(), 300); - - // All three windows should be docked and snapped to the right edge. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w3->parent()->id()); - - // All windows should be near same size vertically and about 1/3 of work area. - EXPECT_NEAR(w1->GetBoundsInScreen().height(), - w2->GetBoundsInScreen().height(), - 1); - EXPECT_NEAR(w2->GetBoundsInScreen().height(), - w3->GetBoundsInScreen().height(), - 1); - EXPECT_NEAR(work_area.height() / 3, w1->GetBoundsInScreen().height(), - min_dock_gap() * 2); -} - -// Docks two windows and tests that restrictions on vertical size are honored. -TEST_P(DockedWindowLayoutManagerTest, TwoWindowsHeightRestrictions) { - if (!SupportsHostWindowResize()) - return; - - // The first window is fixed height. - aura::test::TestWindowDelegate delegate1; - delegate1.set_minimum_size(gfx::Size(0, 300)); - delegate1.set_maximum_size(gfx::Size(0, 300)); - scoped_ptr<aura::Window> w1(CreateTestWindowWithDelegate( - gfx::Rect(0, 0, 201, 300), &delegate1)); - // The second window has maximum height. - aura::test::TestWindowDelegate delegate2; - delegate2.set_maximum_size(gfx::Size(0, 100)); - scoped_ptr<aura::Window> w2(CreateTestWindowWithDelegate( - gfx::Rect(0, 0, 280, 90), &delegate2)); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 200); - - // The two windows should be attached and snapped to the right edge. - 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()); - - // The two windows should have their heights restricted. - EXPECT_EQ(300, w1->GetBoundsInScreen().height()); - EXPECT_EQ(100, w2->GetBoundsInScreen().height()); - - // w1 should be more than half of the work area height (even with a margin). - // w2 should be less than half of the work area height (even with a margin). - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area(); - EXPECT_GT(w1->GetBoundsInScreen().height(), work_area.height() / 2 + 10); - EXPECT_LT(w2->GetBoundsInScreen().height(), work_area.height() / 2 - 10); -} - -// Tests run twice - on both panels and normal windows -INSTANTIATE_TEST_CASE_P(NormalOrPanel, - DockedWindowLayoutManagerTest, - testing::Values(aura::client::WINDOW_TYPE_NORMAL, - aura::client::WINDOW_TYPE_PANEL)); -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/dock/docked_window_resizer.cc b/chromium/ash/wm/dock/docked_window_resizer.cc deleted file mode 100644 index cd06beec370..00000000000 --- a/chromium/ash/wm/dock/docked_window_resizer.cc +++ /dev/null @@ -1,337 +0,0 @@ -// Copyright 2013 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/dock/docked_window_resizer.h" - -#include "ash/display/display_controller.h" -#include "ash/launcher/launcher.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_types.h" -#include "ash/shelf/shelf_widget.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/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/magnetism_matcher.h" -#include "ash/wm/workspace/workspace_window_resizer.h" -#include "base/command_line.h" -#include "base/memory/weak_ptr.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/window_tree_client.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_types.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -namespace { - -DockedWindowLayoutManager* GetDockedLayoutManagerAtPoint( - const gfx::Point& point) { - gfx::Display display = ScreenAsh::FindDisplayContainingPoint(point); - if (!display.is_valid()) - return NULL; - aura::Window* root = Shell::GetInstance()->display_controller()-> - GetRootWindowForDisplayId(display.id()); - aura::Window* dock_container = Shell::GetContainer( - root, kShellWindowId_DockedContainer); - return static_cast<DockedWindowLayoutManager*>( - dock_container->layout_manager()); -} - -} // namespace - -DockedWindowResizer::~DockedWindowResizer() { -} - -// static -DockedWindowResizer* -DockedWindowResizer::Create(WindowResizer* next_window_resizer, - aura::Window* window, - const gfx::Point& location, - int window_component, - aura::client::WindowMoveSource source) { - Details details(window, location, window_component, source); - return details.is_resizable ? - new DockedWindowResizer(next_window_resizer, details) : NULL; -} - -void DockedWindowResizer::Drag(const gfx::Point& location, int event_flags) { - last_location_ = location; - wm::ConvertPointToScreen(GetTarget()->parent(), &last_location_); - if (!did_move_or_resize_) { - did_move_or_resize_ = true; - StartedDragging(); - } - gfx::Point offset; - gfx::Rect bounds(CalculateBoundsForDrag(details_, location)); - MaybeSnapToEdge(bounds, &offset); - gfx::Point modified_location(location); - modified_location.Offset(offset.x(), offset.y()); - - base::WeakPtr<DockedWindowResizer> resizer(weak_ptr_factory_.GetWeakPtr()); - next_window_resizer_->Drag(modified_location, event_flags); - if (!resizer) - return; - - DockedWindowLayoutManager* new_dock_layout = - GetDockedLayoutManagerAtPoint(last_location_); - if (new_dock_layout && 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_->is_dragged_window_docked()) - dock_layout_->UndockDraggedWindow(); - if (dock_layout_ != initial_dock_layout_) - dock_layout_->FinishDragging( - DOCKED_ACTION_NONE, - details_.source == aura::client::WINDOW_MOVE_SOURCE_MOUSE ? - DOCKED_ACTION_SOURCE_MOUSE : DOCKED_ACTION_SOURCE_TOUCH); - 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()); - } - // Window could get docked by the WorkspaceWindowResizer, update the state. - is_docked_ = dock_layout_->is_dragged_window_docked(); - // Whenever a window is dragged out of the dock it will be auto-sized - // in the dock if it gets docked again. - if (!is_docked_) - was_bounds_changed_by_user_ = false; -} - -void DockedWindowResizer::CompleteDrag(int event_flags) { - // The root window can change when dragging into a different screen. - next_window_resizer_->CompleteDrag(event_flags); - FinishedDragging(); -} - -void DockedWindowResizer::RevertDrag() { - next_window_resizer_->RevertDrag(); - // Restore docked state to what it was before the drag if necessary. - if (is_docked_ != was_docked_) { - is_docked_ = was_docked_; - if (is_docked_) - dock_layout_->DockDraggedWindow(GetTarget()); - else - dock_layout_->UndockDraggedWindow(); - } - FinishedDragging(); -} - -aura::Window* DockedWindowResizer::GetTarget() { - return next_window_resizer_->GetTarget(); -} - -const gfx::Point& DockedWindowResizer::GetInitialLocation() const { - return details_.initial_location_in_parent; -} - -DockedWindowResizer::DockedWindowResizer(WindowResizer* next_window_resizer, - const Details& details) - : 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), - was_bounds_changed_by_user_( - wm::GetWindowState(details.window)->bounds_changed_by_user()), - weak_ptr_factory_(this) { - DCHECK(details_.is_resizable); - aura::Window* dock_container = Shell::GetContainer( - details.window->GetRootWindow(), - kShellWindowId_DockedContainer); - dock_layout_ = static_cast<DockedWindowLayoutManager*>( - dock_container->layout_manager()); - initial_dock_layout_ = dock_layout_; - was_docked_ = details.window->parent() == dock_container; - is_docked_ = was_docked_; -} - -void DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds, - gfx::Point* offset) { - // Windows only snap magnetically when they were previously docked. - if (!was_docked_) - return; - DockedAlignment dock_alignment = dock_layout_->CalculateAlignment(); - gfx::Rect dock_bounds = ScreenAsh::ConvertRectFromScreen( - GetTarget()->parent(), - dock_layout_->dock_container()->GetBoundsInScreen()); - - // 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) { - const int distance = bounds.x() - dock_bounds.x(); - if (distance < kSnapToDockDistance && distance > 0) { - offset->set_x(-distance); - return; - } - } - if (dock_alignment == DOCKED_ALIGNMENT_RIGHT || - dock_alignment == DOCKED_ALIGNMENT_NONE) { - const int distance = dock_bounds.right() - bounds.right(); - if (distance < kSnapToDockDistance && distance > 0) - offset->set_x(distance); - } -} - -void DockedWindowResizer::StartedDragging() { - // During resizing the window width is preserved by DockedwindowLayoutManager. - wm::WindowState* window_state = wm::GetWindowState(GetTarget()); - if (is_docked_ && - (details_.bounds_change & WindowResizer::kBoundsChange_Resizes)) { - window_state->set_bounds_changed_by_user(true); - } - - // 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. - window_state->set_continue_drag_after_reparent(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); - wm::ReparentChildWithTransientChildren(GetTarget(), - GetTarget()->parent(), - docked_container); - } - if (is_docked_) - dock_layout_->DockDraggedWindow(GetTarget()); -} - -void DockedWindowResizer::FinishedDragging() { - if (!did_move_or_resize_) - return; - did_move_or_resize_ = false; - aura::Window* window = GetTarget(); - wm::WindowState* window_state = wm::GetWindowState(window); - const bool is_attached_panel = - window->type() == aura::client::WINDOW_TYPE_PANEL && - window_state->panel_attached(); - const bool is_resized = - (details_.bounds_change & WindowResizer::kBoundsChange_Resizes) != 0; - - // When drag is completed the dragged docked window is resized to the bounds - // calculated by the layout manager that conform to other docked windows. - if (!is_attached_panel && is_docked_ && !is_resized) { - gfx::Rect bounds = ScreenAsh::ConvertRectFromScreen( - window->parent(), dock_layout_->dragged_bounds()); - if (!bounds.IsEmpty() && bounds.width() != window->bounds().width()) { - window->SetBounds(bounds); - } - } - // If a window has restore bounds, update the restore origin and width but not - // the height (since the height is auto-calculated for the docked windows). - if (is_resized && is_docked_ && window_state->HasRestoreBounds()) { - gfx::Rect restore_bounds = window->GetBoundsInScreen(); - restore_bounds.set_height( - window_state->GetRestoreBoundsInScreen().height()); - window_state->SetRestoreBoundsInScreen(restore_bounds); - } - - // Check if the window needs to be docked or returned to workspace. - DockedAction action = MaybeReparentWindowOnDragCompletion(is_resized, - is_attached_panel); - dock_layout_->FinishDragging( - action, - details_.source == aura::client::WINDOW_MOVE_SOURCE_MOUSE ? - DOCKED_ACTION_SOURCE_MOUSE : DOCKED_ACTION_SOURCE_TOUCH); - - // 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( - DOCKED_ACTION_NONE, - details_.source == aura::client::WINDOW_MOVE_SOURCE_MOUSE ? - DOCKED_ACTION_SOURCE_MOUSE : DOCKED_ACTION_SOURCE_TOUCH); - is_docked_ = false; -} - -DockedAction DockedWindowResizer::MaybeReparentWindowOnDragCompletion( - bool is_resized, bool is_attached_panel) { - aura::Window* window = GetTarget(); - - // Check if the window needs to be docked or returned to workspace. - DockedAction action = DOCKED_ACTION_NONE; - aura::Window* dock_container = Shell::GetContainer( - window->GetRootWindow(), - kShellWindowId_DockedContainer); - if ((is_resized || !is_attached_panel) && - is_docked_ != (window->parent() == dock_container)) { - if (is_docked_) { - wm::ReparentChildWithTransientChildren(window, - window->parent(), - dock_container); - action = DOCKED_ACTION_DOCK; - } else if (window->parent()->id() == kShellWindowId_DockedContainer) { - // Reparent the window back to workspace. - // We need to be careful to give ParentWindowWithContext a location in - // the right root window (matching the logic in DragWindowResizer) based - // on which root window a mouse pointer is in. We want to undock into the - // right screen near the edge of a multiscreen setup (based on where the - // mouse is). - gfx::Rect near_last_location(last_location_, gfx::Size()); - // Reparenting will cause Relayout and possible dock shrinking. - aura::Window* previous_parent = window->parent(); - aura::client::ParentWindowWithContext(window, window, near_last_location); - if (window->parent() != previous_parent) { - wm::ReparentTransientChildrenOfChild(window, - previous_parent, - window->parent()); - } - action = was_docked_ ? DOCKED_ACTION_UNDOCK : DOCKED_ACTION_NONE; - } - } else { - // Docked state was not changed but still need to record a UMA action. - if (is_resized && is_docked_ && was_docked_) - action = DOCKED_ACTION_RESIZE; - else if (is_docked_ && was_docked_) - action = DOCKED_ACTION_REORDER; - else if (is_docked_ && !was_docked_) - action = DOCKED_ACTION_DOCK; - else - action = DOCKED_ACTION_NONE; - } - // When a window is newly docked it is auto-sized by docked layout adjusting - // to other windows. If it is just dragged (but not resized) while being - // docked it is auto-sized unless it has been resized while being docked - // before. - if (is_docked_) { - wm::GetWindowState(window)->set_bounds_changed_by_user( - was_docked_ && (is_resized || was_bounds_changed_by_user_)); - } - return action; -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/dock/docked_window_resizer.h b/chromium/ash/wm/dock/docked_window_resizer.h deleted file mode 100644 index 929259e59ea..00000000000 --- a/chromium/ash/wm/dock/docked_window_resizer.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2013 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_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" -#include "base/memory/weak_ptr.h" - -namespace gfx { -class Point; -class Rect; -} - -namespace aura { -class RootWindow; -} - -namespace ash { -namespace internal { - -class DockedWindowLayoutManager; - -// DockWindowResizer is used by ToplevelWindowEventFilter to handle dragging, -// moving or resizing of a window while it is docked to the side of a screen. -class ASH_EXPORT DockedWindowResizer : public WindowResizer { - public: - virtual ~DockedWindowResizer(); - - // Creates a new DockWindowResizer. The caller takes ownership of the - // returned object. The ownership of |next_window_resizer| is taken by the - // returned object. Returns NULL if not resizable. - static DockedWindowResizer* Create(WindowResizer* next_window_resizer, - aura::Window* window, - const gfx::Point& location, - int window_component, - aura::client::WindowMoveSource source); - - // WindowResizer: - virtual void Drag(const gfx::Point& location, int event_flags) OVERRIDE; - virtual void CompleteDrag(int event_flags) OVERRIDE; - virtual void RevertDrag() OVERRIDE; - virtual aura::Window* GetTarget() OVERRIDE; - virtual const gfx::Point& GetInitialLocation() const OVERRIDE; - - private: - // Creates DockWindowResizer that adds the ability to attach / detach - // windows to / from the dock. This object takes ownership of - // |next_window_resizer|. - DockedWindowResizer(WindowResizer* next_window_resizer, - const Details& details); - - // If the provided window bounds should snap to the side of a screen, - // returns the offset that gives the necessary adjustment to snap. - void MaybeSnapToEdge(const gfx::Rect& bounds, gfx::Point* offset); - - // Tracks the window's initial position and attachment at the start of a drag - // and informs the DockLayoutManager that a drag has started if necessary. - void StartedDragging(); - - // Informs the DockLayoutManager that the drag is complete if it was informed - // of the drag start. - void FinishedDragging(); - - // Reparents dragged window as necessary to the docked container or back to - // workspace at the end of the drag. Calculates and returns action taken that - // can be reported in UMA stats. |is_resized| reports if the window is merely - // being resized rather than repositioned. |attached_panel| is necessary to - // avoid docking panels that have been attached to the launcher shelf at the - // end of the drag. - DockedAction MaybeReparentWindowOnDragCompletion(bool is_resized, - bool is_attached_panel); - - const Details details_; - - gfx::Point last_location_; - - // Wraps a window resizer and adds detaching / reattaching during drags. - scoped_ptr<WindowResizer> next_window_resizer_; - - // 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_; - - // 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_; - - // True if the dragged window had |bounds_changed_by_user| before the drag. - // Cleared whenever the target window gets dragged outside of the docked area. - bool was_bounds_changed_by_user_; - - base::WeakPtrFactory<DockedWindowResizer> weak_ptr_factory_; - - 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 deleted file mode 100644 index 9bfe7217f96..00000000000 --- a/chromium/ash/wm/dock/docked_window_resizer_unittest.cc +++ /dev/null @@ -1,1436 +0,0 @@ -// Copyright (c) 2013 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/dock/docked_window_resizer.h" - -#include "ash/ash_switches.h" -#include "ash/launcher/launcher.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_model.h" -#include "ash/shelf/shelf_types.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/cursor_manager_test_api.h" -#include "ash/test/shell_test_api.h" -#include "ash/test/test_shelf_delegate.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/dock/docked_window_layout_manager.h" -#include "ash/wm/drag_window_resizer.h" -#include "ash/wm/panels/panel_layout_manager.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "base/command_line.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/window_tree_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_types.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -class DockedWindowResizerTest - : public test::AshTestBase, - public testing::WithParamInterface<aura::client::WindowType> { - public: - DockedWindowResizerTest() : model_(NULL), window_type_(GetParam()) {} - virtual ~DockedWindowResizerTest() {} - - virtual void SetUp() OVERRIDE { - CommandLine::ForCurrentProcess()->AppendSwitch( - ash::switches::kAshEnableDockedWindows); - AshTestBase::SetUp(); - UpdateDisplay("600x400"); - test::ShellTestApi test_api(Shell::GetInstance()); - model_ = test_api.shelf_model(); - } - - virtual void TearDown() OVERRIDE { - AshTestBase::TearDown(); - } - - protected: - enum DockedEdge { - DOCKED_EDGE_NONE, - DOCKED_EDGE_LEFT, - DOCKED_EDGE_RIGHT, - }; - - int ideal_width() const { return DockedWindowLayoutManager::kIdealWidth; } - int min_dock_gap() const { return DockedWindowLayoutManager::kMinDockGap; } - int max_width() const { return DockedWindowLayoutManager::kMaxDockWidth; } - int docked_width(const DockedWindowLayoutManager* layout_manager) const { - return layout_manager->docked_width_; - } - int docked_alignment(const DockedWindowLayoutManager* layout_manager) const { - return layout_manager->alignment_; - } - aura::Window* CreateTestWindow(const gfx::Rect& bounds) { - aura::Window* window = CreateTestWindowInShellWithDelegateAndType( - &delegate_, - window_type_, - 0, - bounds); - if (window_type_ == aura::client::WINDOW_TYPE_PANEL) { - test::TestShelfDelegate* shelf_delegate = - test::TestShelfDelegate::instance(); - shelf_delegate->AddLauncherItem(window); - PanelLayoutManager* manager = - static_cast<PanelLayoutManager*>( - Shell::GetContainer(window->GetRootWindow(), - internal::kShellWindowId_PanelContainer)-> - layout_manager()); - manager->Relayout(); - } - return window; - } - - aura::Window* CreateModalWindow(const gfx::Rect& bounds) { - aura::Window* window = new aura::Window(&delegate_); - window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - window->Show(); - - if (bounds.IsEmpty()) { - ParentWindowInPrimaryRootWindow(window); - } else { - gfx::Display display = - Shell::GetScreen()->GetDisplayMatching(bounds); - aura::Window* root = ash::Shell::GetInstance()->display_controller()-> - GetRootWindowForDisplayId(display.id()); - gfx::Point origin = bounds.origin(); - wm::ConvertPointFromScreen(root, &origin); - window->SetBounds(gfx::Rect(origin, bounds.size())); - aura::client::ParentWindowWithContext(window, root, bounds); - } - return window; - } - - static WindowResizer* CreateSomeWindowResizer( - aura::Window* window, - const gfx::Point& point_in_parent, - int window_component) { - return CreateWindowResizer( - window, - point_in_parent, - window_component, - aura::client::WINDOW_MOVE_SOURCE_MOUSE).release(); - } - - void DragStart(aura::Window* window) { - DragStartAtOffsetFromWindowOrigin(window, 0, 0); - } - - void DragStartAtOffsetFromWindowOrigin(aura::Window* window, - int dx, int dy) { - initial_location_in_parent_ = - window->bounds().origin() + gfx::Vector2d(dx, dy); - resizer_.reset(CreateSomeWindowResizer(window, - initial_location_in_parent_, - HTCAPTION)); - ASSERT_TRUE(resizer_.get()); - } - - void ResizeStartAtOffsetFromWindowOrigin(aura::Window* window, - int dx, int dy, - int window_component) { - initial_location_in_parent_ = - window->bounds().origin() + gfx::Vector2d(dx, dy); - resizer_.reset(CreateSomeWindowResizer(window, - initial_location_in_parent_, - window_component)); - ASSERT_TRUE(resizer_.get()); - } - - void DragMove(int dx, int dy) { - resizer_->Drag(initial_location_in_parent_ + gfx::Vector2d(dx, dy), 0); - } - - void DragEnd() { - resizer_->CompleteDrag(0); - resizer_.reset(); - } - - void DragRevert() { - resizer_->RevertDrag(); - resizer_.reset(); - } - - // Panels are parented by panel container during drags. - // All other windows that are tested here are parented by dock container - // during drags. - int CorrectContainerIdDuringDrag() { - if (window_type_ == aura::client::WINDOW_TYPE_PANEL) - return internal::kShellWindowId_PanelContainer; - return internal::kShellWindowId_DockedContainer; - } - - // Test dragging the window vertically (to detach if it is a panel) and then - // horizontally to the edge with an added offset from the edge of |dx|. - void DragRelativeToEdge(DockedEdge edge, - aura::Window* window, - int dx) { - DragVerticallyAndRelativeToEdge( - edge, - window, - dx, window_type_ == aura::client::WINDOW_TYPE_PANEL ? -100 : 20, - 25, 5); - } - - void DragToVerticalPositionAndToEdge(DockedEdge edge, - aura::Window* window, - int y) { - DragToVerticalPositionRelativeToEdge(edge, window, 0, y); - } - - void DragToVerticalPositionRelativeToEdge(DockedEdge edge, - aura::Window* window, - int dx, - int y) { - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - DragVerticallyAndRelativeToEdge(edge, - window, - dx, y - initial_bounds.y(), - 25, 5); - } - - // Detach if our window is a panel, then drag it vertically by |dy| and - // horizontally to the edge with an added offset from the edge of |dx|. - void DragVerticallyAndRelativeToEdge(DockedEdge edge, - aura::Window* window, - int dx, int dy, - int grab_x, int grab_y) { - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - // avoid snap by clicking away from the border - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(window, - grab_x, grab_y)); - - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(window).work_area(); - gfx::Point initial_location_in_screen = initial_location_in_parent_; - wm::ConvertPointToScreen(window->parent(), &initial_location_in_screen); - // Drag the window left or right to the edge (or almost to it). - if (edge == DOCKED_EDGE_LEFT) - dx += work_area.x() - initial_location_in_screen.x(); - else if (edge == DOCKED_EDGE_RIGHT) - dx += work_area.right() - 1 - initial_location_in_screen.x(); - DragMove(dx, dy); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); - // Release the mouse and the panel should be attached to the dock. - DragEnd(); - - // x-coordinate can get adjusted by snapping or sticking. - // y-coordinate could be changed by possible automatic layout if docked. - if (window->parent()->id() != internal::kShellWindowId_DockedContainer && - !wm::GetWindowState(window)->HasRestoreBounds()) { - EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y()); - } - } - - bool test_panels() const { - return window_type_ == aura::client::WINDOW_TYPE_PANEL; - } - - const gfx::Point& initial_location_in_parent() const { - return initial_location_in_parent_; - } - - private: - scoped_ptr<WindowResizer> resizer_; - ShelfModel* model_; - aura::client::WindowType window_type_; - aura::test::TestWindowDelegate delegate_; - - // Location at start of the drag in |window->parent()|'s coordinates. - gfx::Point initial_location_in_parent_; - - DISALLOW_COPY_AND_ASSIGN(DockedWindowResizerTest); -}; - -// Verifies a window can be dragged and attached to the dock. -TEST_P(DockedWindowResizerTest, AttachRightPrecise) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); - - // The window should be docked at the right edge. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); -} - -// Verifies a window can be dragged and attached to the dock -// even if pointer overshoots the screen edge by a few pixels (sticky edge) -TEST_P(DockedWindowResizerTest, AttachRightOvershoot) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), +4); - - // The window should be docked at the right edge. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); -} - -// Verifies a window can be dragged and then if a pointer is not quite reaching -// the screen edge the window does not get docked and stays in the desktop. -TEST_P(DockedWindowResizerTest, AttachRightUndershoot) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - // Grabbing at 70px ensures that at least 30% of the window is in screen, - // otherwise the window would be adjusted in - // WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded. - const int kGrabOffsetX = 70; - const int kUndershootBy = 1; - DragVerticallyAndRelativeToEdge(DOCKED_EDGE_RIGHT, - window.get(), - -kUndershootBy, test_panels() ? -100 : 20, - kGrabOffsetX, 5); - - // The window right should be past the screen edge but not docked. - // Initial touch point is 70px to the right which helps to find where the edge - // should be. - EXPECT_EQ(window->GetRootWindow()->bounds().right() + - window->bounds().width() - kGrabOffsetX - kUndershootBy - 1, - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, - window->parent()->id()); -} - -// Verifies a window can be dragged and attached to the dock. -TEST_P(DockedWindowResizerTest, AttachLeftPrecise) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 0); - - // The window should be docked at the left edge. - EXPECT_EQ(window->GetRootWindow()->bounds().x(), - window->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); -} - -// Verifies a window can be dragged and attached to the dock -// even if pointer overshoots the screen edge by a few pixels (sticky edge) -TEST_P(DockedWindowResizerTest, AttachLeftOvershoot) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), -4); - - // The window should be docked at the left edge. - EXPECT_EQ(window->GetRootWindow()->bounds().x(), - window->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); -} - -// Verifies a window can be dragged and then if a pointer is not quite reaching -// the screen edge the window does not get docked and stays in the desktop. -TEST_P(DockedWindowResizerTest, AttachLeftUndershoot) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - gfx::Rect initial_bounds(window->bounds()); - DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 1); - - // The window should be crossing the screen edge but not docked. - int expected_x = initial_bounds.x() - initial_location_in_parent().x() + 1; - EXPECT_EQ(expected_x, window->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, - window->parent()->id()); -} - -// Dock on the right side, change shelf alignment, check that windows move to -// the opposite side. -TEST_P(DockedWindowResizerTest, AttachRightChangeShelf) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); - - // The window should be docked at the right edge. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - // set launcher shelf to be aligned on the right - ash::Shell* shell = ash::Shell::GetInstance(); - shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT, - shell->GetPrimaryRootWindow()); - // The window should have moved and get attached to the left dock. - EXPECT_EQ(window->GetRootWindow()->bounds().x(), - window->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - // set launcher shelf to be aligned on the left - shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, - shell->GetPrimaryRootWindow()); - // The window should have moved and get attached to the right edge. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - // set launcher shelf to be aligned at the bottom - shell->SetShelfAlignment(SHELF_ALIGNMENT_BOTTOM, - shell->GetPrimaryRootWindow()); - // The window should stay in the right edge. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); -} - -// Dock on the right side, try to undock, then drag more to really undock -TEST_P(DockedWindowResizerTest, AttachTryDetach) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow( - gfx::Rect(0, 0, ideal_width() + 10, 201))); - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); - - // The window should be docked at the right edge. - // Its width should shrink to ideal width. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(ideal_width(), window->GetBoundsInScreen().width()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - // Try to detach by dragging left less than kSnapToDockDistance. - // The window should stay docked. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin( - window.get(), 10, 0)); - DragMove(-4, -10); - // Release the mouse and the window should be still attached to the dock. - DragEnd(); - - // The window should be still attached to the right edge. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - 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. - const int left_edge = window->bounds().x(); - ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); - DragMove(-32, -10); - // Release the mouse and the window should be no longer attached to the dock. - DragEnd(); - - // The window should be floating on the desktop again and moved to the left. - EXPECT_EQ(left_edge - 32, window->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, - window->parent()->id()); -} - -// Minimize a docked window, then restore it and check that it is still docked. -TEST_P(DockedWindowResizerTest, AttachMinimizeRestore) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); - - // The window should be docked at the right edge. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - // Minimize the window, it should be hidden. - window_state->Minimize(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(window->IsVisible()); - EXPECT_TRUE(window_state->IsMinimized()); - // Restore the window; window should be visible. - window_state->Restore(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window->IsVisible()); - EXPECT_TRUE(window_state->IsNormalShowState()); -} - -// Maximize a docked window and check that it is maximized and no longer docked. -TEST_P(DockedWindowResizerTest, AttachMaximize) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); - - // The window should be docked at the right edge. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - // Maximize the window, it should get undocked and maximized in a desktop. - window_state->Maximize(); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(window->IsVisible()); - EXPECT_TRUE(window_state->IsMaximized()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); -} - -// Dock two windows, undock one, check that the other one is still docked. -TEST_P(DockedWindowResizerTest, AttachTwoWindows) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 50); - - // Both windows should be docked at the right edge. - 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()); - - // Detach by dragging left (should get undocked). - const int left_edge = w2->bounds().x(); - ASSERT_NO_FATAL_FAILURE(DragStart(w2.get())); - // Drag up as well to avoid attaching panels to launcher shelf. - DragMove(-32, -100); - // Release the mouse and the window should be no longer attached to the edge. - DragEnd(); - - // The first window should be still docked. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - - // The window should be floating on the desktop again and moved to the left. - EXPECT_EQ(left_edge - 32, w2->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, - w2->parent()->id()); -} - -// Create two windows, dock one and change shelf to auto-hide. -TEST_P(DockedWindowResizerTest, AttachOneAutoHideShelf) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - - // w1 should be docked at the right edge. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - - scoped_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegateAndType( - NULL, aura::client::WINDOW_TYPE_NORMAL, 0, gfx::Rect(20, 20, 150, 20))); - wm::GetWindowState(w2.get())->Maximize(); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); - EXPECT_TRUE(wm::GetWindowState(w2.get())->IsMaximized()); - - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area(); - DockedWindowLayoutManager* manager = - static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); - - // Docked window should be centered vertically in the work area. - EXPECT_EQ(work_area.CenterPoint().y(), w1->bounds().CenterPoint().y()); - // Docked background should extend to the bottom of work area. - EXPECT_EQ(work_area.bottom(), manager->docked_bounds().bottom()); - - // set launcher shelf to be aligned on the right - ash::Shell* shell = ash::Shell::GetInstance(); - shell->SetShelfAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, - shell->GetPrimaryRootWindow()); - work_area = - Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area(); - // Docked window should be centered vertically in the work area. - EXPECT_EQ(work_area.CenterPoint().y(), w1->bounds().CenterPoint().y()); - // Docked background should extend to the bottom of work area. - EXPECT_EQ(work_area.bottom(), manager->docked_bounds().bottom()); -} - -// Dock one window, try to dock another window on the opposite side (should not -// dock). -TEST_P(DockedWindowResizerTest, AttachOnTwoSides) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - gfx::Rect initial_bounds(w2->bounds()); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w2.get(), 50); - - // The first window should be docked at the right edge. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - - // The second window should be near the left edge but not snapped. - // Normal window will get side-maximized while panels will not. - int expected_x = test_panels() ? - (initial_bounds.x() - initial_location_in_parent().x()) : 0; - EXPECT_EQ(expected_x, w2->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); -} - -// Tests that reverting a drag restores docked state if a window was docked. -TEST_P(DockedWindowResizerTest, RevertDragRestoresAttachment) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); - - // The window should be docked at the right edge. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - // Drag the window out but revert the drag - ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); - DragMove(-50, 0); - DragRevert(); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - // Detach window. - ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); - DragMove(-50, 0); - DragEnd(); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, - window->parent()->id()); -} - -// Tests that reverting drag restores undocked state if a window was not docked. -TEST_P(DockedWindowResizerTest, RevertDockedDragRevertsAttachment) { - if (!SupportsHostWindowResize()) - return; - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - int previous_container_id = window->parent()->id(); - // Drag the window out but revert the drag - ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); - DragMove(-50 - window->bounds().x(), 50 - window->bounds().y()); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); - DragRevert(); - EXPECT_EQ(previous_container_id, window->parent()->id()); -} - -// Move a docked window to the second display -TEST_P(DockedWindowResizerTest, DragAcrossDisplays) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("800x800,800x800"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - EXPECT_EQ(2, static_cast<int>(root_windows.size())); - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - - DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); - // The window should be docked at the right edge. - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - - // Try dragging to the right - enough to get it peeking at the other screen - // but not enough to land in the other screen. - // The window should stay on the left screen. - ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); - DragMove(100, 0); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); - DragEnd(); - EXPECT_EQ(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, - window->parent()->id()); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - - // Undock and move to the right - enough to get the mouse pointer past the - // edge of the screen and into the second screen. The window should now be - // in the second screen and not docked. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin( - window.get(), - window->bounds().width()/2 + 10, - 0)); - DragMove(window->bounds().width()/2 - 5, 0); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); - DragEnd(); - EXPECT_NE(window->GetRootWindow()->bounds().right(), - window->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, - window->parent()->id()); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - - // Keep dragging it to the right until its left edge touches the screen edge. - // The window should now be in the second screen and not docked. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin( - window.get(), - window->bounds().width()/2 + 10, - 0)); - DragMove(window->GetRootWindow()->GetBoundsInScreen().x() - - window->GetBoundsInScreen().x(), - 0); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); - DragEnd(); - EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(), - window->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); -} - -// Dock two windows, undock one. -// Test the docked windows area size and default container resizing. -TEST_P(DockedWindowResizerTest, AttachTwoWindowsDetachOne) { - if (!SupportsHostWindowResize()) - return; - UpdateDisplay("600x600"); - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); - // Work area should cover the whole screen. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // A window should be docked at the right edge. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - DockedWindowLayoutManager* manager = - static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100); - // Both windows should now be docked at the right edge. - EXPECT_EQ(w2->GetRootWindow()->bounds().right(), - w2->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - // Dock width should be set to a wider window. - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()), - docked_width(manager)); - - // Try to detach by dragging left a bit (should not get undocked). - // This would normally detach a single docked window but since we have another - // window and the mouse pointer does not leave the dock area the window - // should stay docked. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 60, 0)); - // Drag up as well as left to avoid attaching panels to launcher shelf. - DragMove(-40, -40); - // Release the mouse and the window should be still attached to the edge. - DragEnd(); - - // The first window should be still docked. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - - // The second window should be still docked. - EXPECT_EQ(w2->GetRootWindow()->bounds().right(), - w2->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - - // Detach by dragging left more (should get undocked). - const int left_edge = w2->bounds().x(); - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin( - w2.get(), - w2->bounds().width()/2 + 10, - 0)); - // Drag up as well to avoid attaching panels to launcher shelf. - const int drag_x = -(w2->bounds().width()/2 + 20); - DragMove(drag_x, -100); - // Release the mouse and the window should be no longer attached to the edge. - DragEnd(); - - // The second window should be floating on the desktop again. - EXPECT_EQ(left_edge + drag_x, w2->bounds().x()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); - // Dock width should be set to remaining single docked window. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); -} - -// Dock one of the windows. Maximize other testing desktop resizing. -TEST_P(DockedWindowResizerTest, AttachWindowMaximizeOther) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); - // Work area should cover the whole screen. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // A window should be docked at the right edge. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - DockedWindowLayoutManager* manager = - static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 25, 5)); - DragMove(w2->GetRootWindow()->bounds().right() - -w2->bounds().width() - -(w2->bounds().width()/2 + 20) - -w2->bounds().x(), - 50 - w2->bounds().y()); - DragEnd(); - // The first window should be still docked. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - - // The second window should be floating on the desktop. - EXPECT_EQ(w2->GetRootWindow()->bounds().right() - - (w2->bounds().width()/2 + 20), - w2->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); - // Dock width should be set to remaining single docked window. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - // Desktop work area should now shrink. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - - docked_width(manager) - min_dock_gap(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); - - // Maximize the second window - Maximized area should be shrunk. - const gfx::Rect restored_bounds = w2->bounds(); - wm::WindowState* w2_state = wm::GetWindowState(w2.get()); - w2_state->Maximize(); - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - - docked_width(manager) - min_dock_gap(), - w2->bounds().width()); - - // Detach the first window (this should require very little drag). - ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - DragMove(-35, 10); - // Alignment is set to "NONE" when drag starts. - EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); - // Release the mouse and the window should be no longer attached to the edge. - DragEnd(); - EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); - // 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()); - EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); - EXPECT_EQ(0, docked_width(manager)); - // The second window should now get resized and take up the whole screen. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), - w2->bounds().width()); - - // Dock the first window to the left edge. - // Click at an offset from origin to prevent snapping. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w1.get(), 10, 0)); - // Drag left to get pointer touching the screen edge. - DragMove(-w1->bounds().x() - 10, 0); - // Alignment set to "NONE" during the drag of the window when none are docked. - EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); - // Release the mouse and the window should be now attached to the edge. - DragEnd(); - // Dock should get expanded and desktop should get shrunk. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - // Second window should still be in the desktop. - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); - // Maximized window should be shrunk. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - - docked_width(manager) - min_dock_gap(), - w2->bounds().width()); - - // Unmaximize the second window. - w2_state->Restore(); - // Its bounds should get restored. - EXPECT_EQ(restored_bounds, w2->bounds()); -} - -// Dock one window. Test the sticky behavior near screen or desktop edge. -TEST_P(DockedWindowResizerTest, AttachOneTestSticky) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); - // Work area should cover the whole screen. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w1.get(), 20); - // A window should be docked at the left edge. - EXPECT_EQ(w1->GetRootWindow()->bounds().x(), - w1->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - DockedWindowLayoutManager* manager = - static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); - // The first window should be docked. - EXPECT_EQ(w1->GetRootWindow()->bounds().x(), - w1->GetBoundsInScreen().x()); - // Dock width should be set to that of a single docked window. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - // Position second window in the desktop 20px to the right of the docked w1. - DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, - w2.get(), - 20 + 25 - - min_dock_gap(), - 50); - // The second window should be floating on the desktop. - EXPECT_EQ(w2->GetRootWindow()->bounds().x() + (w1->bounds().right() + 20), - w2->GetBoundsInScreen().x()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); - // Dock width should be set to that of a single docked window. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - // Drag w2 almost to the dock, the mouse pointer not quite reaching the dock. - ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 10, 0)); - DragMove(1 + docked_width(manager) - w2->bounds().x(), 0); - // Alignment set to "LEFT" during the drag because dock has a window in it. - EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); - // Release the mouse and the window should not be attached to the edge. - DragEnd(); - // Dock should still have only one window in it. - EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - // The second window should still be in the desktop. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); - - // 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)); - DragMove(-2, 0); - // Window should not actually move. - EXPECT_EQ(start_x, w2->bounds().x()); - // Alignment set to "LEFT" during the drag because dock has a window in it. - EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); - // Release the mouse and the window should not be attached to the edge. - DragEnd(); - // Window should be still where it was before the last drag started. - EXPECT_EQ(start_x, w2->bounds().x()); - // Dock should still have only one window in it - EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - // The second window should still be in the desktop - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); - - // Drag w2 by more than the stuck threshold and drop it into the dock. - ASSERT_NO_FATAL_FAILURE(DragStart(w2.get())); - DragMove(-100, 0); - // Window should actually move. - EXPECT_NE(start_x, w2->bounds().x()); - // Alignment set to "LEFT" during the drag because dock has a window in it. - EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); - // Release the mouse and the window should be attached to the edge. - DragEnd(); - // Both windows are docked now. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - // Dock should get expanded and desktop should get shrunk. - EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); - EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()), - docked_width(manager)); - // Desktop work area should now shrink by dock width. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - - docked_width(manager) - min_dock_gap(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); -} - -// Dock two windows, resize one. -// Test the docked windows area size and remaining desktop resizing. -TEST_P(DockedWindowResizerTest, ResizeOneOfTwoWindows) { - if (!SupportsHostWindowResize()) - return; - - // Wider display to start since panels are limited to half the display width. - UpdateDisplay("1000x600"); - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); - // Work area should cover the whole screen. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // A window should be docked at the right edge. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - DockedWindowLayoutManager* manager = - static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100); - // Both windows should now be docked at the right edge. - EXPECT_EQ(w2->GetRootWindow()->bounds().right(), - w2->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - // Dock width should be set to a wider window. - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()), - docked_width(manager)); - - // Resize the first window left by a bit and test that the dock expands. - int previous_width = w1->bounds().width(); - const int kResizeSpan1 = 30; - ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), - 0, 20, - HTLEFT)); - DragMove(-kResizeSpan1, 0); - // Alignment set to "RIGHT" during the drag because dock has a window in it. - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - // Release the mouse and the window should be attached to the edge. - DragEnd(); - // Dock should still have both windows in it. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - // w1 is now wider than before. The dock should expand and be as wide as w1. - EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); - // Both windows should get resized since they both don't have min/max size. - EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - // Desktop work area should shrink. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - - docked_width(manager) - min_dock_gap(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); - - // Resize the first window left by more than the dock maximum width. - // This should cause the window width to be restricted by maximum dock width. - previous_width = w1->bounds().width(); - const int kResizeSpan2 = 250; - ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), - 0, 20, - HTLEFT)); - DragMove(-kResizeSpan2, 0); - // Alignment set to "RIGHT" during the drag because dock has a window in it. - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - // Release the mouse and the window should be attached to the edge. - DragEnd(); - // Dock should still have both windows in it. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - // w1 is now as wide as the maximum dock width and the dock should get - // resized to the maximum width. - EXPECT_EQ(max_width(), w1->bounds().width()); - // Both windows should get resized since they both don't have min/max size. - EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - // Desktop work area should shrink. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - - docked_width(manager) - min_dock_gap(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); - - // Resize the first window right to get it completely inside the docked area. - previous_width = w1->bounds().width(); - const int kResizeSpan3 = 100; - ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), - 0, 20, - HTLEFT)); - DragMove(kResizeSpan3, 0); - // Alignment set to "RIGHT" during the drag because dock has a window in it. - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - // Release the mouse and the window should be docked. - DragEnd(); - // Dock should still have both windows in it. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - // w1 should be narrower than before by the length of the drag. - EXPECT_EQ(previous_width - kResizeSpan3, w1->bounds().width()); - // Both windows should get resized since they both don't have min/max size. - EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); - // The dock should be as wide as w1 or w2. - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - // Desktop work area should shrink. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - - docked_width(manager) - min_dock_gap(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); - - // Resize the first window left to be overhang again. - previous_width = w1->bounds().width(); - ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), - 0, 20, - HTLEFT)); - DragMove(-kResizeSpan3, 0); - DragEnd(); - EXPECT_EQ(previous_width + kResizeSpan3, w1->bounds().width()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - // Docked area should be as wide as possible (maximum) and same as w1. - EXPECT_EQ(max_width(), docked_width(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - // Undock the first window. Docked area should shrink to its ideal size. - ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); - // Drag up as well to avoid attaching panels to launcher shelf. - DragMove(-(400 - 210), -100); - // Alignment set to "RIGHT" since we have another window docked. - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - // Release the mouse and the window should be no longer attached to the edge. - DragEnd(); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id()); - // Dock should be as wide as w2 (and same as ideal width). - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(ideal_width(), docked_width(manager)); - EXPECT_EQ(w2->bounds().width(), docked_width(manager)); - // The second window should be still docked. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - // Desktop work area should be inset. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w1.get()).width() - - docked_width(manager) - min_dock_gap(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).width()); -} - -// Dock a window, resize it and test that undocking it preserves the width. -TEST_P(DockedWindowResizerTest, ResizingKeepsWidth) { - if (!SupportsHostWindowResize()) - return; - - // Wider display to start since panels are limited to half the display width. - UpdateDisplay("1000x600"); - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // A window should be docked at the right edge. - EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - DockedWindowLayoutManager* manager = - static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - // Resize the window left by a bit and test that the dock expands. - int previous_width = w1->bounds().width(); - const int kResizeSpan1 = 30; - ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), - 0, 20, - HTLEFT)); - DragMove(-kResizeSpan1, 0); - // Alignment set to "RIGHT" during the drag because the only docked window - // is being dragged. - EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); - // Release the mouse and the window should be attached to the edge. - DragEnd(); - // A window should get docked. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - // w1 is now wider and the dock should expand to be as wide as w1. - EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - // Undock by dragging almost to the left edge. - DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, w1.get(), 100, 20); - // Width should be preserved. - EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); - // Height should be restored to what it was originally. - EXPECT_EQ(201, w1->bounds().height()); - - // Dock again. - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // Width should be reset to initial ideal width (25px). - EXPECT_EQ(ideal_width(), w1->bounds().width()); - - // Undock again by dragging left. - DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, w1.get(), 100, 20); - // Width should be reset to what it was last time the window was not docked. - EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); - // Height should be restored to what it was originally. - EXPECT_EQ(201, w1->bounds().height()); -} - -// Dock two windows, resize one. Test the docked windows area size. -TEST_P(DockedWindowResizerTest, ResizeTwoWindows) { - if (!SupportsHostWindowResize()) - return; - - // Wider display to start since panels are limited to half the display width. - UpdateDisplay("1000x600"); - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100); - // Both windows should now be docked at the right edge. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - // Dock width should be set to ideal width. - DockedWindowLayoutManager* manager = - static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(ideal_width(), docked_width(manager)); - - // Resize the first window left by a bit and test that the dock expands. - int previous_width = w1->bounds().width(); - const int kResizeSpan1 = 30; - ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), - 0, 20, - HTLEFT)); - DragMove(-kResizeSpan1, 0); - DragEnd(); - // w1 is now wider than before. - EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); - // Both windows should get resized since they both don't have min/max size. - EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - // Resize the second window left by a bit more and test that the dock expands. - previous_width = w2->bounds().width(); - ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w2.get(), - 0, 20, - HTLEFT)); - DragMove(-kResizeSpan1, 0); - DragEnd(); - // Only w2 should get wider since w1 was resized by a user. - EXPECT_EQ(previous_width + kResizeSpan1, w2->bounds().width()); - // w1 should stays same size as before since it was resized by a user. - EXPECT_EQ(previous_width, w1->bounds().width()); - EXPECT_EQ(w2->bounds().width(), docked_width(manager)); - - // Undock w2 and then dock it back. - DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), -400, 100); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); - // w2 should become same width as w1. - EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - // Make w1 even wider. - ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), - 0, 20, - HTLEFT)); - DragMove(-kResizeSpan1, 0); - DragEnd(); - // Making w1 wider should make both windows wider since w2 no longer remembers - // user width. - EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); -} - -// Tests that dragging a window down to shelf attaches a panel but does not -// attach a regular window. -TEST_P(DockedWindowResizerTest, DragToShelf) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - // Work area should cover the whole screen. - EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w1.get()).width(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).width()); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // A window should be docked at the right edge. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - DockedWindowLayoutManager* manager = - static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - - // 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, docked_alignment(manager)); - // Release the mouse and the window should be no longer attached to the edge. - DragEnd(); - EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); - - // Drag down almost to shelf. A panel will snap, a regular window won't. - ShelfWidget* shelf = Launcher::ForPrimaryDisplay()->shelf_widget(); - const int shelf_y = shelf->GetWindowBoundsInScreen().y(); - const int kDistanceFromShelf = 10; - ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); - DragMove(0, -kDistanceFromShelf + shelf_y - w1->bounds().bottom()); - DragEnd(); - if (test_panels()) { - // The panel should be touching the shelf and attached. - EXPECT_EQ(shelf_y, w1->bounds().bottom()); - EXPECT_TRUE(wm::GetWindowState(w1.get())->panel_attached()); - } else { - // The window should not be touching the shelf. - EXPECT_EQ(shelf_y - kDistanceFromShelf, w1->bounds().bottom()); - } -} - -// Tests that docking and undocking a |window| with a transient child properly -// maintains the parent of that transient child to be the same as the |window|. -TEST_P(DockedWindowResizerTest, DragWindowWithTransientChild) { - if (!SupportsHostWindowResize()) - return; - - // Create a window with a transient child. - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - scoped_ptr<aura::Window> child(CreateTestWindowInShellWithDelegateAndType( - NULL, aura::client::WINDOW_TYPE_NORMAL, 0, gfx::Rect(20, 20, 150, 20))); - window->AddTransientChild(child.get()); - if (window->parent() != child->parent()) - window->parent()->AddChild(child.get()); - EXPECT_EQ(window.get(), child->transient_parent()); - - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, window.get(), 20); - - // A window should be docked at the right edge. - EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, child->parent()->id()); - - // Drag the child - it should move freely and stay where it is dragged. - ASSERT_NO_FATAL_FAILURE(DragStart(child.get())); - DragMove(500, 20); - DragEnd(); - EXPECT_EQ(gfx::Point(20 + 500, 20 + 20).ToString(), - child->GetBoundsInScreen().origin().ToString()); - - // Undock the window by dragging left. - ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); - DragMove(-32, -10); - DragEnd(); - - // The window should be undocked and the transient child should be reparented. - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, child->parent()->id()); - // The child should not have moved. - EXPECT_EQ(gfx::Point(20 + 500, 20 + 20).ToString(), - child->GetBoundsInScreen().origin().ToString()); -} - -// Tests that reparenting windows during the drag does not affect system modal -// windows that are transient children of the dragged windows. -TEST_P(DockedWindowResizerTest, DragWindowWithModalTransientChild) { - if (!SupportsHostWindowResize()) - return; - - // Create a window. - scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - gfx::Rect bounds(window->bounds()); - - // Start dragging the window. - ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); - gfx::Vector2d move_vector(40, test_panels() ? -60 : 60); - DragMove(move_vector.x(), move_vector.y()); - EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); - - // While still dragging create a modal window and make it a transient child of - // the |window|. - scoped_ptr<aura::Window> child(CreateModalWindow(gfx::Rect(20, 20, 150, 20))); - window->AddTransientChild(child.get()); - EXPECT_EQ(window.get(), child->transient_parent()); - EXPECT_EQ(internal::kShellWindowId_SystemModalContainer, - child->parent()->id()); - - // End the drag, the |window| should have moved (if it is a panel it will - // no longer be attached to the shelf since we dragged it above). - DragEnd(); - bounds.Offset(move_vector); - EXPECT_EQ(bounds.ToString(), window->GetBoundsInScreen().ToString()); - - // The original |window| should be in the default container (not docked or - // attached). - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); - // The transient |child| should still be in system modal container. - EXPECT_EQ(internal::kShellWindowId_SystemModalContainer, - child->parent()->id()); - // The |child| should not have moved. - EXPECT_EQ(gfx::Point(20, 20).ToString(), - child->GetBoundsInScreen().origin().ToString()); - // The |child| should still be a transient child of |window|. - EXPECT_EQ(window.get(), child->transient_parent()); -} - -// Tests that side snapping a window undocks it, closes the dock and then snaps. -TEST_P(DockedWindowResizerTest, SideSnapDocked) { - if (!SupportsHostWindowResize() || test_panels()) - return; - - scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); - wm::WindowState* window_state = wm::GetWindowState(w1.get()); - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // A window should be docked at the right edge. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - DockedWindowLayoutManager* manager = - static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - EXPECT_TRUE(window_state->IsDocked()); - EXPECT_FALSE(window_state->IsSnapped()); - - // Side snap at right edge. - internal::SnapSizer::SnapWindow(window_state, - internal::SnapSizer::RIGHT_EDGE); - // The window should be snapped at the right edge and the dock should close. - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get())); - EXPECT_EQ(0, docked_width(manager)); - EXPECT_EQ(work_area.height(), w1->bounds().height()); - EXPECT_EQ(work_area.right(), w1->bounds().right()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id()); - EXPECT_FALSE(window_state->IsDocked()); - EXPECT_TRUE(window_state->IsSnapped()); - - // Dock again. - DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); - // A window should be docked at the right edge. - EXPECT_EQ(w1->GetRootWindow()->bounds().right(), - w1->GetBoundsInScreen().right()); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); - EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); - EXPECT_EQ(w1->bounds().width(), docked_width(manager)); - EXPECT_TRUE(window_state->IsDocked()); - EXPECT_FALSE(window_state->IsSnapped()); - - // Side snap at left edge. - internal::SnapSizer::SnapWindow(window_state, - internal::SnapSizer::LEFT_EDGE); - // The window should be snapped at the right edge and the dock should close. - EXPECT_EQ(work_area.ToString(), - ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).ToString()); - EXPECT_EQ(0, docked_width(manager)); - EXPECT_EQ(work_area.height(), w1->bounds().height()); - EXPECT_EQ(work_area.x(), w1->bounds().x()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id()); - EXPECT_FALSE(window_state->IsDocked()); - EXPECT_TRUE(window_state->IsSnapped()); -} - -// Tests run twice - on both panels and normal windows -INSTANTIATE_TEST_CASE_P(NormalOrPanel, - DockedWindowResizerTest, - testing::Values(aura::client::WINDOW_TYPE_NORMAL, - aura::client::WINDOW_TYPE_PANEL)); -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/drag_window_controller.cc b/chromium/ash/wm/drag_window_controller.cc deleted file mode 100644 index 937af3b0abf..00000000000 --- a/chromium/ash/wm/drag_window_controller.cc +++ /dev/null @@ -1,126 +0,0 @@ -// 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/drag_window_controller.h" - -#include "ash/shell_window_ids.h" -#include "ash/wm/window_util.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/views/corewm/shadow_types.h" -#include "ui/views/corewm/window_util.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -DragWindowController::DragWindowController(aura::Window* window) - : window_(window), - drag_widget_(NULL), - layer_(NULL) { -} - -DragWindowController::~DragWindowController() { - Hide(); -} - -void DragWindowController::SetDestinationDisplay( - const gfx::Display& dst_display) { - dst_display_ = dst_display; -} - -void DragWindowController::Show() { - if (!drag_widget_) - CreateDragWidget(window_->GetBoundsInScreen()); - drag_widget_->Show(); -} - -void DragWindowController::SetBounds(const gfx::Rect& bounds) { - DCHECK(drag_widget_); - bounds_ = bounds; - SetBoundsInternal(bounds); -} - -void DragWindowController::Hide() { - if (drag_widget_) { - drag_widget_->Close(); - drag_widget_ = NULL; - } - if (layer_) { - views::corewm::DeepDeleteLayers(layer_); - layer_ = NULL; - } -} - -void DragWindowController::SetOpacity(float opacity) { - DCHECK(drag_widget_); - ui::Layer* layer = drag_widget_->GetNativeWindow()->layer(); - ui::ScopedLayerAnimationSettings scoped_setter(layer->GetAnimator()); - layer->SetOpacity(opacity); -} - -void DragWindowController::CreateDragWidget(const gfx::Rect& bounds) { - DCHECK(!drag_widget_); - drag_widget_ = new views::Widget; - views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.parent = window_->parent(); - params.can_activate = false; - params.keep_on_top = true; - drag_widget_->set_focus_on_creation(false); - drag_widget_->Init(params); - drag_widget_->SetVisibilityChangedAnimationsEnabled(false); - drag_widget_->GetNativeWindow()->SetName("DragWindow"); - drag_widget_->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow); - // Show shadow for the dragging window. - SetShadowType(drag_widget_->GetNativeWindow(), - views::corewm::SHADOW_TYPE_RECTANGULAR); - SetBoundsInternal(bounds); - drag_widget_->StackAbove(window_); - - RecreateWindowLayers(); - aura::Window* window = drag_widget_->GetNativeWindow(); - layer_->SetVisible(true); - window->layer()->Add(layer_); - window->layer()->StackAtTop(layer_); - - // Show the widget after all the setups. - drag_widget_->Show(); - - // Fade the window in. - ui::Layer* widget_layer = drag_widget_->GetNativeWindow()->layer(); - widget_layer->SetOpacity(0); - ui::ScopedLayerAnimationSettings scoped_setter(widget_layer->GetAnimator()); - widget_layer->SetOpacity(1); -} - -void DragWindowController::SetBoundsInternal(const gfx::Rect& bounds) { - aura::Window* window = drag_widget_->GetNativeWindow(); - aura::client::ScreenPositionClient* screen_position_client = - aura::client::GetScreenPositionClient(window->GetRootWindow()); - if (screen_position_client && dst_display_.is_valid()) - screen_position_client->SetBounds(window, bounds, dst_display_); - else - drag_widget_->SetBounds(bounds); -} - -void DragWindowController::RecreateWindowLayers() { - DCHECK(!layer_); - layer_ = views::corewm::RecreateWindowLayers(window_, true); - layer_->set_delegate(window_->layer()->delegate()); - // Place the layer at (0, 0) of the DragWindowController's window. - gfx::Rect layer_bounds = layer_->bounds(); - layer_bounds.set_origin(gfx::Point(0, 0)); - layer_->SetBounds(layer_bounds); - layer_->SetVisible(false); - // Detach it from the current container. - layer_->parent()->Remove(layer_); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/drag_window_controller.h b/chromium/ash/wm/drag_window_controller.h deleted file mode 100644 index 08e115de217..00000000000 --- a/chromium/ash/wm/drag_window_controller.h +++ /dev/null @@ -1,97 +0,0 @@ -// 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_DRAG_WINDOW_CONTROLLER_H_ -#define ASH_WM_DRAG_WINDOW_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "ui/gfx/display.h" -#include "ui/gfx/rect.h" - -namespace aura { -class Window; -} - -namespace ui { -class Layer; -} - -namespace views { -class Widget; -} - -namespace ash { -namespace internal { - -// DragWindowController is responsible for showing a semi-transparent window -// while dragging a window across displays. -class ASH_EXPORT DragWindowController { - public: - explicit DragWindowController(aura::Window* window); - virtual ~DragWindowController(); - - // Sets the display where the window is placed after the window is dropped. - void SetDestinationDisplay(const gfx::Display& dst_display); - - // Shows the drag window at the specified location (coordinates of the - // parent). If |layer| is non-NULL, it is shown on top of the drag window. - // |layer| is owned by the caller. - // This does not immediately show the window. - void Show(); - - // Hides the drag window. - void Hide(); - - // This is used to set bounds for the drag window immediately. This should - // be called only when the drag window is already visible. - void SetBounds(const gfx::Rect& bounds); - - // Sets the opacity of the drag window. - void SetOpacity(float opacity); - - private: - FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest, DragWindowController); - - // Creates and shows the |drag_widget_| at |bounds|. - // |layer| is shown on top of the drag window if it is non-NULL. - // |layer| is not owned by this object. - void CreateDragWidget(const gfx::Rect& bounds); - - // Sets bounds of the drag window. The window is shown on |dst_display_| - // if its id() is valid. Otherwise, a display nearest to |bounds| is chosen. - void SetBoundsInternal(const gfx::Rect& bounds); - - // Recreates a fresh layer for |window_| and all its child windows. - void RecreateWindowLayers(); - - // Window the drag window is placed beneath. - aura::Window* window_; - - // The display where the drag is placed. When dst_display_.id() is - // kInvalidDisplayID (i.e. the default), a display nearest to the current - // |bounds_| is automatically used. - gfx::Display dst_display_; - - // Initially the bounds of |window_|. Each time Show() is invoked - // |start_bounds_| is then reset to the bounds of |drag_widget_| and - // |bounds_| is set to the value passed into Show(). The animation animates - // between these two values. - gfx::Rect bounds_; - - views::Widget* drag_widget_; - - // The copy of window_->layer() and its children. This object is the owner of - // the layer. - ui::Layer* layer_; - - DISALLOW_COPY_AND_ASSIGN(DragWindowController); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_DRAG_WINDOW_CONTROLLER_H_ diff --git a/chromium/ash/wm/drag_window_resizer.cc b/chromium/ash/wm/drag_window_resizer.cc deleted file mode 100644 index 000d1198419..00000000000 --- a/chromium/ash/wm/drag_window_resizer.cc +++ /dev/null @@ -1,277 +0,0 @@ -// 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/drag_window_resizer.h" - -#include "ash/display/mouse_cursor_event_filter.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/system/tray/system_tray.h" -#include "ash/system/user/tray_user.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/drag_window_controller.h" -#include "ash/wm/window_state.h" -#include "base/memory/weak_ptr.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_types.h" -#include "ui/gfx/screen.h" - -namespace ash { -namespace internal { - -namespace { - -// The maximum opacity of the drag phantom window. -const float kMaxOpacity = 0.8f; - -// The opacity of the window when dragging it over a user item in the tray. -const float kOpacityWhenDraggedOverUserIcon = 0.4f; - -// Returns true if Ash has more than one root window. -bool HasSecondaryRootWindow() { - return Shell::GetAllRootWindows().size() > 1; -} - -// When there are two root windows, returns one of the root windows which is not -// |root_window|. Returns NULL if only one root window exists. -aura::Window* GetAnotherRootWindow(aura::Window* root_window) { - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - if (root_windows.size() < 2) - return NULL; - DCHECK_EQ(2U, root_windows.size()); - if (root_windows[0] == root_window) - return root_windows[1]; - return root_windows[0]; -} - -} // namespace - -// static -DragWindowResizer* DragWindowResizer::instance_ = NULL; - -DragWindowResizer::~DragWindowResizer() { - if (GetTarget()) - wm::GetWindowState(GetTarget())->set_window_resizer_(NULL); - Shell* shell = Shell::GetInstance(); - shell->mouse_cursor_filter()->set_mouse_warp_mode( - MouseCursorEventFilter::WARP_ALWAYS); - shell->mouse_cursor_filter()->HideSharedEdgeIndicator(); - if (instance_ == this) - instance_ = NULL; -} - -// static -DragWindowResizer* DragWindowResizer::Create( - WindowResizer* next_window_resizer, - aura::Window* window, - const gfx::Point& location, - int window_component, - aura::client::WindowMoveSource source) { - Details details(window, location, window_component, source); - return details.is_resizable ? - new DragWindowResizer(next_window_resizer, details) : NULL; -} - -void DragWindowResizer::Drag(const gfx::Point& location, int event_flags) { - base::WeakPtr<DragWindowResizer> resizer(weak_ptr_factory_.GetWeakPtr()); - - // If we are on top of a window to desktop transfer button, we move the window - // temporarily back to where it was initially and make it semi-transparent. - GetTarget()->layer()->SetOpacity( - GetTrayUserItemAtPoint(location) ? kOpacityWhenDraggedOverUserIcon : - details_.initial_opacity); - - next_window_resizer_->Drag(location, event_flags); - - if (!resizer) - return; - - last_mouse_location_ = location; - // Show a phantom window for dragging in another root window. - if (HasSecondaryRootWindow()) { - gfx::Point location_in_screen = location; - wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen); - const bool in_original_root = - wm::GetRootWindowAt(location_in_screen) == GetTarget()->GetRootWindow(); - UpdateDragWindow(GetTarget()->bounds(), in_original_root); - } else { - drag_window_controller_.reset(); - } -} - -void DragWindowResizer::CompleteDrag(int event_flags) { - if (TryDraggingToNewUser()) - return; - - next_window_resizer_->CompleteDrag(event_flags); - - GetTarget()->layer()->SetOpacity(details_.initial_opacity); - drag_window_controller_.reset(); - - // Check if the destination is another display. - gfx::Point last_mouse_location_in_screen = last_mouse_location_; - wm::ConvertPointToScreen(GetTarget()->parent(), - &last_mouse_location_in_screen); - gfx::Screen* screen = Shell::GetScreen(); - const gfx::Display dst_display = - screen->GetDisplayNearestPoint(last_mouse_location_in_screen); - - if (dst_display.id() != - screen->GetDisplayNearestWindow(GetTarget()->GetRootWindow()).id()) { - const gfx::Rect dst_bounds = - ScreenAsh::ConvertRectToScreen(GetTarget()->parent(), - GetTarget()->bounds()); - GetTarget()->SetBoundsInScreen(dst_bounds, dst_display); - } -} - -void DragWindowResizer::RevertDrag() { - next_window_resizer_->RevertDrag(); - - drag_window_controller_.reset(); - GetTarget()->layer()->SetOpacity(details_.initial_opacity); -} - -aura::Window* DragWindowResizer::GetTarget() { - return next_window_resizer_->GetTarget(); -} - -const gfx::Point& DragWindowResizer::GetInitialLocation() const { - return details_.initial_location_in_parent; -} - -DragWindowResizer::DragWindowResizer(WindowResizer* next_window_resizer, - const Details& details) - : next_window_resizer_(next_window_resizer), - details_(details), - weak_ptr_factory_(this) { - // The pointer should be confined in one display during resizing a window - // because the window cannot span two displays at the same time anyway. The - // exception is window/tab dragging operation. During that operation, - // |mouse_warp_mode_| should be set to WARP_DRAG so that the user could move a - // window/tab to another display. - MouseCursorEventFilter* mouse_cursor_filter = - Shell::GetInstance()->mouse_cursor_filter(); - mouse_cursor_filter->set_mouse_warp_mode( - ShouldAllowMouseWarp() ? - MouseCursorEventFilter::WARP_DRAG : MouseCursorEventFilter::WARP_NONE); - if (ShouldAllowMouseWarp()) { - mouse_cursor_filter->ShowSharedEdgeIndicator( - details.window->GetRootWindow()); - } - instance_ = this; -} - -void DragWindowResizer::UpdateDragWindow(const gfx::Rect& bounds, - bool in_original_root) { - if (details_.window_component != HTCAPTION || !ShouldAllowMouseWarp()) - return; - - // It's available. Show a phantom window on the display if needed. - aura::Window* another_root = - GetAnotherRootWindow(GetTarget()->GetRootWindow()); - const gfx::Rect root_bounds_in_screen(another_root->GetBoundsInScreen()); - const gfx::Rect bounds_in_screen = - ScreenAsh::ConvertRectToScreen(GetTarget()->parent(), bounds); - gfx::Rect bounds_in_another_root = - gfx::IntersectRects(root_bounds_in_screen, bounds_in_screen); - const float fraction_in_another_window = - (bounds_in_another_root.width() * bounds_in_another_root.height()) / - static_cast<float>(bounds.width() * bounds.height()); - - if (fraction_in_another_window > 0) { - if (!drag_window_controller_) { - drag_window_controller_.reset( - new DragWindowController(GetTarget())); - // Always show the drag phantom on the |another_root| window. - drag_window_controller_->SetDestinationDisplay( - Shell::GetScreen()->GetDisplayNearestWindow(another_root)); - drag_window_controller_->Show(); - } else { - // No animation. - drag_window_controller_->SetBounds(bounds_in_screen); - } - const float phantom_opacity = - !in_original_root ? 1 : (kMaxOpacity * fraction_in_another_window); - const float window_opacity = - in_original_root ? 1 : (kMaxOpacity * (1 - fraction_in_another_window)); - drag_window_controller_->SetOpacity(phantom_opacity); - GetTarget()->layer()->SetOpacity(window_opacity); - } else { - drag_window_controller_.reset(); - GetTarget()->layer()->SetOpacity(1.0f); - } -} - -bool DragWindowResizer::ShouldAllowMouseWarp() { - return (details_.window_component == HTCAPTION) && - !GetTarget()->transient_parent() && - (GetTarget()->type() == aura::client::WINDOW_TYPE_NORMAL || - GetTarget()->type() == aura::client::WINDOW_TYPE_PANEL); -} - -TrayUser* DragWindowResizer::GetTrayUserItemAtPoint( - const gfx::Point& point_in_screen) { - // Unit tests might not have an ash shell. - if (!ash::Shell::GetInstance()) - return NULL; - - // Check that this is a drag move operation from a suitable window. - if (details_.window_component != HTCAPTION || - GetTarget()->transient_parent() || - (GetTarget()->type() != aura::client::WINDOW_TYPE_NORMAL && - GetTarget()->type() != aura::client::WINDOW_TYPE_PANEL && - GetTarget()->type() != aura::client::WINDOW_TYPE_POPUP)) - return NULL; - - // We only allow to drag the window onto a tray of it's own RootWindow. - SystemTray* tray = internal::GetRootWindowController( - details_.window->GetRootWindow())->GetSystemTray(); - - // Again - unit tests might not have a tray. - if (!tray) - return NULL; - - const std::vector<internal::TrayUser*> tray_users = tray->GetTrayUserItems(); - if (tray_users.size() <= 1) - return NULL; - - std::vector<internal::TrayUser*>::const_iterator it = tray_users.begin(); - for (; it != tray_users.end(); ++it) { - if ((*it)->CanDropWindowHereToTransferToUser(point_in_screen)) - return *it; - } - return NULL; -} - -bool DragWindowResizer::TryDraggingToNewUser() { - TrayUser* tray_user = GetTrayUserItemAtPoint(last_mouse_location_); - // No need to try dragging if there is no user. - if (!tray_user) - return false; - - // We have to avoid a brief flash caused by the RevertDrag operation. - // To do this, we first set the opacity of our target window to 0, so that no - // matter what the RevertDrag does the window will stay hidden. Then transfer - // the window to the new owner (which will hide it). RevertDrag will then do - // it's thing and return the transparency to its original value. - int old_opacity = GetTarget()->layer()->opacity(); - GetTarget()->layer()->SetOpacity(0); - GetTarget()->SetBounds(details_.initial_bounds_in_parent); - if (!tray_user->TransferWindowToUser(details_.window)) { - GetTarget()->layer()->SetOpacity(old_opacity); - return false; - } - RevertDrag(); - return true; -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/drag_window_resizer.h b/chromium/ash/wm/drag_window_resizer.h deleted file mode 100644 index f88e0779f27..00000000000 --- a/chromium/ash/wm/drag_window_resizer.h +++ /dev/null @@ -1,86 +0,0 @@ -// 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_DRAG_WINDOW_RESIZER_H_ -#define ASH_WM_DRAG_WINDOW_RESIZER_H_ - -#include "ash/wm/window_resizer.h" -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "base/memory/weak_ptr.h" -#include "ui/gfx/point.h" - -namespace ash { -namespace internal { - -class DragWindowController; -class TrayUser; - -// DragWindowResizer is a decorator of WindowResizer and adds the ability to -// drag windows across displays. -class ASH_EXPORT DragWindowResizer : public WindowResizer { - public: - virtual ~DragWindowResizer(); - - // Creates a new DragWindowResizer. The caller takes ownership of the - // returned object. The ownership of |next_window_resizer| is taken by the - // returned object. Returns NULL if not resizable. - static DragWindowResizer* Create(WindowResizer* next_window_resizer, - aura::Window* window, - const gfx::Point& location, - int window_component, - aura::client::WindowMoveSource source); - - // WindowResizer: - virtual void Drag(const gfx::Point& location, int event_flags) OVERRIDE; - virtual void CompleteDrag(int event_flags) OVERRIDE; - virtual void RevertDrag() OVERRIDE; - virtual aura::Window* GetTarget() OVERRIDE; - virtual const gfx::Point& GetInitialLocation() const OVERRIDE; - - private: - FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest, DragWindowController); - - // Creates DragWindowResizer that adds the ability of dragging windows across - // displays to |next_window_resizer|. This object takes the ownership of - // |next_window_resizer|. - explicit DragWindowResizer(WindowResizer* next_window_resizer, - const Details& details); - - // Updates the bounds of the phantom window for window dragging. Set true on - // |in_original_root| if the pointer is still in |window()->GetRootWindow()|. - void UpdateDragWindow(const gfx::Rect& bounds, bool in_original_root); - - // Returns true if we should allow the mouse pointer to warp. - bool ShouldAllowMouseWarp(); - - // Get the user drop target underneath the given |point_in_screen| or NULL. - TrayUser* GetTrayUserItemAtPoint(const gfx::Point& point_in_screen); - - // Check if a completed drag might cause the window to change active desktops. - // If the call was causing a "transfer of ownership to another desktop" and it - // will return false indicating that no further processing is needed. - bool TryDraggingToNewUser(); - - scoped_ptr<WindowResizer> next_window_resizer_; - - // Shows a semi-transparent image of the window being dragged. - scoped_ptr<DragWindowController> drag_window_controller_; - - const Details details_; - - gfx::Point last_mouse_location_; - - // Current instance for use by the DragWindowResizerTest. - static DragWindowResizer* instance_; - - base::WeakPtrFactory<DragWindowResizer> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(DragWindowResizer); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_DRAG_WINDOW_RESIZER_H_ diff --git a/chromium/ash/wm/drag_window_resizer_unittest.cc b/chromium/ash/wm/drag_window_resizer_unittest.cc deleted file mode 100644 index 04e00f2f87e..00000000000 --- a/chromium/ash/wm/drag_window_resizer_unittest.cc +++ /dev/null @@ -1,674 +0,0 @@ -// 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/drag_window_resizer.h" - -#include "ash/display/mouse_cursor_event_filter.h" -#include "ash/root_window_controller.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/cursor_manager_test_api.h" -#include "ash/wm/drag_window_controller.h" -#include "ash/wm/window_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_types.h" -#include "ui/gfx/insets.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" - -#if defined(OS_CHROMEOS) -#include "ash/system/tray/system_tray.h" -#include "ash/system/user/tray_user.h" -#include "ash/test/test_session_state_delegate.h" -#include "ash/test/test_shell_delegate.h" -#endif - -namespace ash { -namespace internal { -namespace { - -const int kRootHeight = 600; - -} // namespace - -class DragWindowResizerTest : public test::AshTestBase { - public: - DragWindowResizerTest() {} - virtual ~DragWindowResizerTest() {} - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - UpdateDisplay(base::StringPrintf("800x%d", kRootHeight)); - - aura::Window* root = Shell::GetPrimaryRootWindow(); - gfx::Rect root_bounds(root->bounds()); - EXPECT_EQ(kRootHeight, root_bounds.height()); - EXPECT_EQ(800, root_bounds.width()); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - window_.reset(new aura::Window(&delegate_)); - window_->SetType(aura::client::WINDOW_TYPE_NORMAL); - window_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(window_.get()); - window_->set_id(1); - - always_on_top_window_.reset(new aura::Window(&delegate2_)); - always_on_top_window_->SetType(aura::client::WINDOW_TYPE_NORMAL); - always_on_top_window_->SetProperty(aura::client::kAlwaysOnTopKey, true); - always_on_top_window_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(always_on_top_window_.get()); - always_on_top_window_->set_id(2); - - system_modal_window_.reset(new aura::Window(&delegate3_)); - system_modal_window_->SetType(aura::client::WINDOW_TYPE_NORMAL); - system_modal_window_->SetProperty(aura::client::kModalKey, - ui::MODAL_TYPE_SYSTEM); - system_modal_window_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(system_modal_window_.get()); - system_modal_window_->set_id(3); - - transient_child_ = new aura::Window(&delegate4_); - transient_child_->SetType(aura::client::WINDOW_TYPE_NORMAL); - transient_child_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(transient_child_); - transient_child_->set_id(4); - - transient_parent_.reset(new aura::Window(&delegate5_)); - transient_parent_->SetType(aura::client::WINDOW_TYPE_NORMAL); - transient_parent_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(transient_parent_.get()); - transient_parent_->AddTransientChild(transient_child_); - transient_parent_->set_id(5); - - panel_window_.reset(new aura::Window(&delegate6_)); - panel_window_->SetType(aura::client::WINDOW_TYPE_PANEL); - panel_window_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(panel_window_.get()); - } - - virtual void TearDown() OVERRIDE { - window_.reset(); - always_on_top_window_.reset(); - system_modal_window_.reset(); - transient_parent_.reset(); - panel_window_.reset(); - AshTestBase::TearDown(); - } - - protected: - gfx::Point CalculateDragPoint(const WindowResizer& resizer, - int delta_x, - int delta_y) const { - gfx::Point location = resizer.GetInitialLocation(); - location.set_x(location.x() + delta_x); - location.set_y(location.y() + delta_y); - return location; - } - - internal::ShelfLayoutManager* shelf_layout_manager() { - return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); - } - - static WindowResizer* CreateDragWindowResizer( - aura::Window* window, - const gfx::Point& point_in_parent, - int window_component) { - return CreateWindowResizer( - window, - point_in_parent, - window_component, - aura::client::WINDOW_MOVE_SOURCE_MOUSE).release(); - } - - bool WarpMouseCursorIfNecessary(aura::Window* target_root, - const gfx::Point& point_in_screen) { - MouseCursorEventFilter* event_filter = - Shell::GetInstance()->mouse_cursor_filter(); - bool is_warped = event_filter->WarpMouseCursorIfNecessary(target_root, - point_in_screen); - event_filter->reset_was_mouse_warped_for_test(); - return is_warped; - } - - aura::test::TestWindowDelegate delegate_; - aura::test::TestWindowDelegate delegate2_; - aura::test::TestWindowDelegate delegate3_; - aura::test::TestWindowDelegate delegate4_; - aura::test::TestWindowDelegate delegate5_; - aura::test::TestWindowDelegate delegate6_; - - scoped_ptr<aura::Window> window_; - scoped_ptr<aura::Window> always_on_top_window_; - scoped_ptr<aura::Window> system_modal_window_; - scoped_ptr<aura::Window> panel_window_; - aura::Window* transient_child_; - scoped_ptr<aura::Window> transient_parent_; - - private: - DISALLOW_COPY_AND_ASSIGN(DragWindowResizerTest); -}; - -// Verifies a window can be moved from the primary display to another. -TEST_F(DragWindowResizerTest, WindowDragWithMultiDisplays) { - if (!SupportsMultipleDisplays()) - return; - - // The secondary display is logically on the right, but on the system (e.g. X) - // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc. - UpdateDisplay("800x600,800x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - ASSERT_EQ(2U, root_windows.size()); - - window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - { - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Drag the pointer to the right. Once it reaches the right edge of the - // primary display, it warps to the secondary. - resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0); - resizer->CompleteDrag(0); - // The whole window is on the secondary display now. The parent should be - // changed. - EXPECT_EQ(root_windows[1], window_->GetRootWindow()); - EXPECT_EQ("0,10 50x60", window_->bounds().ToString()); - } - - window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - { - // Grab (0, 0) of the window and move the pointer to (790, 10). - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 795, 10), 0); - // Window should be adjusted for minimum visibility (10px) during the drag. - EXPECT_EQ("790,10 50x60", window_->bounds().ToString()); - resizer->CompleteDrag(0); - // Since the pointer is still on the primary root window, the parent should - // not be changed. - // Window origin should be adjusted for minimum visibility (10px). - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - EXPECT_EQ("790,10 50x60", window_->bounds().ToString()); - } - - window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - { - // Grab the top-right edge of the window and move the pointer to (0, 10) - // in the secondary root window's coordinates. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(49, 0), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 751, 10), ui::EF_CONTROL_DOWN); - resizer->CompleteDrag(0); - // Since the pointer is on the secondary, the parent should be changed - // even though only small fraction of the window is within the secondary - // root window's bounds. - EXPECT_EQ(root_windows[1], window_->GetRootWindow()); - // Window origin should be adjusted for minimum visibility (10px). - int expected_x = -50 + 10; - EXPECT_EQ(base::IntToString(expected_x) + ",10 50x60", - window_->bounds().ToString()); - } -} - -// Verifies that dragging the active window to another display makes the new -// root window the active root window. -TEST_F(DragWindowResizerTest, WindowDragWithMultiDisplaysActiveRoot) { - if (!SupportsMultipleDisplays()) - return; - - // The secondary display is logically on the right, but on the system (e.g. X) - // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc. - UpdateDisplay("800x600,800x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - ASSERT_EQ(2U, root_windows.size()); - - aura::test::TestWindowDelegate delegate; - scoped_ptr<aura::Window> window(new aura::Window(&delegate)); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - ParentWindowInPrimaryRootWindow(window.get()); - window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - window->Show(); - EXPECT_TRUE(ash::wm::CanActivateWindow(window.get())); - ash::wm::ActivateWindow(window.get()); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - EXPECT_EQ(root_windows[0], ash::Shell::GetTargetRootWindow()); - { - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Drag the pointer to the right. Once it reaches the right edge of the - // primary display, it warps to the secondary. - resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0); - resizer->CompleteDrag(0); - // The whole window is on the secondary display now. The parent should be - // changed. - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ(root_windows[1], ash::Shell::GetTargetRootWindow()); - } -} - -// Verifies a window can be moved from the secondary display to primary. -TEST_F(DragWindowResizerTest, WindowDragWithMultiDisplaysRightToLeft) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("800x600,800x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - ASSERT_EQ(2U, root_windows.size()); - - window_->SetBoundsInScreen( - gfx::Rect(800, 00, 50, 60), - Shell::GetScreen()->GetDisplayNearestWindow(root_windows[1])); - EXPECT_EQ(root_windows[1], window_->GetRootWindow()); - { - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move the mouse near the right edge, (798, 0), of the primary display. - resizer->Drag(CalculateDragPoint(*resizer, -2, 0), ui::EF_CONTROL_DOWN); - resizer->CompleteDrag(0); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - // Window origin should be adjusted for minimum visibility (10px). - int expected_x = 800 - 10; - EXPECT_EQ(base::IntToString(expected_x) + ",0 50x60", - window_->bounds().ToString()); - } -} - -// Verifies the drag window is shown correctly. -TEST_F(DragWindowResizerTest, DragWindowController) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("800x600,800x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - ASSERT_EQ(2U, root_windows.size()); - - window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); - { - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - internal::DragWindowResizer* drag_resizer = DragWindowResizer::instance_; - ASSERT_TRUE(drag_resizer); - EXPECT_FALSE(drag_resizer->drag_window_controller_.get()); - - // The pointer is inside the primary root. The drag window controller - // should be NULL. - resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0); - EXPECT_FALSE(drag_resizer->drag_window_controller_.get()); - - // The window spans both root windows. - resizer->Drag(CalculateDragPoint(*resizer, 798, 10), 0); - DragWindowController* controller = - drag_resizer->drag_window_controller_.get(); - ASSERT_TRUE(controller); - - ASSERT_TRUE(controller->drag_widget_); - ui::Layer* drag_layer = - controller->drag_widget_->GetNativeWindow()->layer(); - ASSERT_TRUE(drag_layer); - // Check if |resizer->layer_| is properly set to the drag widget. - const std::vector<ui::Layer*>& layers = drag_layer->children(); - EXPECT_FALSE(layers.empty()); - EXPECT_EQ(controller->layer_, layers.back()); - - // |window_| should be opaque since the pointer is still on the primary - // root window. The drag window should be semi-transparent. - EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); - ASSERT_TRUE(controller->drag_widget_); - EXPECT_GT(1.0f, drag_layer->opacity()); - - // Enter the pointer to the secondary display. - resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0); - controller = drag_resizer->drag_window_controller_.get(); - ASSERT_TRUE(controller); - // |window_| should be transparent, and the drag window should be opaque. - EXPECT_GT(1.0f, window_->layer()->opacity()); - EXPECT_FLOAT_EQ(1.0f, drag_layer->opacity()); - - resizer->CompleteDrag(0); - EXPECT_EQ(root_windows[1], window_->GetRootWindow()); - EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); - } - - // Do the same test with RevertDrag(). - window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); - { - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - internal::DragWindowResizer* drag_resizer = DragWindowResizer::instance_; - ASSERT_TRUE(drag_resizer); - EXPECT_FALSE(drag_resizer->drag_window_controller_.get()); - - resizer->Drag(CalculateDragPoint(*resizer, 0, 610), 0); - resizer->RevertDrag(); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); - } -} - -// Verifies if the resizer sets and resets -// MouseCursorEventFilter::mouse_warp_mode_ as expected. -TEST_F(DragWindowResizerTest, WarpMousePointer) { - MouseCursorEventFilter* event_filter = - Shell::GetInstance()->mouse_cursor_filter(); - ASSERT_TRUE(event_filter); - window_->SetBounds(gfx::Rect(0, 0, 50, 60)); - - EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS, - event_filter->mouse_warp_mode_); - { - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTCAPTION)); - // While dragging a window, warp should be allowed. - EXPECT_EQ(MouseCursorEventFilter::WARP_DRAG, - event_filter->mouse_warp_mode_); - resizer->CompleteDrag(0); - } - EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS, - event_filter->mouse_warp_mode_); - - { - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTCAPTION)); - EXPECT_EQ(MouseCursorEventFilter::WARP_DRAG, - event_filter->mouse_warp_mode_); - resizer->RevertDrag(); - } - EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS, - event_filter->mouse_warp_mode_); - - { - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTRIGHT)); - // While resizing a window, warp should NOT be allowed. - EXPECT_EQ(MouseCursorEventFilter::WARP_NONE, - event_filter->mouse_warp_mode_); - resizer->CompleteDrag(0); - } - EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS, - event_filter->mouse_warp_mode_); - - { - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTRIGHT)); - EXPECT_EQ(MouseCursorEventFilter::WARP_NONE, - event_filter->mouse_warp_mode_); - resizer->RevertDrag(); - } - EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS, - event_filter->mouse_warp_mode_); -} - -// Verifies cursor's device scale factor is updated whe a window is moved across -// root windows with different device scale factors (http://crbug.com/154183). -TEST_F(DragWindowResizerTest, CursorDeviceScaleFactor) { - if (!SupportsMultipleDisplays()) - return; - - // The secondary display is logically on the right, but on the system (e.g. X) - // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc. - UpdateDisplay("400x400,800x800*2"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - ASSERT_EQ(2U, root_windows.size()); - - test::CursorManagerTestApi cursor_test_api( - Shell::GetInstance()->cursor_manager()); - // Move window from the root window with 1.0 device scale factor to the root - // window with 2.0 device scale factor. - { - window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTCAPTION)); - EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(399, 200)); - EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor()); - resizer->CompleteDrag(0); - EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor()); - } - - // Move window from the root window with 2.0 device scale factor to the root - // window with 1.0 device scale factor. - { - window_->SetBoundsInScreen( - gfx::Rect(600, 0, 50, 60), - Shell::GetScreen()->GetDisplayNearestWindow(root_windows[1])); - EXPECT_EQ(root_windows[1], window_->GetRootWindow()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window_.get(), gfx::Point(), HTCAPTION)); - EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor()); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, -200, 200), 0); - WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(400, 200)); - EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); - resizer->CompleteDrag(0); - EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); - } -} - -// Verifies several kinds of windows can be moved across displays. -TEST_F(DragWindowResizerTest, MoveWindowAcrossDisplays) { - if (!SupportsMultipleDisplays()) - return; - - // The secondary display is logically on the right, but on the system (e.g. X) - // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc. - UpdateDisplay("400x400,400x400"); - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - ASSERT_EQ(2U, root_windows.size()); - - // Normal window can be moved across display. - { - aura::Window* window = window_.get(); - window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window, gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(399, 200))); - resizer->CompleteDrag(0); - } - - // Always on top window can be moved across display. - { - aura::Window* window = always_on_top_window_.get(); - window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window, gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(399, 200))); - resizer->CompleteDrag(0); - } - - // System modal window can be moved across display. - { - aura::Window* window = system_modal_window_.get(); - window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window, gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(399, 200))); - resizer->CompleteDrag(0); - } - - // Transient window cannot be moved across display. - { - aura::Window* window = transient_child_; - window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window, gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_FALSE(WarpMouseCursorIfNecessary( - root_windows[0], - gfx::Point(399, 200))); - resizer->CompleteDrag(0); - } - - // The parent of transient window can be moved across display. - { - aura::Window* window = transient_parent_.get(); - window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window, gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(399, 200))); - resizer->CompleteDrag(0); - } - - // Panel window can be moved across display. - { - aura::Window* window = panel_window_.get(); - window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window, gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(399, 200))); - resizer->CompleteDrag(0); - } -} - -#if defined(OS_CHROMEOS) -// Checks that moving a window to another desktop will properly set and reset -// the transparency. -TEST_F(DragWindowResizerTest, DragToOtherDesktopOpacity) { - // Set up a few things we need for multi profile. - ash::test::TestSessionStateDelegate* session_delegate = - static_cast<ash::test::TestSessionStateDelegate*>( - ash::Shell::GetInstance()->session_state_delegate()); - session_delegate->set_logged_in_users(2); - ash::test::TestShellDelegate* shell_delegate = - static_cast<ash::test::TestShellDelegate*>( - ash::Shell::GetInstance()->delegate()); - shell_delegate->set_multi_profiles_enabled(true); - - // Create one other user where we can drag our stuff onto. - SystemTray* tray = Shell::GetPrimaryRootWindowController()->GetSystemTray(); - TrayUser* tray_user = new TrayUser(tray, 1); - tray->AddTrayUserItemForTest(tray_user); - - // Move the view somewhere where we can hit it. - views::View* view = tray->GetTrayItemViewForTest(tray_user); - view->SetBounds(80, 0, 20, 20); - gfx::Point center = view->GetBoundsInScreen().CenterPoint(); - - gfx::Rect initial_bounds = gfx::Rect(0, 0, 50, 60); - // Drag the window over the icon and let it drop. Test that the window's - // layer gets transparent and reverts back. - { - aura::Window* window = window_.get(); - window->SetBoundsInScreen(initial_bounds, - Shell::GetScreen()->GetPrimaryDisplay()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window, gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - EXPECT_EQ(1.0, window->layer()->opacity()); - resizer->Drag(center, 0); - EXPECT_NE(1.0, window->layer()->opacity()); - EXPECT_EQ(0, session_delegate->num_transfer_to_desktop_of_user_calls()); - resizer->CompleteDrag(0); - EXPECT_EQ(1.0, window->layer()->opacity()); - EXPECT_EQ(1, session_delegate->num_transfer_to_desktop_of_user_calls()); - EXPECT_EQ(initial_bounds.ToString(), window->bounds().ToString()); - } - - // Drag the window over the icon and cancel the operation. Test that the - // window's layer gets transparent and reverts back. - { - aura::Window* window = window_.get(); - window->SetBoundsInScreen(initial_bounds, - Shell::GetScreen()->GetPrimaryDisplay()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window, gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - EXPECT_EQ(1.0, window->layer()->opacity()); - resizer->Drag(center, 0); - EXPECT_NE(1.0, window->layer()->opacity()); - resizer->RevertDrag(); - EXPECT_EQ(1.0, window->layer()->opacity()); - EXPECT_EQ(1, session_delegate->num_transfer_to_desktop_of_user_calls()); - EXPECT_EQ(initial_bounds.ToString(), window->bounds().ToString()); - } - - // Drag the window over the icon and somewhere else and see that it properly - // reverts its transparency. - { - aura::Window* window = window_.get(); - window->SetBoundsInScreen(initial_bounds, - Shell::GetScreen()->GetPrimaryDisplay()); - // Grab (0, 0) of the window. - scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( - window, gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - EXPECT_EQ(1.0, window->layer()->opacity()); - resizer->Drag(center, 0); - EXPECT_NE(1.0, window->layer()->opacity()); - resizer->Drag(gfx::Point(), 0); - EXPECT_EQ(1.0, window->layer()->opacity()); - resizer->CompleteDrag(0); - EXPECT_EQ(1, session_delegate->num_transfer_to_desktop_of_user_calls()); - EXPECT_NE(initial_bounds.ToString(), window->bounds().ToString()); - } -} -#endif - - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/event_client_impl.cc b/chromium/ash/wm/event_client_impl.cc deleted file mode 100644 index fbf5f86eda3..00000000000 --- a/chromium/ash/wm/event_client_impl.cc +++ /dev/null @@ -1,60 +0,0 @@ -// 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/event_client_impl.h" - -#include "ash/session_state_delegate.h" -#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 { - -EventClientImpl::EventClientImpl() { -} - -EventClientImpl::~EventClientImpl() { -} - -bool EventClientImpl::CanProcessEventsWithinSubtree( - const aura::Window* window) const { - const aura::Window* root_window = window ? window->GetRootWindow() : NULL; - if (!root_window || - !Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked()) { - 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( - root_window, - kShellWindowId_VirtualKeyboardContainer); - can_process_events |= (window->Contains(virtual_keyboard_container) || - virtual_keyboard_container->Contains(window)); - } - return can_process_events; -} - -ui::EventTarget* EventClientImpl::GetToplevelEventTarget() { - return Shell::GetInstance(); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/event_client_impl.h b/chromium/ash/wm/event_client_impl.h deleted file mode 100644 index b38228be942..00000000000 --- a/chromium/ash/wm/event_client_impl.h +++ /dev/null @@ -1,33 +0,0 @@ -// 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_EVENT_CLIENT_IMPL_H_ -#define ASH_WM_EVENT_CLIENT_IMPL_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/aura/client/event_client.h" - -namespace ash { -namespace internal { - -class EventClientImpl : public aura::client::EventClient { - public: - EventClientImpl(); - virtual ~EventClientImpl(); - - private: - // Overridden from aura::client::EventClient: - virtual bool CanProcessEventsWithinSubtree( - const aura::Window* window) const OVERRIDE; - virtual ui::EventTarget* GetToplevelEventTarget() OVERRIDE; - - DISALLOW_COPY_AND_ASSIGN(EventClientImpl); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_EVENT_CLIENT_IMPL_H_ diff --git a/chromium/ash/wm/event_rewriter_event_filter.cc b/chromium/ash/wm/event_rewriter_event_filter.cc deleted file mode 100644 index dd87e2a48a0..00000000000 --- a/chromium/ash/wm/event_rewriter_event_filter.cc +++ /dev/null @@ -1,56 +0,0 @@ -// 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/event_rewriter_event_filter.h" - -#include "ash/event_rewriter_delegate.h" -#include "base/logging.h" -#include "ui/events/event.h" - -namespace ash { -namespace internal { - -EventRewriterEventFilter::EventRewriterEventFilter() {} - -EventRewriterEventFilter::~EventRewriterEventFilter() {} - -void EventRewriterEventFilter::SetEventRewriterDelegate( - scoped_ptr<EventRewriterDelegate> delegate) { - delegate_ = delegate.Pass(); -} - -void EventRewriterEventFilter::OnKeyEvent(ui::KeyEvent* event) { - if (!delegate_) - return; - - // Do not consume a translated key event which is generated by an IME. - if (event->type() == ui::ET_TRANSLATED_KEY_PRESS || - event->type() == ui::ET_TRANSLATED_KEY_RELEASE) { - return; - } - - switch (delegate_->RewriteOrFilterKeyEvent(event)) { - case EventRewriterDelegate::ACTION_REWRITE_EVENT: - break; - case EventRewriterDelegate::ACTION_DROP_EVENT: - event->StopPropagation(); - break; - } -} - -void EventRewriterEventFilter::OnMouseEvent(ui::MouseEvent* event) { - if (!delegate_) - return; - - switch (delegate_->RewriteOrFilterLocatedEvent(event)) { - case EventRewriterDelegate::ACTION_REWRITE_EVENT: - break; - case EventRewriterDelegate::ACTION_DROP_EVENT: - event->StopPropagation(); - break; - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/event_rewriter_event_filter.h b/chromium/ash/wm/event_rewriter_event_filter.h deleted file mode 100644 index 86f7f538119..00000000000 --- a/chromium/ash/wm/event_rewriter_event_filter.h +++ /dev/null @@ -1,41 +0,0 @@ -// 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_EVENT_REWRITER_EVENT_FILTER_ -#define ASH_WM_EVENT_REWRITER_EVENT_FILTER_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "ui/events/event_handler.h" - -namespace ash { - -class EventRewriterDelegate; - -namespace internal { - -// An event filter that rewrites or drops an event. -class ASH_EXPORT EventRewriterEventFilter : public ui::EventHandler { - public: - EventRewriterEventFilter(); - virtual ~EventRewriterEventFilter(); - - void SetEventRewriterDelegate(scoped_ptr<EventRewriterDelegate> delegate); - - private: - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - - scoped_ptr<EventRewriterDelegate> delegate_; - - DISALLOW_COPY_AND_ASSIGN(EventRewriterEventFilter); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_EVENT_REWRITER_EVENT_FILTER_ diff --git a/chromium/ash/wm/frame_border_hit_test_controller.cc b/chromium/ash/wm/frame_border_hit_test_controller.cc deleted file mode 100644 index 28a57266715..00000000000 --- a/chromium/ash/wm/frame_border_hit_test_controller.cc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2013 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/frame_border_hit_test_controller.h" - -#include "ash/ash_constants.h" -#include "ash/wm/header_painter.h" -#include "ash/wm/window_state.h" -#include "ui/aura/env.h" -#include "ui/aura/window.h" -#include "ui/base/hit_test.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" -#include "ui/views/window/non_client_view.h" - -namespace ash { - -FrameBorderHitTestController::FrameBorderHitTestController(views::Widget* frame) - : frame_window_(frame->GetNativeWindow()) { - gfx::Insets mouse_outer_insets(-kResizeOutsideBoundsSize, - -kResizeOutsideBoundsSize, - -kResizeOutsideBoundsSize, - -kResizeOutsideBoundsSize); - gfx::Insets touch_outer_insets = mouse_outer_insets.Scale( - kResizeOutsideBoundsScaleForTouch); - // Ensure we get resize cursors for a few pixels outside our bounds. - frame_window_->SetHitTestBoundsOverrideOuter(mouse_outer_insets, - touch_outer_insets); - // Ensure we get resize cursors just inside our bounds as well. - UpdateHitTestBoundsOverrideInner(); - - frame_window_->AddObserver(this); - ash::wm::GetWindowState(frame_window_)->AddObserver(this); -} - -FrameBorderHitTestController::~FrameBorderHitTestController() { - if (frame_window_) { - frame_window_->RemoveObserver(this); - ash::wm::GetWindowState(frame_window_)->RemoveObserver(this); - } -} - -// static -int FrameBorderHitTestController::NonClientHitTest( - views::NonClientFrameView* view, - HeaderPainter* header_painter, - const gfx::Point& point) { - gfx::Rect expanded_bounds = view->bounds(); - int outside_bounds = kResizeOutsideBoundsSize; - - if (aura::Env::GetInstance()->is_touch_down()) - outside_bounds *= kResizeOutsideBoundsScaleForTouch; - expanded_bounds.Inset(-outside_bounds, -outside_bounds); - - if (!expanded_bounds.Contains(point)) - return HTNOWHERE; - - // Check the frame first, as we allow a small area overlapping the contents - // to be used for resize handles. - views::Widget* frame = view->GetWidget(); - bool can_ever_resize = frame->widget_delegate()->CanResize(); - // Don't allow overlapping resize handles when the window is maximized or - // fullscreen, as it can't be resized in those states. - int resize_border = - frame->IsMaximized() || frame->IsFullscreen() ? 0 : - kResizeInsideBoundsSize; - int frame_component = view->GetHTComponentForFrame(point, - resize_border, - resize_border, - kResizeAreaCornerSize, - kResizeAreaCornerSize, - can_ever_resize); - if (frame_component != HTNOWHERE) - return frame_component; - - int client_component = frame->client_view()->NonClientHitTest(point); - if (client_component != HTNOWHERE) - return client_component; - - return header_painter->NonClientHitTest(point); -} - -void FrameBorderHitTestController::UpdateHitTestBoundsOverrideInner() { - // Maximized and fullscreen windows don't want resize handles overlapping the - // content area, because when the user moves the cursor to the right screen - // edge we want them to be able to hit the scroll bar. - if (wm::GetWindowState(frame_window_)->IsMaximizedOrFullscreen()) { - frame_window_->set_hit_test_bounds_override_inner(gfx::Insets()); - } else { - frame_window_->set_hit_test_bounds_override_inner( - gfx::Insets(kResizeInsideBoundsSize, kResizeInsideBoundsSize, - kResizeInsideBoundsSize, kResizeInsideBoundsSize)); - } -} - -void FrameBorderHitTestController::OnWindowShowTypeChanged( - wm::WindowState* window_state, - wm::WindowShowType old_type) { - UpdateHitTestBoundsOverrideInner(); -} - -void FrameBorderHitTestController::OnWindowDestroying(aura::Window* window) { - frame_window_->RemoveObserver(this); - ash::wm::GetWindowState(frame_window_)->RemoveObserver(this); - frame_window_ = NULL; -} - -} // namespace ash diff --git a/chromium/ash/wm/frame_border_hit_test_controller.h b/chromium/ash/wm/frame_border_hit_test_controller.h deleted file mode 100644 index 21fe9cf0305..00000000000 --- a/chromium/ash/wm/frame_border_hit_test_controller.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2013 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_FRAME_BORDER_HITTEST_CONTROLLER_H_ -#define ASH_WM_FRAME_BORDER_HITTEST_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "ash/wm/window_state_observer.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/aura/window_observer.h" - -namespace gfx { -class Point; -} - -namespace views { -class NonClientFrameView; -class Widget; -} - -namespace ash { -class HeaderPainter; - -// Class which manages the hittest override bounds for |frame|. The override -// bounds are used to ensure that the resize cursors are shown when the user -// hovers over |frame|'s edges. -class ASH_EXPORT FrameBorderHitTestController : public wm::WindowStateObserver, - public aura::WindowObserver { - public: - explicit FrameBorderHitTestController(views::Widget* frame); - virtual ~FrameBorderHitTestController(); - - // Does the non client hit test on behalf of |view|. |point| must be in the - // coordinates of |view|'s widget. - static int NonClientHitTest(views::NonClientFrameView* view, - HeaderPainter* header_painter, - const gfx::Point& point); - - private: - // Updates the size of the region inside of |window_| in which the resize - // handles are shown based on |window_|'s show type. - void UpdateHitTestBoundsOverrideInner(); - - // WindowStateObserver override: - virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType old_type) OVERRIDE; - // WindowObserver override: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - // The window whose hittest override bounds are being managed. - aura::Window* frame_window_; - - DISALLOW_COPY_AND_ASSIGN(FrameBorderHitTestController); -}; - -} // namespace ash - -#endif // ASH_WM_FRAME_BORDER_HITTEST_CONTROLLER_H_ diff --git a/chromium/ash/wm/gestures/OWNERS b/chromium/ash/wm/gestures/OWNERS deleted file mode 100644 index b8e32c10903..00000000000 --- a/chromium/ash/wm/gestures/OWNERS +++ /dev/null @@ -1 +0,0 @@ -sadrul@chromium.org diff --git a/chromium/ash/wm/gestures/long_press_affordance_handler.cc b/chromium/ash/wm/gestures/long_press_affordance_handler.cc deleted file mode 100644 index 2a96f0707f0..00000000000 --- a/chromium/ash/wm/gestures/long_press_affordance_handler.cc +++ /dev/null @@ -1,370 +0,0 @@ -// 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/gestures/long_press_affordance_handler.h" - -#include "ash/display/display_controller.h" -#include "ash/root_window_controller.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "third_party/skia/include/core/SkColor.h" -#include "third_party/skia/include/core/SkPaint.h" -#include "third_party/skia/include/core/SkPath.h" -#include "third_party/skia/include/core/SkRect.h" -#include "third_party/skia/include/effects/SkGradientShader.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/events/gestures/gesture_configuration.h" -#include "ui/events/gestures/gesture_util.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/screen.h" -#include "ui/gfx/transform.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { -namespace { - -const int kAffordanceOuterRadius = 60; -const int kAffordanceInnerRadius = 50; - -// Angles from x-axis at which the outer and inner circles start. -const int kAffordanceOuterStartAngle = -109; -const int kAffordanceInnerStartAngle = -65; - -const int kAffordanceGlowWidth = 20; -// The following is half width to avoid division by 2. -const int kAffordanceArcWidth = 3; - -// Start and end values for various animations. -const double kAffordanceScaleStartValue = 0.8; -const double kAffordanceScaleEndValue = 1.0; -const double kAffordanceShrinkScaleEndValue = 0.5; -const double kAffordanceOpacityStartValue = 0.1; -const double kAffordanceOpacityEndValue = 0.5; -const int kAffordanceAngleStartValue = 0; -// The end angle is a bit greater than 360 to make sure the circle completes at -// the end of the animation. -const int kAffordanceAngleEndValue = 380; -const int kAffordanceDelayBeforeShrinkMs = 200; -const int kAffordanceShrinkAnimationDurationMs = 100; - -// Visual constants. -const SkColor kAffordanceGlowStartColor = SkColorSetARGB(24, 255, 255, 255); -const SkColor kAffordanceGlowEndColor = SkColorSetARGB(0, 255, 255, 255); -const SkColor kAffordanceArcColor = SkColorSetARGB(80, 0, 0, 0); -const int kAffordanceFrameRateHz = 60; - -views::Widget* CreateAffordanceWidget(aura::Window* root_window) { - views::Widget* widget = new views::Widget; - views::Widget::InitParams params; - params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; - params.keep_on_top = true; - params.accept_events = false; - params.can_activate = false; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.context = root_window; - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - widget->Init(params); - widget->SetOpacity(0xFF); - GetRootWindowController(root_window)->GetContainer( - kShellWindowId_OverlayContainer)->AddChild(widget->GetNativeWindow()); - return widget; -} - -void PaintAffordanceArc(gfx::Canvas* canvas, - gfx::Point& center, - int radius, - int start_angle, - int end_angle) { - SkPaint paint; - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(2 * kAffordanceArcWidth); - paint.setColor(kAffordanceArcColor); - paint.setAntiAlias(true); - - SkPath arc_path; - arc_path.addArc(SkRect::MakeXYWH(center.x() - radius, - center.y() - radius, - 2 * radius, - 2 * radius), - start_angle, end_angle); - canvas->DrawPath(arc_path, paint); -} - -void PaintAffordanceGlow(gfx::Canvas* canvas, - gfx::Point& center, - int start_radius, - int end_radius, - SkColor* colors, - SkScalar* pos, - int num_colors) { - SkPoint sk_center; - int radius = (end_radius + start_radius) / 2; - int glow_width = end_radius - start_radius; - sk_center.iset(center.x(), center.y()); - skia::RefPtr<SkShader> shader = skia::AdoptRef( - SkGradientShader::CreateTwoPointRadial( - sk_center, - SkIntToScalar(start_radius), - sk_center, - SkIntToScalar(end_radius), - colors, - pos, - num_colors, - SkShader::kClamp_TileMode)); - DCHECK(shader); - SkPaint paint; - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(glow_width); - paint.setShader(shader.get()); - paint.setAntiAlias(true); - SkPath arc_path; - arc_path.addArc(SkRect::MakeXYWH(center.x() - radius, - center.y() - radius, - 2 * radius, - 2 * radius), - 0, 360); - canvas->DrawPath(arc_path, paint); -} - -} // namespace - -// View of the LongPressAffordanceHandler. Draws the actual contents and -// updates as the animation proceeds. It also maintains the views::Widget that -// the animation is shown in. -class LongPressAffordanceHandler::LongPressAffordanceView - : public views::View { - public: - LongPressAffordanceView(const gfx::Point& event_location, - aura::Window* root_window) - : views::View(), - widget_(CreateAffordanceWidget(root_window)), - current_angle_(kAffordanceAngleStartValue), - current_scale_(kAffordanceScaleStartValue) { - widget_->SetContentsView(this); - widget_->SetAlwaysOnTop(true); - - // We are owned by the LongPressAffordance. - set_owned_by_client(); - gfx::Point point = event_location; - aura::client::GetScreenPositionClient(root_window)->ConvertPointToScreen( - root_window, &point); - widget_->SetBounds(gfx::Rect( - point.x() - (kAffordanceOuterRadius + kAffordanceGlowWidth), - point.y() - (kAffordanceOuterRadius + kAffordanceGlowWidth), - GetPreferredSize().width(), - GetPreferredSize().height())); - widget_->Show(); - widget_->GetNativeView()->layer()->SetOpacity(kAffordanceOpacityStartValue); - } - - virtual ~LongPressAffordanceView() { - } - - void UpdateWithGrowAnimation(gfx::Animation* animation) { - // Update the portion of the circle filled so far and re-draw. - current_angle_ = animation->CurrentValueBetween(kAffordanceAngleStartValue, - kAffordanceAngleEndValue); - current_scale_ = animation->CurrentValueBetween(kAffordanceScaleStartValue, - kAffordanceScaleEndValue); - widget_->GetNativeView()->layer()->SetOpacity( - animation->CurrentValueBetween(kAffordanceOpacityStartValue, - kAffordanceOpacityEndValue)); - SchedulePaint(); - } - - void UpdateWithShrinkAnimation(gfx::Animation* animation) { - current_scale_ = animation->CurrentValueBetween(kAffordanceScaleEndValue, - kAffordanceShrinkScaleEndValue); - widget_->GetNativeView()->layer()->SetOpacity( - animation->CurrentValueBetween(kAffordanceOpacityEndValue, - kAffordanceOpacityStartValue)); - SchedulePaint(); - } - - private: - // Overridden from views::View. - virtual gfx::Size GetPreferredSize() OVERRIDE { - return gfx::Size(2 * (kAffordanceOuterRadius + kAffordanceGlowWidth), - 2 * (kAffordanceOuterRadius + kAffordanceGlowWidth)); - } - - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { - gfx::Point center(GetPreferredSize().width() / 2, - GetPreferredSize().height() / 2); - canvas->Save(); - - gfx::Transform scale; - scale.Scale(current_scale_, current_scale_); - // We want to scale from the center. - canvas->Translate(center.OffsetFromOrigin()); - canvas->Transform(scale); - canvas->Translate(-center.OffsetFromOrigin()); - - // Paint affordance glow - int start_radius = kAffordanceInnerRadius - kAffordanceGlowWidth; - int end_radius = kAffordanceOuterRadius + kAffordanceGlowWidth; - const int num_colors = 3; - SkScalar pos[num_colors] = {0, 0.5, 1}; - SkColor colors[num_colors] = {kAffordanceGlowEndColor, - kAffordanceGlowStartColor, kAffordanceGlowEndColor}; - PaintAffordanceGlow(canvas, center, start_radius, end_radius, colors, pos, - num_colors); - - // Paint inner circle. - PaintAffordanceArc(canvas, center, kAffordanceInnerRadius, - kAffordanceInnerStartAngle, -current_angle_); - // Paint outer circle. - PaintAffordanceArc(canvas, center, kAffordanceOuterRadius, - kAffordanceOuterStartAngle, current_angle_); - - canvas->Restore(); - } - - scoped_ptr<views::Widget> widget_; - int current_angle_; - double current_scale_; - - DISALLOW_COPY_AND_ASSIGN(LongPressAffordanceView); -}; - -//////////////////////////////////////////////////////////////////////////////// -// LongPressAffordanceHandler, public - -LongPressAffordanceHandler::LongPressAffordanceHandler() - : gfx::LinearAnimation(kAffordanceFrameRateHz, NULL), - tap_down_target_(NULL), - current_animation_type_(NONE) {} - -LongPressAffordanceHandler::~LongPressAffordanceHandler() { - StopAffordance(); -} - -void LongPressAffordanceHandler::ProcessEvent(aura::Window* target, - ui::GestureEvent* event) { - // Once we have a target, we are only interested in events with that target. - if (tap_down_target_ && tap_down_target_ != target) - return; - switch (event->type()) { - case ui::ET_GESTURE_TAP_DOWN: { - // Start timer that will start animation on "semi-long-press". - tap_down_location_ = event->root_location(); - SetTapDownTarget(target); - current_animation_type_ = GROW_ANIMATION; - int64 timer_start_time_ms = - ui::GestureConfiguration::semi_long_press_time_in_seconds() * 1000; - timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds(timer_start_time_ms), - this, - &LongPressAffordanceHandler::StartAnimation); - break; - } - case ui::ET_GESTURE_TAP: - case ui::ET_GESTURE_TAP_CANCEL: - StopAffordance(); - break; - case ui::ET_GESTURE_LONG_PRESS: - End(); - break; - default: - break; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// LongPressAffordanceHandler, private - -void LongPressAffordanceHandler::StartAnimation() { - switch (current_animation_type_) { - case GROW_ANIMATION: { - aura::Window* root_window = tap_down_target_->GetRootWindow(); - if (!root_window) { - StopAffordance(); - return; - } - view_.reset(new LongPressAffordanceView(tap_down_location_, root_window)); - SetDuration( - ui::GestureConfiguration::long_press_time_in_seconds() * 1000 - - ui::GestureConfiguration::semi_long_press_time_in_seconds() * 1000 - - kAffordanceDelayBeforeShrinkMs); - Start(); - break; - } - case SHRINK_ANIMATION: - SetDuration(kAffordanceShrinkAnimationDurationMs); - Start(); - break; - default: - NOTREACHED(); - break; - } -} - -void LongPressAffordanceHandler::StopAffordance() { - if (timer_.IsRunning()) - timer_.Stop(); - // Since, Animation::Stop() calls AnimationStopped(), we need to reset the - // |current_animation_type_| before Stop(), otherwise AnimationStopped() may - // start the timer again. - current_animation_type_ = NONE; - Stop(); - view_.reset(); - SetTapDownTarget(NULL); -} - -void LongPressAffordanceHandler::SetTapDownTarget(aura::Window* target) { - if (tap_down_target_ == target) - return; - - if (tap_down_target_) - tap_down_target_->RemoveObserver(this); - tap_down_target_ = target; - if (tap_down_target_) - tap_down_target_->AddObserver(this); -} - -void LongPressAffordanceHandler::AnimateToState(double state) { - DCHECK(view_.get()); - switch (current_animation_type_) { - case GROW_ANIMATION: - view_->UpdateWithGrowAnimation(this); - break; - case SHRINK_ANIMATION: - view_->UpdateWithShrinkAnimation(this); - break; - default: - NOTREACHED(); - break; - } -} - -void LongPressAffordanceHandler::AnimationStopped() { - switch (current_animation_type_) { - case GROW_ANIMATION: - current_animation_type_ = SHRINK_ANIMATION; - timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds(kAffordanceDelayBeforeShrinkMs), - this, &LongPressAffordanceHandler::StartAnimation); - break; - case SHRINK_ANIMATION: - current_animation_type_ = NONE; - // fall through to reset the view. - default: - view_.reset(); - SetTapDownTarget(NULL); - break; - } -} - -void LongPressAffordanceHandler::OnWindowDestroying(aura::Window* window) { - DCHECK_EQ(tap_down_target_, window); - StopAffordance(); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/gestures/long_press_affordance_handler.h b/chromium/ash/wm/gestures/long_press_affordance_handler.h deleted file mode 100644 index fa0337aee8f..00000000000 --- a/chromium/ash/wm/gestures/long_press_affordance_handler.h +++ /dev/null @@ -1,75 +0,0 @@ -// 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_GESTURES_LONG_PRESS_AFFORDANCE_HANDLER_H_ -#define ASH_WM_GESTURES_LONG_PRESS_AFFORDANCE_HANDLER_H_ - -#include "base/timer/timer.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/animation/linear_animation.h" -#include "ui/gfx/point.h" - -namespace ui { -class GestureEvent; -} - -namespace ash { - -namespace test { -class SystemGestureEventFilterTest; -} - -namespace internal { - -// LongPressAffordanceHandler displays an animated affordance that is shown -// on a TAP_DOWN gesture. The animation sequence consists of two parts: -// The first part is a grow animation that starts at semi-long-press and -// completes on a long-press gesture. The affordance animates to full size -// during grow animation. -// The second part is a shrink animation that start after grow and shrinks the -// affordance out of view. -class LongPressAffordanceHandler : public gfx::LinearAnimation, - public aura::WindowObserver { - public: - LongPressAffordanceHandler(); - virtual ~LongPressAffordanceHandler(); - - // Displays or removes long press affordance according to the |event|. - void ProcessEvent(aura::Window* target, ui::GestureEvent* event); - - private: - friend class ash::test::SystemGestureEventFilterTest; - - class LongPressAffordanceView; - - enum LongPressAnimationType { - NONE, - GROW_ANIMATION, - SHRINK_ANIMATION, - }; - - void StartAnimation(); - void StopAffordance(); - void SetTapDownTarget(aura::Window* target); - - // Overridden from gfx::LinearAnimation. - virtual void AnimateToState(double state) OVERRIDE; - virtual void AnimationStopped() OVERRIDE; - - // Overridden from aura::WindowObserver. - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - scoped_ptr<LongPressAffordanceView> view_; - gfx::Point tap_down_location_; - base::OneShotTimer<LongPressAffordanceHandler> timer_; - aura::Window* tap_down_target_; - LongPressAnimationType current_animation_type_; - - DISALLOW_COPY_AND_ASSIGN(LongPressAffordanceHandler); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_GESTURES_LONG_PRESS_AFFORDANCE_HANDLER_H_ diff --git a/chromium/ash/wm/gestures/overview_gesture_handler.cc b/chromium/ash/wm/gestures/overview_gesture_handler.cc deleted file mode 100644 index ebff8e680bc..00000000000 --- a/chromium/ash/wm/gestures/overview_gesture_handler.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2013 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/gestures/overview_gesture_handler.h" - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/shell.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/overview/window_selector_controller.h" -#include "ui/aura/window.h" -#include "ui/events/event.h" -#include "ui/events/event_constants.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/screen.h" - -namespace ash { -namespace internal { - -namespace { - -// The number of pixels from the top of the screen (a virtual bezel) to allow -// the overview swipe down gesture to begin within. Note this does not actually -// prevent handling of the touches so a fullscreen page which consumes these can -// prevent entering overview with a swipe down. -const int kTopBezelExtraPixels = 5; - -// The threshold before engaging overview on a three finger swipe on the -// touchpad. -const float kSwipeThresholdPixels = 300; - -} // namespace; - -OverviewGestureHandler::OverviewGestureHandler() - : in_top_bezel_gesture_(false), - scroll_x_(0), - scroll_y_(0) { -} - -OverviewGestureHandler::~OverviewGestureHandler() { -} - -bool OverviewGestureHandler::ProcessScrollEvent(const ui::ScrollEvent& event) { - if (event.type() == ui::ET_SCROLL_FLING_START || - event.type() == ui::ET_SCROLL_FLING_CANCEL || - event.finger_count() != 3) { - scroll_x_ = scroll_y_ = 0; - return false; - } - - scroll_x_ += event.x_offset(); - scroll_y_ += event.y_offset(); - - // Horizontal swiping is ignored. - if (std::fabs(scroll_x_) >= std::fabs(scroll_y_)) { - scroll_x_ = scroll_y_ = 0; - return false; - } - - // Only allow swipe up to enter overview, down to exit. Ignore extra swiping - // in the wrong direction. - Shell* shell = Shell::GetInstance(); - if (shell->window_selector_controller()->IsSelecting()) { - if (scroll_y_ < 0) - scroll_x_ = scroll_y_ = 0; - if (scroll_y_ < kSwipeThresholdPixels) - return false; - } else { - if (scroll_y_ > 0) - scroll_x_ = scroll_y_ = 0; - if (scroll_y_ > -kSwipeThresholdPixels) - return false; - } - - // Reset scroll amount on toggling. - scroll_x_ = scroll_y_ = 0; - shell->metrics()->RecordUserMetricsAction(UMA_TOUCHPAD_GESTURE_OVERVIEW); - shell->window_selector_controller()->ToggleOverview(); - return true; -} - -bool OverviewGestureHandler::ProcessGestureEvent( - const ui::GestureEvent& event) { - // Detect at the beginning of any gesture whether it begins on the top bezel. - if (event.type() == ui::ET_GESTURE_BEGIN && - event.details().touch_points() == 1) { - gfx::Point point_in_screen(event.location()); - aura::Window* target = static_cast<aura::Window*>(event.target()); - wm::ConvertPointToScreen(target, &point_in_screen); - in_top_bezel_gesture_ = !Shell::GetScreen()->GetDisplayNearestPoint( - point_in_screen).bounds().y() + kTopBezelExtraPixels > - point_in_screen.y(); - return false; - } - - if (!in_top_bezel_gesture_ || - event.type() != ui::ET_GESTURE_MULTIFINGER_SWIPE || - !event.details().swipe_down() || - event.details().touch_points() != 3) { - return false; - } - - Shell* shell = Shell::GetInstance(); - shell->metrics()->RecordUserMetricsAction(UMA_GESTURE_OVERVIEW); - shell->window_selector_controller()->ToggleOverview(); - return true; -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/gestures/overview_gesture_handler.h b/chromium/ash/wm/gestures/overview_gesture_handler.h deleted file mode 100644 index 8b9fde50224..00000000000 --- a/chromium/ash/wm/gestures/overview_gesture_handler.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2013 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_GESTURES_OVERVIEW_GESTURE_HANDLER_H_ -#define ASH_WM_GESTURES_OVERVIEW_GESTURE_HANDLER_H_ - -#include "base/basictypes.h" - -namespace aura { -class Window; -} - -namespace ui { -class GestureEvent; -class ScrollEvent; -} - -namespace ash { -namespace internal { - -// This handles a 3-finger swipe down gesture from the top of the screen to -// enter overview mode. -class OverviewGestureHandler { - public: - OverviewGestureHandler(); - virtual ~OverviewGestureHandler(); - - // Processes a scroll event and may start overview. Returns true if the event - // has been handled and should not be processed further, false otherwise. - bool ProcessScrollEvent(const ui::ScrollEvent& event); - - // Processes a gesture event and may start overview. Returns true if the event - // has been handled and should not be processed any farther, false otherwise. - bool ProcessGestureEvent(const ui::GestureEvent& event); - - private: - // True if the current/last gesture began in the top bezel. - bool in_top_bezel_gesture_; - - // The total distance scrolled with three fingers. - float scroll_x_; - float scroll_y_; - - DISALLOW_COPY_AND_ASSIGN(OverviewGestureHandler); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_GESTURES_OVERVIEW_GESTURE_HANDLER_H_ diff --git a/chromium/ash/wm/gestures/overview_gesture_handler_unittest.cc b/chromium/ash/wm/gestures/overview_gesture_handler_unittest.cc deleted file mode 100644 index e3eddbd2539..00000000000 --- a/chromium/ash/wm/gestures/overview_gesture_handler_unittest.cc +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2013 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/root_window_controller.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/overview/window_selector_controller.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" - -namespace ash { -namespace internal { - -class OverviewGestureHandlerTest : public test::AshTestBase { - public: - OverviewGestureHandlerTest() {} - virtual ~OverviewGestureHandlerTest() {} - - aura::Window* CreateWindow(const gfx::Rect& bounds) { - return CreateTestWindowInShellWithDelegate(&delegate_, -1, bounds); - } - - bool IsSelecting() { - return ash::Shell::GetInstance()->window_selector_controller()-> - IsSelecting(); - } - - private: - aura::test::TestWindowDelegate delegate_; - - DISALLOW_COPY_AND_ASSIGN(OverviewGestureHandlerTest); -}; - -// Tests a swipe up with three fingers to enter and a swipe down to exit -// overview. -TEST_F(OverviewGestureHandlerTest, VerticalSwipes) { - gfx::Rect bounds(0, 0, 400, 400); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - aura::test::EventGenerator generator(root_window, root_window); - generator.ScrollSequence(gfx::Point(), base::TimeDelta::FromMilliseconds(5), - 0, -500, 100, 3); - EXPECT_TRUE(IsSelecting()); - - // Swiping up again does nothing. - generator.ScrollSequence(gfx::Point(), base::TimeDelta::FromMilliseconds(5), - 0, -500, 100, 3); - EXPECT_TRUE(IsSelecting()); - - // Swiping down exits. - generator.ScrollSequence(gfx::Point(), base::TimeDelta::FromMilliseconds(5), - 0, 500, 100, 3); - EXPECT_FALSE(IsSelecting()); - - // Swiping down again does nothing. - generator.ScrollSequence(gfx::Point(), base::TimeDelta::FromMilliseconds(5), - 0, 500, 100, 3); - EXPECT_FALSE(IsSelecting()); -} - -// Tests that a mostly horizontal swipe does not trigger overview. -TEST_F(OverviewGestureHandlerTest, HorizontalSwipes) { - gfx::Rect bounds(0, 0, 400, 400); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - aura::test::EventGenerator generator(root_window, root_window); - generator.ScrollSequence(gfx::Point(), base::TimeDelta::FromMilliseconds(5), - 600, -500, 100, 3); - EXPECT_FALSE(IsSelecting()); - - generator.ScrollSequence(gfx::Point(), base::TimeDelta::FromMilliseconds(5), - -600, -500, 100, 3); - EXPECT_FALSE(IsSelecting()); -} - -// Tests a swipe up with three fingers without releasing followed by a swipe -// down by a lesser amount which should still be enough to exit. -TEST_F(OverviewGestureHandlerTest, SwipeUpDownWithoutReleasing) { - gfx::Rect bounds(0, 0, 400, 400); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - aura::test::EventGenerator generator(root_window, root_window); - base::TimeDelta timestamp = base::TimeDelta::FromInternalValue( - base::TimeTicks::Now().ToInternalValue()); - gfx::Point start; - int num_fingers = 3; - base::TimeDelta step_delay(base::TimeDelta::FromMilliseconds(5)); - ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL, - start, - timestamp, - 0, - 0, 0, - 0, 0, - num_fingers); - generator.Dispatch(&fling_cancel); - - // Scroll up by 1000px. - for (int i = 0; i < 100; ++i) { - timestamp += step_delay; - ui::ScrollEvent move(ui::ET_SCROLL, - start, - timestamp, - 0, - 0, -10, - 0, -10, - num_fingers); - generator.Dispatch(&move); - } - - EXPECT_TRUE(IsSelecting()); - - // Without releasing scroll back down by 600px. - for (int i = 0; i < 60; ++i) { - timestamp += step_delay; - ui::ScrollEvent move(ui::ET_SCROLL, - start, - timestamp, - 0, - 0, 10, - 0, 10, - num_fingers); - generator.Dispatch(&move); - } - - EXPECT_FALSE(IsSelecting()); - ui::ScrollEvent fling_start(ui::ET_SCROLL_FLING_START, - start, - timestamp, - 0, - 0, 10, - 0, 10, - num_fingers); - generator.Dispatch(&fling_start); -} - -// Tests a swipe down from the top of the screen to enter and exit overview. -TEST_F(OverviewGestureHandlerTest, GestureSwipe) { - gfx::Rect bounds(0, 0, 400, 400); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - aura::test::EventGenerator generator(root_window, root_window); - gfx::Point start_points[3]; - start_points[0] = start_points[1] = start_points[2] = gfx::Point(); - generator.GestureMultiFingerScroll(3, start_points, 5, 10, 0, 100); - EXPECT_TRUE(IsSelecting()); - - generator.GestureMultiFingerScroll(3, start_points, 5, 10, 0, 100); - EXPECT_FALSE(IsSelecting()); -} - -// Tests that a swipe down from the top of a window doesn't enter overview. -// http://crbug.com/313859 -TEST_F(OverviewGestureHandlerTest, GestureSwipeTopOfWindow) { - gfx::Rect bounds(100, 100, 400, 400); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - aura::test::EventGenerator generator(root_window, window2.get()); - gfx::Point start_points[3]; - start_points[0] = start_points[1] = start_points[2] = gfx::Point(105, 105); - generator.GestureMultiFingerScroll(3, start_points, 5, 10, 0, 100); - EXPECT_FALSE(IsSelecting()); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/gestures/shelf_gesture_handler.cc b/chromium/ash/wm/gestures/shelf_gesture_handler.cc deleted file mode 100644 index f9fb1b8d43c..00000000000 --- a/chromium/ash/wm/gestures/shelf_gesture_handler.cc +++ /dev/null @@ -1,92 +0,0 @@ -// 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/gestures/shelf_gesture_handler.h" - -#include "ash/root_window_controller.h" -#include "ash/session_state_delegate.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_types.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/system/status_area_widget.h" -#include "ash/wm/gestures/tray_gesture_handler.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/transform.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -ShelfGestureHandler::ShelfGestureHandler() - : drag_in_progress_(false) { -} - -ShelfGestureHandler::~ShelfGestureHandler() { -} - -bool ShelfGestureHandler::ProcessGestureEvent(const ui::GestureEvent& event) { - Shell* shell = Shell::GetInstance(); - if (!shell->session_state_delegate()->NumberOfLoggedInUsers() || - shell->session_state_delegate()->IsScreenLocked()) { - // The gestures are disabled in the lock/login screen. - return false; - } - - // TODO(oshima): Find the root window controller from event's location. - RootWindowController* controller = Shell::GetPrimaryRootWindowController(); - - ShelfLayoutManager* shelf = controller->GetShelfLayoutManager(); - - const aura::Window* fullscreen = controller->GetWindowForFullscreenMode(); - if (fullscreen && - ash::wm::GetWindowState(fullscreen)->hide_shelf_when_fullscreen()) { - return false; - } - - if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) { - drag_in_progress_ = true; - shelf->StartGestureDrag(event); - return true; - } - - if (!drag_in_progress_) - return false; - - if (event.type() == ui::ET_GESTURE_SCROLL_UPDATE) { - if (tray_handler_) { - if (!tray_handler_->UpdateGestureDrag(event)) - tray_handler_.reset(); - } else if (shelf->UpdateGestureDrag(event) == - ShelfLayoutManager::DRAG_TRAY) { - tray_handler_.reset(new TrayGestureHandler()); - } - - return true; - } - - drag_in_progress_ = false; - - if (event.type() == ui::ET_GESTURE_SCROLL_END || - event.type() == ui::ET_SCROLL_FLING_START) { - if (tray_handler_) { - tray_handler_->CompleteGestureDrag(event); - tray_handler_.reset(); - } - - shelf->CompleteGestureDrag(event); - return true; - } - - // Unexpected event. Reset the state and let the event fall through. - shelf->CancelGestureDrag(); - return false; -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/gestures/shelf_gesture_handler.h b/chromium/ash/wm/gestures/shelf_gesture_handler.h deleted file mode 100644 index 90dfd7c923e..00000000000 --- a/chromium/ash/wm/gestures/shelf_gesture_handler.h +++ /dev/null @@ -1,43 +0,0 @@ -// 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_GESTURES_SHELF_GESTURE_HANDLER_H_ -#define ASH_WM_GESTURES_SHELF_GESTURE_HANDLER_H_ - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" - -namespace ui { -class GestureEvent; -} - -namespace ash { -namespace internal { - -class TrayGestureHandler; - -// This manages gestures on the shelf (e.g. launcher, status tray) that affects -// the shelf visibility. -class ShelfGestureHandler { - public: - ShelfGestureHandler(); - virtual ~ShelfGestureHandler(); - - // Processes a gesture event and updates the status of the shelf when - // appropriate. Returns true of the gesture has been handled and it should not - // be processed any farther, false otherwise. - bool ProcessGestureEvent(const ui::GestureEvent& event); - - private: - bool drag_in_progress_; - - scoped_ptr<TrayGestureHandler> tray_handler_; - - DISALLOW_COPY_AND_ASSIGN(ShelfGestureHandler); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_GESTURES_SHELF_GESTURE_HANDLER_H_ diff --git a/chromium/ash/wm/gestures/system_pinch_handler.cc b/chromium/ash/wm/gestures/system_pinch_handler.cc deleted file mode 100644 index 2c066161304..00000000000 --- a/chromium/ash/wm/gestures/system_pinch_handler.cc +++ /dev/null @@ -1,142 +0,0 @@ -// 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/gestures/system_pinch_handler.h" - -#include "ash/launcher/launcher.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "ui/aura/window.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/events/event_constants.h" -#include "ui/events/gestures/gesture_types.h" -#include "ui/gfx/rect.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -const double kPinchThresholdForMaximize = 1.5; -const double kPinchThresholdForMinimize = 0.7; - -namespace ash { -namespace internal { - -const int SystemPinchHandler::kSystemGesturePoints = 4; - -SystemPinchHandler::SystemPinchHandler(aura::Window* target) - : target_(target), - phantom_(target), - phantom_state_(PHANTOM_WINDOW_NORMAL), - pinch_factor_(1.) { - widget_ = views::Widget::GetWidgetForNativeWindow(target_); -} - -SystemPinchHandler::~SystemPinchHandler() { -} - -SystemGestureStatus SystemPinchHandler::ProcessGestureEvent( - const ui::GestureEvent& event) { - // The target has changed, somehow. Let's bale. - if (!widget_ || !widget_->widget_delegate()->CanResize()) - return SYSTEM_GESTURE_END; - wm::WindowState* window_state = wm::GetWindowState(target_); - switch (event.type()) { - case ui::ET_GESTURE_END: { - if (event.details().touch_points() > kSystemGesturePoints) - break; - - if (phantom_state_ == PHANTOM_WINDOW_MAXIMIZED) { - if (!window_state->IsMaximizedOrFullscreen()) - window_state->Maximize(); - } else if (phantom_state_ == PHANTOM_WINDOW_MINIMIZED) { - if (window_state->IsMaximizedOrFullscreen()) { - window_state->Restore(); - } else { - window_state->Minimize(); - - // NOTE: Minimizing the window will cause this handler to be - // destroyed. So do not access anything from |this| from here. - return SYSTEM_GESTURE_END; - } - } - return SYSTEM_GESTURE_END; - } - - case ui::ET_GESTURE_PINCH_UPDATE: { - // The PINCH_UPDATE events contain incremental scaling updates. - pinch_factor_ *= event.details().scale(); - gfx::Rect bounds = - GetPhantomWindowScreenBounds(target_, event.location()); - if (phantom_state_ != PHANTOM_WINDOW_NORMAL || phantom_.IsShowing()) - phantom_.Show(bounds); - break; - } - - case ui::ET_GESTURE_MULTIFINGER_SWIPE: { - phantom_.Hide(); - pinch_factor_ = 1.0; - phantom_state_ = PHANTOM_WINDOW_NORMAL; - - if (event.details().swipe_left() || event.details().swipe_right()) { - // Snap for left/right swipes. - ui::ScopedLayerAnimationSettings settings( - target_->layer()->GetAnimator()); - internal::SnapSizer::SnapWindow(window_state, - event.details().swipe_left() ? internal::SnapSizer::LEFT_EDGE : - internal::SnapSizer::RIGHT_EDGE); - } else if (event.details().swipe_up()) { - if (!window_state->IsMaximizedOrFullscreen()) - window_state->Maximize(); - } else if (event.details().swipe_down()) { - window_state->Minimize(); - } else { - NOTREACHED() << "Swipe happened without a direction."; - } - break; - } - - default: - break; - } - - return SYSTEM_GESTURE_PROCESSED; -} - -gfx::Rect SystemPinchHandler::GetPhantomWindowScreenBounds( - aura::Window* window, - const gfx::Point& point) { - if (pinch_factor_ > kPinchThresholdForMaximize) { - phantom_state_ = PHANTOM_WINDOW_MAXIMIZED; - return ScreenAsh::ConvertRectToScreen( - target_->parent(), - ScreenAsh::GetMaximizedWindowBoundsInParent(target_)); - } - - if (pinch_factor_ < kPinchThresholdForMinimize) { - wm::WindowState* window_state = wm::GetWindowState(window); - if (window_state->IsMaximizedOrFullscreen()) { - if (window_state->HasRestoreBounds()) { - phantom_state_ = PHANTOM_WINDOW_MINIMIZED; - return window_state->GetRestoreBoundsInScreen(); - } - return window->bounds(); - } - - gfx::Rect rect = GetMinimizeAnimationTargetBoundsInScreen(target_); - if (!rect.IsEmpty()) - rect.Inset(-8, -8); - phantom_state_ = PHANTOM_WINDOW_MINIMIZED; - return rect; - } - - phantom_state_ = PHANTOM_WINDOW_NORMAL; - return window->bounds(); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/gestures/system_pinch_handler.h b/chromium/ash/wm/gestures/system_pinch_handler.h deleted file mode 100644 index d5c5a0eade9..00000000000 --- a/chromium/ash/wm/gestures/system_pinch_handler.h +++ /dev/null @@ -1,85 +0,0 @@ -// 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_GESTURES_SYSTEM_PINCH_HANDLER_H_ -#define ASH_WM_GESTURES_SYSTEM_PINCH_HANDLER_H_ - -#include "ash/wm/workspace/phantom_window_controller.h" - -namespace aura { -class Window; -} - -namespace gfx { -class Point; -} - -namespace ui { -class GestureEvent; -} - -namespace views { -class Widget; -} - -namespace ash { -namespace internal { - -enum SystemGestureStatus { - SYSTEM_GESTURE_PROCESSED, // The system gesture has been processed. - SYSTEM_GESTURE_IGNORED, // The system gesture was ignored. - SYSTEM_GESTURE_END, // Marks the end of the sytem gesture. -}; - -// This handles 4+ finger pinch gestures to maximize/minimize/restore windows. -class SystemPinchHandler { - public: - explicit SystemPinchHandler(aura::Window* target); - virtual ~SystemPinchHandler(); - - // Processes a gesture event. Returns SYSTEM_GESTURE_PROCESSED if the gesture - // event has been processed. Returns SYSTEM_GESTURE_END if the gesture event - // has been processed, and marks the end of the gesture sequence (i.e. the - // handler should receive no more input events). - SystemGestureStatus ProcessGestureEvent(const ui::GestureEvent& event); - - static const int kSystemGesturePoints; - - private: - // Returns the appropriate bounds for the phantom window depending on the - // state of the window, the state of the gesture sequence, and the current - // event location. - gfx::Rect GetPhantomWindowScreenBounds(aura::Window* window, - const gfx::Point& point); - - enum PhantomWindowState { - PHANTOM_WINDOW_NORMAL, - PHANTOM_WINDOW_MAXIMIZED, - PHANTOM_WINDOW_MINIMIZED, - }; - - aura::Window* target_; - views::Widget* widget_; - - // A phantom window is used to provide visual cues for - // pinch-to-resize/maximize/minimize gestures. - PhantomWindowController phantom_; - - // When the phantom window is in minimized or maximized state, moving the - // target window should not move the phantom window. So |phantom_state_| is - // used to track the state of the phantom window. - PhantomWindowState phantom_state_; - - // PINCH_UPDATE events include incremental pinch-amount. But it is necessary - // to keep track of the overall pinch-amount. |pinch_factor_| is used for - // that. - double pinch_factor_; - - DISALLOW_COPY_AND_ASSIGN(SystemPinchHandler); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_GESTURES_SYSTEM_PINCH_HANDLER_H_ diff --git a/chromium/ash/wm/gestures/tray_gesture_handler.cc b/chromium/ash/wm/gestures/tray_gesture_handler.cc deleted file mode 100644 index 0d2e8cfdd6d..00000000000 --- a/chromium/ash/wm/gestures/tray_gesture_handler.cc +++ /dev/null @@ -1,109 +0,0 @@ -// 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/gestures/tray_gesture_handler.h" - -#include "ash/shell.h" -#include "ash/system/tray/system_tray.h" -#include "ash/system/tray/system_tray_bubble.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/events/event.h" -#include "ui/gfx/transform.h" -#include "ui/views/widget/widget.h" - -const int kMinBubbleHeight = 13; - -namespace ash { -namespace internal { - -TrayGestureHandler::TrayGestureHandler() - : widget_(NULL), - gesture_drag_amount_(0) { - // TODO(oshima): Support multiple display case. - SystemTray* tray = Shell::GetInstance()->GetPrimarySystemTray(); - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - SystemTrayBubble* bubble = tray->GetSystemBubble(); - if (!bubble) - return; - bubble->bubble_view()->set_gesture_dragging(true); - widget_ = bubble->bubble_view()->GetWidget(); - widget_->AddObserver(this); - - gfx::Rect bounds = widget_->GetWindowBoundsInScreen(); - int height_change = bounds.height() - kMinBubbleHeight; - bounds.set_height(kMinBubbleHeight); - bounds.set_y(bounds.y() + height_change); - widget_->SetBounds(bounds); -} - -TrayGestureHandler::~TrayGestureHandler() { - if (widget_) - widget_->RemoveObserver(this); -} - -bool TrayGestureHandler::UpdateGestureDrag(const ui::GestureEvent& event) { - CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event.type()); - if (!widget_) - return false; - - gesture_drag_amount_ += event.details().scroll_y(); - if (gesture_drag_amount_ > 0 && gesture_drag_amount_ < kMinBubbleHeight) { - widget_->Close(); - return false; - } - - gfx::Rect bounds = widget_->GetWindowBoundsInScreen(); - int new_height = std::min( - kMinBubbleHeight + std::max(0, static_cast<int>(-gesture_drag_amount_)), - widget_->GetContentsView()->GetPreferredSize().height()); - int height_change = bounds.height() - new_height; - bounds.set_height(new_height); - bounds.set_y(bounds.y() + height_change); - widget_->SetBounds(bounds); - return true; -} - -void TrayGestureHandler::CompleteGestureDrag(const ui::GestureEvent& event) { - if (!widget_) - return; - - widget_->RemoveObserver(this); - - // Close the widget if it hasn't been dragged enough. - bool should_close = false; - int height = widget_->GetWindowBoundsInScreen().height(); - int preferred_height = - widget_->GetContentsView()->GetPreferredSize().height(); - if (event.type() == ui::ET_GESTURE_SCROLL_END) { - const float kMinThresholdGestureDrag = 0.4f; - if (height < preferred_height * kMinThresholdGestureDrag) - should_close = true; - } else if (event.type() == ui::ET_SCROLL_FLING_START) { - const float kMinThresholdGestureDragExposeFling = 0.25f; - const float kMinThresholdGestureFling = 1000.f; - if (height < preferred_height * kMinThresholdGestureDragExposeFling && - event.details().velocity_y() > -kMinThresholdGestureFling) - should_close = true; - } else { - NOTREACHED(); - } - - if (should_close) { - widget_->Close(); - } else { - SystemTrayBubble* bubble = - Shell::GetInstance()->GetPrimarySystemTray()->GetSystemBubble(); - if (bubble) - bubble->bubble_view()->set_gesture_dragging(false); - } -} - -void TrayGestureHandler::OnWidgetDestroying(views::Widget* widget) { - CHECK_EQ(widget_, widget); - widget_ = NULL; -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/gestures/tray_gesture_handler.h b/chromium/ash/wm/gestures/tray_gesture_handler.h deleted file mode 100644 index 34f033b35f0..00000000000 --- a/chromium/ash/wm/gestures/tray_gesture_handler.h +++ /dev/null @@ -1,48 +0,0 @@ -// 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_GESTURES_TRAY_GESTURE_HANDLER_H_ -#define ASH_WM_GESTURES_TRAY_GESTURE_HANDLER_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/views/widget/widget_observer.h" - -namespace ui { -class GestureEvent; -} - -namespace ash { -namespace internal { - -// Handles gesture events on the shelf to show the system tray bubble. -class TrayGestureHandler : public views::WidgetObserver { - public: - TrayGestureHandler(); - virtual ~TrayGestureHandler(); - - // Handles a gesture-update event and updates the dragging state of the tray - // bubble. Returns true if the handler can continue to process gesture events - // for the bubble. Returns false if it should no longer receive gesture - // events. - bool UpdateGestureDrag(const ui::GestureEvent& event); - - void CompleteGestureDrag(const ui::GestureEvent& event); - - private: - virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; - - // The widget for the tray-bubble. - views::Widget* widget_; - - // The amount that has been dragged. - float gesture_drag_amount_; - - DISALLOW_COPY_AND_ASSIGN(TrayGestureHandler); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_GESTURES_TRAY_GESTURE_HANDLER_H_ diff --git a/chromium/ash/wm/gestures/two_finger_drag_handler.cc b/chromium/ash/wm/gestures/two_finger_drag_handler.cc deleted file mode 100644 index 5cf98a68ab8..00000000000 --- a/chromium/ash/wm/gestures/two_finger_drag_handler.cc +++ /dev/null @@ -1,216 +0,0 @@ -// 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/gestures/two_finger_drag_handler.h" - -#include "ash/wm/window_resizer.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "ui/aura/client/window_types.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/events/event.h" -#include "ui/events/event_constants.h" - -namespace { - -bool IsTopEdge(int component) { - return component == HTTOPLEFT || - component == HTTOP || - component == HTTOPRIGHT; -} - -bool IsBottomEdge(int component) { - return component == HTBOTTOMLEFT || - component == HTBOTTOM || - component == HTBOTTOMRIGHT; -} - -bool IsRightEdge(int component) { - return component == HTTOPRIGHT || - component == HTRIGHT || - component == HTBOTTOMRIGHT; -} - -bool IsLeftEdge(int component) { - return component == HTTOPLEFT || - component == HTLEFT || - component == HTBOTTOMLEFT; -} - -bool IsSomeEdge(int component) { - switch (component) { - case HTTOPLEFT: - case HTTOP: - case HTTOPRIGHT: - case HTRIGHT: - case HTBOTTOMRIGHT: - case HTBOTTOM: - case HTBOTTOMLEFT: - case HTLEFT: - return true; - } - return false; -} - -// Returns whether a window-move should be allowed depending on the hit-test -// results of the two fingers. -bool WindowComponentsAllowMoving(int component1, int component2) { - return ((IsTopEdge(component1) && IsTopEdge(component2)) || - (IsBottomEdge(component1) && IsBottomEdge(component2)) || - (IsLeftEdge(component1) && IsLeftEdge(component2)) || - (IsRightEdge(component1) && IsRightEdge(component2)) || - (!IsSomeEdge(component1) && !IsSomeEdge(component2))); -} - -} // namespace - -namespace ash { -namespace internal { - -TwoFingerDragHandler::TwoFingerDragHandler() - : first_finger_hittest_(HTNOWHERE), - in_gesture_drag_(false) { -} - -TwoFingerDragHandler::~TwoFingerDragHandler() { -} - -bool TwoFingerDragHandler::ProcessGestureEvent(aura::Window* target, - const ui::GestureEvent& event) { - if (!target->delegate()) - return false; - - if (event.type() == ui::ET_GESTURE_BEGIN && - event.details().touch_points() == 1) { - first_finger_hittest_ = - target->delegate()->GetNonClientComponent(event.location()); - return false; - } - - wm::WindowState* window_state = wm::GetWindowState(target); - - if (event.type() == ui::ET_GESTURE_BEGIN && - event.details().touch_points() == 2) { - if (!in_gesture_drag_ && window_state->IsNormalShowState() && - target->type() == aura::client::WINDOW_TYPE_NORMAL) { - if (WindowComponentsAllowMoving(first_finger_hittest_, - target->delegate()->GetNonClientComponent(event.location()))) { - in_gesture_drag_ = true; - target->AddObserver(this); - // Only create a new WindowResizer if one doesn't already exist - // for the target window. - window_resizer_ = CreateWindowResizer( - target, - event.details().bounding_box().CenterPoint(), - HTCAPTION, - aura::client::WINDOW_MOVE_SOURCE_TOUCH); - return true; - } - } - - return false; - } - - if (!in_gesture_drag_) { - // Consume all two-finger gestures on a normal window. - return event.details().touch_points() == 2 && - target->type() == aura::client::WINDOW_TYPE_NORMAL && - window_state->IsNormalShowState(); - } - // Since |in_gesture_drag_| is true a resizer was either created above or - // it was created elsewhere and can be found in |window_state|. - WindowResizer* any_window_resizer = window_resizer_ ? - window_resizer_.get() : window_state->window_resizer(); - DCHECK(any_window_resizer); - - if (target != any_window_resizer->GetTarget()) - return false; - - switch (event.type()) { - case ui::ET_GESTURE_BEGIN: - if (event.details().touch_points() > 2) { - if (window_resizer_) - window_resizer_->CompleteDrag(event.flags()); - Reset(target); - } - return false; - - case ui::ET_GESTURE_SCROLL_BEGIN: - case ui::ET_GESTURE_PINCH_BEGIN: - case ui::ET_GESTURE_SCROLL_END: - return true; - - case ui::ET_GESTURE_MULTIFINGER_SWIPE: { - // For a swipe, the window either maximizes, minimizes, or snaps. In this - // case, complete the drag, and do the appropriate action. - if (window_resizer_) - window_resizer_->CompleteDrag(event.flags()); - Reset(target); - if (event.details().swipe_up()) { - if (window_state->CanMaximize()) - window_state->Maximize(); - } else if (event.details().swipe_down() && window_state->CanMinimize()) { - window_state->Minimize(); - } else if (window_state->CanSnap()) { - ui::ScopedLayerAnimationSettings scoped_setter( - target->layer()->GetAnimator()); - scoped_setter.SetPreemptionStrategy( - ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); - internal::SnapSizer::SnapWindow(window_state, - event.details().swipe_left() ? internal::SnapSizer::LEFT_EDGE : - internal::SnapSizer::RIGHT_EDGE); - } - return true; - } - - case ui::ET_GESTURE_PINCH_UPDATE: - case ui::ET_GESTURE_SCROLL_UPDATE: - any_window_resizer->Drag(event.details().bounding_box().CenterPoint(), - event.flags()); - return true; - - case ui::ET_GESTURE_PINCH_END: - if (window_resizer_) - window_resizer_->CompleteDrag(event.flags()); - Reset(target); - return true; - - case ui::ET_GESTURE_END: - if (event.details().touch_points() == 2) { - if (window_resizer_) - window_resizer_->RevertDrag(); - Reset(target); - return true; - } - break; - - default: - break; - } - - return false; -} - -void TwoFingerDragHandler::Reset(aura::Window* window) { - window->RemoveObserver(this); - window_resizer_.reset(); - in_gesture_drag_ = false; -} - -void TwoFingerDragHandler::OnWindowVisibilityChanged(aura::Window* window, - bool visible) { - Reset(window); -} - -void TwoFingerDragHandler::OnWindowDestroying(aura::Window* window) { - Reset(window); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/gestures/two_finger_drag_handler.h b/chromium/ash/wm/gestures/two_finger_drag_handler.h deleted file mode 100644 index 11b7f51e582..00000000000 --- a/chromium/ash/wm/gestures/two_finger_drag_handler.h +++ /dev/null @@ -1,58 +0,0 @@ -// 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_GESTURES_TWO_FINGER_DRAG_HANDLER_H_ -#define ASH_WM_GESTURES_TWO_FINGER_DRAG_HANDLER_H_ - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/window_observer.h" - -namespace aura { -class Window; -} - -namespace ui { -class GestureEvent; -} - -namespace ash { - -class WindowResizer; - -namespace internal { - -// This handles 2-finger drag gestures to move toplevel windows. -class TwoFingerDragHandler : public aura::WindowObserver { - public: - TwoFingerDragHandler(); - virtual ~TwoFingerDragHandler(); - - // Processes a gesture event and starts a drag, or updates/ends an in-progress - // drag. Returns true if the event has been handled and should not be - // processed any farther, false otherwise. - bool ProcessGestureEvent(aura::Window* target, const ui::GestureEvent& event); - - private: - void Reset(aura::Window* window); - - // Overridden from aura::WindowObserver. - virtual void OnWindowVisibilityChanged(aura::Window* window, - bool visible) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - int first_finger_hittest_; - - // Set to true while a drag initiated with two-finger gesture is in progress. - bool in_gesture_drag_; - - scoped_ptr<WindowResizer> window_resizer_; - - DISALLOW_COPY_AND_ASSIGN(TwoFingerDragHandler); -}; - -} -} // namespace ash - -#endif // ASH_WM_GESTURES_TWO_FINGER_DRAG_HANDLER_H_ diff --git a/chromium/ash/wm/header_painter.cc b/chromium/ash/wm/header_painter.cc deleted file mode 100644 index bf87015b177..00000000000 --- a/chromium/ash/wm/header_painter.cc +++ /dev/null @@ -1,583 +0,0 @@ -// Copyright 2013 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/header_painter.h" - -#include <vector> - -#include "ash/root_window_controller.h" -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/solo_window_tracker.h" -#include "base/logging.h" // DCHECK -#include "grit/ash_resources.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkColor.h" -#include "third_party/skia/include/core/SkPaint.h" -#include "third_party/skia/include/core/SkPath.h" -#include "ui/aura/window.h" -#include "ui/base/hit_test.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/base/theme_provider.h" -#include "ui/gfx/animation/slide_animation.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/screen.h" -#include "ui/gfx/skia_util.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -using aura::Window; -using views::Widget; - -namespace { -// Space between left edge of window and popup window icon. -const int kIconOffsetX = 9; -// Height and width of window icon. -const int kIconSize = 16; -// Space between the title text and the caption buttons. -const int kTitleLogoSpacing = 5; -// Space between window icon and title text. -const int kTitleIconOffsetX = 5; -// Space between window edge and title text, when there is no icon. -const int kTitleNoIconOffsetX = 8; -// Color for the non-maximized window title text. -const SkColor kNonMaximizedWindowTitleTextColor = SkColorSetRGB(40, 40, 40); -// Color for the maximized window title text. -const SkColor kMaximizedWindowTitleTextColor = SK_ColorWHITE; -// Size of header/content separator line below the header image. -const int kHeaderContentSeparatorSize = 1; -// Color of header bottom edge line. -const SkColor kHeaderContentSeparatorColor = SkColorSetRGB(128, 128, 128); -// In the pre-Ash era the web content area had a frame along the left edge, so -// user-generated theme images for the new tab page assume they are shifted -// right relative to the header. Now that we have removed the left edge frame -// we need to copy the theme image for the window header from a few pixels -// inset to preserve alignment with the NTP image, or else we'll break a bunch -// of existing themes. We do something similar on OS X for the same reason. -const int kThemeFrameImageInsetX = 5; -// Duration of crossfade animation for activating and deactivating frame. -const int kActivationCrossfadeDurationMs = 200; -// Alpha/opacity value for fully-opaque headers. -const int kFullyOpaque = 255; - -// Tiles an image into an area, rounding the top corners. Samples |image| -// starting |image_inset_x| pixels from the left of the image. -void TileRoundRect(gfx::Canvas* canvas, - const gfx::ImageSkia& image, - const SkPaint& paint, - const gfx::Rect& bounds, - int top_left_corner_radius, - int top_right_corner_radius, - int image_inset_x) { - SkRect rect = gfx::RectToSkRect(bounds); - const SkScalar kTopLeftRadius = SkIntToScalar(top_left_corner_radius); - const SkScalar kTopRightRadius = SkIntToScalar(top_right_corner_radius); - SkScalar radii[8] = { - kTopLeftRadius, kTopLeftRadius, // top-left - kTopRightRadius, kTopRightRadius, // top-right - 0, 0, // bottom-right - 0, 0}; // bottom-left - SkPath path; - path.addRoundRect(rect, radii, SkPath::kCW_Direction); - canvas->DrawImageInPath(image, -image_inset_x, 0, path, paint); -} - -// Tiles |frame_image| and |frame_overlay_image| into an area, rounding the top -// corners. -void PaintFrameImagesInRoundRect(gfx::Canvas* canvas, - const gfx::ImageSkia* frame_image, - const gfx::ImageSkia* frame_overlay_image, - const SkPaint& paint, - const gfx::Rect& bounds, - int corner_radius, - int image_inset_x) { - SkXfermode::Mode normal_mode; - SkXfermode::AsMode(NULL, &normal_mode); - - // If |paint| is using an unusual SkXfermode::Mode (this is the case while - // crossfading), we must create a new canvas to overlay |frame_image| and - // |frame_overlay_image| using |normal_mode| and then paint the result - // using the unusual mode. We try to avoid this because creating a new - // browser-width canvas is expensive. - bool fast_path = (!frame_overlay_image || - SkXfermode::IsMode(paint.getXfermode(), normal_mode)); - if (fast_path) { - TileRoundRect(canvas, *frame_image, paint, bounds, corner_radius, - corner_radius, image_inset_x); - - if (frame_overlay_image) { - // Adjust |bounds| such that |frame_overlay_image| is not tiled. - gfx::Rect overlay_bounds = bounds; - overlay_bounds.Intersect( - gfx::Rect(bounds.origin(), frame_overlay_image->size())); - int top_left_corner_radius = corner_radius; - int top_right_corner_radius = corner_radius; - if (overlay_bounds.width() < bounds.width() - corner_radius) - top_right_corner_radius = 0; - TileRoundRect(canvas, *frame_overlay_image, paint, overlay_bounds, - top_left_corner_radius, top_right_corner_radius, 0); - } - } else { - gfx::Canvas temporary_canvas(bounds.size(), canvas->image_scale(), false); - temporary_canvas.TileImageInt(*frame_image, - image_inset_x, 0, - 0, 0, - bounds.width(), bounds.height()); - temporary_canvas.DrawImageInt(*frame_overlay_image, 0, 0); - TileRoundRect(canvas, gfx::ImageSkia(temporary_canvas.ExtractImageRep()), - paint, bounds, corner_radius, corner_radius, 0); - } -} - -} // namespace - -namespace ash { - -// static -int HeaderPainter::kActiveWindowOpacity = 255; // 1.0 -int HeaderPainter::kInactiveWindowOpacity = 255; // 1.0 -int HeaderPainter::kSoloWindowOpacity = 77; // 0.3 - -/////////////////////////////////////////////////////////////////////////////// -// HeaderPainter, public: - -HeaderPainter::HeaderPainter() - : frame_(NULL), - header_view_(NULL), - window_icon_(NULL), - caption_button_container_(NULL), - window_(NULL), - header_height_(0), - top_left_corner_(NULL), - top_edge_(NULL), - top_right_corner_(NULL), - header_left_edge_(NULL), - header_right_edge_(NULL), - previous_theme_frame_id_(0), - previous_theme_frame_overlay_id_(0), - previous_opacity_(0), - crossfade_theme_frame_id_(0), - crossfade_theme_frame_overlay_id_(0), - crossfade_opacity_(0) {} - -HeaderPainter::~HeaderPainter() { - // Sometimes we are destroyed before the window closes, so ensure we clean up. - if (window_) - window_->RemoveObserver(this); -} - -void HeaderPainter::Init( - views::Widget* frame, - views::View* header_view, - views::View* window_icon, - FrameCaptionButtonContainerView* caption_button_container) { - DCHECK(frame); - DCHECK(header_view); - // window_icon may be NULL. - DCHECK(caption_button_container); - frame_ = frame; - header_view_ = header_view; - window_icon_ = window_icon; - caption_button_container_ = caption_button_container; - - // Window frame image parts. - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - top_left_corner_ = - rb.GetImageNamed(IDR_AURA_WINDOW_HEADER_SHADE_TOP_LEFT).ToImageSkia(); - top_edge_ = - rb.GetImageNamed(IDR_AURA_WINDOW_HEADER_SHADE_TOP).ToImageSkia(); - top_right_corner_ = - rb.GetImageNamed(IDR_AURA_WINDOW_HEADER_SHADE_TOP_RIGHT).ToImageSkia(); - header_left_edge_ = - rb.GetImageNamed(IDR_AURA_WINDOW_HEADER_SHADE_LEFT).ToImageSkia(); - header_right_edge_ = - rb.GetImageNamed(IDR_AURA_WINDOW_HEADER_SHADE_RIGHT).ToImageSkia(); - - window_ = frame->GetNativeWindow(); - - // Observer removes itself in OnWindowDestroying() below, or in the destructor - // if we go away before the window. - window_->AddObserver(this); - - // Solo-window header updates are handled by the WorkspaceLayoutManager when - // this window is added to the desktop. -} - -// static -gfx::Rect HeaderPainter::GetBoundsForClientView( - int header_height, - const gfx::Rect& window_bounds) { - gfx::Rect client_bounds(window_bounds); - client_bounds.Inset(0, header_height, 0, 0); - return client_bounds; -} - -// static -gfx::Rect HeaderPainter::GetWindowBoundsForClientBounds( - int header_height, - const gfx::Rect& client_bounds) { - gfx::Rect window_bounds(client_bounds); - window_bounds.Inset(0, -header_height, 0, 0); - if (window_bounds.y() < 0) - window_bounds.set_y(0); - return window_bounds; -} - -int HeaderPainter::NonClientHitTest(const gfx::Point& point) const { - gfx::Point point_in_header_view(point); - views::View::ConvertPointFromWidget(header_view_, &point_in_header_view); - if (!GetHeaderLocalBounds().Contains(point_in_header_view)) - return HTNOWHERE; - if (caption_button_container_->visible()) { - gfx::Point point_in_caption_button_container(point); - views::View::ConvertPointFromWidget(caption_button_container_, - &point_in_caption_button_container); - int component = caption_button_container_->NonClientHitTest( - point_in_caption_button_container); - if (component != HTNOWHERE) - return component; - } - // Caption is a safe default. - return HTCAPTION; -} - -int HeaderPainter::GetMinimumHeaderWidth() const { - // Ensure we have enough space for the window icon and buttons. We allow - // the title string to collapse to zero width. - return GetTitleOffsetX() + - caption_button_container_->GetMinimumSize().width(); -} - -int HeaderPainter::GetRightInset() const { - return caption_button_container_->GetPreferredSize().width(); -} - -int HeaderPainter::GetThemeBackgroundXInset() const { - return kThemeFrameImageInsetX; -} - -void HeaderPainter::PaintHeader(gfx::Canvas* canvas, - HeaderMode header_mode, - int theme_frame_id, - int theme_frame_overlay_id) { - bool initial_paint = (previous_theme_frame_id_ == 0); - if (!initial_paint && - (previous_theme_frame_id_ != theme_frame_id || - previous_theme_frame_overlay_id_ != theme_frame_overlay_id)) { - aura::Window* parent = frame_->GetNativeWindow()->parent(); - // Don't animate the header if the parent (a workspace) is already - // animating. Doing so results in continually painting during the animation - // and gives a slower frame rate. - // TODO(sky): expose a better way to determine this rather than assuming - // the parent is a workspace. - bool parent_animating = parent && - (parent->layer()->GetAnimator()->IsAnimatingProperty( - ui::LayerAnimationElement::OPACITY) || - parent->layer()->GetAnimator()->IsAnimatingProperty( - ui::LayerAnimationElement::VISIBILITY)); - if (!parent_animating) { - crossfade_animation_.reset(new gfx::SlideAnimation(this)); - crossfade_theme_frame_id_ = previous_theme_frame_id_; - crossfade_theme_frame_overlay_id_ = previous_theme_frame_overlay_id_; - crossfade_opacity_ = previous_opacity_; - crossfade_animation_->SetSlideDuration(kActivationCrossfadeDurationMs); - crossfade_animation_->Show(); - } else { - crossfade_animation_.reset(); - } - } - - int opacity = - GetHeaderOpacity(header_mode, theme_frame_id, theme_frame_overlay_id); - ui::ThemeProvider* theme_provider = frame_->GetThemeProvider(); - gfx::ImageSkia* theme_frame = theme_provider->GetImageSkiaNamed( - theme_frame_id); - gfx::ImageSkia* theme_frame_overlay = NULL; - if (theme_frame_overlay_id != 0) { - theme_frame_overlay = theme_provider->GetImageSkiaNamed( - theme_frame_overlay_id); - } - - int corner_radius = GetHeaderCornerRadius(); - SkPaint paint; - - if (crossfade_animation_.get() && crossfade_animation_->is_animating()) { - gfx::ImageSkia* crossfade_theme_frame = - theme_provider->GetImageSkiaNamed(crossfade_theme_frame_id_); - gfx::ImageSkia* crossfade_theme_frame_overlay = NULL; - if (crossfade_theme_frame_overlay_id_ != 0) { - crossfade_theme_frame_overlay = theme_provider->GetImageSkiaNamed( - crossfade_theme_frame_overlay_id_); - } - if (!crossfade_theme_frame || - (crossfade_theme_frame_overlay_id_ != 0 && - !crossfade_theme_frame_overlay)) { - // Reset the animation. This case occurs when the user switches the theme - // that they are using. - crossfade_animation_.reset(); - paint.setAlpha(opacity); - } else { - double current_value = crossfade_animation_->GetCurrentValue(); - int old_alpha = (1 - current_value) * crossfade_opacity_; - int new_alpha = current_value * opacity; - - // Draw the old header background, clipping the corners to be rounded. - paint.setAlpha(old_alpha); - paint.setXfermodeMode(SkXfermode::kPlus_Mode); - PaintFrameImagesInRoundRect(canvas, - crossfade_theme_frame, - crossfade_theme_frame_overlay, - paint, - GetHeaderLocalBounds(), - corner_radius, - GetThemeBackgroundXInset()); - - paint.setAlpha(new_alpha); - } - } else { - paint.setAlpha(opacity); - } - - // Draw the header background, clipping the corners to be rounded. - PaintFrameImagesInRoundRect(canvas, - theme_frame, - theme_frame_overlay, - paint, - GetHeaderLocalBounds(), - corner_radius, - GetThemeBackgroundXInset()); - - previous_theme_frame_id_ = theme_frame_id; - previous_theme_frame_overlay_id_ = theme_frame_overlay_id; - previous_opacity_ = opacity; - - // We don't need the extra lightness in the edges when we're at the top edge - // of the screen or when the header's corners are not rounded. - // - // TODO(sky): this isn't quite right. What we really want is a method that - // returns bounds ignoring transforms on certain windows (such as workspaces) - // and is relative to the root. - if (frame_->GetNativeWindow()->bounds().y() == 0 || corner_radius == 0) - return; - - // Draw the top corners and edge. - int top_left_width = top_left_corner_->width(); - int top_left_height = top_left_corner_->height(); - canvas->DrawImageInt(*top_left_corner_, - 0, 0, top_left_width, top_left_height, - 0, 0, top_left_width, top_left_height, - false); - canvas->TileImageInt(*top_edge_, - top_left_width, - 0, - header_view_->width() - top_left_width - top_right_corner_->width(), - top_edge_->height()); - int top_right_height = top_right_corner_->height(); - canvas->DrawImageInt(*top_right_corner_, - 0, 0, - top_right_corner_->width(), top_right_height, - header_view_->width() - top_right_corner_->width(), 0, - top_right_corner_->width(), top_right_height, - false); - - // Header left edge. - int header_left_height = theme_frame->height() - top_left_height; - canvas->TileImageInt(*header_left_edge_, - 0, top_left_height, - header_left_edge_->width(), header_left_height); - - // Header right edge. - int header_right_height = theme_frame->height() - top_right_height; - canvas->TileImageInt(*header_right_edge_, - header_view_->width() - header_right_edge_->width(), - top_right_height, - header_right_edge_->width(), - header_right_height); - - // We don't draw edges around the content area. Web content goes flush - // to the edge of the window. -} - -void HeaderPainter::PaintHeaderContentSeparator(gfx::Canvas* canvas) { - canvas->FillRect(gfx::Rect(0, - header_height_ - kHeaderContentSeparatorSize, - header_view_->width(), - kHeaderContentSeparatorSize), - kHeaderContentSeparatorColor); -} - -int HeaderPainter::HeaderContentSeparatorSize() const { - return kHeaderContentSeparatorSize; -} - -void HeaderPainter::PaintTitleBar(gfx::Canvas* canvas, - const gfx::Font& title_font) { - // The window icon is painted by its own views::View. - views::WidgetDelegate* delegate = frame_->widget_delegate(); - if (delegate && delegate->ShouldShowWindowTitle()) { - gfx::Rect title_bounds = GetTitleBounds(title_font); - SkColor title_color = (frame_->IsMaximized() || frame_->IsFullscreen()) ? - kMaximizedWindowTitleTextColor : kNonMaximizedWindowTitleTextColor; - canvas->DrawStringInt(delegate->GetWindowTitle(), - title_font, - title_color, - header_view_->GetMirroredXForRect(title_bounds), - title_bounds.y(), - title_bounds.width(), - title_bounds.height(), - gfx::Canvas::NO_SUBPIXEL_RENDERING); - } -} - -void HeaderPainter::LayoutHeader(bool shorter_layout) { - caption_button_container_->set_header_style(shorter_layout ? - FrameCaptionButtonContainerView::HEADER_STYLE_SHORT : - FrameCaptionButtonContainerView::HEADER_STYLE_TALL); - caption_button_container_->Layout(); - - gfx::Size caption_button_container_size = - caption_button_container_->GetPreferredSize(); - caption_button_container_->SetBounds( - header_view_->width() - caption_button_container_size.width(), - 0, - caption_button_container_size.width(), - caption_button_container_size.height()); - - if (window_icon_) { - // Vertically center the window icon with respect to the caption button - // container. - int icon_offset_y = - GetCaptionButtonContainerCenterY() - window_icon_->height() / 2; - window_icon_->SetBounds(kIconOffsetX, icon_offset_y, kIconSize, kIconSize); - } -} - -void HeaderPainter::SchedulePaintForTitle(const gfx::Font& title_font) { - header_view_->SchedulePaintInRect(GetTitleBounds(title_font)); -} - -void HeaderPainter::OnThemeChanged() { - // We do not cache the images for |previous_theme_frame_id_| and - // |previous_theme_frame_overlay_id_|. Changing the theme changes the images - // returned from ui::ThemeProvider for |previous_theme_frame_id_| - // and |previous_theme_frame_overlay_id_|. Reset the image ids to prevent - // starting a crossfade animation with these images. - previous_theme_frame_id_ = 0; - previous_theme_frame_overlay_id_ = 0; - - if (crossfade_animation_.get() && crossfade_animation_->is_animating()) { - crossfade_animation_.reset(); - header_view_->SchedulePaintInRect(GetHeaderLocalBounds()); - } -} - -/////////////////////////////////////////////////////////////////////////////// -// aura::WindowObserver overrides: - -void HeaderPainter::OnWindowDestroying(aura::Window* destroying) { - DCHECK_EQ(window_, destroying); - - // Must be removed here and not in the destructor, as the aura::Window is - // already destroyed when our destructor runs. - window_->RemoveObserver(this); - - window_ = NULL; -} - -void HeaderPainter::OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - // TODO(sky): this isn't quite right. What we really want is a method that - // returns bounds ignoring transforms on certain windows (such as workspaces). - if ((!frame_->IsMaximized() && !frame_->IsFullscreen()) && - ((old_bounds.y() == 0 && new_bounds.y() != 0) || - (old_bounds.y() != 0 && new_bounds.y() == 0))) { - SchedulePaintForHeader(); - } -} - -/////////////////////////////////////////////////////////////////////////////// -// gfx::AnimationDelegate overrides: - -void HeaderPainter::AnimationProgressed(const gfx::Animation* animation) { - header_view_->SchedulePaintInRect(GetHeaderLocalBounds()); -} - -/////////////////////////////////////////////////////////////////////////////// -// HeaderPainter, private: - -gfx::Rect HeaderPainter::GetHeaderLocalBounds() const { - return gfx::Rect(header_view_->width(), header_height_); -} - -int HeaderPainter::GetTitleOffsetX() const { - return window_icon_ ? - window_icon_->bounds().right() + kTitleIconOffsetX : - kTitleNoIconOffsetX; -} - -int HeaderPainter::GetCaptionButtonContainerCenterY() const { - return caption_button_container_->y() + - caption_button_container_->height() / 2; -} - -int HeaderPainter::GetHeaderCornerRadius() const { - bool square_corners = (frame_->IsMaximized() || frame_->IsFullscreen()); - const int kCornerRadius = 2; - return square_corners ? 0 : kCornerRadius; -} - -int HeaderPainter::GetHeaderOpacity( - HeaderMode header_mode, - int theme_frame_id, - int theme_frame_overlay_id) const { - // User-provided themes are painted fully opaque. - ui::ThemeProvider* theme_provider = frame_->GetThemeProvider(); - if (theme_provider->HasCustomImage(theme_frame_id) || - (theme_frame_overlay_id != 0 && - theme_provider->HasCustomImage(theme_frame_overlay_id))) { - return kFullyOpaque; - } - - // Maximized and fullscreen windows are fully opaque. - if (frame_->IsMaximized() || frame_->IsFullscreen()) - return kFullyOpaque; - - // Solo header is very transparent. - ash::SoloWindowTracker* solo_window_tracker = - internal::RootWindowController::ForWindow(window_)->solo_window_tracker(); - if (solo_window_tracker && - solo_window_tracker->GetWindowWithSoloHeader() == window_) { - return kSoloWindowOpacity; - } - - // Otherwise, change transparency based on window activation status. - if (header_mode == ACTIVE) - return kActiveWindowOpacity; - return kInactiveWindowOpacity; -} - -void HeaderPainter::SchedulePaintForHeader() { - int top_left_height = top_left_corner_->height(); - int top_right_height = top_right_corner_->height(); - header_view_->SchedulePaintInRect( - gfx::Rect(0, 0, header_view_->width(), - std::max(top_left_height, top_right_height))); -} - -gfx::Rect HeaderPainter::GetTitleBounds(const gfx::Font& title_font) { - int title_x = GetTitleOffsetX(); - // Center the text with respect to the caption button container. This way it - // adapts to the caption button height and aligns exactly with the window - // icon. Don't use |window_icon_| for this computation as it may be NULL. - int title_y = GetCaptionButtonContainerCenterY() - title_font.GetHeight() / 2; - return gfx::Rect( - title_x, - std::max(0, title_y), - std::max(0, caption_button_container_->x() - kTitleLogoSpacing - title_x), - title_font.GetHeight()); -} - -} // namespace ash diff --git a/chromium/ash/wm/header_painter.h b/chromium/ash/wm/header_painter.h deleted file mode 100644 index accc6e370d6..00000000000 --- a/chromium/ash/wm/header_painter.h +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2013 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_HEADER_PAINTER_H_ -#define ASH_WM_HEADER_PAINTER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" // OVERRIDE -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/animation/animation_delegate.h" -#include "ui/gfx/rect.h" - -namespace aura { -class Window; -} -namespace gfx { -class Canvas; -class Font; -class ImageSkia; -class Point; -class Size; -class SlideAnimation; -} -namespace views { -class View; -class Widget; -} - -namespace ash { -class FrameCaptionButtonContainerView; - -// Helper class for painting the window header. -class ASH_EXPORT HeaderPainter : public aura::WindowObserver, - public gfx::AnimationDelegate { - public: - // Opacity values for the window header in various states, from 0 to 255. - static int kActiveWindowOpacity; - static int kInactiveWindowOpacity; - static int kSoloWindowOpacity; - - enum HeaderMode { - ACTIVE, - INACTIVE - }; - - HeaderPainter(); - virtual ~HeaderPainter(); - - // None of the parameters are owned. - void Init(views::Widget* frame, - views::View* header_view, - views::View* window_icon, - FrameCaptionButtonContainerView* caption_button_container); - - // Returns the bounds of the client view for a window with |header_height| - // and |window_bounds|. The return value and |window_bounds| are in the - // views::NonClientView's coordinates. - static gfx::Rect GetBoundsForClientView(int header_height, - const gfx::Rect& window_bounds); - - // Returns the bounds of the window given |header_height| and |client_bounds|. - // The return value and |client_bounds| are in the views::NonClientView's - // coordinates. - static gfx::Rect GetWindowBoundsForClientBounds( - int header_height, - const gfx::Rect& client_bounds); - - // Determines the window HT* code at |point|. Returns HTNOWHERE if |point| is - // not within the top |header_height_| of |header_view_|. |point| is in the - // coordinates of |header_view_|'s widget. The client view must be hittested - // before calling this method because a browser's tabs are in the top - // |header_height_| of |header_view_|. - int NonClientHitTest(const gfx::Point& point) const; - - // Returns the header's minimum width. - int GetMinimumHeaderWidth() const; - - // Returns the inset from the right edge. - int GetRightInset() const; - - // Returns the amount that the theme background should be inset. - int GetThemeBackgroundXInset() const; - - // Paints the header. - // |theme_frame_overlay_id| is 0 if no overlay image should be used. - void PaintHeader(gfx::Canvas* canvas, - HeaderMode header_mode, - int theme_frame_id, - int theme_frame_overlay_id); - - // Paints the header/content separator line. Exists as a separate function - // because some windows with complex headers (e.g. browsers with tab strips) - // need to draw their own line. - void PaintHeaderContentSeparator(gfx::Canvas* canvas); - - // Returns size of the header/content separator line in pixels. - int HeaderContentSeparatorSize() const; - - // Paint the title bar, primarily the title string. - void PaintTitleBar(gfx::Canvas* canvas, const gfx::Font& title_font); - - // Performs layout for the header based on whether we want the shorter - // appearance. |shorter_layout| is typically used for maximized windows, but - // not always. - void LayoutHeader(bool shorter_layout); - - // Sets the height of the header. The height of the header affects painting, - // and non client hit tests. It does not affect layout. - void set_header_height(int header_height) { - header_height_ = header_height; - } - - // Returns the header height. - int header_height() const { - return header_height_; - } - - // Schedule a re-paint of the entire title. - void SchedulePaintForTitle(const gfx::Font& title_font); - - // Called when the browser theme changes. - void OnThemeChanged(); - - // aura::WindowObserver overrides: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - virtual void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - - // Overridden from gfx::AnimationDelegate - virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; - - private: - FRIEND_TEST_ALL_PREFIXES(HeaderPainterTest, GetHeaderOpacity); - FRIEND_TEST_ALL_PREFIXES(HeaderPainterTest, TitleIconAlignment); - - // Returns the header bounds in the coordinates of |header_view_|. The header - // is assumed to be positioned at the top left corner of |header_view_| and to - // have the same width as |header_view_|. - gfx::Rect GetHeaderLocalBounds() const; - - // Returns the offset between window left edge and title string. - int GetTitleOffsetX() const; - - // Returns the vertical center of the caption button container in window - // coordinates. - int GetCaptionButtonContainerCenterY() const; - - // Returns the opacity value used to paint the header. - // |theme_frame_overlay_id| is 0 if no overlay image is used. - int GetHeaderOpacity(HeaderMode header_mode, - int theme_frame_id, - int theme_frame_overlay_id) const; - - // Returns the radius of the header's top corners. - int GetHeaderCornerRadius() const; - - // Schedules a paint for the header. Used when transitioning from no header to - // a header (or other way around). - void SchedulePaintForHeader(); - - // Get the bounds for the title. The provided |title_font| is used to - // determine the correct dimensions. - gfx::Rect GetTitleBounds(const gfx::Font& title_font); - - // Not owned - views::Widget* frame_; - views::View* header_view_; - views::View* window_icon_; // May be NULL. - FrameCaptionButtonContainerView* caption_button_container_; - aura::Window* window_; - - // The height of the header. - int header_height_; - - // Window frame header/caption parts. - const gfx::ImageSkia* top_left_corner_; - const gfx::ImageSkia* top_edge_; - const gfx::ImageSkia* top_right_corner_; - const gfx::ImageSkia* header_left_edge_; - const gfx::ImageSkia* header_right_edge_; - - // Image ids and opacity last used for painting header. - int previous_theme_frame_id_; - int previous_theme_frame_overlay_id_; - int previous_opacity_; - - // Image ids and opacity we are crossfading from. - int crossfade_theme_frame_id_; - int crossfade_theme_frame_overlay_id_; - int crossfade_opacity_; - - scoped_ptr<gfx::SlideAnimation> crossfade_animation_; - - DISALLOW_COPY_AND_ASSIGN(HeaderPainter); -}; - -} // namespace ash - -#endif // ASH_WM_HEADER_PAINTER_H_ diff --git a/chromium/ash/wm/header_painter_unittest.cc b/chromium/ash/wm/header_painter_unittest.cc deleted file mode 100644 index 8ce8917a581..00000000000 --- a/chromium/ash/wm/header_painter_unittest.cc +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2013 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/header_painter.h" - -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/window_state.h" -#include "base/memory/scoped_ptr.h" -#include "grit/ash_resources.h" -#include "ui/gfx/font.h" -#include "ui/views/widget/widget.h" -#include "ui/views/window/non_client_view.h" - -using ash::HeaderPainter; -using views::NonClientFrameView; -using views::Widget; - -namespace { - -// Modifies the values of kInactiveWindowOpacity, kActiveWindowOpacity, and -// kSoloWindowOpacity for the lifetime of the class. This is useful so that -// the constants each have different values. -class ScopedOpacityConstantModifier { - public: - ScopedOpacityConstantModifier() - : initial_active_window_opacity_( - ash::HeaderPainter::kActiveWindowOpacity), - initial_inactive_window_opacity_( - ash::HeaderPainter::kInactiveWindowOpacity), - initial_solo_window_opacity_(ash::HeaderPainter::kSoloWindowOpacity) { - ash::HeaderPainter::kActiveWindowOpacity = 100; - ash::HeaderPainter::kInactiveWindowOpacity = 120; - ash::HeaderPainter::kSoloWindowOpacity = 140; - } - ~ScopedOpacityConstantModifier() { - ash::HeaderPainter::kActiveWindowOpacity = initial_active_window_opacity_; - ash::HeaderPainter::kInactiveWindowOpacity = - initial_inactive_window_opacity_; - ash::HeaderPainter::kSoloWindowOpacity = initial_solo_window_opacity_; - } - - private: - int initial_active_window_opacity_; - int initial_inactive_window_opacity_; - int initial_solo_window_opacity_; - - DISALLOW_COPY_AND_ASSIGN(ScopedOpacityConstantModifier); -}; - -// Creates a new HeaderPainter with empty buttons. Caller owns the memory. -HeaderPainter* CreateTestPainter(Widget* widget) { - HeaderPainter* painter = new HeaderPainter(); - NonClientFrameView* frame_view = widget->non_client_view()->frame_view(); - ash::FrameCaptionButtonContainerView* container = - new ash::FrameCaptionButtonContainerView( - widget, - ash::FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - // Add the container to the widget's non-client frame view so that it will be - // deleted when the widget is destroyed. - frame_view->AddChildView(container); - painter->Init(widget, frame_view, NULL, container); - return painter; -} - -} // namespace - -namespace ash { - -class HeaderPainterTest : public ash::test::AshTestBase { - public: - // Creates a test widget that owns its native widget. - Widget* CreateTestWidget() { - Widget* widget = new Widget; - Widget::InitParams params; - params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.context = CurrentContext(); - widget->Init(params); - return widget; - } -}; - -TEST_F(HeaderPainterTest, GetHeaderOpacity) { - // Create a widget and a painter for it. - scoped_ptr<Widget> w1(CreateTestWidget()); - scoped_ptr<HeaderPainter> p1(CreateTestPainter(w1.get())); - w1->Show(); - - // Modify the values of the opacity constants so that they each have a - // different value. - ScopedOpacityConstantModifier opacity_constant_modifier; - - // Solo active window has solo window opacity. - EXPECT_EQ(HeaderPainter::kSoloWindowOpacity, - p1->GetHeaderOpacity(HeaderPainter::ACTIVE, - IDR_AURA_WINDOW_HEADER_BASE_ACTIVE, - 0)); - - // Create a second widget and painter. - scoped_ptr<Widget> w2(CreateTestWidget()); - scoped_ptr<HeaderPainter> p2(CreateTestPainter(w2.get())); - w2->Show(); - - // Active window has active window opacity. - EXPECT_EQ(HeaderPainter::kActiveWindowOpacity, - p2->GetHeaderOpacity(HeaderPainter::ACTIVE, - IDR_AURA_WINDOW_HEADER_BASE_ACTIVE, - 0)); - - // Inactive window has inactive window opacity. - EXPECT_EQ(HeaderPainter::kInactiveWindowOpacity, - p2->GetHeaderOpacity(HeaderPainter::INACTIVE, - IDR_AURA_WINDOW_HEADER_BASE_INACTIVE, - 0)); - - // Regular maximized windows are fully opaque. - wm::GetWindowState(w1->GetNativeWindow())->Maximize(); - EXPECT_EQ(255, - p1->GetHeaderOpacity(HeaderPainter::ACTIVE, - IDR_AURA_WINDOW_HEADER_BASE_ACTIVE, - 0)); -} - -// Ensure the title text is vertically aligned with the window icon. -TEST_F(HeaderPainterTest, TitleIconAlignment) { - scoped_ptr<Widget> w(CreateTestWidget()); - HeaderPainter p; - ash::FrameCaptionButtonContainerView container(w.get(), - ash::FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - views::View window_icon; - window_icon.SetBounds(0, 0, 16, 16); - p.Init(w.get(), - w->non_client_view()->frame_view(), - &window_icon, - &container); - w->SetBounds(gfx::Rect(0, 0, 500, 500)); - w->Show(); - - // Title and icon are aligned when shorter_header is false. - p.LayoutHeader(false); - gfx::Font default_font; - gfx::Rect large_header_title_bounds = p.GetTitleBounds(default_font); - EXPECT_EQ(window_icon.bounds().CenterPoint().y(), - large_header_title_bounds.CenterPoint().y()); - - // Title and icon are aligned when shorter_header is true. - p.LayoutHeader(true); - gfx::Rect short_header_title_bounds = p.GetTitleBounds(default_font); - EXPECT_EQ(window_icon.bounds().CenterPoint().y(), - short_header_title_bounds.CenterPoint().y()); -} - -} // namespace ash diff --git a/chromium/ash/wm/image_cursors.cc b/chromium/ash/wm/image_cursors.cc deleted file mode 100644 index e63bece7ffd..00000000000 --- a/chromium/ash/wm/image_cursors.cc +++ /dev/null @@ -1,152 +0,0 @@ -// 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/image_cursors.h" - -#include <float.h> - -#include "base/logging.h" -#include "base/strings/string16.h" -#include "ui/base/cursor/cursor.h" -#include "ui/base/cursor/cursor_loader.h" -#include "ui/base/cursor/cursors_aura.h" -#include "ui/gfx/display.h" -#include "ui/gfx/point.h" - -namespace ash { - -const int kImageCursorIds[] = { - ui::kCursorNull, - ui::kCursorPointer, - ui::kCursorNoDrop, - ui::kCursorNotAllowed, - ui::kCursorCopy, - ui::kCursorHand, - ui::kCursorMove, - ui::kCursorNorthEastResize, - ui::kCursorSouthWestResize, - ui::kCursorSouthEastResize, - ui::kCursorNorthWestResize, - ui::kCursorNorthResize, - ui::kCursorSouthResize, - ui::kCursorEastResize, - ui::kCursorWestResize, - ui::kCursorIBeam, - ui::kCursorAlias, - ui::kCursorCell, - ui::kCursorContextMenu, - ui::kCursorCross, - ui::kCursorHelp, - ui::kCursorVerticalText, - ui::kCursorZoomIn, - ui::kCursorZoomOut, - ui::kCursorRowResize, - ui::kCursorColumnResize, - ui::kCursorEastWestResize, - ui::kCursorNorthSouthResize, - ui::kCursorNorthEastSouthWestResize, - ui::kCursorNorthWestSouthEastResize, - ui::kCursorGrab, - ui::kCursorGrabbing, -}; - -const int kAnimatedCursorIds[] = { - ui::kCursorWait, - ui::kCursorProgress -}; - -ImageCursors::ImageCursors() : scale_(1.f), cursor_set_(ui::CURSOR_SET_NORMAL) { -} - -ImageCursors::~ImageCursors() { -} - -gfx::Display ImageCursors::GetDisplay() const { - if (!cursor_loader_) { - NOTREACHED(); - // Returning default on release build as it's not serious enough to crash - // even if this ever happens. - return gfx::Display(); - } - return cursor_loader_->display(); -} - -bool ImageCursors::SetDisplay(const gfx::Display& display) { - float device_scale_factor = display.device_scale_factor(); - if (!cursor_loader_) { - cursor_loader_.reset(ui::CursorLoader::Create()); - cursor_loader_->set_scale(scale_); - } else if (cursor_loader_->display().rotation() == display.rotation() && - cursor_loader_->display().device_scale_factor() == - device_scale_factor) { - return false; - } - - cursor_loader_->set_display(display); - ReloadCursors(); - return true; -} - -void ImageCursors::ReloadCursors() { - const gfx::Display& display = cursor_loader_->display(); - float device_scale_factor = display.device_scale_factor(); - - cursor_loader_->UnloadAll(); - - for (size_t i = 0; i < arraysize(kImageCursorIds); ++i) { - int resource_id = -1; - gfx::Point hot_point; - bool success = ui::GetCursorDataFor(cursor_set_, - kImageCursorIds[i], - device_scale_factor, - &resource_id, - &hot_point); - DCHECK(success); - cursor_loader_->LoadImageCursor(kImageCursorIds[i], resource_id, hot_point); - } - for (size_t i = 0; i < arraysize(kAnimatedCursorIds); ++i) { - int resource_id = -1; - gfx::Point hot_point; - bool success = ui::GetAnimatedCursorDataFor(cursor_set_, - kAnimatedCursorIds[i], - device_scale_factor, - &resource_id, - &hot_point); - DCHECK(success); - cursor_loader_->LoadAnimatedCursor(kAnimatedCursorIds[i], - resource_id, - hot_point, - ui::kAnimatedCursorFrameDelayMs); - } -} - -void ImageCursors::SetScale(float scale) { - if (scale < FLT_EPSILON) { - NOTREACHED() << "Scale must be bigger than 0."; - scale = 1.0f; - } - - scale_ = scale; - - if (cursor_loader_.get()) { - cursor_loader_->set_scale(scale); - ReloadCursors(); - } -} - -void ImageCursors::SetCursorSet(ui::CursorSetType cursor_set) { - if (cursor_set_ == cursor_set) - return; - - cursor_set_ = cursor_set; - - if (cursor_loader_.get()) - ReloadCursors(); -} - -void ImageCursors::SetPlatformCursor(gfx::NativeCursor* cursor) { - cursor_loader_->SetPlatformCursor(cursor); -} - -} // namespace ash diff --git a/chromium/ash/wm/image_cursors.h b/chromium/ash/wm/image_cursors.h deleted file mode 100644 index 55bc34c0c44..00000000000 --- a/chromium/ash/wm/image_cursors.h +++ /dev/null @@ -1,63 +0,0 @@ -// 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_IMAGE_CURSORS_H_ -#define ASH_WM_IMAGE_CURSORS_H_ - -#include "ash/ash_export.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string16.h" -#include "ui/base/cursor/cursor.h" -#include "ui/gfx/native_widget_types.h" - -namespace gfx { -class Display; -} - -namespace ui { -class CursorLoader; -} - -namespace ash { - -// A utility class that provides cursors for NativeCursors for which we have -// image resources. -class ASH_EXPORT ImageCursors { - public: - ImageCursors(); - ~ImageCursors(); - - // Returns the display the cursors are loaded for. The display must - // be set by SetDisplay before using this. - gfx::Display GetDisplay() const; - - // Sets the display the cursors are loaded for. The device scale factor - // determines the size of the image to load, and the rotation of the display - // determines if the image and its host point has to be retated. - // Returns true if the cursor image is reloaded. - bool SetDisplay(const gfx::Display& display); - - // Sets the scale of the mouse cursor icon. - void SetScale(float scale); - - // Sets the type of the mouse cursor icon. - void SetCursorSet(ui::CursorSetType cursor_set); - - // Sets the platform cursor based on the native type of |cursor|. - void SetPlatformCursor(gfx::NativeCursor* cursor); - - private: - // Reloads the all loaded cursors in the cursor loader. - void ReloadCursors(); - - scoped_ptr<ui::CursorLoader> cursor_loader_; - float scale_; - ui::CursorSetType cursor_set_; - - DISALLOW_COPY_AND_ASSIGN(ImageCursors); -}; - -} // namespace ash - -#endif // ASH_WM_IMAGE_CURSORS_H_ diff --git a/chromium/ash/wm/immersive_fullscreen_controller.cc b/chromium/ash/wm/immersive_fullscreen_controller.cc deleted file mode 100644 index 701096edfd0..00000000000 --- a/chromium/ash/wm/immersive_fullscreen_controller.cc +++ /dev/null @@ -1,931 +0,0 @@ -// Copyright 2013 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/immersive_fullscreen_controller.h" - -#include <set> - -#include "ash/shell.h" -#include "ash/wm/window_state.h" -#include "base/metrics/histogram.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/capture_client.h" -#include "ui/aura/client/cursor_client.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/gfx/animation/slide_animation.h" -#include "ui/gfx/display.h" -#include "ui/gfx/point.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/screen.h" -#include "ui/views/bubble/bubble_delegate.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -using views::View; - -namespace ash { - -namespace { - -// Duration for the reveal show/hide slide animation. The slower duration is -// used for the initial slide out to give the user more change to see what -// happened. -const int kRevealSlowAnimationDurationMs = 400; -const int kRevealFastAnimationDurationMs = 200; - -// The delay in milliseconds between the mouse stopping at the top edge of the -// screen and the top-of-window views revealing. -const int kMouseRevealDelayMs = 200; - -// The maximum amount of pixels that the cursor can move for the cursor to be -// considered "stopped". This allows the user to reveal the top-of-window views -// without holding the cursor completely still. -const int kMouseRevealXThresholdPixels = 3; - -// How many pixels a gesture can start away from |top_container_| when in -// closed state and still be considered near it. This is needed to overcome -// issues with poor location values near the edge of the display. -const int kNearTopContainerDistance = 8; - -// Used to multiply x value of an update in check to determine if gesture is -// vertical. This is used to make sure that gesture is close to vertical instead -// of just more vertical then horizontal. -const int kSwipeVerticalThresholdMultiplier = 3; - -// The height in pixels of the region above the top edge of the display which -// hosts the immersive fullscreen window in which mouse events are ignored -// (cannot reveal or unreveal the top-of-window views). -// See ShouldIgnoreMouseEventAtLocation() for more details. -const int kHeightOfDeadRegionAboveTopContainer = 10; - -// The height in pixels of the region below the top edge of the display in which -// the mouse can trigger revealing the top-of-window views. The height must be -// greater than 1px because the top pixel is used to trigger moving the cursor -// between displays if the user has a vertical display layout (primary display -// above/below secondary display). -const int kMouseRevealBoundsHeight = 3; - -// Returns the BubbleDelegateView corresponding to |maybe_bubble| if -// |maybe_bubble| is a bubble. -views::BubbleDelegateView* AsBubbleDelegate(aura::Window* maybe_bubble) { - if (!maybe_bubble) - return NULL; - views::Widget* widget = views::Widget::GetWidgetForNativeView(maybe_bubble); - if (!widget) - return NULL; - return widget->widget_delegate()->AsBubbleDelegate(); -} - -// Returns true if |maybe_transient| is a transient child of |toplevel|. -bool IsWindowTransientChildOf(aura::Window* maybe_transient, - aura::Window* toplevel) { - if (!maybe_transient || !toplevel) - return false; - - for (aura::Window* window = maybe_transient; window; - window = window->transient_parent()) { - if (window == toplevel) - return true; - } - return false; -} - -// Returns the location of |event| in screen coordinates. -gfx::Point GetEventLocationInScreen(const ui::LocatedEvent& event) { - gfx::Point location_in_screen = event.location(); - aura::Window* target = static_cast<aura::Window*>(event.target()); - aura::client::ScreenPositionClient* screen_position_client = - aura::client::GetScreenPositionClient(target->GetRootWindow()); - screen_position_client->ConvertPointToScreen(target, &location_in_screen); - return location_in_screen; -} - -// Returns the bounds of the display nearest to |window| in screen coordinates. -gfx::Rect GetDisplayBoundsInScreen(aura::Window* window) { - return Shell::GetScreen()->GetDisplayNearestWindow(window).bounds(); -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// - -// Class which keeps the top-of-window views revealed as long as one of the -// bubbles it is observing is visible. The logic to keep the top-of-window -// views revealed based on the visibility of bubbles anchored to -// children of |ImmersiveFullscreenController::top_container_| is separate from -// the logic related to |ImmersiveFullscreenController::focus_revealed_lock_| -// so that bubbles which are not activatable and bubbles which do not close -// upon deactivation also keep the top-of-window views revealed for the -// duration of their visibility. -class ImmersiveFullscreenController::BubbleManager - : public aura::WindowObserver { - public: - explicit BubbleManager(ImmersiveFullscreenController* controller); - virtual ~BubbleManager(); - - // Start / stop observing changes to |bubble|'s visibility. - void StartObserving(aura::Window* bubble); - void StopObserving(aura::Window* bubble); - - private: - // Updates |revealed_lock_| based on whether any of |bubbles_| is visible. - void UpdateRevealedLock(); - - // aura::WindowObserver overrides: - virtual void OnWindowVisibilityChanged(aura::Window* window, - bool visible) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - ImmersiveFullscreenController* controller_; - - std::set<aura::Window*> bubbles_; - - // Lock which keeps the top-of-window views revealed based on whether any of - // |bubbles_| is visible. - scoped_ptr<ImmersiveRevealedLock> revealed_lock_; - - DISALLOW_COPY_AND_ASSIGN(BubbleManager); -}; - -ImmersiveFullscreenController::BubbleManager::BubbleManager( - ImmersiveFullscreenController* controller) - : controller_(controller) { -} - -ImmersiveFullscreenController::BubbleManager::~BubbleManager() { - for (std::set<aura::Window*>::const_iterator it = bubbles_.begin(); - it != bubbles_.end(); ++it) { - (*it)->RemoveObserver(this); - } -} - -void ImmersiveFullscreenController::BubbleManager::StartObserving( - aura::Window* bubble) { - if (bubbles_.insert(bubble).second) { - bubble->AddObserver(this); - UpdateRevealedLock(); - } -} - -void ImmersiveFullscreenController::BubbleManager::StopObserving( - aura::Window* bubble) { - if (bubbles_.erase(bubble)) { - bubble->RemoveObserver(this); - UpdateRevealedLock(); - } -} - -void ImmersiveFullscreenController::BubbleManager::UpdateRevealedLock() { - bool has_visible_bubble = false; - for (std::set<aura::Window*>::const_iterator it = bubbles_.begin(); - it != bubbles_.end(); ++it) { - if ((*it)->IsVisible()) { - has_visible_bubble = true; - break; - } - } - - bool was_revealed = controller_->IsRevealed(); - if (has_visible_bubble) { - if (!revealed_lock_.get()) { - // Reveal the top-of-window views without animating because it looks - // weird for the top-of-window views to animate and the bubble not to - // animate along with the top-of-window views. - revealed_lock_.reset(controller_->GetRevealedLock( - ImmersiveFullscreenController::ANIMATE_REVEAL_NO)); - } - } else { - revealed_lock_.reset(); - } - - if (!was_revealed && revealed_lock_.get()) { - // Currently, there is no nice way for bubbles to reposition themselves - // whenever the anchor view moves. Tell the bubbles to reposition themselves - // explicitly instead. The hidden bubbles are also repositioned because - // BubbleDelegateView does not reposition its widget as a result of a - // visibility change. - for (std::set<aura::Window*>::const_iterator it = bubbles_.begin(); - it != bubbles_.end(); ++it) { - AsBubbleDelegate(*it)->OnAnchorBoundsChanged(); - } - } -} - -void ImmersiveFullscreenController::BubbleManager::OnWindowVisibilityChanged( - aura::Window*, - bool visible) { - UpdateRevealedLock(); -} - -void ImmersiveFullscreenController::BubbleManager::OnWindowDestroying( - aura::Window* window) { - StopObserving(window); -} - -//////////////////////////////////////////////////////////////////////////////// - -ImmersiveFullscreenController::ImmersiveFullscreenController() - : delegate_(NULL), - top_container_(NULL), - widget_(NULL), - native_window_(NULL), - observers_enabled_(false), - enabled_(false), - reveal_state_(CLOSED), - revealed_lock_count_(0), - mouse_x_when_hit_top_in_screen_(-1), - gesture_begun_(false), - animation_(new gfx::SlideAnimation(this)), - animations_disabled_for_test_(false), - weak_ptr_factory_(this) { -} - -ImmersiveFullscreenController::~ImmersiveFullscreenController() { - EnableWindowObservers(false); -} - -void ImmersiveFullscreenController::Init(Delegate* delegate, - views::Widget* widget, - views::View* top_container) { - delegate_ = delegate; - top_container_ = top_container; - widget_ = widget; - native_window_ = widget_->GetNativeWindow(); -} - -void ImmersiveFullscreenController::SetEnabled(WindowType window_type, - bool enabled) { - if (enabled_ == enabled) - return; - enabled_ = enabled; - - EnableWindowObservers(enabled_); - - // Auto hide the shelf in immersive fullscreen instead of hiding it. - wm::GetWindowState(native_window_)->set_hide_shelf_when_fullscreen(!enabled); - Shell::GetInstance()->UpdateShelfVisibility(); - - if (enabled_) { - // Animate enabling immersive mode by sliding out the top-of-window views. - // No animation occurs if a lock is holding the top-of-window views open. - - // Do a reveal to set the initial state for the animation. (And any - // required state in case the animation cannot run because of a lock holding - // the top-of-window views open.) - MaybeStartReveal(ANIMATE_NO); - - // Reset the located event and the focus revealed locks so that they do not - // affect whether the top-of-window views are hidden. - located_event_revealed_lock_.reset(); - focus_revealed_lock_.reset(); - - // Try doing the animation. - MaybeEndReveal(ANIMATE_SLOW); - - if (reveal_state_ == REVEALED) { - // Reveal was unsuccessful. Reacquire the revealed locks if appropriate. - UpdateLocatedEventRevealedLock(NULL); - UpdateFocusRevealedLock(); - } else { - // Clearing focus is important because it closes focus-related popups like - // the touch selection handles. - widget_->GetFocusManager()->ClearFocus(); - } - } else { - // Stop cursor-at-top tracking. - top_edge_hover_timer_.Stop(); - reveal_state_ = CLOSED; - - delegate_->OnImmersiveFullscreenExited(); - } - - if (enabled_) { - UMA_HISTOGRAM_ENUMERATION("Ash.ImmersiveFullscreen.WindowType", - window_type, - WINDOW_TYPE_COUNT); - } -} - -bool ImmersiveFullscreenController::IsEnabled() const { - return enabled_; -} - -bool ImmersiveFullscreenController::IsRevealed() const { - return enabled_ && reveal_state_ != CLOSED; -} - -ImmersiveRevealedLock* ImmersiveFullscreenController::GetRevealedLock( - AnimateReveal animate_reveal) { - return new ImmersiveRevealedLock(weak_ptr_factory_.GetWeakPtr(), - animate_reveal); -} - -//////////////////////////////////////////////////////////////////////////////// -// Testing interface: - -void ImmersiveFullscreenController::SetupForTest() { - DCHECK(!enabled_); - animations_disabled_for_test_ = true; - - // Move the mouse off of the top-of-window views so that it does not keep the - // top-of-window views revealed. - std::vector<gfx::Rect> bounds_in_screen( - delegate_->GetVisibleBoundsInScreen()); - DCHECK(!bounds_in_screen.empty()); - int bottommost_in_screen = bounds_in_screen[0].bottom(); - for (size_t i = 1; i < bounds_in_screen.size(); ++i) { - if (bounds_in_screen[i].bottom() > bottommost_in_screen) - bottommost_in_screen = bounds_in_screen[i].bottom(); - } - gfx::Point cursor_pos(0, bottommost_in_screen + 100); - aura::Env::GetInstance()->set_last_mouse_location(cursor_pos); - UpdateLocatedEventRevealedLock(NULL); -} - -//////////////////////////////////////////////////////////////////////////////// -// ui::EventHandler overrides: - -void ImmersiveFullscreenController::OnMouseEvent(ui::MouseEvent* event) { - if (!enabled_) - return; - - if (event->type() != ui::ET_MOUSE_MOVED && - event->type() != ui::ET_MOUSE_PRESSED && - event->type() != ui::ET_MOUSE_RELEASED && - event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) { - return; - } - - // Mouse hover can initiate revealing the top-of-window views while |widget_| - // is inactive. - - if (reveal_state_ == SLIDING_OPEN || reveal_state_ == REVEALED) { - top_edge_hover_timer_.Stop(); - UpdateLocatedEventRevealedLock(event); - } else if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) { - // Trigger a reveal if the cursor pauses at the top of the screen for a - // while. - UpdateTopEdgeHoverTimer(event); - } -} - -void ImmersiveFullscreenController::OnTouchEvent(ui::TouchEvent* event) { - if (!enabled_ || event->type() != ui::ET_TOUCH_PRESSED) - return; - - // Touch should not initiate revealing the top-of-window views while |widget_| - // is inactive. - if (!widget_->IsActive()) - return; - - UpdateLocatedEventRevealedLock(event); -} - -void ImmersiveFullscreenController::OnGestureEvent(ui::GestureEvent* event) { - if (!enabled_) - return; - - // Touch gestures should not initiate revealing the top-of-window views while - // |widget_| is inactive. - if (!widget_->IsActive()) - return; - - switch (event->type()) { - case ui::ET_GESTURE_SCROLL_BEGIN: - if (ShouldHandleGestureEvent(GetEventLocationInScreen(*event))) { - gesture_begun_ = true; - // Do not consume the event. Otherwise, we end up consuming all - // ui::ET_GESTURE_SCROLL_BEGIN events in the top-of-window views - // when the top-of-window views are revealed. - } - break; - case ui::ET_GESTURE_SCROLL_UPDATE: - if (gesture_begun_) { - if (UpdateRevealedLocksForSwipe(GetSwipeType(event))) - event->SetHandled(); - gesture_begun_ = false; - } - break; - case ui::ET_GESTURE_SCROLL_END: - case ui::ET_SCROLL_FLING_START: - gesture_begun_ = false; - break; - default: - break; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// views::FocusChangeListener overrides: - -void ImmersiveFullscreenController::OnWillChangeFocus( - views::View* focused_before, - views::View* focused_now) { -} - -void ImmersiveFullscreenController::OnDidChangeFocus( - views::View* focused_before, - views::View* focused_now) { - UpdateFocusRevealedLock(); -} - -//////////////////////////////////////////////////////////////////////////////// -// views::WidgetObserver overrides: - -void ImmersiveFullscreenController::OnWidgetDestroying(views::Widget* widget) { - EnableWindowObservers(false); - native_window_ = NULL; - - // Set |enabled_| to false such that any calls to MaybeStartReveal() and - // MaybeEndReveal() have no effect. - enabled_ = false; -} - -void ImmersiveFullscreenController::OnWidgetActivationChanged( - views::Widget* widget, - bool active) { - UpdateFocusRevealedLock(); -} - -//////////////////////////////////////////////////////////////////////////////// -// gfx::AnimationDelegate overrides: - -void ImmersiveFullscreenController::AnimationEnded( - const gfx::Animation* animation) { - if (reveal_state_ == SLIDING_OPEN) { - OnSlideOpenAnimationCompleted(); - } else if (reveal_state_ == SLIDING_CLOSED) { - OnSlideClosedAnimationCompleted(); - } -} - -void ImmersiveFullscreenController::AnimationProgressed( - const gfx::Animation* animation) { - delegate_->SetVisibleFraction(animation->GetCurrentValue()); -} - -//////////////////////////////////////////////////////////////////////////////// -// aura::WindowObserver overrides: - -void ImmersiveFullscreenController::OnAddTransientChild(aura::Window* window, - aura::Window* transient) { - views::BubbleDelegateView* bubble_delegate = AsBubbleDelegate(transient); - if (bubble_delegate && - bubble_delegate->GetAnchorView() && - top_container_->Contains(bubble_delegate->GetAnchorView())) { - // Observe the aura::Window because the BubbleDelegateView may not be - // parented to the widget's root view yet so |bubble_delegate->GetWidget()| - // may still return NULL. - bubble_manager_->StartObserving(transient); - } -} - -void ImmersiveFullscreenController::OnRemoveTransientChild( - aura::Window* window, - aura::Window* transient) { - bubble_manager_->StopObserving(transient); -} - -//////////////////////////////////////////////////////////////////////////////// -// ash::ImmersiveRevealedLock::Delegate overrides: - -void ImmersiveFullscreenController::LockRevealedState( - AnimateReveal animate_reveal) { - ++revealed_lock_count_; - Animate animate = (animate_reveal == ANIMATE_REVEAL_YES) ? - ANIMATE_FAST : ANIMATE_NO; - MaybeStartReveal(animate); -} - -void ImmersiveFullscreenController::UnlockRevealedState() { - --revealed_lock_count_; - DCHECK_GE(revealed_lock_count_, 0); - if (revealed_lock_count_ == 0) { - // Always animate ending the reveal fast. - MaybeEndReveal(ANIMATE_FAST); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// private: - -void ImmersiveFullscreenController::EnableWindowObservers(bool enable) { - if (observers_enabled_ == enable) - return; - observers_enabled_ = enable; - - views::FocusManager* focus_manager = widget_->GetFocusManager(); - - if (enable) { - widget_->AddObserver(this); - focus_manager->AddFocusChangeListener(this); - Shell::GetInstance()->AddPreTargetHandler(this); - native_window_->AddObserver(this); - - RecreateBubbleManager(); - } else { - widget_->RemoveObserver(this); - focus_manager->RemoveFocusChangeListener(this); - Shell::GetInstance()->RemovePreTargetHandler(this); - native_window_->RemoveObserver(this); - - // We have stopped observing whether transient children are added or removed - // to |native_window_|. The set of bubbles that BubbleManager is observing - // will become stale really quickly. Destroy BubbleManager and recreate it - // when we start observing |native_window_| again. - bubble_manager_.reset(); - - animation_->Stop(); - } -} - -void ImmersiveFullscreenController::UpdateTopEdgeHoverTimer( - ui::MouseEvent* event) { - DCHECK(enabled_); - DCHECK(reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED); - - // Check whether |native_window_| is the event target's parent window instead - // of checking for activation. This allows the timer to be started when - // |widget_| is inactive but prevents starting the timer if the mouse is over - // a portion of the top edge obscured by an unrelated widget. - if (!top_edge_hover_timer_.IsRunning() && - !native_window_->Contains(static_cast<aura::Window*>(event->target()))) { - return; - } - - // Mouse hover should not initiate revealing the top-of-window views while a - // window has mouse capture. - if (aura::client::GetCaptureWindow(native_window_)) - return; - - gfx::Point location_in_screen = GetEventLocationInScreen(*event); - if (ShouldIgnoreMouseEventAtLocation(location_in_screen)) - return; - - // Stop the timer if the cursor left the top edge or is on a different - // display. - gfx::Rect hit_bounds_in_screen = GetDisplayBoundsInScreen(native_window_); - hit_bounds_in_screen.set_height(kMouseRevealBoundsHeight); - if (!hit_bounds_in_screen.Contains(location_in_screen)) { - top_edge_hover_timer_.Stop(); - return; - } - - // The cursor is now at the top of the screen. Consider the cursor "not - // moving" even if it moves a little bit because users don't have perfect - // pointing precision. (The y position is not tested because - // |hit_bounds_in_screen| is short.) - if (top_edge_hover_timer_.IsRunning() && - abs(location_in_screen.x() - mouse_x_when_hit_top_in_screen_) <= - kMouseRevealXThresholdPixels) - return; - - // Start the reveal if the cursor doesn't move for some amount of time. - mouse_x_when_hit_top_in_screen_ = location_in_screen.x(); - top_edge_hover_timer_.Stop(); - // Timer is stopped when |this| is destroyed, hence Unretained() is safe. - top_edge_hover_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kMouseRevealDelayMs), - base::Bind( - &ImmersiveFullscreenController::AcquireLocatedEventRevealedLock, - base::Unretained(this))); -} - -void ImmersiveFullscreenController::UpdateLocatedEventRevealedLock( - ui::LocatedEvent* event) { - if (!enabled_) - return; - DCHECK(!event || event->IsMouseEvent() || event->IsTouchEvent()); - - // Neither the mouse nor touch can initiate a reveal when the top-of-window - // views are sliding closed or are closed with the following exceptions: - // - Hovering at y = 0 which is handled in OnMouseEvent(). - // - Doing a SWIPE_OPEN edge gesture which is handled in OnGestureEvent(). - if (reveal_state_ == CLOSED || reveal_state_ == SLIDING_CLOSED) - return; - - // For the sake of simplicity, ignore |widget_|'s activation in computing - // whether the top-of-window views should stay revealed. Ideally, the - // top-of-window views would stay revealed only when the mouse cursor is - // hovered above a non-obscured portion of the top-of-window views. The - // top-of-window views may be partially obscured when |widget_| is inactive. - - // Ignore all events while a window has capture. This keeps the top-of-window - // views revealed during a drag. - if (aura::client::GetCaptureWindow(native_window_)) - return; - - gfx::Point location_in_screen; - if (event && event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) { - location_in_screen = GetEventLocationInScreen(*event); - } else { - aura::client::CursorClient* cursor_client = aura::client::GetCursorClient( - native_window_->GetRootWindow()); - if (!cursor_client->IsMouseEventsEnabled()) { - // If mouse events are disabled, the user's last interaction was probably - // via touch. Do no do further processing in this case as there is no easy - // way of retrieving the position of the user's last touch. - return; - } - location_in_screen = aura::Env::GetInstance()->last_mouse_location(); - } - - if ((!event || event->IsMouseEvent()) && - ShouldIgnoreMouseEventAtLocation(location_in_screen)) { - return; - } - - // The visible bounds of |top_container_| should be contained in - // |hit_bounds_in_screen|. - std::vector<gfx::Rect> hit_bounds_in_screen = - delegate_->GetVisibleBoundsInScreen(); - bool keep_revealed = false; - for (size_t i = 0; i < hit_bounds_in_screen.size(); ++i) { - // Allow the cursor to move slightly off the top-of-window views before - // sliding closed. In the case of ImmersiveModeControllerAsh, this helps - // when the user is attempting to click on the bookmark bar and overshoots - // slightly. - if (event && event->type() == ui::ET_MOUSE_MOVED) { - const int kBoundsOffsetY = 8; - hit_bounds_in_screen[i].Inset(0, 0, 0, -kBoundsOffsetY); - } - - if (hit_bounds_in_screen[i].Contains(location_in_screen)) { - keep_revealed = true; - break; - } - } - - if (keep_revealed) - AcquireLocatedEventRevealedLock(); - else - located_event_revealed_lock_.reset(); -} - -void ImmersiveFullscreenController::AcquireLocatedEventRevealedLock() { - // CAUTION: Acquiring the lock results in a reentrant call to - // AcquireLocatedEventRevealedLock() when - // |ImmersiveFullscreenController::animations_disabled_for_test_| is true. - if (!located_event_revealed_lock_.get()) - located_event_revealed_lock_.reset(GetRevealedLock(ANIMATE_REVEAL_YES)); -} - -void ImmersiveFullscreenController::UpdateFocusRevealedLock() { - if (!enabled_) - return; - - bool hold_lock = false; - if (widget_->IsActive()) { - views::View* focused_view = widget_->GetFocusManager()->GetFocusedView(); - if (top_container_->Contains(focused_view)) - hold_lock = true; - } else { - aura::Window* active_window = aura::client::GetActivationClient( - native_window_->GetRootWindow())->GetActiveWindow(); - views::BubbleDelegateView* bubble_delegate = - AsBubbleDelegate(active_window); - if (bubble_delegate && bubble_delegate->anchor_widget()) { - // BubbleManager will already have locked the top-of-window views if the - // bubble is anchored to a child of |top_container_|. Don't acquire - // |focus_revealed_lock_| here for the sake of simplicity. - // Note: Instead of checking for the existence of the |anchor_view|, - // the existence of the |anchor_widget| is performed to avoid the case - // where the view is already gone (and the widget is still running). - } else { - // The currently active window is not |native_window_| and it is not a - // bubble with an anchor view. The top-of-window views should be revealed - // if: - // 1) The active window is a transient child of |native_window_|. - // 2) The top-of-window views are already revealed. This restriction - // prevents a transient window opened by the web contents while the - // top-of-window views are hidden from from initiating a reveal. - // The top-of-window views will stay revealed till |native_window_| is - // reactivated. - if (IsRevealed() && - IsWindowTransientChildOf(active_window, native_window_)) { - hold_lock = true; - } - } - } - - if (hold_lock) { - if (!focus_revealed_lock_.get()) - focus_revealed_lock_.reset(GetRevealedLock(ANIMATE_REVEAL_YES)); - } else { - focus_revealed_lock_.reset(); - } -} - -bool ImmersiveFullscreenController::UpdateRevealedLocksForSwipe( - SwipeType swipe_type) { - if (!enabled_ || swipe_type == SWIPE_NONE) - return false; - - // Swipes while |native_window_| is inactive should have been filtered out in - // OnGestureEvent(). - DCHECK(widget_->IsActive()); - - if (reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED) { - if (swipe_type == SWIPE_OPEN && !located_event_revealed_lock_.get()) { - located_event_revealed_lock_.reset(GetRevealedLock(ANIMATE_REVEAL_YES)); - return true; - } - } else { - if (swipe_type == SWIPE_CLOSE) { - // Attempt to end the reveal. If other code is holding onto a lock, the - // attempt will be unsuccessful. - located_event_revealed_lock_.reset(); - focus_revealed_lock_.reset(); - - if (reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED) { - widget_->GetFocusManager()->ClearFocus(); - return true; - } - - // Ending the reveal was unsuccessful. Reaquire the locks if appropriate. - UpdateLocatedEventRevealedLock(NULL); - UpdateFocusRevealedLock(); - } - } - return false; -} - -int ImmersiveFullscreenController::GetAnimationDuration(Animate animate) const { - switch (animate) { - case ANIMATE_NO: - return 0; - case ANIMATE_SLOW: - return kRevealSlowAnimationDurationMs; - case ANIMATE_FAST: - return kRevealFastAnimationDurationMs; - } - NOTREACHED(); - return 0; -} - -void ImmersiveFullscreenController::MaybeStartReveal(Animate animate) { - if (!enabled_) - return; - - if (animations_disabled_for_test_) - animate = ANIMATE_NO; - - // Callers with ANIMATE_NO expect this function to synchronously reveal the - // top-of-window views. - if (reveal_state_ == REVEALED || - (reveal_state_ == SLIDING_OPEN && animate != ANIMATE_NO)) { - return; - } - - RevealState previous_reveal_state = reveal_state_; - reveal_state_ = SLIDING_OPEN; - if (previous_reveal_state == CLOSED) { - delegate_->OnImmersiveRevealStarted(); - - // Do not do any more processing if OnImmersiveRevealStarted() changed - // |reveal_state_|. - if (reveal_state_ != SLIDING_OPEN) - return; - } - // Slide in the reveal view. - if (animate == ANIMATE_NO) { - animation_->Reset(1); - OnSlideOpenAnimationCompleted(); - } else { - animation_->SetSlideDuration(GetAnimationDuration(animate)); - animation_->Show(); - } -} - -void ImmersiveFullscreenController::OnSlideOpenAnimationCompleted() { - DCHECK_EQ(SLIDING_OPEN, reveal_state_); - reveal_state_ = REVEALED; - delegate_->SetVisibleFraction(1); - - // The user may not have moved the mouse since the reveal was initiated. - // Update the revealed lock to reflect the mouse's current state. - UpdateLocatedEventRevealedLock(NULL); -} - -void ImmersiveFullscreenController::MaybeEndReveal(Animate animate) { - if (!enabled_ || revealed_lock_count_ != 0) - return; - - if (animations_disabled_for_test_) - animate = ANIMATE_NO; - - // Callers with ANIMATE_NO expect this function to synchronously close the - // top-of-window views. - if (reveal_state_ == CLOSED || - (reveal_state_ == SLIDING_CLOSED && animate != ANIMATE_NO)) { - return; - } - - reveal_state_ = SLIDING_CLOSED; - int duration_ms = GetAnimationDuration(animate); - if (duration_ms > 0) { - animation_->SetSlideDuration(duration_ms); - animation_->Hide(); - } else { - animation_->Reset(0); - OnSlideClosedAnimationCompleted(); - } -} - -void ImmersiveFullscreenController::OnSlideClosedAnimationCompleted() { - DCHECK_EQ(SLIDING_CLOSED, reveal_state_); - reveal_state_ = CLOSED; - delegate_->OnImmersiveRevealEnded(); -} - -ImmersiveFullscreenController::SwipeType -ImmersiveFullscreenController::GetSwipeType(ui::GestureEvent* event) const { - if (event->type() != ui::ET_GESTURE_SCROLL_UPDATE) - return SWIPE_NONE; - // Make sure that it is a clear vertical gesture. - if (abs(event->details().scroll_y()) <= - kSwipeVerticalThresholdMultiplier * abs(event->details().scroll_x())) - return SWIPE_NONE; - if (event->details().scroll_y() < 0) - return SWIPE_CLOSE; - else if (event->details().scroll_y() > 0) - return SWIPE_OPEN; - return SWIPE_NONE; -} - -bool ImmersiveFullscreenController::ShouldIgnoreMouseEventAtLocation( - const gfx::Point& location) const { - // Ignore mouse events in the region immediately above the top edge of the - // display. This is to handle the case of a user with a vertical display - // layout (primary display above/below secondary display) and the immersive - // fullscreen window on the bottom display. It is really hard to trigger a - // reveal in this case because: - // - It is hard to stop the cursor in the top |kMouseRevealBoundsHeight| - // pixels of the bottom display. - // - The cursor is warped to the top display if the cursor gets to the top - // edge of the bottom display. - // Mouse events are ignored in the bottom few pixels of the top display - // (Mouse events in this region cannot start or end a reveal). This allows a - // user to overshoot the top of the bottom display and still reveal the - // top-of-window views. - gfx::Rect dead_region = GetDisplayBoundsInScreen(native_window_); - dead_region.set_y(dead_region.y() - kHeightOfDeadRegionAboveTopContainer); - dead_region.set_height(kHeightOfDeadRegionAboveTopContainer); - return dead_region.Contains(location); -} - -bool ImmersiveFullscreenController::ShouldHandleGestureEvent( - const gfx::Point& location) const { - DCHECK(widget_->IsActive()); - if (reveal_state_ == REVEALED) { - std::vector<gfx::Rect> hit_bounds_in_screen( - delegate_->GetVisibleBoundsInScreen()); - for (size_t i = 0; i < hit_bounds_in_screen.size(); ++i) { - if (hit_bounds_in_screen[i].Contains(location)) - return true; - } - return false; - } - - // When the top-of-window views are not fully revealed, handle gestures which - // start in the top few pixels of the screen. - gfx::Rect hit_bounds_in_screen(GetDisplayBoundsInScreen(native_window_)); - hit_bounds_in_screen.set_height(kNearTopContainerDistance); - if (hit_bounds_in_screen.Contains(location)) - return true; - - // There may be a bezel sensor off screen logically above - // |hit_bounds_in_screen|. The check for the event not contained by the - // closest screen ensures that the event is from a valid bezel (as opposed to - // another screen in an extended desktop). - gfx::Rect screen_bounds = - Shell::GetScreen()->GetDisplayNearestPoint(location).bounds(); - return (!screen_bounds.Contains(location) && - location.y() < hit_bounds_in_screen.y() && - location.x() >= hit_bounds_in_screen.x() && - location.x() < hit_bounds_in_screen.right()); -} - -void ImmersiveFullscreenController::RecreateBubbleManager() { - bubble_manager_.reset(new BubbleManager(this)); - const std::vector<aura::Window*> transient_children = - native_window_->transient_children(); - for (size_t i = 0; i < transient_children.size(); ++i) { - aura::Window* transient_child = transient_children[i]; - views::BubbleDelegateView* bubble_delegate = - AsBubbleDelegate(transient_child); - if (bubble_delegate && - bubble_delegate->GetAnchorView() && - top_container_->Contains(bubble_delegate->GetAnchorView())) { - bubble_manager_->StartObserving(transient_child); - } - } -} - -} // namespace ash diff --git a/chromium/ash/wm/immersive_fullscreen_controller.h b/chromium/ash/wm/immersive_fullscreen_controller.h deleted file mode 100644 index 9b6b600b168..00000000000 --- a/chromium/ash/wm/immersive_fullscreen_controller.h +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2013 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_IMMERSIVE_FULLSCREEN_CONTROLLER_H_ -#define ASH_WM_IMMERSIVE_FULLSCREEN_CONTROLLER_H_ - -#include <vector> - -#include "ash/ash_export.h" -#include "ash/wm/immersive_revealed_lock.h" -#include "base/timer/timer.h" -#include "ui/aura/window_observer.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/animation/animation_delegate.h" -#include "ui/views/focus/focus_manager.h" -#include "ui/views/widget/widget_observer.h" - -namespace aura { -class Window; -} - -namespace gfx { -class Point; -class Rect; -class SlideAnimation; -} - -namespace ui { -class LocatedEvent; -} - -namespace views { -class View; -class Widget; -} - -namespace ash { - -class ASH_EXPORT ImmersiveFullscreenController - : public gfx::AnimationDelegate, - public ui::EventHandler, - public views::FocusChangeListener, - public views::WidgetObserver, - public aura::WindowObserver, - public ImmersiveRevealedLock::Delegate { - public: - // The enum is used for an enumerated histogram. New items should be only - // added to the end. - enum WindowType { - WINDOW_TYPE_OTHER, - WINDOW_TYPE_BROWSER, - WINDOW_TYPE_HOSTED_APP, - WINDOW_TYPE_PACKAGED_APP, - WINDOW_TYPE_COUNT - }; - - class Delegate { - public: - // Called when a reveal of the top-of-window views starts. - virtual void OnImmersiveRevealStarted() = 0; - - // Called when the top-of-window views have finished closing. This call - // implies a visible fraction of 0. SetVisibleFraction(0) may not be called - // prior to OnImmersiveRevealEnded(). - virtual void OnImmersiveRevealEnded() = 0; - - // Called as a result of disabling immersive fullscreen via SetEnabled(). - virtual void OnImmersiveFullscreenExited() = 0; - - // Called to update the fraction of the top-of-window views height which is - // visible. - virtual void SetVisibleFraction(double visible_fraction) = 0; - - // Returns a list of rects whose union makes up the top-of-window views. - // The returned list is used for hittesting when the top-of-window views - // are revealed. GetVisibleBoundsInScreen() must return a valid value when - // not in immersive fullscreen for the sake of SetupForTest(). - virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const = 0; - - protected: - virtual ~Delegate() {} - }; - - ImmersiveFullscreenController(); - virtual ~ImmersiveFullscreenController(); - - // Initializes the controller. Must be called prior to enabling immersive - // fullscreen via SetEnabled(). |top_container| is used to keep the - // top-of-window views revealed when a child of |top_container| has focus. - // |top_container| does not affect which mouse and touch events keep the - // top-of-window views revealed. - void Init(Delegate* delegate, - views::Widget* widget, - views::View* top_container); - - // Enables or disables immersive fullscreen. - // |window_type| is the type of window which is put in immersive fullscreen. - // It is only used for histogramming. - void SetEnabled(WindowType window_type, bool enable); - - // Returns true if |native_window_| is in immersive fullscreen. - bool IsEnabled() const; - - // Returns true if |native_window_| is in immersive fullscreen and the - // top-of-window views are fully or partially visible. - bool IsRevealed() const; - - // Returns a lock which will keep the top-of-window views revealed for its - // lifetime. Several locks can be obtained. When all of the locks are - // destroyed, if immersive fullscreen is enabled and there is nothing else - // keeping the top-of-window views revealed, the top-of-window views will be - // closed. This method always returns a valid lock regardless of whether - // immersive fullscreen is enabled. The lock's lifetime can span immersive - // fullscreen being enabled / disabled. If acquiring the lock causes a reveal, - // the top-of-window views will animate according to |animate_reveal|. The - // caller takes ownership of the returned lock. - ImmersiveRevealedLock* GetRevealedLock( - AnimateReveal animate_reveal) WARN_UNUSED_RESULT; - - // Disables animations and moves the mouse so that it is not over the - // top-of-window views for the sake of testing. - void SetupForTest(); - - // ui::EventHandler overrides: - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - // views::FocusChangeObserver overrides: - virtual void OnWillChangeFocus(views::View* focused_before, - views::View* focused_now) OVERRIDE; - virtual void OnDidChangeFocus(views::View* focused_before, - views::View* focused_now) OVERRIDE; - - // views::WidgetObserver overrides: - virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; - virtual void OnWidgetActivationChanged(views::Widget* widget, - bool active) OVERRIDE; - - // gfx::AnimationDelegate overrides: - virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; - virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; - - // aura::WindowObserver overrides: - virtual void OnAddTransientChild(aura::Window* window, - aura::Window* transient) OVERRIDE; - virtual void OnRemoveTransientChild(aura::Window* window, - aura::Window* transient) OVERRIDE; - - // ash::ImmersiveRevealedLock::Delegate overrides: - virtual void LockRevealedState(AnimateReveal animate_reveal) OVERRIDE; - virtual void UnlockRevealedState() OVERRIDE; - - private: - friend class ImmersiveFullscreenControllerTest; - - enum Animate { - ANIMATE_NO, - ANIMATE_SLOW, - ANIMATE_FAST, - }; - enum RevealState { - CLOSED, - SLIDING_OPEN, - REVEALED, - SLIDING_CLOSED, - }; - enum SwipeType { - SWIPE_OPEN, - SWIPE_CLOSE, - SWIPE_NONE - }; - - // Enables or disables observers for mouse, touch, focus, and activation. - void EnableWindowObservers(bool enable); - - // Updates |top_edge_hover_timer_| based on a mouse |event|. If the mouse is - // hovered at the top of the screen the timer is started. If the mouse moves - // away from the top edge, or moves too much in the x direction, the timer is - // stopped. - void UpdateTopEdgeHoverTimer(ui::MouseEvent* event); - - // Updates |located_event_revealed_lock_| based on the current mouse state and - // the current touch state. - // |event| is NULL if the source event is not known. - void UpdateLocatedEventRevealedLock(ui::LocatedEvent* event); - - // Acquires |located_event_revealed_lock_| if it is not already held. - void AcquireLocatedEventRevealedLock(); - - // Updates |focus_revealed_lock_| based on the currently active view and the - // currently active widget. - void UpdateFocusRevealedLock(); - - // Update |located_event_revealed_lock_| and |focus_revealed_lock_| as a - // result of a gesture of |swipe_type|. Returns true if any locks were - // acquired or released. - bool UpdateRevealedLocksForSwipe(SwipeType swipe_type); - - // Returns the animation duration given |animate|. - int GetAnimationDuration(Animate animate) const; - - // Temporarily reveals the top-of-window views while in immersive mode, - // hiding them when the cursor exits the area of the top views. If |animate| - // is not ANIMATE_NO, slides in the view, otherwise shows it immediately. - void MaybeStartReveal(Animate animate); - - // Called when the animation to slide open the top-of-window views has - // completed. - void OnSlideOpenAnimationCompleted(); - - // Hides the top-of-window views if immersive mode is enabled and nothing is - // keeping them revealed. Optionally animates. - void MaybeEndReveal(Animate animate); - - // Called when the animation to slide out the top-of-window views has - // completed. - void OnSlideClosedAnimationCompleted(); - - // Returns the type of swipe given |event|. - SwipeType GetSwipeType(ui::GestureEvent* event) const; - - // Returns true if a mouse event at |location_in_screen| should be ignored. - // Ignored mouse events should not contribute to revealing or unrevealing the - // top-of-window views. - bool ShouldIgnoreMouseEventAtLocation( - const gfx::Point& location_in_screen) const; - - // True when |location| is "near" to the top container. When the top container - // is not closed "near" means within the displayed bounds or above it. When - // the top container is closed "near" means either within the displayed - // bounds, above it, or within a few pixels below it. This allow the container - // to steal enough pixels to detect a swipe in and handles the case that there - // is a bezel sensor above the top container. - bool ShouldHandleGestureEvent(const gfx::Point& location) const; - - // Recreate |bubble_manager_| and start observing any bubbles anchored to a - // child of |top_container_|. - void RecreateBubbleManager(); - - // Not owned. - Delegate* delegate_; - views::View* top_container_; - views::Widget* widget_; - aura::Window* native_window_; - - // True if the observers have been enabled. - bool observers_enabled_; - - // True when in immersive fullscreen. - bool enabled_; - - // State machine for the revealed/closed animations. - RevealState reveal_state_; - - int revealed_lock_count_; - - // Timer to track cursor being held at the top edge of the screen. - base::OneShotTimer<ImmersiveFullscreenController> top_edge_hover_timer_; - - // The cursor x position in screen coordinates when the cursor first hit the - // top edge of the screen. - int mouse_x_when_hit_top_in_screen_; - - // Tracks if the controller has seen a ET_GESTURE_SCROLL_BEGIN, without the - // following events. - bool gesture_begun_; - - // Lock which keeps the top-of-window views revealed based on the current - // mouse state and the current touch state. Acquiring the lock is used to - // trigger a reveal when the user moves the mouse to the top of the screen - // and when the user does a SWIPE_OPEN edge gesture. - scoped_ptr<ImmersiveRevealedLock> located_event_revealed_lock_; - - // Lock which keeps the top-of-window views revealed based on the focused view - // and the active widget. Acquiring the lock never triggers a reveal because - // a view is not focusable till a reveal has made it visible. - scoped_ptr<ImmersiveRevealedLock> focus_revealed_lock_; - - // The animation which controls sliding the top-of-window views in and out. - scoped_ptr<gfx::SlideAnimation> animation_; - - // Whether the animations are disabled for testing. - bool animations_disabled_for_test_; - - // Manages bubbles which are anchored to a child of |top_container_|. - class BubbleManager; - scoped_ptr<BubbleManager> bubble_manager_; - - base::WeakPtrFactory<ImmersiveFullscreenController> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ImmersiveFullscreenController); -}; - -} // namespace ash - -#endif // ASH_WM_IMMERSIVE_FULLSCREEN_CONTROLLER_H_ diff --git a/chromium/ash/wm/immersive_fullscreen_controller_unittest.cc b/chromium/ash/wm/immersive_fullscreen_controller_unittest.cc deleted file mode 100644 index 7e50916d227..00000000000 --- a/chromium/ash/wm/immersive_fullscreen_controller_unittest.cc +++ /dev/null @@ -1,958 +0,0 @@ -// Copyright 2013 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/immersive_fullscreen_controller.h" - -#include "ash/display/display_manager.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_types.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/cursor_client.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/window.h" -#include "ui/gfx/animation/slide_animation.h" -#include "ui/views/bubble/bubble_delegate.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -// For now, immersive fullscreen is Chrome OS only. -#if defined(OS_CHROMEOS) - -namespace ash { - -namespace { - -class MockImmersiveFullscreenControllerDelegate - : public ImmersiveFullscreenController::Delegate { - public: - MockImmersiveFullscreenControllerDelegate(views::View* top_container_view) - : top_container_view_(top_container_view), - enabled_(false), - visible_fraction_(1) { - } - virtual ~MockImmersiveFullscreenControllerDelegate() {} - - // ImmersiveFullscreenController::Delegate overrides: - virtual void OnImmersiveRevealStarted() OVERRIDE { - enabled_ = true; - visible_fraction_ = 0; - } - virtual void OnImmersiveRevealEnded() OVERRIDE { - visible_fraction_ = 0; - } - virtual void OnImmersiveFullscreenExited() OVERRIDE { - enabled_ = false; - visible_fraction_ = 1; - } - virtual void SetVisibleFraction(double visible_fraction) OVERRIDE { - visible_fraction_ = visible_fraction; - } - virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const OVERRIDE { - std::vector<gfx::Rect> bounds_in_screen; - bounds_in_screen.push_back(top_container_view_->GetBoundsInScreen()); - return bounds_in_screen; - } - - bool is_enabled() const { - return enabled_; - } - - double visible_fraction() const { - return visible_fraction_; - } - - private: - views::View* top_container_view_; - bool enabled_; - double visible_fraction_; - - DISALLOW_COPY_AND_ASSIGN(MockImmersiveFullscreenControllerDelegate); -}; - -} // namespace - -///////////////////////////////////////////////////////////////////////////// - -class ImmersiveFullscreenControllerTest : public ash::test::AshTestBase { - public: - enum Modality { - MODALITY_MOUSE, - MODALITY_TOUCH, - MODALITY_GESTURE - }; - - ImmersiveFullscreenControllerTest() : widget_(NULL), top_container_(NULL) {} - virtual ~ImmersiveFullscreenControllerTest() {} - - ImmersiveFullscreenController* controller() { - return controller_.get(); - } - - views::View* top_container() { - return top_container_; - } - - aura::Window* window() { - return widget_->GetNativeWindow(); - } - - MockImmersiveFullscreenControllerDelegate* delegate() { - return delegate_.get(); - } - - // Access to private data from the controller. - bool top_edge_hover_timer_running() const { - return controller_->top_edge_hover_timer_.IsRunning(); - } - int mouse_x_when_hit_top() const { - return controller_->mouse_x_when_hit_top_in_screen_; - } - - // ash::test::AshTestBase overrides: - virtual void SetUp() OVERRIDE { - ash::test::AshTestBase::SetUp(); - - widget_ = new views::Widget(); - views::Widget::InitParams params; - params.context = CurrentContext(); - widget_->Init(params); - widget_->Show(); - - window()->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - - top_container_ = new views::View(); - top_container_->SetBounds( - 0, 0, widget_->GetWindowBoundsInScreen().width(), 100); - top_container_->SetFocusable(true); - widget_->GetContentsView()->AddChildView(top_container_); - - delegate_.reset( - new MockImmersiveFullscreenControllerDelegate(top_container_)); - controller_.reset(new ImmersiveFullscreenController); - controller_->Init(delegate_.get(), widget_, top_container_); - controller_->SetupForTest(); - - // The mouse is moved so that it is not over |top_container_| by - // AshTestBase. - } - - // Enables / disables immersive fullscreen. - void SetEnabled(bool enabled) { - controller_->SetEnabled(ImmersiveFullscreenController::WINDOW_TYPE_OTHER, - enabled); - } - - // Attempt to reveal the top-of-window views via |modality|. - // The top-of-window views can only be revealed via mouse hover or a gesture. - void AttemptReveal(Modality modality) { - ASSERT_NE(modality, MODALITY_TOUCH); - AttemptRevealStateChange(true, modality); - } - - // Attempt to unreveal the top-of-window views via |modality|. The - // top-of-window views can be unrevealed via any modality. - void AttemptUnreveal(Modality modality) { - AttemptRevealStateChange(false, modality); - } - - // Sets whether the mouse is hovered above |top_container_|. - // SetHovered(true) moves the mouse over the |top_container_| but does not - // move it to the top of the screen so will not initiate a reveal. - void SetHovered(bool is_mouse_hovered) { - MoveMouse(0, is_mouse_hovered ? 10 : top_container_->height() + 100); - } - - // Move the mouse to the given coordinates. The coordinates should be in - // |top_container_| coordinates. - void MoveMouse(int x, int y) { - gfx::Point screen_position(x, y); - views::View::ConvertPointToScreen(top_container_, &screen_position); - GetEventGenerator().MoveMouseTo(screen_position.x(), screen_position.y()); - - // If the top edge timer started running as a result of the mouse move, run - // the task which occurs after the timer delay. This reveals the - // top-of-window views synchronously if the mouse is hovered at the top of - // the screen. - if (controller()->top_edge_hover_timer_.IsRunning()) { - controller()->top_edge_hover_timer_.user_task().Run(); - controller()->top_edge_hover_timer_.Stop(); - } - } - - private: - // Attempt to change the revealed state to |revealed| via |modality|. - void AttemptRevealStateChange(bool revealed, Modality modality) { - // Compute the event position in |top_container_| coordinates. - gfx::Point event_position(0, revealed ? 0 : top_container_->height() + 100); - switch (modality) { - case MODALITY_MOUSE: { - MoveMouse(event_position.x(), event_position.y()); - break; - } - case MODALITY_TOUCH: { - gfx::Point screen_position = event_position; - views::View::ConvertPointToScreen(top_container_, &screen_position); - - aura::test::EventGenerator& event_generator(GetEventGenerator()); - event_generator.MoveTouch(event_position); - event_generator.PressTouch(); - event_generator.ReleaseTouch(); - break; - } - case MODALITY_GESTURE: { - aura::client::GetCursorClient(CurrentContext())->DisableMouseEvents(); - ImmersiveFullscreenController::SwipeType swipe_type = revealed ? - ImmersiveFullscreenController::SWIPE_OPEN : - ImmersiveFullscreenController::SWIPE_CLOSE; - controller_->UpdateRevealedLocksForSwipe(swipe_type); - break; - } - } - } - - scoped_ptr<ImmersiveFullscreenController> controller_; - scoped_ptr<MockImmersiveFullscreenControllerDelegate> delegate_; - views::Widget* widget_; // Owned by the native widget. - views::View* top_container_; // Owned by |root_view_|. - - DISALLOW_COPY_AND_ASSIGN(ImmersiveFullscreenControllerTest); -}; - -// Test the initial state and that the delegate gets notified of the -// top-of-window views getting hidden and revealed. -TEST_F(ImmersiveFullscreenControllerTest, Delegate) { - // Initial state. - EXPECT_FALSE(controller()->IsEnabled()); - EXPECT_FALSE(controller()->IsRevealed()); - EXPECT_FALSE(delegate()->is_enabled()); - - // Enabling initially hides the top views. - SetEnabled(true); - EXPECT_TRUE(controller()->IsEnabled()); - EXPECT_FALSE(controller()->IsRevealed()); - EXPECT_TRUE(delegate()->is_enabled()); - EXPECT_EQ(0, delegate()->visible_fraction()); - - // Revealing shows the top views. - AttemptReveal(MODALITY_MOUSE); - EXPECT_TRUE(controller()->IsEnabled()); - EXPECT_TRUE(controller()->IsRevealed()); - EXPECT_TRUE(delegate()->is_enabled()); - EXPECT_EQ(1, delegate()->visible_fraction()); - - // Disabling ends the immersive reveal. - SetEnabled(false); - EXPECT_FALSE(controller()->IsEnabled()); - EXPECT_FALSE(controller()->IsRevealed()); - EXPECT_FALSE(delegate()->is_enabled()); -} - -// GetRevealedLock() specific tests. -TEST_F(ImmersiveFullscreenControllerTest, RevealedLock) { - scoped_ptr<ImmersiveRevealedLock> lock1; - scoped_ptr<ImmersiveRevealedLock> lock2; - - // Immersive fullscreen is not on by default. - EXPECT_FALSE(controller()->IsEnabled()); - - // 1) Test acquiring and releasing a revealed state lock while immersive - // fullscreen is disabled. Acquiring or releasing the lock should have no - // effect till immersive fullscreen is enabled. - lock1.reset(controller()->GetRevealedLock( - ImmersiveFullscreenController::ANIMATE_REVEAL_NO)); - EXPECT_FALSE(controller()->IsEnabled()); - EXPECT_FALSE(controller()->IsRevealed()); - - // Immersive fullscreen should start in the revealed state due to the lock. - SetEnabled(true); - EXPECT_TRUE(controller()->IsEnabled()); - EXPECT_TRUE(controller()->IsRevealed()); - - SetEnabled(false); - EXPECT_FALSE(controller()->IsEnabled()); - EXPECT_FALSE(controller()->IsRevealed()); - - lock1.reset(); - EXPECT_FALSE(controller()->IsEnabled()); - EXPECT_FALSE(controller()->IsRevealed()); - - // Immersive fullscreen should start in the closed state because the lock is - // no longer held. - SetEnabled(true); - EXPECT_TRUE(controller()->IsEnabled()); - EXPECT_FALSE(controller()->IsRevealed()); - - // 2) Test that acquiring a lock reveals the top-of-window views if they are - // hidden. - lock1.reset(controller()->GetRevealedLock( - ImmersiveFullscreenController::ANIMATE_REVEAL_NO)); - EXPECT_TRUE(controller()->IsRevealed()); - - // 3) Test that the top-of-window views are only hidden when all of the locks - // are released. - lock2.reset(controller()->GetRevealedLock( - ImmersiveFullscreenController::ANIMATE_REVEAL_NO)); - lock1.reset(); - EXPECT_TRUE(controller()->IsRevealed()); - - lock2.reset(); - EXPECT_FALSE(controller()->IsRevealed()); -} - -// Test mouse event processing for top-of-screen reveal triggering. -TEST_F(ImmersiveFullscreenControllerTest, OnMouseEvent) { - // Set up initial state. - UpdateDisplay("800x600,800x600"); - ash::DisplayLayout display_layout(ash::DisplayLayout::RIGHT, 0); - ash::Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays( - display_layout); - - // Set up initial state. - SetEnabled(true); - ASSERT_TRUE(controller()->IsEnabled()); - ASSERT_FALSE(controller()->IsRevealed()); - - aura::test::EventGenerator& event_generator(GetEventGenerator()); - - gfx::Rect top_container_bounds_in_screen = - top_container()->GetBoundsInScreen(); - // A position along the top edge of TopContainerView in screen coordinates. - gfx::Point top_edge_pos(top_container_bounds_in_screen.x() + 100, - top_container_bounds_in_screen.y()); - - // Mouse wheel event does nothing. - ui::MouseEvent wheel( - ui::ET_MOUSEWHEEL, top_edge_pos, top_edge_pos, ui::EF_NONE); - event_generator.Dispatch(&wheel); - EXPECT_FALSE(top_edge_hover_timer_running()); - - // Move to top edge of screen starts hover timer running. We cannot use - // MoveMouse() because MoveMouse() stops the timer if it started running. - event_generator.MoveMouseTo(top_edge_pos); - EXPECT_TRUE(top_edge_hover_timer_running()); - EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top()); - - // Moving |ImmersiveFullscreenControllerTest::kMouseRevealBoundsHeight| down - // from the top edge stops it. - event_generator.MoveMouseBy(0, 3); - EXPECT_FALSE(top_edge_hover_timer_running()); - - // Moving back to the top starts the timer again. - event_generator.MoveMouseTo(top_edge_pos); - EXPECT_TRUE(top_edge_hover_timer_running()); - EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top()); - - // Slight move to the right keeps the timer running for the same hit point. - event_generator.MoveMouseBy(1, 0); - EXPECT_TRUE(top_edge_hover_timer_running()); - EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top()); - - // Moving back to the left also keeps the timer running. - event_generator.MoveMouseBy(-1, 0); - EXPECT_TRUE(top_edge_hover_timer_running()); - EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top()); - - // Large move right restarts the timer (so it is still running) and considers - // this a new hit at the top. - event_generator.MoveMouseTo(top_edge_pos.x() + 100, top_edge_pos.y()); - EXPECT_TRUE(top_edge_hover_timer_running()); - EXPECT_EQ(top_edge_pos.x() + 100, mouse_x_when_hit_top()); - - // Moving off the top edge horizontally stops the timer. - event_generator.MoveMouseTo(top_container_bounds_in_screen.right() + 1, - top_container_bounds_in_screen.y()); - EXPECT_FALSE(top_edge_hover_timer_running()); - - // Once revealed, a move just a little below the top container doesn't end a - // reveal. - AttemptReveal(MODALITY_MOUSE); - event_generator.MoveMouseTo(top_container_bounds_in_screen.x(), - top_container_bounds_in_screen.bottom() + 1); - EXPECT_TRUE(controller()->IsRevealed()); - - // Once revealed, clicking just below the top container ends the reveal. - event_generator.ClickLeftButton(); - EXPECT_FALSE(controller()->IsRevealed()); - - // Moving a lot below the top container ends a reveal. - AttemptReveal(MODALITY_MOUSE); - EXPECT_TRUE(controller()->IsRevealed()); - event_generator.MoveMouseTo(top_container_bounds_in_screen.x(), - top_container_bounds_in_screen.bottom() + 50); - EXPECT_FALSE(controller()->IsRevealed()); - - // The mouse position cannot cause a reveal when the top container's widget - // has capture. - views::Widget* widget = top_container()->GetWidget(); - widget->SetCapture(top_container()); - AttemptReveal(MODALITY_MOUSE); - EXPECT_FALSE(controller()->IsRevealed()); - widget->ReleaseCapture(); - - // The mouse position cannot end the reveal while the top container's widget - // has capture. - AttemptReveal(MODALITY_MOUSE); - EXPECT_TRUE(controller()->IsRevealed()); - widget->SetCapture(top_container()); - event_generator.MoveMouseTo(top_container_bounds_in_screen.x(), - top_container_bounds_in_screen.bottom() + 51); - EXPECT_TRUE(controller()->IsRevealed()); - - // Releasing capture should end the reveal. - widget->ReleaseCapture(); - EXPECT_FALSE(controller()->IsRevealed()); -} - -// Test mouse event processing for top-of-screen reveal triggering when the -// top container's widget is inactive. -TEST_F(ImmersiveFullscreenControllerTest, Inactive) { - // Set up initial state. - views::Widget* popup_widget = views::Widget::CreateWindowWithContextAndBounds( - NULL, - CurrentContext(), - gfx::Rect(0, 0, 200, 200)); - popup_widget->Show(); - ASSERT_FALSE(top_container()->GetWidget()->IsActive()); - - SetEnabled(true); - ASSERT_TRUE(controller()->IsEnabled()); - ASSERT_FALSE(controller()->IsRevealed()); - - gfx::Rect top_container_bounds_in_screen = - top_container()->GetBoundsInScreen(); - gfx::Rect popup_bounds_in_screen = popup_widget->GetWindowBoundsInScreen(); - ASSERT_EQ(top_container_bounds_in_screen.origin().ToString(), - popup_bounds_in_screen.origin().ToString()); - ASSERT_GT(top_container_bounds_in_screen.right(), - popup_bounds_in_screen.right()); - - // The top-of-window views should stay hidden if the cursor is at the top edge - // but above an obscured portion of the top-of-window views. - MoveMouse(popup_bounds_in_screen.x(), - top_container_bounds_in_screen.y()); - EXPECT_FALSE(controller()->IsRevealed()); - - // The top-of-window views should reveal if the cursor is at the top edge and - // above an unobscured portion of the top-of-window views. - MoveMouse(top_container_bounds_in_screen.right() - 1, - top_container_bounds_in_screen.y()); - EXPECT_TRUE(controller()->IsRevealed()); - - // The top-of-window views should stay revealed if the cursor is moved off - // of the top edge. - MoveMouse(top_container_bounds_in_screen.right() - 1, - top_container_bounds_in_screen.bottom() - 1); - EXPECT_TRUE(controller()->IsRevealed()); - - // Moving way off of the top-of-window views should end the immersive reveal. - MoveMouse(top_container_bounds_in_screen.right() - 1, - top_container_bounds_in_screen.bottom() + 50); - EXPECT_FALSE(controller()->IsRevealed()); - - // Moving way off of the top-of-window views in a region where the - // top-of-window views are obscured should also end the immersive reveal. - // Ideally, the immersive reveal would end immediately when the cursor moves - // to an obscured portion of the top-of-window views. - MoveMouse(top_container_bounds_in_screen.right() - 1, - top_container_bounds_in_screen.y()); - EXPECT_TRUE(controller()->IsRevealed()); - MoveMouse(top_container_bounds_in_screen.x(), - top_container_bounds_in_screen.bottom() + 50); - EXPECT_FALSE(controller()->IsRevealed()); -} - -// Test mouse event processing for top-of-screen reveal triggering when the user -// has a vertical display layout (primary display above/below secondary display) -// and the immersive fullscreen window is on the bottom display. -TEST_F(ImmersiveFullscreenControllerTest, MouseEventsVerticalDisplayLayout) { - if (!SupportsMultipleDisplays()) - return; - - // Set up initial state. - UpdateDisplay("800x600,800x600"); - ash::DisplayLayout display_layout(ash::DisplayLayout::TOP, 0); - ash::Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays( - display_layout); - - SetEnabled(true); - ASSERT_TRUE(controller()->IsEnabled()); - ASSERT_FALSE(controller()->IsRevealed()); - - aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows(); - ASSERT_EQ(root_windows[0], - top_container()->GetWidget()->GetNativeWindow()->GetRootWindow()); - - gfx::Rect primary_root_window_bounds_in_screen = - root_windows[0]->GetBoundsInScreen(); - // Do not set |x| to the root window's x position because the display's - // corners have special behavior. - int x = primary_root_window_bounds_in_screen.x() + 10; - // The y position of the top edge of the primary display. - int y_top_edge = primary_root_window_bounds_in_screen.y(); - - aura::test::EventGenerator& event_generator(GetEventGenerator()); - - // Moving right below the top edge starts the hover timer running. We - // cannot use MoveMouse() because MoveMouse() stops the timer if it started - // running. - event_generator.MoveMouseTo(x, y_top_edge + 1); - EXPECT_TRUE(top_edge_hover_timer_running()); - EXPECT_EQ(y_top_edge + 1, - aura::Env::GetInstance()->last_mouse_location().y()); - - // The timer should continue running if the user moves the mouse to the top - // edge even though the mouse is warped to the secondary display. - event_generator.MoveMouseTo(x, y_top_edge); - EXPECT_TRUE(top_edge_hover_timer_running()); - EXPECT_NE(y_top_edge, - aura::Env::GetInstance()->last_mouse_location().y()); - - // The timer should continue running if the user overshoots the top edge - // a bit. - event_generator.MoveMouseTo(x, y_top_edge - 2); - EXPECT_TRUE(top_edge_hover_timer_running()); - - // The timer should stop running if the user overshoots the top edge by - // a lot. - event_generator.MoveMouseTo(x, y_top_edge - 20); - EXPECT_FALSE(top_edge_hover_timer_running()); - - // The timer should not start if the user moves the mouse to the bottom of the - // secondary display without crossing the top edge first. - event_generator.MoveMouseTo(x, y_top_edge - 2); - - // Reveal the top-of-window views by overshooting the top edge slightly. - event_generator.MoveMouseTo(x, y_top_edge + 1); - // MoveMouse() runs the timer task. - MoveMouse(x, y_top_edge - 2); - EXPECT_TRUE(controller()->IsRevealed()); - - // The top-of-window views should stay revealed if the user moves the mouse - // around in the bottom region of the secondary display. - event_generator.MoveMouseTo(x + 10, y_top_edge - 3); - EXPECT_TRUE(controller()->IsRevealed()); - - // The top-of-window views should hide if the user moves the mouse away from - // the bottom region of the secondary display. - event_generator.MoveMouseTo(x, y_top_edge - 20); - EXPECT_FALSE(controller()->IsRevealed()); - - // Test that it is possible to reveal the top-of-window views by overshooting - // the top edge slightly when the top container's widget is not active. - views::Widget* popup_widget = views::Widget::CreateWindowWithContextAndBounds( - NULL, - CurrentContext(), - gfx::Rect(0, 200, 100, 100)); - popup_widget->Show(); - ASSERT_FALSE(top_container()->GetWidget()->IsActive()); - ASSERT_FALSE(top_container()->GetBoundsInScreen().Intersects( - popup_widget->GetWindowBoundsInScreen())); - event_generator.MoveMouseTo(x, y_top_edge + 1); - MoveMouse(x, y_top_edge - 2); - EXPECT_TRUE(controller()->IsRevealed()); -} - -// Test behavior when the mouse becomes hovered without moving. -TEST_F(ImmersiveFullscreenControllerTest, MouseHoveredWithoutMoving) { - SetEnabled(true); - scoped_ptr<ImmersiveRevealedLock> lock; - - // 1) Test that if the mouse becomes hovered without the mouse moving due to a - // lock causing the top-of-window views to be revealed (and the mouse - // happening to be near the top of the screen), the top-of-window views do not - // hide till the mouse moves off of the top-of-window views. - SetHovered(true); - EXPECT_FALSE(controller()->IsRevealed()); - lock.reset(controller()->GetRevealedLock( - ImmersiveFullscreenController::ANIMATE_REVEAL_NO)); - EXPECT_TRUE(controller()->IsRevealed()); - lock.reset(); - EXPECT_TRUE(controller()->IsRevealed()); - SetHovered(false); - EXPECT_FALSE(controller()->IsRevealed()); - - // 2) Test that if the mouse becomes hovered without moving because of a - // reveal in ImmersiveFullscreenController::SetEnabled(true) and there are no - // locks keeping the top-of-window views revealed, that mouse hover does not - // prevent the top-of-window views from closing. - SetEnabled(false); - SetHovered(true); - EXPECT_FALSE(controller()->IsRevealed()); - SetEnabled(true); - EXPECT_FALSE(controller()->IsRevealed()); - - // 3) Test that if the mouse becomes hovered without moving because of a - // reveal in ImmersiveFullscreenController::SetEnabled(true) and there is a - // lock keeping the top-of-window views revealed, that the top-of-window views - // do not hide till the mouse moves off of the top-of-window views. - SetEnabled(false); - SetHovered(true); - lock.reset(controller()->GetRevealedLock( - ImmersiveFullscreenController::ANIMATE_REVEAL_NO)); - EXPECT_FALSE(controller()->IsRevealed()); - SetEnabled(true); - EXPECT_TRUE(controller()->IsRevealed()); - lock.reset(); - EXPECT_TRUE(controller()->IsRevealed()); - SetHovered(false); - EXPECT_FALSE(controller()->IsRevealed()); -} - -// Test revealing the top-of-window views using one modality and ending -// the reveal via another. For instance, initiating the reveal via a SWIPE_OPEN -// edge gesture, switching to using the mouse and ending the reveal by moving -// the mouse off of the top-of-window views. -TEST_F(ImmersiveFullscreenControllerTest, DifferentModalityEnterExit) { - SetEnabled(true); - EXPECT_TRUE(controller()->IsEnabled()); - EXPECT_FALSE(controller()->IsRevealed()); - - // Initiate reveal via gesture, end reveal via mouse. - AttemptReveal(MODALITY_GESTURE); - EXPECT_TRUE(controller()->IsRevealed()); - MoveMouse(1, 1); - EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_MOUSE); - EXPECT_FALSE(controller()->IsRevealed()); - - // Initiate reveal via gesture, end reveal via touch. - AttemptReveal(MODALITY_GESTURE); - EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_TOUCH); - EXPECT_FALSE(controller()->IsRevealed()); - - // Initiate reveal via mouse, end reveal via gesture. - AttemptReveal(MODALITY_MOUSE); - EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_GESTURE); - EXPECT_FALSE(controller()->IsRevealed()); - - // Initiate reveal via mouse, end reveal via touch. - AttemptReveal(MODALITY_MOUSE); - EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_TOUCH); - EXPECT_FALSE(controller()->IsRevealed()); -} - -// Test when the SWIPE_CLOSE edge gesture closes the top-of-window views. -TEST_F(ImmersiveFullscreenControllerTest, EndRevealViaGesture) { - SetEnabled(true); - EXPECT_TRUE(controller()->IsEnabled()); - EXPECT_FALSE(controller()->IsRevealed()); - - // A gesture should be able to close the top-of-window views when - // top-of-window views have focus. - AttemptReveal(MODALITY_MOUSE); - top_container()->RequestFocus(); - EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_GESTURE); - EXPECT_FALSE(controller()->IsRevealed()); - - // The top-of-window views should no longer have focus. Clearing focus is - // important because it closes focus-related popup windows like the touch - // selection handles. - EXPECT_FALSE(top_container()->HasFocus()); - - // If some other code is holding onto a lock, a gesture should not be able to - // end the reveal. - AttemptReveal(MODALITY_MOUSE); - scoped_ptr<ImmersiveRevealedLock> lock(controller()->GetRevealedLock( - ImmersiveFullscreenController::ANIMATE_REVEAL_NO)); - EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_GESTURE); - EXPECT_TRUE(controller()->IsRevealed()); - lock.reset(); - EXPECT_FALSE(controller()->IsRevealed()); -} - -// Do not test under windows because focus testing is not reliable on -// Windows. (crbug.com/79493) -#if !defined(OS_WIN) - -// Test how focus and activation affects whether the top-of-window views are -// revealed. -TEST_F(ImmersiveFullscreenControllerTest, Focus) { - // Add views to the view hierarchy which we will focus and unfocus during the - // test. - views::View* child_view = new views::View(); - child_view->SetBounds(0, 0, 10, 10); - child_view->SetFocusable(true); - top_container()->AddChildView(child_view); - views::View* unrelated_view = new views::View(); - unrelated_view->SetBounds(0, 100, 10, 10); - unrelated_view->SetFocusable(true); - top_container()->parent()->AddChildView(unrelated_view); - views::FocusManager* focus_manager = - top_container()->GetWidget()->GetFocusManager(); - - SetEnabled(true); - - // 1) Test that the top-of-window views stay revealed as long as either a - // |child_view| has focus or the mouse is hovered above the top-of-window - // views. - AttemptReveal(MODALITY_MOUSE); - child_view->RequestFocus(); - focus_manager->ClearFocus(); - EXPECT_TRUE(controller()->IsRevealed()); - child_view->RequestFocus(); - SetHovered(false); - EXPECT_TRUE(controller()->IsRevealed()); - focus_manager->ClearFocus(); - EXPECT_FALSE(controller()->IsRevealed()); - - // 2) Test that focusing |unrelated_view| hides the top-of-window views. - // Note: In this test we can cheat and trigger a reveal via focus because - // the top container does not hide when the top-of-window views are not - // revealed. - child_view->RequestFocus(); - EXPECT_TRUE(controller()->IsRevealed()); - unrelated_view->RequestFocus(); - EXPECT_FALSE(controller()->IsRevealed()); - - // 3) Test that a loss of focus of |child_view| to |unrelated_view| - // while immersive mode is disabled is properly registered. - child_view->RequestFocus(); - EXPECT_TRUE(controller()->IsRevealed()); - SetEnabled(false); - EXPECT_FALSE(controller()->IsRevealed()); - unrelated_view->RequestFocus(); - SetEnabled(true); - EXPECT_FALSE(controller()->IsRevealed()); - - // Repeat test but with a revealed lock acquired when immersive mode is - // disabled because the code path is different. - child_view->RequestFocus(); - EXPECT_TRUE(controller()->IsRevealed()); - SetEnabled(false); - scoped_ptr<ImmersiveRevealedLock> lock(controller()->GetRevealedLock( - ImmersiveFullscreenController::ANIMATE_REVEAL_NO)); - EXPECT_FALSE(controller()->IsRevealed()); - unrelated_view->RequestFocus(); - SetEnabled(true); - EXPECT_TRUE(controller()->IsRevealed()); - lock.reset(); - EXPECT_FALSE(controller()->IsRevealed()); -} - -// Test how transient windows affect whether the top-of-window views are -// revealed. -TEST_F(ImmersiveFullscreenControllerTest, Transient) { - views::Widget* top_container_widget = top_container()->GetWidget(); - - SetEnabled(true); - ASSERT_FALSE(controller()->IsRevealed()); - - // 1) Test that a transient window which is not a bubble does not trigger a - // reveal but does keep the top-of-window views revealed if they are already - // revealed. - views::Widget::InitParams transient_params; - transient_params.ownership = - views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - transient_params.parent = top_container_widget->GetNativeView(); - transient_params.bounds = gfx::Rect(0, 100, 100, 100); - scoped_ptr<views::Widget> transient_widget(new views::Widget()); - transient_widget->Init(transient_params); - - EXPECT_FALSE(controller()->IsRevealed()); - AttemptReveal(MODALITY_MOUSE); - EXPECT_TRUE(controller()->IsRevealed()); - transient_widget->Show(); - SetHovered(false); - EXPECT_TRUE(controller()->IsRevealed()); - transient_widget.reset(); - EXPECT_FALSE(controller()->IsRevealed()); - - // 2) Test that activating a non-transient window does not keep the - // top-of-window views revealed. - views::Widget::InitParams non_transient_params; - non_transient_params.ownership = - views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - non_transient_params.context = top_container_widget->GetNativeView(); - non_transient_params.bounds = gfx::Rect(0, 100, 100, 100); - scoped_ptr<views::Widget> non_transient_widget(new views::Widget()); - non_transient_widget->Init(non_transient_params); - - EXPECT_FALSE(controller()->IsRevealed()); - AttemptReveal(MODALITY_MOUSE); - EXPECT_TRUE(controller()->IsRevealed()); - non_transient_widget->Show(); - SetHovered(false); - EXPECT_FALSE(controller()->IsRevealed()); -} - -// Test how bubbles affect whether the top-of-window views are revealed. -TEST_F(ImmersiveFullscreenControllerTest, Bubbles) { - scoped_ptr<ImmersiveRevealedLock> revealed_lock; - views::Widget* top_container_widget = top_container()->GetWidget(); - - // Add views to the view hierarchy to which we will anchor bubbles. - views::View* child_view = new views::View(); - child_view->SetBounds(0, 0, 10, 10); - top_container()->AddChildView(child_view); - views::View* unrelated_view = new views::View(); - unrelated_view->SetBounds(0, 100, 10, 10); - top_container()->parent()->AddChildView(unrelated_view); - - SetEnabled(true); - ASSERT_FALSE(controller()->IsRevealed()); - - // 1) Test that a bubble anchored to a child of the top container triggers - // a reveal and keeps the top-of-window views revealed for the duration of - // its visibility. - views::Widget* bubble_widget1(views::BubbleDelegateView::CreateBubble( - new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE))); - bubble_widget1->Show(); - EXPECT_TRUE(controller()->IsRevealed()); - - // Activating |top_container_widget| will close |bubble_widget1|. - top_container_widget->Activate(); - AttemptReveal(MODALITY_MOUSE); - revealed_lock.reset(controller()->GetRevealedLock( - ImmersiveFullscreenController::ANIMATE_REVEAL_NO)); - EXPECT_TRUE(controller()->IsRevealed()); - - views::Widget* bubble_widget2 = views::BubbleDelegateView::CreateBubble( - new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE)); - bubble_widget2->Show(); - EXPECT_TRUE(controller()->IsRevealed()); - revealed_lock.reset(); - SetHovered(false); - EXPECT_TRUE(controller()->IsRevealed()); - bubble_widget2->Close(); - EXPECT_FALSE(controller()->IsRevealed()); - - // 2) Test that transitioning from keeping the top-of-window views revealed - // because of a bubble to keeping the top-of-window views revealed because of - // mouse hover by activating |top_container_widget| works. - views::Widget* bubble_widget3 = views::BubbleDelegateView::CreateBubble( - new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE)); - bubble_widget3->Show(); - SetHovered(true); - EXPECT_TRUE(controller()->IsRevealed()); - top_container_widget->Activate(); - EXPECT_TRUE(controller()->IsRevealed()); - - // 3) Test that the top-of-window views stay revealed as long as at least one - // bubble anchored to a child of the top container is visible. - SetHovered(false); - EXPECT_FALSE(controller()->IsRevealed()); - - views::BubbleDelegateView* bubble_delegate4(new views::BubbleDelegateView( - child_view, views::BubbleBorder::NONE)); - bubble_delegate4->set_use_focusless(true); - views::Widget* bubble_widget4(views::BubbleDelegateView::CreateBubble( - bubble_delegate4)); - bubble_widget4->Show(); - - views::BubbleDelegateView* bubble_delegate5(new views::BubbleDelegateView( - child_view, views::BubbleBorder::NONE)); - bubble_delegate5->set_use_focusless(true); - views::Widget* bubble_widget5(views::BubbleDelegateView::CreateBubble( - bubble_delegate5)); - bubble_widget5->Show(); - - EXPECT_TRUE(controller()->IsRevealed()); - bubble_widget4->Hide(); - EXPECT_TRUE(controller()->IsRevealed()); - bubble_widget5->Hide(); - EXPECT_FALSE(controller()->IsRevealed()); - bubble_widget5->Show(); - EXPECT_TRUE(controller()->IsRevealed()); - - // 4) Test that visibility changes which occur while immersive fullscreen is - // disabled are handled upon reenabling immersive fullscreen. - SetEnabled(false); - bubble_widget5->Hide(); - SetEnabled(true); - EXPECT_FALSE(controller()->IsRevealed()); - - // We do not need |bubble_widget4| or |bubble_widget5| anymore, close them. - bubble_widget4->Close(); - bubble_widget5->Close(); - - // 5) Test that a bubble added while immersive fullscreen is disabled is - // handled upon reenabling immersive fullscreen. - SetEnabled(false); - - views::Widget* bubble_widget6 = views::BubbleDelegateView::CreateBubble( - new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE)); - bubble_widget6->Show(); - - SetEnabled(true); - EXPECT_TRUE(controller()->IsRevealed()); - - bubble_widget6->Close(); - - // 6) Test that a bubble which is not anchored to a child of the - // TopContainerView does not trigger a reveal or keep the - // top-of-window views revealed if they are already revealed. - views::Widget* bubble_widget7 = views::BubbleDelegateView::CreateBubble( - new views::BubbleDelegateView(unrelated_view, views::BubbleBorder::NONE)); - bubble_widget7->Show(); - EXPECT_FALSE(controller()->IsRevealed()); - - // Activating |top_container_widget| will close |bubble_widget6|. - top_container_widget->Activate(); - AttemptReveal(MODALITY_MOUSE); - EXPECT_TRUE(controller()->IsRevealed()); - - views::Widget* bubble_widget8 = views::BubbleDelegateView::CreateBubble( - new views::BubbleDelegateView(unrelated_view, views::BubbleBorder::NONE)); - bubble_widget8->Show(); - SetHovered(false); - EXPECT_FALSE(controller()->IsRevealed()); - bubble_widget8->Close(); -} - -#endif // defined(OS_WIN) - -// Test that the shelf is set to auto hide as long as the window is in -// immersive fullscreen and that the shelf's state before entering immersive -// fullscreen is restored upon exiting immersive fullscreen. -TEST_F(ImmersiveFullscreenControllerTest, Shelf) { - ash::internal::ShelfLayoutManager* shelf = - ash::Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); - - // Shelf is visible by default. - window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - ASSERT_FALSE(controller()->IsEnabled()); - ASSERT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state()); - - // Entering immersive fullscreen sets the shelf to auto hide. - window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - SetEnabled(true); - EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state()); - - // Disabling immersive fullscreen puts it back. - SetEnabled(false); - window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - ASSERT_FALSE(controller()->IsEnabled()); - EXPECT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state()); - - // The user could toggle the shelf auto-hide behavior. - shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state()); - - // Entering immersive fullscreen keeps auto-hide. - window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - SetEnabled(true); - EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state()); - - // Disabling immersive fullscreen maintains the user's auto-hide selection. - SetEnabled(false); - window()->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_NORMAL); - EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state()); -} - -} // namespase ash - -#endif // defined(OS_CHROMEOS) diff --git a/chromium/ash/wm/immersive_revealed_lock.cc b/chromium/ash/wm/immersive_revealed_lock.cc deleted file mode 100644 index 052c2131790..00000000000 --- a/chromium/ash/wm/immersive_revealed_lock.cc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 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/immersive_revealed_lock.h" - -namespace ash { - -ImmersiveRevealedLock::ImmersiveRevealedLock( - const base::WeakPtr<Delegate>& delegate, - Delegate::AnimateReveal animate_reveal) - : delegate_(delegate) { - delegate_->LockRevealedState(animate_reveal); -} - -ImmersiveRevealedLock::~ImmersiveRevealedLock() { - if (delegate_) - delegate_->UnlockRevealedState(); -} - -} // namespace ash diff --git a/chromium/ash/wm/immersive_revealed_lock.h b/chromium/ash/wm/immersive_revealed_lock.h deleted file mode 100644 index a7dbea51bc2..00000000000 --- a/chromium/ash/wm/immersive_revealed_lock.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2013 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_IMMERSIVE_REVEALED_LOCK_H_ -#define ASH_WM_IMMERSIVE_REVEALED_LOCK_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/memory/weak_ptr.h" - -namespace ash { - -// Class which keeps the top-of-window views revealed for the duration of its -// lifetime. If acquiring the lock causes a reveal, the top-of-window views -// will animate according to the |animate_reveal| parameter passed in the -// constructor. See ImmersiveFullscreenController::GetRevealedLock() for more -// details. -class ASH_EXPORT ImmersiveRevealedLock { - public: - class ASH_EXPORT Delegate { - public: - enum AnimateReveal { - ANIMATE_REVEAL_YES, - ANIMATE_REVEAL_NO - }; - - virtual void LockRevealedState(AnimateReveal animate_reveal) = 0; - virtual void UnlockRevealedState() = 0; - - protected: - virtual ~Delegate() {} - }; - - ImmersiveRevealedLock(const base::WeakPtr<Delegate>& delegate, - Delegate::AnimateReveal animate_reveal); - ~ImmersiveRevealedLock(); - - private: - base::WeakPtr<Delegate> delegate_; - - DISALLOW_COPY_AND_ASSIGN(ImmersiveRevealedLock); -}; - -} // namespace ash - -#endif // ASH_WM_IMMERSIVE_REVEALED_LOCK_H_ diff --git a/chromium/ash/wm/lock_state_controller.cc b/chromium/ash/wm/lock_state_controller.cc deleted file mode 100644 index cffbb6bd577..00000000000 --- a/chromium/ash/wm/lock_state_controller.cc +++ /dev/null @@ -1,674 +0,0 @@ -// Copyright 2013 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/lock_state_controller.h" - -#include <algorithm> - -#include "ash/accessibility_delegate.h" -#include "ash/ash_switches.h" -#include "ash/cancel_mode.h" -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/shell.h" -#include "ash/shell_delegate.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/session_state_animator.h" -#include "base/bind_helpers.h" -#include "base/command_line.h" -#include "base/timer/timer.h" -#include "content/public/browser/user_metrics.h" -#include "ui/aura/root_window.h" -#include "ui/compositor/layer_animation_sequence.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/views/corewm/compound_event_filter.h" - -#if defined(OS_CHROMEOS) -#include "base/sys_info.h" -#include "media/audio/sounds/sounds_manager.h" -#endif - -#if defined(OS_CHROMEOS) -using media::SoundsManager; -#endif - -namespace ash { - -namespace { - -const int kMaxShutdownSoundDurationMs = 1500; - -aura::Window* GetBackground() { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - return Shell::GetContainer(root_window, - internal::kShellWindowId_DesktopBackgroundContainer); -} - -bool IsBackgroundHidden() { - return !GetBackground()->IsVisible(); -} - -void ShowBackground() { - ui::ScopedLayerAnimationSettings settings( - GetBackground()->layer()->GetAnimator()); - settings.SetTransitionDuration(base::TimeDelta()); - GetBackground()->Show(); -} - -void HideBackground() { - ui::ScopedLayerAnimationSettings settings( - GetBackground()->layer()->GetAnimator()); - settings.SetTransitionDuration(base::TimeDelta()); - GetBackground()->Hide(); -} - -// This observer is intended to use in cases when some action has to be taken -// once some animation successfully completes (i.e. it was not aborted). -// Observer will count a number of sequences it is attached to, and a number of -// finished sequences (either Ended or Aborted). Once these two numbers are -// equal, observer will delete itself, calling callback passed to constructor if -// there were no aborted animations. -// This way it can be either used to wait for some animation to be finished in -// multiple layers, to wait once a sequence of animations is finished in one -// layer or the mixture of both. -class AnimationFinishedObserver : public ui::LayerAnimationObserver { - public: - explicit AnimationFinishedObserver(base::Closure &callback) - : callback_(callback), - sequences_attached_(0), - sequences_completed_(0), - paused_(false) { - } - - // Pauses observer: no checks will be made while paused. It can be used when - // a sequence has some immediate animations in the beginning, and for - // animations that can be tested with flag that makes all animations - // immediate. - void Pause() { - paused_ = true; - } - - // Unpauses observer. It does a check and calls callback if conditions are - // met. - void Unpause() { - if (!paused_) - return; - paused_ = false; - if (sequences_completed_ == sequences_attached_) { - callback_.Run(); - delete this; - } - } - - private: - virtual ~AnimationFinishedObserver() { - } - - // LayerAnimationObserver implementation - virtual void OnLayerAnimationEnded( - ui::LayerAnimationSequence* sequence) OVERRIDE { - sequences_completed_++; - if ((sequences_completed_ == sequences_attached_) && !paused_) { - callback_.Run(); - delete this; - } - } - - virtual void OnLayerAnimationAborted( - ui::LayerAnimationSequence* sequence) OVERRIDE { - sequences_completed_++; - if ((sequences_completed_ == sequences_attached_) && !paused_) - delete this; - } - - virtual void OnLayerAnimationScheduled( - ui::LayerAnimationSequence* sequence) OVERRIDE { - } - - virtual void OnAttachedToSequence( - ui::LayerAnimationSequence* sequence) OVERRIDE { - LayerAnimationObserver::OnAttachedToSequence(sequence); - sequences_attached_++; - } - - // Callback to be called. - base::Closure callback_; - - // Number of sequences this observer was attached to. - int sequences_attached_; - - // Number of sequences either ended or aborted. - int sequences_completed_; - - bool paused_; - - DISALLOW_COPY_AND_ASSIGN(AnimationFinishedObserver); -}; - -} // namespace - -const int LockStateController::kLockTimeoutMs = 400; -const int LockStateController::kShutdownTimeoutMs = 400; -const int LockStateController::kLockFailTimeoutMs = 8000; -const int LockStateController::kLockToShutdownTimeoutMs = 150; -const int LockStateController::kShutdownRequestDelayMs = 50; - -LockStateController::TestApi::TestApi(LockStateController* controller) - : controller_(controller) { -} - -LockStateController::TestApi::~TestApi() { -} - -LockStateController::LockStateController() - : animator_(new internal::SessionStateAnimator()), - login_status_(user::LOGGED_IN_NONE), - system_is_locked_(false), - shutting_down_(false), - shutdown_after_lock_(false), - animating_lock_(false), - can_cancel_lock_animation_(false) { - Shell::GetPrimaryRootWindow()->GetDispatcher()->AddRootWindowObserver(this); -} - -LockStateController::~LockStateController() { - Shell::GetPrimaryRootWindow()->GetDispatcher()->RemoveRootWindowObserver( - this); -} - -void LockStateController::SetDelegate(LockStateControllerDelegate* delegate) { - delegate_.reset(delegate); -} - -void LockStateController::AddObserver(LockStateObserver* observer) { - observers_.AddObserver(observer); -} - -void LockStateController::RemoveObserver(LockStateObserver* observer) { - observers_.RemoveObserver(observer); -} - -bool LockStateController::HasObserver(LockStateObserver* observer) { - return observers_.HasObserver(observer); -} - -void LockStateController::StartLockAnimation( - bool shutdown_after_lock) { - if (animating_lock_) - return; - shutdown_after_lock_ = shutdown_after_lock; - can_cancel_lock_animation_ = true; - - StartCancellablePreLockAnimation(); -} - -void LockStateController::StartShutdownAnimation() { - StartCancellableShutdownAnimation(); -} - -void LockStateController::StartLockAnimationAndLockImmediately() { - if (animating_lock_) - return; - StartImmediatePreLockAnimation(true /* request_lock_on_completion */); -} - -bool LockStateController::LockRequested() { - return lock_fail_timer_.IsRunning(); -} - -bool LockStateController::ShutdownRequested() { - return shutting_down_; -} - -bool LockStateController::CanCancelLockAnimation() { - return can_cancel_lock_animation_; -} - -void LockStateController::CancelLockAnimation() { - if (!CanCancelLockAnimation()) - return; - shutdown_after_lock_ = false; - animating_lock_ = false; - CancelPreLockAnimation(); -} - -bool LockStateController::CanCancelShutdownAnimation() { - return pre_shutdown_timer_.IsRunning() || - shutdown_after_lock_ || - lock_to_shutdown_timer_.IsRunning(); -} - -void LockStateController::CancelShutdownAnimation() { - if (!CanCancelShutdownAnimation()) - return; - if (lock_to_shutdown_timer_.IsRunning()) { - lock_to_shutdown_timer_.Stop(); - return; - } - if (shutdown_after_lock_) { - shutdown_after_lock_ = false; - return; - } - - animator_->StartGlobalAnimation( - internal::SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS, - internal::SessionStateAnimator::ANIMATION_SPEED_REVERT_SHUTDOWN); - pre_shutdown_timer_.Stop(); -} - -void LockStateController::OnStartingLock() { - if (shutting_down_ || system_is_locked_) - return; - if (animating_lock_) - return; - StartImmediatePreLockAnimation(false /* request_lock_on_completion */); -} - -void LockStateController::RequestShutdown() { - if (shutting_down_) - return; - - shutting_down_ = true; - - Shell* shell = ash::Shell::GetInstance(); - shell->cursor_manager()->HideCursor(); - - animator_->StartGlobalAnimation( - internal::SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS, - internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); - StartRealShutdownTimer(true); -} - -void LockStateController::OnLockScreenHide( - base::Callback<void(void)>& callback) { - StartUnlockAnimationBeforeUIDestroyed(callback); -} - -void LockStateController::SetLockScreenDisplayedCallback( - const base::Closure& callback) { - lock_screen_displayed_callback_ = callback; -} - -void LockStateController::OnRootWindowHostCloseRequested( - const aura::RootWindow*) { - Shell::GetInstance()->delegate()->Exit(); -} - -void LockStateController::OnLoginStateChanged( - user::LoginStatus status) { - if (status != user::LOGGED_IN_LOCKED) - login_status_ = status; - system_is_locked_ = (status == user::LOGGED_IN_LOCKED); -} - -void LockStateController::OnAppTerminating() { - // If we hear that Chrome is exiting but didn't request it ourselves, all we - // can really hope for is that we'll have time to clear the screen. - // This is also the case when the user signs off. - if (!shutting_down_) { - shutting_down_ = true; - Shell* shell = ash::Shell::GetInstance(); - shell->cursor_manager()->HideCursor(); - shell->cursor_manager()->LockCursor(); - animator_->StartAnimation( - internal::SessionStateAnimator::kAllContainersMask, - internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY, - internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE); - } -} - -void LockStateController::OnLockStateChanged(bool locked) { - if (shutting_down_ || (system_is_locked_ == locked)) - return; - - system_is_locked_ = locked; - - if (locked) { - StartPostLockAnimation(); - lock_fail_timer_.Stop(); - } else { - StartUnlockAnimationAfterUIDestroyed(); - } -} - -void LockStateController::OnLockFailTimeout() { - DCHECK(!system_is_locked_); - // Undo lock animation. - StartUnlockAnimationAfterUIDestroyed(); -} - -void LockStateController::StartLockToShutdownTimer() { - shutdown_after_lock_ = false; - lock_to_shutdown_timer_.Stop(); - lock_to_shutdown_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kLockToShutdownTimeoutMs), - this, &LockStateController::OnLockToShutdownTimeout); -} - -void LockStateController::OnLockToShutdownTimeout() { - DCHECK(system_is_locked_); - StartCancellableShutdownAnimation(); -} - -void LockStateController::StartPreShutdownAnimationTimer() { - pre_shutdown_timer_.Stop(); - pre_shutdown_timer_.Start( - FROM_HERE, - animator_-> - GetDuration(internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN), - this, - &LockStateController::OnPreShutdownAnimationTimeout); -} - -void LockStateController::OnPreShutdownAnimationTimeout() { - shutting_down_ = true; - - Shell* shell = ash::Shell::GetInstance(); - shell->cursor_manager()->HideCursor(); - - StartRealShutdownTimer(false); -} - -void LockStateController::StartRealShutdownTimer(bool with_animation_time) { - base::TimeDelta duration = - base::TimeDelta::FromMilliseconds(kShutdownRequestDelayMs); - if (with_animation_time) { - duration += animator_->GetDuration( - internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); - } - -#if defined(OS_CHROMEOS) - const AccessibilityDelegate* const delegate = - Shell::GetInstance()->accessibility_delegate(); - base::TimeDelta sound_duration = delegate->PlayShutdownSound(); - sound_duration = - std::min(sound_duration, - base::TimeDelta::FromMilliseconds(kMaxShutdownSoundDurationMs)); - duration = std::max(duration, sound_duration); -#endif - - real_shutdown_timer_.Start( - FROM_HERE, duration, this, &LockStateController::OnRealShutdownTimeout); -} - -void LockStateController::OnRealShutdownTimeout() { - DCHECK(shutting_down_); -#if defined(OS_CHROMEOS) - if (!base::SysInfo::IsRunningOnChromeOS()) { - ShellDelegate* delegate = Shell::GetInstance()->delegate(); - if (delegate) { - delegate->Exit(); - return; - } - } -#endif - Shell::GetInstance()->metrics()->RecordUserMetricsAction( - UMA_ACCEL_SHUT_DOWN_POWER_BUTTON); - delegate_->RequestShutdown(); -} - -void LockStateController::StartCancellableShutdownAnimation() { - Shell* shell = ash::Shell::GetInstance(); - // Hide cursor, but let it reappear if the mouse moves. - shell->cursor_manager()->HideCursor(); - - animator_->StartGlobalAnimation( - internal::SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS, - internal::SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); - StartPreShutdownAnimationTimer(); -} - -void LockStateController::StartImmediatePreLockAnimation( - bool request_lock_on_completion) { - animating_lock_ = true; - - StoreUnlockedProperties(); - - base::Closure next_animation_starter = - base::Bind(&LockStateController::PreLockAnimationFinished, - base::Unretained(this), request_lock_on_completion); - AnimationFinishedObserver* observer = - new AnimationFinishedObserver(next_animation_starter); - - observer->Pause(); - - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, - internal::SessionStateAnimator::ANIMATION_LIFT, - internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, - observer); - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::LAUNCHER, - internal::SessionStateAnimator::ANIMATION_FADE_OUT, - internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, - observer); - // Hide the screen locker containers so we can raise them later. - animator_->StartAnimation( - internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY, - internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE); - AnimateBackgroundAppearanceIfNecessary( - internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, - observer); - - observer->Unpause(); - - DispatchCancelMode(); - FOR_EACH_OBSERVER(LockStateObserver, observers_, - OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_STARTED)); -} - -void LockStateController::StartCancellablePreLockAnimation() { - animating_lock_ = true; - StoreUnlockedProperties(); - - base::Closure next_animation_starter = - base::Bind(&LockStateController::PreLockAnimationFinished, - base::Unretained(this), true /* request_lock */); - AnimationFinishedObserver* observer = - new AnimationFinishedObserver(next_animation_starter); - - observer->Pause(); - - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, - internal::SessionStateAnimator::ANIMATION_LIFT, - internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, - observer); - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::LAUNCHER, - internal::SessionStateAnimator::ANIMATION_FADE_OUT, - internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, - observer); - // Hide the screen locker containers so we can raise them later. - animator_->StartAnimation( - internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY, - internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE); - AnimateBackgroundAppearanceIfNecessary( - internal::SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, - observer); - - DispatchCancelMode(); - FOR_EACH_OBSERVER(LockStateObserver, observers_, - OnLockStateEvent(LockStateObserver::EVENT_PRELOCK_ANIMATION_STARTED)); - observer->Unpause(); -} - -void LockStateController::CancelPreLockAnimation() { - base::Closure next_animation_starter = - base::Bind(&LockStateController::LockAnimationCancelled, - base::Unretained(this)); - AnimationFinishedObserver* observer = - new AnimationFinishedObserver(next_animation_starter); - - observer->Pause(); - - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, - internal::SessionStateAnimator::ANIMATION_UNDO_LIFT, - internal::SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS, - observer); - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::LAUNCHER, - internal::SessionStateAnimator::ANIMATION_FADE_IN, - internal::SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS, - observer); - AnimateBackgroundHidingIfNecessary( - internal::SessionStateAnimator::ANIMATION_SPEED_UNDO_MOVE_WINDOWS, - observer); - - observer->Unpause(); -} - -void LockStateController::StartPostLockAnimation() { - base::Closure next_animation_starter = - base::Bind(&LockStateController::PostLockAnimationFinished, - base::Unretained(this)); - - AnimationFinishedObserver* observer = - new AnimationFinishedObserver(next_animation_starter); - - observer->Pause(); - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - internal::SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN, - internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, - observer); - observer->Unpause(); -} - -void LockStateController::StartUnlockAnimationBeforeUIDestroyed( - base::Closure& callback) { - animator_->StartAnimationWithCallback( - internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - internal::SessionStateAnimator::ANIMATION_LIFT, - internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, - callback); -} - -void LockStateController::StartUnlockAnimationAfterUIDestroyed() { - base::Closure next_animation_starter = - base::Bind(&LockStateController::UnlockAnimationAfterUIDestroyedFinished, - base::Unretained(this)); - - AnimationFinishedObserver* observer = - new AnimationFinishedObserver(next_animation_starter); - - observer->Pause(); - - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, - internal::SessionStateAnimator::ANIMATION_DROP, - internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, - observer); - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::LAUNCHER, - internal::SessionStateAnimator::ANIMATION_FADE_IN, - internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, - observer); - AnimateBackgroundHidingIfNecessary( - internal::SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, - observer); - observer->Unpause(); -} - -void LockStateController::LockAnimationCancelled() { - can_cancel_lock_animation_ = false; - RestoreUnlockedProperties(); -} - -void LockStateController::PreLockAnimationFinished(bool request_lock) { - can_cancel_lock_animation_ = false; - - if (request_lock) { - Shell::GetInstance()->metrics()->RecordUserMetricsAction( - shutdown_after_lock_ ? - UMA_ACCEL_LOCK_SCREEN_POWER_BUTTON : - UMA_ACCEL_LOCK_SCREEN_LOCK_BUTTON); - delegate_->RequestLockScreen(); - } - - lock_fail_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kLockFailTimeoutMs), - this, - &LockStateController::OnLockFailTimeout); -} - -void LockStateController::PostLockAnimationFinished() { - animating_lock_ = false; - - FOR_EACH_OBSERVER(LockStateObserver, observers_, - OnLockStateEvent(LockStateObserver::EVENT_LOCK_ANIMATION_FINISHED)); - if (!lock_screen_displayed_callback_.is_null()) { - lock_screen_displayed_callback_.Run(); - lock_screen_displayed_callback_.Reset(); - } - if (shutdown_after_lock_) { - shutdown_after_lock_ = false; - StartLockToShutdownTimer(); - } -} - -void LockStateController::UnlockAnimationAfterUIDestroyedFinished() { - RestoreUnlockedProperties(); -} - -void LockStateController::StoreUnlockedProperties() { - if (!unlocked_properties_) { - unlocked_properties_.reset(new UnlockedStateProperties()); - unlocked_properties_->background_is_hidden = IsBackgroundHidden(); - } - if (unlocked_properties_->background_is_hidden) { - // Hide background so that it can be animated later. - animator_->StartAnimation( - internal::SessionStateAnimator::DESKTOP_BACKGROUND, - internal::SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY, - internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE); - ShowBackground(); - } -} - -void LockStateController::RestoreUnlockedProperties() { - if (!unlocked_properties_) - return; - if (unlocked_properties_->background_is_hidden) { - HideBackground(); - // Restore background visibility. - animator_->StartAnimation( - internal::SessionStateAnimator::DESKTOP_BACKGROUND, - internal::SessionStateAnimator::ANIMATION_FADE_IN, - internal::SessionStateAnimator::ANIMATION_SPEED_IMMEDIATE); - } - unlocked_properties_.reset(); -} - -void LockStateController::AnimateBackgroundAppearanceIfNecessary( - internal::SessionStateAnimator::AnimationSpeed speed, - ui::LayerAnimationObserver* observer) { - if (unlocked_properties_.get() && - unlocked_properties_->background_is_hidden) { - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::DESKTOP_BACKGROUND, - internal::SessionStateAnimator::ANIMATION_FADE_IN, - speed, - observer); - } -} - -void LockStateController::AnimateBackgroundHidingIfNecessary( - internal::SessionStateAnimator::AnimationSpeed speed, - ui::LayerAnimationObserver* observer) { - if (unlocked_properties_.get() && - unlocked_properties_->background_is_hidden) { - animator_->StartAnimationWithObserver( - internal::SessionStateAnimator::DESKTOP_BACKGROUND, - internal::SessionStateAnimator::ANIMATION_FADE_OUT, - speed, - observer); - } -} - -} // namespace ash diff --git a/chromium/ash/wm/lock_state_controller.h b/chromium/ash/wm/lock_state_controller.h deleted file mode 100644 index c2e7a6aab60..00000000000 --- a/chromium/ash/wm/lock_state_controller.h +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright 2013 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_LOCK_STATE_CONTROLLER_H_ -#define ASH_WM_LOCK_STATE_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "ash/shell_observer.h" -#include "ash/wm/lock_state_observer.h" -#include "ash/wm/session_state_animator.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "ui/aura/root_window_observer.h" - -namespace gfx { -class Rect; -class Size; -} - -namespace ui { -class Layer; -} - -namespace ash { - -namespace test { -class LockStateControllerTest; -class PowerButtonControllerTest; -} - -// Performs system-related functions on behalf of LockStateController. -class ASH_EXPORT LockStateControllerDelegate { - public: - LockStateControllerDelegate() {} - virtual ~LockStateControllerDelegate() {} - - virtual void RequestLockScreen() = 0; - virtual void RequestShutdown() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(LockStateControllerDelegate); -}; - -// Displays onscreen animations and locks or suspends the system in response to -// the power button being pressed or released. -// Lock workflow: -// Entry points: -// * StartLockAnimation (bool shutdown after lock) - starts lock that can be -// cancelled. -// * StartLockAnimationAndLockImmediately - starts uninterruptible lock -// animation. -// This leads to call of either StartImmediatePreLockAnimation or -// StartCancellablePreLockAnimation. Once they complete -// PreLockAnimationFinished is called, and system lock is requested. -// Once system locks and lock UI is created, OnLockStateChanged is called, and -// StartPostLockAnimation is called. In PostLockAnimationFinished two -// things happen : EVENT_LOCK_ANIMATION_FINISHED notification is sent (it -// triggers third part of animation within lock UI), and check for continuing to -// shutdown is made. -// -// Unlock workflow: -// WebUI does first part of animation, and calls OnLockScreenHide(callback) that -// triggers StartUnlockAnimationBeforeUIDestroyed(callback). Once callback is -// called at the end of the animation, lock UI is deleted, system unlocks, and -// OnLockStateChanged is called. It leads to -// StartUnlockAnimationAfterUIDestroyed. -class ASH_EXPORT LockStateController : public aura::RootWindowObserver, - public ShellObserver { - public: - // Amount of time that the power button needs to be held before we lock the - // screen. - static const int kLockTimeoutMs; - - // Amount of time that the power button needs to be held before we shut down. - static const int kShutdownTimeoutMs; - - // Amount of time to wait for our lock requests to be honored before giving - // up. - static const int kLockFailTimeoutMs; - - // When the button has been held continuously from the unlocked state, amount - // of time that we wait after the screen locker window is shown before - // starting the pre-shutdown animation. - static const int kLockToShutdownTimeoutMs; - - // Additional time (beyond kFastCloseAnimMs) to wait after starting the - // fast-close shutdown animation before actually requesting shutdown, to give - // the animation time to finish. - static const int kShutdownRequestDelayMs; - - // Helper class used by tests to access internal state. - class ASH_EXPORT TestApi { - public: - explicit TestApi(LockStateController* controller); - - virtual ~TestApi(); - - bool lock_fail_timer_is_running() const { - return controller_->lock_fail_timer_.IsRunning(); - } - bool lock_to_shutdown_timer_is_running() const { - return controller_->lock_to_shutdown_timer_.IsRunning(); - } - bool shutdown_timer_is_running() const { - return controller_->pre_shutdown_timer_.IsRunning(); - } - bool real_shutdown_timer_is_running() const { - return controller_->real_shutdown_timer_.IsRunning(); - } - bool is_animating_lock() const { - return controller_->animating_lock_; - } - bool is_lock_cancellable() const { - return controller_->CanCancelLockAnimation(); - } - - void trigger_lock_fail_timeout() { - controller_->OnLockFailTimeout(); - controller_->lock_fail_timer_.Stop(); - } - void trigger_lock_to_shutdown_timeout() { - controller_->OnLockToShutdownTimeout(); - controller_->lock_to_shutdown_timer_.Stop(); - } - void trigger_shutdown_timeout() { - controller_->OnPreShutdownAnimationTimeout(); - controller_->pre_shutdown_timer_.Stop(); - } - void trigger_real_shutdown_timeout() { - controller_->OnRealShutdownTimeout(); - controller_->real_shutdown_timer_.Stop(); - } - private: - LockStateController* controller_; // not owned - - DISALLOW_COPY_AND_ASSIGN(TestApi); - }; - - LockStateController(); - virtual ~LockStateController(); - - // Takes ownership of |delegate|. - void SetDelegate(LockStateControllerDelegate* delegate); - - void AddObserver(LockStateObserver* observer); - void RemoveObserver(LockStateObserver* observer); - bool HasObserver(LockStateObserver* observer); - - // Starts locking (with slow animation) that can be cancelled. - // After locking and |kLockToShutdownTimeoutMs| StartShutdownAnimation() - // will be called unless CancelShutdownAnimation() is called, if - // |shutdown_after_lock| is true. - void StartLockAnimation(bool shutdown_after_lock); - - // Starts shutting down (with slow animation) that can be cancelled. - void StartShutdownAnimation(); - - // Starts usual lock animation, but locks immediately. - // Unlike StartLockAnimation it does no lead to StartShutdownAnimation. - void StartLockAnimationAndLockImmediately(); - - // Returns true if we have requested system to lock, but haven't received - // confirmation yet. - bool LockRequested(); - - // Returns true if we are shutting down. - bool ShutdownRequested(); - - // Returns true if we are within cancellable lock timeframe. - bool CanCancelLockAnimation(); - - // Cancels locking and reverts lock animation. - void CancelLockAnimation(); - - // Returns true if we are within cancellable shutdown timeframe. - bool CanCancelShutdownAnimation(); - - // Cancels shutting down and reverts shutdown animation. - void CancelShutdownAnimation(); - - // Called when Chrome gets a request to display the lock screen. - void OnStartingLock(); - - // Displays the shutdown animation and requests shutdown when it's done. - void RequestShutdown(); - - // Called when ScreenLocker is ready to close, but not yet destroyed. - // Can be used to display "hiding" animations on unlock. - // |callback| will be called when all animations are done. - void OnLockScreenHide(base::Closure& callback); - - // Sets up the callback that should be called once lock animation is finished. - // Callback is guaranteed to be called once and then discarded. - void SetLockScreenDisplayedCallback(const base::Closure& callback); - - // RootWindowObserver override: - virtual void OnRootWindowHostCloseRequested( - const aura::RootWindow* root) OVERRIDE; - - // ShellObserver overrides: - virtual void OnLoginStateChanged(user::LoginStatus status) OVERRIDE; - virtual void OnAppTerminating() OVERRIDE; - virtual void OnLockStateChanged(bool locked) OVERRIDE; - - private: - friend class test::PowerButtonControllerTest; - friend class test::LockStateControllerTest; - - struct UnlockedStateProperties { - bool background_is_hidden; - }; - - // Reverts the pre-lock animation, reports the error. - void OnLockFailTimeout(); - - // Starts timer for gap between lock and shutdown. - void StartLockToShutdownTimer(); - - // Calls StartShutdownAnimation(). - void OnLockToShutdownTimeout(); - - // Starts timer for undoable shutdown animation. - void StartPreShutdownAnimationTimer(); - - // Calls StartRealShutdownTimer(). - void OnPreShutdownAnimationTimeout(); - - // Starts timer for final shutdown animation. - // If |with_animation_time| is true, it will also include time of "fade to - // white" shutdown animation. - void StartRealShutdownTimer(bool with_animation_time); - - // Requests that the machine be shut down. - void OnRealShutdownTimeout(); - - // Starts shutdown animation that can be cancelled and starts pre-shutdown - // timer. - void StartCancellableShutdownAnimation(); - - // If |request_lock_on_completion| is true, a lock request will be sent - // after the pre-lock animation completes. (The pre-lock animation is - // also displayed in response to already-in-progress lock requests; in - // these cases an additional lock request is undesirable.) - void StartImmediatePreLockAnimation(bool request_lock_on_completion); - void StartCancellablePreLockAnimation(); - void CancelPreLockAnimation(); - void StartPostLockAnimation(); - // This method calls |callback| when animation completes. - void StartUnlockAnimationBeforeUIDestroyed(base::Closure &callback); - void StartUnlockAnimationAfterUIDestroyed(); - - // These methods are called when corresponding animation completes. - void LockAnimationCancelled(); - void PreLockAnimationFinished(bool request_lock); - void PostLockAnimationFinished(); - void UnlockAnimationAfterUIDestroyedFinished(); - - // Stores properties of UI that have to be temporarily modified while locking. - void StoreUnlockedProperties(); - void RestoreUnlockedProperties(); - - // Fades in background layer with |speed| if it was hidden in unlocked state. - void AnimateBackgroundAppearanceIfNecessary( - ash::internal::SessionStateAnimator::AnimationSpeed speed, - ui::LayerAnimationObserver* observer); - - // Fades out background layer with |speed| if it was hidden in unlocked state. - void AnimateBackgroundHidingIfNecessary( - ash::internal::SessionStateAnimator::AnimationSpeed speed, - ui::LayerAnimationObserver* observer); - - scoped_ptr<internal::SessionStateAnimator> animator_; - - scoped_ptr<LockStateControllerDelegate> delegate_; - - ObserverList<LockStateObserver> observers_; - - // The current login status, or original login status from before we locked. - user::LoginStatus login_status_; - - // Current lock status. - bool system_is_locked_; - - // Are we in the process of shutting the machine down? - bool shutting_down_; - - // Indicates whether controller should proceed to (cancellable) shutdown after - // locking. - bool shutdown_after_lock_; - - // Indicates that controller displays lock animation. - bool animating_lock_; - - // Indicates that lock animation can be undone. - bool can_cancel_lock_animation_; - - scoped_ptr<UnlockedStateProperties> unlocked_properties_; - - // Started when we request that the screen be locked. When it fires, we - // assume that our request got dropped. - base::OneShotTimer<LockStateController> lock_fail_timer_; - - // Started when the screen is locked while the power button is held. Adds a - // delay between the appearance of the lock screen and the beginning of the - // pre-shutdown animation. - base::OneShotTimer<LockStateController> lock_to_shutdown_timer_; - - // Started when we begin displaying the pre-shutdown animation. When it - // fires, we start the shutdown animation and get ready to request shutdown. - base::OneShotTimer<LockStateController> pre_shutdown_timer_; - - // Started when we display the shutdown animation. When it fires, we actually - // request shutdown. Gives the animation time to complete before Chrome, X, - // etc. are shut down. - base::OneShotTimer<LockStateController> real_shutdown_timer_; - - base::Closure lock_screen_displayed_callback_; - - DISALLOW_COPY_AND_ASSIGN(LockStateController); -}; - -} // namespace ash - -#endif // ASH_WM_LOCK_STATE_CONTROLLER_H_ diff --git a/chromium/ash/wm/lock_state_controller_unittest.cc b/chromium/ash/wm/lock_state_controller_unittest.cc deleted file mode 100644 index 5290457d212..00000000000 --- a/chromium/ash/wm/lock_state_controller_unittest.cc +++ /dev/null @@ -1,1056 +0,0 @@ -// Copyright 2013 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/lock_state_controller.h" - -#include "ash/ash_switches.h" -#include "ash/session_state_delegate.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/test_shell_delegate.h" -#include "ash/wm/power_button_controller.h" -#include "ash/wm/session_state_animator.h" -#include "base/command_line.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/compositor/layer_animator.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/size.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - -namespace ash { - -using internal::SessionStateAnimator; - -namespace test { - -namespace { - -bool cursor_visible() { - return ash::Shell::GetInstance()->cursor_manager()->IsCursorVisible(); -} - -void CheckCalledCallback(bool* flag) { - if (flag) - (*flag) = true; -} - -aura::Window* GetContainer(int container ) { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - return Shell::GetContainer(root_window, container); -} - -bool IsBackgroundHidden() { - return !GetContainer(internal::kShellWindowId_DesktopBackgroundContainer)-> - IsVisible(); -} - -void HideBackground() { - ui::ScopedLayerAnimationSettings settings( - GetContainer(internal::kShellWindowId_DesktopBackgroundContainer)-> - layer()->GetAnimator()); - settings.SetTransitionDuration(base::TimeDelta()); - GetContainer(internal::kShellWindowId_DesktopBackgroundContainer)->Hide(); -} - -} // namespace - -// Fake implementation of PowerButtonControllerDelegate that just logs requests -// to lock the screen and shut down the device. -class TestLockStateControllerDelegate : public LockStateControllerDelegate { - public: - TestLockStateControllerDelegate() - : num_lock_requests_(0), - num_shutdown_requests_(0) {} - - int num_lock_requests() const { return num_lock_requests_; } - int num_shutdown_requests() const { return num_shutdown_requests_; } - - // LockStateControllerDelegate implementation. - virtual void RequestLockScreen() OVERRIDE { - num_lock_requests_++; - } - virtual void RequestShutdown() OVERRIDE { - num_shutdown_requests_++; - } - - private: - int num_lock_requests_; - int num_shutdown_requests_; - - DISALLOW_COPY_AND_ASSIGN(TestLockStateControllerDelegate); -}; - -class LockStateControllerTest : public AshTestBase { - public: - LockStateControllerTest() : controller_(NULL), delegate_(NULL) {} - virtual ~LockStateControllerTest() {} - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - - // We would control animations in a fine way: - animation_duration_mode_.reset(new ui::ScopedAnimationDurationScaleMode( - ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION)); - // TODO(antrim) : restore - // animator_helper_ = ui::test::CreateLayerAnimatorHelperForTest(); - - // Temporary disable animations so that observer is always called, and - // no leaks happen during tests. - animation_duration_mode_.reset(new ui::ScopedAnimationDurationScaleMode( - ui::ScopedAnimationDurationScaleMode::ZERO_DURATION)); - // TODO(antrim): once there is a way to mock time and run animations, make - // sure that animations are finished even in simple tests. - - delegate_ = new TestLockStateControllerDelegate; - controller_ = Shell::GetInstance()->power_button_controller(); - lock_state_controller_ = static_cast<LockStateController*>( - Shell::GetInstance()->lock_state_controller()); - lock_state_controller_->SetDelegate(delegate_); // transfers ownership - test_api_.reset(new LockStateController::TestApi(lock_state_controller_)); - animator_api_.reset( - new SessionStateAnimator::TestApi(lock_state_controller_-> - animator_.get())); - shell_delegate_ = reinterpret_cast<TestShellDelegate*>( - ash::Shell::GetInstance()->delegate()); - session_state_delegate_ = Shell::GetInstance()->session_state_delegate(); - } - - virtual void TearDown() { - // TODO(antrim) : restore - // animator_helper_->AdvanceUntilDone(); - AshTestBase::TearDown(); - } - - protected: - void GenerateMouseMoveEvent() { - aura::test::EventGenerator generator( - Shell::GetPrimaryRootWindow()); - generator.MoveMouseTo(10, 10); - } - - int NumShutdownRequests() { - return delegate_->num_shutdown_requests() + - shell_delegate_->num_exit_requests(); - } - - void Advance(SessionStateAnimator::AnimationSpeed speed) { - // TODO (antrim) : restore - // animator_helper_->Advance(SessionStateAnimator::GetDuration(speed)); - } - - void AdvancePartially(SessionStateAnimator::AnimationSpeed speed, - float factor) { -// TODO (antrim) : restore -// base::TimeDelta duration = SessionStateAnimator::GetDuration(speed); -// base::TimeDelta partial_duration = -// base::TimeDelta::FromInternalValue(duration.ToInternalValue() * factor); -// animator_helper_->Advance(partial_duration); - } - - void ExpectPreLockAnimationStarted() { - //TODO (antrim) : restore EXPECT_TRUE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_LIFT)); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LAUNCHER, - SessionStateAnimator::ANIMATION_FADE_OUT)); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY)); - EXPECT_TRUE(test_api_->is_animating_lock()); - } - - void ExpectPreLockAnimationCancel() { - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_DROP)); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LAUNCHER, - SessionStateAnimator::ANIMATION_FADE_IN)); - } - - void ExpectPreLockAnimationFinished() { - //TODO (antrim) : restore EXPECT_FALSE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_LIFT)); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LAUNCHER, - SessionStateAnimator::ANIMATION_FADE_OUT)); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY)); - } - - void ExpectPostLockAnimationStarted() { - //TODO (antrim) : restore EXPECT_TRUE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN)); - } - - void ExpectPastLockAnimationFinished() { - //TODO (antrim) : restore EXPECT_FALSE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN)); - } - - void ExpectUnlockBeforeUIDestroyedAnimationStarted() { - //TODO (antrim) : restore EXPECT_TRUE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_LIFT)); - } - - void ExpectUnlockBeforeUIDestroyedAnimationFinished() { - //TODO (antrim) : restore EXPECT_FALSE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_LIFT)); - } - - void ExpectUnlockAfterUIDestroyedAnimationStarted() { - //TODO (antrim) : restore EXPECT_TRUE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_DROP)); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LAUNCHER, - SessionStateAnimator::ANIMATION_FADE_IN)); - } - - void ExpectUnlockAfterUIDestroyedAnimationFinished() { - //TODO (antrim) : restore EXPECT_FALSE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, - SessionStateAnimator::ANIMATION_DROP)); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::LAUNCHER, - SessionStateAnimator::ANIMATION_FADE_IN)); - } - - void ExpectShutdownAnimationStarted() { - //TODO (antrim) : restore EXPECT_TRUE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->RootWindowIsAnimated( - SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS)); - } - - void ExpectShutdownAnimationFinished() { - //TODO (antrim) : restore EXPECT_FALSE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->RootWindowIsAnimated( - SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS)); - } - - void ExpectShutdownAnimationCancel() { - //TODO (antrim) : restore EXPECT_TRUE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->RootWindowIsAnimated( - SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS)); - } - - void ExpectBackgroundIsShowing() { - //TODO (antrim) : restore EXPECT_TRUE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::DESKTOP_BACKGROUND, - SessionStateAnimator::ANIMATION_FADE_IN)); - } - - void ExpectBackgroundIsHiding() { - //TODO (antrim) : restore EXPECT_TRUE(animator_helper_->IsAnimating()); - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::DESKTOP_BACKGROUND, - SessionStateAnimator::ANIMATION_FADE_OUT)); - } - - void ExpectUnlockedState() { - //TODO (antrim) : restore EXPECT_FALSE(animator_helper_->IsAnimating()); - EXPECT_FALSE(session_state_delegate_->IsScreenLocked()); - - aura::Window::Windows containers; - - SessionStateAnimator::GetContainers( - SessionStateAnimator::LAUNCHER | - SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, - &containers); - for (aura::Window::Windows::const_iterator it = containers.begin(); - it != containers.end(); ++it) { - aura::Window* window = *it; - ui::Layer* layer = window->layer(); - EXPECT_EQ(1.0f, layer->opacity()); - EXPECT_EQ(0.0f, layer->layer_brightness()); - EXPECT_EQ(0.0f, layer->layer_saturation()); - EXPECT_EQ(gfx::Transform(), layer->transform()); - } - } - - void ExpectLockedState() { - //TODO (antrim) : restore EXPECT_FALSE(animator_helper_->IsAnimating()); - EXPECT_TRUE(session_state_delegate_->IsScreenLocked()); - - aura::Window::Windows containers; - - SessionStateAnimator::GetContainers( - SessionStateAnimator::LOCK_SCREEN_RELATED_CONTAINERS | - SessionStateAnimator::LOCK_SCREEN_CONTAINERS, - &containers); - for (aura::Window::Windows::const_iterator it = containers.begin(); - it != containers.end(); ++it) { - aura::Window* window = *it; - ui::Layer* layer = window->layer(); - EXPECT_EQ(1.0f, layer->opacity()); - EXPECT_EQ(0.0f, layer->layer_brightness()); - EXPECT_EQ(0.0f, layer->layer_saturation()); - EXPECT_EQ(gfx::Transform(), layer->transform()); - } - } - - void PressPowerButton() { - controller_->OnPowerButtonEvent(true, base::TimeTicks::Now()); - //TODO (antrim) : restore animator_helper_->Advance(base::TimeDelta()); - } - - void ReleasePowerButton() { - controller_->OnPowerButtonEvent(false, base::TimeTicks::Now()); - //TODO (antrim) : restore animator_helper_->Advance(base::TimeDelta()); - } - - void PressLockButton() { - controller_->OnLockButtonEvent(true, base::TimeTicks::Now()); - } - - void ReleaseLockButton() { - controller_->OnLockButtonEvent(false, base::TimeTicks::Now()); - } - - void SystemLocks() { - lock_state_controller_->OnLockStateChanged(true); - session_state_delegate_->LockScreen(); - //TODO (antrim) : restore animator_helper_->Advance(base::TimeDelta()); - } - - void SuccessfulAuthentication(bool* call_flag) { - base::Closure closure = base::Bind(&CheckCalledCallback, call_flag); - lock_state_controller_->OnLockScreenHide(closure); - //TODO (antrim) : restore animator_helper_->Advance(base::TimeDelta()); - } - - void SystemUnlocks() { - lock_state_controller_->OnLockStateChanged(false); - session_state_delegate_->UnlockScreen(); - //TODO (antrim) : restore animator_helper_->Advance(base::TimeDelta()); - } - - void Initialize(bool legacy_button, user::LoginStatus status) { - controller_->set_has_legacy_power_button_for_test(legacy_button); - lock_state_controller_->OnLoginStateChanged(status); - SetUserLoggedIn(status != user::LOGGED_IN_NONE); - if (status == user::LOGGED_IN_GUEST) - SetCanLockScreen(false); - lock_state_controller_->OnLockStateChanged(false); - } - - PowerButtonController* controller_; // not owned - LockStateController* lock_state_controller_; // not owned - TestLockStateControllerDelegate* delegate_; // not owned - TestShellDelegate* shell_delegate_; // not owned - SessionStateDelegate* session_state_delegate_; // not owned - - scoped_ptr<ui::ScopedAnimationDurationScaleMode> animation_duration_mode_; - scoped_ptr<LockStateController::TestApi> test_api_; - scoped_ptr<SessionStateAnimator::TestApi> animator_api_; - // TODO(antrim) : restore -// scoped_ptr<ui::test::AnimationContainerTestHelper> animator_helper_; - - private: - DISALLOW_COPY_AND_ASSIGN(LockStateControllerTest); -}; - -// Test the lock-to-shutdown flow for non-Chrome-OS hardware that doesn't -// correctly report power button releases. We should lock immediately the first -// time the button is pressed and shut down when it's pressed from the locked -// state. -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, DISABLED_LegacyLockAndShutDown) { - Initialize(true, user::LOGGED_IN_USER); - - ExpectUnlockedState(); - - // We should request that the screen be locked immediately after seeing the - // power button get pressed. - PressPowerButton(); - - ExpectPreLockAnimationStarted(); - - EXPECT_FALSE(test_api_->is_lock_cancellable()); - - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - - ExpectPreLockAnimationFinished(); - EXPECT_EQ(1, delegate_->num_lock_requests()); - - // Notify that we locked successfully. - lock_state_controller_->OnStartingLock(); - // We had that animation already. - //TODO (antrim) : restore - // EXPECT_FALSE(animator_helper_->IsAnimating()); - - SystemLocks(); - - ExpectPostLockAnimationStarted(); - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectPastLockAnimationFinished(); - - // We shouldn't progress towards the shutdown state, however. - EXPECT_FALSE(test_api_->lock_to_shutdown_timer_is_running()); - EXPECT_FALSE(test_api_->shutdown_timer_is_running()); - - ReleasePowerButton(); - - // Hold the button again and check that we start shutting down. - PressPowerButton(); - - ExpectShutdownAnimationStarted(); - - EXPECT_EQ(0, NumShutdownRequests()); - // Make sure a mouse move event won't show the cursor. - GenerateMouseMoveEvent(); - EXPECT_FALSE(cursor_visible()); - - EXPECT_TRUE(test_api_->real_shutdown_timer_is_running()); - test_api_->trigger_real_shutdown_timeout(); - EXPECT_EQ(1, NumShutdownRequests()); -} - -// Test that we start shutting down immediately if the power button is pressed -// while we're not logged in on an unofficial system. -TEST_F(LockStateControllerTest, LegacyNotLoggedIn) { - Initialize(true, user::LOGGED_IN_NONE); - - PressPowerButton(); - ExpectShutdownAnimationStarted(); - - EXPECT_TRUE(test_api_->real_shutdown_timer_is_running()); -} - -// Test that we start shutting down immediately if the power button is pressed -// while we're logged in as a guest on an unofficial system. -TEST_F(LockStateControllerTest, LegacyGuest) { - Initialize(true, user::LOGGED_IN_GUEST); - - PressPowerButton(); - ExpectShutdownAnimationStarted(); - - EXPECT_TRUE(test_api_->real_shutdown_timer_is_running()); -} - -// When we hold the power button while the user isn't logged in, we should shut -// down the machine directly. -TEST_F(LockStateControllerTest, ShutdownWhenNotLoggedIn) { - Initialize(false, user::LOGGED_IN_NONE); - - // Press the power button and check that we start the shutdown timer. - PressPowerButton(); - EXPECT_FALSE(test_api_->is_animating_lock()); - EXPECT_TRUE(test_api_->shutdown_timer_is_running()); - ExpectShutdownAnimationStarted(); - - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN, 0.5f); - - // Release the power button before the shutdown timer fires. - ReleasePowerButton(); - - EXPECT_FALSE(test_api_->shutdown_timer_is_running()); - ExpectShutdownAnimationCancel(); - - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_REVERT, 0.5f); - - // Press the button again and make the shutdown timeout fire this time. - // Check that we start the timer for actually requesting the shutdown. - PressPowerButton(); - - EXPECT_TRUE(test_api_->shutdown_timer_is_running()); - - Advance(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); - ExpectShutdownAnimationFinished(); - test_api_->trigger_shutdown_timeout(); - - EXPECT_TRUE(test_api_->real_shutdown_timer_is_running()); - EXPECT_EQ(0, NumShutdownRequests()); - - // When the timout fires, we should request a shutdown. - test_api_->trigger_real_shutdown_timeout(); - - EXPECT_EQ(1, NumShutdownRequests()); -} - -// Test that we lock the screen and deal with unlocking correctly. -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, DISABLED_LockAndUnlock) { - Initialize(false, user::LOGGED_IN_USER); - - ExpectUnlockedState(); - - // Press the power button and check that the lock timer is started and that we - // start lifting the non-screen-locker containers. - PressPowerButton(); - - ExpectPreLockAnimationStarted(); - EXPECT_TRUE(test_api_->is_lock_cancellable()); - EXPECT_EQ(0, delegate_->num_lock_requests()); - - Advance(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE); - ExpectPreLockAnimationFinished(); - - EXPECT_EQ(1, delegate_->num_lock_requests()); - - // Notify that we locked successfully. - lock_state_controller_->OnStartingLock(); - // We had that animation already. - //TODO (antrim) : restore EXPECT_FALSE(animator_helper_->IsAnimating()); - - SystemLocks(); - - ExpectPostLockAnimationStarted(); - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectPastLockAnimationFinished(); - - // When we release the power button, the lock-to-shutdown timer should be - // stopped. - ExpectLockedState(); - EXPECT_TRUE(test_api_->lock_to_shutdown_timer_is_running()); - ReleasePowerButton(); - ExpectLockedState(); - EXPECT_FALSE(test_api_->lock_to_shutdown_timer_is_running()); - - // Notify that the screen has been unlocked. We should show the - // non-screen-locker windows. - bool called = false; - SuccessfulAuthentication(&called); - - ExpectUnlockBeforeUIDestroyedAnimationStarted(); - EXPECT_FALSE(called); - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectUnlockBeforeUIDestroyedAnimationFinished(); - - EXPECT_TRUE(called); - - SystemUnlocks(); - - ExpectUnlockAfterUIDestroyedAnimationStarted(); - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectUnlockAfterUIDestroyedAnimationFinished(); - - ExpectUnlockedState(); -} - -// Test that we deal with cancelling lock correctly. -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, DISABLED_LockAndCancel) { - Initialize(false, user::LOGGED_IN_USER); - - ExpectUnlockedState(); - - // Press the power button and check that the lock timer is started and that we - // start lifting the non-screen-locker containers. - PressPowerButton(); - - ExpectPreLockAnimationStarted(); - EXPECT_TRUE(test_api_->is_lock_cancellable()); - - // forward only half way through - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, 0.5f); - - gfx::Transform transform_before_button_released = - GetContainer(internal::kShellWindowId_DefaultContainer)-> - layer()->transform(); - - // Release the button before the lock timer fires. - ReleasePowerButton(); - - ExpectPreLockAnimationCancel(); - - gfx::Transform transform_after_button_released = - GetContainer(internal::kShellWindowId_DefaultContainer)-> - layer()->transform(); - // Expect no flickering, animation should proceed from mid-state. - EXPECT_EQ(transform_before_button_released, transform_after_button_released); - - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectUnlockedState(); - EXPECT_EQ(0, delegate_->num_lock_requests()); -} - -// Test that we deal with cancelling lock correctly. -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, - DISABLED_LockAndCancelAndLockAgain) { - Initialize(false, user::LOGGED_IN_USER); - - ExpectUnlockedState(); - - // Press the power button and check that the lock timer is started and that we - // start lifting the non-screen-locker containers. - PressPowerButton(); - - ExpectPreLockAnimationStarted(); - EXPECT_TRUE(test_api_->is_lock_cancellable()); - - // forward only half way through - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, 0.5f); - - // Release the button before the lock timer fires. - ReleasePowerButton(); - ExpectPreLockAnimationCancel(); - - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, 0.5f); - - PressPowerButton(); - ExpectPreLockAnimationStarted(); - EXPECT_TRUE(test_api_->is_lock_cancellable()); - - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, 0.6f); - - EXPECT_EQ(0, delegate_->num_lock_requests()); - ExpectPreLockAnimationStarted(); - - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, 0.6f); - ExpectPreLockAnimationFinished(); - EXPECT_EQ(1, delegate_->num_lock_requests()); -} - -// Hold the power button down from the unlocked state to eventual shutdown. -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, DISABLED_LockToShutdown) { - Initialize(false, user::LOGGED_IN_USER); - - // Hold the power button and lock the screen. - PressPowerButton(); - EXPECT_TRUE(test_api_->is_animating_lock()); - - Advance(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE); - SystemLocks(); - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - - // When the lock-to-shutdown timeout fires, we should start the shutdown - // timer. - EXPECT_TRUE(test_api_->lock_to_shutdown_timer_is_running()); - - test_api_->trigger_lock_to_shutdown_timeout(); - - ExpectShutdownAnimationStarted(); - EXPECT_TRUE(test_api_->shutdown_timer_is_running()); - - // Fire the shutdown timeout and check that we request shutdown. - Advance(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); - ExpectShutdownAnimationFinished(); - test_api_->trigger_shutdown_timeout(); - - EXPECT_TRUE(test_api_->real_shutdown_timer_is_running()); - EXPECT_EQ(0, NumShutdownRequests()); - test_api_->trigger_real_shutdown_timeout(); - EXPECT_EQ(1, NumShutdownRequests()); -} - -// Hold the power button down from the unlocked state to eventual shutdown, -// then release the button while system does locking. -TEST_F(LockStateControllerTest, CancelLockToShutdown) { - Initialize(false, user::LOGGED_IN_USER); - - PressPowerButton(); - - // Hold the power button and lock the screen. - EXPECT_TRUE(test_api_->is_animating_lock()); - - Advance(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE); - SystemLocks(); - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS, 0.5f); - - // Power button is released while system attempts to lock. - ReleasePowerButton(); - - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - - EXPECT_FALSE(lock_state_controller_->ShutdownRequested()); - EXPECT_FALSE(test_api_->lock_to_shutdown_timer_is_running()); - EXPECT_FALSE(test_api_->shutdown_timer_is_running()); -} - -// Test that we handle the case where lock requests are ignored. -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, DISABLED_Lock) { - // We require animations to have a duration for this test. - ui::ScopedAnimationDurationScaleMode normal_duration_mode( - ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); - - Initialize(false, user::LOGGED_IN_USER); - - // Hold the power button and lock the screen. - PressPowerButton(); - ExpectPreLockAnimationStarted(); - - Advance(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE); - - EXPECT_EQ(1, delegate_->num_lock_requests()); - EXPECT_TRUE(test_api_->lock_fail_timer_is_running()); - // We shouldn't start the lock-to-shutdown timer until the screen has actually - // been locked and this was animated. - EXPECT_FALSE(test_api_->lock_to_shutdown_timer_is_running()); - - // Act as if the request timed out. We should restore the windows. - test_api_->trigger_lock_fail_timeout(); - - ExpectUnlockAfterUIDestroyedAnimationStarted(); - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectUnlockAfterUIDestroyedAnimationFinished(); - ExpectUnlockedState(); -} - -// Test the basic operation of the lock button (not logged in). -TEST_F(LockStateControllerTest, LockButtonBasicNotLoggedIn) { - // The lock button shouldn't do anything if we aren't logged in. - Initialize(false, user::LOGGED_IN_NONE); - - PressLockButton(); - EXPECT_FALSE(test_api_->is_animating_lock()); - ReleaseLockButton(); - EXPECT_EQ(0, delegate_->num_lock_requests()); -} - -// Test the basic operation of the lock button (guest). -TEST_F(LockStateControllerTest, LockButtonBasicGuest) { - // The lock button shouldn't do anything when we're logged in as a guest. - Initialize(false, user::LOGGED_IN_GUEST); - - PressLockButton(); - EXPECT_FALSE(test_api_->is_animating_lock()); - ReleaseLockButton(); - EXPECT_EQ(0, delegate_->num_lock_requests()); -} - -// Test the basic operation of the lock button. -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, DISABLED_LockButtonBasic) { - // If we're logged in as a regular user, we should start the lock timer and - // the pre-lock animation. - Initialize(false, user::LOGGED_IN_USER); - - PressLockButton(); - ExpectPreLockAnimationStarted(); - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, 0.5f); - - // If the button is released immediately, we shouldn't lock the screen. - ReleaseLockButton(); - ExpectPreLockAnimationCancel(); - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - - ExpectUnlockedState(); - EXPECT_EQ(0, delegate_->num_lock_requests()); - - // Press the button again and let the lock timeout fire. We should request - // that the screen be locked. - PressLockButton(); - ExpectPreLockAnimationStarted(); - Advance(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE); - EXPECT_EQ(1, delegate_->num_lock_requests()); - - // Pressing the lock button while we have a pending lock request shouldn't do - // anything. - ReleaseLockButton(); - PressLockButton(); - ExpectPreLockAnimationFinished(); - ReleaseLockButton(); - - // Pressing the button also shouldn't do anything after the screen is locked. - SystemLocks(); - ExpectPostLockAnimationStarted(); - - PressLockButton(); - ReleaseLockButton(); - ExpectPostLockAnimationStarted(); - - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectPastLockAnimationFinished(); - - PressLockButton(); - ReleaseLockButton(); - ExpectPastLockAnimationFinished(); -} - -// Test that the power button takes priority over the lock button. -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, - DISABLED_PowerButtonPreemptsLockButton) { - Initialize(false, user::LOGGED_IN_USER); - - // While the lock button is down, hold the power button. - PressLockButton(); - ExpectPreLockAnimationStarted(); - PressPowerButton(); - ExpectPreLockAnimationStarted(); - - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, 0.5f); - - // The lock timer shouldn't be stopped when the lock button is released. - ReleaseLockButton(); - ExpectPreLockAnimationStarted(); - ReleasePowerButton(); - ExpectPreLockAnimationCancel(); - - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectUnlockedState(); - - // Now press the power button first and then the lock button. - PressPowerButton(); - ExpectPreLockAnimationStarted(); - PressLockButton(); - ExpectPreLockAnimationStarted(); - - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, 0.5f); - - // Releasing the power button should stop the lock timer. - ReleasePowerButton(); - ExpectPreLockAnimationCancel(); - ReleaseLockButton(); - ExpectPreLockAnimationCancel(); -} - -// When the screen is locked without going through the usual power-button -// slow-close path (e.g. via the wrench menu), test that we still show the -// fast-close animation. -TEST_F(LockStateControllerTest, LockWithoutButton) { - Initialize(false, user::LOGGED_IN_USER); - lock_state_controller_->OnStartingLock(); - - ExpectPreLockAnimationStarted(); - EXPECT_FALSE(test_api_->is_lock_cancellable()); - - // TODO(antrim): After time-faking is fixed, let the pre-lock animation - // complete here and check that delegate_->num_lock_requests() is 0 to - // prevent http://crbug.com/172487 from regressing. -} - -// When we hear that the process is exiting but we haven't had a chance to -// display an animation, we should just blank the screen. -TEST_F(LockStateControllerTest, ShutdownWithoutButton) { - Initialize(false, user::LOGGED_IN_USER); - lock_state_controller_->OnAppTerminating(); - - EXPECT_TRUE( - animator_api_->ContainersAreAnimated( - SessionStateAnimator::kAllContainersMask, - SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY)); - GenerateMouseMoveEvent(); - EXPECT_FALSE(cursor_visible()); -} - -// Test that we display the fast-close animation and shut down when we get an -// outside request to shut down (e.g. from the login or lock screen). -TEST_F(LockStateControllerTest, RequestShutdownFromLoginScreen) { - Initialize(false, user::LOGGED_IN_NONE); - - lock_state_controller_->RequestShutdown(); - - ExpectShutdownAnimationStarted(); - Advance(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); - - GenerateMouseMoveEvent(); - EXPECT_FALSE(cursor_visible()); - - EXPECT_EQ(0, NumShutdownRequests()); - EXPECT_TRUE(test_api_->real_shutdown_timer_is_running()); - test_api_->trigger_real_shutdown_timeout(); - EXPECT_EQ(1, NumShutdownRequests()); -} - -TEST_F(LockStateControllerTest, RequestShutdownFromLockScreen) { - Initialize(false, user::LOGGED_IN_USER); - - SystemLocks(); - Advance(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); - ExpectPastLockAnimationFinished(); - - lock_state_controller_->RequestShutdown(); - - ExpectShutdownAnimationStarted(); - Advance(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); - - GenerateMouseMoveEvent(); - EXPECT_FALSE(cursor_visible()); - - EXPECT_EQ(0, NumShutdownRequests()); - EXPECT_TRUE(test_api_->real_shutdown_timer_is_running()); - test_api_->trigger_real_shutdown_timeout(); - EXPECT_EQ(1, NumShutdownRequests()); -} - -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, - DISABLED_RequestAndCancelShutdownFromLockScreen) { - Initialize(false, user::LOGGED_IN_USER); - - SystemLocks(); - Advance(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN); - ExpectLockedState(); - - // Press the power button and check that we start the shutdown timer. - PressPowerButton(); - EXPECT_FALSE(test_api_->is_animating_lock()); - EXPECT_TRUE(test_api_->shutdown_timer_is_running()); - - ExpectShutdownAnimationStarted(); - - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN, 0.5f); - - float grayscale_before_button_release = - Shell::GetPrimaryRootWindow()->layer()->layer_grayscale(); - - // Release the power button before the shutdown timer fires. - ReleasePowerButton(); - - EXPECT_FALSE(test_api_->shutdown_timer_is_running()); - - ExpectShutdownAnimationCancel(); - - float grayscale_after_button_release = - Shell::GetPrimaryRootWindow()->layer()->layer_grayscale(); - // Expect no flickering in undo animation. - EXPECT_EQ(grayscale_before_button_release, grayscale_after_button_release); - - Advance(SessionStateAnimator::ANIMATION_SPEED_REVERT); - ExpectLockedState(); -} - -// Test that we ignore power button presses when the screen is turned off. -TEST_F(LockStateControllerTest, IgnorePowerButtonIfScreenIsOff) { - Initialize(false, user::LOGGED_IN_USER); - - // When the screen brightness is at 0%, we shouldn't do anything in response - // to power button presses. - controller_->OnScreenBrightnessChanged(0.0); - - PressPowerButton(); - EXPECT_FALSE(test_api_->is_animating_lock()); - ReleasePowerButton(); - - // After increasing the brightness to 10%, we should start the timer like - // usual. - controller_->OnScreenBrightnessChanged(10.0); - - PressPowerButton(); - EXPECT_TRUE(test_api_->is_animating_lock()); -} - -// Test that hidden background appears and revers correctly on lock/cancel. -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, DISABLED_TestHiddenBackgroundLockCancel) { - Initialize(false, user::LOGGED_IN_USER); - HideBackground(); - - EXPECT_TRUE(IsBackgroundHidden()); - ExpectUnlockedState(); - PressPowerButton(); - - ExpectPreLockAnimationStarted(); - EXPECT_FALSE(IsBackgroundHidden()); - ExpectBackgroundIsShowing(); - - // Forward only half way through. - AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE, 0.5f); - - // Release the button before the lock timer fires. - ReleasePowerButton(); - ExpectPreLockAnimationCancel(); - ExpectBackgroundIsHiding(); - EXPECT_FALSE(IsBackgroundHidden()); - - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - - ExpectUnlockedState(); - EXPECT_TRUE(IsBackgroundHidden()); -} - -// Test that hidden background appears and revers correctly on lock/unlock. -// TODO(antrim): Reenable this: http://crbug.com/167048 -TEST_F(LockStateControllerTest, DISABLED_TestHiddenBackgroundLockUnlock) { - Initialize(false, user::LOGGED_IN_USER); - HideBackground(); - - EXPECT_TRUE(IsBackgroundHidden()); - ExpectUnlockedState(); - - // Press the power button and check that the lock timer is started and that we - // start lifting the non-screen-locker containers. - PressPowerButton(); - - ExpectPreLockAnimationStarted(); - EXPECT_FALSE(IsBackgroundHidden()); - ExpectBackgroundIsShowing(); - - Advance(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE); - - ExpectPreLockAnimationFinished(); - - SystemLocks(); - - ReleasePowerButton(); - - ExpectPostLockAnimationStarted(); - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectPastLockAnimationFinished(); - - ExpectLockedState(); - - SuccessfulAuthentication(NULL); - - ExpectUnlockBeforeUIDestroyedAnimationStarted(); - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectUnlockBeforeUIDestroyedAnimationFinished(); - - SystemUnlocks(); - - ExpectUnlockAfterUIDestroyedAnimationStarted(); - ExpectBackgroundIsHiding(); - EXPECT_FALSE(IsBackgroundHidden()); - - Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); - ExpectUnlockAfterUIDestroyedAnimationFinished(); - EXPECT_TRUE(IsBackgroundHidden()); - - ExpectUnlockedState(); -} - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/lock_state_observer.h b/chromium/ash/wm/lock_state_observer.h deleted file mode 100644 index d247e828347..00000000000 --- a/chromium/ash/wm/lock_state_observer.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 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_LOCK_STATE_OBSERVER_H_ -#define ASH_WM_LOCK_STATE_OBSERVER_H_ - -#include "ash/ash_export.h" - -namespace ash { - -// Interface for classes that want to be notified by LockStateController when -// session-related events occur. -class ASH_EXPORT LockStateObserver { - public: - enum EventType { - EVENT_PRELOCK_ANIMATION_STARTED, - EVENT_LOCK_ANIMATION_STARTED, - EVENT_LOCK_ANIMATION_FINISHED, - }; - - virtual void OnLockStateEvent(EventType event) = 0; - virtual ~LockStateObserver() {} -}; - -} // namespace ash - -#endif // ASH_WM_LOCK_STATE_OBSERVER_H_ diff --git a/chromium/ash/wm/mru_window_tracker.cc b/chromium/ash/wm/mru_window_tracker.cc deleted file mode 100644 index 4ed9a1df723..00000000000 --- a/chromium/ash/wm/mru_window_tracker.cc +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2013 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/mru_window_tracker.h" - -#include <algorithm> - -#include "ash/session_state_delegate.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/window_cycle_list.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace_controller.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/root_window.h" -#include "ui/events/event.h" -#include "ui/events/event_handler.h" - -namespace ash { - -namespace { - -// Adds the windows that can be cycled through for the specified window id to -// |windows|. -void AddTrackedWindows(aura::Window* root, - int container_id, - MruWindowTracker::WindowList* windows) { - aura::Window* container = Shell::GetContainer(root, container_id); - const MruWindowTracker::WindowList& children(container->children()); - windows->insert(windows->end(), children.begin(), children.end()); -} - -// Returns true if |window| is a container whose windows can be cycled to. -bool IsSwitchableContainer(aura::Window* window) { - if (!window) - return false; - for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { - if (window->id() == kSwitchableWindowContainerIds[i]) - return true; - } - return false; -} - -// Returns whether |w1| should be considered less recently used than |w2|. This -// is used for a stable sort to move minimized windows to the LRU end of the -// list. -bool CompareWindowState(aura::Window* w1, aura::Window* w2) { - return ash::wm::IsWindowMinimized(w1) && !ash::wm::IsWindowMinimized(w2); -} - -// Returns a list of windows ordered by their stacking order. -// If |mru_windows| is passed, these windows are moved to the front of the list. -// If |top_most_at_end|, the list is returned in descending (bottom-most / least -// recently used) order. -MruWindowTracker::WindowList BuildWindowListInternal( - const std::list<aura::Window*>* mru_windows, - bool top_most_at_end) { - MruWindowTracker::WindowList windows; - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - aura::Window* active_root = Shell::GetTargetRootWindow(); - for (aura::Window::Windows::const_iterator iter = root_windows.begin(); - iter != root_windows.end(); ++iter) { - if (*iter == active_root) - continue; - for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) - AddTrackedWindows(*iter, kSwitchableWindowContainerIds[i], &windows); - } - - // Add windows in the active root windows last so that the topmost window - // in the active root window becomes the front of the list. - for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) - AddTrackedWindows(active_root, kSwitchableWindowContainerIds[i], &windows); - - // Removes unfocusable windows. - MruWindowTracker::WindowList::iterator last = - std::remove_if( - windows.begin(), - windows.end(), - std::not1(std::ptr_fun(ash::wm::CanActivateWindow))); - windows.erase(last, windows.end()); - - // Put the windows in the mru_windows list at the head, if it's available. - if (mru_windows) { - // Iterate through the list backwards, so that we can move each window to - // the front of the windows list as we find them. - for (std::list<aura::Window*>::const_reverse_iterator ix = - mru_windows->rbegin(); - ix != mru_windows->rend(); ++ix) { - // Exclude windows in non-switchable containers and those which cannot - // be activated. - if (!IsSwitchableContainer((*ix)->parent()) || - !ash::wm::CanActivateWindow(*ix)) { - continue; - } - - MruWindowTracker::WindowList::iterator window = - std::find(windows.begin(), windows.end(), *ix); - if (window != windows.end()) { - windows.erase(window); - windows.push_back(*ix); - } - } - } - - // Move minimized windows to the beginning (LRU end) of the list. - std::stable_sort(windows.begin(), windows.end(), CompareWindowState); - - // Window cycling expects the topmost window at the front of the list. - if (!top_most_at_end) - std::reverse(windows.begin(), windows.end()); - - return windows; -} - -} // namespace - -const int kSwitchableWindowContainerIds[] = { - internal::kShellWindowId_DefaultContainer, - internal::kShellWindowId_AlwaysOnTopContainer, - internal::kShellWindowId_PanelContainer -}; - -const size_t kSwitchableWindowContainerIdsLength = - arraysize(kSwitchableWindowContainerIds); - -////////////////////////////////////////////////////////////////////////////// -// MruWindowTracker, public: - -MruWindowTracker::MruWindowTracker( - aura::client::ActivationClient* activation_client) - : activation_client_(activation_client), - ignore_window_activations_(false) { - activation_client_->AddObserver(this); -} - -MruWindowTracker::~MruWindowTracker() { - for (std::list<aura::Window*>::iterator iter = mru_windows_.begin(); - iter != mru_windows_.end(); ++iter) { - (*iter)->RemoveObserver(this); - } - - activation_client_->RemoveObserver(this); -} - -// static -MruWindowTracker::WindowList MruWindowTracker::BuildWindowList( - bool top_most_at_end) { - return BuildWindowListInternal(NULL, top_most_at_end); -} - -MruWindowTracker::WindowList MruWindowTracker::BuildMruWindowList() { - return BuildWindowListInternal(&mru_windows_, false); -} - -void MruWindowTracker::SetIgnoreActivations(bool ignore) { - ignore_window_activations_ = ignore; - - // If no longer ignoring window activations, move currently active window - // to front. - if (!ignore) - SetActiveWindow(wm::GetActiveWindow()); -} - -////////////////////////////////////////////////////////////////////////////// -// MruWindowTracker, private: - -void MruWindowTracker::SetActiveWindow(aura::Window* active_window) { - if (!active_window) - return; - - std::list<aura::Window*>::iterator iter = - std::find(mru_windows_.begin(), mru_windows_.end(), active_window); - // Observe all newly tracked windows. - if (iter == mru_windows_.end()) - active_window->AddObserver(this); - else - mru_windows_.erase(iter); - // TODO(flackr): Remove this check if this doesn't fire for a while. This - // should verify that all tracked windows start with a layer, see - // http://crbug.com/291354. - CHECK(active_window->layer()); - mru_windows_.push_front(active_window); -} - -void MruWindowTracker::OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) { - if (!ignore_window_activations_) - SetActiveWindow(gained_active); -} - -void MruWindowTracker::OnWindowDestroying(aura::Window* window) { - mru_windows_.remove(window); - window->RemoveObserver(this); -} - -} // namespace ash diff --git a/chromium/ash/wm/mru_window_tracker.h b/chromium/ash/wm/mru_window_tracker.h deleted file mode 100644 index 1569a98841d..00000000000 --- a/chromium/ash/wm/mru_window_tracker.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2013 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_MRU_WINDOW_TRACKER_H_ -#define ASH_WM_MRU_WINDOW_TRACKER_H_ - -#include <list> -#include <vector> - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/client/activation_change_observer.h" -#include "ui/aura/window_observer.h" - -namespace aura { -class RootWindow; -class Window; -namespace client { -class ActivationClient; -} -} - -namespace ash { - -// List of containers which contain windows that can be switched to. -ASH_EXPORT extern const int kSwitchableWindowContainerIds[]; - -// The number of elements in kSwitchableWindowContainerIds. -ASH_EXPORT extern const size_t kSwitchableWindowContainerIdsLength; - -// Maintains a most recently used list of windows. This is used for window -// cycling using Alt+Tab and overview mode. -class ASH_EXPORT MruWindowTracker - : public aura::client::ActivationChangeObserver, - public aura::WindowObserver { - public: - typedef std::vector<aura::Window*> WindowList; - - explicit MruWindowTracker( - aura::client::ActivationClient* activation_client); - virtual ~MruWindowTracker(); - - // Returns the set of windows which can be cycled through. This method creates - // the vector based on the current set of windows across all valid root - // windows. As a result it is not necessarily the same as the set of - // windows being iterated over. - // If |top_most_at_end| the window list will return in ascending (lowest - // window in stacking order first) order instead of the default descending - // (top most window first) order. - static WindowList BuildWindowList(bool top_most_at_end); - - // Returns the set of windows which can be cycled through using the tracked - // list of most recently used windows. - WindowList BuildMruWindowList(); - - // Starts or stops ignoring window activations. If no longer ignoring - // activations the currently active window is moved to the front of the - // MRU window list. Used by WindowCycleList to avoid adding all cycled - // windows to the front of the MRU window list. - void SetIgnoreActivations(bool ignore); - - private: - // Updates the mru_windows_ list to insert/move |active_window| at/to the - // front. - void SetActiveWindow(aura::Window* active_window); - - // Overridden from aura::client::ActivationChangeObserver: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE; - - // Overridden from WindowObserver: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - // List of windows that have been activated in containers that we cycle - // through, sorted by most recently used. - std::list<aura::Window*> mru_windows_; - - aura::client::ActivationClient* activation_client_; - - bool ignore_window_activations_; - - DISALLOW_COPY_AND_ASSIGN(MruWindowTracker); -}; - -} // namespace ash - -#endif // ASH_WM_MRU_WINDOW_TRACKER_H_ diff --git a/chromium/ash/wm/mru_window_tracker_unittest.cc b/chromium/ash/wm/mru_window_tracker_unittest.cc deleted file mode 100644 index 924060db7b5..00000000000 --- a/chromium/ash/wm/mru_window_tracker_unittest.cc +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2013 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/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/test_shelf_delegate.h" -#include "ash/wm/mru_window_tracker.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/compiler_specific.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/window.h" - -namespace ash { -namespace internal { - -class MruWindowTrackerTest : public test::AshTestBase { - public: - MruWindowTrackerTest() {} - virtual ~MruWindowTrackerTest() {} - - aura::Window* CreateWindow() { - return CreateTestWindowInShellWithBounds(gfx::Rect(0, 0, 400, 400)); - } - - ash::MruWindowTracker* mru_window_tracker() { - return Shell::GetInstance()->mru_window_tracker(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(MruWindowTrackerTest); -}; - -// Basic test that the activation order is tracked. -TEST_F(MruWindowTrackerTest, Basic) { - scoped_ptr<aura::Window> w1(CreateWindow()); - scoped_ptr<aura::Window> w2(CreateWindow()); - scoped_ptr<aura::Window> w3(CreateWindow()); - wm::ActivateWindow(w3.get()); - wm::ActivateWindow(w2.get()); - wm::ActivateWindow(w1.get()); - - MruWindowTracker::WindowList window_list = - mru_window_tracker()->BuildMruWindowList(); - EXPECT_EQ(w1.get(), window_list[0]); - EXPECT_EQ(w2.get(), window_list[1]); - EXPECT_EQ(w3.get(), window_list[2]); -} - -// Test that minimized windows are considered least recently used (but kept in -// correct relative order). -TEST_F(MruWindowTrackerTest, MinimizedWindowsAreLru) { - scoped_ptr<aura::Window> w1(CreateWindow()); - scoped_ptr<aura::Window> w2(CreateWindow()); - scoped_ptr<aura::Window> w3(CreateWindow()); - scoped_ptr<aura::Window> w4(CreateWindow()); - scoped_ptr<aura::Window> w5(CreateWindow()); - scoped_ptr<aura::Window> w6(CreateWindow()); - wm::ActivateWindow(w6.get()); - wm::ActivateWindow(w5.get()); - wm::ActivateWindow(w4.get()); - wm::ActivateWindow(w3.get()); - wm::ActivateWindow(w2.get()); - wm::ActivateWindow(w1.get()); - - wm::GetWindowState(w1.get())->Minimize(); - wm::GetWindowState(w4.get())->Minimize(); - wm::GetWindowState(w5.get())->Minimize(); - - // Expect the relative order of minimized windows to remain the same, but all - // minimized windows to be at the end of the list. - MruWindowTracker::WindowList window_list = - mru_window_tracker()->BuildMruWindowList(); - EXPECT_EQ(w2.get(), window_list[0]); - EXPECT_EQ(w3.get(), window_list[1]); - EXPECT_EQ(w6.get(), window_list[2]); - EXPECT_EQ(w1.get(), window_list[3]); - EXPECT_EQ(w4.get(), window_list[4]); - EXPECT_EQ(w5.get(), window_list[5]); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/overlay_event_filter.cc b/chromium/ash/wm/overlay_event_filter.cc deleted file mode 100644 index ed4f3161eed..00000000000 --- a/chromium/ash/wm/overlay_event_filter.cc +++ /dev/null @@ -1,74 +0,0 @@ -// 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/overlay_event_filter.h" - -#include "ash/wm/partial_screenshot_view.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/events/event.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -OverlayEventFilter::OverlayEventFilter() - : delegate_(NULL) { -} - -OverlayEventFilter::~OverlayEventFilter() { - delegate_ = NULL; -} - -void OverlayEventFilter::OnKeyEvent(ui::KeyEvent* event) { - if (!delegate_) - return; - - // Do not consume a translated key event which is generated by an IME (e.g., - // ui::VKEY_PROCESSKEY) since the key event is generated in response to a key - // press or release before showing the ovelay. This is important not to - // confuse key event handling JavaScript code in a page. - if (event->type() == ui::ET_TRANSLATED_KEY_PRESS || - event->type() == ui::ET_TRANSLATED_KEY_RELEASE) { - return; - } - - if (delegate_ && delegate_->IsCancelingKeyEvent(event)) - Cancel(); - - // Pass key events only when they are sent to a child of the delegate's - // window. - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (!delegate_ || !delegate_->GetWindow() || - !delegate_->GetWindow()->Contains(target)) - event->StopPropagation(); -} - -void OverlayEventFilter::OnLoginStateChanged( - user::LoginStatus status) { - Cancel(); -} - -void OverlayEventFilter::OnAppTerminating() { - Cancel(); -} - -void OverlayEventFilter::OnLockStateChanged(bool locked) { - Cancel(); -} - -void OverlayEventFilter::Activate(Delegate* delegate) { - delegate_ = delegate; -} - -void OverlayEventFilter::Deactivate() { - delegate_ = NULL; -} - -void OverlayEventFilter::Cancel() { - if (delegate_) - delegate_->Cancel(); -} -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/overlay_event_filter.h b/chromium/ash/wm/overlay_event_filter.h deleted file mode 100644 index 0d5afb6974a..00000000000 --- a/chromium/ash/wm/overlay_event_filter.h +++ /dev/null @@ -1,71 +0,0 @@ -// 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_OVERLAY_EVENT_FILTER_H_ -#define ASH_WM_OVERLAY_EVENT_FILTER_H_ - -#include "ash/shell_observer.h" -#include "base/compiler_specific.h" -#include "ui/aura/window.h" -#include "ui/events/event_handler.h" - -namespace ash { -namespace internal { - -// EventFilter for the "overlay window", which intercepts events before they are -// processed by the usual path (e.g. the partial screenshot UI, the keyboard -// overlay). It does nothing the first time, but works when |Activate()| is -// called. The main task of this event filter is just to stop propagation -// of any key events during activation, and also signal cancellation when keys -// for canceling are pressed. -class OverlayEventFilter : public ui::EventHandler, - public ShellObserver { - public: - // Windows that need to receive events from OverlayEventFilter implement this. - class Delegate { - public: - // Invoked when OverlayEventFilter needs to stop handling events. - virtual void Cancel() = 0; - - // Returns true if the overlay should be canceled in response to |event|. - virtual bool IsCancelingKeyEvent(ui::KeyEvent* event) = 0; - - // Returns the window that needs to receive events. NULL if no window needs - // to receive key events from OverlayEventFilter. - virtual aura::Window* GetWindow() = 0; - }; - - OverlayEventFilter(); - virtual ~OverlayEventFilter(); - - // Starts the filtering of events. It also notifies the specified - // |delegate| when a key event means cancel (like Esc). It holds the - // pointer to the specified |delegate| until Deactivate() is called, but - // does not take ownership. - void Activate(Delegate* delegate); - - // Ends the filtering of events. - void Deactivate(); - - // Cancels the partial screenshot UI. Do nothing if it's not activated. - void Cancel(); - - // ui::EventHandler overrides: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - - // ShellObserver overrides: - virtual void OnLoginStateChanged(user::LoginStatus status) OVERRIDE; - virtual void OnAppTerminating() OVERRIDE; - virtual void OnLockStateChanged(bool locked) OVERRIDE; - - private: - Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(OverlayEventFilter); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_OVERLAY_EVENT_FILTER_H_ diff --git a/chromium/ash/wm/overview/scoped_transform_overview_window.cc b/chromium/ash/wm/overview/scoped_transform_overview_window.cc deleted file mode 100644 index 507df0c581f..00000000000 --- a/chromium/ash/wm/overview/scoped_transform_overview_window.cc +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright 2013 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/overview/scoped_transform_overview_window.h" - -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/wm/overview/scoped_window_copy.h" -#include "ash/wm/window_state.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/window.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/animation/tween.h" -#include "ui/views/corewm/window_animations.h" -#include "ui/views/widget/widget.h" - -namespace ash { - -namespace { - -// The animation settings used for window selector animations. -class WindowSelectorAnimationSettings - : public ui::ScopedLayerAnimationSettings { - public: - WindowSelectorAnimationSettings(aura::Window* window) : - ui::ScopedLayerAnimationSettings(window->layer()->GetAnimator()) { - SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - SetTransitionDuration(base::TimeDelta::FromMilliseconds( - ScopedTransformOverviewWindow::kTransitionMilliseconds)); - SetTweenType(gfx::Tween::EASE_OUT); - } - - virtual ~WindowSelectorAnimationSettings() { - } -}; - -void SetTransformOnWindow(aura::Window* window, - const gfx::Transform& transform, - bool animate) { - if (animate) { - WindowSelectorAnimationSettings animation_settings(window); - window->SetTransform(transform); - } else { - window->SetTransform(transform); - } -} - -gfx::Transform TranslateTransformOrigin(const gfx::Vector2d& new_origin, - const gfx::Transform& transform) { - gfx::Transform result; - result.Translate(-new_origin.x(), -new_origin.y()); - result.PreconcatTransform(transform); - result.Translate(new_origin.x(), new_origin.y()); - return result; -} - -void SetTransformOnWindowAndAllTransientChildren( - aura::Window* window, - const gfx::Transform& transform, - bool animate) { - SetTransformOnWindow(window, transform, animate); - - aura::Window::Windows transient_children = window->transient_children(); - for (aura::Window::Windows::iterator iter = transient_children.begin(); - iter != transient_children.end(); ++iter) { - aura::Window* transient_child = *iter; - gfx::Rect window_bounds = window->bounds(); - gfx::Rect child_bounds = transient_child->bounds(); - gfx::Transform transient_window_transform( - TranslateTransformOrigin(child_bounds.origin() - window_bounds.origin(), - transform)); - SetTransformOnWindow(transient_child, transient_window_transform, animate); - } -} - -aura::Window* GetModalTransientParent(aura::Window* window) { - if (window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_WINDOW) - return window->transient_parent(); - return NULL; -} - -} // namespace - -const int ScopedTransformOverviewWindow::kTransitionMilliseconds = 200; - -ScopedTransformOverviewWindow::ScopedTransformOverviewWindow( - aura::Window* window) - : window_(window), - minimized_(window->GetProperty(aura::client::kShowStateKey) == - ui::SHOW_STATE_MINIMIZED), - ignored_by_shelf_(ash::wm::GetWindowState(window)->ignored_by_shelf()), - overview_started_(false), - original_transform_(window->layer()->GetTargetTransform()) { -} - -ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() { - if (window_) { - WindowSelectorAnimationSettings animation_settings(window_); - gfx::Transform transform; - SetTransformOnWindowAndTransientChildren(original_transform_, true); - if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) != - ui::SHOW_STATE_MINIMIZED) { - // Setting opacity 0 and visible false ensures that the property change - // to SHOW_STATE_MINIMIZED will not animate the window from its original - // bounds to the minimized position. - // Hiding the window needs to be done before the target opacity is 0, - // otherwise the layer's visibility will not be updated - // (See VisibilityController::UpdateLayerVisibility). - window_->Hide(); - window_->layer()->SetOpacity(0); - window_->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_MINIMIZED); - } - ash::wm::GetWindowState(window_)->set_ignored_by_shelf(ignored_by_shelf_); - } -} - -bool ScopedTransformOverviewWindow::Contains(const aura::Window* target) const { - for (ScopedVector<ScopedWindowCopy>::const_iterator iter = - window_copies_.begin(); iter != window_copies_.end(); ++iter) { - if ((*iter)->GetWindow()->Contains(target)) - return true; - } - aura::Window* window = window_; - while (window) { - if (window->Contains(target)) - return true; - window = GetModalTransientParent(window); - } - return false; -} - -gfx::Rect ScopedTransformOverviewWindow::GetBoundsInScreen() const { - gfx::Rect bounds; - aura::Window* window = window_; - while (window) { - bounds.Union(ScreenAsh::ConvertRectToScreen(window->parent(), - window->GetTargetBounds())); - window = GetModalTransientParent(window); - } - return bounds; -} - -void ScopedTransformOverviewWindow::RestoreWindow() { - if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) == - ui::SHOW_STATE_MINIMIZED) { - window_->Show(); - } -} - -void ScopedTransformOverviewWindow::RestoreWindowOnExit() { - minimized_ = false; - original_transform_ = gfx::Transform(); -} - -void ScopedTransformOverviewWindow::OnWindowDestroyed() { - window_ = NULL; -} - -gfx::Rect ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio( - const gfx::Rect& rect, - const gfx::Rect& bounds) { - DCHECK(!rect.IsEmpty()); - DCHECK(!bounds.IsEmpty()); - float scale = std::min(1.0f, - std::min(static_cast<float>(bounds.width()) / rect.width(), - static_cast<float>(bounds.height()) / rect.height())); - return gfx::Rect(bounds.x() + 0.5 * (bounds.width() - scale * rect.width()), - bounds.y() + 0.5 * (bounds.height() - scale * rect.height()), - rect.width() * scale, - rect.height() * scale); -} - -gfx::Transform ScopedTransformOverviewWindow::GetTransformForRect( - const gfx::Rect& src_rect, - const gfx::Rect& dst_rect) { - DCHECK(!src_rect.IsEmpty()); - DCHECK(!dst_rect.IsEmpty()); - gfx::Transform transform; - transform.Translate(dst_rect.x() - src_rect.x(), - dst_rect.y() - src_rect.y()); - transform.Scale(static_cast<float>(dst_rect.width()) / src_rect.width(), - static_cast<float>(dst_rect.height()) / src_rect.height()); - return transform; -} - -void ScopedTransformOverviewWindow::SetTransform( - aura::Window* root_window, - const gfx::Transform& transform, - bool animate) { - DCHECK(overview_started_); - - if (root_window != window_->GetRootWindow()) { - if (!window_copies_.empty()) { - bool bounds_or_hierarchy_changed = false; - aura::Window* window = window_; - for (ScopedVector<ScopedWindowCopy>::reverse_iterator iter = - window_copies_.rbegin(); - !bounds_or_hierarchy_changed && iter != window_copies_.rend(); - ++iter, window = GetModalTransientParent(window)) { - if (!window) { - bounds_or_hierarchy_changed = true; - } else if ((*iter)->GetWindow()->GetBoundsInScreen() != - window->GetBoundsInScreen()) { - bounds_or_hierarchy_changed = true; - } - } - // Clearing the window copies array will force it to be recreated. - // TODO(flackr): If only the position changed and not the size, - // update the existing window copy's position and continue to use it. - if (bounds_or_hierarchy_changed) - window_copies_.clear(); - } - if (window_copies_.empty()) { - // TODO(flackr): Create copies of the transient children windows as well. - // Currently they will only be visible on the window's initial display. - CopyWindowAndTransientParents(root_window, window_); - } - } - SetTransformOnWindowAndTransientChildren(transform, animate); -} - -void ScopedTransformOverviewWindow::CopyWindowAndTransientParents( - aura::Window* target_root, - aura::Window* window) { - aura::Window* modal_parent = GetModalTransientParent(window); - if (modal_parent) - CopyWindowAndTransientParents(target_root, modal_parent); - window_copies_.push_back(new ScopedWindowCopy(target_root, window)); -} - -void ScopedTransformOverviewWindow::SetTransformOnWindowAndTransientChildren( - const gfx::Transform& transform, - bool animate) { - gfx::Point origin(GetBoundsInScreen().origin()); - aura::Window* window = window_; - while (window->transient_parent()) - window = window->transient_parent(); - for (ScopedVector<ScopedWindowCopy>::const_iterator iter = - window_copies_.begin(); iter != window_copies_.end(); ++iter) { - SetTransformOnWindow( - (*iter)->GetWindow(), - TranslateTransformOrigin(ScreenAsh::ConvertRectToScreen( - (*iter)->GetWindow()->parent(), - (*iter)->GetWindow()->GetTargetBounds()).origin() - origin, - transform), - animate); - } - SetTransformOnWindowAndAllTransientChildren( - window, - TranslateTransformOrigin(ScreenAsh::ConvertRectToScreen( - window->parent(), window->GetTargetBounds()).origin() - origin, - transform), - animate); -} - -void ScopedTransformOverviewWindow::PrepareForOverview() { - DCHECK(!overview_started_); - overview_started_ = true; - ash::wm::GetWindowState(window_)->set_ignored_by_shelf(true); - RestoreWindow(); -} - -} // namespace ash diff --git a/chromium/ash/wm/overview/scoped_transform_overview_window.h b/chromium/ash/wm/overview/scoped_transform_overview_window.h deleted file mode 100644 index 2bc1b0f61f9..00000000000 --- a/chromium/ash/wm/overview/scoped_transform_overview_window.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2013 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_OVERVIEW_SCOPED_TRANSFORM_OVERVIEW_WINDOW_H_ -#define ASH_WM_OVERVIEW_SCOPED_TRANSFORM_OVERVIEW_WINDOW_H_ - -#include "base/compiler_specific.h" -#include "base/memory/scoped_vector.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/transform.h" - -namespace aura { -class Window; -} - -namespace ui { -class Layer; -} - -namespace views { -class Widget; -} - -namespace ash { - -class ScopedWindowCopy; - -// Manages a window in the overview mode. This class allows transforming the -// window with a helper to determine the best fit in certain bounds and -// copies the window if being moved to another display. The window's state is -// restored on destruction of this object. -class ScopedTransformOverviewWindow { - public: - // The duration of transitions used for window transforms. - static const int kTransitionMilliseconds; - - // Returns |rect| having been shrunk to fit within |bounds| (preserving the - // aspect ratio). - static gfx::Rect ShrinkRectToFitPreservingAspectRatio( - const gfx::Rect& rect, - const gfx::Rect& bounds); - - // Returns the transform turning |src_rect| into |dst_rect|. - static gfx::Transform GetTransformForRect(const gfx::Rect& src_rect, - const gfx::Rect& dst_rect); - - explicit ScopedTransformOverviewWindow(aura::Window* window); - virtual ~ScopedTransformOverviewWindow(); - - // Returns true if this window selector window contains the |target|. This is - // used to determine if an event targetted this window. - bool Contains(const aura::Window* target) const; - - // Returns the original bounds of all transformed windows. - gfx::Rect GetBoundsInScreen() const; - - // Restores the window if it was minimized. - void RestoreWindow(); - - // Restores this window on exit rather than returning it to a minimized state - // if it was minimized on entering overview mode. - void RestoreWindowOnExit(); - - // Informs the ScopedTransformOverviewWindow that the window being watched was - // destroyed. This resets the internal window pointer to avoid calling - // anything on the window at destruction time. - void OnWindowDestroyed(); - - // Prepares for overview mode by doing any necessary actions before entering. - virtual void PrepareForOverview(); - - // Sets |transform| on the window and a copy of the window if the target - // |root_window| is not the window's root window. If |animate| the transform - // is animated in, otherwise it is immediately applied. - void SetTransform(aura::Window* root_window, - const gfx::Transform& transform, - bool animate); - - aura::Window* window() const { return window_; } - - private: - // Creates copies of |window| and all of its modal transient parents on the - // root window |target_root|. - void CopyWindowAndTransientParents(aura::Window* target_root, - aura::Window* window); - - // Applies the |transform| to the overview window and all of its transient - // children using animations. If |animate| the transform is animated in, - // otherwise it is applied immediately. - void SetTransformOnWindowAndTransientChildren(const gfx::Transform& transform, - bool animate); - - // A weak pointer to the real window in the overview. - aura::Window* window_; - - // Copies of the window and transient parents for a different root window. - ScopedVector<ScopedWindowCopy> window_copies_; - - // If true, the window was minimized and should be restored if the window - // was not selected. - bool minimized_; - - // Tracks if this window was ignored by the shelf. - bool ignored_by_shelf_; - - // True if the window has been transformed for overview mode. - bool overview_started_; - - // The original transform of the window before entering overview mode. - gfx::Transform original_transform_; - - DISALLOW_COPY_AND_ASSIGN(ScopedTransformOverviewWindow); -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_SCOPED_TRANSFORM_OVERVIEW_WINDOW_H_ diff --git a/chromium/ash/wm/overview/scoped_window_copy.cc b/chromium/ash/wm/overview/scoped_window_copy.cc deleted file mode 100644 index 660b2845964..00000000000 --- a/chromium/ash/wm/overview/scoped_window_copy.cc +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2013 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/overview/scoped_window_copy.h" - -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer_animation_observer.h" -#include "ui/gfx/display.h" -#include "ui/views/corewm/shadow_types.h" -#include "ui/views/corewm/window_util.h" -#include "ui/views/widget/widget.h" - -namespace ash { - -namespace { - -// Creates a copy of |window| with |recreated_layer| in the |target_root|. -views::Widget* CreateCopyOfWindow(aura::Window* target_root, - aura::Window* src_window, - ui::Layer* recreated_layer) { - // Save and remove the transform from the layer to later reapply to both the - // source and newly created copy window. - gfx::Transform transform = recreated_layer->transform(); - recreated_layer->SetTransform(gfx::Transform()); - - src_window->SetTransform(transform); - views::Widget* widget = new views::Widget; - views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.parent = src_window->parent(); - params.can_activate = false; - params.keep_on_top = true; - widget->set_focus_on_creation(false); - widget->Init(params); - widget->SetVisibilityChangedAnimationsEnabled(false); - std::string name = src_window->name() + " (Copy)"; - widget->GetNativeWindow()->SetName(name); - views::corewm::SetShadowType(widget->GetNativeWindow(), - views::corewm::SHADOW_TYPE_RECTANGULAR); - - // Set the bounds in the target root window. - gfx::Display target_display = - Shell::GetScreen()->GetDisplayNearestWindow(target_root); - aura::client::ScreenPositionClient* screen_position_client = - aura::client::GetScreenPositionClient(src_window->GetRootWindow()); - if (screen_position_client && target_display.is_valid()) { - screen_position_client->SetBounds(widget->GetNativeWindow(), - src_window->GetBoundsInScreen(), target_display); - } else { - widget->SetBounds(src_window->GetBoundsInScreen()); - } - widget->StackAbove(src_window); - - // Move the |recreated_layer| to the newly created window. - recreated_layer->set_delegate(src_window->layer()->delegate()); - gfx::Rect layer_bounds = recreated_layer->bounds(); - layer_bounds.set_origin(gfx::Point(0, 0)); - recreated_layer->SetBounds(layer_bounds); - recreated_layer->SetVisible(false); - recreated_layer->parent()->Remove(recreated_layer); - - aura::Window* window = widget->GetNativeWindow(); - recreated_layer->SetVisible(true); - window->layer()->Add(recreated_layer); - window->layer()->StackAtTop(recreated_layer); - window->layer()->SetOpacity(1); - window->SetTransform(transform); - window->Show(); - return widget; -} - -} // namespace - -// An observer which closes the widget and deletes the layer after an -// animation finishes. -class CleanupWidgetAfterAnimationObserver : public ui::LayerAnimationObserver { - public: - CleanupWidgetAfterAnimationObserver(views::Widget* widget, ui::Layer* layer); - - // Takes ownership of the widget. At this point the class will delete itself - // and clean up the layer when there are no pending animations. - void TakeOwnershipOfWidget(); - - // ui::LayerAnimationObserver: - virtual void OnLayerAnimationEnded( - ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationAborted( - ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationScheduled( - ui::LayerAnimationSequence* sequence) OVERRIDE; - - private: - virtual ~CleanupWidgetAfterAnimationObserver(); - - // If the necessary conditions have been satisfied to destruct this - // class, deletes itself and cleans up the widget and layer. - void MaybeDestruct(); - - views::Widget* widget_; - ui::Layer* layer_; - bool owns_widget_; - int pending_animations_; - - DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver); -}; - -CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver( - views::Widget* widget, - ui::Layer* layer) - : widget_(widget), - layer_(layer), - owns_widget_(false), - pending_animations_(0) { - widget_->GetNativeWindow()->layer()->GetAnimator()->AddObserver(this); -} - -void CleanupWidgetAfterAnimationObserver::TakeOwnershipOfWidget() { - owns_widget_ = true; - MaybeDestruct(); -} - -void CleanupWidgetAfterAnimationObserver::OnLayerAnimationEnded( - ui::LayerAnimationSequence* sequence) { - pending_animations_--; - MaybeDestruct(); -} - -void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted( - ui::LayerAnimationSequence* sequence) { - pending_animations_--; - MaybeDestruct(); -} - -void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled( - ui::LayerAnimationSequence* sequence) { - pending_animations_++; -} - -CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() { - widget_->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this); - widget_->Close(); - widget_ = NULL; - if (layer_) { - views::corewm::DeepDeleteLayers(layer_); - layer_ = NULL; - } -} - -void CleanupWidgetAfterAnimationObserver::MaybeDestruct() { - if (pending_animations_ || !owns_widget_) - return; - delete this; -} - -ScopedWindowCopy::ScopedWindowCopy(aura::Window* target_root, - aura::Window* src_window) { - layer_ = views::corewm::RecreateWindowLayers(src_window, true); - widget_ = CreateCopyOfWindow(target_root, src_window, layer_); - cleanup_observer_ = new CleanupWidgetAfterAnimationObserver(widget_, layer_); -} - -ScopedWindowCopy::~ScopedWindowCopy() { - // The cleanup observer will delete itself and the window when any pending - // animations have completed. - cleanup_observer_->TakeOwnershipOfWidget(); -} - -aura::Window* ScopedWindowCopy::GetWindow() { - return widget_->GetNativeWindow(); -} - -} // namespace ash diff --git a/chromium/ash/wm/overview/scoped_window_copy.h b/chromium/ash/wm/overview/scoped_window_copy.h deleted file mode 100644 index d5da4458e92..00000000000 --- a/chromium/ash/wm/overview/scoped_window_copy.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2013 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_OVERVIEW_SCOPED_WINDOW_COPY_H_ -#define ASH_WM_OVERVIEW_SCOPED_WINDOW_COPY_H_ - -#include "base/basictypes.h" - -namespace aura { -class RootWindow; -class Window; -} - -namespace ui { -class Layer; -} - -namespace views { -class Widget; -} - -namespace ash { - -class CleanupWidgetAfterAnimationObserver; - -// ScopedWindowCopy copies a window and will clean up the copied layers after -// the class goes out of scope and the last animation has finished. -class ScopedWindowCopy { - public: - ScopedWindowCopy(aura::Window* target_root, aura::Window* src_window); - ~ScopedWindowCopy(); - - aura::Window* GetWindow(); - - private: - // A weak pointer to a copy of the source window owned by cleanup_observer_. - views::Widget* widget_; - - // A weak pointer to the deep copy of the source window's layers owned by - // cleanup_observer_. - ui::Layer* layer_; - - // A weak pointer to an animation observer which owns itself. When the - // ScopedWindowCopy is destroyed The animation observer will clean up the - // widget, layer and itself once any pending animations have completed. - CleanupWidgetAfterAnimationObserver* cleanup_observer_; - - DISALLOW_COPY_AND_ASSIGN(ScopedWindowCopy); -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_SCOPED_WINDOW_COPY_H_ diff --git a/chromium/ash/wm/overview/window_overview.cc b/chromium/ash/wm/overview/window_overview.cc deleted file mode 100644 index a7df1f7a458..00000000000 --- a/chromium/ash/wm/overview/window_overview.cc +++ /dev/null @@ -1,444 +0,0 @@ -// Copyright 2013 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/overview/window_overview.h" - -#include <algorithm> - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/mru_window_tracker.h" -#include "ash/wm/overview/scoped_transform_overview_window.h" -#include "ash/wm/overview/window_selector.h" -#include "ash/wm/overview/window_selector_item.h" -#include "base/metrics/histogram.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/aura/client/cursor_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/events/event.h" -#include "ui/views/background.h" -#include "ui/views/widget/widget.h" - -namespace ash { - -namespace { - -// Conceptually the window overview is a table or grid of cells having this -// fixed aspect ratio. The number of columns is determined by maximizing the -// area of them based on the number of windows. -const float kCardAspectRatio = 4.0f / 3.0f; - -// In the conceptual overview table, the window margin is the space reserved -// around the window within the cell. This margin does not overlap so the -// closest distance between adjacent windows will be twice this amount. -const int kWindowMargin = 30; - -// The minimum number of cards along the major axis (i.e. horizontally on a -// landscape orientation). -const int kMinCardsMajor = 3; - -// The duration of transition animations on the overview selector. -const int kOverviewSelectorTransitionMilliseconds = 100; - -// The color and opacity of the overview selector. -const SkColor kWindowOverviewSelectionColor = SK_ColorBLACK; -const float kWindowOverviewSelectionOpacity = 0.5f; - -// The padding or amount of the window selector widget visible around the edges -// of the currently selected window. -const int kWindowOverviewSelectionPadding = 25; - -// A comparator for locating a given target window. -struct WindowSelectorItemComparator - : public std::unary_function<WindowSelectorItem*, bool> { - explicit WindowSelectorItemComparator(const aura::Window* target_window) - : target(target_window) { - } - - bool operator()(WindowSelectorItem* window) const { - return window->TargetedWindow(target) != NULL; - } - - const aura::Window* target; -}; - -// An observer which holds onto the passed widget until the animation is -// complete. -class CleanupWidgetAfterAnimationObserver : public ui::LayerAnimationObserver { - public: - explicit CleanupWidgetAfterAnimationObserver( - scoped_ptr<views::Widget> widget); - - // ui::LayerAnimationObserver: - virtual void OnLayerAnimationEnded( - ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationAborted( - ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationScheduled( - ui::LayerAnimationSequence* sequence) OVERRIDE; - - private: - virtual ~CleanupWidgetAfterAnimationObserver(); - - scoped_ptr<views::Widget> widget_; - - DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver); -}; - -CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver( - scoped_ptr<views::Widget> widget) - : widget_(widget.Pass()) { - widget_->GetNativeWindow()->layer()->GetAnimator()->AddObserver(this); -} - -CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() { - widget_->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this); -} - -void CleanupWidgetAfterAnimationObserver::OnLayerAnimationEnded( - ui::LayerAnimationSequence* sequence) { - delete this; -} - -void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted( - ui::LayerAnimationSequence* sequence) { - delete this; -} - -void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled( - ui::LayerAnimationSequence* sequence) { -} - -} // namespace - -WindowOverview::WindowOverview(WindowSelector* window_selector, - WindowSelectorItemList* windows, - aura::Window* single_root_window) - : window_selector_(window_selector), - windows_(windows), - selection_index_(0), - single_root_window_(single_root_window), - overview_start_time_(base::Time::Now()), - cursor_client_(NULL) { - for (WindowSelectorItemList::iterator iter = windows_->begin(); - iter != windows_->end(); ++iter) { - (*iter)->PrepareForOverview(); - } - PositionWindows(); - DCHECK(!windows_->empty()); - cursor_client_ = aura::client::GetCursorClient( - windows_->front()->GetRootWindow()); - if (cursor_client_) { - cursor_client_->SetCursor(ui::kCursorPointer); - cursor_client_->ShowCursor(); - // TODO(flackr): Only prevent cursor changes for windows in the overview. - // This will be easier to do without exposing the overview mode code if the - // cursor changes are moved to ToplevelWindowEventHandler::HandleMouseMoved - // as suggested there. - cursor_client_->LockCursor(); - } - ash::Shell::GetInstance()->PrependPreTargetHandler(this); - Shell* shell = Shell::GetInstance(); - shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); - HideAndTrackNonOverviewWindows(); -} - -WindowOverview::~WindowOverview() { - const aura::WindowTracker::Windows hidden_windows = hidden_windows_.windows(); - for (aura::WindowTracker::Windows::const_iterator iter = - hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { - ui::ScopedLayerAnimationSettings settings( - (*iter)->layer()->GetAnimator()); - settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( - ScopedTransformOverviewWindow::kTransitionMilliseconds)); - settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - (*iter)->Show(); - (*iter)->layer()->SetOpacity(1); - } - if (cursor_client_) - cursor_client_->UnlockCursor(); - ash::Shell::GetInstance()->RemovePreTargetHandler(this); - UMA_HISTOGRAM_MEDIUM_TIMES( - "Ash.WindowSelector.TimeInOverview", - base::Time::Now() - overview_start_time_); -} - -void WindowOverview::SetSelection(size_t index) { - gfx::Rect target_bounds(GetSelectionBounds(index)); - - if (selection_widget_) { - // If the selection widget is already active, determine the animation to - // use to animate the widget to the new bounds. - int change = static_cast<int>(index) - static_cast<int>(selection_index_); - int windows = static_cast<int>(windows_->size()); - // If moving from the first to the last or last to the first index, - // convert the delta to be +/- 1. - if (windows > 2 && abs(change) == windows - 1) { - if (change < 0) - change += windows; - else - change -= windows; - } - if (selection_index_ < windows_->size() && - (*windows_)[selection_index_]->target_bounds().y() != - (*windows_)[index]->target_bounds().y() && - abs(change) == 1) { - // The selection has changed forward or backwards by one with a change - // in the height of the target. In this case create a new selection widget - // to fade in on the new position and animate and fade out the old one. - gfx::Display dst_display = gfx::Screen::GetScreenFor( - selection_widget_->GetNativeWindow())->GetDisplayMatching( - target_bounds); - gfx::Vector2d fade_out_direction( - change * ((*windows_)[selection_index_]->target_bounds().width() + - 2 * kWindowMargin), 0); - aura::Window* old_selection = selection_widget_->GetNativeWindow(); - - // CleanupWidgetAfterAnimationObserver will delete itself (and the - // widget) when the animation is complete. - new CleanupWidgetAfterAnimationObserver(selection_widget_.Pass()); - ui::ScopedLayerAnimationSettings animation_settings( - old_selection->layer()->GetAnimator()); - animation_settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds( - kOverviewSelectorTransitionMilliseconds)); - animation_settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - old_selection->SetBoundsInScreen( - GetSelectionBounds(selection_index_) + fade_out_direction, - dst_display); - old_selection->layer()->SetOpacity(0); - InitializeSelectionWidget(); - selection_widget_->GetNativeWindow()->SetBoundsInScreen( - target_bounds - fade_out_direction, dst_display); - } - ui::ScopedLayerAnimationSettings animation_settings( - selection_widget_->GetNativeWindow()->layer()->GetAnimator()); - animation_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( - kOverviewSelectorTransitionMilliseconds)); - animation_settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - selection_widget_->SetBounds(target_bounds); - selection_widget_->GetNativeWindow()->layer()->SetOpacity( - kWindowOverviewSelectionOpacity); - } else { - InitializeSelectionWidget(); - selection_widget_->SetBounds(target_bounds); - selection_widget_->GetNativeWindow()->layer()->SetOpacity( - kWindowOverviewSelectionOpacity); - } - selection_index_ = index; -} - -void WindowOverview::OnWindowsChanged() { - PositionWindows(); -} - -void WindowOverview::MoveToSingleRootWindow(aura::Window* root_window) { - single_root_window_ = root_window; - PositionWindows(); -} - -void WindowOverview::OnKeyEvent(ui::KeyEvent* event) { - if (GetTargetedWindow(static_cast<aura::Window*>(event->target()))) - event->StopPropagation(); - if (event->type() != ui::ET_KEY_PRESSED) - return; - - if (event->key_code() == ui::VKEY_ESCAPE) - window_selector_->CancelSelection(); -} - -void WindowOverview::OnMouseEvent(ui::MouseEvent* event) { - aura::Window* target = GetEventTarget(event); - if (!target) - return; - - event->StopPropagation(); - if (event->type() != ui::ET_MOUSE_RELEASED) - return; - - window_selector_->SelectWindow(target); -} - -void WindowOverview::OnScrollEvent(ui::ScrollEvent* event) { - // Set the handled flag to prevent delivering scroll events to the window but - // still allowing other pretarget handlers to process the scroll event. - if (GetTargetedWindow(static_cast<aura::Window*>(event->target()))) - event->SetHandled(); -} - -void WindowOverview::OnTouchEvent(ui::TouchEvent* event) { - // Existing touches should be allowed to continue. This prevents getting - // stuck in a gesture or with pressed fingers being tracked elsewhere. - if (event->type() != ui::ET_TOUCH_PRESSED) - return; - - aura::Window* target = GetEventTarget(event); - if (!target) - return; - - // 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 and then a tap - // gesture could be used to activate the window. - event->SetHandled(); - window_selector_->SelectWindow(target); -} - -aura::Window* WindowOverview::GetEventTarget(ui::LocatedEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - // If the target window doesn't actually contain the event location (i.e. - // mouse down over the window and mouse up elsewhere) then do not select the - // window. - if (!target->HitTest(event->location())) - return NULL; - - return GetTargetedWindow(target); -} - -aura::Window* WindowOverview::GetTargetedWindow(aura::Window* window) { - for (WindowSelectorItemList::iterator iter = windows_->begin(); - iter != windows_->end(); ++iter) { - aura::Window* selected = (*iter)->TargetedWindow(window); - if (selected) - return selected; - } - return NULL; -} - -void WindowOverview::HideAndTrackNonOverviewWindows() { - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - for (aura::Window::Windows::const_iterator root_iter = root_windows.begin(); - root_iter != root_windows.end(); ++root_iter) { - for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { - aura::Window* container = Shell::GetContainer(*root_iter, - kSwitchableWindowContainerIds[i]); - // Copy the children list as it can change during iteration. - aura::Window::Windows children(container->children()); - for (aura::Window::Windows::const_iterator iter = children.begin(); - iter != children.end(); ++iter) { - if (GetTargetedWindow(*iter) || !(*iter)->IsVisible()) - continue; - ui::ScopedLayerAnimationSettings settings( - (*iter)->layer()->GetAnimator()); - settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( - ScopedTransformOverviewWindow::kTransitionMilliseconds)); - settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - (*iter)->Hide(); - (*iter)->layer()->SetOpacity(0); - hidden_windows_.Add(*iter); - } - } - } -} - -void WindowOverview::PositionWindows() { - if (single_root_window_) { - std::vector<WindowSelectorItem*> windows; - for (WindowSelectorItemList::iterator iter = windows_->begin(); - iter != windows_->end(); ++iter) { - windows.push_back(*iter); - } - PositionWindowsOnRoot(single_root_window_, windows); - } else { - aura::Window::Windows root_window_list = Shell::GetAllRootWindows(); - for (size_t i = 0; i < root_window_list.size(); ++i) - PositionWindowsFromRoot(root_window_list[i]); - } -} - -void WindowOverview::PositionWindowsFromRoot(aura::Window* root_window) { - std::vector<WindowSelectorItem*> windows; - for (WindowSelectorItemList::iterator iter = windows_->begin(); - iter != windows_->end(); ++iter) { - if ((*iter)->GetRootWindow() == root_window) - windows.push_back(*iter); - } - PositionWindowsOnRoot(root_window, windows); -} - -void WindowOverview::PositionWindowsOnRoot( - aura::Window* root_window, - const std::vector<WindowSelectorItem*>& windows) { - if (windows.empty()) - return; - - gfx::Size window_size; - gfx::Rect total_bounds = ScreenAsh::ConvertRectToScreen(root_window, - ScreenAsh::GetDisplayWorkAreaBoundsInParent( - Shell::GetContainer(root_window, - internal::kShellWindowId_DefaultContainer))); - - // Find the minimum number of windows per row that will fit all of the - // windows on screen. - size_t columns = std::max( - total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1, - static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() / - (kCardAspectRatio * total_bounds.height()))))); - size_t rows = ((windows.size() + columns - 1) / columns); - window_size.set_width(std::min( - static_cast<int>(total_bounds.width() / columns), - static_cast<int>(total_bounds.height() * kCardAspectRatio / rows))); - window_size.set_height(window_size.width() / kCardAspectRatio); - - // Calculate the X and Y offsets necessary to center the grid. - int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 : - (columns - windows.size()) * window_size.width()) + - (total_bounds.width() - columns * window_size.width())) / 2; - int y_offset = total_bounds.y() + (total_bounds.height() - - rows * window_size.height()) / 2; - for (size_t i = 0; i < windows.size(); ++i) { - gfx::Transform transform; - int column = i % columns; - int row = i / columns; - gfx::Rect target_bounds(window_size.width() * column + x_offset, - window_size.height() * row + y_offset, - window_size.width(), - window_size.height()); - target_bounds.Inset(kWindowMargin, kWindowMargin); - windows[i]->SetBounds(root_window, target_bounds); - } -} - -void WindowOverview::InitializeSelectionWidget() { - selection_widget_.reset(new views::Widget); - views::Widget::InitParams params; - params.type = views::Widget::InitParams::TYPE_POPUP; - params.can_activate = false; - params.keep_on_top = false; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.opacity = views::Widget::InitParams::OPAQUE_WINDOW; - params.parent = Shell::GetContainer( - single_root_window_ ? single_root_window_ : - windows_->front()->GetRootWindow(), - internal::kShellWindowId_DefaultContainer); - params.accept_events = false; - selection_widget_->set_focus_on_creation(false); - selection_widget_->Init(params); - views::View* content_view = new views::View; - content_view->set_background( - views::Background::CreateSolidBackground(kWindowOverviewSelectionColor)); - selection_widget_->SetContentsView(content_view); - selection_widget_->Show(); - selection_widget_->GetNativeWindow()->parent()->StackChildAtBottom( - selection_widget_->GetNativeWindow()); - selection_widget_->GetNativeWindow()->layer()->SetOpacity(0); -} - -gfx::Rect WindowOverview::GetSelectionBounds(size_t index) { - gfx::Rect bounds((*windows_)[index]->bounds()); - bounds.Inset(-kWindowOverviewSelectionPadding, - -kWindowOverviewSelectionPadding); - return bounds; -} - -} // namespace ash diff --git a/chromium/ash/wm/overview/window_overview.h b/chromium/ash/wm/overview/window_overview.h deleted file mode 100644 index 5c771818e20..00000000000 --- a/chromium/ash/wm/overview/window_overview.h +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2013 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_OVERVIEW_WINDOW_OVERVIEW_H_ -#define ASH_WM_OVERVIEW_WINDOW_OVERVIEW_H_ - -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/time/time.h" -#include "ui/aura/window_tracker.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/rect.h" - -namespace aura { -class Window; -namespace client { -class CursorClient; -} -} // namespace aura - -namespace ui { -class LocatedEvent; -} - -namespace views { -class Widget; -} - -namespace ash { - -class WindowSelector; -class WindowSelectorItem; - -// The WindowOverview shows a grid of all of your windows and allows selecting -// a window by clicking or tapping on it. It also displays a selection widget -// used to indicate the current selection when alt-tabbing between windows. -class WindowOverview : public ui::EventHandler { - public: - typedef ScopedVector<WindowSelectorItem> WindowSelectorItemList; - - // Enters an overview mode displaying |windows| and dispatches methods - // on |window_selector| when a window is selected or selection is canceled. - // If |single_root_window| is not NULL, all windows will be positioned on the - // given root window. - WindowOverview(WindowSelector* window_selector, - WindowSelectorItemList* windows, - aura::Window* single_root_window); - virtual ~WindowOverview(); - - // Sets the selected window to be the window in position |index|. - void SetSelection(size_t index); - - // Dispatched when the list of windows has changed. - void OnWindowsChanged(); - - // Moves the overview to only |root_window|. - void MoveToSingleRootWindow(aura::Window* root_window); - - // ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; - virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; - - private: - // Returns the target of |event| or NULL if the event is not targeted at - // any of the windows in the selector. - aura::Window* GetEventTarget(ui::LocatedEvent* event); - - // Returns the top-level window selected by targeting |window| or NULL if - // no overview window was found for |window|. - aura::Window* GetTargetedWindow(aura::Window* window); - - // Hide and track all hidden windows not in overview. - void HideAndTrackNonOverviewWindows(); - - // Position all of the windows based on the current selection mode. - void PositionWindows(); - // Position all of the windows from |root_window| on |root_window|. - void PositionWindowsFromRoot(aura::Window* root_window); - // Position all of the |windows| to fit on the |root_window|. - void PositionWindowsOnRoot(aura::Window* root_window, - const std::vector<WindowSelectorItem*>& windows); - - // Creates the selection widget. - void InitializeSelectionWidget(); - - // Returns the bounds for the selection widget for the windows_ at |index|. - gfx::Rect GetSelectionBounds(size_t index); - - // Weak pointer to the window selector which owns this class. - WindowSelector* window_selector_; - - // A weak pointer to the collection of windows in the overview wrapped by a - // helper class which restores their state and helps transform them to other - // root windows. - WindowSelectorItemList* windows_; - - // Widget indicating which window is currently selected. - scoped_ptr<views::Widget> selection_widget_; - - // Index of the currently selected window. This is used to determine when the - // selection changes rows and use a different animation. - size_t selection_index_; - - // If NULL, each root window displays an overview of the windows in that - // display. Otherwise, all windows are in a single overview on - // |single_root_window_|. - aura::Window* single_root_window_; - - // The time when overview was started. - base::Time overview_start_time_; - - // The cursor client used to lock the current cursor during overview. - aura::client::CursorClient* cursor_client_; - - // Tracks windows which were hidden because they were not part of the - // overview. - aura::WindowTracker hidden_windows_; - - DISALLOW_COPY_AND_ASSIGN(WindowOverview); -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_WINDOW_OVERVIEW_H_ diff --git a/chromium/ash/wm/overview/window_selector.cc b/chromium/ash/wm/overview/window_selector.cc deleted file mode 100644 index f4d8bd08f69..00000000000 --- a/chromium/ash/wm/overview/window_selector.cc +++ /dev/null @@ -1,521 +0,0 @@ -// Copyright 2013 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/overview/window_selector.h" - -#include <algorithm> - -#include "ash/ash_switches.h" -#include "ash/root_window_controller.h" -#include "ash/shell.h" -#include "ash/wm/mru_window_tracker.h" -#include "ash/wm/overview/window_overview.h" -#include "ash/wm/overview/window_selector_delegate.h" -#include "ash/wm/overview/window_selector_panels.h" -#include "ash/wm/overview/window_selector_window.h" -#include "ash/wm/window_state.h" -#include "base/auto_reset.h" -#include "base/command_line.h" -#include "base/metrics/histogram.h" -#include "base/strings/string_number_conversions.h" -#include "base/timer/timer.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/events/event.h" -#include "ui/events/event_handler.h" - -namespace ash { - -namespace { - -// The time from when the user pressed alt+tab while still holding alt before -// overview is engaged. -const int kOverviewDelayOnCycleMilliseconds = 10000; - -// If the delay before overview is less than or equal to this threshold the -// initial monitor is used for multi-display overview, otherwise the monitor -// of the currently selected window is used. -const int kOverviewDelayInitialMonitorThreshold = 100; - -// The maximum amount of time allowed for the delay before overview on cycling. -// If the specified time exceeds this the timer will not be started. -const int kMaxOverviewDelayOnCycleMilliseconds = 10000; - -int GetOverviewDelayOnCycleMilliseconds() { - static int value = -1; - if (value == -1) { - value = kOverviewDelayOnCycleMilliseconds; - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshOverviewDelayOnAltTab)) { - if (!base::StringToInt(CommandLine::ForCurrentProcess()-> - GetSwitchValueASCII(switches::kAshOverviewDelayOnAltTab), &value)) { - LOG(ERROR) << "Expected int value for " - << switches::kAshOverviewDelayOnAltTab; - } - } - } - return value; -} - -// A comparator for locating a given selectable window. -struct WindowSelectorItemComparator - : public std::unary_function<WindowSelectorItem*, bool> { - explicit WindowSelectorItemComparator(const aura::Window* window) - : window_(window) { - } - - bool operator()(WindowSelectorItem* window) const { - return window->HasSelectableWindow(window_); - } - - const aura::Window* window_; -}; - -// A comparator for locating a selectable window given a targeted window. -struct WindowSelectorItemTargetComparator - : public std::unary_function<WindowSelectorItem*, bool> { - explicit WindowSelectorItemTargetComparator(const aura::Window* target_window) - : target(target_window) { - } - - bool operator()(WindowSelectorItem* window) const { - return window->TargetedWindow(target) != NULL; - } - - const aura::Window* target; -}; - -// A comparator for locating a selector item for a given root. -struct WindowSelectorItemForRoot - : public std::unary_function<WindowSelectorItem*, bool> { - explicit WindowSelectorItemForRoot(const aura::Window* root) - : root_window(root) { - } - - bool operator()(WindowSelectorItem* item) const { - return item->GetRootWindow() == root_window; - } - - const aura::Window* root_window; -}; - -// Filter to watch for the termination of a keyboard gesture to cycle through -// multiple windows. -class WindowSelectorEventFilter : public ui::EventHandler { - public: - WindowSelectorEventFilter(WindowSelector* selector); - virtual ~WindowSelectorEventFilter(); - - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - - private: - // A weak pointer to the WindowSelector which owns this instance. - WindowSelector* selector_; - - DISALLOW_COPY_AND_ASSIGN(WindowSelectorEventFilter); -}; - -// Watch for all keyboard events by filtering the root window. -WindowSelectorEventFilter::WindowSelectorEventFilter(WindowSelector* selector) - : selector_(selector) { - Shell::GetInstance()->AddPreTargetHandler(this); -} - -WindowSelectorEventFilter::~WindowSelectorEventFilter() { - Shell::GetInstance()->RemovePreTargetHandler(this); -} - -void WindowSelectorEventFilter::OnKeyEvent(ui::KeyEvent* event) { - // Views uses VKEY_MENU for both left and right Alt keys. - if (event->key_code() == ui::VKEY_MENU && - event->type() == ui::ET_KEY_RELEASED) { - selector_->SelectWindow(); - // Warning: |this| will be deleted from here on. - } -} - -// Triggers a shelf visibility update on all root window controllers. -void UpdateShelfVisibility() { - Shell::RootWindowControllerList root_window_controllers = - Shell::GetInstance()->GetAllRootWindowControllers(); - for (Shell::RootWindowControllerList::iterator iter = - root_window_controllers.begin(); - iter != root_window_controllers.end(); ++iter) { - (*iter)->UpdateShelfVisibility(); - } -} - -// Returns the window immediately below |window| in the current container. -aura::Window* GetWindowBelow(aura::Window* window) { - aura::Window* parent = window->parent(); - if (!parent) - return NULL; - aura::Window* below = NULL; - for (aura::Window::Windows::const_iterator iter = parent->children().begin(); - iter != parent->children().end(); ++iter) { - if (*iter == window) - return below; - below = *iter; - } - NOTREACHED(); - return NULL; -} - -} // namespace - -// This class restores and moves a window to the front of the stacking order for -// the duration of the class's scope. -class ScopedShowWindow : public aura::WindowObserver { - public: - ScopedShowWindow(); - virtual ~ScopedShowWindow(); - - // Show |window| at the top of the stacking order. - void Show(aura::Window* window); - - // Cancel restoring the window on going out of scope. - void CancelRestore(); - - aura::Window* window() { return window_; } - - // aura::WindowObserver: - virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE; - - private: - // The window being shown. - aura::Window* window_; - - // The window immediately below where window_ belongs. - aura::Window* stack_window_above_; - - // If true, minimize window_ on going out of scope. - bool minimized_; - - DISALLOW_COPY_AND_ASSIGN(ScopedShowWindow); -}; - -ScopedShowWindow::ScopedShowWindow() - : window_(NULL), - stack_window_above_(NULL), - minimized_(false) { -} - -void ScopedShowWindow::Show(aura::Window* window) { - DCHECK(!window_); - window_ = window; - stack_window_above_ = GetWindowBelow(window); - minimized_ = wm::GetWindowState(window)->IsMinimized(); - window_->parent()->AddObserver(this); - window_->Show(); - wm::GetWindowState(window_)->Activate(); -} - -ScopedShowWindow::~ScopedShowWindow() { - if (window_) { - window_->parent()->RemoveObserver(this); - - // Restore window's stacking position. - if (stack_window_above_) - window_->parent()->StackChildAbove(window_, stack_window_above_); - else - window_->parent()->StackChildAtBottom(window_); - - // Restore minimized state. - if (minimized_) - wm::GetWindowState(window_)->Minimize(); - } -} - -void ScopedShowWindow::CancelRestore() { - if (!window_) - return; - window_->parent()->RemoveObserver(this); - window_ = stack_window_above_ = NULL; -} - -void ScopedShowWindow::OnWillRemoveWindow(aura::Window* window) { - if (window == window_) { - CancelRestore(); - } else if (window == stack_window_above_) { - // If the window this window was above is removed, use the next window down - // as the restore marker. - stack_window_above_ = GetWindowBelow(stack_window_above_); - } -} - -WindowSelector::WindowSelector(const WindowList& windows, - WindowSelector::Mode mode, - WindowSelectorDelegate* delegate) - : mode_(mode), - timer_enabled_(GetOverviewDelayOnCycleMilliseconds() < - kMaxOverviewDelayOnCycleMilliseconds), - start_overview_timer_(FROM_HERE, - base::TimeDelta::FromMilliseconds( - GetOverviewDelayOnCycleMilliseconds()), - this, &WindowSelector::StartOverview), - delegate_(delegate), - selected_window_(0), - restore_focus_window_(aura::client::GetFocusClient( - Shell::GetPrimaryRootWindow())->GetFocusedWindow()), - ignore_activations_(false) { - DCHECK(delegate_); - - if (restore_focus_window_) - restore_focus_window_->AddObserver(this); - - std::vector<WindowSelectorPanels*> panels_items; - for (size_t i = 0; i < windows.size(); ++i) { - WindowSelectorItem* item = NULL; - if (windows[i] != restore_focus_window_) - windows[i]->AddObserver(this); - observed_windows_.insert(windows[i]); - - if (windows[i]->type() == aura::client::WINDOW_TYPE_PANEL && - wm::GetWindowState(windows[i])->panel_attached()) { - // Attached panel windows are grouped into a single overview item per - // root window (display). - std::vector<WindowSelectorPanels*>::iterator iter = - std::find_if(panels_items.begin(), panels_items.end(), - WindowSelectorItemForRoot(windows[i]->GetRootWindow())); - WindowSelectorPanels* panels_item = NULL; - if (iter == panels_items.end()) { - panels_item = new WindowSelectorPanels(); - panels_items.push_back(panels_item); - windows_.push_back(panels_item); - } else { - panels_item = *iter; - } - panels_item->AddWindow(windows[i]); - item = panels_item; - } else { - item = new WindowSelectorWindow(windows[i]); - windows_.push_back(item); - } - // Verify that the window has been added to an item in overview. - CHECK(item->TargetedWindow(windows[i])); - } - UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", windows_.size()); - - // Observe window activations and switchable containers on all root windows - // for newly created windows during overview. - Shell::GetInstance()->activation_client()->AddObserver(this); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - for (aura::Window::Windows::const_iterator iter = root_windows.begin(); - iter != root_windows.end(); ++iter) { - for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { - aura::Window* container = Shell::GetContainer(*iter, - kSwitchableWindowContainerIds[i]); - container->AddObserver(this); - observed_windows_.insert(container); - } - } - - if (mode == WindowSelector::CYCLE) { - cycle_start_time_ = base::Time::Now(); - event_handler_.reset(new WindowSelectorEventFilter(this)); - if (timer_enabled_) - start_overview_timer_.Reset(); - } else { - StartOverview(); - } -} - -WindowSelector::~WindowSelector() { - ResetFocusRestoreWindow(true); - for (std::set<aura::Window*>::iterator iter = observed_windows_.begin(); - iter != observed_windows_.end(); ++iter) { - (*iter)->RemoveObserver(this); - } - Shell::GetInstance()->activation_client()->RemoveObserver(this); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - window_overview_.reset(); - // Clearing the window list resets the ignored_by_shelf flag on the windows. - windows_.clear(); - UpdateShelfVisibility(); - - if (!cycle_start_time_.is_null()) { - UMA_HISTOGRAM_MEDIUM_TIMES("Ash.WindowSelector.CycleTime", - base::Time::Now() - cycle_start_time_); - } -} - -void WindowSelector::Step(WindowSelector::Direction direction) { - DCHECK(!windows_.empty()); - // Upgrade to CYCLE mode if currently in OVERVIEW mode. - if (mode_ != CYCLE) { - event_handler_.reset(new WindowSelectorEventFilter(this)); - DCHECK(window_overview_); - // Set the initial selection window to animate to the new selection. - window_overview_->SetSelection(selected_window_); - window_overview_->MoveToSingleRootWindow( - windows_[selected_window_]->GetRootWindow()); - mode_ = CYCLE; - } - - selected_window_ = (selected_window_ + windows_.size() + - (direction == WindowSelector::FORWARD ? 1 : -1)) % windows_.size(); - if (window_overview_) { - window_overview_->SetSelection(selected_window_); - } else { - base::AutoReset<bool> restoring_focus(&ignore_activations_, true); - showing_window_.reset(new ScopedShowWindow); - showing_window_->Show(windows_[selected_window_]->SelectionWindow()); - if (timer_enabled_) - start_overview_timer_.Reset(); - } -} - -void WindowSelector::SelectWindow() { - SelectWindow(windows_[selected_window_]->SelectionWindow()); -} - -void WindowSelector::SelectWindow(aura::Window* window) { - ResetFocusRestoreWindow(false); - if (showing_window_ && showing_window_->window() == window) - showing_window_->CancelRestore(); - ScopedVector<WindowSelectorItem>::iterator iter = - std::find_if(windows_.begin(), windows_.end(), - WindowSelectorItemTargetComparator(window)); - DCHECK(iter != windows_.end()); - // The selected window should not be minimized when window selection is - // ended. - (*iter)->RestoreWindowOnExit(window); - delegate_->OnWindowSelected(window); -} - -void WindowSelector::CancelSelection() { - delegate_->OnSelectionCanceled(); -} - -void WindowSelector::OnWindowAdded(aura::Window* new_window) { - if (new_window->type() != aura::client::WINDOW_TYPE_NORMAL && - new_window->type() != aura::client::WINDOW_TYPE_PANEL) { - return; - } - - for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { - if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && - !new_window->transient_parent()) { - // The new window is in one of the switchable containers, abort overview. - CancelSelection(); - return; - } - } -} - -void WindowSelector::OnWindowDestroying(aura::Window* window) { - // window is one of a container, the restore_focus_window and/or - // one of the selectable windows in overview. - ScopedVector<WindowSelectorItem>::iterator iter = - std::find_if(windows_.begin(), windows_.end(), - WindowSelectorItemComparator(window)); - window->RemoveObserver(this); - observed_windows_.erase(window); - if (window == restore_focus_window_) - restore_focus_window_ = NULL; - if (iter == windows_.end()) - return; - - (*iter)->RemoveWindow(window); - // If there are still windows in this selector entry then the overview is - // still active and the active selection remains the same. - if (!(*iter)->empty()) - return; - - size_t deleted_index = iter - windows_.begin(); - windows_.erase(iter); - if (windows_.empty()) { - CancelSelection(); - return; - } - if (window_overview_) - window_overview_->OnWindowsChanged(); - if (mode_ == CYCLE && selected_window_ >= deleted_index) { - if (selected_window_ > deleted_index) - selected_window_--; - selected_window_ = selected_window_ % windows_.size(); - if (window_overview_) - window_overview_->SetSelection(selected_window_); - } -} - -void WindowSelector::OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - if (!window_overview_) - return; - - ScopedVector<WindowSelectorItem>::iterator iter = - std::find_if(windows_.begin(), windows_.end(), - WindowSelectorItemTargetComparator(window)); - DCHECK(window == restore_focus_window_ || iter != windows_.end()); - if (iter == windows_.end()) - return; - - // Immediately finish any active bounds animation. - window->layer()->GetAnimator()->StopAnimatingProperty( - ui::LayerAnimationElement::BOUNDS); - - // Recompute the transform for the window. - (*iter)->RecomputeWindowTransforms(); -} - -void WindowSelector::OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) { - if (ignore_activations_ || !gained_active) - return; - // Don't restore focus on exit if a window was just activated. - ResetFocusRestoreWindow(false); - CancelSelection(); -} - -void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, - aura::Window* actual_active) { - if (ignore_activations_) - return; - // Don't restore focus on exit if a window was just activated. - ResetFocusRestoreWindow(false); - CancelSelection(); -} - -void WindowSelector::StartOverview() { - DCHECK(!window_overview_); - // Remove focus from active window before entering overview. - aura::client::GetFocusClient( - Shell::GetPrimaryRootWindow())->FocusWindow(NULL); - - aura::Window* overview_root = NULL; - if (mode_ == CYCLE) { - overview_root = GetOverviewDelayOnCycleMilliseconds() <= - kOverviewDelayInitialMonitorThreshold ? - windows_.front()->GetRootWindow() : - windows_[selected_window_]->GetRootWindow(); - } - window_overview_.reset(new WindowOverview(this, &windows_, overview_root)); - if (mode_ == CYCLE) - window_overview_->SetSelection(selected_window_); - UpdateShelfVisibility(); -} - -void WindowSelector::ResetFocusRestoreWindow(bool focus) { - if (!restore_focus_window_) - return; - if (focus) { - base::AutoReset<bool> restoring_focus(&ignore_activations_, true); - restore_focus_window_->Focus(); - } - // If the window is in the observed_windows_ list it needs to continue to be - // observed. - if (observed_windows_.find(restore_focus_window_) == - observed_windows_.end()) { - restore_focus_window_->RemoveObserver(this); - } - restore_focus_window_ = NULL; -} - -} // namespace ash diff --git a/chromium/ash/wm/overview/window_selector.h b/chromium/ash/wm/overview/window_selector.h deleted file mode 100644 index faee73d1d72..00000000000 --- a/chromium/ash/wm/overview/window_selector.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2013 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_OVERVIEW_WINDOW_SELECTOR_H_ -#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_H_ - -#include <set> -#include <vector> - -#include "ash/ash_export.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/timer/timer.h" -#include "ui/aura/client/activation_change_observer.h" -#include "ui/aura/window_observer.h" - -namespace aura { -class RootWindow; -} - -namespace ui { -class EventHandler; -} - -namespace ash { - -namespace internal { -class WindowSelectorTest; -} - -class ScopedShowWindow; -class WindowOverview; -class WindowSelectorDelegate; -class WindowSelectorItem; - -// The WindowSelector allows selecting a window by alt-tabbing (CYCLE mode) or -// by clicking or tapping on it (OVERVIEW mode). A WindowOverview will be shown -// in OVERVIEW mode or if the user lingers on a window while alt tabbing. -class ASH_EXPORT WindowSelector - : public aura::WindowObserver, - public aura::client::ActivationChangeObserver { - public: - enum Direction { - FORWARD, - BACKWARD - }; - enum Mode { - CYCLE, - OVERVIEW - }; - - typedef std::vector<aura::Window*> WindowList; - - WindowSelector(const WindowList& windows, - Mode mode, - WindowSelectorDelegate* delegate); - virtual ~WindowSelector(); - - // Step to the next window in |direction|. - void Step(Direction direction); - - // Choose the currently selected window. - void SelectWindow(); - - // Choose |window| from the available windows to select. - void SelectWindow(aura::Window* window); - - // Cancels window selection. - void CancelSelection(); - - Mode mode() { return mode_; } - - // aura::WindowObserver: - virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE; - virtual void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - // Overridden from aura::client::ActivationChangeObserver: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE; - virtual void OnAttemptToReactivateWindow( - aura::Window* request_active, - aura::Window* actual_active) OVERRIDE; - - private: - friend class internal::WindowSelectorTest; - - // Begins positioning windows such that all windows are visible on the screen. - void StartOverview(); - - // Resets the stored window from RemoveFocusAndSetRestoreWindow to NULL. If - // |focus|, restores focus to the stored window. - void ResetFocusRestoreWindow(bool focus); - - // The collection of items in the overview wrapped by a helper class which - // restores their state and helps transform them to other root windows. - ScopedVector<WindowSelectorItem> windows_; - - // Tracks observed windows. - std::set<aura::Window*> observed_windows_; - - // The window selection mode. - Mode mode_; - - // An event handler listening for the release of the alt key during alt-tab - // cycling. - scoped_ptr<ui::EventHandler> event_handler_; - - // The currently selected window being shown (temporarily brought to the front - // of the stacking order and made visible). - scoped_ptr<ScopedShowWindow> showing_window_; - - bool timer_enabled_; - base::DelayTimer<WindowSelector> start_overview_timer_; - scoped_ptr<WindowOverview> window_overview_; - - // The time when window cycling was started. - base::Time cycle_start_time_; - - // Weak pointer to the selector delegate which will be called when a - // selection is made. - WindowSelectorDelegate* delegate_; - - // Index of the currently selected window if the mode is CYCLE. - size_t selected_window_; - - // A weak pointer to the window which was focused on beginning window - // selection. If window selection is canceled the focus should be restored to - // this window. - aura::Window* restore_focus_window_; - - // True when performing operations that may cause window activations. This is - // used to prevent handling the resulting expected activation. - bool ignore_activations_; - - DISALLOW_COPY_AND_ASSIGN(WindowSelector); -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_H_ diff --git a/chromium/ash/wm/overview/window_selector_controller.cc b/chromium/ash/wm/overview/window_selector_controller.cc deleted file mode 100644 index e80490e421c..00000000000 --- a/chromium/ash/wm/overview/window_selector_controller.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2013 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/overview/window_selector_controller.h" - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/root_window_controller.h" -#include "ash/session_state_delegate.h" -#include "ash/shell.h" -#include "ash/wm/mru_window_tracker.h" -#include "ash/wm/overview/window_selector.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/metrics/histogram.h" -#include "ui/aura/window.h" - -namespace ash { - -WindowSelectorController::WindowSelectorController() { -} - -WindowSelectorController::~WindowSelectorController() { -} - -// static -bool WindowSelectorController::CanSelect() { - // Don't allow a window overview if the screen is locked or a modal dialog is - // open. - return !Shell::GetInstance()->session_state_delegate()->IsScreenLocked() && - !Shell::GetInstance()->IsSystemModalWindowOpen(); -} - -void WindowSelectorController::ToggleOverview() { - if (IsSelecting()) { - OnSelectionCanceled(); - } else { - std::vector<aura::Window*> windows = ash::Shell::GetInstance()-> - mru_window_tracker()->BuildMruWindowList(); - // Don't enter overview mode with no windows. - if (windows.empty()) - return; - - window_selector_.reset( - new WindowSelector(windows, WindowSelector::OVERVIEW, this)); - OnSelectionStarted(); - } -} - -void WindowSelectorController::HandleCycleWindow( - WindowSelector::Direction direction) { - if (!CanSelect()) - return; - - if (!IsSelecting()) { - std::vector<aura::Window*> windows = ash::Shell::GetInstance()-> - mru_window_tracker()->BuildMruWindowList(); - // Don't cycle with no windows. - if (windows.empty()) - return; - - window_selector_.reset( - new WindowSelector(windows, WindowSelector::CYCLE, this)); - OnSelectionStarted(); - } - window_selector_->Step(direction); -} - -bool WindowSelectorController::IsSelecting() { - return window_selector_.get() != NULL; -} - -void WindowSelectorController::OnWindowSelected(aura::Window* window) { - window_selector_.reset(); - wm::ActivateWindow(window); - last_selection_time_ = base::Time::Now(); - Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(false); -} - -void WindowSelectorController::OnSelectionCanceled() { - window_selector_.reset(); - last_selection_time_ = base::Time::Now(); - Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(false); -} - -void WindowSelectorController::OnSelectionStarted() { - Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(true); - Shell* shell = Shell::GetInstance(); - shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_SELECTION); - if (!last_selection_time_.is_null()) { - UMA_HISTOGRAM_LONG_TIMES( - "Ash.WindowSelector.TimeBetweenUse", - base::Time::Now() - last_selection_time_); - } -} - -} // namespace ash diff --git a/chromium/ash/wm/overview/window_selector_controller.h b/chromium/ash/wm/overview/window_selector_controller.h deleted file mode 100644 index 2bd9697a31a..00000000000 --- a/chromium/ash/wm/overview/window_selector_controller.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 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_OVERVIEW_WINDOW_SELECTOR_CONTROLLER_H_ -#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_CONTROLLER_H_ - -#include <list> -#include <vector> - -#include "ash/ash_export.h" -#include "ash/wm/overview/window_selector.h" -#include "ash/wm/overview/window_selector_delegate.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "ui/aura/window_observer.h" - -namespace aura { -class Window; -} - -namespace ash { - -namespace internal { -class WindowSelectorTest; -} - -class WindowSelector; - -// Manages a window selector which displays an overview of all windows and -// allows selecting a window to activate it. -class ASH_EXPORT WindowSelectorController - : public WindowSelectorDelegate { - public: - WindowSelectorController(); - virtual ~WindowSelectorController(); - - // Returns true if selecting windows in an overview is enabled. This is false - // at certain times, such as when the lock screen is visible. - static bool CanSelect(); - - // Enters overview mode. This is essentially the window cycling mode however - // not released on releasing the alt key and allows selecting with the mouse - // or touch rather than keypresses. - void ToggleOverview(); - - // Cycles between windows in the given |direction|. It is assumed that the - // alt key is held down and a key filter is installed to watch for alt being - // released. - void HandleCycleWindow(WindowSelector::Direction direction); - - // Returns true if window selection mode is active. - bool IsSelecting(); - - // WindowSelectorDelegate: - virtual void OnWindowSelected(aura::Window* window) OVERRIDE; - virtual void OnSelectionCanceled() OVERRIDE; - - private: - friend class internal::WindowSelectorTest; - - // Dispatched when window selection begins. - void OnSelectionStarted(); - - scoped_ptr<WindowSelector> window_selector_; - base::Time last_selection_time_; - - DISALLOW_COPY_AND_ASSIGN(WindowSelectorController); -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_CONTROLLER_H_ diff --git a/chromium/ash/wm/overview/window_selector_delegate.h b/chromium/ash/wm/overview/window_selector_delegate.h deleted file mode 100644 index 2bce3ca3fd7..00000000000 --- a/chromium/ash/wm/overview/window_selector_delegate.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 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_OVERVIEW_WINDOW_SELECTOR_DELEGATE_H_ -#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_DELEGATE_H_ - -#include "ash/ash_export.h" -#include "base/compiler_specific.h" - -namespace aura { -class Window; -} - -namespace ash { - -// Implement this class to handle the selection event from WindowSelector. -class ASH_EXPORT WindowSelectorDelegate { - public: - // Invoked when a window is selected. - virtual void OnWindowSelected(aura::Window* window) = 0; - - // Invoked if selection is canceled. - virtual void OnSelectionCanceled() = 0; - - protected: - virtual ~WindowSelectorDelegate() {} -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_DELEGATE_H_ diff --git a/chromium/ash/wm/overview/window_selector_item.cc b/chromium/ash/wm/overview/window_selector_item.cc deleted file mode 100644 index a2c25b617e9..00000000000 --- a/chromium/ash/wm/overview/window_selector_item.cc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 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/overview/window_selector_item.h" -#include "base/auto_reset.h" -#include "ui/aura/window.h" - -namespace ash { - -WindowSelectorItem::WindowSelectorItem() - : root_window_(NULL), - in_bounds_update_(false) { -} - -WindowSelectorItem::~WindowSelectorItem() { -} - -void WindowSelectorItem::SetBounds(aura::Window* root_window, - const gfx::Rect& target_bounds) { - if (in_bounds_update_) - return; - base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true); - root_window_ = root_window; - target_bounds_ = target_bounds; - SetItemBounds(root_window, target_bounds, true); -} - -void WindowSelectorItem::RecomputeWindowTransforms() { - if (in_bounds_update_ || target_bounds_.IsEmpty()) - return; - DCHECK(root_window_); - base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true); - SetItemBounds(root_window_, target_bounds_, false); -} - -} // namespace ash diff --git a/chromium/ash/wm/overview/window_selector_item.h b/chromium/ash/wm/overview/window_selector_item.h deleted file mode 100644 index 0ea7178976a..00000000000 --- a/chromium/ash/wm/overview/window_selector_item.h +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2013 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_OVERVIEW_WINDOW_SELECTOR_ITEM_H_ -#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_ITEM_H_ - -#include "base/compiler_specific.h" -#include "ui/gfx/rect.h" - -namespace aura { -class Window; -} - -namespace ash { - -// This class represents an item in overview mode. An item can have one or more -// windows, of which only one can be activated by keyboard (i.e. alt+tab) but -// any can be selected with a pointer (touch or mouse). -class WindowSelectorItem { - public: - WindowSelectorItem(); - virtual ~WindowSelectorItem(); - - // Returns the root window on which this item is shown. - virtual aura::Window* GetRootWindow() = 0; - - // Returns true if the window selector item has |window| as a selectable - // window. - virtual bool HasSelectableWindow(const aura::Window* window) = 0; - - // Returns the targeted window given the event |target| window. - // Returns NULL if no Window in this item was selected. - virtual aura::Window* TargetedWindow(const aura::Window* target) = 0; - - // Restores |window| on exiting window overview rather than returning it - // to its previous state. - virtual void RestoreWindowOnExit(aura::Window* window) = 0; - - // Returns the |window| to activate on selecting of this item. - virtual aura::Window* SelectionWindow() = 0; - - // Removes |window| from this item. Check empty() after calling this to see - // if the entire item is now empty. - virtual void RemoveWindow(const aura::Window* window) = 0; - - // Returns true if this item has no more selectable windows (i.e. after - // calling RemoveWindow for the last contained window). - virtual bool empty() const = 0; - - // Dispatched before beginning window overview. This will do any necessary - // one time actions such as restoring minimized windows. - virtual void PrepareForOverview() = 0; - - // Sets the bounds of this window selector item to |target_bounds| in the - // |root_window| root window. - void SetBounds(aura::Window* root_window, - const gfx::Rect& target_bounds); - - // Recomputes the positions for the windows in this selection item. This is - // dispatched when the bounds of a window change. - void RecomputeWindowTransforms(); - - const gfx::Rect& bounds() { return bounds_; } - const gfx::Rect& target_bounds() { return target_bounds_; } - - protected: - // Sets the bounds of this selector item to |target_bounds| in |root_window|. - // If |animate| the windows are animated from their current location. - virtual void SetItemBounds(aura::Window* root_window, - const gfx::Rect& target_bounds, - bool animate) = 0; - - // Sets the bounds used by the selector item's windows. - void set_bounds(const gfx::Rect& bounds) { bounds_ = bounds; } - - private: - // The root window this item is being displayed on. - aura::Window* root_window_; - - // The target bounds this selector item is fit within. - gfx::Rect target_bounds_; - - // The actual bounds of the window(s) for this item. The aspect ratio of - // window(s) are maintained so they may not fill the target_bounds_. - gfx::Rect bounds_; - - // True if running SetItemBounds. This prevents recursive calls resulting from - // the bounds update when calling views::corewm::RecreateWindowLayers to copy - // a window layer for display on another monitor. - bool in_bounds_update_; - - DISALLOW_COPY_AND_ASSIGN(WindowSelectorItem); -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_ITEM_H_ diff --git a/chromium/ash/wm/overview/window_selector_panels.cc b/chromium/ash/wm/overview/window_selector_panels.cc deleted file mode 100644 index 914b84866de..00000000000 --- a/chromium/ash/wm/overview/window_selector_panels.cc +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2013 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/overview/window_selector_panels.h" - -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/overview/scoped_transform_overview_window.h" -#include "ash/wm/panels/panel_layout_manager.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animation_observer.h" -#include "ui/compositor/layer_animation_sequence.h" -#include "ui/views/widget/widget.h" - -namespace ash { - -namespace { - -const int kPanelCalloutFadeInDurationMilliseconds = 50; - -// This class extends ScopedTransformOverviewMode to hide and show the callout -// widget for a panel window when entering / leaving overview mode. -class ScopedTransformPanelWindow : public ScopedTransformOverviewWindow { - public: - ScopedTransformPanelWindow(aura::Window* window); - virtual ~ScopedTransformPanelWindow(); - - // ScopedTransformOverviewWindow overrides: - virtual void PrepareForOverview() OVERRIDE; - - private: - // Returns the callout widget for the transformed panel. - views::Widget* GetCalloutWidget(); - - // Restores the callout visibility. - void RestoreCallout(); - - // Trigger relayout - void Relayout(); - - bool callout_visible_; - - DISALLOW_COPY_AND_ASSIGN(ScopedTransformPanelWindow); -}; - -ScopedTransformPanelWindow::ScopedTransformPanelWindow(aura::Window* window) - : ScopedTransformOverviewWindow(window) { -} - -ScopedTransformPanelWindow::~ScopedTransformPanelWindow() { - // window() will be NULL if the window was destroyed. - if (window()) - RestoreCallout(); -} - -void ScopedTransformPanelWindow::PrepareForOverview() { - ScopedTransformOverviewWindow::PrepareForOverview(); - GetCalloutWidget()->GetLayer()->SetOpacity(0.0f); -} - -views::Widget* ScopedTransformPanelWindow::GetCalloutWidget() { - DCHECK(window()->parent()->id() == internal::kShellWindowId_PanelContainer); - internal::PanelLayoutManager* panel_layout_manager = - static_cast<internal::PanelLayoutManager*>( - window()->parent()->layout_manager()); - return panel_layout_manager->GetCalloutWidgetForPanel(window()); -} - -void ScopedTransformPanelWindow::RestoreCallout() { - scoped_ptr<ui::LayerAnimationSequence> sequence( - new ui::LayerAnimationSequence); - ui::LayerAnimationElement::AnimatableProperties paused_properties; - paused_properties.insert(ui::LayerAnimationElement::OPACITY); - sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement( - paused_properties, base::TimeDelta::FromMilliseconds( - ScopedTransformOverviewWindow::kTransitionMilliseconds))); - sequence->AddElement(ui::LayerAnimationElement::CreateOpacityElement(1, - base::TimeDelta::FromMilliseconds( - kPanelCalloutFadeInDurationMilliseconds))); - GetCalloutWidget()->GetLayer()->GetAnimator()->StartAnimation( - sequence.release()); -} - -} // namespace - -WindowSelectorPanels::WindowSelectorPanels() { -} - -WindowSelectorPanels::~WindowSelectorPanels() { -} - -void WindowSelectorPanels::AddWindow(aura::Window* window) { - transform_windows_.push_back(new ScopedTransformPanelWindow(window)); -} - -aura::Window* WindowSelectorPanels::GetRootWindow() { - return transform_windows_.front()->window()->GetRootWindow(); -} - -bool WindowSelectorPanels::HasSelectableWindow(const aura::Window* window) { - for (WindowList::const_iterator iter = transform_windows_.begin(); - iter != transform_windows_.end(); ++iter) { - if ((*iter)->window() == window) - return true; - } - return false; -} - -aura::Window* WindowSelectorPanels::TargetedWindow(const aura::Window* target) { - for (WindowList::const_iterator iter = transform_windows_.begin(); - iter != transform_windows_.end(); ++iter) { - if ((*iter)->Contains(target)) - return (*iter)->window(); - } - return NULL; -} - -void WindowSelectorPanels::RestoreWindowOnExit(aura::Window* window) { - for (WindowList::iterator iter = transform_windows_.begin(); - iter != transform_windows_.end(); ++iter) { - if ((*iter)->Contains(window)) { - (*iter)->RestoreWindowOnExit(); - break; - } - } -} - -aura::Window* WindowSelectorPanels::SelectionWindow() { - return transform_windows_.front()->window(); -} - -void WindowSelectorPanels::RemoveWindow(const aura::Window* window) { - for (WindowList::iterator iter = transform_windows_.begin(); - iter != transform_windows_.end(); ++iter) { - if ((*iter)->window() == window) { - (*iter)->OnWindowDestroyed(); - transform_windows_.erase(iter); - break; - } - } -} - -bool WindowSelectorPanels::empty() const { - return transform_windows_.empty(); -} - -void WindowSelectorPanels::PrepareForOverview() { - for (WindowList::iterator iter = transform_windows_.begin(); - iter != transform_windows_.end(); ++iter) { - (*iter)->PrepareForOverview(); - } -} - -void WindowSelectorPanels::SetItemBounds(aura::Window* root_window, - const gfx::Rect& target_bounds, - bool animate) { - gfx::Rect bounding_rect; - for (WindowList::iterator iter = transform_windows_.begin(); - iter != transform_windows_.end(); ++iter) { - bounding_rect.Union((*iter)->GetBoundsInScreen()); - } - set_bounds(ScopedTransformOverviewWindow:: - ShrinkRectToFitPreservingAspectRatio(bounding_rect, target_bounds)); - gfx::Transform bounding_transform = - ScopedTransformOverviewWindow::GetTransformForRect(bounding_rect, - bounds()); - for (WindowList::iterator iter = transform_windows_.begin(); - iter != transform_windows_.end(); ++iter) { - gfx::Transform transform; - gfx::Rect bounds = (*iter)->GetBoundsInScreen(); - transform.Translate(bounding_rect.x() - bounds.x(), - bounding_rect.y() - bounds.y()); - transform.PreconcatTransform(bounding_transform); - transform.Translate(bounds.x() - bounding_rect.x(), - bounds.y() - bounding_rect.y()); - (*iter)->SetTransform(root_window, transform, animate); - } -} - -} // namespace ash diff --git a/chromium/ash/wm/overview/window_selector_panels.h b/chromium/ash/wm/overview/window_selector_panels.h deleted file mode 100644 index 88c31a24719..00000000000 --- a/chromium/ash/wm/overview/window_selector_panels.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2013 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_OVERVIEW_WINDOW_SELECTOR_PANELS_H_ -#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_PANELS_H_ - -#include "ash/wm/overview/window_selector_item.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_vector.h" -#include "ui/gfx/rect.h" - -namespace ash { - -class ScopedTransformOverviewWindow; - -// This class implements a window selector item containing one or more attached -// panel windows. These panels are grouped into a single overview item in -// overview mode and the callout arrows are hidden at this point. -class WindowSelectorPanels : public WindowSelectorItem { - public: - WindowSelectorPanels(); - virtual ~WindowSelectorPanels(); - - // Adds |window| to the selector item. This window should be an attached - // panel window. - void AddWindow(aura::Window* window); - - // WindowSelectorItem: - virtual aura::Window* GetRootWindow() OVERRIDE; - virtual bool HasSelectableWindow(const aura::Window* window) OVERRIDE; - virtual aura::Window* TargetedWindow(const aura::Window* target) OVERRIDE; - virtual void RestoreWindowOnExit(aura::Window* window) OVERRIDE; - virtual aura::Window* SelectionWindow() OVERRIDE; - virtual void RemoveWindow(const aura::Window* window) OVERRIDE; - virtual bool empty() const OVERRIDE; - virtual void PrepareForOverview() OVERRIDE; - virtual void SetItemBounds(aura::Window* root_window, - const gfx::Rect& target_bounds, - bool animate) OVERRIDE; - - private: - typedef ScopedVector<ScopedTransformOverviewWindow> WindowList; - WindowList transform_windows_; - - DISALLOW_COPY_AND_ASSIGN(WindowSelectorPanels); -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_PANELS_H_ diff --git a/chromium/ash/wm/overview/window_selector_unittest.cc b/chromium/ash/wm/overview/window_selector_unittest.cc deleted file mode 100644 index 199f4a72c20..00000000000 --- a/chromium/ash/wm/overview/window_selector_unittest.cc +++ /dev/null @@ -1,998 +0,0 @@ -// Copyright 2013 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/launcher/launcher.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/launcher_test_api.h" -#include "ash/test/shelf_view_test_api.h" -#include "ash/test/shell_test_api.h" -#include "ash/test/test_shelf_delegate.h" -#include "ash/wm/mru_window_tracker.h" -#include "ash/wm/overview/window_selector.h" -#include "ash/wm/overview/window_selector_controller.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_vector.h" -#include "base/run_loop.h" -#include "ui/aura/client/activation_delegate.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/cursor_client.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" -#include "ui/gfx/rect_conversions.h" -#include "ui/gfx/transform.h" - -namespace ash { -namespace internal { - -namespace { - -class NonActivatableActivationDelegate - : public aura::client::ActivationDelegate { - public: - virtual bool ShouldActivate() const OVERRIDE { - return false; - } -}; - -bool IsWindowAbove(aura::Window* w1, aura::Window* w2) { - aura::Window* parent = w1->parent(); - DCHECK_EQ(parent, w2->parent()); - for (aura::Window::Windows::const_iterator iter = parent->children().begin(); - iter != parent->children().end(); ++iter) { - if (*iter == w1) - return false; - if (*iter == w2) - return true; - } - NOTREACHED(); - return false; -} - -aura::Window* GetWindowByName(aura::Window* container, - const std::string& name) { - aura::Window* window = NULL; - for (aura::Window::Windows::const_iterator iter = - container->children().begin(); iter != container->children().end(); - ++iter) { - if ((*iter)->name() == name) { - // The name should be unique. - DCHECK(!window); - window = *iter; - } - } - return window; -} - -// Returns the copy of |window| created for overview. It is found using the -// window name which should be the same as the source window's name with a -// special suffix, and in the same container as the source window. -aura::Window* GetCopyWindow(aura::Window* window) { - aura::Window* copy_window = NULL; - std::string copy_name = window->name() + " (Copy)"; - std::vector<aura::Window*> containers( - Shell::GetContainersFromAllRootWindows(window->parent()->id(), NULL)); - for (std::vector<aura::Window*>::iterator iter = containers.begin(); - iter != containers.end(); ++iter) { - aura::Window* found = GetWindowByName(*iter, copy_name); - if (found) { - // There should only be one copy window. - DCHECK(!copy_window); - copy_window = found; - } - } - return copy_window; -} - -} // namespace - -class WindowSelectorTest : public test::AshTestBase { - public: - WindowSelectorTest() {} - virtual ~WindowSelectorTest() {} - - virtual void SetUp() OVERRIDE { - test::AshTestBase::SetUp(); - ASSERT_TRUE(test::TestShelfDelegate::instance()); - - shelf_view_test_.reset(new test::ShelfViewTestAPI( - test::LauncherTestAPI(Launcher::ForPrimaryDisplay()).shelf_view())); - shelf_view_test_->SetAnimationDuration(1); - } - - aura::Window* CreateWindow(const gfx::Rect& bounds) { - return CreateTestWindowInShellWithDelegate(&delegate_, -1, bounds); - } - - aura::Window* CreateNonActivatableWindow(const gfx::Rect& bounds) { - aura::Window* window = CreateWindow(bounds); - aura::client::SetActivationDelegate(window, - &non_activatable_activation_delegate_); - EXPECT_FALSE(ash::wm::CanActivateWindow(window)); - return window; - } - - aura::Window* CreatePanelWindow(const gfx::Rect& bounds) { - aura::Window* window = CreateTestWindowInShellWithDelegateAndType( - NULL, aura::client::WINDOW_TYPE_PANEL, 0, bounds); - test::TestShelfDelegate::instance()->AddLauncherItem(window); - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - return window; - } - - bool WindowsOverlapping(aura::Window* window1, aura::Window* window2) { - gfx::RectF window1_bounds = GetTransformedTargetBounds(window1); - gfx::RectF window2_bounds = GetTransformedTargetBounds(window2); - return window1_bounds.Intersects(window2_bounds); - } - - void ToggleOverview() { - ash::Shell::GetInstance()->window_selector_controller()->ToggleOverview(); - } - - void Cycle(WindowSelector::Direction direction) { - ash::Shell::GetInstance()->window_selector_controller()-> - HandleCycleWindow(direction); - } - - void StopCycling() { - ash::Shell::GetInstance()->window_selector_controller()->window_selector_-> - SelectWindow(); - } - - void FireOverviewStartTimer() { - // Calls the method to start overview mode which is normally called by the - // timer. The timer will still fire and call this method triggering the - // DCHECK that overview mode was not already started, except that we call - // StopCycling before the timer has a chance to fire. - ash::Shell::GetInstance()->window_selector_controller()->window_selector_-> - StartOverview(); - } - - gfx::Transform GetTransformRelativeTo(gfx::PointF origin, - const gfx::Transform& transform) { - gfx::Transform t; - t.Translate(origin.x(), origin.y()); - t.PreconcatTransform(transform); - t.Translate(-origin.x(), -origin.y()); - return t; - } - - gfx::RectF GetTransformedBounds(aura::Window* window) { - gfx::RectF bounds(ash::ScreenAsh::ConvertRectToScreen( - window->parent(), window->layer()->bounds())); - gfx::Transform transform(GetTransformRelativeTo(bounds.origin(), - window->layer()->transform())); - transform.TransformRect(&bounds); - return bounds; - } - - gfx::RectF GetTransformedTargetBounds(aura::Window* window) { - gfx::RectF bounds(ash::ScreenAsh::ConvertRectToScreen( - window->parent(), window->layer()->GetTargetBounds())); - gfx::Transform transform(GetTransformRelativeTo(bounds.origin(), - window->layer()->GetTargetTransform())); - transform.TransformRect(&bounds); - return bounds; - } - - void ClickWindow(aura::Window* window) { - aura::test::EventGenerator event_generator(window->GetRootWindow(), window); - gfx::RectF target = GetTransformedBounds(window); - event_generator.ClickLeftButton(); - } - - bool IsSelecting() { - return ash::Shell::GetInstance()->window_selector_controller()-> - IsSelecting(); - } - - aura::Window* GetFocusedWindow() { - return aura::client::GetFocusClient( - Shell::GetPrimaryRootWindow())->GetFocusedWindow(); - } - - test::ShelfViewTestAPI* shelf_view_test() { - return shelf_view_test_.get(); - } - - private: - aura::test::TestWindowDelegate delegate_; - NonActivatableActivationDelegate non_activatable_activation_delegate_; - scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_; - - DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest); -}; - -// Tests entering overview mode with two windows and selecting one. -TEST_F(WindowSelectorTest, Basic) { - gfx::Rect bounds(0, 0, 400, 400); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds)); - EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get())); - EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get())); - wm::ActivateWindow(window2.get()); - EXPECT_FALSE(wm::IsActiveWindow(window1.get())); - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - EXPECT_EQ(window2.get(), GetFocusedWindow()); - // Hide the cursor before entering overview to test that it will be shown. - aura::client::GetCursorClient(root_window)->HideCursor(); - - // In overview mode the windows should no longer overlap and focus should - // be removed from the window. - ToggleOverview(); - EXPECT_EQ(NULL, GetFocusedWindow()); - EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get())); - EXPECT_FALSE(WindowsOverlapping(window1.get(), panel1.get())); - // Panels 1 and 2 should still be overlapping being in a single selector - // item. - EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get())); - - // The cursor should be visible and locked as a pointer - EXPECT_EQ(ui::kCursorPointer, - root_window->GetDispatcher()->last_cursor().native_type()); - EXPECT_TRUE(aura::client::GetCursorClient(root_window)->IsCursorLocked()); - EXPECT_TRUE(aura::client::GetCursorClient(root_window)->IsCursorVisible()); - - // Clicking window 1 should activate it. - ClickWindow(window1.get()); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - EXPECT_FALSE(wm::IsActiveWindow(window2.get())); - EXPECT_EQ(window1.get(), GetFocusedWindow()); - - // Cursor should have been unlocked. - EXPECT_FALSE(aura::client::GetCursorClient(root_window)->IsCursorLocked()); -} - -// Tests entering overview mode with two windows and selecting one. -TEST_F(WindowSelectorTest, FullscreenWindow) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds)); - wm::ActivateWindow(window1.get()); - - wm::GetWindowState(window1.get())->ToggleFullscreen(); - // The panel is hidden in fullscreen mode. - EXPECT_FALSE(panel1->IsVisible()); - EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen()); - - // Enter overview and select the fullscreen window. - ToggleOverview(); - - // The panel becomes temporarily visible for the overview. - EXPECT_TRUE(panel1->IsVisible()); - ClickWindow(window1.get()); - - // The window is still fullscreen as it was selected. The panel should again - // be hidden. - EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen()); - EXPECT_FALSE(panel1->IsVisible()); - - // Entering overview and selecting another window, the previous window remains - // fullscreen. - // TODO(flackr): Currently the panel remains hidden, but should become visible - // again. - ToggleOverview(); - ClickWindow(window2.get()); - EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen()); -} - -// Tests that the shelf dimming state is removed while in overview and restored -// on exiting overview. -TEST_F(WindowSelectorTest, OverviewUndimsShelf) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - wm::WindowState* window_state = wm::GetWindowState(window1.get()); - window_state->Maximize(); - ash::ShelfWidget* shelf = Shell::GetPrimaryRootWindowController()->shelf(); - EXPECT_TRUE(shelf->GetDimsShelf()); - ToggleOverview(); - EXPECT_FALSE(shelf->GetDimsShelf()); - ToggleOverview(); - EXPECT_TRUE(shelf->GetDimsShelf()); -} - -// Tests that beginning window selection hides the app list. -TEST_F(WindowSelectorTest, SelectingHidesAppList) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - Shell::GetInstance()->ToggleAppList(NULL); - EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); - ToggleOverview(); - EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility()); - ToggleOverview(); - - // The app list uses an animation to fade out. If it is toggled on immediately - // after being removed the old widget is re-used and it does not gain focus. - // When running under normal circumstances this shouldn't be possible, but - // it is in a test without letting the message loop run. - RunAllPendingInMessageLoop(); - - Shell::GetInstance()->ToggleAppList(NULL); - EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); - Cycle(WindowSelector::FORWARD); - EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility()); - StopCycling(); -} - -// Tests that a minimized window's visibility and layer visibility is correctly -// changed when entering overview and restored when leaving overview mode. -TEST_F(WindowSelectorTest, MinimizedWindowVisibility) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - wm::WindowState* window_state = wm::GetWindowState(window1.get()); - window_state->Minimize(); - EXPECT_FALSE(window1->IsVisible()); - EXPECT_FALSE(window1->layer()->GetTargetVisibility()); - { - ui::ScopedAnimationDurationScaleMode normal_duration_mode( - ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); - ToggleOverview(); - EXPECT_TRUE(window1->IsVisible()); - EXPECT_TRUE(window1->layer()->GetTargetVisibility()); - } - { - ui::ScopedAnimationDurationScaleMode normal_duration_mode( - ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); - ToggleOverview(); - EXPECT_FALSE(window1->IsVisible()); - EXPECT_FALSE(window1->layer()->GetTargetVisibility()); - } -} - -// Tests that a bounds change during overview is corrected for. -TEST_F(WindowSelectorTest, BoundsChangeDuringOverview) { - scoped_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 400, 400))); - ToggleOverview(); - gfx::Rect overview_bounds = - ToEnclosingRect(GetTransformedTargetBounds(window.get())); - window->SetBounds(gfx::Rect(200, 0, 200, 200)); - gfx::Rect new_overview_bounds = - ToEnclosingRect(GetTransformedTargetBounds(window.get())); - EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x()); - EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y()); - EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width()); - EXPECT_EQ(overview_bounds.height(), new_overview_bounds.height()); - ToggleOverview(); -} - -// Tests entering overview mode with three windows and cycling through them. -TEST_F(WindowSelectorTest, BasicCycle) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - scoped_ptr<aura::Window> window3(CreateWindow(bounds)); - wm::ActivateWindow(window3.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - EXPECT_FALSE(wm::IsActiveWindow(window2.get())); - EXPECT_FALSE(wm::IsActiveWindow(window3.get())); - - Cycle(WindowSelector::FORWARD); - EXPECT_TRUE(IsSelecting()); - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - - Cycle(WindowSelector::FORWARD); - EXPECT_TRUE(wm::IsActiveWindow(window3.get())); - - StopCycling(); - EXPECT_FALSE(IsSelecting()); - EXPECT_FALSE(wm::IsActiveWindow(window1.get())); - EXPECT_FALSE(wm::IsActiveWindow(window2.get())); - EXPECT_TRUE(wm::IsActiveWindow(window3.get())); -} - -// Tests that cycling through windows preserves the window stacking order. -TEST_F(WindowSelectorTest, CyclePreservesStackingOrder) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - scoped_ptr<aura::Window> window3(CreateWindow(bounds)); - wm::ActivateWindow(window3.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); - // Window order from top to bottom is 1, 2, 3. - EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get())); - EXPECT_TRUE(IsWindowAbove(window2.get(), window3.get())); - - // On window 2. - Cycle(WindowSelector::FORWARD); - EXPECT_TRUE(IsWindowAbove(window2.get(), window1.get())); - EXPECT_TRUE(IsWindowAbove(window1.get(), window3.get())); - - // On window 3. - Cycle(WindowSelector::FORWARD); - EXPECT_TRUE(IsWindowAbove(window3.get(), window1.get())); - EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get())); - - // Back on window 1. - Cycle(WindowSelector::FORWARD); - EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get())); - EXPECT_TRUE(IsWindowAbove(window2.get(), window3.get())); - StopCycling(); -} - -// Tests that cycling through windows shows and minimizes windows as they -// are passed. -TEST_F(WindowSelectorTest, CyclePreservesMinimization) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - wm::ActivateWindow(window2.get()); - wm::GetWindowState(window2.get())->Minimize(); - wm::ActivateWindow(window1.get()); - EXPECT_TRUE(wm::IsWindowMinimized(window2.get())); - - // On window 2. - Cycle(WindowSelector::FORWARD); - EXPECT_FALSE(wm::IsWindowMinimized(window2.get())); - - // Back on window 1. - Cycle(WindowSelector::FORWARD); - EXPECT_TRUE(wm::IsWindowMinimized(window2.get())); - - StopCycling(); - EXPECT_TRUE(wm::IsWindowMinimized(window2.get())); -} - -// Tests beginning cycling while in overview mode. -TEST_F(WindowSelectorTest, OverviewTransitionToCycle) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); - - ToggleOverview(); - Cycle(WindowSelector::FORWARD); - StopCycling(); - - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - EXPECT_FALSE(wm::IsActiveWindow(window1.get())); - EXPECT_EQ(window2.get(), GetFocusedWindow()); -} - -// Tests cycles between panel and normal windows. -TEST_F(WindowSelectorTest, CyclePanels) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds)); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); - wm::ActivateWindow(panel2.get()); - wm::ActivateWindow(panel1.get()); - EXPECT_TRUE(wm::IsActiveWindow(panel1.get())); - - // Cycling once should select window1 since the panels are grouped into a - // single selectable item. - Cycle(WindowSelector::FORWARD); - StopCycling(); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - // Cycling again should select the most recently used panel. - Cycle(WindowSelector::FORWARD); - StopCycling(); - EXPECT_TRUE(wm::IsActiveWindow(panel1.get())); -} - -// Tests the visibility of panel windows during cycling. -TEST_F(WindowSelectorTest, CyclePanelVisibility) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds)); - wm::ActivateWindow(panel1.get()); - wm::ActivateWindow(window1.get()); - - Cycle(WindowSelector::FORWARD); - FireOverviewStartTimer(); - EXPECT_EQ(1.0f, panel1->layer()->GetTargetOpacity()); - StopCycling(); -} - -// Tests cycles between panel and normal windows. -TEST_F(WindowSelectorTest, CyclePanelsDestroyed) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - scoped_ptr<aura::Window> window3(CreateWindow(bounds)); - scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds)); - wm::ActivateWindow(window3.get()); - wm::ActivateWindow(panel2.get()); - wm::ActivateWindow(panel1.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - // Cycling once highlights window2. - Cycle(WindowSelector::FORWARD); - // All panels are destroyed. - panel1.reset(); - panel2.reset(); - // Cycling again should now select window3. - Cycle(WindowSelector::FORWARD); - StopCycling(); - EXPECT_TRUE(wm::IsActiveWindow(window3.get())); -} - -// Tests cycles between panel and normal windows. -TEST_F(WindowSelectorTest, CycleMruPanelDestroyed) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds)); - wm::ActivateWindow(panel2.get()); - wm::ActivateWindow(panel1.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - // Cycling once highlights window2. - Cycle(WindowSelector::FORWARD); - // Panel 1 is the next item as the MRU panel, removing it should make panel 2 - // the next window to be selected. - panel1.reset(); - // Cycling again should now select window3. - Cycle(WindowSelector::FORWARD); - StopCycling(); - EXPECT_TRUE(wm::IsActiveWindow(panel2.get())); -} - -// Tests that a newly created window aborts overview. -TEST_F(WindowSelectorTest, NewWindowCancelsOveriew) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - ToggleOverview(); - EXPECT_TRUE(IsSelecting()); - - // A window being created should exit overview mode. - scoped_ptr<aura::Window> window3(CreateWindow(bounds)); - EXPECT_FALSE(IsSelecting()); -} - -// Tests that a window activation exits overview mode. -TEST_F(WindowSelectorTest, ActivationCancelsOveriew) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - window2->Focus(); - ToggleOverview(); - EXPECT_TRUE(IsSelecting()); - - // A window being activated should exit overview mode. - window1->Focus(); - EXPECT_FALSE(IsSelecting()); - - // window1 should be focused after exiting even though window2 was focused on - // entering overview because we exited due to an activation. - EXPECT_EQ(window1.get(), GetFocusedWindow()); -} - -// Verifies that overview mode only begins after a delay when cycling. -TEST_F(WindowSelectorTest, CycleOverviewDelay) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get())); - - // When cycling first starts, the windows will still be overlapping. - Cycle(WindowSelector::FORWARD); - EXPECT_TRUE(IsSelecting()); - EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get())); - - // Once the overview timer fires, the windows should no longer overlap. - FireOverviewStartTimer(); - EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get())); - StopCycling(); -} - -// Tests that exiting overview mode without selecting a window restores focus -// to the previously focused window. -TEST_F(WindowSelectorTest, CancelRestoresFocus) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window(CreateWindow(bounds)); - wm::ActivateWindow(window.get()); - EXPECT_EQ(window.get(), GetFocusedWindow()); - - // In overview mode, focus should be removed. - ToggleOverview(); - EXPECT_EQ(NULL, GetFocusedWindow()); - - // If canceling overview mode, focus should be restored. - ToggleOverview(); - EXPECT_EQ(window.get(), GetFocusedWindow()); -} - -// Tests that overview mode is exited if the last remaining window is destroyed. -TEST_F(WindowSelectorTest, LastWindowDestroyed) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - ToggleOverview(); - - window1.reset(); - window2.reset(); - EXPECT_FALSE(IsSelecting()); -} - -// Tests that entering overview mode restores a window to its original -// target location. -TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window(CreateWindow(bounds)); - gfx::Rect initial_bounds = ToEnclosingRect( - GetTransformedBounds(window.get())); - ToggleOverview(); - // Quickly exit and reenter overview mode. The window should still be - // animating when we reenter. We cannot short circuit animations for this but - // we also don't have to wait for them to complete. - { - ui::ScopedAnimationDurationScaleMode normal_duration_mode( - ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); - ToggleOverview(); - ToggleOverview(); - } - EXPECT_NE(initial_bounds, ToEnclosingRect( - GetTransformedTargetBounds(window.get()))); - ToggleOverview(); - EXPECT_FALSE(IsSelecting()); - EXPECT_EQ(initial_bounds, ToEnclosingRect( - GetTransformedTargetBounds(window.get()))); -} - -// Tests that non-activatable windows are hidden when entering overview mode. -TEST_F(WindowSelectorTest, NonActivatableWindowsHidden) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds)); - scoped_ptr<aura::Window> non_activatable_window( - CreateNonActivatableWindow(Shell::GetPrimaryRootWindow()->bounds())); - EXPECT_TRUE(non_activatable_window->IsVisible()); - ToggleOverview(); - EXPECT_FALSE(non_activatable_window->IsVisible()); - ToggleOverview(); - EXPECT_TRUE(non_activatable_window->IsVisible()); - - // Test that a window behind the fullscreen non-activatable window can be - // clicked. - non_activatable_window->parent()->StackChildAtTop( - non_activatable_window.get()); - ToggleOverview(); - ClickWindow(window1.get()); - EXPECT_FALSE(IsSelecting()); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); -} - -// Tests that windows with modal child windows are transformed with the modal -// child even though not activatable themselves. -TEST_F(WindowSelectorTest, ModalChild) { - gfx::Rect bounds(0, 0, 400, 400); - scoped_ptr<aura::Window> window1(CreateWindow(bounds)); - scoped_ptr<aura::Window> child1(CreateWindow(bounds)); - child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - window1->AddTransientChild(child1.get()); - EXPECT_EQ(window1->parent(), child1->parent()); - ToggleOverview(); - EXPECT_TRUE(window1->IsVisible()); - EXPECT_TRUE(child1->IsVisible()); - EXPECT_EQ(ToEnclosingRect(GetTransformedTargetBounds(child1.get())), - ToEnclosingRect(GetTransformedTargetBounds(window1.get()))); - ToggleOverview(); -} - -// Tests that clicking a modal window's parent activates the modal window in -// overview. -TEST_F(WindowSelectorTest, ClickModalWindowParent) { - scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 180, 180))); - scoped_ptr<aura::Window> child1(CreateWindow(gfx::Rect(200, 0, 180, 180))); - child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - window1->AddTransientChild(child1.get()); - EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get())); - EXPECT_EQ(window1->parent(), child1->parent()); - ToggleOverview(); - // Given that their relative positions are preserved, the windows should still - // not overlap. - EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get())); - ClickWindow(window1.get()); - EXPECT_FALSE(IsSelecting()); - - // Clicking on window1 should activate child1. - EXPECT_TRUE(wm::IsActiveWindow(child1.get())); -} - -// Tests that windows remain on the display they are currently on in overview -// mode. -TEST_F(WindowSelectorTest, MultipleDisplays) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("600x400,600x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - gfx::Rect bounds1(0, 0, 400, 400); - gfx::Rect bounds2(650, 0, 400, 400); - - scoped_ptr<aura::Window> window1(CreateWindow(bounds1)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds1)); - scoped_ptr<aura::Window> window3(CreateWindow(bounds2)); - scoped_ptr<aura::Window> window4(CreateWindow(bounds2)); - scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds1)); - scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds1)); - scoped_ptr<aura::Window> panel3(CreatePanelWindow(bounds2)); - scoped_ptr<aura::Window> panel4(CreatePanelWindow(bounds2)); - EXPECT_EQ(root_windows[0], window1->GetRootWindow()); - EXPECT_EQ(root_windows[0], window2->GetRootWindow()); - EXPECT_EQ(root_windows[1], window3->GetRootWindow()); - EXPECT_EQ(root_windows[1], window4->GetRootWindow()); - - EXPECT_EQ(root_windows[0], panel1->GetRootWindow()); - EXPECT_EQ(root_windows[0], panel2->GetRootWindow()); - EXPECT_EQ(root_windows[1], panel3->GetRootWindow()); - EXPECT_EQ(root_windows[1], panel4->GetRootWindow()); - - // In overview mode, each window remains in the same root window. - ToggleOverview(); - EXPECT_EQ(root_windows[0], window1->GetRootWindow()); - EXPECT_EQ(root_windows[0], window2->GetRootWindow()); - EXPECT_EQ(root_windows[1], window3->GetRootWindow()); - EXPECT_EQ(root_windows[1], window4->GetRootWindow()); - EXPECT_EQ(root_windows[0], panel1->GetRootWindow()); - EXPECT_EQ(root_windows[0], panel2->GetRootWindow()); - EXPECT_EQ(root_windows[1], panel3->GetRootWindow()); - EXPECT_EQ(root_windows[1], panel4->GetRootWindow()); - - EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(window1.get())))); - EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(window2.get())))); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(window3.get())))); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(window4.get())))); - - EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(panel1.get())))); - EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(panel2.get())))); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(panel3.get())))); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(panel4.get())))); - EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get())); - EXPECT_TRUE(WindowsOverlapping(panel3.get(), panel4.get())); - EXPECT_FALSE(WindowsOverlapping(panel1.get(), panel3.get())); -} - -// Verifies that the single display overview used during alt tab cycling uses -// the display of the selected window by default. -TEST_F(WindowSelectorTest, CycleOverviewUsesCurrentDisplay) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("400x400,400x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100))); - scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100))); - EXPECT_EQ(root_windows[0], window1->GetRootWindow()); - EXPECT_EQ(root_windows[1], window2->GetRootWindow()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); - EXPECT_EQ(root_windows[0], Shell::GetTargetRootWindow()); - - Cycle(WindowSelector::FORWARD); - FireOverviewStartTimer(); - - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(window1.get())))); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(window2.get())))); - StopCycling(); -} - -// Verifies that the windows being shown on another display are copied. -TEST_F(WindowSelectorTest, CycleMultipleDisplaysCopiesWindows) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("400x400,400x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - gfx::Rect root1_rect(0, 0, 100, 100); - gfx::Rect root2_rect(450, 0, 100, 100); - scoped_ptr<aura::Window> unmoved1(CreateWindow(root2_rect)); - scoped_ptr<aura::Window> unmoved2(CreateWindow(root2_rect)); - scoped_ptr<aura::Window> moved1_trans_parent(CreateWindow(root1_rect)); - scoped_ptr<aura::Window> moved1(CreateWindow(root1_rect)); - unmoved1->SetName("unmoved1"); - unmoved2->SetName("unmoved2"); - moved1->SetName("moved1"); - moved1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - moved1_trans_parent->AddTransientChild(moved1.get()); - moved1_trans_parent->SetName("moved1_trans_parent"); - - EXPECT_EQ(root_windows[0], moved1->GetRootWindow()); - EXPECT_EQ(root_windows[0], moved1_trans_parent->GetRootWindow()); - EXPECT_EQ(root_windows[1], unmoved1->GetRootWindow()); - EXPECT_EQ(root_windows[1], unmoved2->GetRootWindow()); - wm::ActivateWindow(unmoved2.get()); - wm::ActivateWindow(unmoved1.get()); - - Cycle(WindowSelector::FORWARD); - FireOverviewStartTimer(); - - // All windows are moved to second root window. - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(unmoved1.get())))); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(unmoved2.get())))); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(moved1.get())))); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(moved1_trans_parent.get())))); - - // unmoved1 and unmoved2 were already on the correct display and should not - // have been copied. - EXPECT_TRUE(!GetCopyWindow(unmoved1.get())); - EXPECT_TRUE(!GetCopyWindow(unmoved2.get())); - - // moved1 and its transient parent moved1_trans_parent should have also been - // copied for displaying on root_windows[1]. - aura::Window* copy1 = GetCopyWindow(moved1.get()); - aura::Window* copy1_trans_parent = GetCopyWindow(moved1_trans_parent.get()); - ASSERT_FALSE(!copy1); - ASSERT_FALSE(!copy1_trans_parent); - - // Verify that the bounds and transform of the copy match the original window - // but that it is on the other root window. - EXPECT_EQ(root_windows[1], copy1->GetRootWindow()); - EXPECT_EQ(moved1->GetBoundsInScreen().ToString(), - copy1->GetBoundsInScreen().ToString()); - EXPECT_EQ(moved1->layer()->GetTargetTransform().ToString(), - copy1->layer()->GetTargetTransform().ToString()); - StopCycling(); - - // After cycling the copy windows should have been destroyed. - RunAllPendingInMessageLoop(); - EXPECT_TRUE(!GetCopyWindow(moved1.get())); - EXPECT_TRUE(!GetCopyWindow(moved1_trans_parent.get())); -} - -// Tests that beginning to cycle from overview mode moves windows to the -// active display. -TEST_F(WindowSelectorTest, MultipleDisplaysOverviewTransitionToCycle) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("400x400,400x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100))); - scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100))); - EXPECT_EQ(root_windows[0], window1->GetRootWindow()); - EXPECT_EQ(root_windows[1], window2->GetRootWindow()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); - - ToggleOverview(); - EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(window1.get())))); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(window2.get())))); - - Cycle(WindowSelector::FORWARD); - EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(window1.get())))); - EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains( - ToEnclosingRect(GetTransformedTargetBounds(window2.get())))); - StopCycling(); -} - -// Tests that a bounds change during overview is corrected for. -TEST_F(WindowSelectorTest, BoundsChangeDuringCycleOnOtherDisplay) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("400x400,400x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100))); - scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100))); - scoped_ptr<aura::Window> window3(CreateWindow(gfx::Rect(450, 0, 100, 100))); - EXPECT_EQ(root_windows[0], window1->GetRootWindow()); - EXPECT_EQ(root_windows[1], window2->GetRootWindow()); - EXPECT_EQ(root_windows[1], window3->GetRootWindow()); - wm::ActivateWindow(window1.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window3.get()); - - Cycle(WindowSelector::FORWARD); - FireOverviewStartTimer(); - - gfx::Rect overview_bounds( - ToEnclosingRect(GetTransformedTargetBounds(window1.get()))); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(overview_bounds)); - - // Change the position and size of window1 (being displayed on the second - // root window) and it should remain within the same bounds. - window1->SetBounds(gfx::Rect(100, 0, 200, 200)); - gfx::Rect new_overview_bounds = - ToEnclosingRect(GetTransformedTargetBounds(window1.get())); - EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x()); - EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y()); - EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width()); - EXPECT_EQ(overview_bounds.height(), new_overview_bounds.height()); - StopCycling(); -} - -// Tests shutting down during overview. -TEST_F(WindowSelectorTest, Shutdown) { - gfx::Rect bounds(0, 0, 400, 400); - // These windows will be deleted when the test exits and the Shell instance - // is shut down. - aura::Window* window1(CreateWindow(bounds)); - aura::Window* window2(CreateWindow(bounds)); - aura::Window* window3(CreatePanelWindow(bounds)); - aura::Window* window4(CreatePanelWindow(bounds)); - - wm::ActivateWindow(window4); - wm::ActivateWindow(window3); - wm::ActivateWindow(window2); - wm::ActivateWindow(window1); - - ToggleOverview(); -} - -// Tests removing a display during overview. -TEST_F(WindowSelectorTest, RemoveDisplay) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("400x400,400x400"); - gfx::Rect bounds1(0, 0, 100, 100); - gfx::Rect bounds2(450, 0, 100, 100); - scoped_ptr<aura::Window> window1(CreateWindow(bounds1)); - scoped_ptr<aura::Window> window2(CreateWindow(bounds2)); - scoped_ptr<aura::Window> window3(CreatePanelWindow(bounds1)); - scoped_ptr<aura::Window> window4(CreatePanelWindow(bounds2)); - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - EXPECT_EQ(root_windows[0], window1->GetRootWindow()); - EXPECT_EQ(root_windows[1], window2->GetRootWindow()); - EXPECT_EQ(root_windows[0], window3->GetRootWindow()); - EXPECT_EQ(root_windows[1], window4->GetRootWindow()); - - wm::ActivateWindow(window4.get()); - wm::ActivateWindow(window3.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); - - ToggleOverview(); - EXPECT_TRUE(IsSelecting()); - UpdateDisplay("400x400"); - EXPECT_FALSE(IsSelecting()); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/overview/window_selector_window.cc b/chromium/ash/wm/overview/window_selector_window.cc deleted file mode 100644 index ea8241678dc..00000000000 --- a/chromium/ash/wm/overview/window_selector_window.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2013 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/overview/window_selector_window.h" - -#include "ui/aura/window.h" - -namespace ash { - -WindowSelectorWindow::WindowSelectorWindow(aura::Window* window) - : transform_window_(window) { -} - -WindowSelectorWindow::~WindowSelectorWindow() { -} - -aura::Window* WindowSelectorWindow::GetRootWindow() { - return transform_window_.window()->GetRootWindow(); -} - -bool WindowSelectorWindow::HasSelectableWindow(const aura::Window* window) { - return transform_window_.window() == window; -} - -aura::Window* WindowSelectorWindow::TargetedWindow(const aura::Window* target) { - if (transform_window_.Contains(target)) - return transform_window_.window(); - return NULL; -} - -void WindowSelectorWindow::RestoreWindowOnExit(aura::Window* window) { - transform_window_.RestoreWindowOnExit(); -} - -aura::Window* WindowSelectorWindow::SelectionWindow() { - return transform_window_.window(); -} - -void WindowSelectorWindow::RemoveWindow(const aura::Window* window) { - DCHECK_EQ(transform_window_.window(), window); - transform_window_.OnWindowDestroyed(); -} - -bool WindowSelectorWindow::empty() const { - return transform_window_.window() == NULL; -} - -void WindowSelectorWindow::PrepareForOverview() { - transform_window_.PrepareForOverview(); -} - -void WindowSelectorWindow::SetItemBounds(aura::Window* root_window, - const gfx::Rect& target_bounds, - bool animate) { - gfx::Rect src_rect = transform_window_.GetBoundsInScreen(); - set_bounds(ScopedTransformOverviewWindow:: - ShrinkRectToFitPreservingAspectRatio(src_rect, target_bounds)); - transform_window_.SetTransform(root_window, - ScopedTransformOverviewWindow::GetTransformForRect(src_rect, bounds()), - animate); -} - -} // namespace ash diff --git a/chromium/ash/wm/overview/window_selector_window.h b/chromium/ash/wm/overview/window_selector_window.h deleted file mode 100644 index 5662f2907ce..00000000000 --- a/chromium/ash/wm/overview/window_selector_window.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2013 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_OVERVIEW_WINDOW_SELECTOR_WINDOW_H_ -#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_WINDOW_H_ - -#include "ash/wm/overview/scoped_transform_overview_window.h" -#include "ash/wm/overview/window_selector_item.h" -#include "base/compiler_specific.h" -#include "ui/gfx/rect.h" - -namespace aura { -class Window; -} - -namespace ash { - -// This implements a window overview item with a single window which can be -// selected. -class WindowSelectorWindow : public WindowSelectorItem { - public: - WindowSelectorWindow(aura::Window* window); - virtual ~WindowSelectorWindow(); - - // WindowSelectorItem: - virtual aura::Window* GetRootWindow() OVERRIDE; - virtual bool HasSelectableWindow(const aura::Window* window) OVERRIDE; - virtual aura::Window* TargetedWindow(const aura::Window* target) OVERRIDE; - virtual void RestoreWindowOnExit(aura::Window* window) OVERRIDE; - virtual aura::Window* SelectionWindow() OVERRIDE; - virtual void RemoveWindow(const aura::Window* window) OVERRIDE; - virtual bool empty() const OVERRIDE; - virtual void PrepareForOverview() OVERRIDE; - virtual void SetItemBounds(aura::Window* root_window, - const gfx::Rect& target_bounds, - bool animate) OVERRIDE; - - private: - ScopedTransformOverviewWindow transform_window_; - - DISALLOW_COPY_AND_ASSIGN(WindowSelectorWindow); -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_WINDOW_H_ diff --git a/chromium/ash/wm/panels/OWNERS b/chromium/ash/wm/panels/OWNERS deleted file mode 100644 index c9dc2b8e06b..00000000000 --- a/chromium/ash/wm/panels/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -flackr@chromium.org -stevenjb@chromium.org diff --git a/chromium/ash/wm/panels/panel_frame_view.cc b/chromium/ash/wm/panels/panel_frame_view.cc deleted file mode 100644 index 3c01e520f9d..00000000000 --- a/chromium/ash/wm/panels/panel_frame_view.cc +++ /dev/null @@ -1,148 +0,0 @@ -// 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/panels/panel_frame_view.h" - -#include "ash/wm/caption_buttons/frame_caption_button_container_view.h" -#include "ash/wm/frame_border_hit_test_controller.h" -#include "ash/wm/header_painter.h" -#include "grit/ash_resources.h" -#include "ui/base/hit_test.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font.h" -#include "ui/views/controls/image_view.h" -#include "ui/views/widget/native_widget_aura.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { - -// static -const char PanelFrameView::kViewClassName[] = "PanelFrameView"; - -PanelFrameView::PanelFrameView(views::Widget* frame, FrameType frame_type) - : frame_(frame), - caption_button_container_(NULL), - window_icon_(NULL), - title_font_(gfx::Font(views::NativeWidgetAura::GetWindowTitleFont())), - frame_border_hit_test_controller_( - new FrameBorderHitTestController(frame_)) { - DCHECK(!frame_->widget_delegate()->CanMaximize()); - if (frame_type != FRAME_NONE) - InitHeaderPainter(); -} - -PanelFrameView::~PanelFrameView() { -} - -const char* PanelFrameView::GetClassName() const { - return kViewClassName; -} - -void PanelFrameView::InitHeaderPainter() { - header_painter_.reset(new HeaderPainter); - - caption_button_container_ = new FrameCaptionButtonContainerView(frame_, - FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); - AddChildView(caption_button_container_); - - if (frame_->widget_delegate()->ShouldShowWindowIcon()) { - window_icon_ = new views::ImageView(); - AddChildView(window_icon_); - } - - header_painter_->Init(frame_, this, window_icon_, caption_button_container_); -} - -int PanelFrameView::NonClientTopBorderHeight() const { - if (!header_painter_) - return 0; - // Reserve enough space to see the buttons and the separator line. - return caption_button_container_->bounds().bottom() + - header_painter_->HeaderContentSeparatorSize(); -} - -gfx::Size PanelFrameView::GetMinimumSize() { - if (!header_painter_) - return gfx::Size(); - gfx::Size min_client_view_size(frame_->client_view()->GetMinimumSize()); - return gfx::Size( - std::max(header_painter_->GetMinimumHeaderWidth(), - min_client_view_size.width()), - NonClientTopBorderHeight() + min_client_view_size.height()); -} - -void PanelFrameView::Layout() { - if (!header_painter_) - return; - header_painter_->LayoutHeader(true); - header_painter_->set_header_height(NonClientTopBorderHeight()); -} - -void PanelFrameView::GetWindowMask(const gfx::Size&, gfx::Path*) { - // Nothing. -} - -void PanelFrameView::ResetWindowControls() { - NOTIMPLEMENTED(); -} - -void PanelFrameView::UpdateWindowIcon() { - if (!window_icon_) - return; - views::WidgetDelegate* delegate = frame_->widget_delegate(); - if (delegate) - window_icon_->SetImage(delegate->GetWindowIcon()); - window_icon_->SchedulePaint(); -} - -void PanelFrameView::UpdateWindowTitle() { - if (!header_painter_) - return; - header_painter_->SchedulePaintForTitle(title_font_); -} - -int PanelFrameView::NonClientHitTest(const gfx::Point& point) { - if (!header_painter_) - return HTNOWHERE; - return FrameBorderHitTestController::NonClientHitTest(this, - header_painter_.get(), point); -} - -void PanelFrameView::OnPaint(gfx::Canvas* canvas) { - if (!header_painter_) - return; - bool paint_as_active = ShouldPaintAsActive(); - int theme_frame_id = 0; - if (paint_as_active) - theme_frame_id = IDR_AURA_WINDOW_HEADER_BASE_ACTIVE; - else - theme_frame_id = IDR_AURA_WINDOW_HEADER_BASE_INACTIVE; - - header_painter_->PaintHeader( - canvas, - paint_as_active ? HeaderPainter::ACTIVE : HeaderPainter::INACTIVE, - theme_frame_id, - 0); - header_painter_->PaintTitleBar(canvas, title_font_); - header_painter_->PaintHeaderContentSeparator(canvas); -} - -gfx::Rect PanelFrameView::GetBoundsForClientView() const { - if (!header_painter_) - return bounds(); - return HeaderPainter::GetBoundsForClientView( - NonClientTopBorderHeight(), bounds()); -} - -gfx::Rect PanelFrameView::GetWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const { - if (!header_painter_) - return client_bounds; - return HeaderPainter::GetWindowBoundsForClientBounds( - NonClientTopBorderHeight(), client_bounds); -} - -} // namespace ash diff --git a/chromium/ash/wm/panels/panel_frame_view.h b/chromium/ash/wm/panels/panel_frame_view.h deleted file mode 100644 index 6bb27f5b47d..00000000000 --- a/chromium/ash/wm/panels/panel_frame_view.h +++ /dev/null @@ -1,80 +0,0 @@ -// 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_PANELS_PANEL_FRAME_VIEW_H_ -#define ASH_WM_PANELS_PANEL_FRAME_VIEW_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "ui/gfx/font.h" -#include "ui/views/window/non_client_view.h" - -namespace views { -class ImageView; -} - -namespace ash { - -class FrameCaptionButtonContainerView; -class FrameBorderHitTestController; -class HeaderPainter; - -class ASH_EXPORT PanelFrameView : public views::NonClientFrameView { - public: - // Internal class name. - static const char kViewClassName[]; - - enum FrameType { - FRAME_NONE, - FRAME_ASH - }; - - PanelFrameView(views::Widget* frame, FrameType frame_type); - virtual ~PanelFrameView(); - - // Overridden from views::View: - virtual const char* GetClassName() const OVERRIDE; - - private: - void InitHeaderPainter(); - - // Height from top of window to top of client area. - int NonClientTopBorderHeight() const; - - // Overridden from views::NonClientFrameView: - virtual gfx::Rect GetBoundsForClientView() const OVERRIDE; - virtual gfx::Rect GetWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const OVERRIDE; - virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE; - virtual void GetWindowMask(const gfx::Size& size, - gfx::Path* window_mask) OVERRIDE; - virtual void ResetWindowControls() OVERRIDE; - virtual void UpdateWindowIcon() OVERRIDE; - virtual void UpdateWindowTitle() OVERRIDE; - - // Overridden from views::View: - virtual gfx::Size GetMinimumSize() OVERRIDE; - virtual void Layout() OVERRIDE; - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; - - // Child View class describing the panel's title bar behavior - // and buttons, owned by the view hierarchy - views::Widget* frame_; - FrameCaptionButtonContainerView* caption_button_container_; - views::ImageView* window_icon_; - gfx::Rect client_view_bounds_; - const gfx::Font title_font_; - - // Helper class for painting the header. - scoped_ptr<HeaderPainter> header_painter_; - - // Updates the hittest bounds overrides based on the window show type. - scoped_ptr<FrameBorderHitTestController> frame_border_hit_test_controller_; - - DISALLOW_COPY_AND_ASSIGN(PanelFrameView); -}; - -} - -#endif // ASH_WM_PANELS_PANEL_FRAME_VIEW_H_ diff --git a/chromium/ash/wm/panels/panel_layout_manager.cc b/chromium/ash/wm/panels/panel_layout_manager.cc deleted file mode 100644 index ec7027b6129..00000000000 --- a/chromium/ash/wm/panels/panel_layout_manager.cc +++ /dev/null @@ -1,895 +0,0 @@ -// 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/panels/panel_layout_manager.h" - -#include <algorithm> -#include <map> - -#include "ash/launcher/launcher.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_types.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/auto_reset.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "third_party/skia/include/core/SkColor.h" -#include "third_party/skia/include/core/SkPaint.h" -#include "third_party/skia/include/core/SkPath.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/client/window_tree_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_tracker.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/vector2d.h" -#include "ui/views/background.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -namespace { -const int kPanelIdealSpacing = 4; - -const float kMaxHeightFactor = .80f; -const float kMaxWidthFactor = .50f; - -// Duration for panel animations. -const int kPanelSlideDurationMilliseconds = 50; -const int kCalloutFadeDurationMilliseconds = 50; - -// Offset used when sliding panel in/out of the launcher. Used for minimizing, -// restoring and the initial showing of a panel. -const int kPanelSlideInOffset = 20; - -// Callout arrow dimensions. -const int kArrowWidth = 18; -const int kArrowHeight = 9; - -class CalloutWidgetBackground : public views::Background { - public: - CalloutWidgetBackground() : alignment_(SHELF_ALIGNMENT_BOTTOM) { - } - - virtual void Paint(gfx::Canvas* canvas, views::View* view) const OVERRIDE { - SkPath path; - switch (alignment_) { - case SHELF_ALIGNMENT_BOTTOM: - path.moveTo(SkIntToScalar(0), SkIntToScalar(0)); - path.lineTo(SkIntToScalar(kArrowWidth / 2), - SkIntToScalar(kArrowHeight)); - path.lineTo(SkIntToScalar(kArrowWidth), SkIntToScalar(0)); - break; - case SHELF_ALIGNMENT_LEFT: - path.moveTo(SkIntToScalar(kArrowHeight), SkIntToScalar(kArrowWidth)); - path.lineTo(SkIntToScalar(0), SkIntToScalar(kArrowWidth / 2)); - path.lineTo(SkIntToScalar(kArrowHeight), SkIntToScalar(0)); - break; - case SHELF_ALIGNMENT_TOP: - path.moveTo(SkIntToScalar(0), SkIntToScalar(kArrowHeight)); - path.lineTo(SkIntToScalar(kArrowWidth / 2), SkIntToScalar(0)); - path.lineTo(SkIntToScalar(kArrowWidth), SkIntToScalar(kArrowHeight)); - break; - case SHELF_ALIGNMENT_RIGHT: - path.moveTo(SkIntToScalar(0), SkIntToScalar(0)); - path.lineTo(SkIntToScalar(kArrowHeight), - SkIntToScalar(kArrowWidth / 2)); - path.lineTo(SkIntToScalar(0), SkIntToScalar(kArrowWidth)); - break; - } - // Hard code the arrow color for now. - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(SkColorSetARGB(0xff, 0xe5, 0xe5, 0xe5)); - canvas->DrawPath(path, paint); - } - - ShelfAlignment alignment() { - return alignment_; - } - - void set_alignment(ShelfAlignment alignment) { - alignment_ = alignment; - } - - private: - ShelfAlignment alignment_; - - DISALLOW_COPY_AND_ASSIGN(CalloutWidgetBackground); -}; - -struct VisiblePanelPositionInfo { - VisiblePanelPositionInfo() - : min_major(0), - max_major(0), - major_pos(0), - major_length(0), - window(NULL), - slide_in(false) {} - - int min_major; - int max_major; - int major_pos; - int major_length; - aura::Window* window; - bool slide_in; -}; - -bool CompareWindowMajor(const VisiblePanelPositionInfo& win1, - const VisiblePanelPositionInfo& win2) { - return win1.major_pos < win2.major_pos; -} - -void FanOutPanels(std::vector<VisiblePanelPositionInfo>::iterator first, - std::vector<VisiblePanelPositionInfo>::iterator last) { - int num_panels = last - first; - if (num_panels == 1) { - (*first).major_pos = std::max((*first).min_major, std::min( - (*first).max_major, (*first).major_pos)); - } - if (num_panels <= 1) - return; - - if (num_panels == 2) { - // If there are two adjacent overlapping windows, separate them by the - // minimum major_length necessary. - std::vector<VisiblePanelPositionInfo>::iterator second = first + 1; - int separation = (*first).major_length / 2 + (*second).major_length / 2 + - kPanelIdealSpacing; - int overlap = (*first).major_pos + separation - (*second).major_pos; - (*first).major_pos = std::max((*first).min_major, - (*first).major_pos - overlap / 2); - (*second).major_pos = std::min((*second).max_major, - (*first).major_pos + separation); - // Recalculate the first panel position in case the second one was - // constrained on the right. - (*first).major_pos = std::max((*first).min_major, - (*second).major_pos - separation); - return; - } - - // If there are more than two overlapping windows, fan them out from minimum - // position to maximum position equally spaced. - int delta = ((*(last - 1)).max_major - (*first).min_major) / (num_panels - 1); - int major_pos = (*first).min_major; - for (std::vector<VisiblePanelPositionInfo>::iterator iter = first; - iter != last; ++iter) { - (*iter).major_pos = std::max((*iter).min_major, - std::min((*iter).max_major, major_pos)); - major_pos += delta; - } -} - -bool BoundsAdjacent(const gfx::Rect& bounds1, const gfx::Rect& bounds2) { - return bounds1.x() == bounds2.right() || - bounds1.y() == bounds2.bottom() || - bounds1.right() == bounds2.x() || - bounds1.bottom() == bounds2.y(); -} - -gfx::Vector2d GetSlideInAnimationOffset(ShelfAlignment alignment) { - gfx::Vector2d offset; - switch (alignment) { - case SHELF_ALIGNMENT_BOTTOM: - offset.set_y(kPanelSlideInOffset); - break; - case SHELF_ALIGNMENT_LEFT: - offset.set_x(-kPanelSlideInOffset); - break; - case SHELF_ALIGNMENT_RIGHT: - offset.set_x(kPanelSlideInOffset); - break; - case SHELF_ALIGNMENT_TOP: - offset.set_y(-kPanelSlideInOffset); - break; - } - return offset; -} - -} // namespace - -class PanelCalloutWidget : public views::Widget { - public: - explicit PanelCalloutWidget(aura::Window* container) - : background_(NULL) { - InitWidget(container); - } - - void SetAlignment(ShelfAlignment alignment) { - gfx::Rect callout_bounds = GetWindowBoundsInScreen(); - if (alignment == SHELF_ALIGNMENT_BOTTOM || - alignment == SHELF_ALIGNMENT_TOP) { - callout_bounds.set_width(kArrowWidth); - callout_bounds.set_height(kArrowHeight); - } else { - callout_bounds.set_width(kArrowHeight); - callout_bounds.set_height(kArrowWidth); - } - GetNativeWindow()->SetBounds(callout_bounds); - if (background_->alignment() != alignment) { - background_->set_alignment(alignment); - SchedulePaintInRect(gfx::Rect(gfx::Point(), callout_bounds.size())); - } - } - - private: - void InitWidget(aura::Window* parent) { - views::Widget::InitParams params; - params.type = views::Widget::InitParams::TYPE_POPUP; - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.can_activate = false; - params.keep_on_top = true; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = parent; - params.bounds = ScreenAsh::ConvertRectToScreen(parent, gfx::Rect()); - params.bounds.set_width(kArrowWidth); - params.bounds.set_height(kArrowHeight); - // Why do we need this and can_activate = false? - set_focus_on_creation(false); - Init(params); - DCHECK_EQ(GetNativeView()->GetRootWindow(), parent->GetRootWindow()); - views::View* content_view = new views::View; - background_ = new CalloutWidgetBackground; - content_view->set_background(background_); - SetContentsView(content_view); - GetNativeWindow()->layer()->SetOpacity(0); - } - - // Weak pointer owned by this widget's content view. - CalloutWidgetBackground* background_; - - DISALLOW_COPY_AND_ASSIGN(PanelCalloutWidget); -}; - -//////////////////////////////////////////////////////////////////////////////// -// PanelLayoutManager public implementation: -PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container) - : panel_container_(panel_container), - in_add_window_(false), - in_layout_(false), - dragged_panel_(NULL), - launcher_(NULL), - shelf_layout_manager_(NULL), - last_active_panel_(NULL), - weak_factory_(this) { - DCHECK(panel_container); - aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())-> - AddObserver(this); - Shell::GetInstance()->display_controller()->AddObserver(this); - Shell::GetInstance()->AddShellObserver(this); -} - -PanelLayoutManager::~PanelLayoutManager() { - Shutdown(); -} - -void PanelLayoutManager::Shutdown() { - if (shelf_layout_manager_) - shelf_layout_manager_->RemoveObserver(this); - shelf_layout_manager_ = NULL; - for (PanelList::iterator iter = panel_windows_.begin(); - iter != panel_windows_.end(); ++iter) { - delete iter->callout_widget; - } - panel_windows_.clear(); - if (launcher_) - launcher_->RemoveIconObserver(this); - launcher_ = NULL; - aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())-> - RemoveObserver(this); - Shell::GetInstance()->display_controller()->RemoveObserver(this); - Shell::GetInstance()->RemoveShellObserver(this); -} - -void PanelLayoutManager::StartDragging(aura::Window* panel) { - DCHECK(!dragged_panel_); - dragged_panel_ = panel; - Relayout(); -} - -void PanelLayoutManager::FinishDragging() { - dragged_panel_ = NULL; - Relayout(); -} - -void PanelLayoutManager::SetLauncher(ash::Launcher* launcher) { - DCHECK(!launcher_); - DCHECK(!shelf_layout_manager_); - launcher_ = launcher; - launcher_->AddIconObserver(this); - 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); - } -} - -void PanelLayoutManager::ToggleMinimize(aura::Window* panel) { - DCHECK(panel->parent() == panel_container_); - wm::WindowState* window_state = wm::GetWindowState(panel); - if (window_state->IsMinimized()) - window_state->Restore(); - else - window_state->Minimize(); -} - -views::Widget* PanelLayoutManager::GetCalloutWidgetForPanel( - aura::Window* panel) { - DCHECK(panel->parent() == panel_container_); - PanelList::iterator found = - std::find(panel_windows_.begin(), panel_windows_.end(), panel); - DCHECK(found != panel_windows_.end()); - return found->callout_widget; -} - -//////////////////////////////////////////////////////////////////////////////// -// PanelLayoutManager, aura::LayoutManager implementation: -void PanelLayoutManager::OnWindowResized() { - Relayout(); -} - -void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) { - if (child->type() == aura::client::WINDOW_TYPE_POPUP) - return; - if (in_add_window_) - return; - base::AutoReset<bool> auto_reset_in_add_window(&in_add_window_, true); - if (!wm::GetWindowState(child)->panel_attached()) { - // This should only happen when a window is added to panel container as a - // result of bounds change from within the application during a drag. - // If so we have already stopped the drag and should reparent the panel - // back to appropriate container and ignore it. - // TODO(varkha): Updating bounds during a drag can cause problems and a more - // general solution is needed. See http://crbug.com/251813 . - aura::Window* old_parent = child->parent(); - aura::client::ParentWindowWithContext( - child, child, child->GetRootWindow()->GetBoundsInScreen()); - wm::ReparentTransientChildrenOfChild(child, old_parent, child->parent()); - DCHECK(child->parent()->id() != kShellWindowId_PanelContainer); - return; - } - PanelInfo panel_info; - panel_info.window = child; - panel_info.callout_widget = new PanelCalloutWidget(panel_container_); - if (child != dragged_panel_) { - // Set the panel to 0 opacity until it has been positioned to prevent it - // from flashing briefly at position (0, 0). - child->layer()->SetOpacity(0); - panel_info.slide_in = true; - } - panel_windows_.push_back(panel_info); - child->AddObserver(this); - wm::GetWindowState(child)->AddObserver(this); - Relayout(); -} - -void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { -} - -void PanelLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { - if (child->type() == aura::client::WINDOW_TYPE_POPUP) - return; - PanelList::iterator found = - std::find(panel_windows_.begin(), panel_windows_.end(), child); - if (found != panel_windows_.end()) { - delete found->callout_widget; - panel_windows_.erase(found); - } - child->RemoveObserver(this); - wm::GetWindowState(child)->RemoveObserver(this); - - if (dragged_panel_ == child) - dragged_panel_ = NULL; - - if (last_active_panel_ == child) - last_active_panel_ = NULL; - - Relayout(); -} - -void PanelLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) { - Relayout(); -} - -void PanelLayoutManager::SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) { - gfx::Rect bounds(requested_bounds); - const gfx::Rect& max_bounds = panel_container_->GetRootWindow()->bounds(); - const int max_width = max_bounds.width() * kMaxWidthFactor; - const int max_height = max_bounds.height() * kMaxHeightFactor; - if (bounds.width() > max_width) - bounds.set_width(max_width); - if (bounds.height() > max_height) - bounds.set_height(max_height); - - // Reposition dragged panel in the panel order. - if (dragged_panel_ == child) { - PanelList::iterator dragged_panel_iter = - std::find(panel_windows_.begin(), panel_windows_.end(), dragged_panel_); - DCHECK(dragged_panel_iter != panel_windows_.end()); - PanelList::iterator new_position; - for (new_position = panel_windows_.begin(); - new_position != panel_windows_.end(); - ++new_position) { - const gfx::Rect& bounds = (*new_position).window->bounds(); - if (bounds.x() + bounds.width()/2 <= requested_bounds.x()) break; - } - if (new_position != dragged_panel_iter) { - PanelInfo dragged_panel_info = *dragged_panel_iter; - panel_windows_.erase(dragged_panel_iter); - panel_windows_.insert(new_position, dragged_panel_info); - } - } - - SetChildBoundsDirect(child, bounds); - Relayout(); -} - -//////////////////////////////////////////////////////////////////////////////// -// PanelLayoutManager, ShelfIconObserver implementation: - -void PanelLayoutManager::OnShelfIconPositionsChanged() { - // TODO: As this is called for every animation step now. Relayout needs to be - // updated to use current icon position instead of use the ideal bounds so - // that the panels slide with their icons instead of jumping. - Relayout(); -} - -//////////////////////////////////////////////////////////////////////////////// -// PanelLayoutManager, ash::ShellObserver implementation: - -void PanelLayoutManager::OnShelfAlignmentChanged(aura::Window* root_window) { - if (panel_container_->GetRootWindow() == root_window) - Relayout(); -} - -///////////////////////////////////////////////////////////////////////////// -// PanelLayoutManager, WindowObserver implementation: - -void PanelLayoutManager::OnWindowShowTypeChanged( - wm::WindowState* window_state, - wm::WindowShowType old_type) { - // If the shelf is currently hidden then windows will not actually be shown - // but the set to restore when the shelf becomes visible is updated. - if (restore_windows_on_shelf_visible_) { - if (window_state->IsMinimized()) { - MinimizePanel(window_state->window()); - restore_windows_on_shelf_visible_->Remove(window_state->window()); - } else { - restore_windows_on_shelf_visible_->Add(window_state->window()); - } - return; - } - - if (window_state->IsMinimized()) - MinimizePanel(window_state->window()); - else - RestorePanel(window_state->window()); -} - -void PanelLayoutManager::OnWindowVisibilityChanged( - aura::Window* window, bool visible) { - if (visible) - wm::GetWindowState(window)->Restore(); -} - -//////////////////////////////////////////////////////////////////////////////// -// PanelLayoutManager, aura::client::ActivationChangeObserver implementation: - -void PanelLayoutManager::OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) { - // Ignore if the panel that is not managed by this was activated. - if (gained_active && - gained_active->type() == aura::client::WINDOW_TYPE_PANEL && - gained_active->parent() == panel_container_) { - UpdateStacking(gained_active); - UpdateCallouts(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// PanelLayoutManager, DisplayController::Observer implementation: - -void PanelLayoutManager::OnDisplayConfigurationChanged() { - Relayout(); -} - -//////////////////////////////////////////////////////////////////////////////// -// PanelLayoutManager, ShelfLayoutManagerObserver implementation: - -void PanelLayoutManager::WillChangeVisibilityState( - ShelfVisibilityState new_state) { - // On entering / leaving full screen mode the shelf visibility state is - // changed to / from SHELF_HIDDEN. In this state, panel windows should hide - // to allow the full-screen application to use the full screen. - bool shelf_hidden = new_state == ash::SHELF_HIDDEN; - if (!shelf_hidden) { - if (restore_windows_on_shelf_visible_) { - scoped_ptr<aura::WindowTracker> restore_windows( - restore_windows_on_shelf_visible_.Pass()); - for (aura::WindowTracker::Windows::const_iterator iter = - restore_windows->windows().begin(); iter != - restore_windows->windows().end(); ++iter) { - RestorePanel(*iter); - } - } - return; - } - - if (restore_windows_on_shelf_visible_) - return; - scoped_ptr<aura::WindowTracker> minimized_windows(new aura::WindowTracker); - for (PanelList::iterator iter = panel_windows_.begin(); - iter != panel_windows_.end(); ++iter) { - if (iter->window->IsVisible()) { - minimized_windows->Add(iter->window); - wm::GetWindowState(iter->window)->Minimize(); - } - } - restore_windows_on_shelf_visible_ = minimized_windows.Pass(); -} - -//////////////////////////////////////////////////////////////////////////////// -// PanelLayoutManager private implementation: - -void PanelLayoutManager::MinimizePanel(aura::Window* panel) { - views::corewm::SetWindowVisibilityAnimationType( - panel, WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); - ui::Layer* layer = panel->layer(); - ui::ScopedLayerAnimationSettings panel_slide_settings(layer->GetAnimator()); - panel_slide_settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - panel_slide_settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kPanelSlideDurationMilliseconds)); - gfx::Rect bounds(panel->bounds()); - bounds.Offset(GetSlideInAnimationOffset( - launcher_->shelf_widget()->GetAlignment())); - SetChildBoundsDirect(panel, bounds); - panel->Hide(); - PanelList::iterator found = - std::find(panel_windows_.begin(), panel_windows_.end(), panel); - if (found != panel_windows_.end()) { - layer->SetOpacity(0); - // The next time the window is visible it should slide into place. - found->slide_in = true; - } - if (wm::IsActiveWindow(panel)) - wm::DeactivateWindow(panel); - Relayout(); -} - -void PanelLayoutManager::RestorePanel(aura::Window* panel) { - panel->Show(); - Relayout(); -} - -void PanelLayoutManager::Relayout() { - if (!launcher_ || !launcher_->shelf_widget()) - return; - - if (in_layout_) - return; - base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true); - - ShelfAlignment alignment = launcher_->shelf_widget()->GetAlignment(); - bool horizontal = alignment == SHELF_ALIGNMENT_TOP || - alignment == SHELF_ALIGNMENT_BOTTOM; - gfx::Rect launcher_bounds = ash::ScreenAsh::ConvertRectFromScreen( - panel_container_, launcher_->shelf_widget()->GetWindowBoundsInScreen()); - int panel_start_bounds = kPanelIdealSpacing; - int panel_end_bounds = horizontal ? - panel_container_->bounds().width() - kPanelIdealSpacing : - panel_container_->bounds().height() - kPanelIdealSpacing; - aura::Window* active_panel = NULL; - std::vector<VisiblePanelPositionInfo> visible_panels; - for (PanelList::iterator iter = panel_windows_.begin(); - iter != panel_windows_.end(); ++iter) { - aura::Window* panel = iter->window; - iter->callout_widget->SetAlignment(alignment); - - // Consider the dragged panel as part of the layout as long as it is - // touching the launcher. - if (!panel->IsVisible() || - (panel == dragged_panel_ && - !BoundsAdjacent(panel->bounds(), launcher_bounds))) { - continue; - } - - // If the shelf is currently hidden (full-screen mode), minimize panel until - // full-screen mode is exited. - if (restore_windows_on_shelf_visible_) { - wm::GetWindowState(panel)->Minimize(); - restore_windows_on_shelf_visible_->Add(panel); - continue; - } - - gfx::Rect icon_bounds = - launcher_->GetScreenBoundsOfItemIconForWindow(panel); - - // If both the icon width and height are 0 then there is no icon in the - // launcher. If the launcher is hidden, one of the height or width will be - // 0 but the position in the launcher and major dimension is still reported - // correctly and the panel can be aligned above where the hidden icon is. - if (icon_bounds.width() == 0 && icon_bounds.height() == 0) - continue; - - if (panel->HasFocus() || - panel->Contains( - aura::client::GetFocusClient(panel)->GetFocusedWindow())) { - DCHECK(!active_panel); - active_panel = panel; - } - icon_bounds = ScreenAsh::ConvertRectFromScreen(panel_container_, - icon_bounds); - gfx::Point icon_origin = icon_bounds.origin(); - VisiblePanelPositionInfo position_info; - int icon_start = horizontal ? icon_origin.x() : icon_origin.y(); - int icon_end = icon_start + (horizontal ? icon_bounds.width() : - icon_bounds.height()); - position_info.major_length = horizontal ? - panel->bounds().width() : panel->bounds().height(); - position_info.min_major = std::max( - panel_start_bounds + position_info.major_length / 2, - icon_end - position_info.major_length / 2); - position_info.max_major = std::min( - icon_start + position_info.major_length / 2, - panel_end_bounds - position_info.major_length / 2); - position_info.major_pos = (icon_start + icon_end) / 2; - position_info.window = panel; - position_info.slide_in = iter->slide_in; - iter->slide_in = false; - visible_panels.push_back(position_info); - } - - // Sort panels by their X positions and fan out groups of overlapping panels. - // The fan out method may result in new overlapping panels however given that - // the panels start at least a full panel width apart this overlap will - // never completely obscure a panel. - // TODO(flackr): Rearrange panels if new overlaps are introduced. - std::sort(visible_panels.begin(), visible_panels.end(), CompareWindowMajor); - size_t first_overlapping_panel = 0; - for (size_t i = 1; i < visible_panels.size(); ++i) { - if (visible_panels[i - 1].major_pos + - visible_panels[i - 1].major_length / 2 < visible_panels[i].major_pos - - visible_panels[i].major_length / 2) { - FanOutPanels(visible_panels.begin() + first_overlapping_panel, - visible_panels.begin() + i); - first_overlapping_panel = i; - } - } - FanOutPanels(visible_panels.begin() + first_overlapping_panel, - visible_panels.end()); - - for (size_t i = 0; i < visible_panels.size(); ++i) { - if (visible_panels[i].window == dragged_panel_) - continue; - bool slide_in = visible_panels[i].slide_in; - gfx::Rect bounds = visible_panels[i].window->GetTargetBounds(); - switch (alignment) { - case SHELF_ALIGNMENT_BOTTOM: - bounds.set_y(launcher_bounds.y() - bounds.height()); - break; - case SHELF_ALIGNMENT_LEFT: - bounds.set_x(launcher_bounds.right()); - break; - case SHELF_ALIGNMENT_RIGHT: - bounds.set_x(launcher_bounds.x() - bounds.width()); - break; - case SHELF_ALIGNMENT_TOP: - bounds.set_y(launcher_bounds.bottom()); - break; - } - bool on_launcher = visible_panels[i].window->GetTargetBounds() == bounds; - - if (horizontal) { - bounds.set_x(visible_panels[i].major_pos - - visible_panels[i].major_length / 2); - } else { - bounds.set_y(visible_panels[i].major_pos - - visible_panels[i].major_length / 2); - } - - ui::Layer* layer = visible_panels[i].window->layer(); - if (slide_in) { - // New windows shift up from the launcher into position. - gfx::Rect initial_bounds(bounds); - initial_bounds.Offset(GetSlideInAnimationOffset(alignment)); - SetChildBoundsDirect(visible_panels[i].window, initial_bounds); - // Set on launcher so that the panel animates into its target position. - on_launcher = true; - } - - if (on_launcher) { - ui::ScopedLayerAnimationSettings panel_slide_settings( - layer->GetAnimator()); - panel_slide_settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - panel_slide_settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kPanelSlideDurationMilliseconds)); - SetChildBoundsDirect(visible_panels[i].window, bounds); - if (slide_in) - layer->SetOpacity(1); - } else { - // If the launcher moved don't animate, move immediately to the new - // target location. - SetChildBoundsDirect(visible_panels[i].window, bounds); - } - } - - UpdateStacking(active_panel); - UpdateCallouts(); -} - -void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) { - if (!active_panel) { - if (!last_active_panel_) - return; - active_panel = last_active_panel_; - } - - ShelfAlignment alignment = launcher_->alignment(); - bool horizontal = alignment == SHELF_ALIGNMENT_TOP || - alignment == SHELF_ALIGNMENT_BOTTOM; - - // We want to to stack the panels like a deck of cards: - // ,--,--,--,-------.--.--. - // | | | | | | | - // | | | | | | | - // - // We use the middle of each panel to figure out how to stack the panels. This - // allows us to update the stacking when a panel is being dragged around by - // the titlebar--even though it doesn't update the launcher icon positions, we - // still want the visual effect. - std::map<int, aura::Window*> window_ordering; - for (PanelList::const_iterator it = panel_windows_.begin(); - it != panel_windows_.end(); ++it) { - gfx::Rect bounds = it->window->bounds(); - window_ordering.insert(std::make_pair(horizontal ? - bounds.x() + bounds.width() / 2 : - bounds.y() + bounds.height() / 2, - it->window)); - } - - aura::Window* previous_panel = NULL; - for (std::map<int, aura::Window*>::const_iterator it = - window_ordering.begin(); - it != window_ordering.end() && it->second != active_panel; ++it) { - if (previous_panel) - panel_container_->StackChildAbove(it->second, previous_panel); - previous_panel = it->second; - } - - previous_panel = NULL; - for (std::map<int, aura::Window*>::const_reverse_iterator it = - window_ordering.rbegin(); - it != window_ordering.rend() && it->second != active_panel; ++it) { - if (previous_panel) - panel_container_->StackChildAbove(it->second, previous_panel); - previous_panel = it->second; - } - - panel_container_->StackChildAtTop(active_panel); - if (dragged_panel_ && dragged_panel_->parent() == panel_container_) - panel_container_->StackChildAtTop(dragged_panel_); - last_active_panel_ = active_panel; -} - -void PanelLayoutManager::UpdateCallouts() { - ShelfAlignment alignment = launcher_->alignment(); - bool horizontal = alignment == SHELF_ALIGNMENT_TOP || - alignment == SHELF_ALIGNMENT_BOTTOM; - - for (PanelList::iterator iter = panel_windows_.begin(); - iter != panel_windows_.end(); ++iter) { - aura::Window* panel = iter->window; - views::Widget* callout_widget = iter->callout_widget; - - gfx::Rect current_bounds = panel->GetBoundsInScreen(); - gfx::Rect bounds = ScreenAsh::ConvertRectToScreen(panel->parent(), - panel->GetTargetBounds()); - gfx::Rect icon_bounds = - launcher_->GetScreenBoundsOfItemIconForWindow(panel); - if (icon_bounds.IsEmpty() || !panel->layer()->GetTargetVisibility() || - panel == dragged_panel_) { - callout_widget->Hide(); - callout_widget->GetNativeWindow()->layer()->SetOpacity(0); - continue; - } - - gfx::Rect callout_bounds = callout_widget->GetWindowBoundsInScreen(); - gfx::Vector2d slide_vector = bounds.origin() - current_bounds.origin(); - int slide_distance = horizontal ? slide_vector.x() : slide_vector.y(); - int distance_until_over_panel = 0; - if (horizontal) { - callout_bounds.set_x( - icon_bounds.x() + (icon_bounds.width() - callout_bounds.width()) / 2); - distance_until_over_panel = std::max( - current_bounds.x() - callout_bounds.x(), - callout_bounds.right() - current_bounds.right()); - } else { - callout_bounds.set_y( - icon_bounds.y() + (icon_bounds.height() - - callout_bounds.height()) / 2); - distance_until_over_panel = std::max( - current_bounds.y() - callout_bounds.y(), - callout_bounds.bottom() - current_bounds.bottom()); - } - switch (alignment) { - case SHELF_ALIGNMENT_BOTTOM: - callout_bounds.set_y(bounds.bottom()); - break; - case SHELF_ALIGNMENT_LEFT: - callout_bounds.set_x(bounds.x() - callout_bounds.width()); - break; - case SHELF_ALIGNMENT_RIGHT: - callout_bounds.set_x(bounds.right()); - break; - case SHELF_ALIGNMENT_TOP: - callout_bounds.set_y(bounds.y() - callout_bounds.height()); - break; - } - callout_bounds = ScreenAsh::ConvertRectFromScreen( - callout_widget->GetNativeWindow()->parent(), - callout_bounds); - - SetChildBoundsDirect(callout_widget->GetNativeWindow(), callout_bounds); - panel_container_->StackChildAbove(callout_widget->GetNativeWindow(), - panel); - callout_widget->Show(); - - ui::Layer* layer = callout_widget->GetNativeWindow()->layer(); - // If the panel is not over the callout position or has just become visible - // then fade in the callout. - if ((distance_until_over_panel > 0 || layer->GetTargetOpacity() < 1) && - panel->layer()->GetTargetTransform().IsIdentity()) { - if (distance_until_over_panel > 0 && - slide_distance >= distance_until_over_panel) { - layer->SetOpacity(0); - // If the panel is not yet over the callout, then delay fading in - // the callout until after the panel should be over it. - int delay = kPanelSlideDurationMilliseconds * - distance_until_over_panel / slide_distance; - layer->SetOpacity(0); - layer->GetAnimator()->StopAnimating(); - layer->GetAnimator()->SchedulePauseForProperties( - base::TimeDelta::FromMilliseconds(delay), - ui::LayerAnimationElement::OPACITY); - } - { - ui::ScopedLayerAnimationSettings callout_settings(layer->GetAnimator()); - callout_settings.SetPreemptionStrategy( - ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); - callout_settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds( - kCalloutFadeDurationMilliseconds)); - layer->SetOpacity(1); - } - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// keyboard::KeyboardControllerObserver implementation: - -void PanelLayoutManager::OnKeyboardBoundsChanging( - const gfx::Rect& keyboard_bounds) { - // This bounds change will have caused a change to the Shelf which does not - // propogate automatically to this class, so manually recalculate bounds. - OnWindowResized(); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/panels/panel_layout_manager.h b/chromium/ash/wm/panels/panel_layout_manager.h deleted file mode 100644 index 042d285cb1d..00000000000 --- a/chromium/ash/wm/panels/panel_layout_manager.h +++ /dev/null @@ -1,196 +0,0 @@ -// 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_PANELS_PANEL_LAYOUT_MANAGER_H_ -#define ASH_WM_PANELS_PANEL_LAYOUT_MANAGER_H_ - -#include <list> - -#include "ash/ash_export.h" -#include "ash/display/display_controller.h" -#include "ash/shelf/shelf_icon_observer.h" -#include "ash/shelf/shelf_layout_manager_observer.h" -#include "ash/shell_observer.h" -#include "ash/wm/window_state_observer.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "ui/aura/client/activation_change_observer.h" -#include "ui/aura/layout_manager.h" -#include "ui/aura/window_observer.h" -#include "ui/keyboard/keyboard_controller.h" -#include "ui/keyboard/keyboard_controller_observer.h" - -namespace aura { -class Window; -class WindowTracker; -} - -namespace gfx { -class Rect; -} - -namespace views { -class Widget; -} - -namespace ash { -class Launcher; - -namespace internal { -class PanelCalloutWidget; -class ShelfLayoutManager; - -// PanelLayoutManager is responsible for organizing panels within the -// workspace. It is associated with a specific container window (i.e. -// kShellWindowId_PanelContainer) and controls the layout of any windows -// added to that container. -// -// The constructor takes a |panel_container| argument which is expected to set -// its layout manager to this instance, e.g.: -// panel_container->SetLayoutManager(new PanelLayoutManager(panel_container)); - -class ASH_EXPORT PanelLayoutManager - : public aura::LayoutManager, - public ShelfIconObserver, - public ShellObserver, - public aura::WindowObserver, - public aura::client::ActivationChangeObserver, - public keyboard::KeyboardControllerObserver, - public DisplayController::Observer, - public ShelfLayoutManagerObserver, - public wm::WindowStateObserver { - public: - explicit PanelLayoutManager(aura::Window* panel_container); - virtual ~PanelLayoutManager(); - - // Call Shutdown() before deleting children of panel_container. - void Shutdown(); - - void StartDragging(aura::Window* panel); - void FinishDragging(); - - void ToggleMinimize(aura::Window* panel); - - // Returns the callout widget (arrow) for |panel|. - views::Widget* GetCalloutWidgetForPanel(aura::Window* panel); - - ash::Launcher* launcher() { return launcher_; } - void SetLauncher(ash::Launcher* launcher); - - // Overridden from aura::LayoutManager: - virtual void OnWindowResized() OVERRIDE; - virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; - virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; - virtual void OnChildWindowVisibilityChanged(aura::Window* child, - bool visibile) OVERRIDE; - virtual void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) OVERRIDE; - - // Overridden from ShelfIconObserver - virtual void OnShelfIconPositionsChanged() OVERRIDE; - - // Overridden from ShellObserver - virtual void OnShelfAlignmentChanged(aura::Window* root_window) OVERRIDE; - - // Overridden from ash::wm::WindowStateObserver - virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType old_type) OVERRIDE; - - // Overridden from aura::WindowObserver - virtual void OnWindowVisibilityChanged(aura::Window* window, - bool visible) OVERRIDE; - - // Overridden from aura::client::ActivationChangeObserver - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE; - - // Overridden from DisplayController::Observer - virtual void OnDisplayConfigurationChanged() OVERRIDE; - - // Overridden from ShelfLayoutManagerObserver - virtual void WillChangeVisibilityState( - ShelfVisibilityState new_state) OVERRIDE; - - private: - friend class PanelLayoutManagerTest; - friend class PanelWindowResizerTest; - friend class DockedWindowResizerTest; - friend class DockedWindowLayoutManagerTest; - - views::Widget* CreateCalloutWidget(); - - struct PanelInfo{ - PanelInfo() : window(NULL), callout_widget(NULL), slide_in(false) {} - - bool operator==(const aura::Window* other_window) const { - return window == other_window; - } - - // A weak pointer to the panel window. - aura::Window* window; - // The callout widget for this panel. This pointer must be managed - // manually as this structure is used in a std::list. See - // http://www.chromium.org/developers/smart-pointer-guidelines - PanelCalloutWidget* callout_widget; - - // True on new and restored panel windows until the panel has been - // positioned. The first time Relayout is called the panel will slide into - // position and this will be set to false. - bool slide_in; - }; - - typedef std::list<PanelInfo> PanelList; - - void MinimizePanel(aura::Window* panel); - void RestorePanel(aura::Window* panel); - - // Called whenever the panel layout might change. - void Relayout(); - - // Called whenever the panel stacking order needs to be updated (e.g. focus - // changes or a panel is moved). - void UpdateStacking(aura::Window* active_panel); - - // Update the callout arrows for all managed panels. - void UpdateCallouts(); - - // Overridden from keyboard::KeyboardControllerObserver: - virtual void OnKeyboardBoundsChanging( - const gfx::Rect& keyboard_bounds) OVERRIDE; - - // Parent window associated with this layout manager. - aura::Window* panel_container_; - // Protect against recursive calls to OnWindowAddedToLayout(). - bool in_add_window_; - // Protect against recursive calls to Relayout(). - bool in_layout_; - // Ordered list of unowned pointers to panel windows. - PanelList panel_windows_; - // The panel being dragged. - aura::Window* dragged_panel_; - // The launcher we are observing for launcher icon changes. - Launcher* launcher_; - // The shelf layout manager being observed for visibility changes. - ShelfLayoutManager* shelf_layout_manager_; - - // When not NULL, the shelf is hidden (i.e. full screen) and this tracks the - // set of panel windows which have been temporarily hidden and need to be - // restored when the shelf becomes visible again. - scoped_ptr<aura::WindowTracker> restore_windows_on_shelf_visible_; - - // The last active panel. Used to maintain stacking order even if no panels - // are currently focused. - aura::Window* last_active_panel_; - base::WeakPtrFactory<PanelLayoutManager> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(PanelLayoutManager); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_PANELS_PANEL_LAYOUT_MANAGER_H_ diff --git a/chromium/ash/wm/panels/panel_layout_manager_unittest.cc b/chromium/ash/wm/panels/panel_layout_manager_unittest.cc deleted file mode 100644 index 5351afa2b1c..00000000000 --- a/chromium/ash/wm/panels/panel_layout_manager_unittest.cc +++ /dev/null @@ -1,800 +0,0 @@ -// 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/panels/panel_layout_manager.h" - -#include "ash/ash_switches.h" -#include "ash/launcher/launcher.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_button.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_model.h" -#include "ash/shelf/shelf_types.h" -#include "ash/shelf/shelf_util.h" -#include "ash/shelf/shelf_view.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/launcher_test_api.h" -#include "ash/test/shelf_view_test_api.h" -#include "ash/test/shell_test_api.h" -#include "ash/test/test_shelf_delegate.h" -#include "ash/wm/mru_window_tracker.h" -#include "ash/wm/window_util.h" -#include "base/basictypes.h" -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/i18n/rtl.h" -#include "base/run_loop.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/views/corewm/corewm_switches.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -using aura::test::WindowIsAbove; - -class PanelLayoutManagerTest : public test::AshTestBase { - public: - PanelLayoutManagerTest() {} - virtual ~PanelLayoutManagerTest() {} - - virtual void SetUp() OVERRIDE { - test::AshTestBase::SetUp(); - ASSERT_TRUE(test::TestShelfDelegate::instance()); - - shelf_view_test_.reset(new test::ShelfViewTestAPI( - GetShelfView(Launcher::ForPrimaryDisplay()))); - shelf_view_test_->SetAnimationDuration(1); - } - - aura::Window* CreateNormalWindow(const gfx::Rect& bounds) { - return CreateTestWindowInShellWithBounds(bounds); - } - - aura::Window* CreatePanelWindow(const gfx::Rect& bounds) { - aura::Window* window = CreateTestWindowInShellWithDelegateAndType( - NULL, - aura::client::WINDOW_TYPE_PANEL, - 0, - bounds); - test::TestShelfDelegate* shelf_delegate = - test::TestShelfDelegate::instance(); - shelf_delegate->AddLauncherItem(window); - PanelLayoutManager* manager = static_cast<PanelLayoutManager*>( - GetPanelContainer(window)->layout_manager()); - manager->Relayout(); - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - return window; - } - - aura::Window* GetPanelContainer(aura::Window* panel) { - return Shell::GetContainer(panel->GetRootWindow(), - internal::kShellWindowId_PanelContainer); - } - - views::Widget* GetCalloutWidgetForPanel(aura::Window* panel) { - PanelLayoutManager* manager = - static_cast<PanelLayoutManager*>(GetPanelContainer(panel)-> - layout_manager()); - DCHECK(manager); - PanelLayoutManager::PanelList::iterator found = std::find( - manager->panel_windows_.begin(), manager->panel_windows_.end(), - panel); - DCHECK(found != manager->panel_windows_.end()); - DCHECK(found->callout_widget); - return reinterpret_cast<views::Widget*>(found->callout_widget); - } - - void PanelInScreen(aura::Window* panel) { - gfx::Rect panel_bounds = panel->GetBoundsInRootWindow(); - gfx::Point root_point = gfx::Point(panel_bounds.x(), panel_bounds.y()); - gfx::Display display = ScreenAsh::FindDisplayContainingPoint(root_point); - - gfx::Rect panel_bounds_in_screen = panel->GetBoundsInScreen(); - gfx::Point screen_bottom_right = gfx::Point( - panel_bounds_in_screen.right(), - panel_bounds_in_screen.bottom()); - gfx::Rect display_bounds = display.bounds(); - EXPECT_TRUE(screen_bottom_right.x() < display_bounds.width() && - screen_bottom_right.y() < display_bounds.height()); - } - - void PanelsNotOverlapping(aura::Window* panel1, aura::Window* panel2) { - // Waits until all shelf view animations are done. - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - gfx::Rect window1_bounds = panel1->GetBoundsInRootWindow(); - gfx::Rect window2_bounds = panel2->GetBoundsInRootWindow(); - - EXPECT_FALSE(window1_bounds.Intersects(window2_bounds)); - } - - // TODO(dcheng): This should be const, but GetScreenBoundsOfItemIconForWindow - // takes a non-const Window. We can probably fix that. - void IsPanelAboveLauncherIcon(aura::Window* panel) { - // Waits until all shelf view animations are done. - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - - Launcher* launcher = - RootWindowController::ForLauncher(panel)->shelf()->launcher(); - gfx::Rect icon_bounds = launcher->GetScreenBoundsOfItemIconForWindow(panel); - 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()); - - if (IsHorizontal(alignment)) { - // The horizontal bounds of the panel window should contain the bounds of - // the launcher icon. - EXPECT_LE(window_bounds.x(), icon_bounds.x()); - EXPECT_GE(window_bounds.right(), icon_bounds.right()); - } else { - // The vertical bounds of the panel window should contain the bounds of - // the launcher icon. - EXPECT_LE(window_bounds.y(), icon_bounds.y()); - EXPECT_GE(window_bounds.bottom(), icon_bounds.bottom()); - } - - switch (alignment) { - case SHELF_ALIGNMENT_BOTTOM: - EXPECT_EQ(launcher_bounds.y(), window_bounds.bottom()); - break; - case SHELF_ALIGNMENT_LEFT: - EXPECT_EQ(launcher_bounds.right(), window_bounds.x()); - break; - case SHELF_ALIGNMENT_RIGHT: - EXPECT_EQ(launcher_bounds.x(), window_bounds.right()); - break; - case SHELF_ALIGNMENT_TOP: - EXPECT_EQ(launcher_bounds.bottom(), window_bounds.y()); - break; - } - } - - void IsCalloutAboveLauncherIcon(aura::Window* panel) { - // Flush the message loop, since callout updates use a delayed task. - base::RunLoop().RunUntilIdle(); - views::Widget* widget = GetCalloutWidgetForPanel(panel); - - Launcher* launcher = - RootWindowController::ForLauncher(panel)->shelf()->launcher(); - gfx::Rect icon_bounds = launcher->GetScreenBoundsOfItemIconForWindow(panel); - ASSERT_FALSE(icon_bounds.IsEmpty()); - - gfx::Rect panel_bounds = panel->GetBoundsInScreen(); - gfx::Rect callout_bounds = widget->GetWindowBoundsInScreen(); - ASSERT_FALSE(icon_bounds.IsEmpty()); - - EXPECT_TRUE(widget->IsVisible()); - - ShelfAlignment alignment = GetAlignment(panel->GetRootWindow()); - switch (alignment) { - case SHELF_ALIGNMENT_BOTTOM: - EXPECT_EQ(panel_bounds.bottom(), callout_bounds.y()); - break; - case SHELF_ALIGNMENT_LEFT: - EXPECT_EQ(panel_bounds.x(), callout_bounds.right()); - break; - case SHELF_ALIGNMENT_RIGHT: - EXPECT_EQ(panel_bounds.right(), callout_bounds.x()); - break; - case SHELF_ALIGNMENT_TOP: - EXPECT_EQ(panel_bounds.y(), callout_bounds.bottom()); - break; - } - - if (IsHorizontal(alignment)) { - EXPECT_NEAR(icon_bounds.CenterPoint().x(), - widget->GetWindowBoundsInScreen().CenterPoint().x(), - 1); - } else { - EXPECT_NEAR(icon_bounds.CenterPoint().y(), - widget->GetWindowBoundsInScreen().CenterPoint().y(), - 1); - } - } - - bool IsPanelCalloutVisible(aura::Window* panel) { - views::Widget* widget = GetCalloutWidgetForPanel(panel); - return widget->IsVisible(); - } - - test::ShelfViewTestAPI* shelf_view_test() { - return shelf_view_test_.get(); - } - - // Clicks the launcher items on |shelf_view| that is - /// associated with given |window|. - void ClickLauncherItemForWindow(ShelfView* shelf_view, - aura::Window* window) { - test::ShelfViewTestAPI test_api(shelf_view); - test_api.SetAnimationDuration(1); - test_api.RunMessageLoopUntilAnimationsDone(); - ShelfModel* model = test::ShellTestApi(Shell::GetInstance()).shelf_model(); - int index = model->ItemIndexByID(GetLauncherIDForWindow(window)); - gfx::Rect bounds = test_api.GetButton(index)->GetBoundsInScreen(); - - aura::test::EventGenerator& event_generator = GetEventGenerator(); - event_generator.MoveMouseTo(bounds.CenterPoint()); - event_generator.ClickLeftButton(); - - test_api.RunMessageLoopUntilAnimationsDone(); - } - - void SetAlignment(aura::Window* root_window, ShelfAlignment alignment) { - ash::Shell* shell = ash::Shell::GetInstance(); - shell->SetShelfAlignment(alignment, root_window); - } - - ShelfAlignment GetAlignment(aura::Window* root_window) { - ash::Shell* shell = ash::Shell::GetInstance(); - return shell->GetShelfAlignment(root_window); - } - - void SetShelfAutoHideBehavior(aura::Window* window, - ShelfAutoHideBehavior behavior) { - internal::ShelfLayoutManager* shelf = - RootWindowController::ForWindow(window)->shelf()-> - shelf_layout_manager(); - shelf->SetAutoHideBehavior(behavior); - ShelfView* shelf_view = GetShelfView(Launcher::ForWindow(window)); - test::ShelfViewTestAPI test_api(shelf_view); - test_api.RunMessageLoopUntilAnimationsDone(); - } - - void SetShelfVisibilityState(aura::Window* window, - ShelfVisibilityState visibility_state) { - internal::ShelfLayoutManager* shelf = - RootWindowController::ForWindow(window)->shelf()-> - shelf_layout_manager(); - shelf->SetState(visibility_state); - } - - internal::ShelfView* GetShelfView(Launcher* launcher) { - return test::LauncherTestAPI(launcher).shelf_view(); - } - - private: - scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_; - - bool IsHorizontal(ShelfAlignment alignment) { - return alignment == SHELF_ALIGNMENT_BOTTOM || - alignment == SHELF_ALIGNMENT_TOP; - } - - DISALLOW_COPY_AND_ASSIGN(PanelLayoutManagerTest); -}; - -class PanelLayoutManagerTextDirectionTest - : public PanelLayoutManagerTest, - public testing::WithParamInterface<bool> { - public: - PanelLayoutManagerTextDirectionTest() : is_rtl_(GetParam()) {} - virtual ~PanelLayoutManagerTextDirectionTest() {} - - virtual void SetUp() OVERRIDE { - original_locale = l10n_util::GetApplicationLocale(std::string()); - if (is_rtl_) - base::i18n::SetICUDefaultLocale("he"); - PanelLayoutManagerTest::SetUp(); - ASSERT_EQ(is_rtl_, base::i18n::IsRTL()); - } - - virtual void TearDown() OVERRIDE { - if (is_rtl_) - base::i18n::SetICUDefaultLocale(original_locale); - PanelLayoutManagerTest::TearDown(); - } - - private: - bool is_rtl_; - std::string original_locale; - - DISALLOW_COPY_AND_ASSIGN(PanelLayoutManagerTextDirectionTest); -}; - -// Tests that a created panel window is above the launcher icon in LTR and RTL. -TEST_P(PanelLayoutManagerTextDirectionTest, AddOnePanel) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> window(CreatePanelWindow(bounds)); - EXPECT_EQ(GetPanelContainer(window.get()), window->parent()); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(window.get())); - EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(window.get())); -} - -// Tests that a created panel window is successfully aligned over a hidden -// launcher icon. -TEST_F(PanelLayoutManagerTest, PanelAlignsToHiddenLauncherIcon) { - gfx::Rect bounds(0, 0, 201, 201); - SetShelfAutoHideBehavior(Shell::GetPrimaryRootWindow(), - SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - scoped_ptr<aura::Window> normal_window(CreateNormalWindow(bounds)); - scoped_ptr<aura::Window> window(CreatePanelWindow(bounds)); - EXPECT_EQ(GetPanelContainer(window.get()), window->parent()); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(window.get())); -} - -TEST_F(PanelLayoutManagerTest, PanelAlignsToHiddenLauncherIconSecondDisplay) { - if (!SupportsMultipleDisplays()) - return; - - // Keep the displays wide so that launchers have enough - // space for launcher buttons. - UpdateDisplay("400x400,600x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> normal_window( - CreateNormalWindow(gfx::Rect(450, 0, 100, 100))); - scoped_ptr<aura::Window> panel(CreatePanelWindow(gfx::Rect(400, 0, 50, 50))); - EXPECT_EQ(root_windows[1], panel->GetRootWindow()); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(panel.get())); - gfx::Rect shelf_visible_position = panel->GetBoundsInScreen(); - - SetShelfAutoHideBehavior(root_windows[1], - SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - // Expect the panel X position to remain the same after the shelf is hidden - // but the Y to move down. - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(panel.get())); - EXPECT_EQ(shelf_visible_position.x(), panel->GetBoundsInScreen().x()); - EXPECT_GT(panel->GetBoundsInScreen().y(), shelf_visible_position.y()); -} - -// Tests interactions between multiple panels -TEST_F(PanelLayoutManagerTest, MultiplePanelsAreAboveIcons) { - gfx::Rect odd_bounds(0, 0, 201, 201); - gfx::Rect even_bounds(0, 0, 200, 200); - - scoped_ptr<aura::Window> w1(CreatePanelWindow(odd_bounds)); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get())); - - scoped_ptr<aura::Window> w2(CreatePanelWindow(even_bounds)); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get())); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get())); - - scoped_ptr<aura::Window> w3(CreatePanelWindow(odd_bounds)); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get())); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get())); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get())); -} - -TEST_F(PanelLayoutManagerTest, MultiplePanelStacking) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds)); - - // Default stacking order. - EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get())); - - // Changing the active window should update the stacking order. - wm::ActivateWindow(w1.get()); - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - EXPECT_TRUE(WindowIsAbove(w1.get(), w2.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get())); - - wm::ActivateWindow(w2.get()); - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - EXPECT_TRUE(WindowIsAbove(w1.get(), w3.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get())); - - wm::ActivateWindow(w3.get()); - EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get())); -} - -TEST_F(PanelLayoutManagerTest, MultiplePanelStackingVertical) { - // set launcher shelf to be aligned on the right - SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_RIGHT); - - // Size panels in such a way that ordering them by X coordinate would cause - // stacking order to be incorrect. Test that stacking order is based on Y. - scoped_ptr<aura::Window> w1(CreatePanelWindow(gfx::Rect(0, 0, 210, 201))); - scoped_ptr<aura::Window> w2(CreatePanelWindow(gfx::Rect(0, 0, 220, 201))); - scoped_ptr<aura::Window> w3(CreatePanelWindow(gfx::Rect(0, 0, 200, 201))); - - // Default stacking order. - EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get())); - - // Changing the active window should update the stacking order. - wm::ActivateWindow(w1.get()); - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - EXPECT_TRUE(WindowIsAbove(w1.get(), w2.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get())); - - wm::ActivateWindow(w2.get()); - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - EXPECT_TRUE(WindowIsAbove(w1.get(), w3.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get())); - - wm::ActivateWindow(w3.get()); - EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get())); -} - -TEST_F(PanelLayoutManagerTest, MultiplePanelCallout) { - gfx::Rect bounds(0, 0, 200, 200); - scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w4(CreateNormalWindow(gfx::Rect())); - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - EXPECT_TRUE(IsPanelCalloutVisible(w1.get())); - EXPECT_TRUE(IsPanelCalloutVisible(w2.get())); - EXPECT_TRUE(IsPanelCalloutVisible(w3.get())); - wm::ActivateWindow(w1.get()); - EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w1.get())); - wm::ActivateWindow(w2.get()); - EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w2.get())); - wm::ActivateWindow(w3.get()); - EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w3.get())); - wm::ActivateWindow(w4.get()); - wm::ActivateWindow(w3.get()); - EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w3.get())); - w3.reset(); - EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w2.get())); -} - -// Tests removing panels. -TEST_F(PanelLayoutManagerTest, RemoveLeftPanel) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds)); - - // At this point, windows should be stacked with 1 < 2 < 3 - wm::ActivateWindow(w1.get()); - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - // Now, windows should be stacked 1 > 2 > 3 - w1.reset(); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get())); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get())); -} - -TEST_F(PanelLayoutManagerTest, RemoveMiddlePanel) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds)); - - // At this point, windows should be stacked with 1 < 2 < 3 - wm::ActivateWindow(w2.get()); - // Windows should be stacked 1 < 2 > 3 - w2.reset(); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get())); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get())); - EXPECT_TRUE(WindowIsAbove(w3.get(), w1.get())); -} - -TEST_F(PanelLayoutManagerTest, RemoveRightPanel) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds)); - - // At this point, windows should be stacked with 1 < 2 < 3 - wm::ActivateWindow(w3.get()); - // Order shouldn't change. - w3.reset(); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get())); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get())); -} - -TEST_F(PanelLayoutManagerTest, RemoveNonActivePanel) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds)); - - // At this point, windows should be stacked with 1 < 2 < 3 - wm::ActivateWindow(w2.get()); - // Windows should be stacked 1 < 2 > 3 - w1.reset(); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get())); - EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get())); - EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get())); -} - -TEST_F(PanelLayoutManagerTest, SplitView) { - gfx::Rect bounds(0, 0, 90, 201); - scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); - - EXPECT_NO_FATAL_FAILURE(PanelsNotOverlapping(w1.get(), w2.get())); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_SplitViewOverlapWhenLarge DISABLED_SplitViewOverlapWhenLarge -#else -#define MAYBE_SplitViewOverlapWhenLarge SplitViewOverlapWhenLarge -#endif - -TEST_F(PanelLayoutManagerTest, MAYBE_SplitViewOverlapWhenLarge) { - gfx::Rect bounds(0, 0, 600, 201); - scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); - - EXPECT_NO_FATAL_FAILURE(PanelInScreen(w1.get())); - EXPECT_NO_FATAL_FAILURE(PanelInScreen(w2.get())); -} - -TEST_F(PanelLayoutManagerTest, FanWindows) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds)); - - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - int window_x1 = w1->GetBoundsInRootWindow().CenterPoint().x(); - int window_x2 = w2->GetBoundsInRootWindow().CenterPoint().x(); - int window_x3 = w3->GetBoundsInRootWindow().CenterPoint().x(); - Launcher* launcher = Launcher::ForPrimaryDisplay(); - int icon_x1 = launcher->GetScreenBoundsOfItemIconForWindow(w1.get()).x(); - int icon_x2 = launcher->GetScreenBoundsOfItemIconForWindow(w2.get()).x(); - EXPECT_EQ(window_x2 - window_x1, window_x3 - window_x2); - int spacing = window_x2 - window_x1; - EXPECT_GT(spacing, icon_x2 - icon_x1); -} - -TEST_F(PanelLayoutManagerTest, FanLargeWindow) { - gfx::Rect small_bounds(0, 0, 201, 201); - gfx::Rect large_bounds(0, 0, 501, 201); - scoped_ptr<aura::Window> w1(CreatePanelWindow(small_bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(large_bounds)); - scoped_ptr<aura::Window> w3(CreatePanelWindow(small_bounds)); - - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); - int window_x1 = w1->GetBoundsInRootWindow().CenterPoint().x(); - int window_x2 = w2->GetBoundsInRootWindow().CenterPoint().x(); - int window_x3 = w3->GetBoundsInRootWindow().CenterPoint().x(); - // The distances may not be equidistant with a large panel but the panels - // should be in the correct order with respect to their midpoints. - EXPECT_GT(window_x2, window_x1); - EXPECT_GT(window_x3, window_x2); -} - -TEST_F(PanelLayoutManagerTest, MinimizeRestorePanel) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> window(CreatePanelWindow(bounds)); - // Activate the window, ensure callout is visible. - wm::ActivateWindow(window.get()); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsPanelCalloutVisible(window.get())); - // Minimize the panel, callout should be hidden. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(IsPanelCalloutVisible(window.get())); - // Restore the pantel; panel should not be activated by default but callout - // should be visible. - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsPanelCalloutVisible(window.get())); - // Activate the window, ensure callout is visible. - wm::ActivateWindow(window.get()); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(IsPanelCalloutVisible(window.get())); -} - -TEST_F(PanelLayoutManagerTest, PanelMoveBetweenMultipleDisplays) { - if (!SupportsMultipleDisplays()) - return; - - // Keep the displays wide so that launchers have enough - // space for launcher buttons. - UpdateDisplay("600x400,600x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> p1_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50))); - scoped_ptr<aura::Window> p2_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50))); - scoped_ptr<aura::Window> p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50))); - scoped_ptr<aura::Window> p2_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50))); - - ShelfView* shelf_view_1st = GetShelfView(Launcher::ForPrimaryDisplay()); - ShelfView* shelf_view_2nd = - GetShelfView(Launcher::ForWindow(root_windows[1])); - - EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow()); - EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow()); - EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow()); - EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow()); - - EXPECT_EQ(internal::kShellWindowId_PanelContainer, p1_d1->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, p2_d1->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, p1_d2->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, p2_d2->parent()->id()); - - // Test a panel on 1st display. - // Clicking on the same display has no effect. - ClickLauncherItemForWindow(shelf_view_1st, p1_d1.get()); - EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow()); - EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow()); - EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow()); - EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow()); - EXPECT_FALSE(root_windows[1]->GetBoundsInScreen().Contains( - p1_d1->GetBoundsInScreen())); - - // Test if clicking on another display moves the panel to - // that display. - ClickLauncherItemForWindow(shelf_view_2nd, p1_d1.get()); - EXPECT_EQ(root_windows[1], p1_d1->GetRootWindow()); - EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow()); - EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow()); - EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow()); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - p1_d1->GetBoundsInScreen())); - - // Test a panel on 2nd display. - // Clicking on the same display has no effect. - ClickLauncherItemForWindow(shelf_view_2nd, p1_d2.get()); - EXPECT_EQ(root_windows[1], p1_d1->GetRootWindow()); - EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow()); - EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow()); - EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow()); - EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( - p1_d2->GetBoundsInScreen())); - - // Test if clicking on another display moves the panel to - // that display. - ClickLauncherItemForWindow(shelf_view_1st, p1_d2.get()); - EXPECT_EQ(root_windows[1], p1_d1->GetRootWindow()); - EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow()); - EXPECT_EQ(root_windows[0], p1_d2->GetRootWindow()); - EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow()); - EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains( - p1_d2->GetBoundsInScreen())); - - // Test if clicking on a previously moved window moves the - // panel back to the original display. - ClickLauncherItemForWindow(shelf_view_1st, p1_d1.get()); - EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow()); - EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow()); - EXPECT_EQ(root_windows[0], p1_d2->GetRootWindow()); - EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow()); - EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains( - p1_d1->GetBoundsInScreen())); -} - -TEST_F(PanelLayoutManagerTest, PanelAttachPositionMultipleDisplays) { - if (!SupportsMultipleDisplays()) - return; - - // Keep the displays wide so that launchers have enough space for launcher - // buttons. Use differently sized displays so the launcher is in a different - // position on second display. - UpdateDisplay("600x400,600x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> p1_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50))); - scoped_ptr<aura::Window> p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50))); - - EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow()); - EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow()); - - IsPanelAboveLauncherIcon(p1_d1.get()); - IsCalloutAboveLauncherIcon(p1_d1.get()); - IsPanelAboveLauncherIcon(p1_d2.get()); - IsCalloutAboveLauncherIcon(p1_d2.get()); -} - -TEST_F(PanelLayoutManagerTest, PanelAlignmentSecondDisplay) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("600x400,600x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50))); - EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow()); - - IsPanelAboveLauncherIcon(p1_d2.get()); - IsCalloutAboveLauncherIcon(p1_d2.get()); - - SetAlignment(root_windows[1], SHELF_ALIGNMENT_RIGHT); - IsPanelAboveLauncherIcon(p1_d2.get()); - IsCalloutAboveLauncherIcon(p1_d2.get()); - SetAlignment(root_windows[1], SHELF_ALIGNMENT_LEFT); - IsPanelAboveLauncherIcon(p1_d2.get()); - IsCalloutAboveLauncherIcon(p1_d2.get()); - SetAlignment(root_windows[1], SHELF_ALIGNMENT_TOP); - IsPanelAboveLauncherIcon(p1_d2.get()); - IsCalloutAboveLauncherIcon(p1_d2.get()); -} - -TEST_F(PanelLayoutManagerTest, AlignmentLeft) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> w(CreatePanelWindow(bounds)); - SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_LEFT); - IsPanelAboveLauncherIcon(w.get()); - IsCalloutAboveLauncherIcon(w.get()); -} - -TEST_F(PanelLayoutManagerTest, AlignmentRight) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> w(CreatePanelWindow(bounds)); - SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_RIGHT); - IsPanelAboveLauncherIcon(w.get()); - IsCalloutAboveLauncherIcon(w.get()); -} - -TEST_F(PanelLayoutManagerTest, AlignmentTop) { - gfx::Rect bounds(0, 0, 201, 201); - scoped_ptr<aura::Window> w(CreatePanelWindow(bounds)); - SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_TOP); - IsPanelAboveLauncherIcon(w.get()); - IsCalloutAboveLauncherIcon(w.get()); -} - -// Tests that panels will hide and restore their state with the shelf visibility -// state. This ensures that entering full-screen mode will hide your panels -// until you leave it. -TEST_F(PanelLayoutManagerTest, PanelsHideAndRestoreWithShelf) { - gfx::Rect bounds(0, 0, 201, 201); - - scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); - scoped_ptr<aura::Window> w3; - // Minimize w2. - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - RunAllPendingInMessageLoop(); - EXPECT_TRUE(w1->IsVisible()); - EXPECT_FALSE(w2->IsVisible()); - - SetShelfVisibilityState(Shell::GetPrimaryRootWindow(), SHELF_HIDDEN); - RunAllPendingInMessageLoop(); - - // w3 is created while in full-screen mode, should only become visible when - // we exit fullscreen mode. - w3.reset(CreatePanelWindow(bounds)); - - EXPECT_FALSE(w1->IsVisible()); - EXPECT_FALSE(w2->IsVisible()); - EXPECT_FALSE(w3->IsVisible()); - - // While in full-screen mode, the panel windows should still be in the - // switchable window list - http://crbug.com/313919. - MruWindowTracker::WindowList switchable_window_list = - Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList(); - EXPECT_EQ(3u, switchable_window_list.size()); - EXPECT_NE(switchable_window_list.end(), - std::find(switchable_window_list.begin(), switchable_window_list.end(), - w1.get())); - EXPECT_NE(switchable_window_list.end(), - std::find(switchable_window_list.begin(), switchable_window_list.end(), - w2.get())); - EXPECT_NE(switchable_window_list.end(), - std::find(switchable_window_list.begin(), switchable_window_list.end(), - w3.get())); - - SetShelfVisibilityState(Shell::GetPrimaryRootWindow(), SHELF_VISIBLE); - RunAllPendingInMessageLoop(); - - // Windows should be restored to their prior state. - EXPECT_TRUE(w1->IsVisible()); - EXPECT_FALSE(w2->IsVisible()); - EXPECT_TRUE(w3->IsVisible()); -} - -INSTANTIATE_TEST_CASE_P(LtrRtl, PanelLayoutManagerTextDirectionTest, - testing::Bool()); - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/panels/panel_window_event_handler.cc b/chromium/ash/wm/panels/panel_window_event_handler.cc deleted file mode 100644 index cb494699195..00000000000 --- a/chromium/ash/wm/panels/panel_window_event_handler.cc +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 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/panels/panel_window_event_handler.h" - -#include "ash/wm/window_state.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/events/event.h" - -namespace ash { -namespace internal { - -PanelWindowEventHandler::PanelWindowEventHandler(aura::Window* owner) - : ToplevelWindowEventHandler(owner) { -} - -PanelWindowEventHandler::~PanelWindowEventHandler() { -} - -void PanelWindowEventHandler::OnMouseEvent(ui::MouseEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (event->type() == ui::ET_MOUSE_PRESSED && - event->flags() & ui::EF_IS_DOUBLE_CLICK && - event->IsOnlyLeftMouseButton() && - target->delegate()->GetNonClientComponent(event->location()) == - HTCAPTION) { - wm::GetWindowState(target)->Minimize(); - return; - } - ToplevelWindowEventHandler::OnMouseEvent(event); -} - -void PanelWindowEventHandler::OnGestureEvent(ui::GestureEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (event->type() == ui::ET_GESTURE_TAP && - event->details().tap_count() == 2 && - target->delegate()->GetNonClientComponent(event->location()) == - HTCAPTION) { - wm::GetWindowState(target)->Minimize(); - event->StopPropagation(); - return; - } - ToplevelWindowEventHandler::OnGestureEvent(event); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/panels/panel_window_event_handler.h b/chromium/ash/wm/panels/panel_window_event_handler.h deleted file mode 100644 index 2823b885cc7..00000000000 --- a/chromium/ash/wm/panels/panel_window_event_handler.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 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_PANELS_PANEL_WINDOW_EVENT_HANDLER_H_ -#define ASH_WM_PANELS_PANEL_WINDOW_EVENT_HANDLER_H_ - -#include "ash/wm/toplevel_window_event_handler.h" - -namespace aura { -class Window; -} - -namespace ash { -namespace internal { - -// PanelWindowEventHandler minimizes panels when the user double clicks or -// double taps on the panel header. -class PanelWindowEventHandler : public ToplevelWindowEventHandler { - public: - explicit PanelWindowEventHandler(aura::Window* owner); - virtual ~PanelWindowEventHandler(); - - // TopLevelWindowEventHandler: - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(PanelWindowEventHandler); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_PANELS_PANEL_WINDOW_EVENT_HANDLER_H_ diff --git a/chromium/ash/wm/panels/panel_window_resizer.cc b/chromium/ash/wm/panels/panel_window_resizer.cc deleted file mode 100644 index 739544f97d4..00000000000 --- a/chromium/ash/wm/panels/panel_window_resizer.cc +++ /dev/null @@ -1,241 +0,0 @@ -// 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/panels/panel_window_resizer.h" - -#include "ash/display/display_controller.h" -#include "ash/launcher/launcher.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_types.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/panels/panel_layout_manager.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/memory/weak_ptr.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/window_tree_client.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_types.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" - -namespace ash { - -namespace { -const int kPanelSnapToLauncherDistance = 30; - -internal::PanelLayoutManager* GetPanelLayoutManager( - aura::Window* panel_container) { - DCHECK(panel_container->id() == internal::kShellWindowId_PanelContainer); - return static_cast<internal::PanelLayoutManager*>( - panel_container->layout_manager()); -} - -} // namespace - -PanelWindowResizer::~PanelWindowResizer() { -} - -// static -PanelWindowResizer* -PanelWindowResizer::Create(WindowResizer* next_window_resizer, - aura::Window* window, - const gfx::Point& location, - int window_component, - aura::client::WindowMoveSource source) { - Details details(window, location, window_component, source); - return details.is_resizable ? - new PanelWindowResizer(next_window_resizer, details) : NULL; -} - -void PanelWindowResizer::Drag(const gfx::Point& location, int event_flags) { - last_location_ = location; - wm::ConvertPointToScreen(GetTarget()->parent(), &last_location_); - if (!did_move_or_resize_) { - did_move_or_resize_ = true; - StartedDragging(); - } - - // Check if the destination has changed displays. - gfx::Screen* screen = Shell::GetScreen(); - const gfx::Display dst_display = - screen->GetDisplayNearestPoint(last_location_); - if (dst_display.id() != - screen->GetDisplayNearestWindow(panel_container_->GetRootWindow()).id()) { - // The panel is being dragged to a new display. If the previous container is - // the current parent of the panel it will be informed of the end of drag - // when the panel is reparented, otherwise let the previous container know - // the drag is complete. If we told the panel's parent that the drag was - // complete it would begin positioning the panel. - if (GetTarget()->parent() != panel_container_) - GetPanelLayoutManager(panel_container_)->FinishDragging(); - aura::Window* dst_root = Shell::GetInstance()->display_controller()-> - GetRootWindowForDisplayId(dst_display.id()); - panel_container_ = Shell::GetContainer( - dst_root, internal::kShellWindowId_PanelContainer); - - // The panel's parent already knows that the drag is in progress for this - // panel. - if (panel_container_ && GetTarget()->parent() != panel_container_) - GetPanelLayoutManager(panel_container_)->StartDragging(GetTarget()); - } - gfx::Point offset; - gfx::Rect bounds(CalculateBoundsForDrag(details_, location)); - should_attach_ = AttachToLauncher(bounds, &offset); - gfx::Point modified_location(location.x() + offset.x(), - location.y() + offset.y()); - - base::WeakPtr<PanelWindowResizer> resizer(weak_ptr_factory_.GetWeakPtr()); - next_window_resizer_->Drag(modified_location, event_flags); - if (!resizer) - return; - - if (should_attach_ && - !(details_.bounds_change & WindowResizer::kBoundsChange_Resizes)) { - UpdateLauncherPosition(); - } -} - -void PanelWindowResizer::CompleteDrag(int event_flags) { - // The root window can change when dragging into a different screen. - next_window_resizer_->CompleteDrag(event_flags); - FinishDragging(); -} - -void PanelWindowResizer::RevertDrag() { - next_window_resizer_->RevertDrag(); - should_attach_ = was_attached_; - FinishDragging(); -} - -aura::Window* PanelWindowResizer::GetTarget() { - return next_window_resizer_->GetTarget(); -} - -const gfx::Point& PanelWindowResizer::GetInitialLocation() const { - return details_.initial_location_in_parent; -} - -PanelWindowResizer::PanelWindowResizer(WindowResizer* next_window_resizer, - const Details& details) - : details_(details), - next_window_resizer_(next_window_resizer), - panel_container_(NULL), - initial_panel_container_(NULL), - did_move_or_resize_(false), - was_attached_(wm::GetWindowState(GetTarget())->panel_attached()), - should_attach_(was_attached_), - weak_ptr_factory_(this) { - DCHECK(details_.is_resizable); - panel_container_ = Shell::GetContainer( - details.window->GetRootWindow(), - internal::kShellWindowId_PanelContainer); - initial_panel_container_ = panel_container_; -} - -bool PanelWindowResizer::AttachToLauncher(const gfx::Rect& bounds, - gfx::Point* offset) { - bool should_attach = false; - if (panel_container_) { - internal::PanelLayoutManager* panel_layout_manager = - GetPanelLayoutManager(panel_container_); - gfx::Rect launcher_bounds = ScreenAsh::ConvertRectFromScreen( - GetTarget()->parent(), - panel_layout_manager->launcher()-> - shelf_widget()->GetWindowBoundsInScreen()); - switch (panel_layout_manager->launcher()->alignment()) { - case SHELF_ALIGNMENT_BOTTOM: - if (bounds.bottom() >= (launcher_bounds.y() - - kPanelSnapToLauncherDistance)) { - should_attach = true; - offset->set_y(launcher_bounds.y() - bounds.height() - bounds.y()); - } - break; - case SHELF_ALIGNMENT_LEFT: - if (bounds.x() <= (launcher_bounds.right() + - kPanelSnapToLauncherDistance)) { - should_attach = true; - offset->set_x(launcher_bounds.right() - bounds.x()); - } - break; - case SHELF_ALIGNMENT_RIGHT: - if (bounds.right() >= (launcher_bounds.x() - - kPanelSnapToLauncherDistance)) { - should_attach = true; - offset->set_x(launcher_bounds.x() - bounds.width() - bounds.x()); - } - break; - case SHELF_ALIGNMENT_TOP: - if (bounds.y() <= (launcher_bounds.bottom() + - kPanelSnapToLauncherDistance)) { - should_attach = true; - offset->set_y(launcher_bounds.bottom() - bounds.y()); - } - break; - } - } - return should_attach; -} - -void PanelWindowResizer::StartedDragging() { - // Tell the panel layout manager that we are dragging this panel before - // attaching it so that it does not get repositioned. - if (panel_container_) - GetPanelLayoutManager(panel_container_)->StartDragging(GetTarget()); - if (!was_attached_) { - // Attach the panel while dragging placing it in front of other panels. - wm::GetWindowState(GetTarget())->set_continue_drag_after_reparent(true); - wm::GetWindowState(GetTarget())->set_panel_attached(true); - // We use root window coordinates to ensure that during the drag the panel - // is reparented to a container in the root window that has that window. - aura::Window* target = GetTarget(); - aura::Window* target_root = target->GetRootWindow(); - aura::Window* old_parent = target->parent(); - aura::client::ParentWindowWithContext( - target, target_root, target_root->GetBoundsInScreen()); - wm::ReparentTransientChildrenOfChild(target, old_parent, target->parent()); - } -} - -void PanelWindowResizer::FinishDragging() { - if (!did_move_or_resize_) - return; - if (details_.bounds_change & WindowResizer::kBoundsChange_Resizes) - should_attach_ = was_attached_; - if (wm::GetWindowState(GetTarget())->panel_attached() != should_attach_) { - wm::GetWindowState(GetTarget())->set_panel_attached(should_attach_); - // We use last known location to ensure that after the drag the panel - // is reparented to a container in the root window that has that location. - aura::Window* target = GetTarget(); - aura::Window* target_root = target->GetRootWindow(); - aura::Window* old_parent = target->parent(); - aura::client::ParentWindowWithContext( - target, target_root, gfx::Rect(last_location_, gfx::Size())); - wm::ReparentTransientChildrenOfChild(target, old_parent, target->parent()); - } - - // 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_panel_container_ != panel_container_) - GetPanelLayoutManager(initial_panel_container_)->FinishDragging(); - if (panel_container_) - GetPanelLayoutManager(panel_container_)->FinishDragging(); -} - -void PanelWindowResizer::UpdateLauncherPosition() { - if (panel_container_) { - GetPanelLayoutManager(panel_container_)->launcher()-> - UpdateIconPositionForWindow(GetTarget()); - } -} - -} // namespace aura diff --git a/chromium/ash/wm/panels/panel_window_resizer.h b/chromium/ash/wm/panels/panel_window_resizer.h deleted file mode 100644 index df3d8c44513..00000000000 --- a/chromium/ash/wm/panels/panel_window_resizer.h +++ /dev/null @@ -1,94 +0,0 @@ -// 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_PANELS_PANEL_WINDOW_RESIZER_H_ -#define ASH_WM_PANELS_PANEL_WINDOW_RESIZER_H_ - -#include "ash/wm/window_resizer.h" -#include "base/compiler_specific.h" -#include "base/memory/weak_ptr.h" - -namespace gfx { -class Rect; -class Point; -} - -namespace ash { - -// PanelWindowResizer is used by ToplevelWindowEventFilter to handle dragging, -// moving or resizing panel window. These can be attached and detached from the -// launcher. -class ASH_EXPORT PanelWindowResizer : public WindowResizer { - public: - virtual ~PanelWindowResizer(); - - // Creates a new PanelWindowResizer. The caller takes ownership of the - // returned object. The ownership of |next_window_resizer| is taken by the - // returned object. Returns NULL if not resizable. - static PanelWindowResizer* Create(WindowResizer* next_window_resizer, - aura::Window* window, - const gfx::Point& location, - int window_component, - aura::client::WindowMoveSource source); - - // WindowResizer: - virtual void Drag(const gfx::Point& location, int event_flags) OVERRIDE; - virtual void CompleteDrag(int event_flags) OVERRIDE; - virtual void RevertDrag() OVERRIDE; - virtual aura::Window* GetTarget() OVERRIDE; - virtual const gfx::Point& GetInitialLocation() const OVERRIDE; - - private: - // Creates PanelWindowResizer that adds the ability to attach / detach panel - // windows as well as reparenting them to the panel layer while dragging to - // |next_window_resizer|. This object takes ownership of - // |next_window_resizer|. - PanelWindowResizer(WindowResizer* next_window_resizer, - const Details& details); - - // Checks if the provided window bounds should attach to the launcher. If true - // the offset gives the necessary adjustment to snap to the launcher. - bool AttachToLauncher(const gfx::Rect& bounds, gfx::Point* offset); - - // Tracks the panel's initial position and attachment at the start of a drag - // and informs the PanelLayoutManager that a drag has started if necessary. - void StartedDragging(); - - // Informs the PanelLayoutManager that the drag is complete if it was informed - // of the drag start. - void FinishDragging(); - - // Updates the dragged panel's index in the launcher. - void UpdateLauncherPosition(); - - const Details details_; - - // Last pointer location in screen coordinates. - gfx::Point last_location_; - - // Wraps a window resizer and adds panel detaching / reattaching and snapping - // to launcher behavior during drags. - scoped_ptr<WindowResizer> next_window_resizer_; - - // Panel container window. - aura::Window* panel_container_; - aura::Window* initial_panel_container_; - - // Set to true once Drag() is invoked and the bounds of the window change. - bool did_move_or_resize_; - - // True if the window started attached to the launcher. - const bool was_attached_; - - // True if the window should attach to the launcher after releasing. - bool should_attach_; - - base::WeakPtrFactory<PanelWindowResizer> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(PanelWindowResizer); -}; - -} // namespace ash - -#endif // ASH_WM_PANELS_PANEL_WINDOW_RESIZER_H_ diff --git a/chromium/ash/wm/panels/panel_window_resizer_unittest.cc b/chromium/ash/wm/panels/panel_window_resizer_unittest.cc deleted file mode 100644 index f264b2b2b94..00000000000 --- a/chromium/ash/wm/panels/panel_window_resizer_unittest.cc +++ /dev/null @@ -1,537 +0,0 @@ -// Copyright (c) 2013 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/panels/panel_window_resizer.h" - -#include "ash/launcher/launcher.h" -#include "ash/root_window_controller.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_model.h" -#include "ash/shelf/shelf_types.h" -#include "ash/shelf/shelf_util.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/cursor_manager_test_api.h" -#include "ash/test/shell_test_api.h" -#include "ash/test/test_shelf_delegate.h" -#include "ash/wm/drag_window_resizer.h" -#include "ash/wm/panels/panel_layout_manager.h" -#include "ash/wm/window_state.h" -#include "base/win/windows_version.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/base/hit_test.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_types.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -class PanelWindowResizerTest : public test::AshTestBase { - public: - PanelWindowResizerTest() {} - virtual ~PanelWindowResizerTest() {} - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - UpdateDisplay("600x400"); - test::ShellTestApi test_api(Shell::GetInstance()); - model_ = test_api.shelf_model(); - shelf_delegate_ = test::TestShelfDelegate::instance(); - } - - virtual void TearDown() OVERRIDE { - AshTestBase::TearDown(); - } - - protected: - gfx::Point CalculateDragPoint(const WindowResizer& resizer, - int delta_x, - int delta_y) const { - gfx::Point location = resizer.GetInitialLocation(); - location.set_x(location.x() + delta_x); - location.set_y(location.y() + delta_y); - return location; - } - - aura::Window* CreatePanelWindow(const gfx::Point& origin) { - gfx::Rect bounds(origin, gfx::Size(101, 101)); - aura::Window* window = CreateTestWindowInShellWithDelegateAndType( - NULL, - aura::client::WINDOW_TYPE_PANEL, - 0, - bounds); - shelf_delegate_->AddLauncherItem(window); - PanelLayoutManager* manager = - static_cast<PanelLayoutManager*>( - Shell::GetContainer(window->GetRootWindow(), - internal::kShellWindowId_PanelContainer)-> - layout_manager()); - manager->Relayout(); - return window; - } - - void DragStart(aura::Window* window) { - resizer_.reset(CreateWindowResizer( - window, - window->bounds().origin(), - HTCAPTION, - aura::client::WINDOW_MOVE_SOURCE_MOUSE).release()); - ASSERT_TRUE(resizer_.get()); - } - - void DragMove(int dx, int dy) { - resizer_->Drag(CalculateDragPoint(*resizer_, dx, dy), 0); - } - - void DragEnd() { - resizer_->CompleteDrag(0); - resizer_.reset(); - } - - void DragRevert() { - resizer_->RevertDrag(); - resizer_.reset(); - } - - // Test dragging the panel slightly, then detaching, and then reattaching - // dragging out by the vector (dx, dy). - void DetachReattachTest(aura::Window* window, int dx, int dy) { - wm::WindowState* window_state = wm::GetWindowState(window); - EXPECT_TRUE(window_state->panel_attached()); - aura::Window* root_window = window->GetRootWindow(); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); - DragStart(window); - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - - // Drag the panel slightly. The window should still be snapped to the - // launcher. - DragMove(dx * 5, dy * 5); - EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x()); - EXPECT_EQ(initial_bounds.y(), window->GetBoundsInScreen().y()); - - // Drag further out and the window should now move to the cursor. - DragMove(dx * 100, dy * 100); - EXPECT_EQ(initial_bounds.x() + dx * 100, window->GetBoundsInScreen().x()); - EXPECT_EQ(initial_bounds.y() + dy * 100, window->GetBoundsInScreen().y()); - - // The panel should be detached when the drag completes. - DragEnd(); - - EXPECT_FALSE(window_state->panel_attached()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, - window->parent()->id()); - EXPECT_EQ(root_window, window->GetRootWindow()); - - DragStart(window); - // Drag the panel down. - DragMove(dx * -95, dy * -95); - // Release the mouse and the panel should be reattached. - DragEnd(); - - // The panel should be reattached and have snapped to the launcher. - EXPECT_TRUE(window_state->panel_attached()); - EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x()); - EXPECT_EQ(initial_bounds.y(), window->GetBoundsInScreen().y()); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); - } - - void TestWindowOrder(const std::vector<aura::Window*>& window_order) { - int panel_index = model_->FirstPanelIndex(); - EXPECT_EQ((int)(panel_index + window_order.size()), model_->item_count()); - for (std::vector<aura::Window*>::const_iterator iter = - window_order.begin(); iter != window_order.end(); - ++iter, ++panel_index) { - LauncherID id = GetLauncherIDForWindow(*iter); - EXPECT_EQ(id, model_->items()[panel_index].id); - } - } - - // Test dragging panel window along the shelf and verify that panel icons - // are reordered appropriately. - void DragAlongShelfReorder(int dx, int dy) { - gfx::Point origin(0, 0); - scoped_ptr<aura::Window> w1(CreatePanelWindow(origin)); - scoped_ptr<aura::Window> w2(CreatePanelWindow(origin)); - std::vector<aura::Window*> window_order_original; - std::vector<aura::Window*> window_order_swapped; - window_order_original.push_back(w1.get()); - window_order_original.push_back(w2.get()); - window_order_swapped.push_back(w2.get()); - window_order_swapped.push_back(w1.get()); - TestWindowOrder(window_order_original); - - // Drag window #2 to the beginning of the shelf. - DragStart(w2.get()); - DragMove(400 * dx, 400 * dy); - TestWindowOrder(window_order_swapped); - DragEnd(); - - // Expect swapped window order. - TestWindowOrder(window_order_swapped); - - // Drag window #2 back to the end. - DragStart(w2.get()); - DragMove(-400 * dx, -400 * dy); - TestWindowOrder(window_order_original); - DragEnd(); - - // Expect original order. - TestWindowOrder(window_order_original); - } - - private: - scoped_ptr<WindowResizer> resizer_; - internal::PanelLayoutManager* panel_layout_manager_; - ShelfModel* model_; - test::TestShelfDelegate* shelf_delegate_; - - DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTest); -}; - -class PanelWindowResizerTextDirectionTest - : public PanelWindowResizerTest, - public testing::WithParamInterface<bool> { - public: - PanelWindowResizerTextDirectionTest() : is_rtl_(GetParam()) {} - virtual ~PanelWindowResizerTextDirectionTest() {} - - virtual void SetUp() OVERRIDE { - original_locale = l10n_util::GetApplicationLocale(std::string()); - if (is_rtl_) - base::i18n::SetICUDefaultLocale("he"); - PanelWindowResizerTest::SetUp(); - ASSERT_EQ(is_rtl_, base::i18n::IsRTL()); - } - - virtual void TearDown() OVERRIDE { - if (is_rtl_) - base::i18n::SetICUDefaultLocale(original_locale); - PanelWindowResizerTest::TearDown(); - } - - private: - bool is_rtl_; - std::string original_locale; - - DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTextDirectionTest); -}; - -// PanelLayoutManager and PanelWindowResizer should work if panels have -// transient children of supported types. -class PanelWindowResizerTransientTest - : public PanelWindowResizerTest, - public testing::WithParamInterface<aura::client::WindowType> { - public: - PanelWindowResizerTransientTest() : transient_window_type_(GetParam()) {} - virtual ~PanelWindowResizerTransientTest() {} - - protected: - aura::client::WindowType transient_window_type_; - - private: - DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTransientTest); -}; - -// Verifies a window can be dragged from the panel and detached and then -// reattached. -TEST_F(PanelWindowResizerTest, PanelDetachReattachBottom) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window( - CreatePanelWindow(gfx::Point(0, 0))); - DetachReattachTest(window.get(), 0, -1); -} - -TEST_F(PanelWindowResizerTest, PanelDetachReattachLeft) { - if (!SupportsHostWindowResize()) - return; - - ash::Shell* shell = ash::Shell::GetInstance(); - shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow()); - scoped_ptr<aura::Window> window( - CreatePanelWindow(gfx::Point(0, 0))); - DetachReattachTest(window.get(), 1, 0); -} - -TEST_F(PanelWindowResizerTest, PanelDetachReattachRight) { - if (!SupportsHostWindowResize()) - return; - - ash::Shell* shell = ash::Shell::GetInstance(); - shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT, - shell->GetPrimaryRootWindow()); - scoped_ptr<aura::Window> window( - CreatePanelWindow(gfx::Point(0, 0))); - DetachReattachTest(window.get(), -1, 0); -} - -TEST_F(PanelWindowResizerTest, PanelDetachReattachTop) { - if (!SupportsHostWindowResize()) - return; - - ash::Shell* shell = ash::Shell::GetInstance(); - shell->SetShelfAlignment(SHELF_ALIGNMENT_TOP, shell->GetPrimaryRootWindow()); - scoped_ptr<aura::Window> window( - CreatePanelWindow(gfx::Point(0, 0))); - DetachReattachTest(window.get(), 0, 1); -} - -TEST_F(PanelWindowResizerTest, PanelDetachReattachMultipleDisplays) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("600x400,600x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - scoped_ptr<aura::Window> window( - CreatePanelWindow(gfx::Point(600, 0))); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - DetachReattachTest(window.get(), 0, -1); -} - -TEST_F(PanelWindowResizerTest, DetachThenDragAcrossDisplays) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("600x400,600x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - scoped_ptr<aura::Window> window( - CreatePanelWindow(gfx::Point(0, 0))); - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - DragStart(window.get()); - DragMove(0, -100); - DragEnd(); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x()); - EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y()); - EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); - - DragStart(window.get()); - DragMove(500, 0); - DragEnd(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x()); - EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y()); - EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); -} - -TEST_F(PanelWindowResizerTest, DetachAcrossDisplays) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("600x400,600x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - scoped_ptr<aura::Window> window( - CreatePanelWindow(gfx::Point(0, 0))); - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - DragStart(window.get()); - DragMove(500, -100); - DragEnd(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x()); - EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y()); - EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); -} - -TEST_F(PanelWindowResizerTest, DetachThenAttachToSecondDisplay) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("600x400,600x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - scoped_ptr<aura::Window> window( - CreatePanelWindow(gfx::Point(0, 0))); - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - - // Detach the window. - DragStart(window.get()); - DragMove(0, -100); - DragEnd(); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached()); - - // Drag the window just above the other display's launcher. - DragStart(window.get()); - DragMove(500, 295); - EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x()); - - // Should stick to other launcher. - EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y()); - DragEnd(); - - // When dropped should move to second display's panel container. - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached()); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); -} - -TEST_F(PanelWindowResizerTest, AttachToSecondDisplay) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("600x400,600x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - scoped_ptr<aura::Window> window( - CreatePanelWindow(gfx::Point(0, 0))); - gfx::Rect initial_bounds = window->GetBoundsInScreen(); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - - // Drag the window just above the other display's launcher. - DragStart(window.get()); - DragMove(500, 195); - EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x()); - - // Should stick to other launcher. - EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y()); - DragEnd(); - - // When dropped should move to second display's panel container. - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached()); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); -} - -TEST_F(PanelWindowResizerTest, RevertDragRestoresAttachment) { - scoped_ptr<aura::Window> window( - CreatePanelWindow(gfx::Point(0, 0))); - EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached()); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); - DragStart(window.get()); - DragMove(0, -100); - DragRevert(); - EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached()); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); - - // Detach panel. - DragStart(window.get()); - DragMove(0, -100); - DragEnd(); - EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); - - // Drag back to launcher. - DragStart(window.get()); - DragMove(0, 100); - - // When the drag is reverted it should remain detached. - DragRevert(); - EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); -} - -TEST_F(PanelWindowResizerTest, DragMovesToPanelLayer) { - scoped_ptr<aura::Window> window(CreatePanelWindow(gfx::Point(0, 0))); - DragStart(window.get()); - DragMove(0, -100); - DragEnd(); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); - - // While moving the panel window should be moved to the panel container. - DragStart(window.get()); - DragMove(20, 0); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); - DragEnd(); - - // When dropped it should return to the default container. - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, - window->parent()->id()); -} - -TEST_P(PanelWindowResizerTextDirectionTest, DragReordersPanelsHorizontal) { - if (!SupportsHostWindowResize()) - return; - - DragAlongShelfReorder(base::i18n::IsRTL() ? 1 : -1, 0); -} - -TEST_F(PanelWindowResizerTest, DragReordersPanelsVertical) { - if (!SupportsHostWindowResize()) - return; - - ash::Shell* shell = ash::Shell::GetInstance(); - shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow()); - DragAlongShelfReorder(0, -1); -} - -// Tests that panels can have transient children of different types. -// The transient children should be reparented in sync with the panel. -TEST_P(PanelWindowResizerTransientTest, PanelWithTransientChild) { - if (!SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> window(CreatePanelWindow(gfx::Point(0, 0))); - scoped_ptr<aura::Window> child(CreateTestWindowInShellWithDelegateAndType( - NULL, transient_window_type_, 0, gfx::Rect(20, 20, 150, 40))); - window->AddTransientChild(child.get()); - if (window->parent() != child->parent()) - window->parent()->AddChild(child.get()); - EXPECT_EQ(window.get(), child->transient_parent()); - - // Drag the child to the shelf. Its new position should not be overridden. - const gfx::Rect attached_bounds(window->GetBoundsInScreen()); - const int dy = window->GetBoundsInScreen().bottom() - - child->GetBoundsInScreen().bottom(); - DragStart(child.get()); - DragMove(50, dy); - // While moving the transient child window should be in the panel container. - EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id()); - DragEnd(); - // Child should move, |window| should not. - EXPECT_EQ(gfx::Point(20 + 50, 20 + dy).ToString(), - child->GetBoundsInScreen().origin().ToString()); - EXPECT_EQ(attached_bounds.ToString(), window->GetBoundsInScreen().ToString()); - - // Drag the child along the the shelf past the |window|. - // Its new position should not be overridden. - DragStart(child.get()); - DragMove(350, 0); - // While moving the transient child window should be in the panel container. - EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id()); - DragEnd(); - // |child| should move, |window| should not. - EXPECT_EQ(gfx::Point(20 + 50 + 350, 20 + dy).ToString(), - child->GetBoundsInScreen().origin().ToString()); - EXPECT_EQ(attached_bounds.ToString(), window->GetBoundsInScreen().ToString()); - - DragStart(window.get()); - DragMove(0, -100); - // While moving the windows should be in the panel container. - EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id()); - DragEnd(); - // When dropped they should return to the default container. - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, child->parent()->id()); - - // While moving the window and child should be moved to the panel container. - DragStart(window.get()); - DragMove(20, 0); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id()); - DragEnd(); - - // When dropped they should return to the default container. - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); - EXPECT_EQ(internal::kShellWindowId_DefaultContainer, child->parent()->id()); -} - -INSTANTIATE_TEST_CASE_P(LtrRtl, PanelWindowResizerTextDirectionTest, - testing::Bool()); -INSTANTIATE_TEST_CASE_P(NormalPanelPopup, PanelWindowResizerTransientTest, - testing::Values(aura::client::WINDOW_TYPE_NORMAL, - aura::client::WINDOW_TYPE_PANEL, - aura::client::WINDOW_TYPE_POPUP)); - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/partial_screenshot_view.cc b/chromium/ash/wm/partial_screenshot_view.cc deleted file mode 100644 index b71c7c8a816..00000000000 --- a/chromium/ash/wm/partial_screenshot_view.cc +++ /dev/null @@ -1,243 +0,0 @@ -// 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/partial_screenshot_view.h" - -#include <algorithm> - -#include "ash/display/mouse_cursor_event_filter.h" -#include "ash/screenshot_delegate.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/overlay_event_filter.h" -#include "ui/aura/client/capture_client.h" -#include "ui/aura/root_window.h" -#include "ui/base/cursor/cursor.h" -#include "ui/events/event.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/rect.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_observer.h" - -namespace ash { - -// A self-owned object to handle the cancel and the finish of current partial -// screenshot session. -class PartialScreenshotView::OverlayDelegate - : public internal::OverlayEventFilter::Delegate, - public views::WidgetObserver { - public: - OverlayDelegate() { - Shell::GetInstance()->overlay_filter()->Activate(this); - } - - void RegisterWidget(views::Widget* widget) { - widgets_.push_back(widget); - widget->AddObserver(this); - } - - // Overridden from OverlayEventFilter::Delegate: - virtual void Cancel() OVERRIDE { - // Make sure the mouse_warp_mode allows warping. It can be stopped by a - // partial screenshot view. - internal::MouseCursorEventFilter* mouse_cursor_filter = - Shell::GetInstance()->mouse_cursor_filter(); - mouse_cursor_filter->set_mouse_warp_mode( - internal::MouseCursorEventFilter::WARP_ALWAYS); - for (size_t i = 0; i < widgets_.size(); ++i) - widgets_[i]->Close(); - } - - virtual bool IsCancelingKeyEvent(ui::KeyEvent* event) OVERRIDE { - return event->key_code() == ui::VKEY_ESCAPE; - } - - virtual aura::Window* GetWindow() OVERRIDE { - // Just returns NULL because this class does not handle key events in - // OverlayEventFilter, except for cancel keys. - return NULL; - } - - // Overridden from views::WidgetObserver: - virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE { - widget->RemoveObserver(this); - widgets_.erase(std::remove(widgets_.begin(), widgets_.end(), widget)); - if (widgets_.empty()) - delete this; - } - - private: - virtual ~OverlayDelegate() { - Shell::GetInstance()->overlay_filter()->Deactivate(); - } - - std::vector<views::Widget*> widgets_; - - DISALLOW_COPY_AND_ASSIGN(OverlayDelegate); -}; - -// static -std::vector<PartialScreenshotView*> -PartialScreenshotView::StartPartialScreenshot( - ScreenshotDelegate* screenshot_delegate) { - std::vector<PartialScreenshotView*> views; - OverlayDelegate* overlay_delegate = new OverlayDelegate(); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - for (aura::Window::Windows::iterator it = root_windows.begin(); - it != root_windows.end(); ++it) { - PartialScreenshotView* new_view = new PartialScreenshotView( - overlay_delegate, screenshot_delegate); - new_view->Init(*it); - views.push_back(new_view); - } - return views; -} - -PartialScreenshotView::PartialScreenshotView( - PartialScreenshotView::OverlayDelegate* overlay_delegate, - ScreenshotDelegate* screenshot_delegate) - : is_dragging_(false), - overlay_delegate_(overlay_delegate), - screenshot_delegate_(screenshot_delegate) { -} - -PartialScreenshotView::~PartialScreenshotView() { - overlay_delegate_ = NULL; - screenshot_delegate_ = NULL; -} - -void PartialScreenshotView::Init(aura::Window* root_window) { - views::Widget* widget = new views::Widget; - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.delegate = this; - // The partial screenshot rectangle has to be at the real top of - // the screen. - params.parent = Shell::GetContainer( - root_window, - internal::kShellWindowId_OverlayContainer); - - widget->Init(params); - widget->SetContentsView(this); - widget->SetBounds(root_window->GetBoundsInScreen()); - widget->GetNativeView()->SetName("PartialScreenshotView"); - widget->StackAtTop(); - widget->Show(); - // Releases the mouse capture to let mouse events come to the view. This - // will close the context menu. - aura::client::CaptureClient* capture_client = - aura::client::GetCaptureClient(root_window); - if (capture_client->GetCaptureWindow()) - capture_client->ReleaseCapture(capture_client->GetCaptureWindow()); - - overlay_delegate_->RegisterWidget(widget); -} - -gfx::Rect PartialScreenshotView::GetScreenshotRect() const { - int left = std::min(start_position_.x(), current_position_.x()); - int top = std::min(start_position_.y(), current_position_.y()); - int width = ::abs(start_position_.x() - current_position_.x()); - int height = ::abs(start_position_.y() - current_position_.y()); - return gfx::Rect(left, top, width, height); -} - -void PartialScreenshotView::OnSelectionStarted(const gfx::Point& position) { - start_position_ = position; -} - -void PartialScreenshotView::OnSelectionChanged(const gfx::Point& position) { - if (is_dragging_ && current_position_ == position) - return; - current_position_ = position; - SchedulePaint(); - is_dragging_ = true; -} - -void PartialScreenshotView::OnSelectionFinished() { - overlay_delegate_->Cancel(); - if (!is_dragging_) - return; - - is_dragging_ = false; - if (screenshot_delegate_) { - aura::Window*root_window = - GetWidget()->GetNativeWindow()->GetRootWindow(); - screenshot_delegate_->HandleTakePartialScreenshot( - root_window, - gfx::IntersectRects(root_window->bounds(), GetScreenshotRect())); - } -} - -gfx::NativeCursor PartialScreenshotView::GetCursor( - const ui::MouseEvent& event) { - // Always use "crosshair" cursor. - return ui::kCursorCross; -} - -void PartialScreenshotView::OnPaint(gfx::Canvas* canvas) { - if (is_dragging_) { - // Screenshot area representation: black rectangle with white - // rectangle inside. To avoid capturing these rectangles when mouse - // release, they should be outside of the actual capturing area. - gfx::Rect screenshot_rect = GetScreenshotRect(); - screenshot_rect.Inset(-1, -1, -1, -1); - canvas->DrawRect(screenshot_rect, SK_ColorWHITE); - screenshot_rect.Inset(-1, -1, -1, -1); - canvas->DrawRect(screenshot_rect, SK_ColorBLACK); - } -} - -bool PartialScreenshotView::OnMousePressed(const ui::MouseEvent& event) { - // Prevent moving across displays during drag. Capturing a screenshot across - // the displays is not supported yet. - // TODO(mukai): remove this restriction. - internal::MouseCursorEventFilter* mouse_cursor_filter = - Shell::GetInstance()->mouse_cursor_filter(); - mouse_cursor_filter->set_mouse_warp_mode( - internal::MouseCursorEventFilter::WARP_NONE); - OnSelectionStarted(event.location()); - return true; -} - -bool PartialScreenshotView::OnMouseDragged(const ui::MouseEvent& event) { - OnSelectionChanged(event.location()); - return true; -} - -bool PartialScreenshotView::OnMouseWheel(const ui::MouseWheelEvent& event) { - // Do nothing but do not propagate events futhermore. - return true; -} - -void PartialScreenshotView::OnMouseReleased(const ui::MouseEvent& event) { - OnSelectionFinished(); -} - -void PartialScreenshotView::OnMouseCaptureLost() { - is_dragging_ = false; - OnSelectionFinished(); -} - -void PartialScreenshotView::OnGestureEvent(ui::GestureEvent* event) { - switch(event->type()) { - case ui::ET_GESTURE_TAP_DOWN: - OnSelectionStarted(event->location()); - break; - case ui::ET_GESTURE_SCROLL_UPDATE: - OnSelectionChanged(event->location()); - break; - case ui::ET_GESTURE_SCROLL_END: - case ui::ET_SCROLL_FLING_START: - OnSelectionFinished(); - break; - default: - break; - } - - event->SetHandled(); -} - -} // namespace ash diff --git a/chromium/ash/wm/partial_screenshot_view.h b/chromium/ash/wm/partial_screenshot_view.h deleted file mode 100644 index 8d799e3132b..00000000000 --- a/chromium/ash/wm/partial_screenshot_view.h +++ /dev/null @@ -1,75 +0,0 @@ -// 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_PARTIAL_SCREENSHOT_VIEW_H_ -#define ASH_WM_PARTIAL_SCREENSHOT_VIEW_H_ - -#include <vector> - -#include "ash/ash_export.h" -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "ui/gfx/point.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -class ScreenshotDelegate; - -// The view of taking partial screenshot, i.e.: drawing region -// rectangles during drag, and changing the mouse cursor to indicate -// the current mode. -class ASH_EXPORT PartialScreenshotView : public views::WidgetDelegateView { - public: - // Starts the UI for taking partial screenshot; dragging to select a region. - // PartialScreenshotViews manage their own lifetime so caller must not delete - // the returned PartialScreenshotViews. - static std::vector<PartialScreenshotView*> - StartPartialScreenshot(ScreenshotDelegate* screenshot_delegate); - - private: - FRIEND_TEST_ALL_PREFIXES(PartialScreenshotViewTest, BasicMouse); - FRIEND_TEST_ALL_PREFIXES(PartialScreenshotViewTest, BasicTouch); - - class OverlayDelegate; - - PartialScreenshotView(OverlayDelegate* overlay_delegate, - ScreenshotDelegate* screenshot_delegate); - virtual ~PartialScreenshotView(); - - // Initializes partial screenshot UI widget for |root_window|. - void Init(aura::Window* root_window); - - // Returns the currently selected region. - gfx::Rect GetScreenshotRect() const; - - void OnSelectionStarted(const gfx::Point& position); - void OnSelectionChanged(const gfx::Point& position); - void OnSelectionFinished(); - - // Overridden from views::View: - virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE; - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; - virtual bool OnMouseWheel(const ui::MouseWheelEvent& event) OVERRIDE; - virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; - virtual void OnMouseCaptureLost() OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - bool is_dragging_; - gfx::Point start_position_; - gfx::Point current_position_; - - // The delegate to receive Cancel. No ownership. - OverlayDelegate* overlay_delegate_; - - // ScreenshotDelegate to take the actual screenshot. No ownership. - ScreenshotDelegate* screenshot_delegate_; - - DISALLOW_COPY_AND_ASSIGN(PartialScreenshotView); -}; - -} // namespace ash - -#endif // #ifndef ASH_WM_PARTIAL_SCREENSHOT_VIEW_H_ diff --git a/chromium/ash/wm/partial_screenshot_view_unittest.cc b/chromium/ash/wm/partial_screenshot_view_unittest.cc deleted file mode 100644 index 3605e807f81..00000000000 --- a/chromium/ash/wm/partial_screenshot_view_unittest.cc +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2013 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/partial_screenshot_view.h" - -#include "ash/screenshot_delegate.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/test_screenshot_delegate.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" - -namespace ash { - -class PartialScreenshotViewTest : public test::AshTestBase { - public: - PartialScreenshotViewTest() : view_(NULL) {} - virtual ~PartialScreenshotViewTest() {} - - virtual void SetUp() OVERRIDE { - test::AshTestBase::SetUp(); - std::vector<PartialScreenshotView*> views = - PartialScreenshotView::StartPartialScreenshot(GetScreenshotDelegate()); - ASSERT_EQ(1u, views.size()); - view_ = views[0]; - } - - protected: - PartialScreenshotView* view_; - - private: - DISALLOW_COPY_AND_ASSIGN(PartialScreenshotViewTest); -}; - -TEST_F(PartialScreenshotViewTest, BasicMouse) { - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - - generator.MoveMouseTo(100, 100); - generator.PressLeftButton(); - EXPECT_FALSE(view_->is_dragging_); - EXPECT_EQ("100,100", view_->start_position_.ToString()); - - generator.MoveMouseTo(200, 200); - EXPECT_TRUE(view_->is_dragging_); - EXPECT_EQ("200,200", view_->current_position_.ToString()); - - generator.ReleaseLeftButton(); - EXPECT_FALSE(view_->is_dragging_); - EXPECT_EQ("100,100 100x100", GetScreenshotDelegate()->last_rect().ToString()); - EXPECT_EQ(1, GetScreenshotDelegate()->handle_take_partial_screenshot_count()); -} - -TEST_F(PartialScreenshotViewTest, BasicTouch) { - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - - generator.set_current_location(gfx::Point(100,100)); - generator.GestureTapDownAndUp(gfx::Point(100,100)); - EXPECT_FALSE(view_->is_dragging_); - EXPECT_EQ(0, GetScreenshotDelegate()->handle_take_partial_screenshot_count()); - - generator.PressTouch(); - EXPECT_FALSE(view_->is_dragging_); - EXPECT_EQ("100,100", view_->start_position_.ToString()); - - generator.MoveTouch(gfx::Point(200, 200)); - EXPECT_TRUE(view_->is_dragging_); - EXPECT_EQ("200,200", view_->current_position_.ToString()); - - generator.ReleaseTouch(); - EXPECT_FALSE(view_->is_dragging_); - EXPECT_EQ(1, GetScreenshotDelegate()->handle_take_partial_screenshot_count()); - EXPECT_EQ("100,100 100x100", GetScreenshotDelegate()->last_rect().ToString()); -} - -} // namespace ash diff --git a/chromium/ash/wm/power_button_controller.cc b/chromium/ash/wm/power_button_controller.cc deleted file mode 100644 index c2e3789f1f0..00000000000 --- a/chromium/ash/wm/power_button_controller.cc +++ /dev/null @@ -1,110 +0,0 @@ -// 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/power_button_controller.h" - -#include "ash/ash_switches.h" -#include "ash/session_state_delegate.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/lock_state_controller.h" -#include "ash/wm/session_state_animator.h" -#include "base/command_line.h" -#include "ui/aura/root_window.h" -#include "ui/views/corewm/compound_event_filter.h" - -namespace ash { - -PowerButtonController::PowerButtonController( - LockStateController* controller) - : power_button_down_(false), - lock_button_down_(false), - screen_is_off_(false), - has_legacy_power_button_( - CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAuraLegacyPowerButton)), - controller_(controller) { -} - -PowerButtonController::~PowerButtonController() { -} - -void PowerButtonController::OnScreenBrightnessChanged(double percent) { - screen_is_off_ = percent <= 0.001; -} - -void PowerButtonController::OnPowerButtonEvent( - bool down, const base::TimeTicks& timestamp) { - power_button_down_ = down; - - if (controller_->ShutdownRequested()) - return; - - // Avoid starting the lock/shutdown sequence if the power button is pressed - // while the screen is off (http://crbug.com/128451). - if (screen_is_off_) - return; - - const SessionStateDelegate* session_state_delegate = - Shell::GetInstance()->session_state_delegate(); - if (has_legacy_power_button_) { - // If power button releases won't get reported correctly because we're not - // running on official hardware, just lock the screen or shut down - // immediately. - if (down) { - if (session_state_delegate->CanLockScreen() && - !session_state_delegate->IsScreenLocked() && - !controller_->LockRequested()) { - controller_->StartLockAnimationAndLockImmediately(); - } else { - controller_->RequestShutdown(); - } - } - } else { // !has_legacy_power_button_ - if (down) { - // If we already have a pending request to lock the screen, wait. - if (controller_->LockRequested()) - return; - - if (session_state_delegate->CanLockScreen() && - !session_state_delegate->IsScreenLocked()) { - controller_->StartLockAnimation(true); - } else { - controller_->StartShutdownAnimation(); - } - } else { // Button is up. - if (controller_->CanCancelLockAnimation()) - controller_->CancelLockAnimation(); - else if (controller_->CanCancelShutdownAnimation()) - controller_->CancelShutdownAnimation(); - } - } -} - -void PowerButtonController::OnLockButtonEvent( - bool down, const base::TimeTicks& timestamp) { - lock_button_down_ = down; - - const SessionStateDelegate* session_state_delegate = - Shell::GetInstance()->session_state_delegate(); - if (!session_state_delegate->CanLockScreen() || - session_state_delegate->IsScreenLocked() || - controller_->LockRequested() || - controller_->ShutdownRequested()) { - return; - } - - // Give the power button precedence over the lock button (we don't expect both - // buttons to be present, so this is just making sure that we don't do - // something completely stupid if that assumption changes later). - if (power_button_down_) - return; - - if (down) - controller_->StartLockAnimation(false); - else - controller_->CancelLockAnimation(); -} - -} // namespace ash diff --git a/chromium/ash/wm/power_button_controller.h b/chromium/ash/wm/power_button_controller.h deleted file mode 100644 index 558bf6d0ae1..00000000000 --- a/chromium/ash/wm/power_button_controller.h +++ /dev/null @@ -1,69 +0,0 @@ -// 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_POWER_BUTTON_CONTROLLER_H_ -#define ASH_WM_POWER_BUTTON_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "ash/wm/session_state_animator.h" -#include "base/basictypes.h" - -namespace gfx { -class Rect; -class Size; -} - -namespace ui { -class Layer; -} - -namespace ash { - -namespace test { -class PowerButtonControllerTest; -} - -class LockStateController; - -// Displays onscreen animations and locks or suspends the system in response to -// the power button being pressed or released. -class ASH_EXPORT PowerButtonController { - public: - - explicit PowerButtonController(LockStateController* controller); - virtual ~PowerButtonController(); - - void set_has_legacy_power_button_for_test(bool legacy) { - has_legacy_power_button_ = legacy; - } - - // Called when the current screen brightness changes. - void OnScreenBrightnessChanged(double percent); - - // Called when the power or lock buttons are pressed or released. - void OnPowerButtonEvent(bool down, const base::TimeTicks& timestamp); - void OnLockButtonEvent(bool down, const base::TimeTicks& timestamp); - - private: - friend class test::PowerButtonControllerTest; - - // Are the power or lock buttons currently held? - bool power_button_down_; - bool lock_button_down_; - - // Is the screen currently turned off? - bool screen_is_off_; - - // Was a command-line switch set telling us that we're running on hardware - // that misreports power button releases? - bool has_legacy_power_button_; - - LockStateController* controller_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(PowerButtonController); -}; - -} // namespace ash - -#endif // ASH_WM_POWER_BUTTON_CONTROLLER_H_ diff --git a/chromium/ash/wm/resize_shadow.cc b/chromium/ash/wm/resize_shadow.cc deleted file mode 100644 index cdf573d93b6..00000000000 --- a/chromium/ash/wm/resize_shadow.cc +++ /dev/null @@ -1,110 +0,0 @@ -// 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/resize_shadow.h" - -#include "base/time/time.h" -#include "grit/ash_resources.h" -#include "ui/aura/window.h" -#include "ui/base/hit_test.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/views/corewm/image_grid.h" - -namespace { - -// Final opacity for resize effect. -const float kShadowTargetOpacity = 0.25f; -// Animation time for resize effect in milliseconds. -const int kShadowAnimationDurationMs = 100; - -// Sets up a layer as invisible and fully transparent, without animating. -void InitLayer(ui::Layer* layer) { - layer->SetVisible(false); - layer->SetOpacity(0.f); -} - -// Triggers an opacity animation that will make |layer| become |visible|. -void ShowLayer(ui::Layer* layer, bool visible) { - ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); - settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs)); - layer->SetOpacity(visible ? kShadowTargetOpacity : 0.f); - // Sets the layer visibility after a delay, which will be identical to the - // opacity animation duration. - layer->SetVisible(visible); -} - -} // namespace - -namespace ash { -namespace internal { - -ResizeShadow::ResizeShadow() : last_hit_test_(HTNOWHERE) {} - -ResizeShadow::~ResizeShadow() {} - -void ResizeShadow::Init(aura::Window* window) { - // Set up our image grid and images. - ResourceBundle& res = ResourceBundle::GetSharedInstance(); - image_grid_.reset(new views::corewm::ImageGrid); - image_grid_->SetImages( - &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP_LEFT), - &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP), - &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_TOP_RIGHT), - &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_LEFT), - NULL, - &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_RIGHT), - &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM_LEFT), - &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM), - &res.GetImageNamed(IDR_AURA_RESIZE_SHADOW_BOTTOM_RIGHT)); - // Initialize all layers to invisible/transparent. - InitLayer(image_grid_->top_left_layer()); - InitLayer(image_grid_->top_layer()); - InitLayer(image_grid_->top_right_layer()); - InitLayer(image_grid_->left_layer()); - InitLayer(image_grid_->right_layer()); - InitLayer(image_grid_->bottom_left_layer()); - InitLayer(image_grid_->bottom_layer()); - InitLayer(image_grid_->bottom_right_layer()); - // Add image grid as a child of the window's layer so it follows the window - // as it moves. - window->layer()->Add(image_grid_->layer()); -} - -void ResizeShadow::ShowForHitTest(int hit) { - // Don't start animations unless something changed. - if (hit == last_hit_test_) - return; - last_hit_test_ = hit; - - // Show affected corners. - ShowLayer(image_grid_->top_left_layer(), hit == HTTOPLEFT); - ShowLayer(image_grid_->top_right_layer(), hit == HTTOPRIGHT); - ShowLayer(image_grid_->bottom_left_layer(), hit == HTBOTTOMLEFT); - ShowLayer(image_grid_->bottom_right_layer(), hit == HTBOTTOMRIGHT); - - // Show affected edges. - ShowLayer(image_grid_->top_layer(), - hit == HTTOPLEFT || hit == HTTOP || hit == HTTOPRIGHT); - ShowLayer(image_grid_->left_layer(), - hit == HTTOPLEFT || hit == HTLEFT || hit == HTBOTTOMLEFT); - ShowLayer(image_grid_->right_layer(), - hit == HTTOPRIGHT || hit == HTRIGHT || hit == HTBOTTOMRIGHT); - ShowLayer(image_grid_->bottom_layer(), - hit == HTBOTTOMLEFT || hit == HTBOTTOM || hit == HTBOTTOMRIGHT); -} - -void ResizeShadow::Hide() { - ShowForHitTest(HTNOWHERE); -} - -void ResizeShadow::Layout(const gfx::Rect& content_bounds) { - gfx::Rect local_bounds(content_bounds.size()); - image_grid_->SetContentBounds(local_bounds); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/resize_shadow.h b/chromium/ash/wm/resize_shadow.h deleted file mode 100644 index f61f393b572..00000000000 --- a/chromium/ash/wm/resize_shadow.h +++ /dev/null @@ -1,68 +0,0 @@ -// 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_RESIZE_SHADOW_H_ -#define ASH_WM_RESIZE_SHADOW_H_ - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" - -namespace aura { -class Window; -} -namespace gfx { -class Rect; -} -namespace ui { -class Layer; -} -namespace views { -namespace corewm { -class ImageGrid; -} -} - -namespace ash { -namespace internal { - -// A class to render the resize edge effect when the user moves their mouse -// over a sizing edge. This is just a visual effect; the actual resize is -// handled by the EventFilter. -class ResizeShadow { - public: - ResizeShadow(); - ~ResizeShadow(); - - // Initializes the resize effect layers for a given |window|. - void Init(aura::Window* window); - - // Shows resize effects for one or more edges based on a |hit_test| code, such - // as HTRIGHT or HTBOTTOMRIGHT. - void ShowForHitTest(int hit_test); - - // Hides all resize effects. - void Hide(); - - // Updates the effect positions based on the |bounds| of the window. - void Layout(const gfx::Rect& bounds); - - int GetLastHitTestForTest() const { - return last_hit_test_; - } - - private: - // Images for the shadow effect. - scoped_ptr<views::corewm::ImageGrid> image_grid_; - - // Hit test value from last call to ShowForHitTest(). Used to prevent - // repeatedly triggering the same animations for the same hit. - int last_hit_test_; - - DISALLOW_COPY_AND_ASSIGN(ResizeShadow); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_RESIZE_SHADOW_H_ diff --git a/chromium/ash/wm/resize_shadow_and_cursor_unittest.cc b/chromium/ash/wm/resize_shadow_and_cursor_unittest.cc deleted file mode 100644 index f60a0308f87..00000000000 --- a/chromium/ash/wm/resize_shadow_and_cursor_unittest.cc +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright 2013 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/ash_constants.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/cursor_manager_test_api.h" -#include "ash/wm/custom_frame_view_ash.h" -#include "ash/wm/resize_shadow.h" -#include "ash/wm/resize_shadow_controller.h" -#include "ash/wm/window_state.h" -#include "base/bind.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/base/cursor/cursor.h" -#include "ui/base/hit_test.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -namespace test { - -namespace { - -// views::WidgetDelegate which uses ash::CustomFrameViewAsh. -class TestWidgetDelegate : public views::WidgetDelegateView { - public: - TestWidgetDelegate() {} - virtual ~TestWidgetDelegate() {} - - // views::WidgetDelegateView overrides: - virtual bool CanResize() const OVERRIDE { - return true; - } - virtual bool CanMaximize() const OVERRIDE { - return true; - } - virtual views::NonClientFrameView* CreateNonClientFrameView( - views::Widget* widget) OVERRIDE { - return new ash::CustomFrameViewAsh(widget); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); -}; - -} // namespace - -// The test tests that the mouse cursor is changed and that the resize shadows -// are shown when the mouse is hovered over the window edge. -class ResizeShadowAndCursorTest : public AshTestBase { - public: - ResizeShadowAndCursorTest() {} - virtual ~ResizeShadowAndCursorTest() {} - - // AshTestBase override: - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - - views::Widget* widget(views::Widget::CreateWindowWithContextAndBounds( - new TestWidgetDelegate(), CurrentContext(), gfx::Rect(0, 0, 100, 100))); - widget->Show(); - window_ = widget->GetNativeView(); - - // Add a child window to |window_| in order to properly test that the resize - // handles and the resize shadows are shown when the mouse is - // ash::kResizeInsideBoundsSize inside of |window_|'s edges. - aura::Window* child = CreateTestWindowInShell( - SK_ColorWHITE, 0, gfx::Rect(0, 10, 100, 90)); - window_->AddChild(child); - } - - // Returns the hit test code if there is a resize shadow. Returns HTNOWHERE if - // there is no resize shadow. - int ResizeShadowHitTest() const { - ash::internal::ResizeShadow* resize_shadow = - ash::Shell::GetInstance()->resize_shadow_controller()-> - GetShadowForWindowForTest(window_); - return resize_shadow ? resize_shadow->GetLastHitTestForTest() : HTNOWHERE; - } - - // Returns true if there is a resize shadow. - bool HasResizeShadow() const { - return ResizeShadowHitTest() != HTNOWHERE; - } - - // Returns the current cursor type. - int GetCurrentCursorType() const { - CursorManagerTestApi test_api(ash::Shell::GetInstance()->cursor_manager()); - return test_api.GetCurrentCursor().native_type(); - } - - // Called for each step of a scroll sequence initiated at the bottom right - // corner of |window_|. Tests whether the resize shadow is shown. - void ProcessBottomRightResizeGesture(ui::EventType type, - const gfx::Vector2dF& delta) { - if (type == ui::ET_GESTURE_SCROLL_END) { - // After gesture scroll ends, there should be no resize shadow. - EXPECT_FALSE(HasResizeShadow()); - } else { - EXPECT_EQ(HTBOTTOMRIGHT, ResizeShadowHitTest()); - } - } - - aura::Window* window() { - return window_; - } - - private: - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(ResizeShadowAndCursorTest); -}; - -// Test whether the resize shadows are visible and the cursor type based on the -// mouse's position. -TEST_F(ResizeShadowAndCursorTest, MouseHover) { - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - ASSERT_TRUE(ash::wm::GetWindowState(window())->IsNormalShowState()); - - generator.MoveMouseTo(50, 50); - EXPECT_FALSE(HasResizeShadow()); - EXPECT_EQ(ui::kCursorNull, GetCurrentCursorType()); - - generator.MoveMouseTo(gfx::Point(50, 0)); - EXPECT_EQ(HTTOP, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorNorthResize, GetCurrentCursorType()); - - generator.MoveMouseTo(50, 50); - EXPECT_FALSE(HasResizeShadow()); - EXPECT_EQ(ui::kCursorNull, GetCurrentCursorType()); - - generator.MoveMouseTo(100, 100); - EXPECT_EQ(HTBOTTOMRIGHT, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorSouthEastResize, GetCurrentCursorType()); - - generator.MoveMouseTo(50, 100); - EXPECT_EQ(HTBOTTOM, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorSouthResize, GetCurrentCursorType()); - - generator.MoveMouseTo(50, 100 + ash::kResizeOutsideBoundsSize - 1); - EXPECT_EQ(HTBOTTOM, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorSouthResize, GetCurrentCursorType()); - - generator.MoveMouseTo(50, 100 + ash::kResizeOutsideBoundsSize + 10); - EXPECT_FALSE(HasResizeShadow()); - EXPECT_EQ(ui::kCursorNull, GetCurrentCursorType()); - - generator.MoveMouseTo(50, 100 - ash::kResizeInsideBoundsSize); - EXPECT_EQ(HTBOTTOM, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorSouthResize, GetCurrentCursorType()); - - generator.MoveMouseTo(50, 100 - ash::kResizeInsideBoundsSize - 10); - EXPECT_FALSE(HasResizeShadow()); - EXPECT_EQ(ui::kCursorNull, GetCurrentCursorType()); -} - -// Test that the resize shadows stay visible and that the cursor stays the same -// as long as a user is resizing a window. -TEST_F(ResizeShadowAndCursorTest, MouseDrag) { - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - ASSERT_TRUE(ash::wm::GetWindowState(window())->IsNormalShowState()); - gfx::Size initial_size(window()->bounds().size()); - - generator.MoveMouseTo(100, 50); - generator.PressLeftButton(); - EXPECT_EQ(HTRIGHT, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorEastResize, GetCurrentCursorType()); - - generator.MoveMouseTo(110, 50); - EXPECT_EQ(HTRIGHT, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorEastResize, GetCurrentCursorType()); - - generator.ReleaseLeftButton(); - EXPECT_EQ(HTRIGHT, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorEastResize, GetCurrentCursorType()); - - gfx::Size new_size(window()->bounds().size()); - EXPECT_NE(new_size.ToString(), initial_size.ToString()); -} - -// Test that the resize shadows stay visible while resizing a window via touch. -TEST_F(ResizeShadowAndCursorTest, Touch) { - ASSERT_TRUE(ash::wm::GetWindowState(window())->IsNormalShowState()); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - - int start = 100 + ash::kResizeOutsideBoundsSize - 1; - generator.GestureScrollSequenceWithCallback( - gfx::Point(start, start), - gfx::Point(start + 50, start + 50), - base::TimeDelta::FromMilliseconds(100), - 3, - base::Bind(&ResizeShadowAndCursorTest::ProcessBottomRightResizeGesture, - base::Unretained(this))); -} - -// Test that the resize shadows are not visible and that the default cursor is -// used when the window is maximized. -TEST_F(ResizeShadowAndCursorTest, MaximizeRestore) { - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - ASSERT_TRUE(ash::wm::GetWindowState(window())->IsNormalShowState()); - - generator.MoveMouseTo(100, 50); - EXPECT_EQ(HTRIGHT, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorEastResize, GetCurrentCursorType()); - generator.MoveMouseTo(100 - ash::kResizeInsideBoundsSize, 50); - EXPECT_EQ(HTRIGHT, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorEastResize, GetCurrentCursorType()); - - ash::wm::GetWindowState(window())->Maximize(); - gfx::Rect bounds(window()->GetBoundsInRootWindow()); - gfx::Point right_center(bounds.right() - 1, - (bounds.y() + bounds.bottom()) / 2); - generator.MoveMouseTo(right_center); - EXPECT_FALSE(HasResizeShadow()); - EXPECT_EQ(ui::kCursorNull, GetCurrentCursorType()); - - ash::wm::GetWindowState(window())->Restore(); - generator.MoveMouseTo(100, 50); - EXPECT_EQ(HTRIGHT, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorEastResize, GetCurrentCursorType()); - generator.MoveMouseTo(100 - ash::kResizeInsideBoundsSize, 50); - EXPECT_EQ(HTRIGHT, ResizeShadowHitTest()); - EXPECT_EQ(ui::kCursorEastResize, GetCurrentCursorType()); -} - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/resize_shadow_controller.cc b/chromium/ash/wm/resize_shadow_controller.cc deleted file mode 100644 index 85778d337a8..00000000000 --- a/chromium/ash/wm/resize_shadow_controller.cc +++ /dev/null @@ -1,74 +0,0 @@ -// 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/resize_shadow_controller.h" - -#include <utility> - -#include "ash/wm/resize_shadow.h" -#include "ui/aura/window.h" - -namespace ash { -namespace internal { - -ResizeShadowController::ResizeShadowController() { -} - -ResizeShadowController::~ResizeShadowController() { - for (WindowShadowMap::const_iterator it = window_shadows_.begin(); - it != window_shadows_.end(); ++it) { - it->first->RemoveObserver(this); - } -} - -void ResizeShadowController::ShowShadow(aura::Window* window, int hit_test) { - ResizeShadow* shadow = GetShadowForWindow(window); - if (!shadow) - shadow = CreateShadow(window); - shadow->ShowForHitTest(hit_test); -} - -void ResizeShadowController::HideShadow(aura::Window* window) { - ResizeShadow* shadow = GetShadowForWindow(window); - if (shadow) - shadow->Hide(); -} - -ResizeShadow* ResizeShadowController::GetShadowForWindowForTest( - aura::Window* window) { - return GetShadowForWindow(window); -} - -void ResizeShadowController::OnWindowBoundsChanged( - aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - ResizeShadow* shadow = GetShadowForWindow(window); - if (shadow) - shadow->Layout(new_bounds); -} - -void ResizeShadowController::OnWindowDestroyed(aura::Window* window) { - window_shadows_.erase(window); -} - -ResizeShadow* ResizeShadowController::CreateShadow(aura::Window* window) { - linked_ptr<ResizeShadow> shadow(new ResizeShadow()); - window_shadows_.insert(std::make_pair(window, shadow)); - // Attach the layers to this window. - shadow->Init(window); - // Ensure initial bounds are correct. - shadow->Layout(window->bounds()); - // Watch for bounds changes. - window->AddObserver(this); - return shadow.get(); -} - -ResizeShadow* ResizeShadowController::GetShadowForWindow(aura::Window* window) { - WindowShadowMap::const_iterator it = window_shadows_.find(window); - return it != window_shadows_.end() ? it->second.get() : NULL; -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/resize_shadow_controller.h b/chromium/ash/wm/resize_shadow_controller.h deleted file mode 100644 index 1eccf4c8364..00000000000 --- a/chromium/ash/wm/resize_shadow_controller.h +++ /dev/null @@ -1,65 +0,0 @@ -// 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_RESIZE_SHADOW_CONTROLLER_H_ -#define ASH_WM_RESIZE_SHADOW_CONTROLLER_H_ - -#include <map> - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/linked_ptr.h" -#include "ui/aura/window_observer.h" - -namespace aura { -class Window; -} - -namespace ash { -namespace internal { - -class ResizeShadow; - -// ResizeShadowController observes changes to resizable windows and shows -// a resize handle visual effect when the cursor is near the edges. -class ASH_EXPORT ResizeShadowController : public aura::WindowObserver { - public: - ResizeShadowController(); - virtual ~ResizeShadowController(); - - // Shows the appropriate shadow for a given |window| and |hit_test| location. - void ShowShadow(aura::Window* window, int hit_test); - - // Hides the shadow for a |window|, if it has one. - void HideShadow(aura::Window* window); - - ResizeShadow* GetShadowForWindowForTest(aura::Window* window); - - // aura::WindowObserver overrides: - virtual void OnWindowBoundsChanged( - aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; - - private: - typedef std::map<aura::Window*, linked_ptr<ResizeShadow> > WindowShadowMap; - - // Creates a shadow for a given window and returns it. |window_shadows_| - // owns the memory. - ResizeShadow* CreateShadow(aura::Window* window); - - // Returns the resize shadow for |window| or NULL if no shadow exists. - ResizeShadow* GetShadowForWindow(aura::Window* window); - - WindowShadowMap window_shadows_; - - DISALLOW_COPY_AND_ASSIGN(ResizeShadowController); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_RESIZE_SHADOW_CONTROLLER_H_ diff --git a/chromium/ash/wm/root_window_layout_manager.cc b/chromium/ash/wm/root_window_layout_manager.cc deleted file mode 100644 index ef1689e38f6..00000000000 --- a/chromium/ash/wm/root_window_layout_manager.cc +++ /dev/null @@ -1,78 +0,0 @@ -// 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/root_window_layout_manager.h" - -#include "ash/desktop_background/desktop_background_widget_controller.h" -#include "ash/root_window_controller.h" -#include "ui/aura/root_window.h" -#include "ui/compositor/layer.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -//////////////////////////////////////////////////////////////////////////////// -// RootWindowLayoutManager, public: - -RootWindowLayoutManager::RootWindowLayoutManager(aura::Window* owner) - : owner_(owner) { -} - -RootWindowLayoutManager::~RootWindowLayoutManager() { -} - - -//////////////////////////////////////////////////////////////////////////////// -// RootWindowLayoutManager, aura::LayoutManager implementation: - -void RootWindowLayoutManager::OnWindowResized() { - gfx::Rect fullscreen_bounds = - gfx::Rect(owner_->bounds().width(), owner_->bounds().height()); - - // Resize both our immediate children (the containers-of-containers animated - // by PowerButtonController) and their children (the actual containers). - aura::Window::Windows::const_iterator i; - for (i = owner_->children().begin(); i != owner_->children().end(); ++i) { - (*i)->SetBounds(fullscreen_bounds); - aura::Window::Windows::const_iterator j; - for (j = (*i)->children().begin(); j != (*i)->children().end(); ++j) - (*j)->SetBounds(fullscreen_bounds); - } - RootWindowController* root_window_controller = - GetRootWindowController(owner_); - DesktopBackgroundWidgetController* background = - root_window_controller->wallpaper_controller(); - - if (!background && root_window_controller->animating_wallpaper_controller()) { - background = root_window_controller->animating_wallpaper_controller()-> - GetController(false); - } - if (background) - background->SetBounds(fullscreen_bounds); -} - -void RootWindowLayoutManager::OnWindowAddedToLayout(aura::Window* child) { -} - -void RootWindowLayoutManager::OnWillRemoveWindowFromLayout( - aura::Window* child) { -} - -void RootWindowLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { -} - -void RootWindowLayoutManager::OnChildWindowVisibilityChanged( - aura::Window* child, - bool visible) { -} - -void RootWindowLayoutManager::SetChildBounds( - aura::Window* child, - const gfx::Rect& requested_bounds) { - SetChildBoundsDirect(child, requested_bounds); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/root_window_layout_manager.h b/chromium/ash/wm/root_window_layout_manager.h deleted file mode 100644 index 708e306b75b..00000000000 --- a/chromium/ash/wm/root_window_layout_manager.h +++ /dev/null @@ -1,56 +0,0 @@ -// 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_ROOT_WINDOW_LAYOUT_MANAGER_H_ -#define ASH_WM_ROOT_WINDOW_LAYOUT_MANAGER_H_ - -#include "ash/shell_window_ids.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/layout_manager.h" - -namespace aura { -class Window; -} -namespace gfx { -class Rect; -} -namespace ui { -class Layer; -} -namespace views { -class Widget; -} - -namespace ash { -namespace internal { - -// A layout manager for the root window. -// Resizes all of its immediate children to fill the bounds of the root window. -class RootWindowLayoutManager : public aura::LayoutManager { - public: - explicit RootWindowLayoutManager(aura::Window* owner); - virtual ~RootWindowLayoutManager(); - - // Overridden from aura::LayoutManager: - virtual void OnWindowResized() OVERRIDE; - virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; - virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; - virtual void OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) OVERRIDE; - virtual void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) OVERRIDE; - - private: - aura::Window* owner_; - - DISALLOW_COPY_AND_ASSIGN(RootWindowLayoutManager); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_ROOT_WINDOW_LAYOUT_MANAGER_H_ diff --git a/chromium/ash/wm/screen_dimmer.cc b/chromium/ash/wm/screen_dimmer.cc deleted file mode 100644 index b12566e7575..00000000000 --- a/chromium/ash/wm/screen_dimmer.cc +++ /dev/null @@ -1,69 +0,0 @@ -// 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/screen_dimmer.h" - -#include "ash/shell.h" -#include "base/time/time.h" -#include "ui/aura/root_window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/size.h" - -namespace ash { -namespace internal { - -namespace { - -// Opacity for |dimming_layer_| when it's dimming the screen. -const float kDimmingLayerOpacity = 0.4f; - -// Duration for dimming animations, in milliseconds. -const int kDimmingTransitionMs = 200; - -} // namespace - -ScreenDimmer::ScreenDimmer(aura::Window* root_window) - : root_window_(root_window), - currently_dimming_(false) { - root_window_->AddObserver(this); -} - -ScreenDimmer::~ScreenDimmer() { - root_window_->RemoveObserver(this); -} - -void ScreenDimmer::SetDimming(bool should_dim) { - if (should_dim == currently_dimming_) - return; - - if (!dimming_layer_) { - dimming_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); - dimming_layer_->SetColor(SK_ColorBLACK); - dimming_layer_->SetOpacity(0.0f); - ui::Layer* root_layer = root_window_->layer(); - dimming_layer_->SetBounds(root_layer->bounds()); - root_layer->Add(dimming_layer_.get()); - root_layer->StackAtTop(dimming_layer_.get()); - } - - currently_dimming_ = should_dim; - - ui::ScopedLayerAnimationSettings scoped_settings( - dimming_layer_->GetAnimator()); - scoped_settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kDimmingTransitionMs)); - dimming_layer_->SetOpacity(should_dim ? kDimmingLayerOpacity : 0.0f); -} - -void ScreenDimmer::OnWindowBoundsChanged(aura::Window* root, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - if (dimming_layer_) - dimming_layer_->SetBounds(gfx::Rect(root->bounds().size())); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/screen_dimmer.h b/chromium/ash/wm/screen_dimmer.h deleted file mode 100644 index abbb0a5b1ab..00000000000 --- a/chromium/ash/wm/screen_dimmer.h +++ /dev/null @@ -1,71 +0,0 @@ -// 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_SCREEN_DIMMER_H_ -#define ASH_WM_SCREEN_DIMMER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/window_observer.h" - -namespace ui { -class Layer; -} - -namespace ash { -namespace internal { - -// ScreenDimmer displays a partially-opaque layer above everything -// else in the root window to darken the display. It shouldn't be used -// for long-term brightness adjustments due to performance -// considerations -- it's only intended for cases where we want to -// briefly dim the screen (e.g. to indicate to the user that we're -// about to suspend a machine that lacks an internal backlight that -// can be adjusted). -class ASH_EXPORT ScreenDimmer : public aura::WindowObserver { - public: - class TestApi { - public: - explicit TestApi(ScreenDimmer* dimmer) : dimmer_(dimmer) {} - - ui::Layer* layer() { return dimmer_->dimming_layer_.get(); } - - private: - ScreenDimmer* dimmer_; // not owned - - DISALLOW_COPY_AND_ASSIGN(TestApi); - }; - - explicit ScreenDimmer(aura::Window* root_window); - virtual ~ScreenDimmer(); - - // Dim or undim the root window. - void SetDimming(bool should_dim); - - // aura::WindowObserver overrides: - virtual void OnWindowBoundsChanged(aura::Window* root_window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - - private: - friend class TestApi; - - aura::Window* root_window_; - - // Partially-opaque layer that's stacked above all of the root window's - // children and used to dim the screen. NULL until the first time we dim. - scoped_ptr<ui::Layer> dimming_layer_; - - // Are we currently dimming the screen? - bool currently_dimming_; - - DISALLOW_COPY_AND_ASSIGN(ScreenDimmer); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_SCREEN_DIMMER_H_ diff --git a/chromium/ash/wm/screen_dimmer_unittest.cc b/chromium/ash/wm/screen_dimmer_unittest.cc deleted file mode 100644 index a87c71bf088..00000000000 --- a/chromium/ash/wm/screen_dimmer_unittest.cc +++ /dev/null @@ -1,79 +0,0 @@ -// 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/screen_dimmer.h" - -#include "ash/root_window_controller.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/root_window.h" -#include "ui/compositor/layer.h" - -namespace ash { -namespace test { - -class ScreenDimmerTest : public AshTestBase { - public: - ScreenDimmerTest() : dimmer_(NULL) {} - virtual ~ScreenDimmerTest() {} - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - dimmer_ = Shell::GetPrimaryRootWindowController()->screen_dimmer(); - test_api_.reset(new internal::ScreenDimmer::TestApi(dimmer_)); - } - - protected: - internal::ScreenDimmer* dimmer_; // not owned - - scoped_ptr<internal::ScreenDimmer::TestApi> test_api_; - - private: - DISALLOW_COPY_AND_ASSIGN(ScreenDimmerTest); -}; - -TEST_F(ScreenDimmerTest, DimAndUndim) { - // Don't create a layer until we need to. - EXPECT_TRUE(test_api_->layer() == NULL); - dimmer_->SetDimming(false); - EXPECT_TRUE(test_api_->layer() == NULL); - - // When we enable dimming, the layer should be created and stacked at the top - // of the root's children. - dimmer_->SetDimming(true); - ASSERT_TRUE(test_api_->layer() != NULL); - ui::Layer* root_layer = Shell::GetPrimaryRootWindow()->layer(); - ASSERT_TRUE(!root_layer->children().empty()); - EXPECT_EQ(test_api_->layer(), root_layer->children().back()); - EXPECT_TRUE(test_api_->layer()->visible()); - EXPECT_GT(test_api_->layer()->GetTargetOpacity(), 0.0f); - - // When we disable dimming, the layer should be animated back to full - // transparency. - dimmer_->SetDimming(false); - ASSERT_TRUE(test_api_->layer() != NULL); - EXPECT_TRUE(test_api_->layer()->visible()); - EXPECT_FLOAT_EQ(0.0f, test_api_->layer()->GetTargetOpacity()); -} - -TEST_F(ScreenDimmerTest, ResizeLayer) { - // The dimming layer should be initially sized to cover the root window. - dimmer_->SetDimming(true); - ui::Layer* dimming_layer = test_api_->layer(); - ASSERT_TRUE(dimming_layer != NULL); - ui::Layer* root_layer = Shell::GetPrimaryRootWindow()->layer(); - EXPECT_EQ(gfx::Rect(root_layer->bounds().size()).ToString(), - dimming_layer->bounds().ToString()); - - // When we resize the root window, the dimming layer should be resized to - // match. - gfx::Size kNewSize(400, 300); - Shell::GetPrimaryRootWindow()->GetDispatcher()->SetHostSize(kNewSize); - EXPECT_EQ(kNewSize.ToString(), dimming_layer->bounds().size().ToString()); -} - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/session_state_animator.cc b/chromium/ash/wm/session_state_animator.cc deleted file mode 100644 index de8cd42d4da..00000000000 --- a/chromium/ash/wm/session_state_animator.cc +++ /dev/null @@ -1,617 +0,0 @@ -// 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/session_state_animator.h" - -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/window_animations.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/compositor/layer_animation_observer.h" -#include "ui/compositor/layer_animation_sequence.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -namespace { - -// Slightly-smaller size that we scale the screen down to for the pre-lock and -// pre-shutdown states. -const float kSlowCloseSizeRatio = 0.95f; - -// Maximum opacity of white layer when animating pre-shutdown state. -const float kPartialFadeRatio = 0.3f; - -// Minimum size. Not zero as it causes numeric issues. -const float kMinimumScale = 1e-4f; - -// Returns the transform that should be applied to containers for the slow-close -// animation. -gfx::Transform GetSlowCloseTransform() { - gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size(); - gfx::Transform transform; - transform.Translate( - floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.width() + 0.5), - floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.height() + 0.5)); - transform.Scale(kSlowCloseSizeRatio, kSlowCloseSizeRatio); - return transform; -} - -// Returns the transform that should be applied to containers for the fast-close -// animation. -gfx::Transform GetFastCloseTransform() { - gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size(); - gfx::Transform transform; - transform.Translate(floor(0.5 * root_size.width() + 0.5), - floor(0.5 * root_size.height() + 0.5)); - transform.Scale(kMinimumScale, kMinimumScale); - return transform; -} - -// Slowly shrinks |window| to a slightly-smaller size. -void StartSlowCloseAnimationForWindow(aura::Window* window, - base::TimeDelta duration, - ui::LayerAnimationObserver* observer) { - ui::LayerAnimator* animator = window->layer()->GetAnimator(); - animator->set_preemption_strategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateTransformElement( - GetSlowCloseTransform(), - duration)); - if (observer) - sequence->AddObserver(observer); - animator->StartAnimation(sequence); -} - -// Quickly undoes the effects of the slow-close animation on |window|. -void StartUndoSlowCloseAnimationForWindow( - aura::Window* window, - base::TimeDelta duration, - ui::LayerAnimationObserver* observer) { - ui::LayerAnimator* animator = window->layer()->GetAnimator(); - animator->set_preemption_strategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateTransformElement( - gfx::Transform(), - duration)); - if (observer) - sequence->AddObserver(observer); - animator->StartAnimation(sequence); -} - -// Quickly shrinks |window| down to a point in the center of the screen and -// fades it out to 0 opacity. -void StartFastCloseAnimationForWindow(aura::Window* window, - base::TimeDelta duration, - ui::LayerAnimationObserver* observer) { - ui::LayerAnimator* animator = window->layer()->GetAnimator(); - animator->set_preemption_strategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - animator->StartAnimation( - new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateTransformElement( - GetFastCloseTransform(), duration))); - ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateOpacityElement(0.0, duration)); - if (observer) - sequence->AddObserver(observer); - animator->StartAnimation(sequence); -} - -// Fades |window| to |target_opacity| over |duration|. -void StartPartialFadeAnimation(aura::Window* window, - float target_opacity, - base::TimeDelta duration, - ui::LayerAnimationObserver* observer) { - ui::LayerAnimator* animator = window->layer()->GetAnimator(); - animator->set_preemption_strategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateOpacityElement( - target_opacity, duration)); - if (observer) - sequence->AddObserver(observer); - animator->StartAnimation(sequence); -} - -// Fades |window| to |opacity| over |duration|. -void StartOpacityAnimationForWindow(aura::Window* window, - float opacity, - base::TimeDelta duration, - ui::LayerAnimationObserver* observer) { - ui::LayerAnimator* animator = window->layer()->GetAnimator(); - animator->set_preemption_strategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateOpacityElement(opacity, duration)); - if (observer) - sequence->AddObserver(observer); - animator->StartAnimation(sequence); -} - -// Makes |window| fully transparent instantaneously. -void HideWindowImmediately(aura::Window* window, - ui::LayerAnimationObserver* observer) { - window->layer()->SetOpacity(0.0); - if (observer) - observer->OnLayerAnimationEnded(NULL); -} - -// Restores |window| to its original position and scale and full opacity -// instantaneously. -void RestoreWindow(aura::Window* window, ui::LayerAnimationObserver* observer) { - window->layer()->SetTransform(gfx::Transform()); - window->layer()->SetOpacity(1.0); - if (observer) - observer->OnLayerAnimationEnded(NULL); -} - -void HideWindow(aura::Window* window, - base::TimeDelta duration, - bool above, - ui::LayerAnimationObserver* observer) { - ui::Layer* layer = window->layer(); - ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); - - settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - settings.SetTransitionDuration(duration); - - settings.SetTweenType(gfx::Tween::EASE_OUT); - SetTransformForScaleAnimation(layer, - above ? LAYER_SCALE_ANIMATION_ABOVE : LAYER_SCALE_ANIMATION_BELOW); - - settings.SetTweenType(gfx::Tween::EASE_IN_OUT); - layer->SetOpacity(0.0f); - - // After the animation completes snap the transform back to the identity, - // otherwise any one that asks for screen bounds gets a slightly scaled - // version. - settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION); - settings.SetTransitionDuration(base::TimeDelta()); - layer->SetTransform(gfx::Transform()); - - // A bit of a dirty trick: we need to catch the end of the animation we don't - // control. So we use two facts we know: which animator will be used and the - // target opacity to add "Do nothing" animation sequence. - // Unfortunately, we can not just use empty LayerAnimationSequence, because - // it does not call NotifyEnded(). - if (observer) { - ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateOpacityElement( - 0.0, base::TimeDelta())); - sequence->AddObserver(observer); - layer->GetAnimator()->ScheduleAnimation(sequence); - } -} - -// Animates |window| to identity transform and full opacity over |duration|. -void TransformWindowToBaseState(aura::Window* window, - base::TimeDelta duration, - ui::LayerAnimationObserver* observer) { - ui::Layer* layer = window->layer(); - ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); - - // Animate to target values. - settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - settings.SetTransitionDuration(duration); - - settings.SetTweenType(gfx::Tween::EASE_OUT); - layer->SetTransform(gfx::Transform()); - - settings.SetTweenType(gfx::Tween::EASE_IN_OUT); - layer->SetOpacity(1.0f); - - // A bit of a dirty trick: we need to catch the end of the animation we don't - // control. So we use two facts we know: which animator will be used and the - // target opacity to add "Do nothing" animation sequence. - // Unfortunately, we can not just use empty LayerAnimationSequence, because - // it does not call NotifyEnded(). - if (observer) { - ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateOpacityElement( - 1.0, base::TimeDelta())); - sequence->AddObserver(observer); - layer->GetAnimator()->ScheduleAnimation(sequence); - } -} - -void ShowWindow(aura::Window* window, - base::TimeDelta duration, - bool above, - ui::LayerAnimationObserver* observer) { - ui::Layer* layer = window->layer(); - ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); - - // Set initial state of animation - settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - settings.SetTransitionDuration(base::TimeDelta()); - SetTransformForScaleAnimation(layer, - above ? LAYER_SCALE_ANIMATION_ABOVE : LAYER_SCALE_ANIMATION_BELOW); - - TransformWindowToBaseState(window, duration, observer); -} - -// Starts grayscale/brightness animation for |window| over |duration|. Target -// value for both grayscale and brightness are specified by |target|. -void StartGrayscaleBrightnessAnimationForWindow( - aura::Window* window, - float target, - base::TimeDelta duration, - gfx::Tween::Type tween_type, - ui::LayerAnimationObserver* observer) { - ui::LayerAnimator* animator = window->layer()->GetAnimator(); - - scoped_ptr<ui::LayerAnimationSequence> brightness_sequence( - new ui::LayerAnimationSequence()); - scoped_ptr<ui::LayerAnimationSequence> grayscale_sequence( - new ui::LayerAnimationSequence()); - - scoped_ptr<ui::LayerAnimationElement> brightness_element( - ui::LayerAnimationElement::CreateBrightnessElement( - target, duration)); - brightness_element->set_tween_type(tween_type); - brightness_sequence->AddElement(brightness_element.release()); - - scoped_ptr<ui::LayerAnimationElement> grayscale_element( - ui::LayerAnimationElement::CreateGrayscaleElement( - target, duration)); - grayscale_element->set_tween_type(tween_type); - grayscale_sequence->AddElement(grayscale_element.release()); - - std::vector<ui::LayerAnimationSequence*> animations; - animations.push_back(brightness_sequence.release()); - animations.push_back(grayscale_sequence.release()); - - if (observer) - animations[0]->AddObserver(observer); - - animator->set_preemption_strategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - - animator->StartTogether(animations); -} - -// Animation observer that will drop animated foreground once animation is -// finished. It is used in when undoing shutdown animation. -class CallbackAnimationObserver : public ui::LayerAnimationObserver { - public: - explicit CallbackAnimationObserver(base::Callback<void(void)> &callback) - : callback_(callback) { - } - virtual ~CallbackAnimationObserver() { - } - - private: - // Overridden from ui::LayerAnimationObserver: - virtual void OnLayerAnimationEnded(ui::LayerAnimationSequence* seq) - OVERRIDE { - // Drop foreground once animation is over. - callback_.Run(); - delete this; - } - - virtual void OnLayerAnimationAborted(ui::LayerAnimationSequence* seq) - OVERRIDE { - // Drop foreground once animation is over. - callback_.Run(); - delete this; - } - - virtual void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq) - OVERRIDE {} - - base::Callback<void(void)> callback_; - - DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver); -}; - - -bool IsLayerAnimated(ui::Layer* layer, - SessionStateAnimator::AnimationType type) { - switch (type) { - case SessionStateAnimator::ANIMATION_PARTIAL_CLOSE: - if (layer->GetTargetTransform() != GetSlowCloseTransform()) - return false; - break; - case SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE: - if (layer->GetTargetTransform() != gfx::Transform()) - return false; - break; - case SessionStateAnimator::ANIMATION_FULL_CLOSE: - if (layer->GetTargetTransform() != GetFastCloseTransform() || - layer->GetTargetOpacity() > 0.0001) - return false; - break; - case SessionStateAnimator::ANIMATION_FADE_IN: - if (layer->GetTargetOpacity() < 0.9999) - return false; - break; - case SessionStateAnimator::ANIMATION_FADE_OUT: - if (layer->GetTargetOpacity() > 0.0001) - return false; - break; - case SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY: - if (layer->GetTargetOpacity() > 0.0001) - return false; - break; - case SessionStateAnimator::ANIMATION_RESTORE: - if (layer->opacity() < 0.9999 || layer->transform() != gfx::Transform()) - return false; - break; - case SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS: - if ((layer->GetTargetBrightness() < 0.9999) || - (layer->GetTargetGrayscale() < 0.9999)) - return false; - break; - case SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS: - if ((layer->GetTargetBrightness() > 0.0001) || - (layer->GetTargetGrayscale() > 0.0001)) - return false; - break; - case SessionStateAnimator::ANIMATION_DROP: - case SessionStateAnimator::ANIMATION_UNDO_LIFT: - //ToDo(antim) : check other effects - if (layer->GetTargetOpacity() < 0.9999) - return false; - break; - //ToDo(antim) : check other effects - case SessionStateAnimator::ANIMATION_LIFT: - if (layer->GetTargetOpacity() > 0.0001) - return false; - break; - case SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN: - //ToDo(antim) : check other effects - if (layer->GetTargetOpacity() < 0.9999) - return false; - break; - //ToDo(antim) : check other effects - case SessionStateAnimator::ANIMATION_LOWER_BELOW_SCREEN: - if (layer->GetTargetOpacity() > 0.0001) - return false; - break; - default: - NOTREACHED() << "Unhandled animation type " << type; - return false; - } - return true; -} - -} // namespace - -bool SessionStateAnimator::TestApi::ContainersAreAnimated( - int container_mask, AnimationType type) const { - aura::Window::Windows containers; - animator_->GetContainers(container_mask, &containers); - for (aura::Window::Windows::const_iterator it = containers.begin(); - it != containers.end(); ++it) { - aura::Window* window = *it; - ui::Layer* layer = window->layer(); - if (!IsLayerAnimated(layer, type)) - return false; - } - return true; -} - -bool SessionStateAnimator::TestApi::RootWindowIsAnimated(AnimationType type) - const { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - ui::Layer* layer = root_window->layer(); - return IsLayerAnimated(layer, type); -} - -const int SessionStateAnimator::kAllLockScreenContainersMask = - SessionStateAnimator::LOCK_SCREEN_BACKGROUND | - SessionStateAnimator::LOCK_SCREEN_CONTAINERS | - SessionStateAnimator::LOCK_SCREEN_RELATED_CONTAINERS; - -const int SessionStateAnimator::kAllContainersMask = - SessionStateAnimator::kAllLockScreenContainersMask | - SessionStateAnimator::DESKTOP_BACKGROUND | - SessionStateAnimator::LAUNCHER | - SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS; - -SessionStateAnimator::SessionStateAnimator() { -} - -SessionStateAnimator::~SessionStateAnimator() { -} - -base::TimeDelta SessionStateAnimator::GetDuration(AnimationSpeed speed) { - switch (speed) { - case ANIMATION_SPEED_IMMEDIATE: - return base::TimeDelta(); - case ANIMATION_SPEED_UNDOABLE: - return base::TimeDelta::FromMilliseconds(400); - case ANIMATION_SPEED_REVERT: - return base::TimeDelta::FromMilliseconds(150); - case ANIMATION_SPEED_FAST: - return base::TimeDelta::FromMilliseconds(150); - case ANIMATION_SPEED_SHOW_LOCK_SCREEN: - return base::TimeDelta::FromMilliseconds(200); - case ANIMATION_SPEED_MOVE_WINDOWS: - return base::TimeDelta::FromMilliseconds(350); - case ANIMATION_SPEED_UNDO_MOVE_WINDOWS: - return base::TimeDelta::FromMilliseconds(350); - case ANIMATION_SPEED_SHUTDOWN: - return base::TimeDelta::FromMilliseconds(1000); - case ANIMATION_SPEED_REVERT_SHUTDOWN: - return base::TimeDelta::FromMilliseconds(500); - } - // Satisfy compilers that do not understand that we will return from switch - // above anyway. - DCHECK(false) << "Unhandled animation speed " << speed; - return base::TimeDelta(); -} - -// Fills |containers| with the containers described by |container_mask|. -void SessionStateAnimator::GetContainers(int container_mask, - aura::Window::Windows* containers) { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - containers->clear(); - - if (container_mask & DESKTOP_BACKGROUND) { - containers->push_back(Shell::GetContainer( - root_window, - internal::kShellWindowId_DesktopBackgroundContainer)); - } - if (container_mask & LAUNCHER) { - containers->push_back(Shell::GetContainer( - root_window, - internal::kShellWindowId_ShelfContainer)); - } - if (container_mask & NON_LOCK_SCREEN_CONTAINERS) { - // TODO(antrim): Figure out a way to eliminate a need to exclude launcher - // in such way. - aura::Window* non_lock_screen_containers = Shell::GetContainer( - root_window, - internal::kShellWindowId_NonLockScreenContainersContainer); - aura::Window::Windows children = non_lock_screen_containers->children(); - - for (aura::Window::Windows::const_iterator it = children.begin(); - it != children.end(); ++it) { - aura::Window* window = *it; - if (window->id() == internal::kShellWindowId_ShelfContainer) - continue; - containers->push_back(window); - } - } - if (container_mask & LOCK_SCREEN_BACKGROUND) { - containers->push_back(Shell::GetContainer( - root_window, - internal::kShellWindowId_LockScreenBackgroundContainer)); - } - if (container_mask & LOCK_SCREEN_CONTAINERS) { - containers->push_back(Shell::GetContainer( - root_window, - internal::kShellWindowId_LockScreenContainersContainer)); - } - if (container_mask & LOCK_SCREEN_RELATED_CONTAINERS) { - containers->push_back(Shell::GetContainer( - root_window, - internal::kShellWindowId_LockScreenRelatedContainersContainer)); - } -} - -void SessionStateAnimator::StartAnimation(int container_mask, - AnimationType type, - AnimationSpeed speed) { - aura::Window::Windows containers; - GetContainers(container_mask, &containers); - for (aura::Window::Windows::const_iterator it = containers.begin(); - it != containers.end(); ++it) { - RunAnimationForWindow(*it, type, speed, NULL); - } -} - -void SessionStateAnimator::StartAnimationWithCallback( - int container_mask, - AnimationType type, - AnimationSpeed speed, - base::Callback<void(void)>& callback) { - aura::Window::Windows containers; - GetContainers(container_mask, &containers); - for (aura::Window::Windows::const_iterator it = containers.begin(); - it != containers.end(); ++it) { - ui::LayerAnimationObserver* observer = - new CallbackAnimationObserver(callback); - RunAnimationForWindow(*it, type, speed, observer); - } -} - -void SessionStateAnimator::StartAnimationWithObserver( - int container_mask, - AnimationType type, - AnimationSpeed speed, - ui::LayerAnimationObserver* observer) { - aura::Window::Windows containers; - GetContainers(container_mask, &containers); - for (aura::Window::Windows::const_iterator it = containers.begin(); - it != containers.end(); ++it) { - RunAnimationForWindow(*it, type, speed, observer); - } -} - -void SessionStateAnimator::StartGlobalAnimation(AnimationType type, - AnimationSpeed speed) { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - RunAnimationForWindow(root_window, type, speed, NULL); -} - -void SessionStateAnimator::RunAnimationForWindow( - aura::Window* window, - AnimationType type, - AnimationSpeed speed, - ui::LayerAnimationObserver* observer) { - base::TimeDelta duration = GetDuration(speed); - - switch (type) { - case ANIMATION_PARTIAL_CLOSE: - StartSlowCloseAnimationForWindow(window, duration, observer); - break; - case ANIMATION_UNDO_PARTIAL_CLOSE: - StartUndoSlowCloseAnimationForWindow(window, duration, observer); - break; - case ANIMATION_FULL_CLOSE: - StartFastCloseAnimationForWindow(window, duration, observer); - break; - case ANIMATION_FADE_IN: - StartOpacityAnimationForWindow(window, 1.0, duration, observer); - break; - case ANIMATION_FADE_OUT: - StartOpacityAnimationForWindow(window, 0.0, duration, observer); - break; - case ANIMATION_HIDE_IMMEDIATELY: - DCHECK_EQ(speed, ANIMATION_SPEED_IMMEDIATE); - HideWindowImmediately(window, observer); - break; - case ANIMATION_RESTORE: - DCHECK_EQ(speed, ANIMATION_SPEED_IMMEDIATE); - RestoreWindow(window, observer); - break; - case ANIMATION_LIFT: - HideWindow(window, duration, true, observer); - break; - case ANIMATION_DROP: - ShowWindow(window, duration, true, observer); - break; - case ANIMATION_UNDO_LIFT: - TransformWindowToBaseState(window, duration, observer); - break; - case ANIMATION_RAISE_TO_SCREEN: - ShowWindow(window, duration, false, observer); - break; - case ANIMATION_LOWER_BELOW_SCREEN: - HideWindow(window, duration, false, observer); - break; - case ANIMATION_PARTIAL_FADE_IN: - StartPartialFadeAnimation( - window, kPartialFadeRatio, duration, observer); - break; - case ANIMATION_UNDO_PARTIAL_FADE_IN: - StartPartialFadeAnimation(window, 0.0, duration, observer); - break; - case ANIMATION_FULL_FADE_IN: - StartPartialFadeAnimation(window, 1.0, duration, observer); - break; - case ANIMATION_GRAYSCALE_BRIGHTNESS: - StartGrayscaleBrightnessAnimationForWindow( - window, 1.0, duration, gfx::Tween::EASE_IN, observer); - break; - case ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS: - StartGrayscaleBrightnessAnimationForWindow( - window, 0.0, duration, gfx::Tween::EASE_IN_OUT, observer); - break; - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/session_state_animator.h b/chromium/ash/wm/session_state_animator.h deleted file mode 100644 index 4cb183e3cea..00000000000 --- a/chromium/ash/wm/session_state_animator.h +++ /dev/null @@ -1,180 +0,0 @@ -// 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_SESSION_STATE_ANIMATOR_H_ -#define ASH_WM_SESSION_STATE_ANIMATOR_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/timer/timer.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer_animation_observer.h" - -namespace gfx { -class Rect; -class Size; -} - -namespace ui { -class Layer; -} - -namespace ash { -namespace internal { - -// Displays onscreen animations for session state changes (lock/unlock, sign -// out, shut down). -class ASH_EXPORT SessionStateAnimator { - public: - // Animations that can be applied to groups of containers. - enum AnimationType { - ANIMATION_PARTIAL_CLOSE = 0, - ANIMATION_UNDO_PARTIAL_CLOSE, - ANIMATION_FULL_CLOSE, - ANIMATION_FADE_IN, - ANIMATION_FADE_OUT, - ANIMATION_HIDE_IMMEDIATELY, - ANIMATION_RESTORE, - // Animations that raise/lower windows to/from area "in front" of the - // screen. - ANIMATION_LIFT, - ANIMATION_UNDO_LIFT, - ANIMATION_DROP, - // Animations that raise/lower windows from/to area "behind" of the screen. - ANIMATION_RAISE_TO_SCREEN, - ANIMATION_LOWER_BELOW_SCREEN, - ANIMATION_PARTIAL_FADE_IN, - ANIMATION_UNDO_PARTIAL_FADE_IN, - ANIMATION_FULL_FADE_IN, - ANIMATION_GRAYSCALE_BRIGHTNESS, - ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS, - }; - - // Constants for determining animation speed. - enum AnimationSpeed { - // Immediately change state. - ANIMATION_SPEED_IMMEDIATE = 0, - // Speed for animations associated with user action that can be undone. - // Used for pre-lock and pre-shutdown animations. - ANIMATION_SPEED_UNDOABLE, - // Speed for animation that reverts undoable action. Used for aborting - // pre-lock and pre-shutdown animations. - ANIMATION_SPEED_REVERT, - // Speed for user action that can not be undone, Used for lock and shutdown - // animations requested via menus/shortcuts and for animating remaining - // parts of partial lock/shutdown animations. - ANIMATION_SPEED_FAST, - // Speed for lock screen appearance in "old" animation set. - ANIMATION_SPEED_SHOW_LOCK_SCREEN, - // Speed for workspace-like animations in "new" animation set. - ANIMATION_SPEED_MOVE_WINDOWS, - // Speed for undoing workspace-like animations in "new" animation set. - ANIMATION_SPEED_UNDO_MOVE_WINDOWS, - // Speed for shutdown in "new" animation set. - ANIMATION_SPEED_SHUTDOWN, - // Speed for reverting shutdown in "new" animation set. - ANIMATION_SPEED_REVERT_SHUTDOWN, - }; - - // Specific containers or groups of containers that can be animated. - enum Container { - DESKTOP_BACKGROUND = 1 << 0, - LAUNCHER = 1 << 1, - - // All user session related containers including system background but - // not including desktop background (wallpaper). - NON_LOCK_SCREEN_CONTAINERS = 1 << 2, - - // Desktop wallpaper is moved to this layer when screen is locked. - // This layer is excluded from lock animation so that wallpaper stays as is, - // user session windows are hidden and lock UI is shown on top of it. - // This layer is included in shutdown animation. - LOCK_SCREEN_BACKGROUND = 1 << 3, - - // Lock screen and lock screen modal containers. - LOCK_SCREEN_CONTAINERS = 1 << 4, - - // Multiple system layers belong here like status, menu, tooltip - // and overlay layers. - LOCK_SCREEN_RELATED_CONTAINERS = 1 << 5, - }; - - // Helper class used by tests to access internal state. - class ASH_EXPORT TestApi { - public: - explicit TestApi(SessionStateAnimator* animator) - : animator_(animator) {} - - // Returns true if containers of a given |container_mask| - // were last animated with |type| (probably; the analysis is fairly ad-hoc). - // |container_mask| is a bitfield of a Container. - bool ContainersAreAnimated(int container_mask, AnimationType type) const; - - // Returns true if root window was last animated with |type| (probably; - // the analysis is fairly ad-hoc). - bool RootWindowIsAnimated(AnimationType type) const; - - private: - SessionStateAnimator* animator_; // not owned - - DISALLOW_COPY_AND_ASSIGN(TestApi); - }; - - // A bitfield mask including LOCK_SCREEN_WALLPAPER, - // LOCK_SCREEN_CONTAINERS, and LOCK_SCREEN_RELATED_CONTAINERS. - const static int kAllLockScreenContainersMask; - - // A bitfield mask of all containers. - const static int kAllContainersMask; - - SessionStateAnimator(); - virtual ~SessionStateAnimator(); - - // Reports animation duration for |speed|. - static base::TimeDelta GetDuration(AnimationSpeed speed); - - // Fills |containers| with the containers included in |container_mask|. - static void GetContainers(int container_mask, - aura::Window::Windows* containers); - - // Apply animation |type| to all containers included in |container_mask| with - // specified |speed|. - void StartAnimation(int container_mask, - AnimationType type, - AnimationSpeed speed); - - // Apply animation |type| to all containers included in |container_mask| with - // specified |speed| and call a |callback| at the end of the animation, if it - // is not null. - void StartAnimationWithCallback(int container_mask, - AnimationType type, - AnimationSpeed speed, - base::Callback<void(void)>& callback); - -// Apply animation |type| to all containers included in |container_mask| with -// specified |speed| and add |observer| to all animations. - void StartAnimationWithObserver(int container_mask, - AnimationType type, - AnimationSpeed speed, - ui::LayerAnimationObserver* observer); - - // Applies animation |type| whith specified |speed| to the root container. - void StartGlobalAnimation(AnimationType type, - AnimationSpeed speed); - - // Apply animation |type| to window |window| with |speed| and add |observer| - // if it is not NULL to the last animation sequence. - void RunAnimationForWindow(aura::Window* window, - AnimationType type, - AnimationSpeed speed, - ui::LayerAnimationObserver* observer); - - DISALLOW_COPY_AND_ASSIGN(SessionStateAnimator); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_SESSION_STATE_ANIMATOR_H_ diff --git a/chromium/ash/wm/solo_window_tracker.cc b/chromium/ash/wm/solo_window_tracker.cc deleted file mode 100644 index 633d3bd450e..00000000000 --- a/chromium/ash/wm/solo_window_tracker.cc +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2013 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/solo_window_tracker.h" - -#include <algorithm> - -#include "ash/ash_constants.h" -#include "ash/root_window_controller.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_state_observer.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" - -namespace ash { - -namespace { - -// A flag to enable/disable the solo window header across all root windows. -bool g_solo_header_enabled = true; - -// Returns the containers from which a solo window is chosen. -std::vector<aura::Window*> GetContainers(aura::RootWindow* root_window) { - int kContainerIds[] = { - internal::kShellWindowId_DefaultContainer, - internal::kShellWindowId_AlwaysOnTopContainer, - // Docked windows never use the solo header, but regular windows move to the - // docked container when dragged. - internal::kShellWindowId_DockedContainer, - }; - std::vector<aura::Window*> containers; - for (size_t i = 0; i < arraysize(kContainerIds); ++i) { - containers.push_back( - Shell::GetContainer(root_window->window(), kContainerIds[i])); - } - return containers; -} - -// Returns true if |child| and all of its ancestors are visible and neither -// |child| nor any its ancestors is animating hidden. -bool GetTargetVisibility(aura::Window* child) { - for (aura::Window* window = child; window; window = window->parent()) { - if (!window->TargetVisibility()) - return false; - } - return true; -} - -// Returns true if |window| can use the solo window header. Returns false for -// windows that are: -// * Not drawn (for example, DragDropTracker uses one for mouse capture) -// * Modal alerts (it looks odd for headers to change when an alert opens) -// * Constrained windows (ditto) -bool IsValidCandidate(aura::Window* window) { - return window->type() == aura::client::WINDOW_TYPE_NORMAL && - window->layer() && - window->layer()->type() != ui::LAYER_NOT_DRAWN && - window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_NONE && - !window->GetProperty(aura::client::kConstrainedWindowKey); -} - -// Schedule's a paint of the window's entire bounds. -void SchedulePaint(aura::Window* window) { - window->SchedulePaintInRect(gfx::Rect(window->bounds().size())); -} - -} // namespace - - -// Class which triggers a repaint of the window which is passed to the -// constructor whenever the window's show type changes. The window's non client -// view is responsible for updating whether it uses the solo header as part of -// the repaint by querying GetWindowWithSoloHeader(). -class SoloWindowTracker::SoloWindowObserver - : public ash::wm::WindowStateObserver { - public: - explicit SoloWindowObserver(aura::Window* window) : window_(window) { - wm::GetWindowState(window_)->AddObserver(this); - } - - virtual ~SoloWindowObserver() { - wm::GetWindowState(window_)->RemoveObserver(this); - } - - private: - // ash::wm::WindowStateObserver override. - virtual void OnWindowShowTypeChanged( - ash::wm::WindowState* window_state, - ash::wm::WindowShowType old_type) OVERRIDE { - SchedulePaint(window_); - } - - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(SoloWindowObserver); -}; - -SoloWindowTracker::SoloWindowTracker(aura::RootWindow* root_window) - : containers_(GetContainers(root_window)), - solo_window_(NULL) { - for (size_t i = 0; i < containers_.size(); ++i) - containers_[i]->AddObserver(this); -} - -SoloWindowTracker::~SoloWindowTracker() { - for (size_t i = 0; i < containers_.size(); ++i) - containers_[i]->RemoveObserver(this); -} - -// static -void SoloWindowTracker::SetSoloHeaderEnabled(bool enabled) { - g_solo_header_enabled = enabled; - std::vector<aura::Window*> root_windows = - Shell::GetInstance()->GetAllRootWindows(); - for (size_t i = 0; i < root_windows.size(); ++i) { - SoloWindowTracker* tracker = - internal::GetRootWindowController(root_windows[i])-> - solo_window_tracker(); - if (tracker) - tracker->UpdateSoloWindow(NULL); - } -} - -aura::Window* SoloWindowTracker::GetWindowWithSoloHeader() { - bool use_solo_header = solo_window_ && - !wm::GetWindowState(solo_window_)->IsMaximizedOrFullscreen(); - return use_solo_header ? solo_window_ : NULL; -} - -void SoloWindowTracker::UpdateSoloWindow(aura::Window* ignore_window) { - std::vector<aura::Window*> candidates; - // Avoid memory allocations for typical window counts. - candidates.reserve(16); - for (size_t i = 0; i < containers_.size(); ++i) { - candidates.insert(candidates.end(), - containers_[i]->children().begin(), - containers_[i]->children().end()); - } - - aura::Window* old_solo_window = solo_window_; - solo_window_ = NULL; - if (g_solo_header_enabled && !AnyVisibleWindowDocked()) { - for (size_t i = 0; i < candidates.size(); ++i) { - aura::Window* candidate = candidates[i]; - // Various sorts of windows "don't count" for this computation. - if (candidate == ignore_window || - !IsValidCandidate(candidate) || - !GetTargetVisibility(candidate)) { - continue; - } - - if (solo_window_) { - // A window can only use the solo header if it is the only visible valid - // candidate (and there are no visible docked windows). - solo_window_ = NULL; - break; - } else { - solo_window_ = candidate; - } - } - } - - if (solo_window_ == old_solo_window) - return; - - solo_window_observer_.reset(solo_window_ ? - new SoloWindowObserver(solo_window_) : NULL); - if (old_solo_window) - SchedulePaint(old_solo_window); - if (solo_window_) - SchedulePaint(solo_window_); -} - -bool SoloWindowTracker::AnyVisibleWindowDocked() const { - // For the purpose of SoloWindowTracker, there is a visible docked window if - // it causes the dock to have non-empty bounds. This is intentionally - // different from: - // DockedWindowLayoutManager::IsAnyWindowDocked() and - // DockedWindowLayoutManager::is_dragged_window_docked(). - return !dock_bounds_.IsEmpty(); -} - -void SoloWindowTracker::OnWindowAdded(aura::Window* new_window) { - UpdateSoloWindow(NULL); -} - -void SoloWindowTracker::OnWillRemoveWindow(aura::Window* window) { - UpdateSoloWindow(window); -} - -void SoloWindowTracker::OnWindowVisibilityChanged(aura::Window* window, - bool visible) { - // |window| may be a grandchild of |containers_|. - std::vector<aura::Window*>::const_iterator it = std::find( - containers_.begin(), containers_.end(), window->parent()); - if (it != containers_.end()) - UpdateSoloWindow(NULL); -} - -void SoloWindowTracker::OnDockBoundsChanging(const gfx::Rect& new_bounds, - Reason reason) { - dock_bounds_ = new_bounds; - UpdateSoloWindow(NULL); -} - -} // namespace ash diff --git a/chromium/ash/wm/solo_window_tracker.h b/chromium/ash/wm/solo_window_tracker.h deleted file mode 100644 index 829af01b402..00000000000 --- a/chromium/ash/wm/solo_window_tracker.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2013 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_SOLO_WINDOW_TRACKER_H_ -#define ASH_WM_SOLO_WINDOW_TRACKER_H_ - -#include <vector> - -#include "ash/ash_export.h" -#include "ash/wm/dock/docked_window_layout_manager_observer.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/rect.h" - -namespace aura { -class RootWindow; -class Window; -} - -namespace ash { - -// Class which keeps track of the window (if any) which should use the solo -// window header. The solo window header is very transparent and is used when -// there is only one visible window and the window is not maximized or -// fullscreen. The solo window header is not used for either panels or docked -// windows. -class ASH_EXPORT SoloWindowTracker - : public aura::WindowObserver, - public internal::DockedWindowLayoutManagerObserver { - public: - explicit SoloWindowTracker(aura::RootWindow* root_window); - virtual ~SoloWindowTracker(); - - // Enable/Disable solo headers. - static void SetSoloHeaderEnabled(bool enabled); - - // Returns the window, if any, which should use the solo window header. - aura::Window* GetWindowWithSoloHeader(); - - private: - // Updates the window which would use the solo header if the window were not - // maximized or fullscreen. If |ignore_window| is not NULL, it is ignored for - // counting valid candidates. This is useful when there is a window which is - // about to be moved to a different root window or about to be closed. - void UpdateSoloWindow(aura::Window* ignore_window); - - // Returns true if there is a visible docked window. - bool AnyVisibleWindowDocked() const; - - // aura::WindowObserver overrides: - virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE; - virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE; - virtual void OnWindowVisibilityChanged(aura::Window* window, - bool visible) OVERRIDE; - - // ash::internal::DockedWindowLayoutManagerObserver override: - virtual void OnDockBoundsChanging(const gfx::Rect& new_bounds, - Reason reason) OVERRIDE; - - // The containers whose children can use the solo header. - std::vector<aura::Window*> containers_; - - // The dock's bounds. - gfx::Rect dock_bounds_; - - // The window which would use the solo header if it were not maximized or - // fullscreen. - aura::Window* solo_window_; - - // Class which observes changes in |solo_window_|'s show type. - class SoloWindowObserver; - scoped_ptr<SoloWindowObserver> solo_window_observer_; - - DISALLOW_COPY_AND_ASSIGN(SoloWindowTracker); -}; - -} // namespace ash - -#endif // ASH_WM_SOLO_WINDOW_TRACKER_H_ diff --git a/chromium/ash/wm/solo_window_tracker_unittest.cc b/chromium/ash/wm/solo_window_tracker_unittest.cc deleted file mode 100644 index 431ae009556..00000000000 --- a/chromium/ash/wm/solo_window_tracker_unittest.cc +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright 2013 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/solo_window_tracker.h" - -#include "ash/ash_constants.h" -#include "ash/ash_switches.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_resizer.h" -#include "ash/wm/window_state.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/base/hit_test.h" -#include "ui/gfx/screen.h" - -namespace ash { - -namespace { - -class WindowRepaintChecker : public aura::WindowObserver { - public: - explicit WindowRepaintChecker(aura::Window* window) - : window_(window), - is_paint_scheduled_(false) { - window_->AddObserver(this); - } - - virtual ~WindowRepaintChecker() { - if (window_) - window_->RemoveObserver(this); - } - - bool IsPaintScheduledAndReset() { - bool result = is_paint_scheduled_; - is_paint_scheduled_ = false; - return result; - } - - private: - // aura::WindowObserver overrides: - virtual void OnWindowPaintScheduled(aura::Window* window, - const gfx::Rect& region) OVERRIDE { - is_paint_scheduled_ = true; - } - virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE { - DCHECK_EQ(window_, window); - window_ = NULL; - } - - aura::Window* window_; - bool is_paint_scheduled_; - - DISALLOW_COPY_AND_ASSIGN(WindowRepaintChecker); -}; - -} // namespace - -class SoloWindowTrackerTest : public test::AshTestBase { - public: - SoloWindowTrackerTest() { - } - virtual ~SoloWindowTrackerTest() { - } - - // Helpers methods to create test windows in the primary root window. - aura::Window* CreateWindowInPrimary() { - aura::Window* window = new aura::Window(NULL); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - window->SetBounds(gfx::Rect(100, 100)); - ParentWindowInPrimaryRootWindow(window); - return window; - } - aura::Window* CreateAlwaysOnTopWindowInPrimary() { - aura::Window* window = new aura::Window(NULL); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - window->SetBounds(gfx::Rect(100, 100)); - window->SetProperty(aura::client::kAlwaysOnTopKey, true); - ParentWindowInPrimaryRootWindow(window); - return window; - } - aura::Window* CreatePanelWindowInPrimary() { - aura::Window* window = new aura::Window(NULL); - window->SetType(aura::client::WINDOW_TYPE_PANEL); - window->Init(ui::LAYER_TEXTURED); - window->SetBounds(gfx::Rect(100, 100)); - ParentWindowInPrimaryRootWindow(window); - return window; - } - - // Drag |window| to the dock. - void DockWindow(aura::Window* window) { - // Because the tests use windows without delegates, - // aura::test::EventGenerator cannot be used. - gfx::Point drag_to = - ash::ScreenAsh::GetDisplayBoundsInParent(window).top_right(); - scoped_ptr<WindowResizer> resizer(CreateWindowResizer( - window, - window->bounds().origin(), - HTCAPTION, - aura::client::WINDOW_MOVE_SOURCE_MOUSE)); - resizer->Drag(drag_to, 0); - resizer->CompleteDrag(0); - EXPECT_EQ(internal::kShellWindowId_DockedContainer, - window->parent()->id()); - } - - // Drag |window| out of the dock. - void UndockWindow(aura::Window* window) { - gfx::Point drag_to = - ash::ScreenAsh::GetDisplayWorkAreaBoundsInParent(window).top_right() - - gfx::Vector2d(10, 0); - scoped_ptr<WindowResizer> resizer(CreateWindowResizer( - window, - window->bounds().origin(), - HTCAPTION, - aura::client::WINDOW_MOVE_SOURCE_MOUSE)); - resizer->Drag(drag_to, 0); - resizer->CompleteDrag(0); - EXPECT_NE(internal::kShellWindowId_DockedContainer, - window->parent()->id()); - } - - // Returns the primary display. - gfx::Display GetPrimaryDisplay() { - return ash::Shell::GetInstance()->GetScreen()->GetPrimaryDisplay(); - } - - // Returns the secondary display. - gfx::Display GetSecondaryDisplay() { - return ScreenAsh::GetSecondaryDisplay(); - } - - // Returns the window which uses the solo header, if any, on the primary - // display. - aura::Window* GetWindowWithSoloHeaderInPrimary() { - return GetWindowWithSoloHeader(Shell::GetPrimaryRootWindow()); - } - - // Returns the window which uses the solo header, if any, in |root|. - aura::Window* GetWindowWithSoloHeader(aura::Window* root) { - SoloWindowTracker* solo_window_tracker = - internal::GetRootWindowController(root)->solo_window_tracker(); - return solo_window_tracker ? - solo_window_tracker->GetWindowWithSoloHeader() : NULL; - } - - private: - DISALLOW_COPY_AND_ASSIGN(SoloWindowTrackerTest); -}; - -TEST_F(SoloWindowTrackerTest, Basic) { - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Create a second window. - scoped_ptr<aura::Window> w2(CreateWindowInPrimary()); - w2->Show(); - - // Now there are two windows, so we should not use solo headers. - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - // Hide one window. Solo should be enabled. - w2->Hide(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Show that window. Solo should be disabled. - w2->Show(); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - // Minimize the first window. Solo should be enabled. - wm::GetWindowState(w1.get())->Minimize(); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeaderInPrimary()); - - // Close the minimized window. - w1.reset(); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeaderInPrimary()); - - // Open an always-on-top window (which lives in a different container). - scoped_ptr<aura::Window> w3(CreateAlwaysOnTopWindowInPrimary()); - w3->Show(); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - // Close the always-on-top window. - w3.reset(); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeaderInPrimary()); -} - -// Test that docked windows never use the solo header and that the presence of a -// docked window prevents all other windows from the using the solo window -// header. -TEST_F(SoloWindowTrackerTest, DockedWindow) { - if (!switches::UseDockedWindows() || !SupportsHostWindowResize()) - return; - - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->Show(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - DockWindow(w1.get()); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - UndockWindow(w1.get()); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - scoped_ptr<aura::Window> w2(CreateWindowInPrimary()); - w2->Show(); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - DockWindow(w2.get()); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - wm::GetWindowState(w2.get())->Minimize(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); -} - -// Panels should not "count" for computing solo window headers, and the panel -// itself should never use the solo header. -TEST_F(SoloWindowTrackerTest, Panel) { - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Create a panel window. - scoped_ptr<aura::Window> w2(CreatePanelWindowInPrimary()); - w2->Show(); - - // Despite two windows, the first window should still be considered "solo" - // because panels aren't included in the computation. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Even after closing the first window, the panel is still not considered - // solo. - w1.reset(); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); -} - -// Modal dialogs should not use solo headers. -TEST_F(SoloWindowTrackerTest, Modal) { - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Create a fake modal window. - scoped_ptr<aura::Window> w2(CreateWindowInPrimary()); - w2->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - w2->Show(); - - // Despite two windows, the first window should still be considered "solo" - // because modal windows aren't included in the computation. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); -} - -// Constrained windows should not use solo headers. -TEST_F(SoloWindowTrackerTest, Constrained) { - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - - // Create a fake constrained window. - scoped_ptr<aura::Window> w2(CreateWindowInPrimary()); - w2->SetProperty(aura::client::kConstrainedWindowKey, true); - w2->Show(); - - // Despite two windows, the first window should still be considered "solo" - // because constrained windows aren't included in the computation. - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); -} - -// Non-drawing windows should not affect the solo computation. -TEST_F(SoloWindowTrackerTest, NotDrawn) { - aura::Window* w = CreateWindowInPrimary(); - w->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w, GetWindowWithSoloHeaderInPrimary()); - - // Create non-drawing window similar to DragDropTracker. - aura::Window* not_drawn = new aura::Window(NULL); - not_drawn->SetType(aura::client::WINDOW_TYPE_NORMAL); - not_drawn->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(not_drawn); - not_drawn->Show(); - - // Despite two windows, the first window should still be considered "solo" - // because non-drawing windows aren't included in the computation. - EXPECT_EQ(w, GetWindowWithSoloHeaderInPrimary()); -} - -TEST_F(SoloWindowTrackerTest, MultiDisplay) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("1000x600,600x400"); - - scoped_ptr<aura::Window> w1(CreateWindowInPrimary()); - w1->SetBoundsInScreen(gfx::Rect(0, 0, 100, 100), GetPrimaryDisplay()); - w1->Show(); - WindowRepaintChecker checker1(w1.get()); - scoped_ptr<aura::Window> w2(CreateWindowInPrimary()); - w2->SetBoundsInScreen(gfx::Rect(0, 0, 100, 100), GetPrimaryDisplay()); - w2->Show(); - WindowRepaintChecker checker2(w2.get()); - - // Now there are two windows in the same display, so we should not use solo - // headers. - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); - - // Moves the second window to the secondary display. Both w1/w2 should be - // solo. - w2->SetBoundsInScreen(gfx::Rect(1200, 0, 100, 100), - ScreenAsh::GetSecondaryDisplay()); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeader(w2->GetRootWindow())); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); - EXPECT_TRUE(checker2.IsPaintScheduledAndReset()); - - // Open two more windows in the primary display. - scoped_ptr<aura::Window> w3(CreateWindowInPrimary()); - w3->SetBoundsInScreen(gfx::Rect(0, 0, 100, 100), GetPrimaryDisplay()); - w3->Show(); - scoped_ptr<aura::Window> w4(CreateWindowInPrimary()); - w4->SetBoundsInScreen(gfx::Rect(0, 0, 100, 100), GetPrimaryDisplay()); - w4->Show(); - - // Because the primary display has three windows w1, w3, and w4, they - // shouldn't be solo. w2 should be solo. - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeader(w2->GetRootWindow())); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); - - // Move w4 to the secondary display. Now w2 shouldn't be solo anymore. - w4->SetBoundsInScreen(gfx::Rect(1200, 0, 100, 100), GetSecondaryDisplay()); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(NULL, GetWindowWithSoloHeader(w2->GetRootWindow())); - EXPECT_TRUE(checker2.IsPaintScheduledAndReset()); - - // Moves w3 to the secondary display too. Now w1 should be solo again. - w3->SetBoundsInScreen(gfx::Rect(1200, 0, 100, 100), GetSecondaryDisplay()); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(NULL, GetWindowWithSoloHeader(w2->GetRootWindow())); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); - - // Change w3's state to maximize. Doesn't affect w1. - wm::GetWindowState(w3.get())->Maximize(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(NULL, GetWindowWithSoloHeader(w2->GetRootWindow())); - - // Close w3 and w4. - w3.reset(); - w4.reset(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - EXPECT_EQ(w2.get(), GetWindowWithSoloHeader(w2->GetRootWindow())); - EXPECT_TRUE(checker2.IsPaintScheduledAndReset()); - - // Move w2 back to the primary display. - w2->SetBoundsInScreen(gfx::Rect(0, 0, 100, 100), GetPrimaryDisplay()); - EXPECT_EQ(w1->GetRootWindow(), w2->GetRootWindow()); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); - EXPECT_TRUE(checker2.IsPaintScheduledAndReset()); - - // Close w2. - w2.reset(); - EXPECT_EQ(w1.get(), GetWindowWithSoloHeaderInPrimary()); - EXPECT_TRUE(checker1.IsPaintScheduledAndReset()); -} - -TEST_F(SoloWindowTrackerTest, ChildWindowVisibility) { - aura::Window* w = CreateWindowInPrimary(); - w->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w, GetWindowWithSoloHeaderInPrimary()); - - // Create a child window. This should not affect the solo-ness of |w1|. - aura::Window* child = new aura::Window(NULL); - child->SetType(aura::client::WINDOW_TYPE_CONTROL); - child->Init(ui::LAYER_TEXTURED); - child->SetBounds(gfx::Rect(100, 100)); - w->AddChild(child); - child->Show(); - EXPECT_EQ(w, GetWindowWithSoloHeaderInPrimary()); - - // Changing the visibility of |child| should not affect the solo-ness of |w1|. - child->Hide(); - EXPECT_EQ(w, GetWindowWithSoloHeaderInPrimary()); -} - -TEST_F(SoloWindowTrackerTest, CreateAndDeleteSingleWindow) { - // Ensure that creating/deleting a window works well and doesn't cause - // crashes. See crbug.com/155634 - scoped_ptr<aura::Window> w(CreateWindowInPrimary()); - w->Show(); - - // We only have one window, so it should use a solo header. - EXPECT_EQ(w.get(), GetWindowWithSoloHeaderInPrimary()); - - // Close the window. - w.reset(); - EXPECT_EQ(NULL, GetWindowWithSoloHeaderInPrimary()); - - // Recreate another window again. - w.reset(CreateWindowInPrimary()); - w->Show(); - EXPECT_EQ(w.get(), GetWindowWithSoloHeaderInPrimary()); -} - -} // namespace ash diff --git a/chromium/ash/wm/stacking_controller.cc b/chromium/ash/wm/stacking_controller.cc deleted file mode 100644 index 915eed41d43..00000000000 --- a/chromium/ash/wm/stacking_controller.cc +++ /dev/null @@ -1,143 +0,0 @@ -// 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/stacking_controller.h" - -#include "ash/root_window_controller.h" -#include "ash/session_state_delegate.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/always_on_top_controller.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/window_state.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/base/ui_base_types.h" - -namespace ash { -namespace { - -// Find a root window that matches the |bounds|. If the virtual screen -// coordinates is enabled and the bounds is specified, the root window -// that matches the window's bound will be used. Otherwise, it'll -// return the active root window. -aura::Window* FindContainerRoot(const gfx::Rect& bounds) { - if (bounds.x() == 0 && bounds.y() == 0 && bounds.IsEmpty()) - return Shell::GetTargetRootWindow(); - return wm::GetRootWindowMatching(bounds); -} - -aura::Window* GetContainerById(aura::Window* root, int id) { - return Shell::GetContainer(root, id); -} - -bool IsSystemModal(aura::Window* window) { - return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM; -} - -bool HasTransientParentWindow(aura::Window* window) { - return window->transient_parent() && - window->transient_parent()->type() != aura::client::WINDOW_TYPE_UNKNOWN; -} - -internal::AlwaysOnTopController* -GetAlwaysOnTopController(aura::Window* root_window) { - return internal::GetRootWindowController(root_window)-> - always_on_top_controller(); -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// StackingController, public: - -StackingController::StackingController() { -} - -StackingController::~StackingController() { -} - -//////////////////////////////////////////////////////////////////////////////// -// StackingController, aura::client::WindowTreeClient implementation: - -aura::Window* StackingController::GetDefaultParent(aura::Window* context, - aura::Window* window, - const gfx::Rect& bounds) { - aura::Window* target_root = NULL; - if (window->transient_parent()) { - // Transient window should use the same root as its transient parent. - target_root = window->transient_parent()->GetRootWindow(); - } else { - target_root = FindContainerRoot(bounds); - } - - switch (window->type()) { - case aura::client::WINDOW_TYPE_NORMAL: - case aura::client::WINDOW_TYPE_POPUP: - if (IsSystemModal(window)) - return GetSystemModalContainer(target_root, window); - else if (HasTransientParentWindow(window)) - return internal::RootWindowController::GetContainerForWindow( - window->transient_parent()); - return GetAlwaysOnTopController(target_root)->GetContainer(window); - case aura::client::WINDOW_TYPE_CONTROL: - return GetContainerById( - target_root, internal::kShellWindowId_UnparentedControlContainer); - case aura::client::WINDOW_TYPE_PANEL: - if (wm::GetWindowState(window)->panel_attached()) - return GetContainerById(target_root, - internal::kShellWindowId_PanelContainer); - else - return GetAlwaysOnTopController(target_root)->GetContainer(window); - case aura::client::WINDOW_TYPE_MENU: - return GetContainerById( - target_root, internal::kShellWindowId_MenuContainer); - case aura::client::WINDOW_TYPE_TOOLTIP: - return GetContainerById( - target_root, internal::kShellWindowId_DragImageAndTooltipContainer); - default: - NOTREACHED() << "Window " << window->id() - << " has unhandled type " << window->type(); - break; - } - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -// StackingController, private: - -aura::Window* StackingController::GetSystemModalContainer( - aura::Window* root, - aura::Window* window) const { - DCHECK(IsSystemModal(window)); - - // If screen lock is not active and user session is active, - // all modal windows are placed into the normal modal container. - // In case of missing transient parent (it could happen for alerts from - // background pages) assume that the window belongs to user session. - SessionStateDelegate* session_state_delegate = - Shell::GetInstance()->session_state_delegate(); - if (!session_state_delegate->IsUserSessionBlocked() || - !window->transient_parent()) { - return GetContainerById(root, - internal::kShellWindowId_SystemModalContainer); - } - - // Otherwise those that originate from LockScreen container and above are - // placed in the screen lock modal container. - int window_container_id = window->transient_parent()->parent()->id(); - aura::Window* container = NULL; - if (window_container_id < internal::kShellWindowId_LockScreenContainer) { - container = GetContainerById( - root, internal::kShellWindowId_SystemModalContainer); - } else { - container = GetContainerById( - root, internal::kShellWindowId_LockSystemModalContainer); - } - - return container; -} - -} // namespace ash diff --git a/chromium/ash/wm/stacking_controller.h b/chromium/ash/wm/stacking_controller.h deleted file mode 100644 index bbe715eba30..00000000000 --- a/chromium/ash/wm/stacking_controller.h +++ /dev/null @@ -1,43 +0,0 @@ -// 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_STACKING_CONTROLLER_H_ -#define ASH_WM_STACKING_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/client/window_tree_client.h" - -namespace ash { -namespace internal { -class AlwaysOnTopController; -} - -class ASH_EXPORT StackingController : public aura::client::WindowTreeClient { - public: - StackingController(); - virtual ~StackingController(); - - // Overridden from aura::client::WindowTreeClient: - virtual aura::Window* GetDefaultParent(aura::Window* context, - aura::Window* window, - const gfx::Rect& bounds) OVERRIDE; - - private: - // Returns corresponding system modal container for a modal window. - // If screen lock is not active, all system modal windows are placed into the - // normal modal container. - // Otherwise those that originate from LockScreen container and above are - // placed in the screen lock modal container. - aura::Window* GetSystemModalContainer(aura::Window* root, - aura::Window* window) const; - - DISALLOW_COPY_AND_ASSIGN(StackingController); -}; - -} // namespace ash - -#endif // ASH_WM_STACKING_CONTROLLER_H_ diff --git a/chromium/ash/wm/stacking_controller_unittest.cc b/chromium/ash/wm/stacking_controller_unittest.cc deleted file mode 100644 index e0ccaa182be..00000000000 --- a/chromium/ash/wm/stacking_controller_unittest.cc +++ /dev/null @@ -1,63 +0,0 @@ -// 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/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_properties.h" -#include "ash/wm/window_util.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" - -using aura::Window; - -namespace ash { -namespace internal { - -class StackingControllerTest : public test::AshTestBase { - public: - StackingControllerTest() {} - virtual ~StackingControllerTest() {} - - aura::Window* CreateTestWindow() { - aura::Window* window = new aura::Window(NULL); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - return window; - } - - private: - DISALLOW_COPY_AND_ASSIGN(StackingControllerTest); -}; - -// Verifies a window with a transient parent is in the same container as its -// transient parent. -TEST_F(StackingControllerTest, TransientParent) { - // Normal window . - scoped_ptr<Window> w2(CreateTestWindow()); - w2->SetBounds(gfx::Rect(10, 11, 250, 251)); - aura::Window* launcher = Shell::GetContainer(Shell::GetPrimaryRootWindow(), - kShellWindowId_ShelfContainer); - launcher->AddChild(w2.get()); - w2->Show(); - - wm::ActivateWindow(w2.get()); - - // Window with a transient parent. - scoped_ptr<Window> w1(CreateTestWindow()); - w2->AddTransientChild(w1.get()); - w1->SetBounds(gfx::Rect(10, 11, 250, 251)); - ParentWindowInPrimaryRootWindow(w1.get()); - w1->Show(); - wm::ActivateWindow(w1.get()); - - // The window with the transient parent should get added to the same container - // as its transient parent. - EXPECT_EQ(launcher, w1->parent()); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/status_area_layout_manager.cc b/chromium/ash/wm/status_area_layout_manager.cc deleted file mode 100644 index d9e0424d240..00000000000 --- a/chromium/ash/wm/status_area_layout_manager.cc +++ /dev/null @@ -1,81 +0,0 @@ -// 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/status_area_layout_manager.h" - -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/system/status_area_widget.h" -#include "base/auto_reset.h" -#include "ui/aura/window.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -//////////////////////////////////////////////////////////////////////////////// -// StatusAreaLayoutManager, public: - -StatusAreaLayoutManager::StatusAreaLayoutManager(ShelfWidget* shelf) - : in_layout_(false), - shelf_(shelf) { -} - -StatusAreaLayoutManager::~StatusAreaLayoutManager() { -} - -//////////////////////////////////////////////////////////////////////////////// -// StatusAreaLayoutManager, aura::LayoutManager implementation: - -void StatusAreaLayoutManager::OnWindowResized() { - LayoutStatusArea(); -} - -void StatusAreaLayoutManager::OnWindowAddedToLayout(aura::Window* child) { -} - -void StatusAreaLayoutManager::OnWillRemoveWindowFromLayout( - aura::Window* child) { -} - -void StatusAreaLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { -} - -void StatusAreaLayoutManager::OnChildWindowVisibilityChanged( - aura::Window* child, bool visible) { -} - -void StatusAreaLayoutManager::SetChildBounds( - aura::Window* child, - const gfx::Rect& requested_bounds) { - // Only need to have the shelf do a layout if the child changing is the status - // area and the shelf isn't in the process of doing a layout. - if (child != shelf_->status_area_widget()->GetNativeView() || in_layout_) { - SetChildBoundsDirect(child, requested_bounds); - return; - } - - // If the size matches, no need to do anything. We don't check the location as - // that is managed by the shelf. - if (requested_bounds == child->bounds()) - return; - - SetChildBoundsDirect(child, requested_bounds); - LayoutStatusArea(); -} - -//////////////////////////////////////////////////////////////////////////////// -// StatusAreaLayoutManager, private: - -void StatusAreaLayoutManager::LayoutStatusArea() { - // Shelf layout manager may be already doing layout. - if (shelf_->shelf_layout_manager()->updating_bounds()) - return; - - base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true); - shelf_->shelf_layout_manager()->LayoutShelf(); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/status_area_layout_manager.h b/chromium/ash/wm/status_area_layout_manager.h deleted file mode 100644 index 8e6944dfacd..00000000000 --- a/chromium/ash/wm/status_area_layout_manager.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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_STATUS_AREA_LAYOUT_MANAGER_H_ -#define ASH_WM_STATUS_AREA_LAYOUT_MANAGER_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/aura/layout_manager.h" - -namespace ash { -class ShelfWidget; -namespace internal { - -// StatusAreaLayoutManager is a layout manager responsible for the status area. -// In any case when status area needs relayout it redirects this call to -// ShelfLayoutManager. -class StatusAreaLayoutManager : public aura::LayoutManager { - public: - explicit StatusAreaLayoutManager(ShelfWidget* shelf); - virtual ~StatusAreaLayoutManager(); - - // Overridden from aura::LayoutManager: - virtual void OnWindowResized() OVERRIDE; - virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; - virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; - virtual void OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) OVERRIDE; - virtual void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) OVERRIDE; - - private: - // Updates layout of the status area. Effectively calls ShelfLayoutManager - // to update layout of the shelf. - void LayoutStatusArea(); - - // True when inside LayoutStatusArea method. - // Used to prevent calling itself again from SetChildBounds(). - bool in_layout_; - - ShelfWidget* shelf_; - - DISALLOW_COPY_AND_ASSIGN(StatusAreaLayoutManager); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_STATUS_AREA_LAYOUT_MANAGER_H_ diff --git a/chromium/ash/wm/sticky_keys.cc b/chromium/ash/wm/sticky_keys.cc deleted file mode 100644 index 9e2cc2a92de..00000000000 --- a/chromium/ash/wm/sticky_keys.cc +++ /dev/null @@ -1,445 +0,0 @@ -// Copyright 2013 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/sticky_keys.h" - -#if defined(USE_X11) -#include <X11/extensions/XInput2.h> -#include <X11/Xlib.h> -#undef RootWindow -#endif - -#include "base/basictypes.h" -#include "base/debug/stack_trace.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_tracker.h" -#include "ui/events/event.h" -#include "ui/events/keycodes/keyboard_code_conversion.h" - -namespace ash { - -namespace { - -// Returns true if the type of mouse event should be modified by sticky keys. -bool ShouldModifyMouseEvent(ui::MouseEvent* event) { - ui::EventType type = event->type(); - return type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED || - type == ui::ET_MOUSEWHEEL; -} - -// An implementation of StickyKeysHandler::StickyKeysHandlerDelegate. -class StickyKeysHandlerDelegateImpl : - public StickyKeysHandler::StickyKeysHandlerDelegate { - public: - StickyKeysHandlerDelegateImpl(); - virtual ~StickyKeysHandlerDelegateImpl(); - - // StickyKeysHandlerDelegate overrides. - virtual void DispatchKeyEvent(ui::KeyEvent* event, - aura::Window* target) OVERRIDE; - - virtual void DispatchMouseEvent(ui::MouseEvent* event, - aura::Window* target) OVERRIDE; - - virtual void DispatchScrollEvent(ui::ScrollEvent* event, - aura::Window* target) OVERRIDE; - private: - DISALLOW_COPY_AND_ASSIGN(StickyKeysHandlerDelegateImpl); -}; - -StickyKeysHandlerDelegateImpl::StickyKeysHandlerDelegateImpl() { -} - -StickyKeysHandlerDelegateImpl::~StickyKeysHandlerDelegateImpl() { -} - -void StickyKeysHandlerDelegateImpl::DispatchKeyEvent(ui::KeyEvent* event, - aura::Window* target) { - DCHECK(target); - target->GetDispatcher()->AsRootWindowHostDelegate()->OnHostKeyEvent(event); -} - -void StickyKeysHandlerDelegateImpl::DispatchMouseEvent(ui::MouseEvent* event, - aura::Window* target) { - DCHECK(target); - // We need to send a new, untransformed mouse event to the host. - if (event->IsMouseWheelEvent()) { - ui::MouseWheelEvent new_event(*static_cast<ui::MouseWheelEvent*>(event)); - target->GetDispatcher()->AsRootWindowHostDelegate() - ->OnHostMouseEvent(&new_event); - } else { - ui::MouseEvent new_event(*event, target, target->GetRootWindow()); - target->GetDispatcher()->AsRootWindowHostDelegate() - ->OnHostMouseEvent(&new_event); - } -} - -void StickyKeysHandlerDelegateImpl::DispatchScrollEvent( - ui::ScrollEvent* event, - aura::Window* target) { - DCHECK(target); - target->GetDispatcher()->AsRootWindowHostDelegate() - ->OnHostScrollEvent(event); -} - -} // namespace - -/////////////////////////////////////////////////////////////////////////////// -// StickyKeys -StickyKeys::StickyKeys() - : enabled_(false), - shift_sticky_key_( - new StickyKeysHandler(ui::EF_SHIFT_DOWN, - new StickyKeysHandlerDelegateImpl())), - alt_sticky_key_( - new StickyKeysHandler(ui::EF_ALT_DOWN, - new StickyKeysHandlerDelegateImpl())), - ctrl_sticky_key_( - new StickyKeysHandler(ui::EF_CONTROL_DOWN, - new StickyKeysHandlerDelegateImpl())) { -} - -StickyKeys::~StickyKeys() { -} - -void StickyKeys::Enable(bool enabled) { - if (enabled_ != enabled) { - enabled_ = enabled; - - // Reset key handlers when activating sticky keys to ensure all - // the handlers' states are reset. - if (enabled_) { - shift_sticky_key_.reset( - new StickyKeysHandler(ui::EF_SHIFT_DOWN, - new StickyKeysHandlerDelegateImpl())); - alt_sticky_key_.reset( - new StickyKeysHandler(ui::EF_ALT_DOWN, - new StickyKeysHandlerDelegateImpl())); - ctrl_sticky_key_.reset( - new StickyKeysHandler(ui::EF_CONTROL_DOWN, - new StickyKeysHandlerDelegateImpl())); - } - } -} - -bool StickyKeys::HandleKeyEvent(ui::KeyEvent* event) { - return shift_sticky_key_->HandleKeyEvent(event) || - alt_sticky_key_->HandleKeyEvent(event) || - ctrl_sticky_key_->HandleKeyEvent(event); - return ctrl_sticky_key_->HandleKeyEvent(event); -} - -bool StickyKeys::HandleMouseEvent(ui::MouseEvent* event) { - return shift_sticky_key_->HandleMouseEvent(event) || - alt_sticky_key_->HandleMouseEvent(event) || - ctrl_sticky_key_->HandleMouseEvent(event); -} - -bool StickyKeys::HandleScrollEvent(ui::ScrollEvent* event) { - return shift_sticky_key_->HandleScrollEvent(event) || - alt_sticky_key_->HandleScrollEvent(event) || - ctrl_sticky_key_->HandleScrollEvent(event); -} - -void StickyKeys::OnKeyEvent(ui::KeyEvent* event) { - // Do not consume a translated key event which is generated by an IME. - if (event->type() == ui::ET_TRANSLATED_KEY_PRESS || - event->type() == ui::ET_TRANSLATED_KEY_RELEASE) { - return; - } - - if (enabled_ && HandleKeyEvent(event)) - event->StopPropagation(); -} - -void StickyKeys::OnMouseEvent(ui::MouseEvent* event) { - if (enabled_ && HandleMouseEvent(event)) - event->StopPropagation(); -} - -void StickyKeys::OnScrollEvent(ui::ScrollEvent* event) { - if (enabled_ && HandleScrollEvent(event)) - event->StopPropagation(); -} - -/////////////////////////////////////////////////////////////////////////////// -// StickyKeysHandler -StickyKeysHandler::StickyKeysHandler(ui::EventFlags target_modifier_flag, - StickyKeysHandlerDelegate* delegate) - : modifier_flag_(target_modifier_flag), - current_state_(DISABLED), - event_from_myself_(false), - preparing_to_enable_(false), - scroll_delta_(0), - delegate_(delegate) { -} - -StickyKeysHandler::~StickyKeysHandler() { -} - -StickyKeysHandler::StickyKeysHandlerDelegate::StickyKeysHandlerDelegate() { -} - -StickyKeysHandler::StickyKeysHandlerDelegate::~StickyKeysHandlerDelegate() { -} - -bool StickyKeysHandler::HandleKeyEvent(ui::KeyEvent* event) { - if (event_from_myself_) - return false; // Do not handle self-generated key event. - switch (current_state_) { - case DISABLED: - return HandleDisabledState(event); - case ENABLED: - return HandleEnabledState(event); - case LOCKED: - return HandleLockedState(event); - } - NOTREACHED(); - return false; -} - -bool StickyKeysHandler::HandleMouseEvent(ui::MouseEvent* event) { - preparing_to_enable_ = false; - if (event_from_myself_ || current_state_ == DISABLED - || !ShouldModifyMouseEvent(event)) { - return false; - } - DCHECK(current_state_ == ENABLED || current_state_ == LOCKED); - - AppendModifier(event); - // Only disable on the mouse released event in normal, non-locked mode. - if (current_state_ == ENABLED && event->type() != ui::ET_MOUSE_PRESSED) { - current_state_ = DISABLED; - DispatchEventAndReleaseModifier(event); - return true; - } - - return false; -} - -bool StickyKeysHandler::HandleScrollEvent(ui::ScrollEvent* event) { - preparing_to_enable_ = false; - if (event_from_myself_ || current_state_ == DISABLED) - return false; - DCHECK(current_state_ == ENABLED || current_state_ == LOCKED); - - // We detect a direction change if the current |scroll_delta_| is assigned - // and the offset of the current scroll event has the opposing sign. - bool direction_changed = false; - if (current_state_ == ENABLED && event->type() == ui::ET_SCROLL) { - int offset = event->y_offset(); - if (scroll_delta_) - direction_changed = offset * scroll_delta_ <= 0; - scroll_delta_ = offset; - } - - if (!direction_changed) - AppendModifier(event); - - // We want to modify all the scroll events in the scroll sequence, which ends - // with a fling start event. We also stop when the scroll sequence changes - // direction. - if (current_state_ == ENABLED && - (event->type() == ui::ET_SCROLL_FLING_START || direction_changed)) { - current_state_ = DISABLED; - scroll_delta_ = 0; - DispatchEventAndReleaseModifier(event); - return true; - } - - return false; -} - -StickyKeysHandler::KeyEventType - StickyKeysHandler::TranslateKeyEvent(ui::KeyEvent* event) { - bool is_target_key = false; - if (event->key_code() == ui::VKEY_SHIFT || - event->key_code() == ui::VKEY_LSHIFT || - event->key_code() == ui::VKEY_RSHIFT) { - is_target_key = (modifier_flag_ == ui::EF_SHIFT_DOWN); - } else if (event->key_code() == ui::VKEY_CONTROL || - event->key_code() == ui::VKEY_LCONTROL || - event->key_code() == ui::VKEY_RCONTROL) { - is_target_key = (modifier_flag_ == ui::EF_CONTROL_DOWN); - } else if (event->key_code() == ui::VKEY_MENU || - event->key_code() == ui::VKEY_LMENU || - event->key_code() == ui::VKEY_RMENU) { - is_target_key = (modifier_flag_ == ui::EF_ALT_DOWN); - } else { - return event->type() == ui::ET_KEY_PRESSED ? - NORMAL_KEY_DOWN : NORMAL_KEY_UP; - } - - if (is_target_key) { - return event->type() == ui::ET_KEY_PRESSED ? - TARGET_MODIFIER_DOWN : TARGET_MODIFIER_UP; - } - return event->type() == ui::ET_KEY_PRESSED ? - OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP; -} - -bool StickyKeysHandler::HandleDisabledState(ui::KeyEvent* event) { - switch (TranslateKeyEvent(event)) { - case TARGET_MODIFIER_UP: - if (preparing_to_enable_) { - preparing_to_enable_ = false; - scroll_delta_ = 0; - current_state_ = ENABLED; - modifier_up_event_.reset(new ui::KeyEvent(*event)); - return true; - } - return false; - case TARGET_MODIFIER_DOWN: - preparing_to_enable_ = true; - return false; - case NORMAL_KEY_DOWN: - preparing_to_enable_ = false; - return false; - case NORMAL_KEY_UP: - case OTHER_MODIFIER_DOWN: - case OTHER_MODIFIER_UP: - return false; - } - NOTREACHED(); - return false; -} - -bool StickyKeysHandler::HandleEnabledState(ui::KeyEvent* event) { - switch (TranslateKeyEvent(event)) { - case NORMAL_KEY_UP: - case TARGET_MODIFIER_DOWN: - return true; - case TARGET_MODIFIER_UP: - current_state_ = LOCKED; - modifier_up_event_.reset(); - return true; - case NORMAL_KEY_DOWN: { - current_state_ = DISABLED; - AppendModifier(event); - DispatchEventAndReleaseModifier(event); - return true; - } - case OTHER_MODIFIER_DOWN: - case OTHER_MODIFIER_UP: - return false; - } - NOTREACHED(); - return false; -} - -bool StickyKeysHandler::HandleLockedState(ui::KeyEvent* event) { - switch (TranslateKeyEvent(event)) { - case TARGET_MODIFIER_DOWN: - return true; - case TARGET_MODIFIER_UP: - current_state_ = DISABLED; - return false; - case NORMAL_KEY_DOWN: - case NORMAL_KEY_UP: - AppendModifier(event); - return false; - case OTHER_MODIFIER_DOWN: - case OTHER_MODIFIER_UP: - return false; - } - NOTREACHED(); - return false; -} - -void StickyKeysHandler::DispatchEventAndReleaseModifier(ui::Event* event) { - DCHECK(event->IsKeyEvent() || - event->IsMouseEvent() || - event->IsScrollEvent()); - DCHECK(modifier_up_event_.get()); - aura::Window* target = static_cast<aura::Window*>(event->target()); - DCHECK(target); - aura::Window* root_window = target->GetRootWindow(); - DCHECK(root_window); - - aura::WindowTracker window_tracker; - window_tracker.Add(target); - - event_from_myself_ = true; - if (event->IsKeyEvent()) { - delegate_->DispatchKeyEvent(static_cast<ui::KeyEvent*>(event), target); - } else if (event->IsMouseEvent()) { - delegate_->DispatchMouseEvent(static_cast<ui::MouseEvent*>(event), target); - } else { - delegate_->DispatchScrollEvent( - static_cast<ui::ScrollEvent*>(event), target); - } - - // The action triggered above may have destroyed the event target, in which - // case we will dispatch the modifier up event to the root window instead. - aura::Window* modifier_up_target = - window_tracker.Contains(target) ? target : root_window; - delegate_->DispatchKeyEvent(modifier_up_event_.get(), modifier_up_target); - event_from_myself_ = false; -} - -void StickyKeysHandler::AppendNativeEventMask(unsigned int* state) { - unsigned int& state_ref = *state; - switch (modifier_flag_) { - case ui::EF_CONTROL_DOWN: - state_ref |= ControlMask; - break; - case ui::EF_ALT_DOWN: - state_ref |= Mod1Mask; - break; - case ui::EF_SHIFT_DOWN: - state_ref |= ShiftMask; - break; - default: - NOTREACHED(); - } -} - -void StickyKeysHandler::AppendModifier(ui::KeyEvent* event) { -#if defined(USE_X11) - XEvent* xev = event->native_event(); - if (xev) { - XKeyEvent* xkey = &(xev->xkey); - AppendNativeEventMask(&xkey->state); - } -#elif defined(USE_OZONE) - NOTIMPLEMENTED() << "Modifier key is not handled"; -#endif - event->set_flags(event->flags() | modifier_flag_); - event->set_character(ui::GetCharacterFromKeyCode(event->key_code(), - event->flags())); - event->NormalizeFlags(); -} - -void StickyKeysHandler::AppendModifier(ui::MouseEvent* event) { -#if defined(USE_X11) - XEvent* xev = event->native_event(); - if (xev) { - XButtonEvent* xkey = &(xev->xbutton); - AppendNativeEventMask(&xkey->state); - } -#elif defined(USE_OZONE) - NOTIMPLEMENTED() << "Modifier key is not handled"; -#endif - event->set_flags(event->flags() | modifier_flag_); -} - -void StickyKeysHandler::AppendModifier(ui::ScrollEvent* event) { -#if defined(USE_X11) - XEvent* xev = event->native_event(); - if (xev) { - XIDeviceEvent* xievent = - static_cast<XIDeviceEvent*>(xev->xcookie.data); - if (xievent) { - AppendNativeEventMask(reinterpret_cast<unsigned int*>( - &xievent->mods.effective)); - } - } -#elif defined(USE_OZONE) - NOTIMPLEMENTED() << "Modifier key is not handled"; -#endif - event->set_flags(event->flags() | modifier_flag_); -} - -} // namespace ash diff --git a/chromium/ash/wm/sticky_keys.h b/chromium/ash/wm/sticky_keys.h deleted file mode 100644 index 1a2789214bb..00000000000 --- a/chromium/ash/wm/sticky_keys.h +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2013 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_STICKY_KEYS_H_ -#define ASH_WM_STICKY_KEYS_H_ - -#include "ash/ash_export.h" -#include "base/memory/scoped_ptr.h" -#include "ui/events/event_constants.h" -#include "ui/events/event_handler.h" - -namespace ui { -class Event; -class KeyEvent; -class MouseEvent; -} // namespace ui - -namespace aura { -class Window; -} // namespace aura - -namespace ash { - -class StickyKeysHandler; - -// StickyKeys is an accessibility feature for users to be able to compose key -// and mouse event with modifier keys without simultaneous key press event. -// Instead they can compose events separately pressing each of the modifier -// keys involved. -// e.g. Composing Ctrl + T -// User Action : The KeyEvent widget will receives -// ---------------------------------------------------------- -// 1. Press Ctrl key : Ctrl Keydown. -// 2. Release Ctrl key : No event -// 3. Press T key : T keydown event with ctrl modifier. -// 4. : Ctrl Keyup -// 5. Release T key : T keyup without ctrl modifier (Windows behavior) -// -// By typing same modifier keys twice, users can generate bunch of modified key -// events. -// e.g. To focus tabs consistently by Ctrl + 1, Ctrl + 2 ... -// User Action : The KeyEvent widget will receives -// ---------------------------------------------------------- -// 1. Press Ctrl key : Ctrl Keydown -// 2. Release Ctrl key : No event -// 3. Press Ctrl key : No event -// 4. Release Ctrl key : No event -// 5. Press 1 key : 1 Keydown event with Ctrl modifier. -// 6. Release 1 key : 1 Keyup event with Ctrl modifier. -// 7. Press 2 key : 2 Keydown event with Ctrl modifier. -// 8. Release 2 key : 2 Keyup event with Ctrl modifier. -// 9. Press Ctrl key : No event -// 10. Release Ctrl key: Ctrl Keyup -// -// In the case of Chrome OS, StickyKeys supports Shift,Alt,Ctrl modifiers. Each -// handling or state is performed independently. -// -// StickyKeys is disabled by default. -class ASH_EXPORT StickyKeys : public ui::EventHandler { - public: - StickyKeys(); - virtual ~StickyKeys(); - - // Activate sticky keys to intercept and modify incoming events. - void Enable(bool enabled); - - private: - // Handles keyboard event. Returns true if Sticky key consumes keyboard event. - bool HandleKeyEvent(ui::KeyEvent* event); - - // Handles mouse event. Returns true if sticky key consumes mouse event. - bool HandleMouseEvent(ui::MouseEvent* event); - - // Handles scroll event. Returns true if sticky key consumes scroll event. - bool HandleScrollEvent(ui::ScrollEvent* event); - - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; - - // Whether sticky keys is activated and modifying events. - bool enabled_; - - // Sticky key handlers. - scoped_ptr<StickyKeysHandler> shift_sticky_key_; - scoped_ptr<StickyKeysHandler> alt_sticky_key_; - scoped_ptr<StickyKeysHandler> ctrl_sticky_key_; - - DISALLOW_COPY_AND_ASSIGN(StickyKeys); -}; - -// StickyKeysHandler handles key event and performs StickyKeys for specific -// modifier keys. If monitored keyboard events are recieved, StickyKeysHandler -// changes internal state. If non modifier keyboard events or mouse events are -// received, StickyKeysHandler will append modifier based on internal state. -// For other events, StickyKeysHandler does nothing. -// -// The DISABLED state is default state and any incoming non modifier keyboard -// events will not be modified. The ENABLED state is one shot modification -// state. Only next keyboard event will be modified. After that, internal state -// will be back to DISABLED state with sending modifier keyup event. In the case -// of LOCKED state, all incomming keyboard events will be modified. The LOCKED -// state will be back to DISABLED state by next monitoring modifier key. -// -// The detailed state flow as follows: -// Current state -// | DISABLED | ENABLED | LOCKED | -// ----------------------------------------------------------------| -// Modifier KeyDown | noop | noop(*) | noop(*) | -// Modifier KeyUp | To ENABLED(*) | To LOCKED(*) | To DISABLED | -// Normal KeyDown | noop | To DISABLED(#) | noop(#) | -// Normal KeyUp | noop | noop | noop(#) | -// Other KeyUp/Down | noop | noop | noop | -// Mouse Press | noop | noop(#) | noop(#) | -// Mouse Release | noop | To DISABLED(#) | noop(#) | -// Mouse Wheel | noop | To DISABLED(#) | noop(#) | -// Other Mouse Event| noop | noop | noop | -// -// Here, (*) means key event will be consumed by StickyKeys, and (#) means event -// is modified. -class ASH_EXPORT StickyKeysHandler { - public: - class StickyKeysHandlerDelegate { - public: - StickyKeysHandlerDelegate(); - virtual ~StickyKeysHandlerDelegate(); - - // Dispatches keyboard event synchronously. - virtual void DispatchKeyEvent(ui::KeyEvent* event, - aura::Window* target) = 0; - - // Dispatches mouse event synchronously. - virtual void DispatchMouseEvent(ui::MouseEvent* event, - aura::Window* target) = 0; - - // Dispatches scroll event synchronously. - virtual void DispatchScrollEvent(ui::ScrollEvent* event, - aura::Window* target) = 0; - }; - // Represents Sticky Key state. - enum StickyKeyState { - // The sticky key is disabled. Incomming non modifier key events are not - // affected. - DISABLED, - // The sticky key is enabled. Incomming non modifier key down events are - // modified with |modifier_flag_|. After that, sticky key state become - // DISABLED. - ENABLED, - // The sticky key is locked. Incomming non modifier key down events are - // modified with |modifier_flag_|. - LOCKED, - }; - - // This class takes an ownership of |delegate|. - StickyKeysHandler(ui::EventFlags modifier_flag, - StickyKeysHandlerDelegate* delegate); - ~StickyKeysHandler(); - - // Handles key event. Returns true if key is consumed. - bool HandleKeyEvent(ui::KeyEvent* event); - - // Handles a mouse event. Returns true if mouse event is consumed. - bool HandleMouseEvent(ui::MouseEvent* event); - - // Handles a scroll event. Returns true if scroll event is consumed. - bool HandleScrollEvent(ui::ScrollEvent* event); - - // Returns current internal state. - StickyKeyState current_state() const { return current_state_; } - - private: - // Represents event type in Sticky Key context. - enum KeyEventType { - TARGET_MODIFIER_DOWN, // The monitoring modifier key is down. - TARGET_MODIFIER_UP, // The monitoring modifier key is up. - NORMAL_KEY_DOWN, // The non modifier key is down. - NORMAL_KEY_UP, // The non modifier key is up. - OTHER_MODIFIER_DOWN, // The modifier key but not monitored key is down. - OTHER_MODIFIER_UP, // The modifier key but not monitored key is up. - }; - - // Translates |event| to sticky keys event type. - KeyEventType TranslateKeyEvent(ui::KeyEvent* event); - - // Handles key event in DISABLED state. - bool HandleDisabledState(ui::KeyEvent* event); - - // Handles key event in ENABLED state. - bool HandleEnabledState(ui::KeyEvent* event); - - // Handles key event in LOCKED state. - bool HandleLockedState(ui::KeyEvent* event); - - // Dispatches |event| to its target and then dispatch a key released event - // for the modifier key. This function is required to ensure that the events - // are sent in the correct order when disabling sticky key after a key/mouse - // button press. - void DispatchEventAndReleaseModifier(ui::Event* event); - - // Adds |modifier_flags_| to a native X11 event state mask. - void AppendNativeEventMask(unsigned int* state); - - // Adds |modifier_flags_| into |event|. - void AppendModifier(ui::KeyEvent* event); - void AppendModifier(ui::MouseEvent* event); - void AppendModifier(ui::ScrollEvent* event); - - // The modifier flag to be monitored and appended. - const ui::EventFlags modifier_flag_; - - // The current sticky key status. - StickyKeyState current_state_; - - // True if the received key event is sent by StickyKeyHandler. - bool event_from_myself_; - - // True if we received the TARGET_MODIFIER_DOWN event while in the DISABLED - // state but before we receive the TARGET_MODIFIER_UP event. Normal - // shortcuts (eg. ctrl + t) during this time will prevent a transition to - // the ENABLED state. - bool preparing_to_enable_; - - // Tracks the scroll direction of the current scroll sequence. Sticky keys - // stops modifying the scroll events of the sequence when the direction - // changes. If no sequence is tracked, the value is 0. - int scroll_delta_; - - // The modifier up key event to be sent on non modifier key on ENABLED state. - scoped_ptr<ui::KeyEvent> modifier_up_event_; - - scoped_ptr<StickyKeysHandlerDelegate> delegate_; - - DISALLOW_COPY_AND_ASSIGN(StickyKeysHandler); -}; - -} // namespace ash - -#endif // ASH_WM_STICKY_KEYS_H_ diff --git a/chromium/ash/wm/sticky_keys_unittest.cc b/chromium/ash/wm/sticky_keys_unittest.cc deleted file mode 100644 index d6fc660e54e..00000000000 --- a/chromium/ash/wm/sticky_keys_unittest.cc +++ /dev/null @@ -1,876 +0,0 @@ -// Copyright 2013 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/sticky_keys.h" - -#include <X11/Xlib.h> -#undef None -#undef Bool -#undef RootWindow - -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "base/bind.h" -#include "base/callback.h" -#include "base/memory/scoped_vector.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_tree_host_delegate.h" -#include "ui/events/event_handler.h" -#include "ui/events/test/events_test_utils_x11.h" -#include "ui/events/x/device_data_manager.h" - -namespace ash { - -namespace { - -// The device id of the test scroll device. -const unsigned int kScrollDeviceId = 1; - -} // namespace - -// Keeps a buffer of handled events. -class EventBuffer : public ui::EventHandler { - public: - EventBuffer() {} - virtual ~EventBuffer() {} - - void PopEvents(ScopedVector<ui::Event>* events) { - events->clear(); - events->swap(events_); - } - - private: - // ui::EventHandler overrides: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE { - events_.push_back(new ui::KeyEvent(*event)); - } - - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { - if (event->IsMouseWheelEvent()) { - events_.push_back( - new ui::MouseWheelEvent(*static_cast<ui::MouseWheelEvent*>(event))); - } else { - events_.push_back(new ui::MouseEvent(event->native_event())); - } - } - - ScopedVector<ui::Event> events_; - - DISALLOW_COPY_AND_ASSIGN(EventBuffer); -}; - -// A testable and StickyKeysHandler. -class MockStickyKeysHandlerDelegate : - public StickyKeysHandler::StickyKeysHandlerDelegate { - public: - class Delegate { - public: - virtual aura::Window* GetExpectedTarget() = 0; - virtual void OnShortcutPressed() = 0; - - protected: - virtual ~Delegate() {} - }; - - MockStickyKeysHandlerDelegate(Delegate* delegate) : delegate_(delegate) {} - - virtual ~MockStickyKeysHandlerDelegate() {} - - // StickyKeysHandler override. - virtual void DispatchKeyEvent(ui::KeyEvent* event, - aura::Window* target) OVERRIDE { - ASSERT_EQ(delegate_->GetExpectedTarget(), target); - - // Detect a special shortcut when it is dispatched. This shortcut will - // not be hit in the LOCKED state as this case does not involve the - // delegate. - if (event->type() == ui::ET_KEY_PRESSED && - event->key_code() == ui::VKEY_J && - event->flags() | ui::EF_CONTROL_DOWN) { - delegate_->OnShortcutPressed(); - } - - events_.push_back(new ui::KeyEvent(*event)); - } - - virtual void DispatchMouseEvent(ui::MouseEvent* event, - aura::Window* target) OVERRIDE { - ASSERT_EQ(delegate_->GetExpectedTarget(), target); - events_.push_back( - new ui::MouseEvent(*event, target, target->GetRootWindow())); - } - - virtual void DispatchScrollEvent(ui::ScrollEvent* event, - aura::Window* target) OVERRIDE { - events_.push_back(new ui::ScrollEvent(event->native_event())); - } - - // Returns the count of dispatched events. - size_t GetEventCount() const { - return events_.size(); - } - - // Returns the |index|-th dispatched event. - const ui::Event* GetEvent(size_t index) const { - return events_[index]; - } - - // Clears all previously dispatched events. - void ClearEvents() { - events_.clear(); - } - - private: - ScopedVector<ui::Event> events_; - Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(MockStickyKeysHandlerDelegate); -}; - -class StickyKeysTest : public test::AshTestBase, - public MockStickyKeysHandlerDelegate::Delegate { - protected: - StickyKeysTest() - : target_(NULL), - root_window_(NULL) {} - - virtual void SetUp() OVERRIDE { - test::AshTestBase::SetUp(); - - // |target_| owned by root window of shell. It is still safe to delete - // it ourselves. - target_ = CreateTestWindowInShellWithId(0); - root_window_ = target_->GetRootWindow(); - } - - virtual void TearDown() OVERRIDE { - test::AshTestBase::TearDown(); - } - - // Overridden from MockStickyKeysHandlerDelegate::Delegate: - virtual aura::Window* GetExpectedTarget() OVERRIDE { - return target_ ? target_ : root_window_; - } - - virtual void OnShortcutPressed() OVERRIDE { - if (target_) { - delete target_; - target_ = NULL; - } - } - - ui::KeyEvent* GenerateKey(bool is_key_press, ui::KeyboardCode code) { - scoped_xevent_.InitKeyEvent( - is_key_press ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, - code, - 0); - ui::KeyEvent* event = new ui::KeyEvent(scoped_xevent_, false); - ui::Event::DispatcherApi dispatcher(event); - dispatcher.set_target(target_); - return event; - } - - ui::MouseEvent* GenerateMouseEvent(bool is_button_press) { - scoped_xevent_.InitButtonEvent( - is_button_press ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED, 0); - ui::MouseEvent* event = new ui::MouseEvent(scoped_xevent_); - ui::Event::DispatcherApi dispatcher(event); - dispatcher.set_target(target_); - return event; - } - - ui::MouseWheelEvent* GenerateMouseWheelEvent(int wheel_delta) { - EXPECT_NE(0, wheel_delta); - scoped_xevent_.InitMouseWheelEvent(wheel_delta, 0); - ui::MouseWheelEvent* event = new ui::MouseWheelEvent(scoped_xevent_); - ui::Event::DispatcherApi dispatcher(event); - dispatcher.set_target(target_); - return event; - } - - ui::ScrollEvent* GenerateScrollEvent(int scroll_delta) { - scoped_xevent_.InitScrollEvent(kScrollDeviceId, // deviceid - 0, // x_offset - scroll_delta, // y_offset - 0, // x_offset_ordinal - scroll_delta, // y_offset_ordinal - 2); // finger_count - ui::ScrollEvent* event = new ui::ScrollEvent(scoped_xevent_); - ui::Event::DispatcherApi dispatcher(event); - dispatcher.set_target(target_); - return event; - } - - ui::ScrollEvent* GenerateFlingScrollEvent(int fling_delta, - bool is_cancel) { - scoped_xevent_.InitFlingScrollEvent( - kScrollDeviceId, // deviceid - 0, // x_velocity - fling_delta, // y_velocity - 0, // x_velocity_ordinal - fling_delta, // y_velocity_ordinal - is_cancel); // is_cancel - ui::ScrollEvent* event = new ui::ScrollEvent(scoped_xevent_); - ui::Event::DispatcherApi dispatcher(event); - dispatcher.set_target(target_); - return event; - } - - // Creates a synthesized KeyEvent that is not backed by a native event. - ui::KeyEvent* GenerateSynthesizedKeyEvent( - bool is_key_press, ui::KeyboardCode code) { - ui::KeyEvent* event = new ui::KeyEvent( - is_key_press ? ui::ET_KEY_PRESSED : ui::ET_MOUSE_RELEASED, - code, 0, true); - ui::Event::DispatcherApi dispatcher(event); - dispatcher.set_target(target_); - return event; - } - - // Creates a synthesized MouseEvent that is not backed by a native event. - ui::MouseEvent* GenerateSynthesizedMouseEvent(bool is_button_press) { - ui::MouseEvent* event = new ui::MouseEvent( - is_button_press ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED, - gfx::Point(0, 0), - gfx::Point(0, 0), - ui::EF_LEFT_MOUSE_BUTTON); - ui::Event::DispatcherApi dispatcher(event); - dispatcher.set_target(target_); - return event; - } - - void SendActivateStickyKeyPattern(StickyKeysHandler* handler, - ui::KeyboardCode key_code) { - scoped_ptr<ui::KeyEvent> ev; - ev.reset(GenerateKey(true, key_code)); - handler->HandleKeyEvent(ev.get()); - ev.reset(GenerateKey(false, key_code)); - handler->HandleKeyEvent(ev.get()); - } - - void SendActivateStickyKeyPattern(aura::RootWindowHostDelegate* delegate, - ui::KeyboardCode key_code) { - scoped_ptr<ui::KeyEvent> ev; - ev.reset(GenerateKey(true, key_code)); - delegate->OnHostKeyEvent(ev.get()); - ev.reset(GenerateKey(false, key_code)); - delegate->OnHostKeyEvent(ev.get()); - } - - aura::Window* target() { return target_; } - - private: - // Owned by root window of shell, but we can still delete |target_| safely. - aura::Window* target_; - // The root window of |target_|. Not owned. - aura::Window* root_window_; - - // Used to construct the various X events. - ui::ScopedXI2Event scoped_xevent_; - - DISALLOW_COPY_AND_ASSIGN(StickyKeysTest); -}; - -TEST_F(StickyKeysTest, BasicOneshotScenarioTest) { - scoped_ptr<ui::KeyEvent> ev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate); - - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - // By typing Shift key, internal state become ENABLED. - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - ev.reset(GenerateKey(true, ui::VKEY_A)); - sticky_key.HandleKeyEvent(ev.get()); - - // Next keyboard event is shift modified. - EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); - - ev.reset(GenerateKey(false, ui::VKEY_A)); - sticky_key.HandleKeyEvent(ev.get()); - - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - // Making sure Shift up keyboard event is dispatched. - ASSERT_EQ(2U, mock_delegate->GetEventCount()); - EXPECT_EQ(ui::ET_KEY_PRESSED, mock_delegate->GetEvent(0)->type()); - EXPECT_EQ(ui::VKEY_A, - static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(0)) - ->key_code()); - EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetEvent(1)->type()); - EXPECT_EQ(ui::VKEY_SHIFT, - static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) - ->key_code()); - - // Enabled state is one shot, so next key event should not be shift modified. - ev.reset(GenerateKey(true, ui::VKEY_A)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_FALSE(ev->flags() & ui::EF_SHIFT_DOWN); - - ev.reset(GenerateKey(false, ui::VKEY_A)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_FALSE(ev->flags() & ui::EF_SHIFT_DOWN); -} - -TEST_F(StickyKeysTest, BasicLockedScenarioTest) { - scoped_ptr<ui::KeyEvent> ev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate); - - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - // By typing shift key, internal state become ENABLED. - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - // By typing shift key again, internal state become LOCKED. - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); - - // All keyboard events including keyUp become shift modified. - ev.reset(GenerateKey(true, ui::VKEY_A)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); - - ev.reset(GenerateKey(false, ui::VKEY_A)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); - - // Locked state keeps after normal keyboard event. - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); - - ev.reset(GenerateKey(true, ui::VKEY_B)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); - - ev.reset(GenerateKey(false, ui::VKEY_B)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); - - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); - - // By typing shift key again, internal state become back to DISABLED. - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); -} - -TEST_F(StickyKeysTest, NonTargetModifierTest) { - scoped_ptr<ui::KeyEvent> ev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate); - - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - // Non target modifier key does not affect internal state - ev.reset(GenerateKey(true, ui::VKEY_MENU)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - ev.reset(GenerateKey(false, ui::VKEY_MENU)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - // Non target modifier key does not affect internal state - ev.reset(GenerateKey(true, ui::VKEY_MENU)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - ev.reset(GenerateKey(false, ui::VKEY_MENU)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); - - // Non target modifier key does not affect internal state - ev.reset(GenerateKey(true, ui::VKEY_MENU)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); - - ev.reset(GenerateKey(false, ui::VKEY_MENU)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); -} - -TEST_F(StickyKeysTest, NormalShortcutTest) { - // Sticky keys should not be enabled if we perform a normal shortcut. - scoped_ptr<ui::KeyEvent> ev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); - - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - // Perform ctrl+n shortcut. - ev.reset(GenerateKey(true, ui::VKEY_CONTROL)); - sticky_key.HandleKeyEvent(ev.get()); - ev.reset(GenerateKey(true, ui::VKEY_N)); - sticky_key.HandleKeyEvent(ev.get()); - ev.reset(GenerateKey(false, ui::VKEY_N)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - // Sticky keys should not be enabled afterwards. - ev.reset(GenerateKey(false, ui::VKEY_CONTROL)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); -} - -TEST_F(StickyKeysTest, NormalModifiedClickTest) { - scoped_ptr<ui::KeyEvent> kev; - scoped_ptr<ui::MouseEvent> mev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); - - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - // Perform ctrl+click. - kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); - sticky_key.HandleKeyEvent(kev.get()); - mev.reset(GenerateMouseEvent(true)); - sticky_key.HandleMouseEvent(mev.get()); - mev.reset(GenerateMouseEvent(false)); - sticky_key.HandleMouseEvent(mev.get()); - - // Sticky keys should not be enabled afterwards. - kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); - sticky_key.HandleKeyEvent(kev.get()); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); -} - -TEST_F(StickyKeysTest, NormalModifiedScrollTest) { - ui::SetUpScrollDeviceForTest(kScrollDeviceId); - - scoped_ptr<ui::KeyEvent> kev; - scoped_ptr<ui::ScrollEvent> sev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); - - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - // Perform ctrl+scroll. - kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); - sev.reset(GenerateFlingScrollEvent(0, true)); - sticky_key.HandleScrollEvent(sev.get()); - sev.reset(GenerateScrollEvent(10)); - sticky_key.HandleScrollEvent(sev.get()); - sev.reset(GenerateFlingScrollEvent(10, false)); - sticky_key.HandleScrollEvent(sev.get()); - - // Sticky keys should not be enabled afterwards. - kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); - sticky_key.HandleKeyEvent(kev.get()); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); -} - -TEST_F(StickyKeysTest, MouseEventOneshot) { - scoped_ptr<ui::MouseEvent> ev; - scoped_ptr<ui::KeyEvent> kev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); - - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - // We should still be in the ENABLED state until we get the mouse - // release event. - ev.reset(GenerateMouseEvent(true)); - sticky_key.HandleMouseEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - ev.reset(GenerateMouseEvent(false)); - sticky_key.HandleMouseEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - // Making sure modifier key release event is dispatched in the right order. - ASSERT_EQ(2u, mock_delegate->GetEventCount()); - EXPECT_EQ(ui::ET_MOUSE_RELEASED, mock_delegate->GetEvent(0)->type()); - EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetEvent(1)->type()); - EXPECT_EQ(ui::VKEY_CONTROL, - static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) - ->key_code()); - - // Enabled state is one shot, so next click should not be control modified. - ev.reset(GenerateMouseEvent(true)); - sticky_key.HandleMouseEvent(ev.get()); - EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); - - ev.reset(GenerateMouseEvent(false)); - sticky_key.HandleMouseEvent(ev.get()); - EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); -} - -TEST_F(StickyKeysTest, MouseEventLocked) { - scoped_ptr<ui::MouseEvent> ev; - scoped_ptr<ui::KeyEvent> kev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); - - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - // Pressing modifier key twice should make us enter lock state. - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); - - // Mouse events should not disable locked mode. - for (int i = 0; i < 3; ++i) { - ev.reset(GenerateMouseEvent(true)); - sticky_key.HandleMouseEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - ev.reset(GenerateMouseEvent(false)); - sticky_key.HandleMouseEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); - } - - // Test with mouse wheel. - for (int i = 0; i < 3; ++i) { - ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); - sticky_key.HandleMouseEvent(ev.get()); - ev.reset(GenerateMouseWheelEvent(-ui::MouseWheelEvent::kWheelDelta)); - sticky_key.HandleMouseEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); - } - - // Test mixed case with mouse events and key events. - ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); - sticky_key.HandleMouseEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - kev.reset(GenerateKey(true, ui::VKEY_N)); - sticky_key.HandleKeyEvent(kev.get()); - EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); - kev.reset(GenerateKey(false, ui::VKEY_N)); - sticky_key.HandleKeyEvent(kev.get()); - EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); - - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); -} - -TEST_F(StickyKeysTest, ScrollEventOneshot) { - ui::SetUpScrollDeviceForTest(kScrollDeviceId); - // Disable Australlian scrolling. - ui::DeviceDataManager::GetInstance()->set_natural_scroll_enabled(true); - - scoped_ptr<ui::ScrollEvent> ev; - scoped_ptr<ui::KeyEvent> kev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); - - int scroll_deltas[] = {-10, 10}; - for (int i = 0; i < 2; ++i) { - mock_delegate->ClearEvents(); - - // Enable sticky keys. - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - // Test a scroll sequence. Sticky keys should only be disabled at the end - // of the scroll sequence. Fling cancel event starts the scroll sequence. - ev.reset(GenerateFlingScrollEvent(0, true)); - sticky_key.HandleScrollEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - // Scrolls should all be modified but not disable sticky keys. - for (int j = 0; j < 3; ++j) { - ev.reset(GenerateScrollEvent(scroll_deltas[i])); - sticky_key.HandleScrollEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - } - - // Fling start event ends scroll sequence. - ev.reset(GenerateFlingScrollEvent(scroll_deltas[i], false)); - sticky_key.HandleScrollEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - ASSERT_EQ(2U, mock_delegate->GetEventCount()); - EXPECT_EQ(ui::ET_SCROLL_FLING_START, mock_delegate->GetEvent(0)->type()); - EXPECT_FLOAT_EQ(scroll_deltas[i], - static_cast<const ui::ScrollEvent*>( - mock_delegate->GetEvent(0))->y_offset()); - EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetEvent(1)->type()); - EXPECT_EQ(ui::VKEY_CONTROL, - static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) - ->key_code()); - } -} - -TEST_F(StickyKeysTest, ScrollDirectionChanged) { - ui::SetUpScrollDeviceForTest(kScrollDeviceId); - // Disable Australlian scrolling. - ui::DeviceDataManager::GetInstance()->set_natural_scroll_enabled(true); - - scoped_ptr<ui::ScrollEvent> ev; - scoped_ptr<ui::KeyEvent> kev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); - - // Test direction change with both boundary value and negative value. - const int direction_change_values[2] = {0, -10}; - for (int i = 0; i < 2; ++i) { - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - // Fling cancel starts scroll sequence. - ev.reset(GenerateFlingScrollEvent(0, true)); - sticky_key.HandleScrollEvent(ev.get()); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - // Test that changing directions in a scroll sequence will - // return sticky keys to DISABLED state. - for (int j = 0; j < 3; ++j) { - ev.reset(GenerateScrollEvent(10)); - sticky_key.HandleScrollEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - } - - ev.reset(GenerateScrollEvent(direction_change_values[i])); - sticky_key.HandleScrollEvent(ev.get()); - EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - } -} - -TEST_F(StickyKeysTest, ScrollEventLocked) { - ui::SetUpScrollDeviceForTest(kScrollDeviceId); - // Disable Australlian scrolling. - ui::DeviceDataManager::GetInstance()->set_natural_scroll_enabled(true); - - scoped_ptr<ui::ScrollEvent> ev; - scoped_ptr<ui::KeyEvent> kev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); - - // Lock sticky keys. - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); - - // Test scroll events are correctly modified in locked state. - for (int i = 0; i < 5; ++i) { - // Fling cancel starts scroll sequence. - ev.reset(GenerateFlingScrollEvent(0, true)); - sticky_key.HandleScrollEvent(ev.get()); - - ev.reset(GenerateScrollEvent(10)); - sticky_key.HandleScrollEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - ev.reset(GenerateScrollEvent(-10)); - sticky_key.HandleScrollEvent(ev.get()); - EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); - - // Fling start ends scroll sequence. - ev.reset(GenerateFlingScrollEvent(-10, false)); - sticky_key.HandleScrollEvent(ev.get()); - } - - EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state()); -} - -TEST_F(StickyKeysTest, EventTargetDestroyed) { - scoped_ptr<ui::KeyEvent> ev; - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); - - target()->Focus(); - - // Go into ENABLED state. - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - // CTRL+J is a special shortcut that will destroy the event target. - ev.reset(GenerateKey(true, ui::VKEY_J)); - sticky_key.HandleKeyEvent(ev.get()); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - EXPECT_FALSE(target()); -} - -TEST_F(StickyKeysTest, SynthesizedEvents) { - // Non-native, internally generated events should be properly handled - // by sticky keys. - MockStickyKeysHandlerDelegate* mock_delegate = - new MockStickyKeysHandlerDelegate(this); - StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); - - // Test non-native key events. - scoped_ptr<ui::KeyEvent> kev; - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - kev.reset(GenerateSynthesizedKeyEvent(true, ui::VKEY_K)); - sticky_key.HandleKeyEvent(kev.get()); - EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - kev.reset(GenerateSynthesizedKeyEvent(false, ui::VKEY_K)); - sticky_key.HandleKeyEvent(kev.get()); - EXPECT_FALSE(kev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); - - // Test non-native mouse events. - SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - scoped_ptr<ui::MouseEvent> mev; - mev.reset(GenerateSynthesizedMouseEvent(true)); - sticky_key.HandleMouseEvent(mev.get()); - EXPECT_TRUE(mev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state()); - - mev.reset(GenerateSynthesizedMouseEvent(false)); - sticky_key.HandleMouseEvent(mev.get()); - EXPECT_TRUE(mev->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state()); -} - -TEST_F(StickyKeysTest, KeyEventDispatchImpl) { - // Test the actual key event dispatch implementation. - EventBuffer buffer; - ScopedVector<ui::Event> events; - aura::RootWindowHostDelegate* delegate = Shell::GetPrimaryRootWindow() - ->GetDispatcher()->AsRootWindowHostDelegate(); - Shell::GetInstance()->AddPreTargetHandler(&buffer); - Shell::GetInstance()->sticky_keys()->Enable(true); - - SendActivateStickyKeyPattern(delegate, ui::VKEY_CONTROL); - scoped_ptr<ui::KeyEvent> ev; - buffer.PopEvents(&events); - - // Test key press event is correctly modified and modifier release - // event is sent. - ev.reset(GenerateKey(true, ui::VKEY_C)); - delegate->OnHostKeyEvent(ev.get()); - buffer.PopEvents(&events); - EXPECT_EQ(2u, events.size()); - EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type()); - EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code()); - EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); - EXPECT_EQ(ui::VKEY_CONTROL, - static_cast<ui::KeyEvent*>(events[1])->key_code()); - - // Test key release event is not modified. - ev.reset(GenerateKey(false, ui::VKEY_C)); - delegate->OnHostKeyEvent(ev.get()); - buffer.PopEvents(&events); - EXPECT_EQ(1u, events.size()); - EXPECT_EQ(ui::ET_KEY_RELEASED, events[0]->type()); - EXPECT_EQ(ui::VKEY_C, - static_cast<ui::KeyEvent*>(events[0])->key_code()); - EXPECT_FALSE(events[0]->flags() & ui::EF_CONTROL_DOWN); - - Shell::GetInstance()->RemovePreTargetHandler(&buffer); -} - -TEST_F(StickyKeysTest, MouseEventDispatchImpl) { - // Test the actual sticky mouse event dispatch implementation. - EventBuffer buffer; - ScopedVector<ui::Event> events; - aura::RootWindowHostDelegate* delegate = Shell::GetPrimaryRootWindow() - ->GetDispatcher()->AsRootWindowHostDelegate(); - Shell::GetInstance()->AddPreTargetHandler(&buffer); - Shell::GetInstance()->sticky_keys()->Enable(true); - - scoped_ptr<ui::MouseEvent> ev; - SendActivateStickyKeyPattern(delegate, ui::VKEY_CONTROL); - buffer.PopEvents(&events); - - // Test mouse press event is correctly modified. - ev.reset(GenerateMouseEvent(true)); - delegate->OnHostMouseEvent(ev.get()); - buffer.PopEvents(&events); - EXPECT_EQ(1u, events.size()); - EXPECT_EQ(ui::ET_MOUSE_PRESSED, events[0]->type()); - EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); - - // Test mouse release event is correctly modified and modifier release - // event is sent. - ev.reset(GenerateMouseEvent(false)); - delegate->OnHostMouseEvent(ev.get()); - buffer.PopEvents(&events); - EXPECT_EQ(2u, events.size()); - EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[0]->type()); - EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); - EXPECT_EQ(ui::VKEY_CONTROL, - static_cast<ui::KeyEvent*>(events[1])->key_code()); - - Shell::GetInstance()->RemovePreTargetHandler(&buffer); -} - -TEST_F(StickyKeysTest, MouseWheelEventDispatchImpl) { - // Test the actual mouse wheel event dispatch implementation. - EventBuffer buffer; - ScopedVector<ui::Event> events; - aura::RootWindowHostDelegate* delegate = Shell::GetPrimaryRootWindow() - ->GetDispatcher()->AsRootWindowHostDelegate(); - Shell::GetInstance()->AddPreTargetHandler(&buffer); - Shell::GetInstance()->sticky_keys()->Enable(true); - - scoped_ptr<ui::MouseWheelEvent> ev; - SendActivateStickyKeyPattern(delegate, ui::VKEY_CONTROL); - buffer.PopEvents(&events); - - // Test positive mouse wheel event is correctly modified and modifier release - // event is sent. - ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); - delegate->OnHostMouseEvent(ev.get()); - buffer.PopEvents(&events); - EXPECT_EQ(2u, events.size()); - EXPECT_TRUE(events[0]->IsMouseWheelEvent()); - EXPECT_EQ(ui::MouseWheelEvent::kWheelDelta, - static_cast<ui::MouseWheelEvent*>(events[0])->y_offset()); - EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); - EXPECT_EQ(ui::VKEY_CONTROL, - static_cast<ui::KeyEvent*>(events[1])->key_code()); - - // Test negative mouse wheel event is correctly modified and modifier release - // event is sent. - SendActivateStickyKeyPattern(delegate, ui::VKEY_CONTROL); - buffer.PopEvents(&events); - - ev.reset(GenerateMouseWheelEvent(-ui::MouseWheelEvent::kWheelDelta)); - delegate->OnHostMouseEvent(ev.get()); - buffer.PopEvents(&events); - EXPECT_EQ(2u, events.size()); - EXPECT_TRUE(events[0]->IsMouseWheelEvent()); - EXPECT_EQ(-ui::MouseWheelEvent::kWheelDelta, - static_cast<ui::MouseWheelEvent*>(events[0])->y_offset()); - EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); - EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); - EXPECT_EQ(ui::VKEY_CONTROL, - static_cast<ui::KeyEvent*>(events[1])->key_code()); - - Shell::GetInstance()->RemovePreTargetHandler(&buffer); -} - -} // namespace ash diff --git a/chromium/ash/wm/system_background_controller.cc b/chromium/ash/wm/system_background_controller.cc deleted file mode 100644 index 7e4054e1378..00000000000 --- a/chromium/ash/wm/system_background_controller.cc +++ /dev/null @@ -1,45 +0,0 @@ -// 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/system_background_controller.h" - -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_type.h" - -namespace ash { -namespace internal { - -SystemBackgroundController::SystemBackgroundController( - aura::Window* root_window, - SkColor color) - : root_window_(root_window), - layer_(new ui::Layer(ui::LAYER_SOLID_COLOR)) { - root_window_->AddObserver(this); - layer_->SetColor(color); - - ui::Layer* root_layer = root_window_->layer(); - layer_->SetBounds(gfx::Rect(root_layer->bounds().size())); - root_layer->Add(layer_.get()); - root_layer->StackAtBottom(layer_.get()); -} - -SystemBackgroundController::~SystemBackgroundController() { - root_window_->RemoveObserver(this); -} - -void SystemBackgroundController::SetColor(SkColor color) { - layer_->SetColor(color); -} - -void SystemBackgroundController::OnWindowBoundsChanged( - aura::Window* root, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - DCHECK_EQ(root_window_, root); - layer_->SetBounds(gfx::Rect(root_window_->layer()->bounds().size())); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/system_background_controller.h b/chromium/ash/wm/system_background_controller.h deleted file mode 100644 index 8d74cdd80a3..00000000000 --- a/chromium/ash/wm/system_background_controller.h +++ /dev/null @@ -1,54 +0,0 @@ -// 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_SYSTEM_BACKGROUND_CONTROLLER_H_ -#define ASH_WM_SYSTEM_BACKGROUND_CONTROLLER_H_ - -#include <string> - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/aura/window_observer.h" - -namespace ui { -class Layer; -} - -namespace ash { -namespace internal { - -// SystemBackgroundController manages a ui::Layer that's stacked at the bottom -// of an aura::RootWindow's children. It exists solely to obscure portions of -// the root layer that aren't covered by any other layers (e.g. before the -// desktop background image is loaded at startup, or when we scale down all of -// the other layers as part of a power-button or window-management animation). -// It should never be transformed or restacked. -class SystemBackgroundController : public aura::WindowObserver { - public: - SystemBackgroundController(aura::Window* root_window, SkColor color); - virtual ~SystemBackgroundController(); - - void SetColor(SkColor color); - - // aura::WindowObserver overrides: - virtual void OnWindowBoundsChanged(aura::Window* root, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - - private: - class HostContentLayerDelegate; - - aura::Window* root_window_; // not owned - - scoped_ptr<ui::Layer> layer_; - - DISALLOW_COPY_AND_ASSIGN(SystemBackgroundController); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_SYSTEM_BACKGROUND_CONTROLLER_H_ diff --git a/chromium/ash/wm/system_gesture_event_filter.cc b/chromium/ash/wm/system_gesture_event_filter.cc deleted file mode 100644 index eb206b9932a..00000000000 --- a/chromium/ash/wm/system_gesture_event_filter.cc +++ /dev/null @@ -1,161 +0,0 @@ -// 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/system_gesture_event_filter.h" - -#include "ash/accelerators/accelerator_controller.h" -#include "ash/accelerators/accelerator_table.h" -#include "ash/ash_switches.h" -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/root_window_controller.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/gestures/long_press_affordance_handler.h" -#include "ash/wm/gestures/overview_gesture_handler.h" -#include "ash/wm/gestures/system_pinch_handler.h" -#include "ash/wm/gestures/two_finger_drag_handler.h" -#include "ash/wm/window_util.h" -#include "base/command_line.h" -#include "ui/aura/root_window.h" -#include "ui/base/ui_base_switches.h" -#include "ui/events/event.h" - -#if defined(OS_CHROMEOS) -#include "ui/events/x/touch_factory_x11.h" -#endif - -namespace { - -aura::Window* GetTargetForSystemGestureEvent(aura::Window* target) { - aura::Window* system_target = target; - if (!system_target || system_target == target->GetRootWindow()) - system_target = ash::wm::GetActiveWindow(); - if (system_target) - system_target = system_target->GetToplevelWindow(); - return system_target; -} - -} // namespace - -namespace ash { -namespace internal { - -SystemGestureEventFilter::SystemGestureEventFilter() - : system_gestures_enabled_(CommandLine::ForCurrentProcess()-> - HasSwitch(ash::switches::kAshEnableAdvancedGestures)), - long_press_affordance_(new LongPressAffordanceHandler), - two_finger_drag_(new TwoFingerDragHandler) { - if (switches::UseOverviewMode()) - overview_gesture_handler_.reset(new OverviewGestureHandler); -} - -SystemGestureEventFilter::~SystemGestureEventFilter() { -} - -void SystemGestureEventFilter::OnMouseEvent(ui::MouseEvent* event) { -#if defined(OS_CHROMEOS) && !defined(USE_OZONE) - if (event->type() == ui::ET_MOUSE_PRESSED && event->native_event() && - ui::TouchFactory::GetInstance()->IsTouchDevicePresent() && - Shell::GetInstance()->delegate()) { - Shell::GetInstance()->metrics()->RecordUserMetricsAction(UMA_MOUSE_DOWN); - } -#endif -} - -void SystemGestureEventFilter::OnScrollEvent(ui::ScrollEvent* event) { - if (overview_gesture_handler_ && - overview_gesture_handler_->ProcessScrollEvent(*event)) { - event->StopPropagation(); - return; - } -} - -void SystemGestureEventFilter::OnTouchEvent(ui::TouchEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - ash::TouchUMA::GetInstance()->RecordTouchEvent(target, *event); -} - -void SystemGestureEventFilter::OnGestureEvent(ui::GestureEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - ash::TouchUMA::GetInstance()->RecordGestureEvent(target, *event); - long_press_affordance_->ProcessEvent(target, event); - - if (two_finger_drag_->ProcessGestureEvent(target, *event)) { - event->StopPropagation(); - return; - } - - if (overview_gesture_handler_ && - overview_gesture_handler_->ProcessGestureEvent(*event)) { - event->StopPropagation(); - return; - } - - if (!system_gestures_enabled_) - return; - - aura::Window* system_target = GetTargetForSystemGestureEvent(target); - if (!system_target) - return; - - RootWindowController* root_controller = - GetRootWindowController(system_target->GetRootWindow()); - CHECK(root_controller); - aura::Window* desktop_container = root_controller->GetContainer( - ash::internal::kShellWindowId_DesktopBackgroundContainer); - if (desktop_container->Contains(system_target)) { - // The gesture was on the desktop window. - if (event->type() == ui::ET_GESTURE_MULTIFINGER_SWIPE && - event->details().swipe_up() && - event->details().touch_points() == - SystemPinchHandler::kSystemGesturePoints) { - ash::AcceleratorController* accelerator = - ash::Shell::GetInstance()->accelerator_controller(); - if (accelerator->PerformAction(CYCLE_FORWARD_MRU, ui::Accelerator())) - event->StopPropagation(); - } - return; - } - - WindowPinchHandlerMap::iterator find = pinch_handlers_.find(system_target); - if (find != pinch_handlers_.end()) { - SystemGestureStatus status = - (*find).second->ProcessGestureEvent(*event); - if (status == SYSTEM_GESTURE_END) - ClearGestureHandlerForWindow(system_target); - event->StopPropagation(); - } else { - if (event->type() == ui::ET_GESTURE_BEGIN && - event->details().touch_points() >= - SystemPinchHandler::kSystemGesturePoints) { - pinch_handlers_[system_target] = new SystemPinchHandler(system_target); - system_target->AddObserver(this); - event->StopPropagation(); - } - } -} - -void SystemGestureEventFilter::OnWindowVisibilityChanged(aura::Window* window, - bool visible) { - if (!visible) - ClearGestureHandlerForWindow(window); -} - -void SystemGestureEventFilter::OnWindowDestroying(aura::Window* window) { - ClearGestureHandlerForWindow(window); -} - -void SystemGestureEventFilter::ClearGestureHandlerForWindow( - aura::Window* window) { - WindowPinchHandlerMap::iterator find = pinch_handlers_.find(window); - if (find == pinch_handlers_.end()) { - // The handler may have already been removed. - return; - } - delete (*find).second; - pinch_handlers_.erase(find); - window->RemoveObserver(this); -} -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/system_gesture_event_filter.h b/chromium/ash/wm/system_gesture_event_filter.h deleted file mode 100644 index 0609802c1d2..00000000000 --- a/chromium/ash/wm/system_gesture_event_filter.h +++ /dev/null @@ -1,79 +0,0 @@ -// 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_SYSTEM_GESTURE_EVENT_FILTER_H_ -#define ASH_WM_SYSTEM_GESTURE_EVENT_FILTER_H_ - -#include "ash/shell.h" -#include "ash/touch/touch_uma.h" -#include "base/timer/timer.h" -#include "ui/aura/window_observer.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/point.h" - -#include <map> - -namespace aura { -class Window; -} - -namespace ui { -class LocatedEvent; -} - -namespace ash { - -namespace test { -class SystemGestureEventFilterTest; -} - -namespace internal { -class LongPressAffordanceHandler; -class OverviewGestureHandler; -class SystemPinchHandler; -class TouchUMA; -class TwoFingerDragHandler; - -// An event filter which handles system level gesture events. -class SystemGestureEventFilter : public ui::EventHandler, - public aura::WindowObserver { - public: - SystemGestureEventFilter(); - virtual ~SystemGestureEventFilter(); - - // Overridden from ui::EventHandler: - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; - virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - // Overridden from aura::WindowObserver. - virtual void OnWindowVisibilityChanged(aura::Window* window, - bool visible) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - private: - friend class ash::test::SystemGestureEventFilterTest; - - // Removes system-gesture handlers for a window. - void ClearGestureHandlerForWindow(aura::Window* window); - - typedef std::map<aura::Window*, SystemPinchHandler*> WindowPinchHandlerMap; - // Created on demand when a system-level pinch gesture is initiated. Destroyed - // when the system-level pinch gesture ends for the window. - WindowPinchHandlerMap pinch_handlers_; - - bool system_gestures_enabled_; - - scoped_ptr<LongPressAffordanceHandler> long_press_affordance_; - scoped_ptr<OverviewGestureHandler> overview_gesture_handler_; - scoped_ptr<TwoFingerDragHandler> two_finger_drag_; - - DISALLOW_COPY_AND_ASSIGN(SystemGestureEventFilter); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_SYSTEM_GESTURE_EVENT_FILTER_H_ diff --git a/chromium/ash/wm/system_gesture_event_filter_unittest.cc b/chromium/ash/wm/system_gesture_event_filter_unittest.cc deleted file mode 100644 index 7a262771a14..00000000000 --- a/chromium/ash/wm/system_gesture_event_filter_unittest.cc +++ /dev/null @@ -1,673 +0,0 @@ -// 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/system_gesture_event_filter.h" - -#include "ash/accelerators/accelerator_controller.h" -#include "ash/ash_switches.h" -#include "ash/display/display_manager.h" -#include "ash/launcher/launcher.h" -#include "ash/shelf/shelf_model.h" -#include "ash/shell.h" -#include "ash/system/brightness_control_delegate.h" -#include "ash/system/tray/system_tray_delegate.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/display_manager_test_api.h" -#include "ash/test/shell_test_api.h" -#include "ash/test/test_shelf_delegate.h" -#include "ash/volume_control_delegate.h" -#include "ash/wm/gestures/long_press_affordance_handler.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "base/command_line.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_windows.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_switches.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" -#include "ui/events/gestures/gesture_configuration.h" -#include "ui/gfx/screen.h" -#include "ui/gfx/size.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -namespace test { - -namespace { - -class DelegatePercentTracker { - public: - explicit DelegatePercentTracker() - : handle_percent_count_(0), - handle_percent_(0){ - } - int handle_percent_count() const { - return handle_percent_count_; - } - double handle_percent() const { - return handle_percent_; - } - void SetPercent(double percent) { - handle_percent_ = percent; - handle_percent_count_++; - } - - private: - int handle_percent_count_; - int handle_percent_; - - DISALLOW_COPY_AND_ASSIGN(DelegatePercentTracker); -}; - -class DummyVolumeControlDelegate : public VolumeControlDelegate, - public DelegatePercentTracker { - public: - explicit DummyVolumeControlDelegate() {} - virtual ~DummyVolumeControlDelegate() {} - - virtual bool HandleVolumeMute(const ui::Accelerator& accelerator) OVERRIDE { - return true; - } - virtual bool HandleVolumeDown(const ui::Accelerator& accelerator) OVERRIDE { - return true; - } - virtual bool HandleVolumeUp(const ui::Accelerator& accelerator) OVERRIDE { - return true; - } - - private: - DISALLOW_COPY_AND_ASSIGN(DummyVolumeControlDelegate); -}; - -class DummyBrightnessControlDelegate : public BrightnessControlDelegate, - public DelegatePercentTracker { - public: - explicit DummyBrightnessControlDelegate() {} - virtual ~DummyBrightnessControlDelegate() {} - - virtual bool HandleBrightnessDown( - const ui::Accelerator& accelerator) OVERRIDE { return true; } - virtual bool HandleBrightnessUp( - const ui::Accelerator& accelerator) OVERRIDE { return true; } - virtual void SetBrightnessPercent(double percent, bool gradual) OVERRIDE { - SetPercent(percent); - } - virtual void GetBrightnessPercent( - const base::Callback<void(double)>& callback) OVERRIDE { - callback.Run(100.0); - } - - private: - DISALLOW_COPY_AND_ASSIGN(DummyBrightnessControlDelegate); -}; - -class ResizableWidgetDelegate : public views::WidgetDelegateView { - public: - ResizableWidgetDelegate() {} - virtual ~ResizableWidgetDelegate() {} - - private: - virtual bool CanResize() const OVERRIDE { return true; } - virtual bool CanMaximize() const OVERRIDE { return true; } - virtual void DeleteDelegate() OVERRIDE { delete this; } - - DISALLOW_COPY_AND_ASSIGN(ResizableWidgetDelegate); -}; - -// Support class for testing windows with a maximum size. -class MaxSizeNCFV : public views::NonClientFrameView { - public: - MaxSizeNCFV() {} - private: - virtual gfx::Size GetMaximumSize() OVERRIDE { - return gfx::Size(200, 200); - } - virtual gfx::Rect GetBoundsForClientView() const OVERRIDE { - return gfx::Rect(); - }; - - virtual gfx::Rect GetWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const OVERRIDE { - return gfx::Rect(); - }; - - // This function must ask the ClientView to do a hittest. We don't do this in - // the parent NonClientView because that makes it more difficult to calculate - // hittests for regions that are partially obscured by the ClientView, e.g. - // HTSYSMENU. - virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE { - return HTNOWHERE; - } - virtual void GetWindowMask(const gfx::Size& size, - gfx::Path* window_mask) OVERRIDE {} - virtual void ResetWindowControls() OVERRIDE {} - virtual void UpdateWindowIcon() OVERRIDE {} - virtual void UpdateWindowTitle() OVERRIDE {} - - DISALLOW_COPY_AND_ASSIGN(MaxSizeNCFV); -}; - -class MaxSizeWidgetDelegate : public views::WidgetDelegateView { - public: - MaxSizeWidgetDelegate() {} - virtual ~MaxSizeWidgetDelegate() {} - - private: - virtual bool CanResize() const OVERRIDE { return true; } - virtual bool CanMaximize() const OVERRIDE { return false; } - virtual void DeleteDelegate() OVERRIDE { delete this; } - virtual views::NonClientFrameView* CreateNonClientFrameView( - views::Widget* widget) OVERRIDE { - return new MaxSizeNCFV; - } - - DISALLOW_COPY_AND_ASSIGN(MaxSizeWidgetDelegate); -}; - -} // namespace - -class SystemGestureEventFilterTest - : public AshTestBase, - public testing::WithParamInterface<bool> { - public: - SystemGestureEventFilterTest() : AshTestBase(), docked_enabled_(GetParam()) {} - virtual ~SystemGestureEventFilterTest() {} - - internal::LongPressAffordanceHandler* GetLongPressAffordance() { - ShellTestApi shell_test(Shell::GetInstance()); - return shell_test.system_gesture_event_filter()-> - long_press_affordance_.get(); - } - - base::OneShotTimer<internal::LongPressAffordanceHandler>* - GetLongPressAffordanceTimer() { - return &GetLongPressAffordance()->timer_; - } - - aura::Window* GetLongPressAffordanceTarget() { - return GetLongPressAffordance()->tap_down_target_; - } - - views::View* GetLongPressAffordanceView() { - return reinterpret_cast<views::View*>( - GetLongPressAffordance()->view_.get()); - } - - // Overridden from AshTestBase: - virtual void SetUp() OVERRIDE { - CommandLine::ForCurrentProcess()->AppendSwitch( - ash::switches::kAshEnableAdvancedGestures); - if (docked_enabled_) { - CommandLine::ForCurrentProcess()->AppendSwitch( - ash::switches::kAshEnableDockedWindows); - } - test::AshTestBase::SetUp(); - // Enable brightness key. - test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()). - SetFirstDisplayAsInternalDisplay(); - } - - private: - // true if docked windows are enabled with a flag. - bool docked_enabled_; - - DISALLOW_COPY_AND_ASSIGN(SystemGestureEventFilterTest); -}; - -ui::GestureEvent* CreateGesture(ui::EventType type, - int x, - int y, - float delta_x, - float delta_y, - int touch_id) { - return new ui::GestureEvent(type, x, y, 0, - base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000), - ui::GestureEventDetails(type, delta_x, delta_y), 1 << touch_id); -} - -TEST_P(SystemGestureEventFilterTest, LongPressAffordanceStateOnCaptureLoss) { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - - aura::test::TestWindowDelegate delegate; - scoped_ptr<aura::Window> window0( - aura::test::CreateTestWindowWithDelegate( - &delegate, 9, gfx::Rect(0, 0, 100, 100), root_window)); - scoped_ptr<aura::Window> window1( - aura::test::CreateTestWindowWithDelegate( - &delegate, 10, gfx::Rect(0, 0, 100, 50), window0.get())); - scoped_ptr<aura::Window> window2( - aura::test::CreateTestWindowWithDelegate( - &delegate, 11, gfx::Rect(0, 50, 100, 50), window0.get())); - - const int kTouchId = 5; - - // Capture first window. - window1->SetCapture(); - EXPECT_TRUE(window1->HasCapture()); - - // Send touch event to first window. - ui::TouchEvent press(ui::ET_TOUCH_PRESSED, - gfx::Point(10, 10), - kTouchId, - ui::EventTimeForNow()); - root_window->GetDispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent( - &press); - EXPECT_TRUE(window1->HasCapture()); - - base::OneShotTimer<internal::LongPressAffordanceHandler>* timer = - GetLongPressAffordanceTimer(); - EXPECT_TRUE(timer->IsRunning()); - EXPECT_EQ(window1, GetLongPressAffordanceTarget()); - - // Force timeout so that the affordance animation can start. - timer->user_task().Run(); - timer->Stop(); - EXPECT_TRUE(GetLongPressAffordance()->is_animating()); - - // Change capture. - window2->SetCapture(); - EXPECT_TRUE(window2->HasCapture()); - - EXPECT_TRUE(GetLongPressAffordance()->is_animating()); - EXPECT_EQ(window1, GetLongPressAffordanceTarget()); - - // Animate to completion. - GetLongPressAffordance()->End(); // end grow animation. - // Force timeout to start shrink animation. - EXPECT_TRUE(timer->IsRunning()); - timer->user_task().Run(); - timer->Stop(); - EXPECT_TRUE(GetLongPressAffordance()->is_animating()); - GetLongPressAffordance()->End(); // end shrink animation. - - // Check if state has reset. - EXPECT_EQ(NULL, GetLongPressAffordanceTarget()); - EXPECT_EQ(NULL, GetLongPressAffordanceView()); -} - -TEST_P(SystemGestureEventFilterTest, MultiFingerSwipeGestures) { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds( - new ResizableWidgetDelegate, root_window, gfx::Rect(0, 0, 600, 600)); - toplevel->Show(); - - const int kSteps = 15; - const int kTouchPoints = 4; - gfx::Point points[kTouchPoints] = { - gfx::Point(250, 250), - gfx::Point(250, 350), - gfx::Point(350, 250), - gfx::Point(350, 350) - }; - - aura::test::EventGenerator generator(root_window, - toplevel->GetNativeWindow()); - - // Swipe down to minimize. - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150); - - wm::WindowState* toplevel_state = - wm::GetWindowState(toplevel->GetNativeWindow()); - EXPECT_TRUE(toplevel_state->IsMinimized()); - - toplevel->Restore(); - - // Swipe up to maximize. - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150); - EXPECT_TRUE(toplevel_state->IsMaximized()); - - toplevel->Restore(); - - // Swipe right to snap. - gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen(); - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0); - gfx::Rect right_tile_bounds = toplevel->GetWindowBoundsInScreen(); - EXPECT_NE(normal_bounds.ToString(), right_tile_bounds.ToString()); - - // Swipe left to snap. - gfx::Point left_points[kTouchPoints]; - for (int i = 0; i < kTouchPoints; ++i) { - left_points[i] = points[i]; - left_points[i].Offset(right_tile_bounds.x(), right_tile_bounds.y()); - } - generator.GestureMultiFingerScroll(kTouchPoints, left_points, 15, kSteps, - -150, 0); - gfx::Rect left_tile_bounds = toplevel->GetWindowBoundsInScreen(); - EXPECT_NE(normal_bounds.ToString(), left_tile_bounds.ToString()); - EXPECT_NE(right_tile_bounds.ToString(), left_tile_bounds.ToString()); - - // Swipe right again. - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0); - gfx::Rect current_bounds = toplevel->GetWindowBoundsInScreen(); - EXPECT_NE(current_bounds.ToString(), left_tile_bounds.ToString()); - EXPECT_EQ(current_bounds.ToString(), right_tile_bounds.ToString()); -} - -TEST_P(SystemGestureEventFilterTest, TwoFingerDrag) { - gfx::Rect bounds(0, 0, 600, 600); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds( - new ResizableWidgetDelegate, root_window, bounds); - toplevel->Show(); - - const int kSteps = 15; - const int kTouchPoints = 2; - gfx::Point points[kTouchPoints] = { - gfx::Point(250, 250), - gfx::Point(350, 350), - }; - - aura::test::EventGenerator generator(root_window, - toplevel->GetNativeWindow()); - - wm::WindowState* toplevel_state = - wm::GetWindowState(toplevel->GetNativeWindow()); - // Swipe down to minimize. - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150); - EXPECT_TRUE(toplevel_state->IsMinimized()); - - toplevel->Restore(); - toplevel->GetNativeWindow()->SetBounds(bounds); - - // Swipe up to maximize. - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150); - EXPECT_TRUE(toplevel_state->IsMaximized()); - - toplevel->Restore(); - toplevel->GetNativeWindow()->SetBounds(bounds); - - // Swipe right to snap. - gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen(); - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0); - gfx::Rect right_tile_bounds = toplevel->GetWindowBoundsInScreen(); - EXPECT_NE(normal_bounds.ToString(), right_tile_bounds.ToString()); - - // Swipe left to snap. - gfx::Point left_points[kTouchPoints]; - for (int i = 0; i < kTouchPoints; ++i) { - left_points[i] = points[i]; - left_points[i].Offset(right_tile_bounds.x(), right_tile_bounds.y()); - } - generator.GestureMultiFingerScroll(kTouchPoints, left_points, 15, kSteps, - -150, 0); - gfx::Rect left_tile_bounds = toplevel->GetWindowBoundsInScreen(); - EXPECT_NE(normal_bounds.ToString(), left_tile_bounds.ToString()); - EXPECT_NE(right_tile_bounds.ToString(), left_tile_bounds.ToString()); - - // Swipe right again. - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0); - gfx::Rect current_bounds = toplevel->GetWindowBoundsInScreen(); - EXPECT_NE(current_bounds.ToString(), left_tile_bounds.ToString()); - EXPECT_EQ(current_bounds.ToString(), right_tile_bounds.ToString()); -} - -TEST_P(SystemGestureEventFilterTest, TwoFingerDragTwoWindows) { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - ui::GestureConfiguration::set_max_separation_for_gesture_touches_in_pixels(0); - views::Widget* first = views::Widget::CreateWindowWithContextAndBounds( - new ResizableWidgetDelegate, root_window, gfx::Rect(0, 0, 50, 100)); - first->Show(); - views::Widget* second = views::Widget::CreateWindowWithContextAndBounds( - new ResizableWidgetDelegate, root_window, gfx::Rect(100, 0, 100, 100)); - second->Show(); - - // Start a two-finger drag on |first|, and then try to use another two-finger - // drag to move |second|. The attempt to move |second| should fail. - const gfx::Rect& first_bounds = first->GetWindowBoundsInScreen(); - const gfx::Rect& second_bounds = second->GetWindowBoundsInScreen(); - const int kSteps = 15; - const int kTouchPoints = 4; - gfx::Point points[kTouchPoints] = { - first_bounds.origin() + gfx::Vector2d(5, 5), - first_bounds.origin() + gfx::Vector2d(30, 10), - second_bounds.origin() + gfx::Vector2d(5, 5), - second_bounds.origin() + gfx::Vector2d(40, 20) - }; - - aura::test::EventGenerator generator(root_window); - // Do not drag too fast to avoid fling. - generator.GestureMultiFingerScroll(kTouchPoints, points, - 50, kSteps, 0, 150); - - EXPECT_NE(first_bounds.ToString(), - first->GetWindowBoundsInScreen().ToString()); - EXPECT_EQ(second_bounds.ToString(), - second->GetWindowBoundsInScreen().ToString()); -} - -TEST_P(SystemGestureEventFilterTest, WindowsWithMaxSizeDontSnap) { - gfx::Rect bounds(250, 150, 100, 100); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds( - new MaxSizeWidgetDelegate, root_window, bounds); - toplevel->Show(); - - const int kSteps = 15; - const int kTouchPoints = 2; - gfx::Point points[kTouchPoints] = { - gfx::Point(bounds.x() + 10, bounds.y() + 30), - gfx::Point(bounds.x() + 30, bounds.y() + 20), - }; - - aura::test::EventGenerator generator(root_window, - toplevel->GetNativeWindow()); - - // Swipe down to minimize. - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150); - wm::WindowState* toplevel_state = - wm::GetWindowState(toplevel->GetNativeWindow()); - EXPECT_TRUE(toplevel_state->IsMinimized()); - - toplevel->Restore(); - toplevel->GetNativeWindow()->SetBounds(bounds); - - // Check that swiping up doesn't maximize. - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150); - EXPECT_FALSE(toplevel_state->IsMaximized()); - - toplevel->Restore(); - toplevel->GetNativeWindow()->SetBounds(bounds); - - // Check that swiping right doesn't snap. - gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen(); - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0); - normal_bounds.set_x(normal_bounds.x() + 150); - EXPECT_EQ(normal_bounds.ToString(), - toplevel->GetWindowBoundsInScreen().ToString()); - - toplevel->GetNativeWindow()->SetBounds(bounds); - - // Check that swiping left doesn't snap. - normal_bounds = toplevel->GetWindowBoundsInScreen(); - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, -150, 0); - normal_bounds.set_x(normal_bounds.x() - 150); - EXPECT_EQ(normal_bounds.ToString(), - toplevel->GetWindowBoundsInScreen().ToString()); - - toplevel->GetNativeWindow()->SetBounds(bounds); - - // Swipe right again, make sure the window still doesn't snap. - normal_bounds = toplevel->GetWindowBoundsInScreen(); - normal_bounds.set_x(normal_bounds.x() + 150); - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0); - EXPECT_EQ(normal_bounds.ToString(), - toplevel->GetWindowBoundsInScreen().ToString()); -} - -TEST_P(SystemGestureEventFilterTest, TwoFingerDragEdge) { - gfx::Rect bounds(0, 0, 100, 100); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds( - new ResizableWidgetDelegate, root_window, bounds); - toplevel->Show(); - - const int kSteps = 15; - const int kTouchPoints = 2; - gfx::Point points[kTouchPoints] = { - gfx::Point(30, 20), // Caption - gfx::Point(0, 40), // Left edge - }; - - EXPECT_EQ(HTLEFT, toplevel->GetNativeWindow()->delegate()-> - GetNonClientComponent(points[1])); - - aura::test::EventGenerator generator(root_window, - toplevel->GetNativeWindow()); - - bounds = toplevel->GetNativeWindow()->bounds(); - // Swipe down. Nothing should happen. - generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150); - EXPECT_EQ(bounds.ToString(), - toplevel->GetNativeWindow()->bounds().ToString()); -} - -TEST_P(SystemGestureEventFilterTest, TwoFingerDragDelayed) { - gfx::Rect bounds(0, 0, 100, 100); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds( - new ResizableWidgetDelegate, root_window, bounds); - toplevel->Show(); - - const int kSteps = 15; - const int kTouchPoints = 2; - gfx::Point points[kTouchPoints] = { - gfx::Point(30, 20), // Caption - gfx::Point(34, 20), // Caption - }; - int delays[kTouchPoints] = {0, 120}; - - EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()-> - GetNonClientComponent(points[0])); - EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()-> - GetNonClientComponent(points[1])); - - aura::test::EventGenerator generator(root_window, - toplevel->GetNativeWindow()); - - bounds = toplevel->GetNativeWindow()->bounds(); - // Swipe right and down starting with one finger. - // Add another finger after 120ms and continue dragging. - // The window should move and the drag should be determined by the center - // point between the fingers. - generator.GestureMultiFingerScrollWithDelays( - kTouchPoints, points, delays, 15, kSteps, 150, 150); - bounds += gfx::Vector2d(150 + (points[1].x() - points[0].x()) / 2, 150); - EXPECT_EQ(bounds.ToString(), - toplevel->GetNativeWindow()->bounds().ToString()); -} - -TEST_P(SystemGestureEventFilterTest, ThreeFingerGestureStopsDrag) { - gfx::Rect bounds(0, 0, 100, 100); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds( - new ResizableWidgetDelegate, root_window, bounds); - toplevel->Show(); - - const int kSteps = 10; - const int kTouchPoints = 3; - gfx::Point points[kTouchPoints] = { - gfx::Point(30, 20), // Caption - gfx::Point(34, 20), // Caption - gfx::Point(38, 20), // Caption - }; - int delays[kTouchPoints] = {0, 0, 120}; - - EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()-> - GetNonClientComponent(points[0])); - EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()-> - GetNonClientComponent(points[1])); - - aura::test::EventGenerator generator(root_window, - toplevel->GetNativeWindow()); - - bounds = toplevel->GetNativeWindow()->bounds(); - // Swipe right and down starting with two fingers. - // Add third finger after 120ms and continue dragging. - // The window should start moving but stop when the 3rd finger touches down. - const int kEventSeparation = 15; - generator.GestureMultiFingerScrollWithDelays( - kTouchPoints, points, delays, kEventSeparation, kSteps, 150, 150); - int expected_drag = 150 / kSteps * 120 / kEventSeparation; - bounds += gfx::Vector2d(expected_drag, expected_drag); - EXPECT_EQ(bounds.ToString(), - toplevel->GetNativeWindow()->bounds().ToString()); -} - -TEST_P(SystemGestureEventFilterTest, DragLeftNearEdgeSnaps) { - gfx::Rect bounds(200, 150, 400, 100); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds( - new ResizableWidgetDelegate, root_window, bounds); - toplevel->Show(); - - const int kSteps = 15; - const int kTouchPoints = 2; - gfx::Point points[kTouchPoints] = { - gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5), - gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5), - }; - aura::test::EventGenerator generator(root_window, - toplevel->GetNativeWindow()); - - // Check that dragging left snaps before reaching the screen edge. - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(root_window).work_area(); - int drag_x = work_area.x() + 20 - points[0].x(); - generator.GestureMultiFingerScroll( - kTouchPoints, points, 120, kSteps, drag_x, 0); - - internal::SnapSizer snap_sizer( - wm::GetWindowState(toplevel->GetNativeWindow()), - gfx::Point(), - internal::SnapSizer::LEFT_EDGE, - internal::SnapSizer::OTHER_INPUT); - gfx::Rect expected_bounds(snap_sizer.target_bounds()); - EXPECT_EQ(expected_bounds.ToString(), - toplevel->GetWindowBoundsInScreen().ToString()); -} - -TEST_P(SystemGestureEventFilterTest, DragRightNearEdgeSnaps) { - gfx::Rect bounds(200, 150, 400, 100); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds( - new ResizableWidgetDelegate, root_window, bounds); - toplevel->Show(); - - const int kSteps = 15; - const int kTouchPoints = 2; - gfx::Point points[kTouchPoints] = { - gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5), - gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5), - }; - aura::test::EventGenerator generator(root_window, - toplevel->GetNativeWindow()); - - // Check that dragging right snaps before reaching the screen edge. - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(root_window).work_area(); - int drag_x = work_area.right() - 20 - points[0].x(); - generator.GestureMultiFingerScroll( - kTouchPoints, points, 120, kSteps, drag_x, 0); - internal::SnapSizer snap_sizer( - wm::GetWindowState(toplevel->GetNativeWindow()), - gfx::Point(), - internal::SnapSizer::RIGHT_EDGE, - internal::SnapSizer::OTHER_INPUT); - gfx::Rect expected_bounds(snap_sizer.target_bounds()); - EXPECT_EQ(expected_bounds.ToString(), - toplevel->GetWindowBoundsInScreen().ToString()); -} - -// Tests run twice - with docked windows disabled or enabled. -INSTANTIATE_TEST_CASE_P(DockedWindowsDisabledOrEnabled, - SystemGestureEventFilterTest, - testing::Bool()); - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/system_modal_container_event_filter.cc b/chromium/ash/wm/system_modal_container_event_filter.cc deleted file mode 100644 index 4412a9c2d45..00000000000 --- a/chromium/ash/wm/system_modal_container_event_filter.cc +++ /dev/null @@ -1,36 +0,0 @@ -// 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/system_modal_container_event_filter.h" - -#include "ash/wm/system_modal_container_event_filter_delegate.h" -#include "ui/aura/window.h" -#include "ui/events/event.h" - -namespace ash { -namespace internal { - -SystemModalContainerEventFilter::SystemModalContainerEventFilter( - SystemModalContainerEventFilterDelegate* delegate) - : delegate_(delegate) { -} - -SystemModalContainerEventFilter::~SystemModalContainerEventFilter() { -} - -void SystemModalContainerEventFilter::OnKeyEvent(ui::KeyEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (!delegate_->CanWindowReceiveEvents(target)) - event->StopPropagation(); -} - -void SystemModalContainerEventFilter::OnMouseEvent( - ui::MouseEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (!delegate_->CanWindowReceiveEvents(target)) - event->StopPropagation(); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/system_modal_container_event_filter.h b/chromium/ash/wm/system_modal_container_event_filter.h deleted file mode 100644 index e1f2e8ea429..00000000000 --- a/chromium/ash/wm/system_modal_container_event_filter.h +++ /dev/null @@ -1,37 +0,0 @@ -// 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_SYSTEM_MODAL_CONTAINER_EVENT_FILTER_H_ -#define ASH_WM_SYSTEM_MODAL_CONTAINER_EVENT_FILTER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/events/event_handler.h" - -namespace ash { -namespace internal { - -class SystemModalContainerEventFilterDelegate; - -class ASH_EXPORT SystemModalContainerEventFilter : public ui::EventHandler { - public: - explicit SystemModalContainerEventFilter( - SystemModalContainerEventFilterDelegate* delegate); - virtual ~SystemModalContainerEventFilter(); - - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - - private: - SystemModalContainerEventFilterDelegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(SystemModalContainerEventFilter); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_SYSTEM_MODAL_CONTAINER_EVENT_FILTER_H_ diff --git a/chromium/ash/wm/system_modal_container_event_filter_delegate.h b/chromium/ash/wm/system_modal_container_event_filter_delegate.h deleted file mode 100644 index 4e27d0000c9..00000000000 --- a/chromium/ash/wm/system_modal_container_event_filter_delegate.h +++ /dev/null @@ -1,26 +0,0 @@ -// 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_MODALITY_EVENT_FILTER_DELEGATE_H_ -#define ASH_WM_MODALITY_EVENT_FILTER_DELEGATE_H_ - -#include "ash/ash_export.h" - -namespace aura { -class Window; -} - -namespace ash { -namespace internal { - -class ASH_EXPORT SystemModalContainerEventFilterDelegate { - public: - // Returns true if |window| can receive the specified event. - virtual bool CanWindowReceiveEvents(aura::Window* window) = 0; -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_MODALITY_EVENT_FILTER_DELEGATE_H_ diff --git a/chromium/ash/wm/system_modal_container_layout_manager.cc b/chromium/ash/wm/system_modal_container_layout_manager.cc deleted file mode 100644 index 2c2cdebb57a..00000000000 --- a/chromium/ash/wm/system_modal_container_layout_manager.cc +++ /dev/null @@ -1,224 +0,0 @@ -// 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/system_modal_container_layout_manager.h" - -#include "ash/session_state_delegate.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/system_modal_container_event_filter.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_util.h" -#include "base/bind.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/capture_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/base/ui_base_switches_util.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animator.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/events/event.h" -#include "ui/gfx/screen.h" -#include "ui/views/background.h" -#include "ui/views/corewm/compound_event_filter.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -//////////////////////////////////////////////////////////////////////////////// -// SystemModalContainerLayoutManager, public: - -SystemModalContainerLayoutManager::SystemModalContainerLayoutManager( - aura::Window* container) - : container_(container), - modal_background_(NULL) { -} - -SystemModalContainerLayoutManager::~SystemModalContainerLayoutManager() { -} - -//////////////////////////////////////////////////////////////////////////////// -// SystemModalContainerLayoutManager, aura::LayoutManager implementation: - -void SystemModalContainerLayoutManager::OnWindowResized() { - if (modal_background_) { - // Note: we have to set the entire bounds with the screen offset. - modal_background_->SetBounds( - Shell::GetScreen()->GetDisplayNearestWindow(container_).bounds()); - } - if (!modal_windows_.empty()) { - aura::Window::Windows::iterator it = modal_windows_.begin(); - for (it = modal_windows_.begin(); it != modal_windows_.end(); ++it) { - gfx::Rect bounds = (*it)->bounds(); - bounds.AdjustToFit(container_->bounds()); - (*it)->SetBounds(bounds); - } - } -} - -void SystemModalContainerLayoutManager::OnWindowAddedToLayout( - aura::Window* child) { - DCHECK((modal_background_ && child == modal_background_->GetNativeView()) || - child->type() == aura::client::WINDOW_TYPE_NORMAL || - child->type() == aura::client::WINDOW_TYPE_POPUP); - DCHECK( - container_->id() != internal::kShellWindowId_LockSystemModalContainer || - Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked()); - - child->AddObserver(this); - if (child->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE) - AddModalWindow(child); -} - -void SystemModalContainerLayoutManager::OnWillRemoveWindowFromLayout( - aura::Window* child) { - child->RemoveObserver(this); - if (child->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE) - RemoveModalWindow(child); -} - -void SystemModalContainerLayoutManager::OnWindowRemovedFromLayout( - aura::Window* child) { -} - -void SystemModalContainerLayoutManager::OnChildWindowVisibilityChanged( - aura::Window* child, - bool visible) { -} - -void SystemModalContainerLayoutManager::SetChildBounds( - aura::Window* child, - const gfx::Rect& requested_bounds) { - SetChildBoundsDirect(child, requested_bounds); -} - -//////////////////////////////////////////////////////////////////////////////// -// SystemModalContainerLayoutManager, aura::WindowObserver implementation: - -void SystemModalContainerLayoutManager::OnWindowPropertyChanged( - aura::Window* window, - const void* key, - intptr_t old) { - if (key != aura::client::kModalKey) - return; - - if (window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE) { - AddModalWindow(window); - } else if (static_cast<ui::ModalType>(old) != ui::MODAL_TYPE_NONE) { - RemoveModalWindow(window); - Shell::GetInstance()->OnModalWindowRemoved(window); - } -} - -void SystemModalContainerLayoutManager::OnWindowDestroying( - aura::Window* window) { - if (modal_background_ && modal_background_->GetNativeView() == window) - modal_background_ = NULL; -} - -bool SystemModalContainerLayoutManager::CanWindowReceiveEvents( - aura::Window* window) { - // We could get when we're at lock screen and there is modal window at - // system modal window layer which added event filter. - // Now this lock modal windows layer layout manager should not block events - // for windows at lock layer. - // See SystemModalContainerLayoutManagerTest.EventFocusContainers and - // http://crbug.com/157469 - if (modal_windows_.empty()) - return true; - // This container can not handle events if the screen is locked and it is not - // above the lock screen layer (crbug.com/110920). - if (Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked() && - container_->id() < ash::internal::kShellWindowId_LockScreenContainer) - return true; - return wm::GetActivatableWindow(window) == modal_window(); -} - -bool SystemModalContainerLayoutManager::ActivateNextModalWindow() { - if (modal_windows_.empty()) - return false; - wm::ActivateWindow(modal_window()); - return true; -} - -void SystemModalContainerLayoutManager::CreateModalBackground() { - if (!modal_background_) { - modal_background_ = new views::Widget; - views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); - params.parent = container_; - params.bounds = Shell::GetScreen()->GetDisplayNearestWindow( - container_).bounds(); - modal_background_->Init(params); - modal_background_->GetNativeView()->SetName( - "SystemModalContainerLayoutManager.ModalBackground"); - views::View* contents_view = new views::View(); - // TODO(jamescook): This could be SK_ColorWHITE for the new dialog style. - contents_view->set_background( - views::Background::CreateSolidBackground(SK_ColorBLACK)); - modal_background_->SetContentsView(contents_view); - modal_background_->GetNativeView()->layer()->SetOpacity(0.0f); - } - - ui::ScopedLayerAnimationSettings settings( - modal_background_->GetNativeView()->layer()->GetAnimator()); - modal_background_->Show(); - modal_background_->GetNativeView()->layer()->SetOpacity(0.5f); - container_->StackChildAtTop(modal_background_->GetNativeView()); -} - -void SystemModalContainerLayoutManager::DestroyModalBackground() { - // modal_background_ can be NULL when a root window is shutting down - // and OnWindowDestroying is called first. - if (modal_background_) { - ui::ScopedLayerAnimationSettings settings( - modal_background_->GetNativeView()->layer()->GetAnimator()); - modal_background_->Close(); - settings.AddObserver(views::corewm::CreateHidingWindowAnimationObserver( - modal_background_->GetNativeView())); - modal_background_->GetNativeView()->layer()->SetOpacity(0.0f); - modal_background_ = NULL; - } -} - -// static -bool SystemModalContainerLayoutManager::IsModalBackground( - aura::Window* window) { - int id = window->parent()->id(); - if (id != internal::kShellWindowId_SystemModalContainer && - id != internal::kShellWindowId_LockSystemModalContainer) - return false; - SystemModalContainerLayoutManager* layout_manager = - static_cast<SystemModalContainerLayoutManager*>( - window->parent()->layout_manager()); - return layout_manager->modal_background_ && - layout_manager->modal_background_->GetNativeWindow() == window; -} - -//////////////////////////////////////////////////////////////////////////////// -// SystemModalContainerLayoutManager, private: - -void SystemModalContainerLayoutManager::AddModalWindow(aura::Window* window) { - if (modal_windows_.empty()) { - aura::Window* capture_window = aura::client::GetCaptureWindow(container_); - if (capture_window) - capture_window->ReleaseCapture(); - } - modal_windows_.push_back(window); - Shell::GetInstance()->CreateModalBackground(window); - window->parent()->StackChildAtTop(window); -} - -void SystemModalContainerLayoutManager::RemoveModalWindow( - aura::Window* window) { - aura::Window::Windows::iterator it = - std::find(modal_windows_.begin(), modal_windows_.end(), window); - if (it != modal_windows_.end()) - modal_windows_.erase(it); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/system_modal_container_layout_manager.h b/chromium/ash/wm/system_modal_container_layout_manager.h deleted file mode 100644 index 76618ece071..00000000000 --- a/chromium/ash/wm/system_modal_container_layout_manager.h +++ /dev/null @@ -1,98 +0,0 @@ -// 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_SYSTEM_MODAL_CONTAINER_LAYOUT_MANAGER_H_ -#define ASH_WM_SYSTEM_MODAL_CONTAINER_LAYOUT_MANAGER_H_ - -#include <vector> - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/layout_manager.h" -#include "ui/aura/window_observer.h" - -namespace aura { -class Window; -class EventFilter; -} -namespace gfx { -class Rect; -} -namespace views { -class Widget; -} - -namespace ash { -namespace internal { - -// LayoutManager for the modal window container. -class ASH_EXPORT SystemModalContainerLayoutManager - : public aura::LayoutManager, - public aura::WindowObserver { - public: - explicit SystemModalContainerLayoutManager(aura::Window* container); - virtual ~SystemModalContainerLayoutManager(); - - bool has_modal_background() const { return modal_background_ != NULL; } - - // Overridden from aura::LayoutManager: - virtual void OnWindowResized() OVERRIDE; - virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; - virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; - virtual void OnChildWindowVisibilityChanged(aura::Window* child, - bool visibile) OVERRIDE; - virtual void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) OVERRIDE; - - // Overridden from aura::WindowObserver: - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - // Can a given |window| receive and handle input events? - bool CanWindowReceiveEvents(aura::Window* window); - - // Activates next modal window if any. Returns false if there - // are no more modal windows in this layout manager. - bool ActivateNextModalWindow(); - - // Creates modal background window, which is a partially-opaque - // fullscreen window. If there is already a modal background window, - // it will bring it the top. - void CreateModalBackground(); - - void DestroyModalBackground(); - - // Is the |window| modal background? - static bool IsModalBackground(aura::Window* window); - - private: - void AddModalWindow(aura::Window* window); - void RemoveModalWindow(aura::Window* window); - - aura::Window* modal_window() { - return !modal_windows_.empty() ? modal_windows_.back() : NULL; - } - - // The container that owns the layout manager. - aura::Window* container_; - - // A widget that dims the windows behind the modal window(s) being - // shown in |container_|. - views::Widget* modal_background_; - - // A stack of modal windows. Only the topmost can receive events. - std::vector<aura::Window*> modal_windows_; - - DISALLOW_COPY_AND_ASSIGN(SystemModalContainerLayoutManager); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_SYSTEM_MODAL_CONTAINER_LAYOUT_MANAGER_H_ diff --git a/chromium/ash/wm/system_modal_container_layout_manager_unittest.cc b/chromium/ash/wm/system_modal_container_layout_manager_unittest.cc deleted file mode 100644 index 6ae336926c1..00000000000 --- a/chromium/ash/wm/system_modal_container_layout_manager_unittest.cc +++ /dev/null @@ -1,495 +0,0 @@ -// 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/system_modal_container_layout_manager.h" - -#include "ash/root_window_controller.h" -#include "ash/session_state_delegate.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_util.h" -#include "base/compiler_specific.h" -#include "base/run_loop.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/gfx/screen.h" -#include "ui/views/test/capture_tracking_view.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -namespace test { - -namespace { - -aura::Window* GetModalContainer() { - return Shell::GetPrimaryRootWindowController()->GetContainer( - ash::internal::kShellWindowId_SystemModalContainer); -} - -bool AllRootWindowsHaveModalBackgroundsForContainer(int container_id) { - std::vector<aura::Window*> containers = - Shell::GetContainersFromAllRootWindows(container_id, NULL); - bool has_modal_screen = !containers.empty(); - for (std::vector<aura::Window*>::iterator iter = containers.begin(); - iter != containers.end(); ++iter) { - has_modal_screen &= - static_cast<internal::SystemModalContainerLayoutManager*>( - (*iter)->layout_manager())->has_modal_background(); - } - return has_modal_screen; -} - -bool AllRootWindowsHaveLockedModalBackgrounds() { - return AllRootWindowsHaveModalBackgroundsForContainer( - internal::kShellWindowId_LockSystemModalContainer); -} - -bool AllRootWindowsHaveModalBackgrounds() { - return AllRootWindowsHaveModalBackgroundsForContainer( - internal::kShellWindowId_SystemModalContainer); -} - -class TestWindow : public views::WidgetDelegateView { - public: - explicit TestWindow(bool modal) : modal_(modal) {} - virtual ~TestWindow() {} - - // The window needs be closed from widget in order for - // aura::client::kModalKey property to be reset. - static void CloseTestWindow(aura::Window* window) { - views::Widget::GetWidgetForNativeWindow(window)->Close(); - } - - // Overridden from views::View: - virtual gfx::Size GetPreferredSize() OVERRIDE { - return gfx::Size(50, 50); - } - - // Overridden from views::WidgetDelegate: - virtual views::View* GetContentsView() OVERRIDE { - return this; - } - virtual ui::ModalType GetModalType() const OVERRIDE { - return modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_NONE; - } - - private: - bool modal_; - - DISALLOW_COPY_AND_ASSIGN(TestWindow); -}; - -class EventTestWindow : public TestWindow { - public: - explicit EventTestWindow(bool modal) : TestWindow(modal), - mouse_presses_(0) {} - virtual ~EventTestWindow() {} - - aura::Window* OpenTestWindowWithContext(aura::Window* context) { - views::Widget* widget = - views::Widget::CreateWindowWithContext(this, context); - widget->Show(); - return widget->GetNativeView(); - } - - aura::Window* OpenTestWindowWithParent(aura::Window* parent) { - DCHECK(parent); - views::Widget* widget = - views::Widget::CreateWindowWithParent(this, parent); - widget->Show(); - return widget->GetNativeView(); - } - - // Overridden from views::View: - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { - mouse_presses_++; - return false; - } - - int mouse_presses() const { return mouse_presses_; } - private: - int mouse_presses_; - - DISALLOW_COPY_AND_ASSIGN(EventTestWindow); -}; - -class TransientWindowObserver : public aura::WindowObserver { - public: - TransientWindowObserver() : destroyed_(false) {} - virtual ~TransientWindowObserver() {} - - bool destroyed() const { return destroyed_; } - - // Overridden from aura::WindowObserver: - virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE { - destroyed_ = true; - } - - private: - bool destroyed_; - - DISALLOW_COPY_AND_ASSIGN(TransientWindowObserver); -}; - -} // namespace - -class SystemModalContainerLayoutManagerTest : public AshTestBase { - public: - aura::Window* OpenToplevelTestWindow(bool modal) { - views::Widget* widget = views::Widget::CreateWindowWithContext( - new TestWindow(modal), CurrentContext()); - widget->Show(); - return widget->GetNativeView(); - } - - aura::Window* OpenTestWindowWithParent(aura::Window* parent, bool modal) { - views::Widget* widget = - views::Widget::CreateWindowWithParent(new TestWindow(modal), parent); - widget->Show(); - return widget->GetNativeView(); - } -}; - -TEST_F(SystemModalContainerLayoutManagerTest, NonModalTransient) { - scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false)); - aura::Window* transient = OpenTestWindowWithParent(parent.get(), false); - TransientWindowObserver destruction_observer; - transient->AddObserver(&destruction_observer); - - EXPECT_EQ(parent.get(), transient->transient_parent()); - EXPECT_EQ(parent->parent(), transient->parent()); - - // The transient should be destroyed with its parent. - parent.reset(); - EXPECT_TRUE(destruction_observer.destroyed()); -} - -TEST_F(SystemModalContainerLayoutManagerTest, ModalTransient) { - scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false)); - // parent should be active. - EXPECT_TRUE(wm::IsActiveWindow(parent.get())); - aura::Window* t1 = OpenTestWindowWithParent(parent.get(), true); - - TransientWindowObserver do1; - t1->AddObserver(&do1); - - EXPECT_EQ(parent.get(), t1->transient_parent()); - EXPECT_EQ(GetModalContainer(), t1->parent()); - - // t1 should now be active. - EXPECT_TRUE(wm::IsActiveWindow(t1)); - - // Attempting to click the parent should result in no activation change. - aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), parent.get()); - e1.ClickLeftButton(); - EXPECT_TRUE(wm::IsActiveWindow(t1)); - - // Now open another modal transient parented to the original modal transient. - aura::Window* t2 = OpenTestWindowWithParent(t1, true); - TransientWindowObserver do2; - t2->AddObserver(&do2); - - EXPECT_TRUE(wm::IsActiveWindow(t2)); - - EXPECT_EQ(t1, t2->transient_parent()); - EXPECT_EQ(GetModalContainer(), t2->parent()); - - // t2 should still be active, even after clicking on t1. - aura::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), t1); - e2.ClickLeftButton(); - EXPECT_TRUE(wm::IsActiveWindow(t2)); - - // Both transients should be destroyed with parent. - parent.reset(); - EXPECT_TRUE(do1.destroyed()); - EXPECT_TRUE(do2.destroyed()); -} - -TEST_F(SystemModalContainerLayoutManagerTest, ModalNonTransient) { - scoped_ptr<aura::Window> t1(OpenToplevelTestWindow(true)); - // parent should be active. - EXPECT_TRUE(wm::IsActiveWindow(t1.get())); - TransientWindowObserver do1; - t1->AddObserver(&do1); - - EXPECT_EQ(NULL, t1->transient_parent()); - EXPECT_EQ(GetModalContainer(), t1->parent()); - - // t1 should now be active. - EXPECT_TRUE(wm::IsActiveWindow(t1.get())); - - // Attempting to click the parent should result in no activation change. - aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), - Shell::GetPrimaryRootWindow()); - e1.ClickLeftButton(); - EXPECT_TRUE(wm::IsActiveWindow(t1.get())); - - // Now open another modal transient parented to the original modal transient. - aura::Window* t2 = OpenTestWindowWithParent(t1.get(), true); - TransientWindowObserver do2; - t2->AddObserver(&do2); - - EXPECT_TRUE(wm::IsActiveWindow(t2)); - - EXPECT_EQ(t1, t2->transient_parent()); - EXPECT_EQ(GetModalContainer(), t2->parent()); - - // t2 should still be active, even after clicking on t1. - aura::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), t1.get()); - e2.ClickLeftButton(); - EXPECT_TRUE(wm::IsActiveWindow(t2)); - - // Both transients should be destroyed with parent. - t1.reset(); - EXPECT_TRUE(do1.destroyed()); - EXPECT_TRUE(do2.destroyed()); -} - -// Tests that we can activate an unrelated window after a modal window is closed -// for a window. -TEST_F(SystemModalContainerLayoutManagerTest, CanActivateAfterEndModalSession) { - scoped_ptr<aura::Window> unrelated(OpenToplevelTestWindow(false)); - unrelated->SetBounds(gfx::Rect(100, 100, 50, 50)); - scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false)); - // parent should be active. - EXPECT_TRUE(wm::IsActiveWindow(parent.get())); - - scoped_ptr<aura::Window> transient( - OpenTestWindowWithParent(parent.get(), true)); - // t1 should now be active. - EXPECT_TRUE(wm::IsActiveWindow(transient.get())); - - // Attempting to click the parent should result in no activation change. - aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), parent.get()); - e1.ClickLeftButton(); - EXPECT_TRUE(wm::IsActiveWindow(transient.get())); - - // Now close the transient. - transient->Hide(); - TestWindow::CloseTestWindow(transient.release()); - - base::RunLoop().RunUntilIdle(); - - // parent should now be active again. - EXPECT_TRUE(wm::IsActiveWindow(parent.get())); - - // Attempting to click unrelated should activate it. - aura::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), unrelated.get()); - e2.ClickLeftButton(); - EXPECT_TRUE(wm::IsActiveWindow(unrelated.get())); -} - -TEST_F(SystemModalContainerLayoutManagerTest, EventFocusContainers) { - // Create a normal window and attempt to receive a click event. - EventTestWindow* main_delegate = new EventTestWindow(false); - scoped_ptr<aura::Window> main( - main_delegate->OpenTestWindowWithContext(CurrentContext())); - EXPECT_TRUE(wm::IsActiveWindow(main.get())); - aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), main.get()); - e1.ClickLeftButton(); - EXPECT_EQ(1, main_delegate->mouse_presses()); - - // Create a modal window for the main window and verify that the main window - // no longer receives mouse events. - EventTestWindow* transient_delegate = new EventTestWindow(true); - aura::Window* transient = - transient_delegate->OpenTestWindowWithParent(main.get()); - EXPECT_TRUE(wm::IsActiveWindow(transient)); - e1.ClickLeftButton(); - EXPECT_EQ(1, transient_delegate->mouse_presses()); - - for (int block_reason = FIRST_BLOCK_REASON; - block_reason < NUMBER_OF_BLOCK_REASONS; - ++block_reason) { - // Create a window in the lock screen container and ensure that it receives - // the mouse event instead of the modal window (crbug.com/110920). - BlockUserSession(static_cast<UserSessionBlockReason>(block_reason)); - EventTestWindow* lock_delegate = new EventTestWindow(false); - scoped_ptr<aura::Window> lock(lock_delegate->OpenTestWindowWithParent( - Shell::GetPrimaryRootWindowController()->GetContainer( - ash::internal::kShellWindowId_LockScreenContainer))); - EXPECT_TRUE(wm::IsActiveWindow(lock.get())); - e1.ClickLeftButton(); - EXPECT_EQ(1, lock_delegate->mouse_presses()); - - // Make sure that a modal container created by the lock screen can still - // receive mouse events. - EventTestWindow* lock_modal_delegate = new EventTestWindow(true); - aura::Window* lock_modal = - lock_modal_delegate->OpenTestWindowWithParent(lock.get()); - EXPECT_TRUE(wm::IsActiveWindow(lock_modal)); - e1.ClickLeftButton(); - // Verify that none of the other containers received any more mouse presses. - EXPECT_EQ(1, lock_modal_delegate->mouse_presses()); - EXPECT_EQ(1, lock_delegate->mouse_presses()); - EXPECT_EQ(1, main_delegate->mouse_presses()); - EXPECT_EQ(1, transient_delegate->mouse_presses()); - UnblockUserSession(); - } -} - -// Makes sure we don't crash if a modal window is shown while the parent window -// is hidden. -TEST_F(SystemModalContainerLayoutManagerTest, ShowModalWhileHidden) { - // Hide the lock screen. - Shell::GetPrimaryRootWindowController()->GetContainer( - internal::kShellWindowId_SystemModalContainer)->layer()->SetOpacity(0); - - // Create a modal window. - scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false)); - scoped_ptr<aura::Window> modal_window( - OpenTestWindowWithParent(parent.get(), true)); - parent->Show(); - modal_window->Show(); -} - -// Verifies we generate a capture lost when showing a modal window. -TEST_F(SystemModalContainerLayoutManagerTest, ChangeCapture) { - views::Widget* widget = views::Widget::CreateWindowWithContext( - new TestWindow(false), CurrentContext()); - scoped_ptr<aura::Window> widget_window(widget->GetNativeView()); - views::test::CaptureTrackingView* view = new views::test::CaptureTrackingView; - widget->GetContentsView()->AddChildView(view); - view->SetBoundsRect(widget->GetContentsView()->bounds()); - widget->Show(); - - gfx::Point center(view->width() / 2, view->height() / 2); - views::View::ConvertPointToScreen(view, ¢er); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), center); - generator.PressLeftButton(); - EXPECT_TRUE(view->got_press()); - scoped_ptr<aura::Window> modal_window( - OpenTestWindowWithParent(widget->GetNativeView(), true)); - modal_window->Show(); - EXPECT_TRUE(view->got_capture_lost()); -} - -// Verifies that the window gets moved into the visible screen area upon screen -// resize. -TEST_F(SystemModalContainerLayoutManagerTest, KeepVisible) { - GetModalContainer()->SetBounds(gfx::Rect(0, 0, 1024, 768)); - scoped_ptr<aura::Window> main(OpenTestWindowWithParent(GetModalContainer(), - true)); - main->SetBounds(gfx::Rect(924, 668, 100, 100)); - // We set now the bounds of the root window to something new which will - // Then trigger the repos operation. - GetModalContainer()->SetBounds(gfx::Rect(0, 0, 800, 600)); - - gfx::Rect bounds = main->bounds(); - EXPECT_EQ(bounds, gfx::Rect(700, 500, 100, 100)); -} - -TEST_F(SystemModalContainerLayoutManagerTest, ShowNormalBackgroundOrLocked) { - scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false)); - scoped_ptr<aura::Window> modal_window( - OpenTestWindowWithParent(parent.get(), true)); - parent->Show(); - modal_window->Show(); - - // Normal system modal window. Shows normal system modal background and not - // locked. - EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); - EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds()); - - TestWindow::CloseTestWindow(modal_window.release()); - EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds()); - EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds()); - - for (int block_reason = FIRST_BLOCK_REASON; - block_reason < NUMBER_OF_BLOCK_REASONS; - ++block_reason) { - // Normal system modal window while blocked. Shows blocked system modal - // background. - BlockUserSession(static_cast<UserSessionBlockReason>(block_reason)); - scoped_ptr<aura::Window> lock_parent(OpenTestWindowWithParent( - Shell::GetPrimaryRootWindowController()->GetContainer( - ash::internal::kShellWindowId_LockScreenContainer), - false)); - scoped_ptr<aura::Window> lock_modal_window(OpenTestWindowWithParent( - lock_parent.get(), true)); - lock_parent->Show(); - lock_modal_window->Show(); - EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds()); - EXPECT_TRUE(AllRootWindowsHaveLockedModalBackgrounds()); - TestWindow::CloseTestWindow(lock_modal_window.release()); - - // Normal system modal window while blocked, but it belongs to the normal - // window. Shouldn't show blocked system modal background, but normal. - scoped_ptr<aura::Window> modal_window( - OpenTestWindowWithParent(parent.get(), true)); - modal_window->Show(); - EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); - EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds()); - TestWindow::CloseTestWindow(modal_window.release()); - UnblockUserSession(); - // Here we should check the behavior of the locked system modal dialog when - // unlocked, but such case isn't handled very well right now. - // See crbug.com/157660 - // TODO(mukai): add the test case when the bug is fixed. - } -} - -TEST_F(SystemModalContainerLayoutManagerTest, MultiDisplays) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("500x500,500x500"); - - scoped_ptr<aura::Window> normal(OpenToplevelTestWindow(false)); - normal->SetBounds(gfx::Rect(100, 100, 50, 50)); - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - EXPECT_EQ(2U, root_windows.size()); - aura::Window* container1 = Shell::GetContainer( - root_windows[0], ash::internal::kShellWindowId_SystemModalContainer); - aura::Window* container2 = Shell::GetContainer( - root_windows[1], ash::internal::kShellWindowId_SystemModalContainer); - - scoped_ptr<aura::Window> modal1( - OpenTestWindowWithParent(container1, true)); - EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); - EXPECT_TRUE(wm::IsActiveWindow(modal1.get())); - - scoped_ptr<aura::Window> modal11( - OpenTestWindowWithParent(container1, true)); - EXPECT_TRUE(wm::IsActiveWindow(modal11.get())); - - scoped_ptr<aura::Window> modal2( - OpenTestWindowWithParent(container2, true)); - EXPECT_TRUE(wm::IsActiveWindow(modal2.get())); - - // Sanity check if they're on the correct containers. - EXPECT_EQ(container1, modal1->parent()); - EXPECT_EQ(container1, modal11->parent()); - EXPECT_EQ(container2, modal2->parent()); - - TestWindow::CloseTestWindow(modal2.release()); - EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); - EXPECT_TRUE(wm::IsActiveWindow(modal11.get())); - - TestWindow::CloseTestWindow(modal11.release()); - EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); - EXPECT_TRUE(wm::IsActiveWindow(modal1.get())); - - UpdateDisplay("500x500"); - EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); - EXPECT_TRUE(wm::IsActiveWindow(modal1.get())); - - UpdateDisplay("500x500,600x600"); - EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); - EXPECT_TRUE(wm::IsActiveWindow(modal1.get())); - - // No more modal screen. - modal1->Hide(); - TestWindow::CloseTestWindow(modal1.release()); - EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds()); - EXPECT_TRUE(wm::IsActiveWindow(normal.get())); -} - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/toplevel_window_event_handler.cc b/chromium/ash/wm/toplevel_window_event_handler.cc deleted file mode 100644 index 10b2a886edb..00000000000 --- a/chromium/ash/wm/toplevel_window_event_handler.cc +++ /dev/null @@ -1,534 +0,0 @@ -// 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/toplevel_window_event_handler.h" - -#include "ash/shell.h" -#include "ash/wm/resize_shadow_controller.h" -#include "ash/wm/window_resizer.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_state_observer.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "ui/aura/client/cursor_client.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/aura/window_observer.h" -#include "ui/base/cursor/cursor.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_types.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" -#include "ui/events/gestures/gesture_recognizer.h" -#include "ui/gfx/screen.h" - -namespace { -const double kMinHorizVelocityForWindowSwipe = 1100; -const double kMinVertVelocityForWindowMinimize = 1000; -} - -namespace ash { - -namespace { - -gfx::Point ConvertPointToParent(aura::Window* window, - const gfx::Point& point) { - gfx::Point result(point); - aura::Window::ConvertPointToTarget(window, window->parent(), &result); - return result; -} - -} // namespace - -// ScopedWindowResizer --------------------------------------------------------- - -// Wraps a WindowResizer and installs an observer on its target window. When -// the window is destroyed ResizerWindowDestroyed() is invoked back on the -// ToplevelWindowEventHandler to clean up. -class ToplevelWindowEventHandler::ScopedWindowResizer - : public aura::WindowObserver, - public wm::WindowStateObserver { - public: - ScopedWindowResizer(ToplevelWindowEventHandler* handler, - WindowResizer* resizer); - virtual ~ScopedWindowResizer(); - - WindowResizer* resizer() { return resizer_.get(); } - - // WindowObserver overrides: - virtual void OnWindowHierarchyChanging( - const HierarchyChangeParams& params) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - // WindowStateObserver overrides: - virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType type) OVERRIDE; - - private: - void AddHandlers(aura::Window* container); - void RemoveHandlers(); - - ToplevelWindowEventHandler* handler_; - scoped_ptr<WindowResizer> resizer_; - - // If not NULL, this is an additional container that the dragged window has - // moved to which ScopedWindowResizer has temporarily added observers on. - aura::Window* target_container_; - - DISALLOW_COPY_AND_ASSIGN(ScopedWindowResizer); -}; - -ToplevelWindowEventHandler::ScopedWindowResizer::ScopedWindowResizer( - ToplevelWindowEventHandler* handler, - WindowResizer* resizer) - : handler_(handler), - resizer_(resizer), - target_container_(NULL) { - if (resizer_) { - resizer_->GetTarget()->AddObserver(this); - wm::GetWindowState(resizer_->GetTarget())->AddObserver(this); - } -} - -ToplevelWindowEventHandler::ScopedWindowResizer::~ScopedWindowResizer() { - RemoveHandlers(); - if (resizer_) { - resizer_->GetTarget()->RemoveObserver(this); - wm::GetWindowState(resizer_->GetTarget())->RemoveObserver(this); - } -} - -void ToplevelWindowEventHandler::ScopedWindowResizer::OnWindowHierarchyChanging( - const HierarchyChangeParams& params) { - if (params.receiver != resizer_->GetTarget()) - return; - wm::WindowState* state = wm::GetWindowState(params.receiver); - if (state->continue_drag_after_reparent()) { - state->set_continue_drag_after_reparent(false); - AddHandlers(params.new_parent); - } else { - handler_->CompleteDrag(DRAG_COMPLETE, 0); - } -} - -void ToplevelWindowEventHandler::ScopedWindowResizer::OnWindowShowTypeChanged( - wm::WindowState* window_state, - wm::WindowShowType old) { - if (!window_state->IsNormalShowState()) - handler_->CompleteDrag(DRAG_COMPLETE, 0); -} - -void ToplevelWindowEventHandler::ScopedWindowResizer::OnWindowDestroying( - aura::Window* window) { - DCHECK(resizer_.get()); - DCHECK_EQ(resizer_->GetTarget(), window); - handler_->ResizerWindowDestroyed(); -} - -void ToplevelWindowEventHandler::ScopedWindowResizer::AddHandlers( - aura::Window* container) { - RemoveHandlers(); - if (!handler_->owner()->Contains(container)) { - container->AddPreTargetHandler(handler_); - container->AddPostTargetHandler(handler_); - target_container_ = container; - } -} - -void ToplevelWindowEventHandler::ScopedWindowResizer::RemoveHandlers() { - if (target_container_) { - target_container_->RemovePreTargetHandler(handler_); - target_container_->RemovePostTargetHandler(handler_); - target_container_ = NULL; - } -} - - -// ToplevelWindowEventHandler -------------------------------------------------- - -ToplevelWindowEventHandler::ToplevelWindowEventHandler(aura::Window* owner) - : owner_(owner), - in_move_loop_(false), - move_cancelled_(false), - in_gesture_drag_(false), - destroyed_(NULL) { - aura::client::SetWindowMoveClient(owner, this); - Shell::GetInstance()->display_controller()->AddObserver(this); - owner->AddPreTargetHandler(this); - owner->AddPostTargetHandler(this); -} - -ToplevelWindowEventHandler::~ToplevelWindowEventHandler() { - Shell::GetInstance()->display_controller()->RemoveObserver(this); - if (destroyed_) - *destroyed_ = true; -} - -void ToplevelWindowEventHandler::OnKeyEvent(ui::KeyEvent* event) { - if (window_resizer_.get() && event->type() == ui::ET_KEY_PRESSED && - event->key_code() == ui::VKEY_ESCAPE) { - CompleteDrag(DRAG_REVERT, event->flags()); - } -} - -void ToplevelWindowEventHandler::OnMouseEvent( - ui::MouseEvent* event) { - if ((event->flags() & - (ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON)) != 0) - return; - - if (in_gesture_drag_) - return; - - aura::Window* target = static_cast<aura::Window*>(event->target()); - switch (event->type()) { - case ui::ET_MOUSE_PRESSED: - HandleMousePressed(target, event); - break; - case ui::ET_MOUSE_DRAGGED: - HandleDrag(target, event); - break; - case ui::ET_MOUSE_CAPTURE_CHANGED: - case ui::ET_MOUSE_RELEASED: - HandleMouseReleased(target, event); - break; - case ui::ET_MOUSE_MOVED: - HandleMouseMoved(target, event); - break; - case ui::ET_MOUSE_EXITED: - HandleMouseExited(target, event); - break; - default: - break; - } -} - -void ToplevelWindowEventHandler::OnGestureEvent(ui::GestureEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (!target->delegate()) - return; - - if (in_move_loop_ && !in_gesture_drag_) - return; - - switch (event->type()) { - case ui::ET_GESTURE_TAP_DOWN: { - int component = - target->delegate()->GetNonClientComponent(event->location()); - if (!(WindowResizer::GetBoundsChangeForWindowComponent(component) & - WindowResizer::kBoundsChange_Resizes)) - return; - internal::ResizeShadowController* controller = - Shell::GetInstance()->resize_shadow_controller(); - if (controller) - controller->ShowShadow(target, component); - return; - } - case ui::ET_GESTURE_END: { - internal::ResizeShadowController* controller = - Shell::GetInstance()->resize_shadow_controller(); - if (controller) - controller->HideShadow(target); - return; - } - case ui::ET_GESTURE_SCROLL_BEGIN: { - if (in_gesture_drag_) - return; - int component = - target->delegate()->GetNonClientComponent(event->location()); - if (WindowResizer::GetBoundsChangeForWindowComponent(component) == 0) { - window_resizer_.reset(); - return; - } - in_gesture_drag_ = true; - pre_drag_window_bounds_ = target->bounds(); - gfx::Point location_in_parent( - ConvertPointToParent(target, event->location())); - CreateScopedWindowResizer(target, location_in_parent, component, - aura::client::WINDOW_MOVE_SOURCE_TOUCH); - break; - } - case ui::ET_GESTURE_SCROLL_UPDATE: { - if (!in_gesture_drag_) - return; - if (window_resizer_.get() && - window_resizer_->resizer()->GetTarget() != target) { - return; - } - HandleDrag(target, event); - break; - } - case ui::ET_GESTURE_SCROLL_END: - case ui::ET_SCROLL_FLING_START: { - if (!in_gesture_drag_) - return; - if (window_resizer_.get() && - window_resizer_->resizer()->GetTarget() != target) { - return; - } - - CompleteDrag(DRAG_COMPLETE, event->flags()); - if (in_move_loop_) { - quit_closure_.Run(); - in_move_loop_ = false; - } - in_gesture_drag_ = false; - - if (event->type() == ui::ET_GESTURE_SCROLL_END) { - event->StopPropagation(); - return; - } - - int component = - target->delegate()->GetNonClientComponent(event->location()); - if (WindowResizer::GetBoundsChangeForWindowComponent(component) == 0) - return; - - wm::WindowState* window_state = wm::GetWindowState(target); - if (!window_state->IsNormalShowState()) - return; - - if (fabs(event->details().velocity_y()) > - kMinVertVelocityForWindowMinimize) { - // Minimize/maximize. - if (event->details().velocity_y() > 0 && - window_state->CanMinimize()) { - window_state->Minimize(); - window_state->set_always_restores_to_restore_bounds(true); - window_state->SetRestoreBoundsInParent(pre_drag_window_bounds_); - } else if (window_state->CanMaximize()) { - window_state->SetRestoreBoundsInParent(pre_drag_window_bounds_); - window_state->Maximize(); - } - } else if (window_state->CanSnap() && - fabs(event->details().velocity_x()) > - kMinHorizVelocityForWindowSwipe) { - // Snap left/right. - ui::ScopedLayerAnimationSettings scoped_setter( - target->layer()->GetAnimator()); - scoped_setter.SetPreemptionStrategy( - ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); - internal::SnapSizer::SnapWindow(window_state, - event->details().velocity_x() < 0 ? - internal::SnapSizer::LEFT_EDGE : internal::SnapSizer::RIGHT_EDGE); - } - break; - } - default: - return; - } - - event->StopPropagation(); -} - -aura::client::WindowMoveResult ToplevelWindowEventHandler::RunMoveLoop( - aura::Window* source, - const gfx::Vector2d& drag_offset, - aura::client::WindowMoveSource move_source) { - DCHECK(!in_move_loop_); // Can only handle one nested loop at a time. - in_move_loop_ = true; - move_cancelled_ = false; - aura::Window* root_window = source->GetRootWindow(); - DCHECK(root_window); - gfx::Point drag_location; - if (move_source == aura::client::WINDOW_MOVE_SOURCE_TOUCH && - aura::Env::GetInstance()->is_touch_down()) { - in_gesture_drag_ = true; - bool has_point = ui::GestureRecognizer::Get()-> - GetLastTouchPointForTarget(source, &drag_location); - DCHECK(has_point); - } else { - drag_location = root_window->GetDispatcher()->GetLastMouseLocationInRoot(); - aura::Window::ConvertPointToTarget( - root_window, source->parent(), &drag_location); - } - // Set the cursor before calling CreateScopedWindowResizer(), as that will - // eventually call LockCursor() and prevent the cursor from changing. - aura::client::CursorClient* cursor_client = - aura::client::GetCursorClient(root_window); - if (cursor_client) - cursor_client->SetCursor(ui::kCursorPointer); - CreateScopedWindowResizer(source, drag_location, HTCAPTION, move_source); - bool destroyed = false; - destroyed_ = &destroyed; - base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); - base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); - base::RunLoop run_loop(aura::Env::GetInstance()->GetDispatcher()); - quit_closure_ = run_loop.QuitClosure(); - run_loop.Run(); - if (destroyed) - return aura::client::MOVE_CANCELED; - destroyed_ = NULL; - in_gesture_drag_ = in_move_loop_ = false; - return move_cancelled_ ? aura::client::MOVE_CANCELED : - aura::client::MOVE_SUCCESSFUL; -} - -void ToplevelWindowEventHandler::EndMoveLoop() { - if (!in_move_loop_) - return; - - in_move_loop_ = false; - CompleteDrag(DRAG_REVERT, 0); - quit_closure_.Run(); -} - -void ToplevelWindowEventHandler::OnDisplayConfigurationChanging() { - if (in_move_loop_) { - move_cancelled_ = true; - EndMoveLoop(); - } else { - CompleteDrag(DRAG_REVERT, 0); - } -} - -void ToplevelWindowEventHandler::CreateScopedWindowResizer( - aura::Window* window, - const gfx::Point& point_in_parent, - int window_component, - aura::client::WindowMoveSource source) { - window_resizer_.reset(); - WindowResizer* resizer = - CreateWindowResizer(window, point_in_parent, window_component, - source).release(); - if (resizer) - window_resizer_.reset(new ScopedWindowResizer(this, resizer)); -} - -void ToplevelWindowEventHandler::CompleteDrag(DragCompletionStatus status, - int event_flags) { - scoped_ptr<ScopedWindowResizer> resizer(window_resizer_.release()); - if (resizer) { - if (status == DRAG_COMPLETE) - resizer->resizer()->CompleteDrag(event_flags); - else - resizer->resizer()->RevertDrag(); - } -} - -void ToplevelWindowEventHandler::HandleMousePressed( - aura::Window* target, - ui::MouseEvent* event) { - // Move/size operations are initiated post-target handling to give the target - // an opportunity to cancel this default behavior by returning ER_HANDLED. - if (ui::EventCanceledDefaultHandling(*event)) - return; - - // We also update the current window component here because for the - // mouse-drag-release-press case, where the mouse is released and - // pressed without mouse move event. - int component = - target->delegate()->GetNonClientComponent(event->location()); - if ((event->flags() & - (ui::EF_IS_DOUBLE_CLICK | ui::EF_IS_TRIPLE_CLICK)) == 0 && - WindowResizer::GetBoundsChangeForWindowComponent(component)) { - gfx::Point location_in_parent( - ConvertPointToParent(target, event->location())); - CreateScopedWindowResizer(target, location_in_parent, component, - aura::client::WINDOW_MOVE_SOURCE_MOUSE); - } else { - window_resizer_.reset(); - } - if (WindowResizer::GetBoundsChangeForWindowComponent(component) != 0) - event->StopPropagation(); -} - -void ToplevelWindowEventHandler::HandleMouseReleased( - aura::Window* target, - ui::MouseEvent* event) { - if (event->phase() != ui::EP_PRETARGET) - return; - - CompleteDrag(event->type() == ui::ET_MOUSE_RELEASED ? - DRAG_COMPLETE : DRAG_REVERT, - event->flags()); - if (in_move_loop_) { - quit_closure_.Run(); - in_move_loop_ = false; - } - // Completing the drag may result in hiding the window. If this happens - // return true so no other handlers/observers see the event. Otherwise - // they see the event on a hidden window. - if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED && - !target->IsVisible()) { - event->StopPropagation(); - } -} - -void ToplevelWindowEventHandler::HandleDrag( - aura::Window* target, - ui::LocatedEvent* event) { - // This function only be triggered to move window - // by mouse drag or touch move event. - DCHECK(event->type() == ui::ET_MOUSE_DRAGGED || - event->type() == ui::ET_TOUCH_MOVED || - event->type() == ui::ET_GESTURE_SCROLL_UPDATE); - - // Drag actions are performed pre-target handling to prevent spurious mouse - // moves from the move/size operation from being sent to the target. - if (event->phase() != ui::EP_PRETARGET) - return; - - if (!window_resizer_) - return; - window_resizer_->resizer()->Drag( - ConvertPointToParent(target, event->location()), event->flags()); - event->StopPropagation(); -} - -void ToplevelWindowEventHandler::HandleMouseMoved( - aura::Window* target, - ui::LocatedEvent* event) { - // Shadow effects are applied after target handling. Note that we don't - // respect ER_HANDLED here right now since we have not had a reason to allow - // the target to cancel shadow rendering. - if (event->phase() != ui::EP_POSTTARGET) - return; - - // TODO(jamescook): Move the resize cursor update code into here from - // CompoundEventFilter? - internal::ResizeShadowController* controller = - Shell::GetInstance()->resize_shadow_controller(); - if (controller) { - if (event->flags() & ui::EF_IS_NON_CLIENT) { - int component = - target->delegate()->GetNonClientComponent(event->location()); - controller->ShowShadow(target, component); - } else { - controller->HideShadow(target); - } - } -} - -void ToplevelWindowEventHandler::HandleMouseExited( - aura::Window* target, - ui::LocatedEvent* event) { - // Shadow effects are applied after target handling. Note that we don't - // respect ER_HANDLED here right now since we have not had a reason to allow - // the target to cancel shadow rendering. - if (event->phase() != ui::EP_POSTTARGET) - return; - - internal::ResizeShadowController* controller = - Shell::GetInstance()->resize_shadow_controller(); - if (controller) - controller->HideShadow(target); -} - -void ToplevelWindowEventHandler::ResizerWindowDestroyed() { - // We explicitly don't invoke RevertDrag() since that may do things to window. - // Instead we destroy the resizer. - window_resizer_.reset(); - - // End the move loop. This does nothing if we're not in a move loop. - EndMoveLoop(); -} - -} // namespace ash diff --git a/chromium/ash/wm/toplevel_window_event_handler.h b/chromium/ash/wm/toplevel_window_event_handler.h deleted file mode 100644 index 98c9296c947..00000000000 --- a/chromium/ash/wm/toplevel_window_event_handler.h +++ /dev/null @@ -1,123 +0,0 @@ -// 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_TOPLEVEL_WINDOW_EVENT_HANDLER_H_ -#define ASH_WM_TOPLEVEL_WINDOW_EVENT_HANDLER_H_ - -#include <set> - -#include "ash/ash_export.h" -#include "ash/display/display_controller.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/client/window_move_client.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/point.h" -#include "ui/gfx/rect.h" - -namespace aura { -class Window; -} - -namespace ui { -class LocatedEvent; -} - -namespace ash { - -class WindowResizer; - -class ASH_EXPORT ToplevelWindowEventHandler - : public ui::EventHandler, - public aura::client::WindowMoveClient, - public DisplayController::Observer { - public: - explicit ToplevelWindowEventHandler(aura::Window* owner); - virtual ~ToplevelWindowEventHandler(); - - const aura::Window* owner() const { return owner_; } - - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - // Overridden form aura::client::WindowMoveClient: - virtual aura::client::WindowMoveResult RunMoveLoop( - aura::Window* source, - const gfx::Vector2d& drag_offset, - aura::client::WindowMoveSource move_source) OVERRIDE; - virtual void EndMoveLoop() OVERRIDE; - - // Overridden form ash::DisplayController::Observer: - virtual void OnDisplayConfigurationChanging() OVERRIDE; - - private: - class ScopedWindowResizer; - - enum DragCompletionStatus { - DRAG_COMPLETE, - DRAG_REVERT - }; - - void CreateScopedWindowResizer(aura::Window* window, - const gfx::Point& point_in_parent, - int window_component, - aura::client::WindowMoveSource source); - - // Finishes the drag. - void CompleteDrag(DragCompletionStatus status, int event_flags); - - void HandleMousePressed(aura::Window* target, ui::MouseEvent* event); - void HandleMouseReleased(aura::Window* target, ui::MouseEvent* event); - - // Called during a drag to resize/position the window. - // The return value is returned by OnMouseEvent() above. - void HandleDrag(aura::Window* target, ui::LocatedEvent* event); - - // Called during mouse moves to update window resize shadows. - // Return value is returned by OnMouseEvent() above. - void HandleMouseMoved(aura::Window* target, ui::LocatedEvent* event); - - // Called for mouse exits to hide window resize shadows. - // Return value is returned by OnMouseEvent() above. - void HandleMouseExited(aura::Window* target, ui::LocatedEvent* event); - - // Invoked from ScopedWindowResizer if the window is destroyed. - void ResizerWindowDestroyed(); - - // The container which this event handler is handling events on. - aura::Window* owner_; - - // Are we running a nested message loop from RunMoveLoop(). - bool in_move_loop_; - - // Was the move operation cancelled? Used only when the nested loop - // is used to move a window. - bool move_cancelled_; - - // Is a window move/resize in progress because of gesture events? - bool in_gesture_drag_; - - // The window bounds before it started the drag. - // When a window is moved using a touch gesture, and it is swiped up/down - // maximize/minimize, the restore bounds should be set to the bounds of the - // window when the drag started. - gfx::Rect pre_drag_window_bounds_; - - scoped_ptr<ScopedWindowResizer> window_resizer_; - - base::Closure quit_closure_; - - // Used to track if this object is deleted while running a nested message - // loop. If non-null the destructor sets this to true. - bool* destroyed_; - - DISALLOW_COPY_AND_ASSIGN(ToplevelWindowEventHandler); -}; - -} // namespace aura - -#endif // ASH_WM_TOPLEVEL_WINDOW_EVENT_HANDLER_H_ diff --git a/chromium/ash/wm/toplevel_window_event_handler_unittest.cc b/chromium/ash/wm/toplevel_window_event_handler_unittest.cc deleted file mode 100644 index 99e7418bb9d..00000000000 --- a/chromium/ash/wm/toplevel_window_event_handler_unittest.cc +++ /dev/null @@ -1,694 +0,0 @@ -// 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/toplevel_window_event_handler.h" - -#include "ash/root_window_controller.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/lock_state_controller.h" -#include "ash/wm/resize_shadow.h" -#include "ash/wm/resize_shadow_controller.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "ash/wm/workspace_controller.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/events/event.h" -#include "ui/gfx/screen.h" - -#if defined(OS_WIN) -// Windows headers define macros for these function names which screw with us. -#if defined(CreateWindow) -#undef CreateWindow -#endif -#endif - -namespace ash { -namespace test { - -namespace { - -// A simple window delegate that returns the specified hit-test code when -// requested and applies a minimum size constraint if there is one. -class TestWindowDelegate : public aura::test::TestWindowDelegate { - public: - explicit TestWindowDelegate(int hittest_code) { - set_window_component(hittest_code); - } - virtual ~TestWindowDelegate() {} - - private: - // Overridden from aura::Test::TestWindowDelegate: - virtual void OnWindowDestroyed() OVERRIDE { - delete this; - } - - DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate); -}; - -class ToplevelWindowEventHandlerTest : public AshTestBase { - public: - ToplevelWindowEventHandlerTest() {} - virtual ~ToplevelWindowEventHandlerTest() {} - - protected: - aura::Window* CreateWindow(int hittest_code) { - TestWindowDelegate* d1 = new TestWindowDelegate(hittest_code); - aura::Window* w1 = new aura::Window(d1); - w1->SetType(aura::client::WINDOW_TYPE_NORMAL); - w1->set_id(1); - w1->Init(ui::LAYER_TEXTURED); - aura::Window* parent = - Shell::GetContainer(Shell::GetPrimaryRootWindow(), - internal::kShellWindowId_AlwaysOnTopContainer); - parent->AddChild(w1); - w1->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->Show(); - return w1; - } - - void DragFromCenterBy(aura::Window* window, int dx, int dy) { - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window); - generator.DragMouseBy(dx, dy); - } - - void TouchDragFromCenterBy(aura::Window* window, int dx, int dy) { - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window); - generator.PressMoveAndReleaseTouchBy(dx, dy); - } - - scoped_ptr<ToplevelWindowEventHandler> handler_; - - private: - DISALLOW_COPY_AND_ASSIGN(ToplevelWindowEventHandlerTest); -}; - -} - -TEST_F(ToplevelWindowEventHandlerTest, Caption) { - scoped_ptr<aura::Window> w1(CreateWindow(HTCAPTION)); - gfx::Size size = w1->bounds().size(); - DragFromCenterBy(w1.get(), 100, 100); - // Position should have been offset by 100,100. - EXPECT_EQ("100,100", w1->bounds().origin().ToString()); - // Size should not have. - EXPECT_EQ(size.ToString(), w1->bounds().size().ToString()); - - TouchDragFromCenterBy(w1.get(), 100, 100); - // Position should have been offset by 100,100. - EXPECT_EQ("200,200", w1->bounds().origin().ToString()); - // Size should not have. - EXPECT_EQ(size.ToString(), w1->bounds().size().ToString()); -} - -TEST_F(ToplevelWindowEventHandlerTest, BottomRight) { - scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT)); - gfx::Point position = w1->bounds().origin(); - DragFromCenterBy(w1.get(), 100, 100); - // Position should not have changed. - EXPECT_EQ(position, w1->bounds().origin()); - // Size should have increased by 100,100. - EXPECT_EQ(gfx::Size(200, 200), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, GrowBox) { - scoped_ptr<aura::Window> w1(CreateWindow(HTGROWBOX)); - TestWindowDelegate* window_delegate = - static_cast<TestWindowDelegate*>(w1->delegate()); - window_delegate->set_minimum_size(gfx::Size(40, 40)); - - gfx::Point position = w1->bounds().origin(); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - generator.MoveMouseToCenterOf(w1.get()); - generator.DragMouseBy(100, 100); - // Position should not have changed. - EXPECT_EQ(position, w1->bounds().origin()); - // Size should have increased by 100,100. - EXPECT_EQ(gfx::Size(200, 200), w1->bounds().size()); - - // Shrink the wnidow by (-100, -100). - generator.DragMouseBy(-100, -100); - // Position should not have changed. - EXPECT_EQ(position, w1->bounds().origin()); - // Size should have decreased by 100,100. - EXPECT_EQ(gfx::Size(100, 100), w1->bounds().size()); - - // Enforce minimum size. - generator.DragMouseBy(-60, -60); - EXPECT_EQ(position, w1->bounds().origin()); - EXPECT_EQ(gfx::Size(40, 40), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, Right) { - scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT)); - gfx::Point position = w1->bounds().origin(); - DragFromCenterBy(w1.get(), 100, 100); - // Position should not have changed. - EXPECT_EQ(position, w1->bounds().origin()); - // Size should have increased by 100,0. - EXPECT_EQ(gfx::Size(200, 100), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, Bottom) { - scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOM)); - gfx::Point position = w1->bounds().origin(); - DragFromCenterBy(w1.get(), 100, 100); - // Position should not have changed. - EXPECT_EQ(position, w1->bounds().origin()); - // Size should have increased by 0,100. - EXPECT_EQ(gfx::Size(100, 200), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, TopRight) { - scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT)); - DragFromCenterBy(w1.get(), -50, 50); - // Position should have been offset by 0,50. - EXPECT_EQ(gfx::Point(0, 50), w1->bounds().origin()); - // Size should have decreased by 50,50. - EXPECT_EQ(gfx::Size(50, 50), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, Top) { - scoped_ptr<aura::Window> w1(CreateWindow(HTTOP)); - DragFromCenterBy(w1.get(), 50, 50); - // Position should have been offset by 0,50. - EXPECT_EQ(gfx::Point(0, 50), w1->bounds().origin()); - // Size should have decreased by 0,50. - EXPECT_EQ(gfx::Size(100, 50), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, Left) { - scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT)); - DragFromCenterBy(w1.get(), 50, 50); - // Position should have been offset by 50,0. - EXPECT_EQ(gfx::Point(50, 0), w1->bounds().origin()); - // Size should have decreased by 50,0. - EXPECT_EQ(gfx::Size(50, 100), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, BottomLeft) { - scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT)); - DragFromCenterBy(w1.get(), 50, -50); - // Position should have been offset by 50,0. - EXPECT_EQ(gfx::Point(50, 0), w1->bounds().origin()); - // Size should have decreased by 50,50. - EXPECT_EQ(gfx::Size(50, 50), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, TopLeft) { - scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT)); - DragFromCenterBy(w1.get(), 50, 50); - // Position should have been offset by 50,50. - EXPECT_EQ(gfx::Point(50, 50), w1->bounds().origin()); - // Size should have decreased by 50,50. - EXPECT_EQ(gfx::Size(50, 50), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, Client) { - scoped_ptr<aura::Window> w1(CreateWindow(HTCLIENT)); - gfx::Rect bounds = w1->bounds(); - DragFromCenterBy(w1.get(), 100, 100); - // Neither position nor size should have changed. - EXPECT_EQ(bounds, w1->bounds()); -} - -TEST_F(ToplevelWindowEventHandlerTest, LeftPastMinimum) { - scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT)); - TestWindowDelegate* window_delegate = - static_cast<TestWindowDelegate*>(w1->delegate()); - window_delegate->set_minimum_size(gfx::Size(40, 40)); - - // Simulate a large left-to-right drag. Window width should be clamped to - // minimum and position change should be limited as well. - DragFromCenterBy(w1.get(), 333, 0); - EXPECT_EQ(gfx::Point(60, 0), w1->bounds().origin()); - EXPECT_EQ(gfx::Size(40, 100), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, RightPastMinimum) { - scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT)); - TestWindowDelegate* window_delegate = - static_cast<TestWindowDelegate*>(w1->delegate()); - window_delegate->set_minimum_size(gfx::Size(40, 40)); - gfx::Point position = w1->bounds().origin(); - - // Simulate a large right-to-left drag. Window width should be clamped to - // minimum and position should not change. - DragFromCenterBy(w1.get(), -333, 0); - EXPECT_EQ(position, w1->bounds().origin()); - EXPECT_EQ(gfx::Size(40, 100), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, TopLeftPastMinimum) { - scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT)); - TestWindowDelegate* window_delegate = - static_cast<TestWindowDelegate*>(w1->delegate()); - window_delegate->set_minimum_size(gfx::Size(40, 40)); - - // Simulate a large top-left to bottom-right drag. Window width should be - // clamped to minimum and position should be limited. - DragFromCenterBy(w1.get(), 333, 444); - EXPECT_EQ(gfx::Point(60, 60), w1->bounds().origin()); - EXPECT_EQ(gfx::Size(40, 40), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, TopRightPastMinimum) { - scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT)); - TestWindowDelegate* window_delegate = - static_cast<TestWindowDelegate*>(w1->delegate()); - window_delegate->set_minimum_size(gfx::Size(40, 40)); - - // Simulate a large top-right to bottom-left drag. Window size should be - // clamped to minimum, x position should not change, and y position should - // be clamped. - DragFromCenterBy(w1.get(), -333, 444); - EXPECT_EQ(gfx::Point(0, 60), w1->bounds().origin()); - EXPECT_EQ(gfx::Size(40, 40), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, BottomLeftPastMinimum) { - scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT)); - TestWindowDelegate* window_delegate = - static_cast<TestWindowDelegate*>(w1->delegate()); - window_delegate->set_minimum_size(gfx::Size(40, 40)); - - // Simulate a large bottom-left to top-right drag. Window size should be - // clamped to minimum, x position should be clamped, and y position should - // not change. - DragFromCenterBy(w1.get(), 333, -444); - EXPECT_EQ(gfx::Point(60, 0), w1->bounds().origin()); - EXPECT_EQ(gfx::Size(40, 40), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, BottomRightPastMinimum) { - scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT)); - TestWindowDelegate* window_delegate = - static_cast<TestWindowDelegate*>(w1->delegate()); - window_delegate->set_minimum_size(gfx::Size(40, 40)); - gfx::Point position = w1->bounds().origin(); - - // Simulate a large bottom-right to top-left drag. Window size should be - // clamped to minimum and position should not change. - DragFromCenterBy(w1.get(), -333, -444); - EXPECT_EQ(position, w1->bounds().origin()); - EXPECT_EQ(gfx::Size(40, 40), w1->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, BottomRightWorkArea) { - scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMRIGHT)); - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - target.get()).work_area(); - gfx::Point position = target->bounds().origin(); - // Drag further than work_area bottom. - DragFromCenterBy(target.get(), 100, work_area.height()); - // Position should not have changed. - EXPECT_EQ(position, target->bounds().origin()); - // Size should have increased by 100, work_area.height() - target->bounds.y() - EXPECT_EQ(gfx::Size(200, work_area.height() - target->bounds().y()), - target->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, BottomLeftWorkArea) { - scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMLEFT)); - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - target.get()).work_area(); - gfx::Point position = target->bounds().origin(); - // Drag further than work_area bottom. - DragFromCenterBy(target.get(), -30, work_area.height()); - // origin is now at 70, 100. - EXPECT_EQ(position.x() - 30, target->bounds().x()); - EXPECT_EQ(position.y(), target->bounds().y()); - // Size should have increased by 30, work_area.height() - target->bounds.y() - EXPECT_EQ(gfx::Size(130, work_area.height() - target->bounds().y()), - target->bounds().size()); -} - -TEST_F(ToplevelWindowEventHandlerTest, BottomWorkArea) { - scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOM)); - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - target.get()).work_area(); - gfx::Point position = target->bounds().origin(); - // Drag further than work_area bottom. - DragFromCenterBy(target.get(), 0, work_area.height()); - // Position should not have changed. - EXPECT_EQ(position, target->bounds().origin()); - // Size should have increased by 0, work_area.height() - target->bounds.y() - EXPECT_EQ(gfx::Size(100, work_area.height() - target->bounds().y()), - target->bounds().size()); -} - -// Verifies we don't let windows drag to a -y location. -TEST_F(ToplevelWindowEventHandlerTest, DontDragToNegativeY) { - scoped_ptr<aura::Window> target(CreateWindow(HTTOP)); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - target.get()); - generator.MoveMouseTo(0, 5); - generator.DragMouseBy(0, -5); - // The y location and height should not have changed. - EXPECT_EQ(0, target->bounds().y()); - EXPECT_EQ(100, target->bounds().height()); -} - -// Verifies we don't let windows go bigger than the display width. -TEST_F(ToplevelWindowEventHandlerTest, DontGotWiderThanScreen) { - scoped_ptr<aura::Window> target(CreateWindow(HTRIGHT)); - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - target.get()).bounds(); - DragFromCenterBy(target.get(), work_area.width() * 2, 0); - // The y location and height should not have changed. - EXPECT_EQ(work_area.width(), target->bounds().width()); -} - -// Verifies that touch-gestures drag the window correctly. -TEST_F(ToplevelWindowEventHandlerTest, GestureDrag) { - scoped_ptr<aura::Window> target( - CreateTestWindowInShellWithDelegate( - new TestWindowDelegate(HTCAPTION), - 0, - gfx::Rect(0, 0, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(target.get()); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - target.get()); - gfx::Rect old_bounds = target->bounds(); - gfx::Point location(5, 5); - target->SetProperty(aura::client::kCanMaximizeKey, true); - - gfx::Point end = location; - - // Snap right; - { - // Get the expected snapped bounds before snapping. - internal::SnapSizer sizer(window_state, location, - internal::SnapSizer::RIGHT_EDGE, - internal::SnapSizer::OTHER_INPUT); - gfx::Rect snapped_bounds = sizer.GetSnapBounds(target->bounds()); - - end.Offset(100, 0); - generator.GestureScrollSequence(location, end, - base::TimeDelta::FromMilliseconds(5), - 10); - RunAllPendingInMessageLoop(); - - // Verify that the window has moved after the gesture. - EXPECT_NE(old_bounds.ToString(), target->bounds().ToString()); - EXPECT_EQ(snapped_bounds.ToString(), target->bounds().ToString()); - } - - old_bounds = target->bounds(); - - // Snap left. - { - // Get the expected snapped bounds before snapping. - internal::SnapSizer sizer(window_state, location, - internal::SnapSizer::LEFT_EDGE, - internal::SnapSizer::OTHER_INPUT); - gfx::Rect snapped_bounds = sizer.GetSnapBounds(target->bounds()); - end = location = target->GetBoundsInRootWindow().CenterPoint(); - end.Offset(-100, 0); - generator.GestureScrollSequence(location, end, - base::TimeDelta::FromMilliseconds(5), - 10); - RunAllPendingInMessageLoop(); - - EXPECT_NE(old_bounds.ToString(), target->bounds().ToString()); - EXPECT_EQ(snapped_bounds.ToString(), target->bounds().ToString()); - } - - gfx::Rect bounds_before_maximization = target->bounds(); - bounds_before_maximization.Offset(0, 100); - target->SetBounds(bounds_before_maximization); - old_bounds = target->bounds(); - - // Maximize. - end = location = target->GetBoundsInRootWindow().CenterPoint(); - end.Offset(0, -100); - generator.GestureScrollSequence(location, end, - base::TimeDelta::FromMilliseconds(5), - 10); - RunAllPendingInMessageLoop(); - - EXPECT_NE(old_bounds.ToString(), target->bounds().ToString()); - EXPECT_TRUE(window_state->IsMaximized()); - EXPECT_EQ(old_bounds.ToString(), - window_state->GetRestoreBoundsInScreen().ToString()); - - window_state->Restore(); - target->SetBounds(old_bounds); - - // Minimize. - end = location = target->GetBoundsInRootWindow().CenterPoint(); - end.Offset(0, 100); - generator.GestureScrollSequence(location, end, - base::TimeDelta::FromMilliseconds(5), - 10); - RunAllPendingInMessageLoop(); - EXPECT_NE(old_bounds.ToString(), target->bounds().ToString()); - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_TRUE(window_state->always_restores_to_restore_bounds()); - EXPECT_EQ(old_bounds.ToString(), - window_state->GetRestoreBoundsInScreen().ToString()); -} - -// Tests that a gesture cannot minimize a window in login/lock screen. -TEST_F(ToplevelWindowEventHandlerTest, GestureDragMinimizeLoginScreen) { - LockStateController* state_controller = - Shell::GetInstance()->lock_state_controller(); - state_controller->OnLoginStateChanged(user::LOGGED_IN_NONE); - state_controller->OnLockStateChanged(false); - SetUserLoggedIn(false); - - scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION)); - aura::Window* lock = internal::RootWindowController::ForWindow(target.get())-> - GetContainer(internal::kShellWindowId_LockSystemModalContainer); - lock->AddChild(target.get()); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - target.get()); - gfx::Rect old_bounds = target->bounds(); - gfx::Point location(5, 5); - target->SetProperty(aura::client::kCanMaximizeKey, true); - - gfx::Point end = location; - end.Offset(0, 100); - generator.GestureScrollSequence(location, end, - base::TimeDelta::FromMilliseconds(5), - 10); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(wm::GetWindowState(target.get())->IsMinimized()); -} - -TEST_F(ToplevelWindowEventHandlerTest, GestureDragToRestore) { - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithDelegate( - new TestWindowDelegate(HTCAPTION), - 0, - gfx::Rect(10, 20, 30, 40))); - window->Show(); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->Activate(); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window.get()); - gfx::Rect old_bounds = window->bounds(); - gfx::Point location, end; - end = location = window->GetBoundsInRootWindow().CenterPoint(); - end.Offset(0, 100); - generator.GestureScrollSequence(location, end, - base::TimeDelta::FromMilliseconds(5), - 10); - RunAllPendingInMessageLoop(); - EXPECT_NE(old_bounds.ToString(), window->bounds().ToString()); - EXPECT_TRUE(window_state->IsMinimized()); - EXPECT_TRUE(window_state->always_restores_to_restore_bounds()); - EXPECT_EQ(old_bounds.ToString(), - window_state->GetRestoreBoundsInScreen().ToString()); -} - -// Tests that an unresizable window cannot be dragged or snapped using gestures. -TEST_F(ToplevelWindowEventHandlerTest, GestureDragForUnresizableWindow) { - scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION)); - wm::WindowState* window_state = wm::GetWindowState(target.get()); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - target.get()); - gfx::Rect old_bounds = target->bounds(); - gfx::Point location(5, 5); - - target->SetProperty(aura::client::kCanResizeKey, false); - - gfx::Point end = location; - - // Try to snap right. The window is not resizable. So it should not snap. - { - // Get the expected snapped bounds before the gesture. - internal::SnapSizer sizer(window_state, location, - internal::SnapSizer::RIGHT_EDGE, - internal::SnapSizer::OTHER_INPUT); - gfx::Rect snapped_bounds = sizer.GetSnapBounds(target->bounds()); - - end.Offset(100, 0); - generator.GestureScrollSequence(location, end, - base::TimeDelta::FromMilliseconds(5), - 10); - RunAllPendingInMessageLoop(); - - // Verify that the window has moved after the gesture. - gfx::Rect expected_bounds(old_bounds); - expected_bounds.Offset(gfx::Vector2d(100, 0)); - EXPECT_EQ(expected_bounds.ToString(), target->bounds().ToString()); - - // Verify that the window did not snap left. - EXPECT_NE(snapped_bounds.ToString(), target->bounds().ToString()); - } - - old_bounds = target->bounds(); - - // Try to snap left. It should not snap. - { - // Get the expected snapped bounds before the gesture. - internal::SnapSizer sizer(window_state, location, - internal::SnapSizer::LEFT_EDGE, - internal::SnapSizer::OTHER_INPUT); - gfx::Rect snapped_bounds = sizer.GetSnapBounds(target->bounds()); - end = location = target->GetBoundsInRootWindow().CenterPoint(); - end.Offset(-100, 0); - generator.GestureScrollSequence(location, end, - base::TimeDelta::FromMilliseconds(5), - 10); - RunAllPendingInMessageLoop(); - - // Verify that the window has moved after the gesture. - gfx::Rect expected_bounds(old_bounds); - expected_bounds.Offset(gfx::Vector2d(-100, 0)); - EXPECT_EQ(expected_bounds.ToString(), target->bounds().ToString()); - - // Verify that the window did not snap left. - EXPECT_NE(snapped_bounds.ToString(), target->bounds().ToString()); - } -} - -// Tests that dragging multiple windows at the same time is not allowed. -TEST_F(ToplevelWindowEventHandlerTest, GestureDragMultipleWindows) { - scoped_ptr<aura::Window> target( - CreateTestWindowInShellWithDelegate( - new TestWindowDelegate(HTCAPTION), - 0, - gfx::Rect(0, 0, 100, 100))); - scoped_ptr<aura::Window> notmoved( - CreateTestWindowInShellWithDelegate( - new TestWindowDelegate(HTCAPTION), - 1, gfx::Rect(100, 0, 100, 100))); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - target.get()); - gfx::Rect old_bounds = target->bounds(); - gfx::Point location(5, 5); - target->SetProperty(aura::client::kCanMaximizeKey, true); - - // Send some touch events to start dragging |target|. - generator.MoveTouch(location); - generator.PressTouch(); - location.Offset(40, 5); - generator.MoveTouch(location); - - // Try to drag |notmoved| window. This should not move the window. - { - gfx::Rect bounds = notmoved->bounds(); - aura::test::EventGenerator gen(Shell::GetPrimaryRootWindow(), - notmoved.get()); - gfx::Point start = notmoved->bounds().origin() + gfx::Vector2d(10, 10); - gfx::Point end = start + gfx::Vector2d(100, 10); - gen.GestureScrollSequence(start, end, - base::TimeDelta::FromMilliseconds(10), - 10); - EXPECT_EQ(bounds.ToString(), notmoved->bounds().ToString()); - } -} - -// Verifies pressing escape resets the bounds to the original bounds. -// Disabled crbug.com/166219. -#if defined(OS_WIN) -#define MAYBE_EscapeReverts DISABLED_EscapeReverts -#else -#define MAYBE_EscapeReverts EscapeReverts -#endif -TEST_F(ToplevelWindowEventHandlerTest, MAYBE_EscapeReverts) { - scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMRIGHT)); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - target.get()); - generator.PressLeftButton(); - generator.MoveMouseBy(10, 11); - - // Execute any scheduled draws so that pending mouse events are processed. - RunAllPendingInMessageLoop(); - - EXPECT_EQ("0,0 110x111", target->bounds().ToString()); - generator.PressKey(ui::VKEY_ESCAPE, 0); - generator.ReleaseKey(ui::VKEY_ESCAPE, 0); - EXPECT_EQ("0,0 100x100", target->bounds().ToString()); -} - -// Verifies window minimization/maximization completes drag. -// Disabled crbug.com/166219. -#if defined(OS_WIN) -#define MAYBE_MinimizeMaximizeCompletes DISABLED_MinimizeMaximizeCompletes -#else -#define MAYBE_MinimizeMaximizeCompletes MinimizeMaximizeCompletes -#endif -TEST_F(ToplevelWindowEventHandlerTest, MAYBE_MinimizeMaximizeCompletes) { - // Once window is minimized, window dragging completes. - { - scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION)); - target->Focus(); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - target.get()); - generator.PressLeftButton(); - generator.MoveMouseBy(10, 11); - RunAllPendingInMessageLoop(); - EXPECT_EQ("10,11 100x100", target->bounds().ToString()); - wm::WindowState* window_state = wm::GetWindowState(target.get()); - window_state->Minimize(); - window_state->Restore(); - - generator.PressLeftButton(); - generator.MoveMouseBy(10, 11); - RunAllPendingInMessageLoop(); - EXPECT_EQ("10,11 100x100", target->bounds().ToString()); - } - - // Once window is maximized, window dragging completes. - { - scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION)); - target->Focus(); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - target.get()); - generator.PressLeftButton(); - generator.MoveMouseBy(10, 11); - RunAllPendingInMessageLoop(); - EXPECT_EQ("10,11 100x100", target->bounds().ToString()); - wm::WindowState* window_state = wm::GetWindowState(target.get()); - window_state->Maximize(); - window_state->Restore(); - - generator.PressLeftButton(); - generator.MoveMouseBy(10, 11); - RunAllPendingInMessageLoop(); - EXPECT_EQ("10,11 100x100", target->bounds().ToString()); - } -} - -// Showing the resize shadows when the mouse is over the window edges is tested -// in resize_shadow_and_cursor_test.cc - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/user_activity_detector.cc b/chromium/ash/wm/user_activity_detector.cc deleted file mode 100644 index 2809bb5b2a5..00000000000 --- a/chromium/ash/wm/user_activity_detector.cc +++ /dev/null @@ -1,112 +0,0 @@ -// 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/user_activity_detector.h" - -#include "ash/wm/user_activity_observer.h" -#include "base/format_macros.h" -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "ui/events/event.h" - -namespace ash { - -namespace { - -// Returns a string describing |event|. -std::string GetEventDebugString(const ui::Event* event) { - std::string details = base::StringPrintf( - "type=%d name=%s flags=%d time=%" PRId64, - event->type(), event->name().c_str(), event->flags(), - event->time_stamp().InMilliseconds()); - - if (event->IsKeyEvent()) { - details += base::StringPrintf(" key_code=%d", - static_cast<const ui::KeyEvent*>(event)->key_code()); - } else if (event->IsMouseEvent() || event->IsTouchEvent() || - event->IsGestureEvent()) { - details += base::StringPrintf(" location=%s", - static_cast<const ui::LocatedEvent*>( - event)->location().ToString().c_str()); - } - - return details; -} - -} // namespace - -const int UserActivityDetector::kNotifyIntervalMs = 200; - -// Too low and mouse events generated at the tail end of reconfiguration -// will be reported as user activity and turn the screen back on; too high -// and we'll ignore legitimate activity. -const int UserActivityDetector::kDisplayPowerChangeIgnoreMouseMs = 1000; - -UserActivityDetector::UserActivityDetector() { -} - -UserActivityDetector::~UserActivityDetector() { -} - -bool UserActivityDetector::HasObserver(UserActivityObserver* observer) const { - return observers_.HasObserver(observer); -} - -void UserActivityDetector::AddObserver(UserActivityObserver* observer) { - observers_.AddObserver(observer); -} - -void UserActivityDetector::RemoveObserver(UserActivityObserver* observer) { - observers_.RemoveObserver(observer); -} - -void UserActivityDetector::OnDisplayPowerChanging() { - honor_mouse_events_time_ = GetCurrentTime() + - base::TimeDelta::FromMilliseconds(kDisplayPowerChangeIgnoreMouseMs); -} - -void UserActivityDetector::OnKeyEvent(ui::KeyEvent* event) { - HandleActivity(event); -} - -void UserActivityDetector::OnMouseEvent(ui::MouseEvent* event) { - if (event->flags() & ui::EF_IS_SYNTHESIZED) - return; - if (!honor_mouse_events_time_.is_null() && - GetCurrentTime() < honor_mouse_events_time_) - return; - - HandleActivity(event); -} - -void UserActivityDetector::OnScrollEvent(ui::ScrollEvent* event) { - HandleActivity(event); -} - -void UserActivityDetector::OnTouchEvent(ui::TouchEvent* event) { - HandleActivity(event); -} - -void UserActivityDetector::OnGestureEvent(ui::GestureEvent* event) { - HandleActivity(event); -} - -base::TimeTicks UserActivityDetector::GetCurrentTime() const { - return !now_for_test_.is_null() ? now_for_test_ : base::TimeTicks::Now(); -} - -void UserActivityDetector::HandleActivity(const ui::Event* event) { - base::TimeTicks now = GetCurrentTime(); - last_activity_time_ = now; - if (last_observer_notification_time_.is_null() || - (now - last_observer_notification_time_).InMillisecondsF() >= - kNotifyIntervalMs) { - if (VLOG_IS_ON(1)) - VLOG(1) << "Reporting user activity: " << GetEventDebugString(event); - FOR_EACH_OBSERVER(UserActivityObserver, observers_, OnUserActivity(event)); - last_observer_notification_time_ = now; - } -} - -} // namespace ash diff --git a/chromium/ash/wm/user_activity_detector.h b/chromium/ash/wm/user_activity_detector.h deleted file mode 100644 index 1140c3d9196..00000000000 --- a/chromium/ash/wm/user_activity_detector.h +++ /dev/null @@ -1,81 +0,0 @@ -// 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_USER_ACTIVITY_DETECTOR_H_ -#define ASH_WM_USER_ACTIVITY_DETECTOR_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/observer_list.h" -#include "base/time/time.h" -#include "ui/events/event_handler.h" - -namespace ash { - -class UserActivityObserver; - -// Watches for input events and notifies observers that the user is active. -class ASH_EXPORT UserActivityDetector : public ui::EventHandler { - public: - // Minimum amount of time between notifications to observers. - static const int kNotifyIntervalMs; - - // Amount of time that mouse events should be ignored after notification - // is received that displays' power states are being changed. - static const int kDisplayPowerChangeIgnoreMouseMs; - - UserActivityDetector(); - virtual ~UserActivityDetector(); - - base::TimeTicks last_activity_time() const { return last_activity_time_; } - - void set_now_for_test(base::TimeTicks now) { now_for_test_ = now; } - - bool HasObserver(UserActivityObserver* observer) const; - void AddObserver(UserActivityObserver* observer); - void RemoveObserver(UserActivityObserver* observer); - - // Called when displays are about to be turned on or off. - void OnDisplayPowerChanging(); - - // ui::EventHandler implementation. - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; - virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - private: - // Returns |now_for_test_| if set or base::TimeTicks::Now() otherwise. - base::TimeTicks GetCurrentTime() const; - - // Updates |last_activity_time_|. Additionally notifies observers and - // updates |last_observer_notification_time_| if enough time has passed - // since the last notification. - void HandleActivity(const ui::Event* event); - - ObserverList<UserActivityObserver> observers_; - - // Last time at which user activity was observed. - base::TimeTicks last_activity_time_; - - // Last time at which we notified observers that the user was active. - base::TimeTicks last_observer_notification_time_; - - // If set, used when the current time is needed. This can be set by tests to - // simulate the passage of time. - base::TimeTicks now_for_test_; - - // If set, mouse events will be ignored until this time is reached. This - // is to avoid reporting mouse events that occur when displays are turned - // on or off as user activity. - base::TimeTicks honor_mouse_events_time_; - - DISALLOW_COPY_AND_ASSIGN(UserActivityDetector); -}; - -} // namespace ash - -#endif // ASH_WM_USER_ACTIVITY_DETECTOR_H_ diff --git a/chromium/ash/wm/user_activity_detector_unittest.cc b/chromium/ash/wm/user_activity_detector_unittest.cc deleted file mode 100644 index 89f6aee910a..00000000000 --- a/chromium/ash/wm/user_activity_detector_unittest.cc +++ /dev/null @@ -1,225 +0,0 @@ -// 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/user_activity_detector.h" - -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/user_activity_observer.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/events/event.h" -#include "ui/events/event_constants.h" -#include "ui/events/keycodes/keyboard_codes.h" -#include "ui/gfx/point.h" - -namespace { - -void SetEventTarget(ui::EventTarget* target, ui::Event* event) { - ui::Event::DispatcherApi dispatch_helper(event); - dispatch_helper.set_target(target); -} - -} - -namespace ash { -namespace test { - -// Implementation that just counts the number of times we've been told that the -// user is active. -class TestUserActivityObserver : public UserActivityObserver { - public: - TestUserActivityObserver() : num_invocations_(0) {} - - int num_invocations() const { return num_invocations_; } - void reset_stats() { num_invocations_ = 0; } - - // UserActivityObserver implementation. - virtual void OnUserActivity(const ui::Event* event) OVERRIDE { - num_invocations_++; - } - - private: - // Number of times that OnUserActivity() has been called. - int num_invocations_; - - DISALLOW_COPY_AND_ASSIGN(TestUserActivityObserver); -}; - -class UserActivityDetectorTest : public AshTestBase { - public: - UserActivityDetectorTest() {} - virtual ~UserActivityDetectorTest() {} - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - observer_.reset(new TestUserActivityObserver); - detector_ = Shell::GetInstance()->user_activity_detector(); - detector_->AddObserver(observer_.get()); - - now_ = base::TimeTicks::Now(); - detector_->set_now_for_test(now_); - } - - virtual void TearDown() OVERRIDE { - detector_->RemoveObserver(observer_.get()); - AshTestBase::TearDown(); - } - - protected: - // Move |detector_|'s idea of the current time forward by |delta|. - void AdvanceTime(base::TimeDelta delta) { - now_ += delta; - detector_->set_now_for_test(now_); - } - - UserActivityDetector* detector_; // not owned - - scoped_ptr<TestUserActivityObserver> observer_; - - base::TimeTicks now_; - - private: - DISALLOW_COPY_AND_ASSIGN(UserActivityDetectorTest); -}; - -// Checks that the observer is notified in response to different types of input -// events. -TEST_F(UserActivityDetectorTest, Basic) { - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(12345)); - - ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE, false); - SetEventTarget(window.get(), &key_event); - detector_->OnKeyEvent(&key_event); - EXPECT_FALSE(key_event.handled()); - EXPECT_EQ(now_.ToInternalValue(), - detector_->last_activity_time().ToInternalValue()); - EXPECT_EQ(1, observer_->num_invocations()); - observer_->reset_stats(); - - base::TimeDelta advance_delta = base::TimeDelta::FromMilliseconds( - UserActivityDetector::kNotifyIntervalMs); - AdvanceTime(advance_delta); - ui::MouseEvent mouse_event( - ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), ui::EF_NONE); - SetEventTarget(window.get(), &mouse_event); - detector_->OnMouseEvent(&mouse_event); - EXPECT_FALSE(mouse_event.handled()); - EXPECT_EQ(now_.ToInternalValue(), - detector_->last_activity_time().ToInternalValue()); - EXPECT_EQ(1, observer_->num_invocations()); - observer_->reset_stats(); - - base::TimeTicks time_before_ignore = now_; - - // Temporarily ignore mouse events when displays are turned on or off. - detector_->OnDisplayPowerChanging(); - detector_->OnMouseEvent(&mouse_event); - EXPECT_FALSE(mouse_event.handled()); - EXPECT_EQ(time_before_ignore.ToInternalValue(), - detector_->last_activity_time().ToInternalValue()); - EXPECT_EQ(0, observer_->num_invocations()); - observer_->reset_stats(); - - const base::TimeDelta kIgnoreMouseTime = - base::TimeDelta::FromMilliseconds( - UserActivityDetector::kDisplayPowerChangeIgnoreMouseMs); - AdvanceTime(kIgnoreMouseTime / 2); - detector_->OnMouseEvent(&mouse_event); - EXPECT_FALSE(mouse_event.handled()); - EXPECT_EQ(time_before_ignore.ToInternalValue(), - detector_->last_activity_time().ToInternalValue()); - EXPECT_EQ(0, observer_->num_invocations()); - observer_->reset_stats(); - - // After enough time has passed, mouse events should be reported again. - AdvanceTime(std::max(kIgnoreMouseTime, advance_delta)); - detector_->OnMouseEvent(&mouse_event); - EXPECT_FALSE(mouse_event.handled()); - EXPECT_EQ(now_.ToInternalValue(), - detector_->last_activity_time().ToInternalValue()); - EXPECT_EQ(1, observer_->num_invocations()); - observer_->reset_stats(); - - AdvanceTime(advance_delta); - ui::TouchEvent touch_event( - ui::ET_TOUCH_PRESSED, gfx::Point(), 0, base::TimeDelta()); - SetEventTarget(window.get(), &touch_event); - detector_->OnTouchEvent(&touch_event); - EXPECT_FALSE(touch_event.handled()); - EXPECT_EQ(now_.ToInternalValue(), - detector_->last_activity_time().ToInternalValue()); - EXPECT_EQ(1, observer_->num_invocations()); - observer_->reset_stats(); - - AdvanceTime(advance_delta); - ui::GestureEvent gesture_event( - ui::ET_GESTURE_TAP, 0, 0, ui::EF_NONE, - base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000), - ui::GestureEventDetails(ui::ET_GESTURE_TAP, 0, 0), 0U); - SetEventTarget(window.get(), &gesture_event); - detector_->OnGestureEvent(&gesture_event); - EXPECT_FALSE(gesture_event.handled()); - EXPECT_EQ(now_.ToInternalValue(), - detector_->last_activity_time().ToInternalValue()); - EXPECT_EQ(1, observer_->num_invocations()); - observer_->reset_stats(); -} - -// Checks that observers aren't notified too frequently. -TEST_F(UserActivityDetectorTest, RateLimitNotifications) { - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(12345)); - - // The observer should be notified about a key event. - ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE, false); - SetEventTarget(window.get(), &event); - detector_->OnKeyEvent(&event); - EXPECT_FALSE(event.handled()); - EXPECT_EQ(1, observer_->num_invocations()); - observer_->reset_stats(); - - // It shouldn't be notified if a second event occurs - // in the same instant in time. - detector_->OnKeyEvent(&event); - EXPECT_FALSE(event.handled()); - EXPECT_EQ(0, observer_->num_invocations()); - observer_->reset_stats(); - - // Advance the time, but not quite enough for another notification to be sent. - AdvanceTime( - base::TimeDelta::FromMilliseconds( - UserActivityDetector::kNotifyIntervalMs - 100)); - detector_->OnKeyEvent(&event); - EXPECT_FALSE(event.handled()); - EXPECT_EQ(0, observer_->num_invocations()); - observer_->reset_stats(); - - // Advance time by the notification interval, definitely moving out of the - // rate limit. This should let us trigger another notification. - AdvanceTime(base::TimeDelta::FromMilliseconds( - UserActivityDetector::kNotifyIntervalMs)); - - detector_->OnKeyEvent(&event); - EXPECT_FALSE(event.handled()); - EXPECT_EQ(1, observer_->num_invocations()); -} - -// Checks that the detector ignores synthetic mouse events. -TEST_F(UserActivityDetectorTest, IgnoreSyntheticMouseEvents) { - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(12345)); - ui::MouseEvent mouse_event( - ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), ui::EF_IS_SYNTHESIZED); - SetEventTarget(window.get(), &mouse_event); - detector_->OnMouseEvent(&mouse_event); - EXPECT_FALSE(mouse_event.handled()); - EXPECT_EQ(base::TimeTicks().ToInternalValue(), - detector_->last_activity_time().ToInternalValue()); - EXPECT_EQ(0, observer_->num_invocations()); -} - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/user_activity_observer.h b/chromium/ash/wm/user_activity_observer.h deleted file mode 100644 index a65ebfa9667..00000000000 --- a/chromium/ash/wm/user_activity_observer.h +++ /dev/null @@ -1,35 +0,0 @@ -// 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_USER_ACTIVITY_OBSERVER_H_ -#define ASH_WM_USER_ACTIVITY_OBSERVER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" - -namespace ui { -class Event; -} - -namespace ash { - -// Interface for classes that want to be notified about user activity. -// Implementations should register themselves with UserActivityDetector. -class ASH_EXPORT UserActivityObserver { - public: - // Invoked periodically while the user is active (i.e. generating input - // events). |event| is the event that triggered the notification; it may - // be NULL in some cases (e.g. testing or synthetic invocations). - virtual void OnUserActivity(const ui::Event* event) = 0; - - protected: - UserActivityObserver() {} - virtual ~UserActivityObserver() {} - - DISALLOW_COPY_AND_ASSIGN(UserActivityObserver); -}; - -} // namespace ash - -#endif // ASH_WM_USER_ACTIVITY_OBSERVER_H_ diff --git a/chromium/ash/wm/video_detector.cc b/chromium/ash/wm/video_detector.cc deleted file mode 100644 index 33eba33a707..00000000000 --- a/chromium/ash/wm/video_detector.cc +++ /dev/null @@ -1,135 +0,0 @@ -// 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/video_detector.h" - -#include "ash/shell.h" -#include "ash/wm/window_state.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/gfx/rect.h" -#include "ui/views/corewm/window_util.h" - -namespace ash { - -const int VideoDetector::kMinUpdateWidth = 333; -const int VideoDetector::kMinUpdateHeight = 250; -const int VideoDetector::kMinFramesPerSecond = 15; -const double VideoDetector::kNotifyIntervalSec = 1.0; - -// Stores information about updates to a window and determines whether it's -// likely that a video is playing in it. -class VideoDetector::WindowInfo { - public: - WindowInfo() : buffer_start_(0), buffer_size_(0) {} - - // Handles an update within a window, returning true if it appears that - // video is currently playing in the window. - bool RecordUpdateAndCheckForVideo(const gfx::Rect& region, - base::TimeTicks now) { - if (region.width() < kMinUpdateWidth || region.height() < kMinUpdateHeight) - return false; - - // If the buffer is full, drop the first timestamp. - if (buffer_size_ == static_cast<size_t>(kMinFramesPerSecond)) { - buffer_start_ = (buffer_start_ + 1) % kMinFramesPerSecond; - buffer_size_--; - } - - update_times_[(buffer_start_ + buffer_size_) % kMinFramesPerSecond] = now; - buffer_size_++; - - return buffer_size_ == static_cast<size_t>(kMinFramesPerSecond) && - (now - update_times_[buffer_start_]).InSecondsF() <= 1.0; - } - - private: - // Circular buffer containing update times of the last (up to - // |kMinFramesPerSecond|) video-sized updates to this window. - base::TimeTicks update_times_[kMinFramesPerSecond]; - - // Index into |update_times_| of the oldest update. - size_t buffer_start_; - - // Number of updates stored in |update_times_|. - size_t buffer_size_; - - DISALLOW_COPY_AND_ASSIGN(WindowInfo); -}; - -VideoDetector::VideoDetector() - : observer_manager_(this), - is_shutting_down_(false) { - aura::Env::GetInstance()->AddObserver(this); - Shell::GetInstance()->AddShellObserver(this); -} - -VideoDetector::~VideoDetector() { - Shell::GetInstance()->RemoveShellObserver(this); - aura::Env::GetInstance()->RemoveObserver(this); -} - -void VideoDetector::AddObserver(VideoDetectorObserver* observer) { - observers_.AddObserver(observer); -} - -void VideoDetector::RemoveObserver(VideoDetectorObserver* observer) { - observers_.RemoveObserver(observer); -} - -void VideoDetector::OnWindowInitialized(aura::Window* window) { - observer_manager_.Add(window); -} - -void VideoDetector::OnWindowPaintScheduled(aura::Window* window, - const gfx::Rect& region) { - if (is_shutting_down_) - return; - linked_ptr<WindowInfo>& info = window_infos_[window]; - if (!info.get()) - info.reset(new WindowInfo); - - base::TimeTicks now = - !now_for_test_.is_null() ? now_for_test_ : base::TimeTicks::Now(); - if (info->RecordUpdateAndCheckForVideo(region, now)) - MaybeNotifyObservers(window, now); -} - -void VideoDetector::OnWindowDestroyed(aura::Window* window) { - window_infos_.erase(window); - observer_manager_.Remove(window); -} - -void VideoDetector::OnAppTerminating() { - // Stop checking video activity once the shutdown - // process starts. crbug.com/231696. - is_shutting_down_ = true; -} - -void VideoDetector::MaybeNotifyObservers(aura::Window* window, - base::TimeTicks now) { - if (!last_observer_notification_time_.is_null() && - (now - last_observer_notification_time_).InSecondsF() < - kNotifyIntervalSec) - return; - - if (!window->IsVisible()) - return; - - gfx::Rect root_bounds = window->GetRootWindow()->bounds(); - if (!window->GetBoundsInRootWindow().Intersects(root_bounds)) - return; - - aura::Window* toplevel_window = views::corewm::GetToplevelWindow(window); - bool is_fullscreen = toplevel_window ? - wm::GetWindowState(toplevel_window)->IsFullscreen() : false; - - FOR_EACH_OBSERVER(VideoDetectorObserver, - observers_, - OnVideoDetected(is_fullscreen)); - last_observer_notification_time_ = now; -} - -} // namespace ash diff --git a/chromium/ash/wm/video_detector.h b/chromium/ash/wm/video_detector.h deleted file mode 100644 index 7a2b112a5a5..00000000000 --- a/chromium/ash/wm/video_detector.h +++ /dev/null @@ -1,109 +0,0 @@ -// 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_VIDEO_DETECTOR_H_ -#define ASH_WM_VIDEO_DETECTOR_H_ - -#include <map> - -#include "ash/ash_export.h" -#include "ash/shell_observer.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/linked_ptr.h" -#include "base/observer_list.h" -#include "base/scoped_observer.h" -#include "base/time/time.h" -#include "ui/aura/env_observer.h" -#include "ui/aura/window_observer.h" - -namespace aura { -class Window; -} - -namespace gfx { -class Rect; -} - -namespace ash { - -class ASH_EXPORT VideoDetectorObserver { - public: - // Invoked periodically while a video is being played onscreen. - virtual void OnVideoDetected(bool is_fullscreen) = 0; - - protected: - virtual ~VideoDetectorObserver() {} -}; - -// Watches for updates to windows and tries to detect when a video is playing. -// We err on the side of false positives and can be fooled by things like -// continuous scrolling of a page. -class ASH_EXPORT VideoDetector : public aura::EnvObserver, - public aura::WindowObserver, - public ShellObserver { - public: - // Minimum dimensions in pixels that a window update must have to be - // considered a potential video frame. - static const int kMinUpdateWidth; - static const int kMinUpdateHeight; - - // Number of video-sized updates that we must see within a second in a window - // before we assume that a video is playing. - static const int kMinFramesPerSecond; - - // Minimum amount of time between notifications to observers that a video is - // playing. - static const double kNotifyIntervalSec; - - VideoDetector(); - virtual ~VideoDetector(); - - void set_now_for_test(base::TimeTicks now) { now_for_test_ = now; } - - void AddObserver(VideoDetectorObserver* observer); - void RemoveObserver(VideoDetectorObserver* observer); - - // EnvObserver overrides. - virtual void OnWindowInitialized(aura::Window* window) OVERRIDE; - - // WindowObserver overrides. - virtual void OnWindowPaintScheduled(aura::Window* window, - const gfx::Rect& region) OVERRIDE; - virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; - - // ShellObserver overrides. - virtual void OnAppTerminating() OVERRIDE; - - private: - class WindowInfo; - typedef std::map<aura::Window*, linked_ptr<WindowInfo> > WindowInfoMap; - - // Possibly notifies observers in response to detection of a video in - // |window|. Notifications are rate-limited and don't get sent if the window - // is invisible or offscreen. - void MaybeNotifyObservers(aura::Window* window, base::TimeTicks now); - - // Maps from a window that we're tracking to information about it. - WindowInfoMap window_infos_; - - ObserverList<VideoDetectorObserver> observers_; - - // Last time at which we notified observers that a video was playing. - base::TimeTicks last_observer_notification_time_; - - // If set, used when the current time is needed. This can be set by tests to - // simulate the passage of time. - base::TimeTicks now_for_test_; - - ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_; - - bool is_shutting_down_; - - DISALLOW_COPY_AND_ASSIGN(VideoDetector); -}; - -} // namespace ash - -#endif // ASH_WM_VIDEO_DETECTOR_H_ diff --git a/chromium/ash/wm/video_detector_unittest.cc b/chromium/ash/wm/video_detector_unittest.cc deleted file mode 100644 index 01c79cf8797..00000000000 --- a/chromium/ash/wm/video_detector_unittest.cc +++ /dev/null @@ -1,295 +0,0 @@ -// 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/video_detector.h" - -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_util.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/window_types.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/gfx/rect.h" - -namespace ash { -namespace test { - -// Implementation that just counts the number of times we've been told that a -// video is playing. -class TestVideoDetectorObserver : public VideoDetectorObserver { - public: - TestVideoDetectorObserver() : num_invocations_(0), - num_fullscreens_(0), - num_not_fullscreens_(0) {} - - int num_invocations() const { return num_invocations_; } - int num_fullscreens() const { return num_fullscreens_; } - int num_not_fullscreens() const { return num_not_fullscreens_; } - void reset_stats() { - num_invocations_ = 0; - num_fullscreens_ = 0; - num_not_fullscreens_ = 0; - } - - // VideoDetectorObserver implementation. - virtual void OnVideoDetected(bool is_fullscreen) OVERRIDE { - num_invocations_++; - if (is_fullscreen) - num_fullscreens_++; - else - num_not_fullscreens_++; - } - - private: - // Number of times that OnVideoDetected() has been called. - int num_invocations_; - // Number of times that OnVideoDetected() has been called with is_fullscreen - // == true. - int num_fullscreens_; - // Number of times that OnVideoDetected() has been called with is_fullscreen - // == false. - int num_not_fullscreens_; - - DISALLOW_COPY_AND_ASSIGN(TestVideoDetectorObserver); -}; - -class VideoDetectorTest : public AshTestBase { - public: - VideoDetectorTest() {} - virtual ~VideoDetectorTest() {} - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - observer_.reset(new TestVideoDetectorObserver); - detector_ = Shell::GetInstance()->video_detector(); - detector_->AddObserver(observer_.get()); - - now_ = base::TimeTicks::Now(); - detector_->set_now_for_test(now_); - } - - virtual void TearDown() OVERRIDE { - detector_->RemoveObserver(observer_.get()); - AshTestBase::TearDown(); - } - - protected: - // Move |detector_|'s idea of the current time forward by |delta|. - void AdvanceTime(base::TimeDelta delta) { - now_ += delta; - detector_->set_now_for_test(now_); - } - - VideoDetector* detector_; // not owned - - scoped_ptr<TestVideoDetectorObserver> observer_; - - base::TimeTicks now_; - - private: - DISALLOW_COPY_AND_ASSIGN(VideoDetectorTest); -}; - -TEST_F(VideoDetectorTest, Basic) { - gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); - scoped_ptr<aura::Window> window( - CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); - - // Send enough updates, but make them be too small to trigger detection. - gfx::Rect update_region( - gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth - 1, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(0, observer_->num_invocations()); - - // Send not-quite-enough adaquately-sized updates. - observer_->reset_stats(); - AdvanceTime(base::TimeDelta::FromSeconds(2)); - update_region.set_size( - gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(0, observer_->num_invocations()); - - // We should get notified after the next update, but not in response to - // additional updates. - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(1, observer_->num_invocations()); - EXPECT_EQ(0, observer_->num_fullscreens()); - EXPECT_EQ(1, observer_->num_not_fullscreens()); - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(1, observer_->num_invocations()); - EXPECT_EQ(0, observer_->num_fullscreens()); - EXPECT_EQ(1, observer_->num_not_fullscreens()); - - // Spread out the frames over a longer period of time, but send enough - // over a one-second window that the observer should be notified. - observer_->reset_stats(); - AdvanceTime(base::TimeDelta::FromSeconds(2)); - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(0, observer_->num_invocations()); - - AdvanceTime(base::TimeDelta::FromMilliseconds(500)); - const int kNumFrames = VideoDetector::kMinFramesPerSecond + 1; - base::TimeDelta kInterval = - base::TimeDelta::FromMilliseconds(1000 / kNumFrames); - for (int i = 0; i < kNumFrames; ++i) { - AdvanceTime(kInterval); - detector_->OnWindowPaintScheduled(window.get(), update_region); - } - EXPECT_EQ(1, observer_->num_invocations()); - - // Keep going and check that the observer is notified again. - for (int i = 0; i < kNumFrames; ++i) { - AdvanceTime(kInterval); - detector_->OnWindowPaintScheduled(window.get(), update_region); - } - EXPECT_EQ(2, observer_->num_invocations()); - - // Send updates at a slower rate and check that the observer isn't notified. - base::TimeDelta kSlowInterval = base::TimeDelta::FromMilliseconds( - 1000 / (VideoDetector::kMinFramesPerSecond - 2)); - for (int i = 0; i < kNumFrames; ++i) { - AdvanceTime(kSlowInterval); - detector_->OnWindowPaintScheduled(window.get(), update_region); - } - EXPECT_EQ(2, observer_->num_invocations()); -} - -TEST_F(VideoDetectorTest, Shutdown) { - gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); - scoped_ptr<aura::Window> window( - CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); - gfx::Rect update_region( - gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - - // It should not detect video during the shutdown. - Shell::GetInstance()->OnAppTerminating(); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(0, observer_->num_invocations()); -} - -TEST_F(VideoDetectorTest, WindowNotVisible) { - gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); - scoped_ptr<aura::Window> window( - CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); - - // Reparent the window to the root to make sure that visibility changes aren't - // animated. - Shell::GetPrimaryRootWindow()->AddChild(window.get()); - - // We shouldn't report video that's played in a hidden window. - window->Hide(); - gfx::Rect update_region( - gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(0, observer_->num_invocations()); - - // Make the window visible and send more updates. - observer_->reset_stats(); - AdvanceTime(base::TimeDelta::FromSeconds(2)); - window->Show(); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(1, observer_->num_invocations()); - EXPECT_EQ(0, observer_->num_fullscreens()); - EXPECT_EQ(1, observer_->num_not_fullscreens()); - - // We also shouldn't report video in a window that's fully offscreen. - observer_->reset_stats(); - AdvanceTime(base::TimeDelta::FromSeconds(2)); - gfx::Rect offscreen_bounds( - gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0), - window_bounds.size()); - window->SetBounds(offscreen_bounds); - ASSERT_EQ(offscreen_bounds, window->bounds()); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(0, observer_->num_invocations()); -} - -TEST_F(VideoDetectorTest, MultipleWindows) { - // Create two windows. - gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); - scoped_ptr<aura::Window> window1( - CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); - scoped_ptr<aura::Window> window2( - CreateTestWindowInShell(SK_ColorBLUE, 23456, window_bounds)); - - // Even if there's video playing in both, the observer should only receive a - // single notification. - gfx::Rect update_region( - gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnWindowPaintScheduled(window1.get(), update_region); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnWindowPaintScheduled(window2.get(), update_region); - EXPECT_EQ(1, observer_->num_invocations()); - EXPECT_EQ(0, observer_->num_fullscreens()); - EXPECT_EQ(1, observer_->num_not_fullscreens()); -} - -// Test that the observer receives repeated notifications. -TEST_F(VideoDetectorTest, RepeatedNotifications) { - gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); - scoped_ptr<aura::Window> window( - CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); - - gfx::Rect update_region( - gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(1, observer_->num_invocations()); - EXPECT_EQ(0, observer_->num_fullscreens()); - EXPECT_EQ(1, observer_->num_not_fullscreens()); - // Let enough time pass that a second notification should be sent. - observer_->reset_stats(); - AdvanceTime(base::TimeDelta::FromSeconds( - static_cast<int64>(VideoDetector::kNotifyIntervalSec + 1))); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(1, observer_->num_invocations()); - EXPECT_EQ(0, observer_->num_fullscreens()); - EXPECT_EQ(1, observer_->num_not_fullscreens()); -} - -// Test that the observer receives a true value when the window is fullscreen. -TEST_F(VideoDetectorTest, FullscreenWindow) { - gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); - scoped_ptr<aura::Window> window( - CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - window->Focus(); - gfx::Rect update_region( - gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(1, observer_->num_invocations()); - EXPECT_EQ(1, observer_->num_fullscreens()); - EXPECT_EQ(0, observer_->num_not_fullscreens()); -} - -} // namespace test -} // namespace ash diff --git a/chromium/ash/wm/window_animations.cc b/chromium/ash/wm/window_animations.cc deleted file mode 100644 index 894e11b0186..00000000000 --- a/chromium/ash/wm/window_animations.cc +++ /dev/null @@ -1,551 +0,0 @@ -// 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/window_animations.h" - -#include <math.h> - -#include <algorithm> -#include <vector> - -#include "ash/launcher/launcher.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace_controller.h" -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/stl_util.h" -#include "base/time/time.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/aura/window_property.h" -#include "ui/compositor/compositor_observer.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animation_observer.h" -#include "ui/compositor/layer_animation_sequence.h" -#include "ui/compositor/layer_animator.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/interpolated_transform.h" -#include "ui/gfx/screen.h" -#include "ui/gfx/vector3d_f.h" -#include "ui/views/corewm/window_util.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace { -const int kLayerAnimationsForMinimizeDurationMS = 200; - -// Durations for the cross-fade animation, in milliseconds. -const float kCrossFadeDurationMinMs = 200.f; -const float kCrossFadeDurationMaxMs = 400.f; - -// Durations for the brightness/grayscale fade animation, in milliseconds. -const int kBrightnessGrayscaleFadeDurationMs = 1000; - -// Brightness/grayscale values for hide/show window animations. -const float kWindowAnimation_HideBrightnessGrayscale = 1.f; -const float kWindowAnimation_ShowBrightnessGrayscale = 0.f; - -const float kWindowAnimation_HideOpacity = 0.f; -const float kWindowAnimation_ShowOpacity = 1.f; -// TODO(sky): if we end up sticking with 0, nuke the code doing the rotation. -const float kWindowAnimation_MinimizeRotate = 0.f; - -// Scales for AshWindow above/below current workspace. -const float kLayerScaleAboveSize = 1.1f; -const float kLayerScaleBelowSize = .9f; - -int64 Round64(float f) { - return static_cast<int64>(f + 0.5f); -} - -} // namespace - -const int kCrossFadeDurationMS = 200; - -void AddLayerAnimationsForMinimize(aura::Window* window, bool show) { - // Recalculate the transform at restore time since the launcher item may have - // moved while the window was minimized. - gfx::Rect bounds = window->bounds(); - gfx::Rect target_bounds = GetMinimizeAnimationTargetBoundsInScreen(window); - target_bounds = - ScreenAsh::ConvertRectFromScreen(window->parent(), target_bounds); - - float scale_x = static_cast<float>(target_bounds.width()) / bounds.width(); - float scale_y = static_cast<float>(target_bounds.height()) / bounds.height(); - - scoped_ptr<ui::InterpolatedTransform> scale( - new ui::InterpolatedScale(gfx::Point3F(1, 1, 1), - gfx::Point3F(scale_x, scale_y, 1))); - - scoped_ptr<ui::InterpolatedTransform> translation( - new ui::InterpolatedTranslation( - gfx::Point(), - gfx::Point(target_bounds.x() - bounds.x(), - target_bounds.y() - bounds.y()))); - - scoped_ptr<ui::InterpolatedTransform> rotation( - new ui::InterpolatedRotation(0, kWindowAnimation_MinimizeRotate)); - - scoped_ptr<ui::InterpolatedTransform> rotation_about_pivot( - new ui::InterpolatedTransformAboutPivot( - gfx::Point(bounds.width() * 0.5, bounds.height() * 0.5), - rotation.release())); - - scale->SetChild(translation.release()); - rotation_about_pivot->SetChild(scale.release()); - - rotation_about_pivot->SetReversed(show); - - base::TimeDelta duration = window->layer()->GetAnimator()-> - GetTransitionDuration(); - - scoped_ptr<ui::LayerAnimationElement> transition( - ui::LayerAnimationElement::CreateInterpolatedTransformElement( - rotation_about_pivot.release(), duration)); - - transition->set_tween_type( - show ? gfx::Tween::EASE_IN : gfx::Tween::EASE_IN_OUT); - - window->layer()->GetAnimator()->ScheduleAnimation( - new ui::LayerAnimationSequence(transition.release())); - - // When hiding a window, turn off blending until the animation is 3 / 4 done - // to save bandwidth and reduce jank. - if (!show) { - window->layer()->GetAnimator()->SchedulePauseForProperties( - (duration * 3) / 4, ui::LayerAnimationElement::OPACITY, -1); - } - - // Fade in and out quickly when the window is small to reduce jank. - float opacity = show ? 1.0f : 0.0f; - window->layer()->GetAnimator()->ScheduleAnimation( - new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateOpacityElement( - opacity, duration / 4))); -} - -void AnimateShowWindow_Minimize(aura::Window* window) { - window->layer()->set_delegate(window); - window->layer()->SetOpacity(kWindowAnimation_HideOpacity); - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - base::TimeDelta duration = base::TimeDelta::FromMilliseconds( - kLayerAnimationsForMinimizeDurationMS); - settings.SetTransitionDuration(duration); - AddLayerAnimationsForMinimize(window, true); - - // Now that the window has been restored, we need to clear its animation style - // to default so that normal animation applies. - views::corewm::SetWindowVisibilityAnimationType( - window, views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT); -} - -void AnimateHideWindow_Minimize(aura::Window* window) { - window->layer()->set_delegate(NULL); - - // Property sets within this scope will be implicitly animated. - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - base::TimeDelta duration = base::TimeDelta::FromMilliseconds( - kLayerAnimationsForMinimizeDurationMS); - settings.SetTransitionDuration(duration); - settings.AddObserver( - views::corewm::CreateHidingWindowAnimationObserver(window)); - window->layer()->SetVisible(false); - - AddLayerAnimationsForMinimize(window, false); -} - -void AnimateShowHideWindowCommon_BrightnessGrayscale(aura::Window* window, - bool show) { - window->layer()->set_delegate(window); - - float start_value, end_value; - if (show) { - start_value = kWindowAnimation_HideBrightnessGrayscale; - end_value = kWindowAnimation_ShowBrightnessGrayscale; - } else { - start_value = kWindowAnimation_ShowBrightnessGrayscale; - end_value = kWindowAnimation_HideBrightnessGrayscale; - } - - window->layer()->SetLayerBrightness(start_value); - window->layer()->SetLayerGrayscale(start_value); - if (show) { - window->layer()->SetOpacity(kWindowAnimation_ShowOpacity); - window->layer()->SetVisible(true); - } - - base::TimeDelta duration = - base::TimeDelta::FromMilliseconds(kBrightnessGrayscaleFadeDurationMs); - - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - settings.SetTransitionDuration(duration); - if (!show) { - settings.AddObserver( - views::corewm::CreateHidingWindowAnimationObserver(window)); - } - - window->layer()->GetAnimator()-> - ScheduleTogether( - CreateBrightnessGrayscaleAnimationSequence(end_value, duration)); - if (!show) { - window->layer()->SetOpacity(kWindowAnimation_HideOpacity); - window->layer()->SetVisible(false); - } -} - -void AnimateShowWindow_BrightnessGrayscale(aura::Window* window) { - AnimateShowHideWindowCommon_BrightnessGrayscale(window, true); -} - -void AnimateHideWindow_BrightnessGrayscale(aura::Window* window) { - AnimateShowHideWindowCommon_BrightnessGrayscale(window, false); -} - -bool AnimateShowWindow(aura::Window* window) { - if (!views::corewm::HasWindowVisibilityAnimationTransition( - window, views::corewm::ANIMATE_SHOW)) { - return false; - } - - switch (views::corewm::GetWindowVisibilityAnimationType(window)) { - case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE: - AnimateShowWindow_Minimize(window); - return true; - case WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE: - AnimateShowWindow_BrightnessGrayscale(window); - return true; - default: - NOTREACHED(); - return false; - } -} - -bool AnimateHideWindow(aura::Window* window) { - if (!views::corewm::HasWindowVisibilityAnimationTransition( - window, views::corewm::ANIMATE_HIDE)) { - return false; - } - - switch (views::corewm::GetWindowVisibilityAnimationType(window)) { - case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE: - AnimateHideWindow_Minimize(window); - return true; - case WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE: - AnimateHideWindow_BrightnessGrayscale(window); - return true; - default: - NOTREACHED(); - return false; - } -} - -// Observer for a window cross-fade animation. If either the window closes or -// the layer's animation completes or compositing is aborted due to GPU crash, -// it deletes the layer and removes itself as an observer. -class CrossFadeObserver : public ui::CompositorObserver, - public aura::WindowObserver, - public ui::ImplicitAnimationObserver { - public: - // Observes |window| for destruction, but does not take ownership. - // Takes ownership of |layer| and its child layers. - CrossFadeObserver(aura::Window* window, ui::Layer* layer) - : window_(window), - layer_(layer) { - window_->AddObserver(this); - layer_->GetCompositor()->AddObserver(this); - } - virtual ~CrossFadeObserver() { - window_->RemoveObserver(this); - window_ = NULL; - layer_->GetCompositor()->RemoveObserver(this); - views::corewm::DeepDeleteLayers(layer_); - layer_ = NULL; - } - - // ui::CompositorObserver overrides: - virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE { - } - virtual void OnCompositingStarted(ui::Compositor* compositor, - base::TimeTicks start_time) OVERRIDE { - } - virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE { - } - virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE { - // Triggers OnImplicitAnimationsCompleted() to be called and deletes us. - layer_->GetAnimator()->StopAnimating(); - } - virtual void OnCompositingLockStateChanged( - ui::Compositor* compositor) OVERRIDE { - } - virtual void OnUpdateVSyncParameters(ui::Compositor* compositor, - base::TimeTicks timebase, - base::TimeDelta interval) OVERRIDE { - } - - // aura::WindowObserver overrides: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { - // 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 { - delete this; - } - - private: - aura::Window* window_; // not owned - ui::Layer* layer_; // owned - - DISALLOW_COPY_AND_ASSIGN(CrossFadeObserver); -}; - -// Implementation of cross fading. Window is the window being cross faded. It -// should be at the target bounds. |old_layer| the previous layer from |window|. -// This takes ownership of |old_layer| and deletes when the animation is done. -// |pause_duration| is the duration to pause at the current bounds before -// animating. Returns the duration of the fade. -base::TimeDelta CrossFadeImpl(aura::Window* window, - ui::Layer* old_layer, - gfx::Tween::Type tween_type) { - const gfx::Rect old_bounds(old_layer->bounds()); - const gfx::Rect new_bounds(window->bounds()); - const bool old_on_top = (old_bounds.width() > new_bounds.width()); - - // Shorten the animation if there's not much visual movement. - const base::TimeDelta duration = GetCrossFadeDuration(window, - old_bounds, new_bounds); - - // Scale up the old layer while translating to new position. - { - old_layer->GetAnimator()->StopAnimating(); - ui::ScopedLayerAnimationSettings settings(old_layer->GetAnimator()); - - // Animation observer owns the old layer and deletes itself. - settings.AddObserver(new CrossFadeObserver(window, old_layer)); - settings.SetTransitionDuration(duration); - settings.SetTweenType(tween_type); - gfx::Transform out_transform; - float scale_x = static_cast<float>(new_bounds.width()) / - static_cast<float>(old_bounds.width()); - float scale_y = static_cast<float>(new_bounds.height()) / - static_cast<float>(old_bounds.height()); - out_transform.Translate(new_bounds.x() - old_bounds.x(), - new_bounds.y() - old_bounds.y()); - out_transform.Scale(scale_x, scale_y); - old_layer->SetTransform(out_transform); - if (old_on_top) { - // The old layer is on top, and should fade out. The new layer below will - // stay opaque to block the desktop. - old_layer->SetOpacity(kWindowAnimation_HideOpacity); - } - // In tests |old_layer| is deleted here, as animations have zero duration. - old_layer = NULL; - } - - // Set the new layer's current transform, such that the user sees a scaled - // version of the window with the original bounds at the original position. - gfx::Transform in_transform; - const float scale_x = static_cast<float>(old_bounds.width()) / - static_cast<float>(new_bounds.width()); - const float scale_y = static_cast<float>(old_bounds.height()) / - static_cast<float>(new_bounds.height()); - in_transform.Translate(old_bounds.x() - new_bounds.x(), - old_bounds.y() - new_bounds.y()); - in_transform.Scale(scale_x, scale_y); - window->layer()->SetTransform(in_transform); - if (!old_on_top) { - // The new layer is on top and should fade in. The old layer below will - // stay opaque and block the desktop. - window->layer()->SetOpacity(kWindowAnimation_HideOpacity); - } - { - // Animate the new layer to the identity transform, so the window goes to - // its newly set bounds. - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - settings.SetTransitionDuration(duration); - settings.SetTweenType(tween_type); - window->layer()->SetTransform(gfx::Transform()); - if (!old_on_top) { - // New layer is on top, fade it in. - window->layer()->SetOpacity(kWindowAnimation_ShowOpacity); - } - } - return duration; -} - -void CrossFadeToBounds(aura::Window* window, const gfx::Rect& new_bounds) { - // Some test results in invoking CrossFadeToBounds when window is not visible. - // No animation is necessary in that case, thus just change the bounds and - // quit. - if (!window->TargetVisibility()) { - window->SetBounds(new_bounds); - return; - } - - const gfx::Rect old_bounds = window->bounds(); - - // Create fresh layers for the window and all its children to paint into. - // Takes ownership of the old layer and all its children, which will be - // cleaned up after the animation completes. - // Specify |set_bounds| to true here to keep the old bounds in the child - // windows of |window|. - ui::Layer* old_layer = views::corewm::RecreateWindowLayers(window, true); - ui::Layer* new_layer = window->layer(); - - // Resize the window to the new size, which will force a layout and paint. - window->SetBounds(new_bounds); - - // Ensure the higher-resolution layer is on top. - bool old_on_top = (old_bounds.width() > new_bounds.width()); - if (old_on_top) - old_layer->parent()->StackBelow(new_layer, old_layer); - else - old_layer->parent()->StackAbove(new_layer, old_layer); - - CrossFadeImpl(window, old_layer, gfx::Tween::EASE_OUT); -} - -base::TimeDelta GetCrossFadeDuration(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - if (views::corewm::WindowAnimationsDisabled(window)) - return base::TimeDelta(); - - int old_area = old_bounds.width() * old_bounds.height(); - int new_area = new_bounds.width() * new_bounds.height(); - int max_area = std::max(old_area, new_area); - // Avoid divide by zero. - if (max_area == 0) - return base::TimeDelta::FromMilliseconds(kCrossFadeDurationMS); - - int delta_area = std::abs(old_area - new_area); - // If the area didn't change, the animation is instantaneous. - if (delta_area == 0) - return base::TimeDelta::FromMilliseconds(kCrossFadeDurationMS); - - float factor = - static_cast<float>(delta_area) / static_cast<float>(max_area); - const float kRange = kCrossFadeDurationMaxMs - kCrossFadeDurationMinMs; - return base::TimeDelta::FromMilliseconds( - Round64(kCrossFadeDurationMinMs + (factor * kRange))); -} - -bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) { - if (views::corewm::WindowAnimationsDisabled(window)) - return false; - - // Attempt to run CoreWm supplied animation types. - if (views::corewm::AnimateOnChildWindowVisibilityChanged(window, visible)) - return true; - - // Otherwise try to run an Ash-specific animation. - if (visible) - return AnimateShowWindow(window); - // Don't start hiding the window again if it's already being hidden. - return window->layer()->GetTargetOpacity() != 0.0f && - AnimateHideWindow(window); -} - -std::vector<ui::LayerAnimationSequence*> -CreateBrightnessGrayscaleAnimationSequence(float target_value, - base::TimeDelta duration) { - gfx::Tween::Type animation_type = gfx::Tween::EASE_OUT; - scoped_ptr<ui::LayerAnimationSequence> brightness_sequence( - new ui::LayerAnimationSequence()); - scoped_ptr<ui::LayerAnimationSequence> grayscale_sequence( - new ui::LayerAnimationSequence()); - - scoped_ptr<ui::LayerAnimationElement> brightness_element( - ui::LayerAnimationElement::CreateBrightnessElement( - target_value, duration)); - brightness_element->set_tween_type(animation_type); - brightness_sequence->AddElement(brightness_element.release()); - - scoped_ptr<ui::LayerAnimationElement> grayscale_element( - ui::LayerAnimationElement::CreateGrayscaleElement( - target_value, duration)); - grayscale_element->set_tween_type(animation_type); - grayscale_sequence->AddElement(grayscale_element.release()); - - std::vector<ui::LayerAnimationSequence*> animations; - animations.push_back(brightness_sequence.release()); - animations.push_back(grayscale_sequence.release()); - - return animations; -} - -// Returns scale related to the specified AshWindowScaleType. -void SetTransformForScaleAnimation(ui::Layer* layer, - LayerScaleAnimationDirection type) { - const float scale = - type == LAYER_SCALE_ANIMATION_ABOVE ? kLayerScaleAboveSize : - kLayerScaleBelowSize; - gfx::Transform transform; - transform.Translate(-layer->bounds().width() * (scale - 1.0f) / 2, - -layer->bounds().height() * (scale - 1.0f) / 2); - transform.Scale(scale, scale); - layer->SetTransform(transform); -} - -gfx::Rect GetMinimizeAnimationTargetBoundsInScreen(aura::Window* window) { - Launcher* launcher = Launcher::ForWindow(window); - // Shelf is created lazily and can be NULL. - if (!launcher) - return gfx::Rect(); - gfx::Rect item_rect = launcher->GetScreenBoundsOfItemIconForWindow(window); - - // The launcher item is visible and has an icon. - if (!item_rect.IsEmpty()) - return item_rect; - - // If both the icon width and height are 0, then there is no icon in the - // launcher for |window| or the icon is hidden in the overflow menu. If the - // launcher is auto hidden, one of the height or width will be 0 but the - // position in the launcher and the major dimension are still reported - // correctly and the window can be animated to the launcher item's light - // bar. - if (item_rect.width() != 0 || item_rect.height() != 0) { - internal::ShelfLayoutManager* layout_manager = - internal::ShelfLayoutManager::ForLauncher(window); - if (layout_manager->visibility_state() == SHELF_AUTO_HIDE) { - gfx::Rect shelf_bounds = - launcher->shelf_widget()->GetWindowBoundsInScreen(); - switch (layout_manager->GetAlignment()) { - case SHELF_ALIGNMENT_BOTTOM: - item_rect.set_y(shelf_bounds.y()); - break; - case SHELF_ALIGNMENT_LEFT: - item_rect.set_x(shelf_bounds.right()); - break; - case SHELF_ALIGNMENT_RIGHT: - item_rect.set_x(shelf_bounds.x()); - break; - case SHELF_ALIGNMENT_TOP: - item_rect.set_y(shelf_bounds.bottom()); - break; - } - return item_rect; - } - } - - // Assume the launcher is overflowed, zoom off to the bottom right of the - // work area. - gfx::Rect work_area = - Shell::GetScreen()->GetDisplayNearestWindow(window).work_area(); - return gfx::Rect(work_area.right(), work_area.bottom(), 0, 0); -} - -} // namespace ash diff --git a/chromium/ash/wm/window_animations.h b/chromium/ash/wm/window_animations.h deleted file mode 100644 index f084bcc838f..00000000000 --- a/chromium/ash/wm/window_animations.h +++ /dev/null @@ -1,76 +0,0 @@ -// 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_WINDOW_ANIMATIONS_H_ -#define ASH_WM_WINDOW_ANIMATIONS_H_ - -#include "ash/ash_export.h" -#include "ui/gfx/transform.h" -#include "ui/views/corewm/window_animations.h" - -namespace aura { -class Window; -} -namespace ui { -class Layer; -} - -// This is only for animations specific to Ash. For window animations shared -// with desktop Chrome, see ui/views/corewm/window_animations.h. -namespace ash { - -// An extension of the window animations provided by CoreWm. These should be -// Ash-specific only. -enum WindowVisibilityAnimationType { - // Window scale/rotates down to its launcher icon. - WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE = - views::corewm::WINDOW_VISIBILITY_ANIMATION_MAX, - // Fade in/out using brightness and grayscale web filters. - WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE -}; - -// Direction for ash-specific window animations used in workspaces and -// lock/unlock animations. -enum LayerScaleAnimationDirection { - LAYER_SCALE_ANIMATION_ABOVE, - LAYER_SCALE_ANIMATION_BELOW, -}; - -// Amount of time for the cross fade animation. -extern const int kCrossFadeDurationMS; - -// Animate a cross-fade of |window| from its current bounds to |new_bounds|. -ASH_EXPORT void CrossFadeToBounds(aura::Window* window, - const gfx::Rect& new_bounds); - -// Returns the duration of the cross-fade animation based on the |old_bounds| -// and |new_bounds| of the |window|. -ASH_EXPORT base::TimeDelta GetCrossFadeDuration(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds); - -ASH_EXPORT bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, - bool visible); - -// Creates vector of animation sequences that lasts for |duration| and changes -// brightness and grayscale to |target_value|. Caller takes ownership of -// returned LayerAnimationSequence objects. -ASH_EXPORT std::vector<ui::LayerAnimationSequence*> -CreateBrightnessGrayscaleAnimationSequence(float target_value, - base::TimeDelta duration); - -// Applies scale related to the specified AshWindowScaleType. -ASH_EXPORT void SetTransformForScaleAnimation( - ui::Layer* layer, - LayerScaleAnimationDirection type); - -// Returns the approximate bounds to which |window| will be animated when it -// is minimized. The bounds are approximate because the minimize animation -// involves rotation. -ASH_EXPORT gfx::Rect GetMinimizeAnimationTargetBoundsInScreen( - aura::Window* window); - -} // namespace ash - -#endif // ASH_WM_WINDOW_ANIMATIONS_H_ diff --git a/chromium/ash/wm/window_animations_unittest.cc b/chromium/ash/wm/window_animations_unittest.cc deleted file mode 100644 index eeeb120b094..00000000000 --- a/chromium/ash/wm/window_animations_unittest.cc +++ /dev/null @@ -1,243 +0,0 @@ -// 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/window_animations.h" - -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/workspace_controller.h" -#include "base/time/time.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animation_observer.h" -#include "ui/compositor/layer_animator.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/animation/animation_container_element.h" - -using aura::Window; -using ui::Layer; - -namespace ash { -namespace internal { - -class WindowAnimationsTest : public ash::test::AshTestBase { - public: - WindowAnimationsTest() {} - - virtual void TearDown() OVERRIDE { - AshTestBase::TearDown(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest); -}; - -// Listens to animation scheduled notifications. Remembers the transition -// duration of the first sequence. -class MinimizeAnimationObserver : public ui::LayerAnimationObserver { - public: - explicit MinimizeAnimationObserver(ui::LayerAnimator* animator) - : animator_(animator) { - animator_->AddObserver(this); - // RemoveObserver is called when the first animation is scheduled and so - // there should be no need for now to remove it in destructor. - }; - base::TimeDelta duration() { return duration_; } - - protected: - // ui::LayerAnimationObserver: - virtual void OnLayerAnimationScheduled( - ui::LayerAnimationSequence* sequence) OVERRIDE { - duration_ = animator_->GetTransitionDuration(); - animator_->RemoveObserver(this); - } - virtual void OnLayerAnimationEnded( - ui::LayerAnimationSequence* sequence) OVERRIDE {} - virtual void OnLayerAnimationAborted( - ui::LayerAnimationSequence* sequence) OVERRIDE {} - - private: - ui::LayerAnimator* animator_; - base::TimeDelta duration_; - - DISALLOW_COPY_AND_ASSIGN(MinimizeAnimationObserver); -}; - -TEST_F(WindowAnimationsTest, HideShowBrightnessGrayscaleAnimation) { - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0)); - window->Show(); - EXPECT_TRUE(window->layer()->visible()); - - // Hiding. - views::corewm::SetWindowVisibilityAnimationType( - window.get(), - WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE); - AnimateOnChildWindowVisibilityChanged(window.get(), false); - EXPECT_EQ(0.0f, window->layer()->GetTargetOpacity()); - EXPECT_FALSE(window->layer()->GetTargetVisibility()); - EXPECT_FALSE(window->layer()->visible()); - - // Showing. - views::corewm::SetWindowVisibilityAnimationType( - window.get(), - WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE); - AnimateOnChildWindowVisibilityChanged(window.get(), true); - EXPECT_EQ(0.0f, window->layer()->GetTargetBrightness()); - EXPECT_EQ(0.0f, window->layer()->GetTargetGrayscale()); - EXPECT_TRUE(window->layer()->visible()); - - // Stays shown. - gfx::AnimationContainerElement* element = - static_cast<gfx::AnimationContainerElement*>( - window->layer()->GetAnimator()); - element->Step(base::TimeTicks::Now() + - base::TimeDelta::FromSeconds(5)); - EXPECT_EQ(0.0f, window->layer()->GetTargetBrightness()); - EXPECT_EQ(0.0f, window->layer()->GetTargetGrayscale()); - EXPECT_TRUE(window->layer()->visible()); -} - -TEST_F(WindowAnimationsTest, LayerTargetVisibility) { - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0)); - - // Layer target visibility changes according to Show/Hide. - window->Show(); - EXPECT_TRUE(window->layer()->GetTargetVisibility()); - window->Hide(); - EXPECT_FALSE(window->layer()->GetTargetVisibility()); - window->Show(); - EXPECT_TRUE(window->layer()->GetTargetVisibility()); -} - -TEST_F(WindowAnimationsTest, CrossFadeToBounds) { - ui::ScopedAnimationDurationScaleMode normal_duration_mode( - ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); - - scoped_ptr<Window> window(CreateTestWindowInShellWithId(0)); - window->SetBounds(gfx::Rect(5, 10, 320, 240)); - window->Show(); - - Layer* old_layer = window->layer(); - EXPECT_EQ(1.0f, old_layer->GetTargetOpacity()); - - // Cross fade to a larger size, as in a maximize animation. - CrossFadeToBounds(window.get(), gfx::Rect(0, 0, 640, 480)); - // Window's layer has been replaced. - EXPECT_NE(old_layer, window->layer()); - // Original layer stays opaque and stretches to new size. - EXPECT_EQ(1.0f, old_layer->GetTargetOpacity()); - EXPECT_EQ("5,10 320x240", old_layer->bounds().ToString()); - gfx::Transform grow_transform; - grow_transform.Translate(-5.f, -10.f); - grow_transform.Scale(640.f / 320.f, 480.f / 240.f); - EXPECT_EQ(grow_transform, old_layer->GetTargetTransform()); - // New layer animates in to the identity transform. - EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity()); - EXPECT_EQ(gfx::Transform(), window->layer()->GetTargetTransform()); - - // Run the animations to completion. - static_cast<gfx::AnimationContainerElement*>(old_layer->GetAnimator())->Step( - base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1)); - static_cast<gfx::AnimationContainerElement*>(window->layer()->GetAnimator())-> - Step(base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1)); - - // Cross fade to a smaller size, as in a restore animation. - old_layer = window->layer(); - CrossFadeToBounds(window.get(), gfx::Rect(5, 10, 320, 240)); - // Again, window layer has been replaced. - EXPECT_NE(old_layer, window->layer()); - // Original layer fades out and stretches down to new size. - EXPECT_EQ(0.0f, old_layer->GetTargetOpacity()); - EXPECT_EQ("0,0 640x480", old_layer->bounds().ToString()); - gfx::Transform shrink_transform; - shrink_transform.Translate(5.f, 10.f); - shrink_transform.Scale(320.f / 640.f, 240.f / 480.f); - EXPECT_EQ(shrink_transform, old_layer->GetTargetTransform()); - // New layer animates in to the identity transform. - EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity()); - EXPECT_EQ(gfx::Transform(), window->layer()->GetTargetTransform()); - - static_cast<gfx::AnimationContainerElement*>(old_layer->GetAnimator())->Step( - base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1)); - static_cast<gfx::AnimationContainerElement*>(window->layer()->GetAnimator())-> - Step(base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1)); -} - -TEST_F(WindowAnimationsTest, LockAnimationDuration) { - ui::ScopedAnimationDurationScaleMode normal_duration_mode( - ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); - - scoped_ptr<Window> window(CreateTestWindowInShellWithId(0)); - Layer* layer = window->layer(); - window->SetBounds(gfx::Rect(5, 10, 320, 240)); - window->Show(); - - // Test that it is possible to override transition duration when it is not - // locked. - { - ui::ScopedLayerAnimationSettings settings1(layer->GetAnimator()); - settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000)); - { - ui::ScopedLayerAnimationSettings settings2(layer->GetAnimator()); - // Duration is not locked so it gets overridden. - settings2.SetTransitionDuration(base::TimeDelta::FromMilliseconds(50)); - wm::GetWindowState(window.get())->Minimize(); - EXPECT_TRUE(layer->GetAnimator()->is_animating()); - // Expect duration from the inner scope - EXPECT_EQ(50, - layer->GetAnimator()->GetTransitionDuration().InMilliseconds()); - } - window->Show(); - layer->GetAnimator()->StopAnimating(); - } - - // Test that it is possible to lock transition duration - { - ui::ScopedLayerAnimationSettings settings1(layer->GetAnimator()); - settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000)); - // Duration is locked in outer scope. - settings1.LockTransitionDuration(); - { - ui::ScopedLayerAnimationSettings settings2(layer->GetAnimator()); - // Transition duration setting is ignored. - settings2.SetTransitionDuration(base::TimeDelta::FromMilliseconds(50)); - wm::GetWindowState(window.get())->Minimize(); - EXPECT_TRUE(layer->GetAnimator()->is_animating()); - // Expect duration from the outer scope - EXPECT_EQ(1000, - layer->GetAnimator()->GetTransitionDuration().InMilliseconds()); - } - window->Show(); - layer->GetAnimator()->StopAnimating(); - } - - // Test that duration respects default. - { - // Query default duration. - MinimizeAnimationObserver observer(layer->GetAnimator()); - wm::GetWindowState(window.get())->Minimize(); - EXPECT_TRUE(layer->GetAnimator()->is_animating()); - base::TimeDelta default_duration(observer.duration()); - window->Show(); - layer->GetAnimator()->StopAnimating(); - - ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); - settings.LockTransitionDuration(); - // Setting transition duration is ignored since duration is locked - settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000)); - wm::GetWindowState(window.get())->Minimize(); - EXPECT_TRUE(layer->GetAnimator()->is_animating()); - // Expect default duration (200ms for stock ash minimizing animation). - EXPECT_EQ(default_duration.InMilliseconds(), - layer->GetAnimator()->GetTransitionDuration().InMilliseconds()); - window->Show(); - layer->GetAnimator()->StopAnimating(); - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/window_cycle_controller.cc b/chromium/ash/wm/window_cycle_controller.cc deleted file mode 100644 index 703080ff37b..00000000000 --- a/chromium/ash/wm/window_cycle_controller.cc +++ /dev/null @@ -1,139 +0,0 @@ -// 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/window_cycle_controller.h" - -#include <algorithm> - -#include "ash/session_state_delegate.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/mru_window_tracker.h" -#include "ash/wm/window_cycle_list.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace_controller.h" -#include "ui/aura/root_window.h" -#include "ui/events/event.h" -#include "ui/events/event_handler.h" - -namespace ash { - -namespace { - -// Filter to watch for the termination of a keyboard gesture to cycle through -// multiple windows. -class WindowCycleEventFilter : public ui::EventHandler { - public: - WindowCycleEventFilter(); - virtual ~WindowCycleEventFilter(); - - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - private: - DISALLOW_COPY_AND_ASSIGN(WindowCycleEventFilter); -}; - -// Watch for all keyboard events by filtering the root window. -WindowCycleEventFilter::WindowCycleEventFilter() { -} - -WindowCycleEventFilter::~WindowCycleEventFilter() { -} - -void WindowCycleEventFilter::OnKeyEvent(ui::KeyEvent* event) { - // Views uses VKEY_MENU for both left and right Alt keys. - if (event->key_code() == ui::VKEY_MENU && - event->type() == ui::ET_KEY_RELEASED) { - Shell::GetInstance()->window_cycle_controller()->AltKeyReleased(); - // Warning: |this| will be deleted from here on. - } -} - -} // namespace - -////////////////////////////////////////////////////////////////////////////// -// WindowCycleController, public: - -WindowCycleController::WindowCycleController() { -} - -WindowCycleController::~WindowCycleController() { - StopCycling(); -} - -// static -bool WindowCycleController::CanCycle() { - // Don't allow window cycling if the screen is locked or a modal dialog is - // open. - return !Shell::GetInstance()->session_state_delegate()->IsScreenLocked() && - !Shell::GetInstance()->IsSystemModalWindowOpen(); -} - -void WindowCycleController::HandleCycleWindow(Direction direction, - bool is_alt_down) { - if (!CanCycle()) - return; - - if (is_alt_down) { - if (!IsCycling()) { - // This is the start of an alt-tab cycle through multiple windows, so - // listen for the alt key being released to stop cycling. - StartCycling(); - Step(direction); - InstallEventFilter(); - } else { - // We're in the middle of an alt-tab cycle, just step forward. - Step(direction); - } - } else { - // This is a simple, single-step window cycle. - StartCycling(); - Step(direction); - StopCycling(); - } -} - -void WindowCycleController::HandleLinearCycleWindow() { - if (!CanCycle() || IsCycling()) - return; - - // Use the reversed list of windows to prevent a 2-cycle of the most recent - // windows occurring. - WindowCycleList cycle_list(MruWindowTracker::BuildWindowList(true)); - cycle_list.Step(WindowCycleList::FORWARD); -} - -void WindowCycleController::AltKeyReleased() { - StopCycling(); -} - -////////////////////////////////////////////////////////////////////////////// -// WindowCycleController, private: - -void WindowCycleController::StartCycling() { - windows_.reset(new WindowCycleList(ash::Shell::GetInstance()-> - mru_window_tracker()->BuildMruWindowList())); -} - -void WindowCycleController::Step(Direction direction) { - DCHECK(windows_.get()); - windows_->Step(direction == FORWARD ? WindowCycleList::FORWARD : - WindowCycleList::BACKWARD); -} - -void WindowCycleController::StopCycling() { - windows_.reset(); - // Remove our key event filter. - if (event_handler_) { - Shell::GetInstance()->RemovePreTargetHandler(event_handler_.get()); - event_handler_.reset(); - } -} - -void WindowCycleController::InstallEventFilter() { - event_handler_.reset(new WindowCycleEventFilter()); - Shell::GetInstance()->AddPreTargetHandler(event_handler_.get()); -} - -} // namespace ash diff --git a/chromium/ash/wm/window_cycle_controller.h b/chromium/ash/wm/window_cycle_controller.h deleted file mode 100644 index 12822c0e0fa..00000000000 --- a/chromium/ash/wm/window_cycle_controller.h +++ /dev/null @@ -1,82 +0,0 @@ -// 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_WINDOW_CYCLE_CONTROLLER_H_ -#define ASH_WM_WINDOW_CYCLE_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" - -namespace ui { -class EventHandler; -} - -namespace ash { - -class WindowCycleList; - -// Controls cycling through windows with the keyboard, for example, via alt-tab. -// Windows are sorted primarily by most recently used, and then by screen order. -// We activate windows as you cycle through them, so the order on the screen -// may change during the gesture, but the most recently used list isn't updated -// until the cycling ends. Thus we maintain the state of the windows -// at the beginning of the gesture so you can cycle through in a consistent -// order. -class ASH_EXPORT WindowCycleController { - public: - enum Direction { - FORWARD, - BACKWARD - }; - WindowCycleController(); - virtual ~WindowCycleController(); - - // Returns true if cycling through windows is enabled. This is false at - // certain times, such as when the lock screen is visible. - static bool CanCycle(); - - // Cycles between windows in the given |direction|. If |is_alt_down| then - // interprets this call as the start of a multi-step cycle sequence and - // installs a key filter to watch for alt being released. - void HandleCycleWindow(Direction direction, bool is_alt_down); - - // Cycles between windows without maintaining a multi-step cycle sequence - // (see above). - void HandleLinearCycleWindow(); - - // Informs the controller that the Alt key has been released and it can - // terminate the existing multi-step cycle. - void AltKeyReleased(); - - // Returns true if we are in the middle of a window cycling gesture. - bool IsCycling() const { return windows_.get() != NULL; } - - // Returns the WindowCycleList. Really only useful for testing. - const WindowCycleList* windows() const { return windows_.get(); } - - private: - // Call to start cycling windows. You must call StopCycling() when done. - void StartCycling(); - - // Cycles to the next or previous window based on |direction|. - void Step(Direction direction); - - // Installs an event filter to watch for release of the alt key. - void InstallEventFilter(); - - // Stops the current window cycle and cleans up the event filter. - void StopCycling(); - - scoped_ptr<WindowCycleList> windows_; - - // Event handler to watch for release of alt key. - scoped_ptr<ui::EventHandler> event_handler_; - - DISALLOW_COPY_AND_ASSIGN(WindowCycleController); -}; - -} // namespace ash - -#endif // ASH_WM_WINDOW_CYCLE_CONTROLLER_H_ diff --git a/chromium/ash/wm/window_cycle_controller_unittest.cc b/chromium/ash/wm/window_cycle_controller_unittest.cc deleted file mode 100644 index 67df90ef2f6..00000000000 --- a/chromium/ash/wm/window_cycle_controller_unittest.cc +++ /dev/null @@ -1,446 +0,0 @@ -// 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/window_cycle_controller.h" - -#include <algorithm> - -#include "ash/session_state_delegate.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/test_shell_delegate.h" -#include "ash/wm/window_cycle_list.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/screen.h" - -namespace ash { - -namespace { - -using aura::test::CreateTestWindowWithId; -using aura::test::TestWindowDelegate; -using aura::Window; - -typedef test::AshTestBase WindowCycleControllerTest; - -TEST_F(WindowCycleControllerTest, HandleCycleWindowBaseCases) { - WindowCycleController* controller = - Shell::GetInstance()->window_cycle_controller(); - - // Cycling doesn't crash if there are no windows. - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - - // Create a single test window. - scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); - wm::ActivateWindow(window0.get()); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - // Cycling works for a single window, even though nothing changes. - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); -} - -// Verifies if there is only one window and it isn't active that cycling -// activates it. -TEST_F(WindowCycleControllerTest, SingleWindowNotActive) { - WindowCycleController* controller = - Shell::GetInstance()->window_cycle_controller(); - - // Create a single test window. - scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); - wm::ActivateWindow(window0.get()); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - // Rotate focus, this should move focus to another window that isn't part of - // the default container. - Shell::GetInstance()->RotateFocus(Shell::FORWARD); - EXPECT_FALSE(wm::IsActiveWindow(window0.get())); - - // Cycling should activate the window. - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); -} - -TEST_F(WindowCycleControllerTest, HandleCycleWindow) { - WindowCycleController* controller = - Shell::GetInstance()->window_cycle_controller(); - - // Set up several windows to use to test cycling. Create them in reverse - // order so they are stacked 0 over 1 over 2. - scoped_ptr<Window> window2(CreateTestWindowInShellWithId(2)); - scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); - scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); - wm::ActivateWindow(window0.get()); - - // Simulate pressing and releasing Alt-tab. - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - - // Window lists should return the topmost window in front. - ASSERT_TRUE(controller->windows()); - ASSERT_EQ(3u, controller->windows()->windows().size()); - ASSERT_EQ(window0.get(), controller->windows()->windows()[0]); - ASSERT_EQ(window1.get(), controller->windows()->windows()[1]); - ASSERT_EQ(window2.get(), controller->windows()->windows()[2]); - - controller->AltKeyReleased(); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - // Pressing and releasing Alt-tab again should cycle back to the most- - // recently-used window in the current child order. - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - controller->AltKeyReleased(); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - // Pressing Alt-tab multiple times without releasing Alt should cycle through - // all the windows and wrap around. - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(controller->IsCycling()); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(controller->IsCycling()); - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(controller->IsCycling()); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - controller->AltKeyReleased(); - EXPECT_FALSE(controller->IsCycling()); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - // Reset our stacking order. - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); - wm::ActivateWindow(window0.get()); - - // Likewise we can cycle backwards through all the windows. - controller->HandleCycleWindow(WindowCycleController::BACKWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - controller->HandleCycleWindow(WindowCycleController::BACKWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - controller->HandleCycleWindow(WindowCycleController::BACKWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - controller->AltKeyReleased(); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - // Passing false for is_alt_down does not start a cycle gesture. - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_FALSE(controller->IsCycling()); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_FALSE(controller->IsCycling()); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - // When the screen is locked, cycling window does not take effect. - Shell::GetInstance()->session_state_delegate()->LockScreen(); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - controller->HandleCycleWindow(WindowCycleController::BACKWARD, false); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - Shell::GetInstance()->session_state_delegate()->UnlockScreen(); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - // When a modal window is active, cycling window does not take effect. - aura::Window* modal_container = - ash::Shell::GetContainer( - Shell::GetPrimaryRootWindow(), - internal::kShellWindowId_SystemModalContainer); - scoped_ptr<Window> modal_window( - CreateTestWindowWithId(-2, modal_container)); - modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM); - wm::ActivateWindow(modal_window.get()); - EXPECT_TRUE(wm::IsActiveWindow(modal_window.get())); - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_TRUE(wm::IsActiveWindow(modal_window.get())); - EXPECT_FALSE(wm::IsActiveWindow(window0.get())); - EXPECT_FALSE(wm::IsActiveWindow(window1.get())); - EXPECT_FALSE(wm::IsActiveWindow(window2.get())); - controller->HandleCycleWindow(WindowCycleController::BACKWARD, false); - EXPECT_TRUE(wm::IsActiveWindow(modal_window.get())); - EXPECT_FALSE(wm::IsActiveWindow(window0.get())); - EXPECT_FALSE(wm::IsActiveWindow(window1.get())); - EXPECT_FALSE(wm::IsActiveWindow(window2.get())); -} - -// Cycles between a maximized and normal window. -TEST_F(WindowCycleControllerTest, MaximizedWindow) { - // Create a couple of test windows. - scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); - scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); - wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - window1_state->Maximize(); - window1_state->Activate(); - EXPECT_TRUE(window1_state->IsActive()); - - // Rotate focus, this should move focus to window0. - WindowCycleController* controller = - Shell::GetInstance()->window_cycle_controller(); - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_TRUE(wm::GetWindowState(window0.get())->IsActive()); - - // One more time. - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_TRUE(window1_state->IsActive()); -} - -// Cycles to a minimized window. -TEST_F(WindowCycleControllerTest, Minimized) { - // Create a couple of test windows. - scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); - scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); - wm::WindowState* window0_state = wm::GetWindowState(window0.get()); - wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - - window1_state->Minimize(); - window0_state->Activate(); - EXPECT_TRUE(window0_state->IsActive()); - - // Rotate focus, this should move focus to window1 and unminimize it. - WindowCycleController* controller = - Shell::GetInstance()->window_cycle_controller(); - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_FALSE(window1_state->IsMinimized()); - EXPECT_TRUE(window1_state->IsActive()); - - // One more time back to w0. - controller->HandleCycleWindow(WindowCycleController::FORWARD, false); - EXPECT_TRUE(window0_state->IsActive()); -} - -TEST_F(WindowCycleControllerTest, AlwaysOnTopWindow) { - WindowCycleController* controller = - Shell::GetInstance()->window_cycle_controller(); - - // Set up several windows to use to test cycling. - scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); - scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); - - Window* top_container = - Shell::GetContainer( - Shell::GetPrimaryRootWindow(), - internal::kShellWindowId_AlwaysOnTopContainer); - scoped_ptr<Window> window2(CreateTestWindowWithId(2, top_container)); - wm::ActivateWindow(window0.get()); - - // Simulate pressing and releasing Alt-tab. - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - - // Window lists should return the topmost window in front. - ASSERT_TRUE(controller->windows()); - ASSERT_EQ(3u, controller->windows()->windows().size()); - EXPECT_EQ(window0.get(), controller->windows()->windows()[0]); - EXPECT_EQ(window2.get(), controller->windows()->windows()[1]); - EXPECT_EQ(window1.get(), controller->windows()->windows()[2]); - - controller->AltKeyReleased(); - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - controller->AltKeyReleased(); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); -} - -TEST_F(WindowCycleControllerTest, AlwaysOnTopMultiWindow) { - WindowCycleController* controller = - Shell::GetInstance()->window_cycle_controller(); - - // Set up several windows to use to test cycling. - scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); - scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); - - Window* top_container = - Shell::GetContainer( - Shell::GetPrimaryRootWindow(), - internal::kShellWindowId_AlwaysOnTopContainer); - scoped_ptr<Window> window2(CreateTestWindowWithId(2, top_container)); - scoped_ptr<Window> window3(CreateTestWindowWithId(3, top_container)); - wm::ActivateWindow(window0.get()); - - // Simulate pressing and releasing Alt-tab. - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - - // Window lists should return the topmost window in front. - ASSERT_TRUE(controller->windows()); - ASSERT_EQ(4u, controller->windows()->windows().size()); - EXPECT_EQ(window0.get(), controller->windows()->windows()[0]); - EXPECT_EQ(window3.get(), controller->windows()->windows()[1]); - EXPECT_EQ(window2.get(), controller->windows()->windows()[2]); - EXPECT_EQ(window1.get(), controller->windows()->windows()[3]); - - controller->AltKeyReleased(); - EXPECT_TRUE(wm::IsActiveWindow(window3.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - controller->AltKeyReleased(); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window3.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); -} - -TEST_F(WindowCycleControllerTest, AlwaysOnTopMultipleRootWindows) { - if (!SupportsMultipleDisplays()) - return; - - // Set up a second root window - UpdateDisplay("1000x600,600x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - ASSERT_EQ(2U, root_windows.size()); - - WindowCycleController* controller = - Shell::GetInstance()->window_cycle_controller(); - - Shell::GetInstance()->set_target_root_window(root_windows[0]); - - // Create two windows in the primary root. - scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); - EXPECT_EQ(root_windows[0], window0->GetRootWindow()); - Window* top_container0 = - Shell::GetContainer( - root_windows[0], - internal::kShellWindowId_AlwaysOnTopContainer); - scoped_ptr<Window> window1(CreateTestWindowWithId(1, top_container0)); - EXPECT_EQ(root_windows[0], window1->GetRootWindow()); - - // And two on the secondary root. - Shell::GetInstance()->set_target_root_window(root_windows[1]); - scoped_ptr<Window> window2(CreateTestWindowInShellWithId(2)); - EXPECT_EQ(root_windows[1], window2->GetRootWindow()); - - Window* top_container1 = - Shell::GetContainer( - root_windows[1], - internal::kShellWindowId_AlwaysOnTopContainer); - scoped_ptr<Window> window3(CreateTestWindowWithId(3, top_container1)); - EXPECT_EQ(root_windows[1], window3->GetRootWindow()); - - // Move the active root window to the secondary. - Shell::GetInstance()->set_target_root_window(root_windows[1]); - - wm::ActivateWindow(window2.get()); - - EXPECT_EQ(root_windows[0], window0->GetRootWindow()); - EXPECT_EQ(root_windows[0], window1->GetRootWindow()); - EXPECT_EQ(root_windows[1], window2->GetRootWindow()); - EXPECT_EQ(root_windows[1], window3->GetRootWindow()); - - // Simulate pressing and releasing Alt-tab. - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - - // Window lists should return the topmost window in front. - ASSERT_TRUE(controller->windows()); - ASSERT_EQ(4u, controller->windows()->windows().size()); - EXPECT_EQ(window2.get(), controller->windows()->windows()[0]); - EXPECT_EQ(window3.get(), controller->windows()->windows()[1]); - EXPECT_EQ(window1.get(), controller->windows()->windows()[2]); - EXPECT_EQ(window0.get(), controller->windows()->windows()[3]); - - controller->AltKeyReleased(); - EXPECT_TRUE(wm::IsActiveWindow(window3.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - - controller->AltKeyReleased(); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window3.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); -} - -TEST_F(WindowCycleControllerTest, MostRecentlyUsed) { - WindowCycleController* controller = - Shell::GetInstance()->window_cycle_controller(); - - // Set up several windows to use to test cycling. - scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); - scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); - scoped_ptr<Window> window2(CreateTestWindowInShellWithId(2)); - - wm::ActivateWindow(window0.get()); - - // Simulate pressing and releasing Alt-tab. - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - - // Window lists should return the topmost window in front. - ASSERT_TRUE(controller->windows()); - ASSERT_EQ(3u, controller->windows()->windows().size()); - EXPECT_EQ(window0.get(), controller->windows()->windows()[0]); - EXPECT_EQ(window2.get(), controller->windows()->windows()[1]); - EXPECT_EQ(window1.get(), controller->windows()->windows()[2]); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - controller->AltKeyReleased(); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); - - controller->AltKeyReleased(); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window2.get())); - - controller->HandleCycleWindow(WindowCycleController::FORWARD, true); - EXPECT_TRUE(wm::IsActiveWindow(window0.get())); -} - -} // namespace - -} // namespace ash diff --git a/chromium/ash/wm/window_cycle_list.cc b/chromium/ash/wm/window_cycle_list.cc deleted file mode 100644 index d6bf24a59cc..00000000000 --- a/chromium/ash/wm/window_cycle_list.cc +++ /dev/null @@ -1,85 +0,0 @@ -// 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/window_cycle_list.h" - -#include "ash/shell.h" -#include "ash/wm/mru_window_tracker.h" -#include "ash/wm/window_util.h" -#include "ui/aura/window.h" -#include "ui/views/corewm/window_animations.h" - -namespace ash { - -WindowCycleList::WindowCycleList(const WindowList& windows) - : windows_(windows), - current_index_(-1) { - ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(true); - // Locate the currently active window in the list to use as our start point. - aura::Window* active_window = wm::GetActiveWindow(); - - // The active window may not be in the cycle list, which is expected if there - // are additional modal windows on the screen. - current_index_ = GetWindowIndex(active_window); - - for (WindowList::const_iterator i = windows_.begin(); i != windows_.end(); - ++i) { - (*i)->AddObserver(this); - } -} - -WindowCycleList::~WindowCycleList() { - ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(false); - for (WindowList::const_iterator i = windows_.begin(); i != windows_.end(); - ++i) { - (*i)->RemoveObserver(this); - } -} - -void WindowCycleList::Step(Direction direction) { - if (windows_.empty()) - return; - - if (current_index_ == -1) { - // We weren't able to find our active window in the shell delegate's - // provided window list. Just switch to the first (or last) one. - current_index_ = (direction == FORWARD ? 0 : windows_.size() - 1); - } else { - // When there is only one window, we should give a feedback to user. - if (windows_.size() == 1) { - AnimateWindow(windows_[0], - views::corewm::WINDOW_ANIMATION_TYPE_BOUNCE); - return; - } - // We're in a valid cycle, so step forward or backward. - current_index_ += (direction == FORWARD ? 1 : -1); - } - // Wrap to window list size. - current_index_ = (current_index_ + windows_.size()) % windows_.size(); - DCHECK(windows_[current_index_]); - // Make sure the next window is visible. - windows_[current_index_]->Show(); - wm::ActivateWindow(windows_[current_index_]); -} - -int WindowCycleList::GetWindowIndex(aura::Window* window) { - WindowList::const_iterator it = - std::find(windows_.begin(), windows_.end(), window); - if (it == windows_.end()) - return -1; // Not found. - return it - windows_.begin(); -} - -void WindowCycleList::OnWindowDestroyed(aura::Window* window) { - WindowList::iterator i = std::find(windows_.begin(), windows_.end(), window); - DCHECK(i != windows_.end()); - int removed_index = static_cast<int>(i - windows_.begin()); - windows_.erase(i); - if (current_index_ > removed_index) - current_index_--; - else if (current_index_ == static_cast<int>(windows_.size())) - current_index_--; -} - -} // namespace ash diff --git a/chromium/ash/wm/window_cycle_list.h b/chromium/ash/wm/window_cycle_list.h deleted file mode 100644 index 6e0c75928c2..00000000000 --- a/chromium/ash/wm/window_cycle_list.h +++ /dev/null @@ -1,59 +0,0 @@ -// 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_WINDOW_CYCLE_LIST_H_ -#define ASH_WM_WINDOW_CYCLE_LIST_H_ - -#include <vector> - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/aura/window_observer.h" - -namespace ash { - -// Tracks a set of Windows that can be stepped through. This class is used by -// the WindowCycleController. -class ASH_EXPORT WindowCycleList : public aura::WindowObserver { - public: - typedef std::vector<aura::Window*> WindowList; - - enum Direction { - FORWARD, - BACKWARD - }; - - explicit WindowCycleList(const WindowList& windows); - virtual ~WindowCycleList(); - - bool empty() const { return windows_.empty(); } - - // Cycles to the next or previous window based on |direction|. - void Step(Direction direction); - - const WindowList& windows() const { return windows_; } - - private: - // Returns the index of |window| in |windows_| or -1 if it isn't there. - int GetWindowIndex(aura::Window* window); - - // aura::WindowObserver overrides: - virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; - - // List of weak pointers to windows to use while cycling with the keyboard. - // List is built when the user initiates the gesture (e.g. hits alt-tab the - // first time) and is emptied when the gesture is complete (e.g. releases the - // alt key). - WindowList windows_; - - // Current position in the |windows_| list or -1 if we're not cycling. - int current_index_; - - DISALLOW_COPY_AND_ASSIGN(WindowCycleList); -}; - -} // namespace ash - -#endif // ASH_WM_WINDOW_CYCLE_LIST_H_ diff --git a/chromium/ash/wm/window_manager_unittest.cc b/chromium/ash/wm/window_manager_unittest.cc deleted file mode 100644 index 2b97e5259e0..00000000000 --- a/chromium/ash/wm/window_manager_unittest.cc +++ /dev/null @@ -1,815 +0,0 @@ -// 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/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/shell_test_api.h" -#include "ash/test/test_activation_delegate.h" -#include "ash/wm/window_util.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/activation_delegate.h" -#include "ui/aura/client/cursor_client_observer.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_event_handler.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/test/test_windows.h" -#include "ui/base/cursor/cursor.h" -#include "ui/base/hit_test.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" -#include "ui/gfx/screen.h" -#include "ui/views/corewm/compound_event_filter.h" -#include "ui/views/corewm/corewm_switches.h" -#include "ui/views/corewm/input_method_event_filter.h" - -namespace { - -class TestingCursorClientObserver : public aura::client::CursorClientObserver { - public: - TestingCursorClientObserver() - : cursor_visibility_(false), - did_visibility_change_(false) {} - void reset() { cursor_visibility_ = did_visibility_change_ = false; } - bool is_cursor_visible() const { return cursor_visibility_; } - bool did_visibility_change() const { return did_visibility_change_; } - - // Overridden from aura::client::CursorClientObserver: - virtual void OnCursorVisibilityChanged(bool is_visible) OVERRIDE { - cursor_visibility_ = is_visible; - did_visibility_change_ = true; - } - - private: - bool cursor_visibility_; - bool did_visibility_change_; - - DISALLOW_COPY_AND_ASSIGN(TestingCursorClientObserver); -}; - -base::TimeDelta getTime() { - return ui::EventTimeForNow(); -} - -// A slightly changed TestEventHandler which can be configured to return a -// specified value for key/mouse event handling. -class CustomEventHandler : public aura::test::TestEventHandler { - public: - CustomEventHandler() - : key_result_(ui::ER_UNHANDLED), - mouse_result_(ui::ER_UNHANDLED) { - } - - virtual ~CustomEventHandler() {} - - void set_key_event_handling_result(ui::EventResult result) { - key_result_ = result; - } - - void set_mouse_event_handling_result(ui::EventResult result) { - mouse_result_ = result; - } - - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE { - aura::test::TestEventHandler::OnKeyEvent(event); - if (key_result_ & ui::ER_HANDLED) - event->SetHandled(); - if (key_result_ & ui::ER_CONSUMED) - event->StopPropagation(); - } - - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { - aura::test::TestEventHandler::OnMouseEvent(event); - if (mouse_result_ & ui::ER_HANDLED) - event->SetHandled(); - if (mouse_result_ & ui::ER_CONSUMED) - event->StopPropagation(); - } - - private: - ui::EventResult key_result_; - ui::EventResult mouse_result_; - - DISALLOW_COPY_AND_ASSIGN(CustomEventHandler); -}; - -} // namespace - -namespace ash { - -typedef test::AshTestBase WindowManagerTest; - -class NonFocusableDelegate : public aura::test::TestWindowDelegate { - public: - NonFocusableDelegate() {} - - private: - virtual bool CanFocus() OVERRIDE { - return false; - } - - DISALLOW_COPY_AND_ASSIGN(NonFocusableDelegate); -}; - -class HitTestWindowDelegate : public aura::test::TestWindowDelegate { - public: - HitTestWindowDelegate() - : hittest_code_(HTNOWHERE) { - } - virtual ~HitTestWindowDelegate() {} - void set_hittest_code(int hittest_code) { hittest_code_ = hittest_code; } - - private: - // Overridden from TestWindowDelegate: - virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE { - return hittest_code_; - } - - int hittest_code_; - - DISALLOW_COPY_AND_ASSIGN(HitTestWindowDelegate); -}; - -TEST_F(WindowManagerTest, Focus) { - // The IME event filter interferes with the basic key event propagation we - // attempt to do here, so we remove it. - test::ShellTestApi shell_test(Shell::GetInstance()); - Shell::GetInstance()->RemovePreTargetHandler( - shell_test.input_method_event_filter()); - - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - root_window->SetBounds(gfx::Rect(0, 0, 510, 510)); - - // Supplied ids are negative so as not to collide with shell ids. - // TODO(beng): maybe introduce a MAKE_SHELL_ID() macro that generates a safe - // id beyond shell id max? - scoped_ptr<aura::Window> w1(CreateTestWindowInShell( - SK_ColorWHITE, -1, gfx::Rect(10, 10, 500, 500))); - scoped_ptr<aura::Window> w11(aura::test::CreateTestWindow( - SK_ColorGREEN, -11, gfx::Rect(5, 5, 100, 100), w1.get())); - scoped_ptr<aura::Window> w111(aura::test::CreateTestWindow( - SK_ColorCYAN, -111, gfx::Rect(5, 5, 75, 75), w11.get())); - scoped_ptr<aura::Window> w1111(aura::test::CreateTestWindow( - SK_ColorRED, -1111, gfx::Rect(5, 5, 50, 50), w111.get())); - scoped_ptr<aura::Window> w12(aura::test::CreateTestWindow( - SK_ColorMAGENTA, -12, gfx::Rect(10, 420, 25, 25), w1.get())); - aura::test::ColorTestWindowDelegate* w121delegate = - new aura::test::ColorTestWindowDelegate(SK_ColorYELLOW); - scoped_ptr<aura::Window> w121(aura::test::CreateTestWindowWithDelegate( - w121delegate, -121, gfx::Rect(5, 5, 5, 5), w12.get())); - aura::test::ColorTestWindowDelegate* w122delegate = - new aura::test::ColorTestWindowDelegate(SK_ColorRED); - scoped_ptr<aura::Window> w122(aura::test::CreateTestWindowWithDelegate( - w122delegate, -122, gfx::Rect(10, 5, 5, 5), w12.get())); - aura::test::ColorTestWindowDelegate* w123delegate = - new aura::test::ColorTestWindowDelegate(SK_ColorRED); - scoped_ptr<aura::Window> w123(aura::test::CreateTestWindowWithDelegate( - w123delegate, -123, gfx::Rect(15, 5, 5, 5), w12.get())); - scoped_ptr<aura::Window> w13(aura::test::CreateTestWindow( - SK_ColorGRAY, -13, gfx::Rect(5, 470, 50, 50), w1.get())); - - // Click on a sub-window (w121) to focus it. - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - w121.get()); - generator.ClickLeftButton(); - - aura::client::FocusClient* focus_client = - aura::client::GetFocusClient(w121.get()); - EXPECT_EQ(w121.get(), focus_client->GetFocusedWindow()); - - aura::WindowEventDispatcher* dispatcher = root_window->GetDispatcher(); - - // The key press should be sent to the focused sub-window. - ui::KeyEvent keyev(ui::ET_KEY_PRESSED, ui::VKEY_E, 0, false); - dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&keyev); - EXPECT_EQ(ui::VKEY_E, w121delegate->last_key_code()); - - // Touch on a sub-window (w122) to focus it. - gfx::Point click_point = w122->bounds().CenterPoint(); - aura::Window::ConvertPointToTarget(w122->parent(), root_window, &click_point); - ui::TouchEvent touchev(ui::ET_TOUCH_PRESSED, click_point, 0, getTime()); - dispatcher->AsRootWindowHostDelegate()->OnHostTouchEvent(&touchev); - focus_client = aura::client::GetFocusClient(w122.get()); - EXPECT_EQ(w122.get(), focus_client->GetFocusedWindow()); - - // The key press should be sent to the focused sub-window. - dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&keyev); - EXPECT_EQ(ui::VKEY_E, w122delegate->last_key_code()); - - // Hiding the focused window will set the focus to its parent if - // it's focusable. - w122->Hide(); - EXPECT_EQ(aura::client::GetFocusClient(w12.get()), - aura::client::GetFocusClient(w122.get())); - EXPECT_EQ(w12.get(), - aura::client::GetFocusClient(w12.get())->GetFocusedWindow()); - - // Sets the focus back to w122. - w122->Show(); - w122->Focus(); - EXPECT_EQ(w122.get(), - aura::client::GetFocusClient(w12.get())->GetFocusedWindow()); - - // Removing the focused window from parent should set the focus to - // its parent if it's focusable. - w12->RemoveChild(w122.get()); - EXPECT_EQ(NULL, aura::client::GetFocusClient(w122.get())); - EXPECT_EQ(w12.get(), - aura::client::GetFocusClient(w12.get())->GetFocusedWindow()); - - // Set the focus to w123, but make the w1 not activatable. - test::TestActivationDelegate activation_delegate(false); - w123->Focus(); - EXPECT_EQ(w123.get(), - aura::client::GetFocusClient(w12.get())->GetFocusedWindow()); - aura::client::SetActivationDelegate(w1.get(), &activation_delegate); - - // Hiding the focused window will set the focus to NULL because - // parent window is not focusable. - w123->Hide(); - EXPECT_EQ(aura::client::GetFocusClient(w12.get()), - aura::client::GetFocusClient(w123.get())); - EXPECT_EQ(NULL, aura::client::GetFocusClient(w12.get())->GetFocusedWindow()); - EXPECT_FALSE(dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&keyev)); - - // Set the focus back to w123 - aura::client::SetActivationDelegate(w1.get(), NULL); - w123->Show(); - w123->Focus(); - EXPECT_EQ(w123.get(), - aura::client::GetFocusClient(w12.get())->GetFocusedWindow()); - aura::client::SetActivationDelegate(w1.get(), &activation_delegate); - - // Removing the focused window will set the focus to NULL because - // parent window is not focusable. - w12->RemoveChild(w123.get()); - EXPECT_EQ(NULL, aura::client::GetFocusClient(w123.get())); - EXPECT_FALSE(dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&keyev)); -} - -// Various assertion testing for activating windows. -TEST_F(WindowManagerTest, ActivateOnMouse) { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - - test::TestActivationDelegate d1; - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate( - &wd, -1, gfx::Rect(10, 10, 50, 50))); - d1.SetWindow(w1.get()); - test::TestActivationDelegate d2; - scoped_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( - &wd, -2, gfx::Rect(70, 70, 50, 50))); - d2.SetWindow(w2.get()); - - aura::client::FocusClient* focus_client = - aura::client::GetFocusClient(w1.get()); - - d1.Clear(); - d2.Clear(); - - // Activate window1. - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - EXPECT_EQ(w1.get(), focus_client->GetFocusedWindow()); - EXPECT_EQ(1, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); - d1.Clear(); - - { - // Click on window2. - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - w2.get()); - generator.ClickLeftButton(); - - // Window2 should have become active. - EXPECT_TRUE(wm::IsActiveWindow(w2.get())); - EXPECT_EQ(w2.get(), focus_client->GetFocusedWindow()); - EXPECT_EQ(0, d1.activated_count()); - EXPECT_EQ(1, d1.lost_active_count()); - EXPECT_EQ(1, d2.activated_count()); - EXPECT_EQ(0, d2.lost_active_count()); - d1.Clear(); - d2.Clear(); - } - - { - // Click back on window1, but set it up so w1 doesn't activate on click. - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - w1.get()); - d1.set_activate(false); - generator.ClickLeftButton(); - - // Window2 should still be active and focused. - EXPECT_TRUE(wm::IsActiveWindow(w2.get())); - EXPECT_EQ(w2.get(), focus_client->GetFocusedWindow()); - EXPECT_EQ(0, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); - EXPECT_EQ(0, d2.activated_count()); - EXPECT_EQ(0, d2.lost_active_count()); - d1.Clear(); - d2.Clear(); - } - - // Destroy window2, this should make window1 active. - d1.set_activate(true); - w2.reset(); - EXPECT_EQ(0, d2.activated_count()); - EXPECT_EQ(1, d2.lost_active_count()); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - EXPECT_EQ(w1.get(), focus_client->GetFocusedWindow()); - EXPECT_EQ(1, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); - - // Clicking an active window with a child shouldn't steal the - // focus from the child. - { - scoped_ptr<aura::Window> w11(CreateTestWindowWithDelegate( - &wd, -11, gfx::Rect(10, 10, 10, 10), w1.get())); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - w11.get()); - // First set the focus to the child |w11|. - generator.ClickLeftButton(); - EXPECT_EQ(w11.get(), focus_client->GetFocusedWindow()); - EXPECT_EQ(w1.get(), wm::GetActiveWindow()); - - // Then click the parent active window. The focus shouldn't move. - gfx::Point left_top = w1->bounds().origin(); - aura::Window::ConvertPointToTarget(w1->parent(), root_window, &left_top); - left_top.Offset(1, 1); - generator.MoveMouseTo(left_top); - generator.ClickLeftButton(); - EXPECT_EQ(w11.get(), focus_client->GetFocusedWindow()); - EXPECT_EQ(w1.get(), wm::GetActiveWindow()); - } - - // Clicking on a non-focusable window inside a background window should still - // give focus to the background window. - { - NonFocusableDelegate nfd; - scoped_ptr<aura::Window> w11(CreateTestWindowWithDelegate( - &nfd, -1, gfx::Rect(10, 10, 10, 10), w1.get())); - // Move focus to |w2| first. - scoped_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( - &wd, -1, gfx::Rect(70, 70, 50, 50))); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - w2.get()); - generator.ClickLeftButton(); - EXPECT_EQ(w2.get(), focus_client->GetFocusedWindow()); - EXPECT_FALSE(w11->CanFocus()); - - // Click on |w11|. This should focus w1. - generator.MoveMouseToCenterOf(w11.get()); - generator.ClickLeftButton(); - EXPECT_EQ(w1.get(), focus_client->GetFocusedWindow()); - } -} - -TEST_F(WindowManagerTest, PanelActivation) { - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate( - &wd, -1, gfx::Rect(10, 10, 50, 50))); - aura::test::TestWindowDelegate pd; - scoped_ptr<aura::Window> p1(CreateTestWindowInShellWithDelegateAndType( - &pd, aura::client::WINDOW_TYPE_PANEL, -1, gfx::Rect(10, 10, 50, 50))); - aura::client::FocusClient* focus_client = - aura::client::GetFocusClient(w1.get()); - - // Activate w1. - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - - // Activate p1. - wm::ActivateWindow(p1.get()); - EXPECT_TRUE(wm::IsActiveWindow(p1.get())); - EXPECT_EQ(p1.get(), focus_client->GetFocusedWindow()); - - // Activate w1. - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - EXPECT_EQ(w1.get(), focus_client->GetFocusedWindow()); - - // Clicking on a non-activatable window should not change the active window. - { - NonFocusableDelegate nfd; - scoped_ptr<aura::Window> w3(CreateTestWindowInShellWithDelegate( - &nfd, -1, gfx::Rect(70, 70, 50, 50))); - aura::test::EventGenerator generator3(Shell::GetPrimaryRootWindow(), - w3.get()); - wm::ActivateWindow(p1.get()); - EXPECT_TRUE(wm::IsActiveWindow(p1.get())); - generator3.ClickLeftButton(); - EXPECT_TRUE(wm::IsActiveWindow(p1.get())); - } -} - -// Essentially the same as ActivateOnMouse, but for touch events. -TEST_F(WindowManagerTest, ActivateOnTouch) { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - - test::TestActivationDelegate d1; - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate( - &wd, -1, gfx::Rect(10, 10, 50, 50))); - d1.SetWindow(w1.get()); - test::TestActivationDelegate d2; - scoped_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( - &wd, -2, gfx::Rect(70, 70, 50, 50))); - d2.SetWindow(w2.get()); - - aura::client::FocusClient* focus_client = - aura::client::GetFocusClient(w1.get()); - - d1.Clear(); - d2.Clear(); - - // Activate window1. - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - EXPECT_EQ(w1.get(), focus_client->GetFocusedWindow()); - EXPECT_EQ(1, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); - d1.Clear(); - - // Touch window2. - gfx::Point press_point = w2->bounds().CenterPoint(); - aura::Window::ConvertPointToTarget(w2->parent(), root_window, &press_point); - ui::TouchEvent touchev1(ui::ET_TOUCH_PRESSED, press_point, 0, getTime()); - - aura::WindowEventDispatcher* dispatcher = root_window->GetDispatcher(); - dispatcher->AsRootWindowHostDelegate()->OnHostTouchEvent(&touchev1); - - // Window2 should have become active. - EXPECT_TRUE(wm::IsActiveWindow(w2.get())); - EXPECT_EQ(w2.get(), focus_client->GetFocusedWindow()); - EXPECT_EQ(0, d1.activated_count()); - EXPECT_EQ(1, d1.lost_active_count()); - EXPECT_EQ(1, d2.activated_count()); - EXPECT_EQ(0, d2.lost_active_count()); - d1.Clear(); - d2.Clear(); - - // Touch window1, but set it up so w1 doesn't activate on touch. - press_point = w1->bounds().CenterPoint(); - aura::Window::ConvertPointToTarget(w1->parent(), root_window, &press_point); - d1.set_activate(false); - ui::TouchEvent touchev2(ui::ET_TOUCH_PRESSED, press_point, 1, getTime()); - dispatcher->AsRootWindowHostDelegate()->OnHostTouchEvent(&touchev2); - - // Window2 should still be active and focused. - EXPECT_TRUE(wm::IsActiveWindow(w2.get())); - EXPECT_EQ(w2.get(), focus_client->GetFocusedWindow()); - EXPECT_EQ(0, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); - EXPECT_EQ(0, d2.activated_count()); - EXPECT_EQ(0, d2.lost_active_count()); - d1.Clear(); - d2.Clear(); - - // Destroy window2, this should make window1 active. - d1.set_activate(true); - w2.reset(); - EXPECT_EQ(0, d2.activated_count()); - EXPECT_EQ(1, d2.lost_active_count()); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - EXPECT_EQ(w1.get(), focus_client->GetFocusedWindow()); - EXPECT_EQ(1, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); -} - -TEST_F(WindowManagerTest, MouseEventCursors) { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - - // Create a window. - const int kWindowLeft = 123; - const int kWindowTop = 45; - HitTestWindowDelegate window_delegate; - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate( - &window_delegate, - -1, - gfx::Rect(kWindowLeft, kWindowTop, 640, 480))); - - // Create two mouse movement events we can switch between. - gfx::Point point1(kWindowLeft, kWindowTop); - aura::Window::ConvertPointToTarget(window->parent(), root_window, &point1); - - gfx::Point point2(kWindowLeft + 1, kWindowTop + 1); - aura::Window::ConvertPointToTarget(window->parent(), root_window, &point2); - - aura::WindowEventDispatcher* dispatcher = root_window->GetDispatcher(); - - // Cursor starts as a pointer (set during Shell::Init()). - EXPECT_EQ(ui::kCursorPointer, dispatcher->last_cursor().native_type()); - - { - // Resize edges and corners show proper cursors. - window_delegate.set_hittest_code(HTBOTTOM); - ui::MouseEvent move1(ui::ET_MOUSE_MOVED, point1, point1, 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&move1); - EXPECT_EQ(ui::kCursorSouthResize, dispatcher->last_cursor().native_type()); - } - - { - window_delegate.set_hittest_code(HTBOTTOMLEFT); - ui::MouseEvent move2(ui::ET_MOUSE_MOVED, point2, point2, 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&move2); - EXPECT_EQ(ui::kCursorSouthWestResize, - dispatcher->last_cursor().native_type()); - } - - { - window_delegate.set_hittest_code(HTBOTTOMRIGHT); - ui::MouseEvent move1(ui::ET_MOUSE_MOVED, point1, point1, 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&move1); - EXPECT_EQ(ui::kCursorSouthEastResize, - dispatcher->last_cursor().native_type()); - } - - { - window_delegate.set_hittest_code(HTLEFT); - ui::MouseEvent move2(ui::ET_MOUSE_MOVED, point2, point2, 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&move2); - EXPECT_EQ(ui::kCursorWestResize, dispatcher->last_cursor().native_type()); - } - - { - window_delegate.set_hittest_code(HTRIGHT); - ui::MouseEvent move1(ui::ET_MOUSE_MOVED, point1, point1, 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&move1); - EXPECT_EQ(ui::kCursorEastResize, dispatcher->last_cursor().native_type()); - } - - { - window_delegate.set_hittest_code(HTTOP); - ui::MouseEvent move2(ui::ET_MOUSE_MOVED, point2, point2, 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&move2); - EXPECT_EQ(ui::kCursorNorthResize, dispatcher->last_cursor().native_type()); - } - - { - window_delegate.set_hittest_code(HTTOPLEFT); - ui::MouseEvent move1(ui::ET_MOUSE_MOVED, point1, point1, 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&move1); - EXPECT_EQ(ui::kCursorNorthWestResize, - dispatcher->last_cursor().native_type()); - } - - { - window_delegate.set_hittest_code(HTTOPRIGHT); - ui::MouseEvent move2(ui::ET_MOUSE_MOVED, point2, point2, 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&move2); - EXPECT_EQ(ui::kCursorNorthEastResize, - dispatcher->last_cursor().native_type()); - } - - { - // Client area uses null cursor. - window_delegate.set_hittest_code(HTCLIENT); - ui::MouseEvent move1(ui::ET_MOUSE_MOVED, point1, point1, 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&move1); - EXPECT_EQ(ui::kCursorNull, dispatcher->last_cursor().native_type()); - } -} - -#if defined(OS_WIN) -#define MAYBE_TransformActivate DISABLED_TransformActivate -#else -#define MAYBE_TransformActivate TransformActivate -#endif -TEST_F(WindowManagerTest, MAYBE_TransformActivate) { - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - gfx::Size size = root_window->bounds().size(); - EXPECT_EQ(gfx::Rect(size).ToString(), - Shell::GetScreen()->GetDisplayNearestPoint( - gfx::Point()).bounds().ToString()); - - // Rotate it clock-wise 90 degrees. - gfx::Transform transform; - transform.Translate(size.width(), 0); - transform.Rotate(90.0f); - root_window->GetDispatcher()->SetTransform(transform); - - test::TestActivationDelegate d1; - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> w1( - CreateTestWindowInShellWithDelegate(&wd, 1, gfx::Rect(0, 10, 50, 50))); - d1.SetWindow(w1.get()); - w1->Show(); - - gfx::Point miss_point(5, 5); - transform.TransformPoint(&miss_point); - ui::MouseEvent mouseev1(ui::ET_MOUSE_PRESSED, - miss_point, - miss_point, - ui::EF_LEFT_MOUSE_BUTTON); - aura::WindowEventDispatcher* dispatcher = root_window->GetDispatcher(); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouseev1); - EXPECT_EQ(NULL, aura::client::GetFocusClient(w1.get())->GetFocusedWindow()); - ui::MouseEvent mouseup(ui::ET_MOUSE_RELEASED, - miss_point, - miss_point, - ui::EF_LEFT_MOUSE_BUTTON); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouseup); - - gfx::Point hit_point(5, 15); - transform.TransformPoint(&hit_point); - ui::MouseEvent mouseev2(ui::ET_MOUSE_PRESSED, - hit_point, - hit_point, - ui::EF_LEFT_MOUSE_BUTTON); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouseev2); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - EXPECT_EQ(w1.get(), - aura::client::GetFocusClient(w1.get())->GetFocusedWindow()); -} - -TEST_F(WindowManagerTest, AdditionalFilters) { - // The IME event filter interferes with the basic key event propagation we - // attempt to do here, so we remove it. - test::ShellTestApi shell_test(Shell::GetInstance()); - Shell::GetInstance()->RemovePreTargetHandler( - shell_test.input_method_event_filter()); - - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - - // Creates a window and make it active - scoped_ptr<aura::Window> w1(CreateTestWindowInShell( - SK_ColorWHITE, -1, gfx::Rect(0, 0, 100, 100))); - wm::ActivateWindow(w1.get()); - - // Creates two addition filters - scoped_ptr<CustomEventHandler> f1(new CustomEventHandler); - scoped_ptr<CustomEventHandler> f2(new CustomEventHandler); - - // Adds them to root window event filter. - views::corewm::CompoundEventFilter* env_filter = - Shell::GetInstance()->env_filter(); - env_filter->AddHandler(f1.get()); - env_filter->AddHandler(f2.get()); - - // Dispatches mouse and keyboard events. - ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, false); - aura::WindowEventDispatcher* dispatcher = root_window->GetDispatcher(); - dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&key_event); - ui::MouseEvent mouse_pressed( - ui::ET_MOUSE_PRESSED, gfx::Point(0, 0), gfx::Point(0, 0), 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse_pressed); - - // Both filters should get the events. - EXPECT_EQ(1, f1->num_key_events()); - EXPECT_EQ(1, f1->num_mouse_events()); - EXPECT_EQ(1, f2->num_key_events()); - EXPECT_EQ(1, f2->num_mouse_events()); - - f1->Reset(); - f2->Reset(); - - // Makes f1 consume events. - f1->set_key_event_handling_result(ui::ER_CONSUMED); - f1->set_mouse_event_handling_result(ui::ER_CONSUMED); - - // Dispatches events. - dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&key_event); - ui::MouseEvent mouse_released( - ui::ET_MOUSE_RELEASED, gfx::Point(0, 0), gfx::Point(0, 0), 0x0); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse_released); - - // f1 should still get the events but f2 no longer gets them. - EXPECT_EQ(1, f1->num_key_events()); - EXPECT_EQ(1, f1->num_mouse_events()); - EXPECT_EQ(0, f2->num_key_events()); - EXPECT_EQ(0, f2->num_mouse_events()); - - f1->Reset(); - f2->Reset(); - - // Remove f1 from additonal filters list. - env_filter->RemoveHandler(f1.get()); - - // Dispatches events. - dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&key_event); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse_pressed); - - // f1 should get no events since it's out and f2 should get them. - EXPECT_EQ(0, f1->num_key_events()); - EXPECT_EQ(0, f1->num_mouse_events()); - EXPECT_EQ(1, f2->num_key_events()); - EXPECT_EQ(1, f2->num_mouse_events()); - - env_filter->RemoveHandler(f2.get()); -} - -// A keypress and/or touch only hides the cursor on ChromeOS (crbug.com/304296). -#if defined(OS_CHROMEOS) -// We should show and hide the cursor in response to mouse and touch events as -// requested. -TEST_F(WindowManagerTest, UpdateCursorVisibility) { - aura::test::EventGenerator& generator = GetEventGenerator(); - views::corewm::CursorManager* cursor_manager = - ash::Shell::GetInstance()->cursor_manager(); - - generator.MoveMouseTo(gfx::Point(0, 0)); - EXPECT_TRUE(cursor_manager->IsCursorVisible()); - EXPECT_TRUE(cursor_manager->IsMouseEventsEnabled()); - generator.PressTouch(); - EXPECT_FALSE(cursor_manager->IsCursorVisible()); - EXPECT_FALSE(cursor_manager->IsMouseEventsEnabled()); - generator.MoveMouseTo(gfx::Point(0, 0)); - EXPECT_TRUE(cursor_manager->IsCursorVisible()); - EXPECT_TRUE(cursor_manager->IsMouseEventsEnabled()); - generator.ReleaseTouch(); - EXPECT_TRUE(cursor_manager->IsCursorVisible()); - EXPECT_TRUE(cursor_manager->IsMouseEventsEnabled()); -} - -TEST_F(WindowManagerTest, UpdateCursorVisibilityOnKeyEvent) { - aura::test::EventGenerator& generator = GetEventGenerator(); - views::corewm::CursorManager* cursor_manager = - ash::Shell::GetInstance()->cursor_manager(); - - // Pressing a key hides the cursor but does not disable mouse events. - generator.PressKey(ui::VKEY_A, ui::EF_NONE); - EXPECT_FALSE(cursor_manager->IsCursorVisible()); - EXPECT_TRUE(cursor_manager->IsMouseEventsEnabled()); - // Moving mouse shows the cursor. - generator.MoveMouseTo(gfx::Point(0, 0)); - EXPECT_TRUE(cursor_manager->IsCursorVisible()); - EXPECT_TRUE(cursor_manager->IsMouseEventsEnabled()); - // Releasing a key also hides the cursor but does not disable mouse events. - generator.ReleaseKey(ui::VKEY_A, ui::EF_NONE); - EXPECT_FALSE(cursor_manager->IsCursorVisible()); - EXPECT_TRUE(cursor_manager->IsMouseEventsEnabled()); - // Moving mouse shows the cursor again. - generator.MoveMouseTo(gfx::Point(0, 0)); - EXPECT_TRUE(cursor_manager->IsCursorVisible()); - EXPECT_TRUE(cursor_manager->IsMouseEventsEnabled()); -} - -TEST_F(WindowManagerTest, TestCursorClientObserver) { - aura::test::EventGenerator& generator = GetEventGenerator(); - views::corewm::CursorManager* cursor_manager = - ash::Shell::GetInstance()->cursor_manager(); - - scoped_ptr<aura::Window> w1(CreateTestWindowInShell( - SK_ColorWHITE, -1, gfx::Rect(0, 0, 100, 100))); - wm::ActivateWindow(w1.get()); - - // Add two observers. Both should have OnCursorVisibilityChanged() - // invoked when an event changes the visibility of the cursor. - TestingCursorClientObserver observer_a; - TestingCursorClientObserver observer_b; - cursor_manager->AddObserver(&observer_a); - cursor_manager->AddObserver(&observer_b); - - // Initial state before any events have been sent. - observer_a.reset(); - observer_b.reset(); - EXPECT_FALSE(observer_a.did_visibility_change()); - EXPECT_FALSE(observer_b.did_visibility_change()); - EXPECT_FALSE(observer_a.is_cursor_visible()); - EXPECT_FALSE(observer_b.is_cursor_visible()); - - // Keypress should hide the cursor. - generator.PressKey(ui::VKEY_A, ui::EF_NONE); - EXPECT_TRUE(observer_a.did_visibility_change()); - EXPECT_TRUE(observer_b.did_visibility_change()); - EXPECT_FALSE(observer_a.is_cursor_visible()); - EXPECT_FALSE(observer_b.is_cursor_visible()); - - // Mouse move should show the cursor. - observer_a.reset(); - observer_b.reset(); - generator.MoveMouseTo(50, 50); - EXPECT_TRUE(observer_a.did_visibility_change()); - EXPECT_TRUE(observer_b.did_visibility_change()); - EXPECT_TRUE(observer_a.is_cursor_visible()); - EXPECT_TRUE(observer_b.is_cursor_visible()); - - // Remove observer_b. Its OnCursorVisibilityChanged() should - // not be invoked past this point. - cursor_manager->RemoveObserver(&observer_b); - - // Gesture tap should hide the cursor. - observer_a.reset(); - observer_b.reset(); - generator.GestureTapAt(gfx::Point(25, 25)); - EXPECT_TRUE(observer_a.did_visibility_change()); - EXPECT_FALSE(observer_b.did_visibility_change()); - EXPECT_FALSE(observer_a.is_cursor_visible()); - - // Mouse move should show the cursor. - observer_a.reset(); - observer_b.reset(); - generator.MoveMouseTo(50, 50); - EXPECT_TRUE(observer_a.did_visibility_change()); - EXPECT_FALSE(observer_b.did_visibility_change()); - EXPECT_TRUE(observer_a.is_cursor_visible()); -} -#endif - -} // namespace ash diff --git a/chromium/ash/wm/window_modality_controller_unittest.cc b/chromium/ash/wm/window_modality_controller_unittest.cc deleted file mode 100644 index 7e3666981e0..00000000000 --- a/chromium/ash/wm/window_modality_controller_unittest.cc +++ /dev/null @@ -1,563 +0,0 @@ -// 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 "ui/views/corewm/window_modality_controller.h" - -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_util.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/base/ui_base_types.h" -#include "ui/views/test/capture_tracking_view.h" -#include "ui/views/test/child_modal_window.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -typedef test::AshTestBase WindowModalityControllerTest; - -namespace { - -bool ValidateStacking(aura::Window* parent, int ids[], int count) { - for (int i = 0; i < count; ++i) { - if (parent->children().at(i)->id() != ids[i]) - return false; - } - return true; -} - -} // namespace - -// Creates three windows, w1, w11, and w12. w11 is a non-modal transient, w12 is -// a modal transient. -// Validates: -// - it should be possible to activate w12 even when w11 is open. -// - activating w1 activates w12 and updates stacking order appropriately. -// - closing a window passes focus up the stack. -TEST_F(WindowModalityControllerTest, BasicActivation) { - aura::test::TestWindowDelegate d; - scoped_ptr<aura::Window> w1( - CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); - scoped_ptr<aura::Window> w11( - CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect())); - scoped_ptr<aura::Window> w12( - CreateTestWindowInShellWithDelegate(&d, -12, gfx::Rect())); - - w1->AddTransientChild(w11.get()); - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - wm::ActivateWindow(w11.get()); - EXPECT_TRUE(wm::IsActiveWindow(w11.get())); - - w12->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - w1->AddTransientChild(w12.get()); - wm::ActivateWindow(w12.get()); - EXPECT_TRUE(wm::IsActiveWindow(w12.get())); - - wm::ActivateWindow(w11.get()); - EXPECT_TRUE(wm::IsActiveWindow(w11.get())); - - int check1[] = { -1, -12, -11 }; - EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1))); - - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w12.get())); - // Transient children are always stacked above their transient parent, which - // is why this order is not -11, -1, -12. - int check2[] = { -1, -11, -12 }; - EXPECT_TRUE(ValidateStacking(w1->parent(), check2, arraysize(check2))); - - w12.reset(); - EXPECT_TRUE(wm::IsActiveWindow(w11.get())); - w11.reset(); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); -} - -// Create two toplevel windows w1 and w2, and nest two modals w11 and w111 below -// w1. -// Validates: -// - activating w1 while w11/w111 is showing always activates most deeply nested -// descendant. -// - closing a window passes focus up the stack. -TEST_F(WindowModalityControllerTest, NestedModals) { - aura::test::TestWindowDelegate d; - scoped_ptr<aura::Window> w1( - CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); - scoped_ptr<aura::Window> w11( - CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect())); - scoped_ptr<aura::Window> w111( - CreateTestWindowInShellWithDelegate(&d, -111, gfx::Rect())); - scoped_ptr<aura::Window> w2( - CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); - - w1->AddTransientChild(w11.get()); - w11->AddTransientChild(w111.get()); - - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - wm::ActivateWindow(w2.get()); - EXPECT_TRUE(wm::IsActiveWindow(w2.get())); - - // Set up modality. - w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - w111->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w111.get())); - int check1[] = { -2, -1, -11, -111 }; - EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1))); - - wm::ActivateWindow(w11.get()); - EXPECT_TRUE(wm::IsActiveWindow(w111.get())); - EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1))); - - wm::ActivateWindow(w111.get()); - EXPECT_TRUE(wm::IsActiveWindow(w111.get())); - EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1))); - - wm::ActivateWindow(w2.get()); - EXPECT_TRUE(wm::IsActiveWindow(w2.get())); - int check2[] = { -1, -11, -111, -2 }; - EXPECT_TRUE(ValidateStacking(w1->parent(), check2, arraysize(check2))); - - w2.reset(); - EXPECT_TRUE(wm::IsActiveWindow(w111.get())); - w111.reset(); - EXPECT_TRUE(wm::IsActiveWindow(w11.get())); - w11.reset(); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); -} - -// Create two toplevel windows w1 and w2, and nest two modals w11 and w111 below -// w1. -// Validates: -// - destroying w11 while w111 is focused activates w1. -TEST_F(WindowModalityControllerTest, NestedModalsOuterClosed) { - aura::test::TestWindowDelegate d; - scoped_ptr<aura::Window> w1( - CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); - scoped_ptr<aura::Window> w11( - CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect())); - // |w111| will be owned and deleted by |w11|. - aura::Window* w111 = - CreateTestWindowInShellWithDelegate(&d, -111, gfx::Rect()); - scoped_ptr<aura::Window> w2( - CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); - - w1->AddTransientChild(w11.get()); - w11->AddTransientChild(w111); - - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - wm::ActivateWindow(w2.get()); - EXPECT_TRUE(wm::IsActiveWindow(w2.get())); - - // Set up modality. - w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - w111->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w111)); - - w111->Hide(); - EXPECT_TRUE(wm::IsActiveWindow(w11.get())); - - // TODO(oshima): Re-showing doesn't set the focus back to - // modal window. There is no such use case right now, but it - // probably should. - - w11.reset(); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); -} - -// Modality also prevents events from being passed to the transient parent. -TEST_F(WindowModalityControllerTest, Events) { - aura::test::TestWindowDelegate d; - scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(&d, -1, - gfx::Rect(0, 0, 100, 100))); - scoped_ptr<aura::Window> w11(CreateTestWindowInShellWithDelegate(&d, -11, - gfx::Rect(20, 20, 50, 50))); - - w1->AddTransientChild(w11.get()); - - { - // Clicking a point within w1 should activate that window. - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - gfx::Point(10, 10)); - generator.ClickLeftButton(); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - } - - w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - - { - // Clicking a point within w1 should activate w11. - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - gfx::Point(10, 10)); - generator.ClickLeftButton(); - EXPECT_TRUE(wm::IsActiveWindow(w11.get())); - } -} - -// Creates windows w1 and non activatiable child w11. Creates transient window -// w2 and adds it as a transeint child of w1. Ensures that w2 is parented to -// the parent of w1, and that GetModalTransient(w11) returns w2. -TEST_F(WindowModalityControllerTest, GetModalTransient) { - aura::test::TestWindowDelegate d; - scoped_ptr<aura::Window> w1( - CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); - scoped_ptr<aura::Window> w11( - aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get())); - scoped_ptr<aura::Window> w2( - CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); - w2->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - - aura::Window* wt; - wt = views::corewm::GetModalTransient(w1.get()); - ASSERT_EQ(static_cast<aura::Window*>(NULL), wt); - - // Parent w2 to w1. It should get parented to the parent of w1. - w1->AddTransientChild(w2.get()); - ASSERT_EQ(2U, w1->parent()->children().size()); - EXPECT_EQ(-2, w1->parent()->children().at(1)->id()); - - // Request the modal transient window for w1, it should be w2. - wt = views::corewm::GetModalTransient(w1.get()); - ASSERT_NE(static_cast<aura::Window*>(NULL), wt); - EXPECT_EQ(-2, wt->id()); - - // Request the modal transient window for w11, it should also be w2. - wt = views::corewm::GetModalTransient(w11.get()); - ASSERT_NE(static_cast<aura::Window*>(NULL), wt); - EXPECT_EQ(-2, wt->id()); -} - -// Verifies we generate a capture lost when showing a modal window. -TEST_F(WindowModalityControllerTest, ChangeCapture) { - views::Widget* widget = views::Widget::CreateWindowWithContext( - NULL, Shell::GetPrimaryRootWindow()); - scoped_ptr<aura::Window> widget_window(widget->GetNativeView()); - views::test::CaptureTrackingView* view = new views::test::CaptureTrackingView; - widget->client_view()->AddChildView(view); - widget->SetBounds(gfx::Rect(0, 0, 200, 200)); - view->SetBoundsRect(widget->client_view()->GetLocalBounds()); - widget->Show(); - - gfx::Point center(view->width() / 2, view->height() / 2); - views::View::ConvertPointToScreen(view, ¢er); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), center); - generator.PressLeftButton(); - EXPECT_TRUE(view->got_press()); - - views::Widget* modal_widget = - views::Widget::CreateWindowWithParent(NULL, widget->GetNativeView()); - scoped_ptr<aura::Window> modal_window(modal_widget->GetNativeView()); - modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - views::test::CaptureTrackingView* modal_view = - new views::test::CaptureTrackingView; - modal_widget->client_view()->AddChildView(modal_view); - modal_widget->SetBounds(gfx::Rect(50, 50, 200, 200)); - modal_view->SetBoundsRect(modal_widget->client_view()->GetLocalBounds()); - modal_widget->Show(); - - EXPECT_TRUE(view->got_capture_lost()); - generator.ReleaseLeftButton(); - - view->reset(); - - EXPECT_FALSE(modal_view->got_capture_lost()); - EXPECT_FALSE(modal_view->got_press()); - - gfx::Point modal_center(modal_view->width() / 2, modal_view->height() / 2); - views::View::ConvertPointToScreen(modal_view, &modal_center); - generator.MoveMouseTo(modal_center, 1); - generator.PressLeftButton(); - EXPECT_TRUE(modal_view->got_press()); - EXPECT_FALSE(modal_view->got_capture_lost()); - EXPECT_FALSE(view->got_capture_lost()); - EXPECT_FALSE(view->got_press()); -} - -class TouchTrackerWindowDelegate : public aura::test::TestWindowDelegate { - public: - TouchTrackerWindowDelegate() - : received_touch_(false), - last_event_type_(ui::ET_UNKNOWN) { - } - virtual ~TouchTrackerWindowDelegate() {} - - void reset() { - received_touch_ = false; - last_event_type_ = ui::ET_UNKNOWN; - } - - bool received_touch() const { return received_touch_; } - ui::EventType last_event_type() const { return last_event_type_; } - - private: - // Overridden from aura::test::TestWindowDelegate. - virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE { - received_touch_ = true; - last_event_type_ = event->type(); - aura::test::TestWindowDelegate::OnTouchEvent(event); - } - - bool received_touch_; - ui::EventType last_event_type_; - - DISALLOW_COPY_AND_ASSIGN(TouchTrackerWindowDelegate); -}; - -// Modality should prevent events from being passed to the transient parent. -TEST_F(WindowModalityControllerTest, TouchEvent) { - TouchTrackerWindowDelegate d1; - scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(&d1, - -1, gfx::Rect(0, 0, 100, 100))); - TouchTrackerWindowDelegate d11; - scoped_ptr<aura::Window> w11(CreateTestWindowInShellWithDelegate(&d11, - -11, gfx::Rect(20, 20, 50, 50))); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - gfx::Point(10, 10)); - - w1->AddTransientChild(w11.get()); - d1.reset(); - d11.reset(); - - { - // Clicking a point within w1 should activate that window. - generator.PressMoveAndReleaseTouchTo(gfx::Point(10, 10)); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - EXPECT_TRUE(d1.received_touch()); - EXPECT_FALSE(d11.received_touch()); - } - - { - // Adding a modal window while a touch is down should fire a touch cancel. - generator.PressTouch(); - generator.MoveTouch(gfx::Point(10, 10)); - d1.reset(); - d11.reset(); - - w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - EXPECT_TRUE(d1.received_touch()); - EXPECT_EQ(ui::ET_TOUCH_CANCELLED, d1.last_event_type()); - EXPECT_FALSE(d11.received_touch()); - } -} - -// Child-modal test. -// Creates: -// - A |parent| window that hosts a |modal_parent| window within itself. The -// |parent| and |modal_parent| windows are not the same window. The -// |modal_parent| window is not activatable, because it's contained within the -// |parent| window. -// - A |child| window with parent window |parent|, but is modal to -// |modal_parent| window. -// Validates: -// - Clicking on the |modal_parent| should activate the |child| window. -// - Clicking on the |parent| window outside of the |modal_parent| bounds should -// activate the |parent| window. -// - Clicking on the |child| while |parent| is active should activate the -// |child| window. -// - Focus should follow the active window. -TEST_F(WindowModalityControllerTest, ChildModal) { - views::test::ChildModalParent* delegate = - new views::test::ChildModalParent(CurrentContext()); - views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds( - delegate, CurrentContext(), gfx::Rect(0, 0, 400, 400)); - widget->Show(); - - aura::Window* parent = widget->GetNativeView(); - EXPECT_TRUE(wm::IsActiveWindow(parent)); - - aura::Window* modal_parent = delegate->GetModalParent(); - EXPECT_NE(static_cast<aura::Window*>(NULL), modal_parent); - EXPECT_NE(parent, modal_parent); - EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); - - delegate->ShowChild(); - aura::Window* child = delegate->GetChild(); - EXPECT_NE(static_cast<aura::Window*>(NULL), child); - - EXPECT_TRUE(wm::IsActiveWindow(child)); - EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); - EXPECT_FALSE(wm::IsActiveWindow(parent)); - - EXPECT_TRUE(child->HasFocus()); - EXPECT_FALSE(modal_parent->HasFocus()); - EXPECT_FALSE(parent->HasFocus()); - - wm::ActivateWindow(modal_parent); - - EXPECT_TRUE(wm::IsActiveWindow(child)); - EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); - EXPECT_FALSE(wm::IsActiveWindow(parent)); - - EXPECT_TRUE(child->HasFocus()); - EXPECT_FALSE(modal_parent->HasFocus()); - EXPECT_FALSE(parent->HasFocus()); - - wm::ActivateWindow(parent); - - EXPECT_FALSE(wm::IsActiveWindow(child)); - EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); - EXPECT_TRUE(wm::IsActiveWindow(parent)); - - EXPECT_FALSE(child->HasFocus()); - EXPECT_FALSE(modal_parent->HasFocus()); - EXPECT_TRUE(parent->HasFocus()); - - wm::ActivateWindow(child); - - EXPECT_TRUE(wm::IsActiveWindow(child)); - EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); - EXPECT_FALSE(wm::IsActiveWindow(parent)); - - EXPECT_TRUE(child->HasFocus()); - EXPECT_FALSE(modal_parent->HasFocus()); - EXPECT_FALSE(parent->HasFocus()); -} - -// Same as |ChildModal| test, but using |EventGenerator| rather than bypassing -// it by calling |ActivateWindow|. -TEST_F(WindowModalityControllerTest, ChildModalEventGenerator) { - views::test::ChildModalParent* delegate = - new views::test::ChildModalParent(CurrentContext()); - views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds( - delegate, CurrentContext(), gfx::Rect(0, 0, 400, 400)); - widget->Show(); - - aura::Window* parent = widget->GetNativeView(); - EXPECT_TRUE(wm::IsActiveWindow(parent)); - - aura::Window* modal_parent = delegate->GetModalParent(); - EXPECT_NE(static_cast<aura::Window*>(NULL), modal_parent); - EXPECT_NE(parent, modal_parent); - EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); - - delegate->ShowChild(); - aura::Window* child = delegate->GetChild(); - EXPECT_NE(static_cast<aura::Window*>(NULL), child); - - EXPECT_TRUE(wm::IsActiveWindow(child)); - EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); - EXPECT_FALSE(wm::IsActiveWindow(parent)); - - EXPECT_TRUE(child->HasFocus()); - EXPECT_FALSE(modal_parent->HasFocus()); - EXPECT_FALSE(parent->HasFocus()); - - { - aura::test::EventGenerator generator( - Shell::GetPrimaryRootWindow(), - parent->bounds().origin() + - gfx::Vector2d(10, parent->bounds().height() - 10)); - generator.ClickLeftButton(); - generator.ClickLeftButton(); - - EXPECT_TRUE(wm::IsActiveWindow(child)); - EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); - EXPECT_FALSE(wm::IsActiveWindow(parent)); - - EXPECT_TRUE(child->HasFocus()); - EXPECT_FALSE(modal_parent->HasFocus()); - EXPECT_FALSE(parent->HasFocus()); - } - - { - aura::test::EventGenerator generator( - Shell::GetPrimaryRootWindow(), - parent->bounds().origin() + gfx::Vector2d(10, 10)); - generator.ClickLeftButton(); - - EXPECT_FALSE(wm::IsActiveWindow(child)); - EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); - EXPECT_TRUE(wm::IsActiveWindow(parent)); - - EXPECT_FALSE(child->HasFocus()); - EXPECT_FALSE(modal_parent->HasFocus()); - EXPECT_TRUE(parent->HasFocus()); - } - - { - aura::test::EventGenerator generator( - Shell::GetPrimaryRootWindow(), - child->bounds().origin() + gfx::Vector2d(10, 10)); - generator.ClickLeftButton(); - - EXPECT_TRUE(wm::IsActiveWindow(child)); - EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); - EXPECT_FALSE(wm::IsActiveWindow(parent)); - - EXPECT_TRUE(child->HasFocus()); - EXPECT_FALSE(modal_parent->HasFocus()); - EXPECT_FALSE(parent->HasFocus()); - } -} - -// Window-modal test for the case when the originally clicked window is an -// ancestor of the modal parent. -TEST_F(WindowModalityControllerTest, WindowModalAncestor) { - aura::test::TestWindowDelegate d; - scoped_ptr<aura::Window> w1( - CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); - scoped_ptr<aura::Window> w2( - aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get())); - scoped_ptr<aura::Window> w3( - aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w2.get())); - scoped_ptr<aura::Window> w4( - CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); - w4->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - w1->AddTransientChild(w4.get()); - - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w4.get())); - - wm::ActivateWindow(w2.get()); - EXPECT_TRUE(wm::IsActiveWindow(w4.get())); - - wm::ActivateWindow(w3.get()); - EXPECT_TRUE(wm::IsActiveWindow(w4.get())); - - wm::ActivateWindow(w4.get()); - EXPECT_TRUE(wm::IsActiveWindow(w4.get())); -} - -// Child-modal test for the case when the originally clicked window is an -// ancestor of the modal parent. -TEST_F(WindowModalityControllerTest, ChildModalAncestor) { - aura::test::TestWindowDelegate d; - scoped_ptr<aura::Window> w1( - CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); - scoped_ptr<aura::Window> w2( - aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get())); - scoped_ptr<aura::Window> w3( - aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w2.get())); - scoped_ptr<aura::Window> w4( - CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); - w4->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_CHILD); - views::corewm::SetModalParent(w4.get(), w2.get()); - w1->AddTransientChild(w4.get()); - - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - - wm::ActivateWindow(w2.get()); - EXPECT_TRUE(wm::IsActiveWindow(w4.get())); - - wm::ActivateWindow(w3.get()); - EXPECT_TRUE(wm::IsActiveWindow(w4.get())); - - wm::ActivateWindow(w4.get()); - EXPECT_TRUE(wm::IsActiveWindow(w4.get())); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/window_positioner.cc b/chromium/ash/wm/window_positioner.cc deleted file mode 100644 index 9b31113f8c4..00000000000 --- a/chromium/ash/wm/window_positioner.cc +++ /dev/null @@ -1,547 +0,0 @@ -// Copyright 2013 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/window_positioner.h" - -#include "ash/ash_switches.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/mru_window_tracker.h" -#include "ash/wm/window_resizer.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/command_line.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/screen.h" -#include "ui/views/corewm/window_animations.h" - -namespace ash { - -const int WindowPositioner::kMinimumWindowOffset = 32; - -// The number of pixels which are kept free top, left and right when a window -// gets positioned to its default location. -// static -const int WindowPositioner::kDesktopBorderSize = 16; - -// Maximum width of a window even if there is more room on the desktop. -// static -const int WindowPositioner::kMaximumWindowWidth = 1100; - -namespace { - -// When a window gets opened in default mode and the screen is less than or -// equal to this width, the window will get opened in maximized mode. This value -// can be reduced to a "tame" number if the feature is disabled. -const int kForceMaximizeWidthLimit = 1366; -const int kForceMaximizeWidthLimitDisabled = 640; - -// The time in milliseconds which should be used to visually move a window -// through an automatic "intelligent" window management option. -const int kWindowAutoMoveDurationMS = 125; - -// If set to true all window repositioning actions will be ignored. Set through -// WindowPositioner::SetIgnoreActivations(). -static bool disable_auto_positioning = false; - -// If set to true, by default the first window in ASH will be maxmized. -static bool maximize_first_window = false; - -// Check if any management should be performed (with a given |window|). -bool UseAutoWindowManager(const aura::Window* window) { - if (disable_auto_positioning) - return false; - const wm::WindowState* window_state = wm::GetWindowState(window); - return !window_state->is_dragged() && window_state->window_position_managed(); -} - -// Check if a given |window| can be managed. This includes that it's state is -// not minimized/maximized/the user has changed it's size by hand already. -// It furthermore checks for the WindowIsManaged status. -bool WindowPositionCanBeManaged(const aura::Window* window) { - if (disable_auto_positioning) - return false; - const wm::WindowState* window_state = wm::GetWindowState(window); - return window_state->window_position_managed() && - !window_state->IsMinimized() && - !window_state->IsMaximized() && - !window_state->bounds_changed_by_user(); -} - -// Get the work area for a given |window| in parent coordinates. -gfx::Rect GetWorkAreaForWindowInParent(aura::Window* window) { -#if defined(OS_WIN) - // On Win 8, the host window can't be resized, so - // use window's bounds instead. - // TODO(oshima): Emulate host window resize on win8. - gfx::Rect work_area = gfx::Rect(window->parent()->bounds().size()); - work_area.Inset(Shell::GetScreen()->GetDisplayMatching( - window->parent()->GetBoundsInScreen()).GetWorkAreaInsets()); - return work_area; -#else - return ScreenAsh::GetDisplayWorkAreaBoundsInParent(window); -#endif -} - -// Move the given |bounds| on the available |work_area| in the direction -// indicated by |move_right|. If |move_right| is true, the rectangle gets moved -// to the right edge, otherwise to the left one. -bool MoveRectToOneSide(const gfx::Rect& work_area, - bool move_right, - gfx::Rect* bounds) { - if (move_right) { - if (work_area.right() > bounds->right()) { - bounds->set_x(work_area.right() - bounds->width()); - return true; - } - } else { - if (work_area.x() < bounds->x()) { - bounds->set_x(work_area.x()); - return true; - } - } - return false; -} - -// Move a |window| to a new |bound|. Animate if desired by user. -// Note: The function will do nothing if the bounds did not change. -void SetBoundsAnimated(aura::Window* window, const gfx::Rect& bounds) { - if (bounds == window->GetTargetBounds()) - return; - - if (views::corewm::WindowAnimationsDisabled(window)) { - window->SetBounds(bounds); - return; - } - - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kWindowAutoMoveDurationMS)); - window->SetBounds(bounds); -} - -// Move |window| into the center of the screen - or restore it to the previous -// position. -void AutoPlaceSingleWindow(aura::Window* window, bool animated) { - gfx::Rect work_area = GetWorkAreaForWindowInParent(window); - gfx::Rect bounds = window->bounds(); - const gfx::Rect* user_defined_area = - wm::GetWindowState(window)->pre_auto_manage_window_bounds(); - if (user_defined_area) { - bounds = *user_defined_area; - ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(work_area, &bounds); - } else { - // Center the window (only in x). - bounds.set_x(work_area.x() + (work_area.width() - bounds.width()) / 2); - } - - if (animated) - SetBoundsAnimated(window, bounds); - else - window->SetBounds(bounds); -} - -// Get the first open (non minimized) window which is on the screen defined. -aura::Window* GetReferenceWindow(const aura::Window* root_window, - const aura::Window* exclude, - bool *single_window) { - if (single_window) - *single_window = true; - // Get the active window. - aura::Window* active = ash::wm::GetActiveWindow(); - if (active && active->GetRootWindow() != root_window) - active = NULL; - - // Get a list of all windows. - const std::vector<aura::Window*> windows = - ash::MruWindowTracker::BuildWindowList(false); - - if (windows.empty()) - return NULL; - - aura::Window::Windows::const_iterator iter = windows.begin(); - // Find the index of the current active window. - if (active) - iter = std::find(windows.begin(), windows.end(), active); - - int index = (iter == windows.end()) ? 0 : (iter - windows.begin()); - - // Scan the cycle list backwards to see which is the second topmost window - // (and so on). Note that we might cycle a few indices twice if there is no - // suitable window. However - since the list is fairly small this should be - // very fast anyways. - aura::Window* found = NULL; - for (int i = index + windows.size(); i >= 0; i--) { - aura::Window* window = windows[i % windows.size()]; - if (window != exclude && - window->type() == aura::client::WINDOW_TYPE_NORMAL && - window->GetRootWindow() == root_window && - window->TargetVisibility() && - wm::GetWindowState(window)->window_position_managed()) { - if (found && found != window) { - // no need to check !signle_window because the function must have - // been already returned in the "if (!single_window)" below. - *single_window = false; - return found; - } - found = window; - // If there is no need to check single window, return now. - if (!single_window) - return found; - } - } - return found; -} - -} // namespace - -// static -int WindowPositioner::GetForceMaximizedWidthLimit() { - static int maximum_limit = 0; - if (!maximum_limit) { - maximum_limit = CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshDisableAutoMaximizing) ? - kForceMaximizeWidthLimitDisabled : kForceMaximizeWidthLimit; - } - return maximum_limit; -} - -// static -void WindowPositioner::GetBoundsAndShowStateForNewWindow( - const gfx::Screen* screen, - const aura::Window* new_window, - bool is_saved_bounds, - ui::WindowShowState show_state_in, - gfx::Rect* bounds_in_out, - ui::WindowShowState* show_state_out) { - - // Always open new window in the target display. - aura::Window* target = Shell::GetTargetRootWindow(); - - aura::Window* top_window = GetReferenceWindow(target, NULL, NULL); - // Our window should not have any impact if we are already on top. - if (top_window == new_window) - top_window = NULL; - - // If there is no valid other window we take and adjust the passed coordinates - // and show state. - if (!top_window) { - gfx::Rect work_area = screen->GetDisplayNearestWindow(target).work_area(); - - bounds_in_out->AdjustToFit(work_area); - // Use adjusted saved bounds, if there is one. - if (is_saved_bounds) - return; - // When using "small screens" we want to always open in full screen mode. - if (show_state_in == ui::SHOW_STATE_DEFAULT && (maximize_first_window || - (work_area.width() <= GetForceMaximizedWidthLimit() && - (!new_window || !wm::GetWindowState(new_window)->IsFullscreen())))) { - *show_state_out = ui::SHOW_STATE_MAXIMIZED; - } - return; - } - bool maximized = wm::GetWindowState(top_window)->IsMaximized(); - // We ignore the saved show state, but look instead for the top level - // window's show state. - if (show_state_in == ui::SHOW_STATE_DEFAULT) { - *show_state_out = maximized ? ui::SHOW_STATE_MAXIMIZED : - ui::SHOW_STATE_DEFAULT; - } - - // Use the size of the other window. The window's bound will be rearranged - // in ash::WorkspaceLayoutManager using this location. - *bounds_in_out = top_window->GetBoundsInScreen(); -} - -// static -void WindowPositioner::RearrangeVisibleWindowOnHideOrRemove( - const aura::Window* removed_window) { - if (!UseAutoWindowManager(removed_window)) - return; - // Find a single open browser window. - bool single_window; - aura::Window* other_shown_window = GetReferenceWindow( - removed_window->GetRootWindow(), removed_window, &single_window); - if (!other_shown_window || !single_window || - !WindowPositionCanBeManaged(other_shown_window)) - return; - AutoPlaceSingleWindow(other_shown_window, true); -} - -// static -bool WindowPositioner::DisableAutoPositioning(bool ignore) { - bool old_state = disable_auto_positioning; - disable_auto_positioning = ignore; - return old_state; -} - -// static -void WindowPositioner::RearrangeVisibleWindowOnShow( - aura::Window* added_window) { - wm::WindowState* added_window_state = wm::GetWindowState(added_window); - if (!added_window->TargetVisibility()) - return; - - if (!UseAutoWindowManager(added_window) || - added_window_state->bounds_changed_by_user()) { - if (added_window_state->minimum_visibility()) { - // Guarante minimum visibility within the work area. - gfx::Rect work_area = GetWorkAreaForWindowInParent(added_window); - gfx::Rect bounds = added_window->bounds(); - gfx::Rect new_bounds = bounds; - ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(work_area, - &new_bounds); - if (new_bounds != bounds) - added_window->SetBounds(new_bounds); - } - return; - } - // Find a single open managed window. - bool single_window; - aura::Window* other_shown_window = GetReferenceWindow( - added_window->GetRootWindow(), added_window, &single_window); - - if (!other_shown_window) { - // It could be that this window is the first window joining the workspace. - if (!WindowPositionCanBeManaged(added_window) || other_shown_window) - return; - // Since we might be going from 0 to 1 window, we have to arrange the new - // window to a good default. - AutoPlaceSingleWindow(added_window, false); - return; - } - - gfx::Rect other_bounds = other_shown_window->bounds(); - gfx::Rect work_area = GetWorkAreaForWindowInParent(added_window); - bool move_other_right = - other_bounds.CenterPoint().x() > work_area.x() + work_area.width() / 2; - - // Push the other window to the size only if there are two windows left. - if (single_window) { - // When going from one to two windows both windows loose their - // "positioned by user" flags. - added_window_state->set_bounds_changed_by_user(false); - wm::WindowState* other_window_state = - wm::GetWindowState(other_shown_window); - other_window_state->set_bounds_changed_by_user(false); - - if (WindowPositionCanBeManaged(other_shown_window)) { - // Don't override pre auto managed bounds as the current bounds - // may not be original. - if (!other_window_state->pre_auto_manage_window_bounds()) - other_window_state->SetPreAutoManageWindowBounds(other_bounds); - - // Push away the other window after remembering its current position. - if (MoveRectToOneSide(work_area, move_other_right, &other_bounds)) - SetBoundsAnimated(other_shown_window, other_bounds); - } - } - - // Remember the current location of the window if it's new and push - // it also to the opposite location if needed. Since it is just - // being shown, we do not need to animate it. - gfx::Rect added_bounds = added_window->bounds(); - if (!added_window_state->pre_auto_manage_window_bounds()) - added_window_state->SetPreAutoManageWindowBounds(added_bounds); - if (MoveRectToOneSide(work_area, !move_other_right, &added_bounds)) - added_window->SetBounds(added_bounds); -} - -WindowPositioner::WindowPositioner() - : pop_position_offset_increment_x(0), - pop_position_offset_increment_y(0), - popup_position_offset_from_screen_corner_x(0), - popup_position_offset_from_screen_corner_y(0), - last_popup_position_x_(0), - last_popup_position_y_(0) { -} - -WindowPositioner::~WindowPositioner() { -} - -gfx::Rect WindowPositioner::GetDefaultWindowBounds( - const gfx::Display& display) { - const gfx::Rect work_area = display.work_area(); - // There should be a 'desktop' border around the window at the left and right - // side. - int default_width = work_area.width() - 2 * kDesktopBorderSize; - // There should also be a 'desktop' border around the window at the top. - // Since the workspace excludes the tray area we only need one border size. - int default_height = work_area.height() - kDesktopBorderSize; - int offset_x = kDesktopBorderSize; - if (default_width > kMaximumWindowWidth) { - // The window should get centered on the screen and not follow the grid. - offset_x = (work_area.width() - kMaximumWindowWidth) / 2; - default_width = kMaximumWindowWidth; - } - return gfx::Rect(work_area.x() + offset_x, - work_area.y() + kDesktopBorderSize, - default_width, - default_height); -} - -gfx::Rect WindowPositioner::GetPopupPosition(const gfx::Rect& old_pos) { - int grid = kMinimumWindowOffset; - popup_position_offset_from_screen_corner_x = grid; - popup_position_offset_from_screen_corner_y = grid; - if (!pop_position_offset_increment_x) { - // When the popup position increment is , the last popup position - // was not yet initialized. - last_popup_position_x_ = popup_position_offset_from_screen_corner_x; - last_popup_position_y_ = popup_position_offset_from_screen_corner_y; - } - pop_position_offset_increment_x = grid; - pop_position_offset_increment_y = grid; - // We handle the Multi monitor support by retrieving the active window's - // work area. - aura::Window* window = wm::GetActiveWindow(); - const gfx::Rect work_area = window && window->IsVisible() ? - Shell::GetScreen()->GetDisplayNearestWindow(window).work_area() : - Shell::GetScreen()->GetPrimaryDisplay().work_area(); - // Only try to reposition the popup when it is not spanning the entire - // screen. - if ((old_pos.width() + popup_position_offset_from_screen_corner_x >= - work_area.width()) || - (old_pos.height() + popup_position_offset_from_screen_corner_y >= - work_area.height())) - return AlignPopupPosition(old_pos, work_area, grid); - const gfx::Rect result = SmartPopupPosition(old_pos, work_area, grid); - if (!result.IsEmpty()) - return AlignPopupPosition(result, work_area, grid); - return NormalPopupPosition(old_pos, work_area); -} - -// static -void WindowPositioner::SetMaximizeFirstWindow(bool maximize) { - maximize_first_window = maximize; -} - -gfx::Rect WindowPositioner::NormalPopupPosition( - const gfx::Rect& old_pos, - const gfx::Rect& work_area) { - int w = old_pos.width(); - int h = old_pos.height(); - // Note: The 'last_popup_position' is checked and kept relative to the - // screen size. The offsetting will be done in the last step when the - // target rectangle gets returned. - bool reset = false; - if (last_popup_position_y_ + h > work_area.height() || - last_popup_position_x_ + w > work_area.width()) { - // Popup does not fit on screen. Reset to next diagonal row. - last_popup_position_x_ -= last_popup_position_y_ - - popup_position_offset_from_screen_corner_x - - pop_position_offset_increment_x; - last_popup_position_y_ = popup_position_offset_from_screen_corner_y; - reset = true; - } - if (last_popup_position_x_ + w > work_area.width()) { - // Start again over. - last_popup_position_x_ = popup_position_offset_from_screen_corner_x; - last_popup_position_y_ = popup_position_offset_from_screen_corner_y; - reset = true; - } - int x = last_popup_position_x_; - int y = last_popup_position_y_; - if (!reset) { - last_popup_position_x_ += pop_position_offset_increment_x; - last_popup_position_y_ += pop_position_offset_increment_y; - } - return gfx::Rect(x + work_area.x(), y + work_area.y(), w, h); -} - -gfx::Rect WindowPositioner::SmartPopupPosition( - const gfx::Rect& old_pos, - const gfx::Rect& work_area, - int grid) { - const std::vector<aura::Window*> windows = - MruWindowTracker::BuildWindowList(false); - - std::vector<const gfx::Rect*> regions; - // Process the window list and check if we can bail immediately. - for (size_t i = 0; i < windows.size(); i++) { - // We only include opaque and visible windows. - if (windows[i] && windows[i]->IsVisible() && windows[i]->layer() && - (!windows[i]->transparent() || - windows[i]->layer()->GetTargetOpacity() == 1.0)) { - wm::WindowState* window_state = wm::GetWindowState(windows[i]); - // When any window is maximized we cannot find any free space. - if (window_state->IsMaximizedOrFullscreen()) - return gfx::Rect(0, 0, 0, 0); - if (window_state->IsNormalShowState()) - regions.push_back(&windows[i]->bounds()); - } - } - - if (regions.empty()) - return gfx::Rect(0, 0, 0, 0); - - int w = old_pos.width(); - int h = old_pos.height(); - int x_end = work_area.width() / 2; - int x, x_increment; - // We parse for a proper location on the screen. We do this in two runs: - // The first run will start from the left, parsing down, skipping any - // overlapping windows it will encounter until the popup's height can not - // be served anymore. Then the next grid position to the right will be - // taken, and the same cycle starts again. This will be repeated until we - // hit the middle of the screen (or we find a suitable location). - // In the second run we parse beginning from the right corner downwards and - // then to the left. - // When no location was found, an empty rectangle will be returned. - for (int run = 0; run < 2; run++) { - if (run == 0) { // First run: Start left, parse right till mid screen. - x = 0; - x_increment = pop_position_offset_increment_x; - } else { // Second run: Start right, parse left till mid screen. - x = work_area.width() - w; - x_increment = -pop_position_offset_increment_x; - } - // Note: The passing (x,y,w,h) window is always relative to the work area's - // origin. - for (; x_increment > 0 ? (x < x_end) : (x > x_end); x += x_increment) { - int y = 0; - while (y + h <= work_area.height()) { - size_t i; - for (i = 0; i < regions.size(); i++) { - if (regions[i]->Intersects(gfx::Rect(x + work_area.x(), - y + work_area.y(), w, h))) { - y = regions[i]->bottom() - work_area.y(); - break; - } - } - if (i >= regions.size()) - return gfx::Rect(x + work_area.x(), y + work_area.y(), w, h); - } - } - } - return gfx::Rect(0, 0, 0, 0); -} - -gfx::Rect WindowPositioner::AlignPopupPosition( - const gfx::Rect& pos, - const gfx::Rect& work_area, - int grid) { - if (grid <= 1) - return pos; - - int x = pos.x() - (pos.x() - work_area.x()) % grid; - int y = pos.y() - (pos.y() - work_area.y()) % grid; - int w = pos.width(); - int h = pos.height(); - - // If the alignment was pushing the window out of the screen, we ignore the - // alignment for that call. - if (abs(pos.right() - work_area.right()) < grid) - x = work_area.right() - w; - if (abs(pos.bottom() - work_area.bottom()) < grid) - y = work_area.bottom() - h; - return gfx::Rect(x, y, w, h); -} - -} // namespace ash diff --git a/chromium/ash/wm/window_positioner.h b/chromium/ash/wm/window_positioner.h deleted file mode 100644 index 2efbac06f9b..00000000000 --- a/chromium/ash/wm/window_positioner.h +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2013 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_WINDOW_POSITIONER_H_ -#define ASH_WM_WINDOW_POSITIONER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "ui/base/ui_base_types.h" -#include "ui/gfx/rect.h" - -namespace aura { -class Window; -class RootWindow; -} - -namespace gfx { -class Display; -class Rect; -class Screen; -} - -namespace ash { - -namespace test { -class WindowPositionerTest; -} - -// WindowPositioner is used by the browser to move new popups automatically to -// a usable position on the closest work area (of the active window). -class ASH_EXPORT WindowPositioner { - public: - // When the screen resolution width is smaller then this size, The algorithm - // will default to maximized. - static int GetForceMaximizedWidthLimit(); - - // The number of pixels which are kept free top, left and right when a window - // gets positioned to its default location. - static const int kDesktopBorderSize; - - // Maximum width of a window even if there is more room on the desktop. - static const int kMaximumWindowWidth; - - // Computes and returns the bounds and show state for new window - // based on the parameter passed AND existing windows. |window| is - // the one this function will generate a bounds for and used to - // exclude the self window in making decision how to position the - // window. |window| can be (and in most case) NULL. - // |is_saved_bounds| indicates the |bounds_in_out| is the saved - // bounds. - static void GetBoundsAndShowStateForNewWindow( - const gfx::Screen* screen, - const aura::Window* new_window, - bool is_saved_bounds, - ui::WindowShowState show_state_in, - gfx::Rect* bounds_in_out, - ui::WindowShowState* show_state_out); - - // Returns the default bounds for a window to be created in the |display|. - static gfx::Rect GetDefaultWindowBounds(const gfx::Display& display); - - // Check if after removal or hide of the given |removed_window| an - // automated desktop location management can be performed and - // rearrange accordingly. - static void RearrangeVisibleWindowOnHideOrRemove( - const aura::Window* removed_window); - - // Turn the automatic positioning logic temporarily off. Returns the previous - // state. - static bool DisableAutoPositioning(bool ignore); - - // Check if after insertion or showing of the given |added_window| - // an automated desktop location management can be performed and - // rearrange accordingly. - static void RearrangeVisibleWindowOnShow(aura::Window* added_window); - - WindowPositioner(); - ~WindowPositioner(); - - // Find a suitable screen position for a popup window and return it. The - // passed input position is only used to retrieve the width and height. - // The position is determined on the left / right / top / bottom first. If - // no smart space is found, the position will follow the standard what other - // operating systems do (default cascading style). - gfx::Rect GetPopupPosition(const gfx::Rect& old_pos); - - // Accessor to set a flag indicating whether the first window in ASH should - // be maximized. - static void SetMaximizeFirstWindow(bool maximize); - - protected: - friend class test::WindowPositionerTest; - - // Find a smart way to position the popup window. If there is no space this - // function will return an empty rectangle. - gfx::Rect SmartPopupPosition(const gfx::Rect& old_pos, - const gfx::Rect& work_area, - int grid); - - // Find the next available cascading popup position (on the given screen). - gfx::Rect NormalPopupPosition(const gfx::Rect& old_pos, - const gfx::Rect& work_area); - - // Align the location to the grid / snap to the right / bottom corner. - gfx::Rect AlignPopupPosition(const gfx::Rect &pos, - const gfx::Rect &work_area, - int grid); - - // Constant exposed for unittest. - static const int kMinimumWindowOffset; - - // The offset in X and Y for the next popup which opens. - int pop_position_offset_increment_x; - int pop_position_offset_increment_y; - - // The position on the screen for the first popup which gets shown if no - // empty space can be found. - int popup_position_offset_from_screen_corner_x; - int popup_position_offset_from_screen_corner_y; - - // The last used position. - int last_popup_position_x_; - int last_popup_position_y_; - - DISALLOW_COPY_AND_ASSIGN(WindowPositioner); -}; - -} // namespace ash - -#endif // ASH_WM_WINDOW_POSITIONER_H_ diff --git a/chromium/ash/wm/window_positioner_unittest.cc b/chromium/ash/wm/window_positioner_unittest.cc deleted file mode 100644 index 72ae6302eb4..00000000000 --- a/chromium/ash/wm/window_positioner_unittest.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2013 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/window_positioner.h" - -#include "ash/shell.h" -#include "ash/shell/toplevel_window.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_positioner.h" -#include "ash/wm/window_state.h" -#include "ui/aura/root_window.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { - -typedef test::AshTestBase WindowPositionerTest; - -TEST_F(WindowPositionerTest, OpenMaximizedWindowOnSecondDisplay) { - if (!SupportsMultipleDisplays()) - return; - UpdateDisplay("400x400,500x500"); - Shell::GetInstance()->set_target_root_window( - Shell::GetAllRootWindows()[1]); - shell::ToplevelWindow::CreateParams params; - params.can_resize = true; - params.can_maximize = true; - views::Widget* widget = - shell::ToplevelWindow::CreateToplevelWindow(params); - EXPECT_EQ("400,0 500x453", widget->GetWindowBoundsInScreen().ToString()); -} - -TEST_F(WindowPositionerTest, OpenDefaultWindowOnSecondDisplay) { - if (!SupportsMultipleDisplays()) - return; -#if defined(OS_WIN) - ash::WindowPositioner::SetMaximizeFirstWindow(true); -#endif - UpdateDisplay("400x400,1400x900"); - aura::Window* second_root_window = Shell::GetAllRootWindows()[1]; - Shell::GetInstance()->set_target_root_window( - second_root_window); - shell::ToplevelWindow::CreateParams params; - params.can_resize = true; - params.can_maximize = true; - views::Widget* widget = - shell::ToplevelWindow::CreateToplevelWindow(params); - gfx::Rect bounds = widget->GetWindowBoundsInScreen(); -#if defined(OS_WIN) - EXPECT_TRUE(widget->IsMaximized()); -#else - // The window should be in the 2nd display with the default size. - EXPECT_EQ("300x300", bounds.size().ToString()); -#endif - EXPECT_TRUE(Shell::GetScreen()->GetDisplayNearestWindow( - second_root_window).bounds().Contains(bounds)); -} - -namespace { - -// A WidgetDelegate that returns the out of display saved bounds. -class OutOfDisplayDelegate : public views::WidgetDelegate { - public: - explicit OutOfDisplayDelegate(views::Widget* widget) : widget_(widget) {} - virtual ~OutOfDisplayDelegate() {} - - // Overridden from WidgetDelegate: - virtual void DeleteDelegate() OVERRIDE { - delete this; - } - virtual views::Widget* GetWidget() OVERRIDE { - return widget_; - } - virtual const views::Widget* GetWidget() const OVERRIDE { - return widget_; - } - virtual bool GetSavedWindowPlacement( - const views::Widget* widget, - gfx::Rect* bounds, - ui::WindowShowState* show_state) const OVERRIDE { - bounds->SetRect(450, 10, 100, 100); - *show_state = ui::SHOW_STATE_NORMAL; - return true; - } - - private: - views::Widget* widget_; - - DISALLOW_COPY_AND_ASSIGN(OutOfDisplayDelegate); -}; - -} // namespace - -TEST_F(WindowPositionerTest, EnsureMinimumVisibility) { - if (!SupportsHostWindowResize()) - return; - - UpdateDisplay("400x400"); - views::Widget* widget = new views::Widget(); - views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); - params.delegate = new OutOfDisplayDelegate(widget); - params.context = Shell::GetPrimaryRootWindow(); - widget->Init(params); - widget->SetBounds(gfx::Rect(450,10, 100, 100)); - wm::GetWindowState(widget->GetNativeView())->set_minimum_visibility(true); - widget->Show(); - // Make sure the bounds is adjusted to be inside the work area. - EXPECT_EQ("390,10 100x100", widget->GetWindowBoundsInScreen().ToString()); - widget->CloseNow(); -} - -} // namespace diff --git a/chromium/ash/wm/window_properties.cc b/chromium/ash/wm/window_properties.cc deleted file mode 100644 index ced25b2a0be..00000000000 --- a/chromium/ash/wm/window_properties.cc +++ /dev/null @@ -1,19 +0,0 @@ -// 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/window_properties.h" - -#include "ash/wm/window_state.h" -#include "ui/aura/window_property.h" - -DECLARE_WINDOW_PROPERTY_TYPE(ash::wm::WindowState*); - -namespace ash { -namespace internal { -DEFINE_WINDOW_PROPERTY_KEY(bool, kStayInSameRootWindowKey, false); -DEFINE_WINDOW_PROPERTY_KEY(bool, kUsesScreenCoordinatesKey, false); -DEFINE_OWNED_WINDOW_PROPERTY_KEY(wm::WindowState, - kWindowStateKey, NULL); -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/window_properties.h b/chromium/ash/wm/window_properties.h deleted file mode 100644 index 74ae4952da2..00000000000 --- a/chromium/ash/wm/window_properties.h +++ /dev/null @@ -1,46 +0,0 @@ -// 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_WINDOW_PROPERTIES_H_ -#define ASH_WM_WINDOW_PROPERTIES_H_ - -#include "ash/ash_export.h" -#include "ui/base/ui_base_types.h" - -namespace aura { -class Window; - -template<typename T> -struct WindowProperty; -} - -namespace ash { -namespace wm { -class WindowState; -} // namespace wm -namespace internal { - -// Shell-specific window property keys. - -// Alphabetical sort. - -// If this is set to true, the window stays in the same root window -// even if the bounds outside of its root window is set. -// This is exported as it's used in the tests. -ASH_EXPORT extern const aura::WindowProperty<bool>* const - kStayInSameRootWindowKey; - -// Property to tell if the container uses the screen coordinates. -extern const aura::WindowProperty<bool>* const kUsesScreenCoordinatesKey; - -// A property key to store WindowState in the window. The window state -// is owned by the window. -extern const aura::WindowProperty<wm::WindowState*>* const kWindowStateKey; - -// Alphabetical sort. - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WINDOW_PROPERTIES_H_ diff --git a/chromium/ash/wm/window_resizer.cc b/chromium/ash/wm/window_resizer.cc deleted file mode 100644 index 372ce4889e0..00000000000 --- a/chromium/ash/wm/window_resizer.cc +++ /dev/null @@ -1,432 +0,0 @@ -// 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/window_resizer.h" - -#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/window_state.h" -#include "ash/wm/window_util.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_types.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/display.h" -#include "ui/gfx/screen.h" - -namespace ash { - -namespace { - -int GetPositionChangeDirectionForWindowComponent(int window_component) { - int pos_change_direction = WindowResizer::kBoundsChangeDirection_None; - switch (window_component) { - case HTTOPLEFT: - case HTBOTTOMRIGHT: - case HTGROWBOX: - case HTCAPTION: - pos_change_direction |= - WindowResizer::kBoundsChangeDirection_Horizontal | - WindowResizer::kBoundsChangeDirection_Vertical; - break; - case HTTOP: - case HTTOPRIGHT: - case HTBOTTOM: - pos_change_direction |= WindowResizer::kBoundsChangeDirection_Vertical; - break; - case HTBOTTOMLEFT: - case HTRIGHT: - case HTLEFT: - pos_change_direction |= WindowResizer::kBoundsChangeDirection_Horizontal; - break; - default: - break; - } - return pos_change_direction; -} - -int GetSizeChangeDirectionForWindowComponent(int window_component) { - int size_change_direction = WindowResizer::kBoundsChangeDirection_None; - switch (window_component) { - case HTTOPLEFT: - case HTTOPRIGHT: - case HTBOTTOMLEFT: - case HTBOTTOMRIGHT: - case HTGROWBOX: - case HTCAPTION: - size_change_direction |= - WindowResizer::kBoundsChangeDirection_Horizontal | - WindowResizer::kBoundsChangeDirection_Vertical; - break; - case HTTOP: - case HTBOTTOM: - size_change_direction |= WindowResizer::kBoundsChangeDirection_Vertical; - break; - case HTRIGHT: - case HTLEFT: - size_change_direction |= WindowResizer::kBoundsChangeDirection_Horizontal; - break; - default: - break; - } - return size_change_direction; -} - -// Returns true for resize components along the right edge, where a drag in -// positive x will make the window larger. -bool IsRightEdge(int window_component) { - return window_component == HTTOPRIGHT || - window_component == HTRIGHT || - window_component == HTBOTTOMRIGHT || - window_component == HTGROWBOX; -} - -} // namespace - -// static -const int WindowResizer::kBoundsChange_None = 0; -// static -const int WindowResizer::kBoundsChange_Repositions = 1; -// static -const int WindowResizer::kBoundsChange_Resizes = 2; - -// static -const int WindowResizer::kBoundsChangeDirection_None = 0; -// static -const int WindowResizer::kBoundsChangeDirection_Horizontal = 1; -// static -const int WindowResizer::kBoundsChangeDirection_Vertical = 2; - -WindowResizer::Details::Details() - : window(NULL), - window_state(NULL), - window_component(HTNOWHERE), - bounds_change(0), - position_change_direction(0), - size_change_direction(0), - is_resizable(false), - source(aura::client::WINDOW_MOVE_SOURCE_MOUSE) { -} - -WindowResizer::Details::Details(aura::Window* window, - const gfx::Point& location, - int window_component, - aura::client::WindowMoveSource source) - : window(window), - window_state(wm::GetWindowState(window)), - initial_bounds_in_parent(window->bounds()), - restore_bounds(gfx::Rect()), - initial_location_in_parent(location), - initial_opacity(window->layer()->opacity()), - window_component(window_component), - bounds_change(GetBoundsChangeForWindowComponent(window_component)), - position_change_direction( - GetPositionChangeDirectionForWindowComponent(window_component)), - size_change_direction( - GetSizeChangeDirectionForWindowComponent(window_component)), - is_resizable(bounds_change != kBoundsChangeDirection_None), - source(source) { - if (window_state->IsNormalShowState() && - window_state->HasRestoreBounds() && - window_component == HTCAPTION) - restore_bounds = window_state->GetRestoreBoundsInScreen(); -} - -WindowResizer::Details::~Details() { -} - -WindowResizer::WindowResizer() { -} - -WindowResizer::~WindowResizer() { -} - -// static -int WindowResizer::GetBoundsChangeForWindowComponent(int component) { - int bounds_change = WindowResizer::kBoundsChange_None; - switch (component) { - case HTTOPLEFT: - case HTTOP: - case HTTOPRIGHT: - case HTLEFT: - case HTBOTTOMLEFT: - bounds_change |= WindowResizer::kBoundsChange_Repositions | - WindowResizer::kBoundsChange_Resizes; - break; - case HTCAPTION: - bounds_change |= WindowResizer::kBoundsChange_Repositions; - break; - case HTRIGHT: - case HTBOTTOMRIGHT: - case HTBOTTOM: - case HTGROWBOX: - bounds_change |= WindowResizer::kBoundsChange_Resizes; - break; - default: - break; - } - return bounds_change; -} - -// static -gfx::Rect WindowResizer::CalculateBoundsForDrag( - const Details& details, - const gfx::Point& passed_location) { - if (!details.is_resizable) - return details.initial_bounds_in_parent; - - gfx::Point location = passed_location; - int delta_x = location.x() - details.initial_location_in_parent.x(); - int delta_y = location.y() - details.initial_location_in_parent.y(); - - AdjustDeltaForTouchResize(details, &delta_x, &delta_y); - - // The minimize size constraint may limit how much we change the window - // position. For example, dragging the left edge to the right should stop - // repositioning the window when the minimize size is reached. - gfx::Size size = GetSizeForDrag(details, &delta_x, &delta_y); - gfx::Point origin = GetOriginForDrag(details, delta_x, delta_y); - gfx::Rect new_bounds(origin, size); - - // Sizing has to keep the result on the screen. Note that this correction - // has to come first since it might have an impact on the origin as well as - // on the size. - 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); - if (details.size_change_direction & kBoundsChangeDirection_Horizontal) { - if (IsRightEdge(details.window_component) && - new_bounds.right() < work_area.x() + kMinimumOnScreenArea) { - int delta = work_area.x() + kMinimumOnScreenArea - new_bounds.right(); - new_bounds.set_width(new_bounds.width() + delta); - } else if (new_bounds.x() > work_area.right() - kMinimumOnScreenArea) { - int width = new_bounds.right() - work_area.right() + - kMinimumOnScreenArea; - new_bounds.set_x(work_area.right() - kMinimumOnScreenArea); - new_bounds.set_width(width); - } - } - if (details.size_change_direction & kBoundsChangeDirection_Vertical) { - if (!IsBottomEdge(details.window_component) && - new_bounds.y() > work_area.bottom() - kMinimumOnScreenArea) { - int height = new_bounds.bottom() - work_area.bottom() + - kMinimumOnScreenArea; - new_bounds.set_y(work_area.bottom() - kMinimumOnScreenArea); - new_bounds.set_height(height); - } else if (details.window_component == HTBOTTOM || - details.window_component == HTBOTTOMRIGHT || - details.window_component == HTBOTTOMLEFT) { - // Update bottom edge to stay in the work area when we are resizing - // by dragging the bottom edge or corners. - if (new_bounds.bottom() > work_area.bottom()) - new_bounds.Inset(0, 0, 0, - new_bounds.bottom() - work_area.bottom()); - } - } - if (details.bounds_change & kBoundsChange_Repositions && - new_bounds.y() < 0) { - int delta = new_bounds.y(); - new_bounds.set_y(0); - new_bounds.set_height(new_bounds.height() + delta); - } - } - - if (details.bounds_change & kBoundsChange_Repositions) { - // When we might want to reposition a window which is also restored to its - // previous size, to keep the cursor within the dragged window. - if (!details.restore_bounds.IsEmpty()) { - // However - it is not desirable to change the origin if the window would - // be still hit by the cursor. - if (details.initial_location_in_parent.x() > - details.initial_bounds_in_parent.x() + details.restore_bounds.width()) - new_bounds.set_x(location.x() - details.restore_bounds.width() / 2); - } - - // Make sure that |new_bounds| doesn't leave any of the displays. Note that - // the |work_area| above isn't good for this check since it is the work area - // for the current display but the window can move to a different one. - aura::Window* parent = details.window->parent(); - gfx::Point passed_location_in_screen(passed_location); - wm::ConvertPointToScreen(parent, &passed_location_in_screen); - gfx::Rect near_passed_location(passed_location_in_screen, gfx::Size()); - // Use a pointer location (matching the logic in DragWindowResizer) to - // calculate the target display after the drag. - const gfx::Display& display = - Shell::GetScreen()->GetDisplayMatching(near_passed_location); - aura::Window* dock_container = Shell::GetContainer( - wm::GetRootWindowMatching(near_passed_location), - 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); - gfx::Rect new_bounds_in_screen = - ScreenAsh::ConvertRectToScreen(parent, new_bounds); - if (!screen_work_area.Intersects(new_bounds_in_screen)) { - // Make sure that the x origin does not leave the current display. - new_bounds_in_screen.set_x( - std::max(screen_work_area.x() - new_bounds.width(), - std::min(screen_work_area.right(), - new_bounds_in_screen.x()))); - new_bounds = - ScreenAsh::ConvertRectFromScreen(parent, new_bounds_in_screen); - } - } - - return new_bounds; -} - -// static -bool WindowResizer::IsBottomEdge(int window_component) { - return window_component == HTBOTTOMLEFT || - window_component == HTBOTTOM || - window_component == HTBOTTOMRIGHT || - window_component == HTGROWBOX; -} - -// static -void WindowResizer::AdjustDeltaForTouchResize(const Details& details, - int* delta_x, - int* delta_y) { - if (details.source != aura::client::WINDOW_MOVE_SOURCE_TOUCH || - !(details.bounds_change & kBoundsChange_Resizes)) - return; - - if (details.size_change_direction & kBoundsChangeDirection_Horizontal) { - if (IsRightEdge(details.window_component)) { - *delta_x += details.initial_location_in_parent.x() - - details.initial_bounds_in_parent.right(); - } else { - *delta_x += details.initial_location_in_parent.x() - - details.initial_bounds_in_parent.x(); - } - } - if (details.size_change_direction & kBoundsChangeDirection_Vertical) { - if (IsBottomEdge(details.window_component)) { - *delta_y += details.initial_location_in_parent.y() - - details.initial_bounds_in_parent.bottom(); - } else { - *delta_y += details.initial_location_in_parent.y() - - details.initial_bounds_in_parent.y(); - } - } -} - -// static -gfx::Point WindowResizer::GetOriginForDrag(const Details& details, - int delta_x, - int delta_y) { - gfx::Point origin = details.initial_bounds_in_parent.origin(); - if (details.bounds_change & kBoundsChange_Repositions) { - int pos_change_direction = - GetPositionChangeDirectionForWindowComponent(details.window_component); - if (pos_change_direction & kBoundsChangeDirection_Horizontal) - origin.Offset(delta_x, 0); - if (pos_change_direction & kBoundsChangeDirection_Vertical) - origin.Offset(0, delta_y); - } - return origin; -} - -// static -gfx::Size WindowResizer::GetSizeForDrag(const Details& details, - int* delta_x, - int* delta_y) { - gfx::Size size = details.initial_bounds_in_parent.size(); - if (details.bounds_change & kBoundsChange_Resizes) { - gfx::Size min_size = details.window->delegate()->GetMinimumSize(); - size.SetSize(GetWidthForDrag(details, min_size.width(), delta_x), - GetHeightForDrag(details, min_size.height(), delta_y)); - } else if (!details.restore_bounds.IsEmpty()) { - size = details.restore_bounds.size(); - } - return size; -} - -// static -int WindowResizer::GetWidthForDrag(const Details& details, - int min_width, - int* delta_x) { - int width = details.initial_bounds_in_parent.width(); - if (details.size_change_direction & kBoundsChangeDirection_Horizontal) { - // Along the right edge, positive delta_x increases the window size. - int x_multiplier = IsRightEdge(details.window_component) ? 1 : -1; - width += x_multiplier * (*delta_x); - - // Ensure we don't shrink past the minimum width and clamp delta_x - // for the window origin computation. - if (width < min_width) { - width = min_width; - *delta_x = -x_multiplier * (details.initial_bounds_in_parent.width() - - min_width); - } - - // And don't let the window go bigger than the display. - int max_width = Shell::GetScreen()->GetDisplayNearestWindow( - details.window).bounds().width(); - gfx::Size max_size = details.window->delegate()->GetMaximumSize(); - if (max_size.width() != 0) - max_width = std::min(max_width, max_size.width()); - if (width > max_width) { - width = max_width; - *delta_x = -x_multiplier * (details.initial_bounds_in_parent.width() - - max_width); - } - } - return width; -} - -// static -int WindowResizer::GetHeightForDrag(const Details& details, - int min_height, - int* delta_y) { - int height = details.initial_bounds_in_parent.height(); - if (details.size_change_direction & kBoundsChangeDirection_Vertical) { - // Along the bottom edge, positive delta_y increases the window size. - int y_multiplier = IsBottomEdge(details.window_component) ? 1 : -1; - height += y_multiplier * (*delta_y); - - // Ensure we don't shrink past the minimum height and clamp delta_y - // for the window origin computation. - if (height < min_height) { - height = min_height; - *delta_y = -y_multiplier * (details.initial_bounds_in_parent.height() - - min_height); - } - - // And don't let the window go bigger than the display. - int max_height = Shell::GetScreen()->GetDisplayNearestWindow( - details.window).bounds().height(); - gfx::Size max_size = details.window->delegate()->GetMaximumSize(); - if (max_size.height() != 0) - max_height = std::min(max_height, max_size.height()); - if (height > max_height) { - height = max_height; - *delta_y = -y_multiplier * (details.initial_bounds_in_parent.height() - - max_height); - } - } - return height; -} - -} // namespace aura diff --git a/chromium/ash/wm/window_resizer.h b/chromium/ash/wm/window_resizer.h deleted file mode 100644 index 29479b3266f..00000000000 --- a/chromium/ash/wm/window_resizer.h +++ /dev/null @@ -1,157 +0,0 @@ -// 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_WINDOW_RESIZER_H_ -#define ASH_WM_WINDOW_RESIZER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/client/window_move_client.h" -#include "ui/gfx/rect.h" - -namespace aura { -class Window; -} - -namespace ash { -namespace wm { -class WindowState; -} - -// WindowResizer is used by ToplevelWindowEventFilter to handle dragging, moving -// or resizing a window. All coordinates passed to this are in the parent -// windows coordinates. -class ASH_EXPORT WindowResizer { - public: - // Constants to identify the type of resize. - static const int kBoundsChange_None; - static const int kBoundsChange_Repositions; - static const int kBoundsChange_Resizes; - - // Used to indicate which direction the resize occurs in. - static const int kBoundsChangeDirection_None; - static const int kBoundsChangeDirection_Horizontal; - static const int kBoundsChangeDirection_Vertical; - - WindowResizer(); - virtual ~WindowResizer(); - - // Returns a bitmask of the kBoundsChange_ values. - static int GetBoundsChangeForWindowComponent(int component); - - // Invoked to drag/move/resize the window. |location| is in the coordinates - // of the window supplied to the constructor. |event_flags| is the event - // flags from the event. - virtual void Drag(const gfx::Point& location, int event_flags) = 0; - - // Invoked to complete the drag. - virtual void CompleteDrag(int event_flags) = 0; - - // Reverts the drag. - virtual void RevertDrag() = 0; - - // Returns the target window the resizer was created for. - virtual aura::Window* GetTarget() = 0; - - // See comment for |Details::initial_location_in_parent|. - virtual const gfx::Point& GetInitialLocation() const = 0; - - protected: - struct Details { - Details(); - Details(aura::Window* window, - const gfx::Point& location, - int window_component, - aura::client::WindowMoveSource source); - ~Details(); - - // The window we're resizing. - // TODO(oshima): replace this with accessor method to - // |window_state->window()|. - aura::Window* window; - - // The ash window state for the |window| above. - wm::WindowState* window_state; - - // Initial bounds of the window in parent coordinates. - gfx::Rect initial_bounds_in_parent; - - // Restore bounds (in screen coordinates) of the window before the drag - // started. Only set if the window is normal and is being dragged. - gfx::Rect restore_bounds; - - // Location passed to the constructor, in |window->parent()|'s coordinates. - gfx::Point initial_location_in_parent; - - // Initial opacity of the window. - float initial_opacity; - - // The component the user pressed on. - int window_component; - - // Bitmask of the |kBoundsChange_| constants. - int bounds_change; - - // Bitmask of the |kBoundsChangeDirection_| constants. - int position_change_direction; - - // Bitmask of the |kBoundsChangeDirection_| constants. - int size_change_direction; - - // Will the drag actually modify the window? - bool is_resizable; - - // Source of the event initiating the drag. - aura::client::WindowMoveSource source; - }; - - static gfx::Rect CalculateBoundsForDrag(const Details& details, - const gfx::Point& location); - - static gfx::Rect AdjustBoundsToGrid(const gfx::Rect& bounds, - int grid_size); - - static bool IsBottomEdge(int component); - - private: - // In case of touch resizing, adjusts deltas so that the border is positioned - // just under the touch point. - static void AdjustDeltaForTouchResize(const Details& details, - int* delta_x, - int* delta_y); - - // Returns the new origin of the window. The arguments are the difference - // between the current location and the initial location. - static gfx::Point GetOriginForDrag(const Details& details, - int delta_x, - int delta_y); - - // Returns the size of the window for the drag. - static gfx::Size GetSizeForDrag(const Details& details, - int* delta_x, - int* delta_y); - - // Returns the width of the window. - static int GetWidthForDrag(const Details& details, - int min_width, - int* delta_x); - - // Returns the height of the drag. - static int GetHeightForDrag(const Details& details, - int min_height, - int* delta_y); -}; - -// Creates a WindowResizer for |window|. This can return a scoped_ptr -// initialized with NULL if |window| should not be resized nor dragged. -ASH_EXPORT scoped_ptr<WindowResizer> CreateWindowResizer( - aura::Window* window, - const gfx::Point& point_in_parent, - int window_component, - aura::client::WindowMoveSource source); - -} // namespace ash - -#endif // ASH_WM_WINDOW_RESIZER_H_ diff --git a/chromium/ash/wm/window_state.cc b/chromium/ash/wm/window_state.cc deleted file mode 100644 index 4bc1484f9b8..00000000000 --- a/chromium/ash/wm/window_state.cc +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2013 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/window_state.h" - -#include "ash/ash_switches.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/window_properties.h" -#include "ash/wm/window_state_delegate.h" -#include "ash/wm/window_state_observer.h" -#include "ash/wm/window_util.h" -#include "ash/wm/wm_types.h" -#include "base/auto_reset.h" -#include "base/command_line.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/gfx/display.h" -#include "ui/views/corewm/window_util.h" - -namespace ash { -namespace wm { - -// static -bool WindowState::IsMaximizedOrFullscreenState(ui::WindowShowState show_state) { - return show_state == ui::SHOW_STATE_FULLSCREEN || - show_state == ui::SHOW_STATE_MAXIMIZED; -} - -WindowState::WindowState(aura::Window* window) - : window_(window), - window_position_managed_(false), - bounds_changed_by_user_(false), - panel_attached_(true), - continue_drag_after_reparent_(false), - ignored_by_shelf_(false), - can_consume_system_keys_(false), - top_row_keys_are_function_keys_(false), - window_resizer_(NULL), - always_restores_to_restore_bounds_(false), - hide_shelf_when_fullscreen_(true), - animate_to_fullscreen_(true), - minimum_visibility_(false), - in_set_window_show_type_(false), - window_show_type_(ToWindowShowType(GetShowState())) { - window_->AddObserver(this); - -#if defined(OS_CHROMEOS) - // NOTE(pkotwicz): Animating to immersive fullscreen does not look good. When - // the kAshEnableImmersiveFullscreenForAllWindows flag is set most windows - // can be put into immersive fullscreen. It is not worth the added complexity - // to only animate to fullscreen if the window is put into immersive - // fullscreen. - animate_to_fullscreen_ = !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshEnableImmersiveFullscreenForAllWindows); -#endif -} - -WindowState::~WindowState() { -} - -bool WindowState::HasDelegate() const { - return delegate_; -} - -void WindowState::SetDelegate(scoped_ptr<WindowStateDelegate> delegate) { - DCHECK(!delegate_.get()); - delegate_ = delegate.Pass(); -} - -ui::WindowShowState WindowState::GetShowState() const { - return window_->GetProperty(aura::client::kShowStateKey); -} - -bool WindowState::IsMinimized() const { - return GetShowState() == ui::SHOW_STATE_MINIMIZED; -} - -bool WindowState::IsMaximized() const { - return GetShowState() == ui::SHOW_STATE_MAXIMIZED; -} - -bool WindowState::IsFullscreen() const { - return GetShowState() == ui::SHOW_STATE_FULLSCREEN; -} - -bool WindowState::IsMaximizedOrFullscreen() const { - return IsMaximizedOrFullscreenState(GetShowState()); -} - -bool WindowState::IsNormalShowState() const { - ui::WindowShowState state = window_->GetProperty(aura::client::kShowStateKey); - return state == ui::SHOW_STATE_NORMAL || state == ui::SHOW_STATE_DEFAULT; -} - -bool WindowState::IsActive() const { - return IsActiveWindow(window_); -} - -bool WindowState::IsDocked() const { - return window_->parent() && - window_->parent()->id() == internal::kShellWindowId_DockedContainer; -} - -bool WindowState::IsSnapped() const { - return window_show_type_ == SHOW_TYPE_LEFT_SNAPPED || - window_show_type_ == SHOW_TYPE_RIGHT_SNAPPED; -} - -bool WindowState::CanMaximize() const { - return window_->GetProperty(aura::client::kCanMaximizeKey); -} - -bool WindowState::CanMinimize() const { - internal::RootWindowController* controller = - internal::RootWindowController::ForWindow(window_); - if (!controller) - return false; - aura::Window* lockscreen = controller->GetContainer( - internal::kShellWindowId_LockScreenContainersContainer); - if (lockscreen->Contains(window_)) - return false; - - return true; -} - -bool WindowState::CanResize() const { - return window_->GetProperty(aura::client::kCanResizeKey); -} - -bool WindowState::CanActivate() const { - return views::corewm::CanActivateWindow(window_); -} - -bool WindowState::CanSnap() const { - if (!CanResize() || - window_->type() == aura::client::WINDOW_TYPE_PANEL || - window_->transient_parent()) - return false; - // If a window has a maximum size defined, snapping may make it too big. - return window_->delegate() ? window_->delegate()->GetMaximumSize().IsEmpty() : - true; -} - -bool WindowState::HasRestoreBounds() const { - return window_->GetProperty(aura::client::kRestoreBoundsKey) != NULL; -} - -void WindowState::Maximize() { - window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); -} - -void WindowState::SnapLeft(const gfx::Rect& bounds) { - SnapWindow(SHOW_TYPE_LEFT_SNAPPED, bounds); -} - -void WindowState::SnapRight(const gfx::Rect& bounds) { - SnapWindow(SHOW_TYPE_RIGHT_SNAPPED, bounds); -} - -void WindowState::Minimize() { - window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); -} - -void WindowState::Unminimize() { - window_->SetProperty( - aura::client::kShowStateKey, - window_->GetProperty(aura::client::kRestoreShowStateKey)); - window_->ClearProperty(aura::client::kRestoreShowStateKey); -} - -void WindowState::Activate() { - ActivateWindow(window_); -} - -void WindowState::Deactivate() { - DeactivateWindow(window_); -} - -void WindowState::Restore() { - window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); -} - -void WindowState::ToggleMaximized() { - if (IsMaximized()) - Restore(); - else if (CanMaximize()) - Maximize(); -} - -void WindowState::ToggleFullscreen() { - // Window which cannot be maximized should not be fullscreened. - // It can, however, be restored if it was fullscreened. - bool is_fullscreen = IsFullscreen(); - if (!is_fullscreen && !CanMaximize()) - return; - if (delegate_ && delegate_->ToggleFullscreen(this)) - return; - if (is_fullscreen) { - Restore(); - } else { - window_->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - } -} - -void WindowState::SetBoundsInScreen( - const gfx::Rect& bounds_in_screen) { - gfx::Rect bounds_in_parent = - ScreenAsh::ConvertRectFromScreen(window_->parent(), - bounds_in_screen); - window_->SetBounds(bounds_in_parent); -} - -void WindowState::SaveCurrentBoundsForRestore() { - gfx::Rect bounds_in_screen = - ScreenAsh::ConvertRectToScreen(window_->parent(), - window_->bounds()); - SetRestoreBoundsInScreen(bounds_in_screen); -} - -gfx::Rect WindowState::GetRestoreBoundsInScreen() const { - return *window_->GetProperty(aura::client::kRestoreBoundsKey); -} - -gfx::Rect WindowState::GetRestoreBoundsInParent() const { - return ScreenAsh::ConvertRectFromScreen(window_->parent(), - GetRestoreBoundsInScreen()); -} - -void WindowState::SetRestoreBoundsInScreen(const gfx::Rect& bounds) { - window_->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds)); -} - -void WindowState::SetRestoreBoundsInParent(const gfx::Rect& bounds) { - SetRestoreBoundsInScreen( - ScreenAsh::ConvertRectToScreen(window_->parent(), bounds)); -} - -void WindowState::ClearRestoreBounds() { - window_->ClearProperty(aura::client::kRestoreBoundsKey); -} - -void WindowState::SetPreAutoManageWindowBounds( - const gfx::Rect& bounds) { - pre_auto_manage_window_bounds_.reset(new gfx::Rect(bounds)); -} - -void WindowState::AddObserver(WindowStateObserver* observer) { - observer_list_.AddObserver(observer); -} - -void WindowState::RemoveObserver(WindowStateObserver* observer) { - observer_list_.RemoveObserver(observer); -} - -void WindowState::OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) { - DCHECK_EQ(window, window_); - if (key == aura::client::kShowStateKey) - SetWindowShowType(ToWindowShowType(GetShowState())); -} - -void WindowState::SnapWindow(WindowShowType left_or_right, - const gfx::Rect& bounds) { - if (window_show_type_ == left_or_right) { - window_->SetBounds(bounds); - return; - } - - // Compute the bounds that the window will restore to. If the window does not - // already have restore bounds, it will be restored (when un-snapped) to the - // last bounds that it had before getting snapped. - gfx::Rect restore_bounds_in_screen(HasRestoreBounds() ? - GetRestoreBoundsInScreen() : window_->GetBoundsInScreen()); - // Set the window's restore bounds so that WorkspaceLayoutManager knows - // which width to use when the snapped window is moved to the edge. - SetRestoreBoundsInParent(bounds); - - bool was_maximized = IsMaximizedOrFullscreen(); - // Before we can set the bounds we need to restore the window. - // Restoring the window will set the window to its restored bounds set above. - // Restore will cause OnWindowPropertyChanged() so it needs to be done - // before notifying that the WindowShowType has changed to |left_or_right|. - if (was_maximized) - Restore(); - DCHECK(left_or_right == SHOW_TYPE_LEFT_SNAPPED || - left_or_right == SHOW_TYPE_RIGHT_SNAPPED); - SetWindowShowType(left_or_right); - // TODO(varkha): Ideally the bounds should be changed in a LayoutManager upon - // observing the WindowShowType change. - // If the window is a child of kShellWindowId_DockedContainer such as during - // a drag, the window's bounds are not set in - // WorkspaceLayoutManager::OnWindowShowTypeChanged(). Set them here. Skip - // setting the bounds otherwise to avoid stopping the slide animation which - // was started as a result of OnWindowShowTypeChanged(). - if (IsDocked()) - window_->SetBounds(bounds); - SetRestoreBoundsInScreen(restore_bounds_in_screen); -} - -void WindowState::SetWindowShowType(WindowShowType new_window_show_type) { - if (in_set_window_show_type_) - return; - base::AutoReset<bool> resetter(&in_set_window_show_type_, true); - - ui::WindowShowState new_window_state = - ToWindowShowState(new_window_show_type); - if (new_window_state != GetShowState()) - window_->SetProperty(aura::client::kShowStateKey, new_window_state); - WindowShowType old_window_show_type = window_show_type_; - window_show_type_ = new_window_show_type; - if (old_window_show_type != window_show_type_) { - FOR_EACH_OBSERVER(WindowStateObserver, observer_list_, - OnWindowShowTypeChanged(this, old_window_show_type)); - } -} - -WindowState* GetActiveWindowState() { - aura::Window* active = GetActiveWindow(); - return active ? GetWindowState(active) : NULL; -} - -WindowState* GetWindowState(aura::Window* window) { - if (!window) - return NULL; - WindowState* settings = window->GetProperty(internal::kWindowStateKey); - if(!settings) { - settings = new WindowState(window); - window->SetProperty(internal::kWindowStateKey, settings); - } - return settings; -} - -const WindowState* GetWindowState(const aura::Window* window) { - return GetWindowState(const_cast<aura::Window*>(window)); -} - -} // namespace wm -} // namespace ash diff --git a/chromium/ash/wm/window_state.h b/chromium/ash/wm/window_state.h deleted file mode 100644 index 618349c86d6..00000000000 --- a/chromium/ash/wm/window_state.h +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright 2013 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_WINDOW_STATE_H_ -#define ASH_WM_WINDOW_STATE_H_ - -#include "ash/ash_export.h" -#include "ash/wm/wm_types.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "ui/aura/window_observer.h" -#include "ui/base/ui_base_types.h" - -namespace aura { -class Window; -} - -namespace gfx { -class Rect; -} - -namespace ash { -class WindowResizer; - -namespace wm { -class WindowStateDelegate; -class WindowStateObserver; - -// WindowState manages and defines ash specific window state and -// behavior. Ash specific per-window state (such as ones that controls -// window manager behavior) and ash specific window behavior (such as -// maximize, minimize, snap sizing etc) should be added here instead -// of defining separate functions (like |MaximizeWindow(aura::Window* -// window)|) or using aura Window property. -// The WindowState gets created when first accessed by -// |wm::GetWindowState|, and deleted when the window is deleted. -// Prefer using this class instead of passing aura::Window* around in -// ash code as this is often what you need to interact with, and -// accessing the window using |window()| is cheap. -class ASH_EXPORT WindowState : public aura::WindowObserver { - public: - static bool IsMaximizedOrFullscreenState(ui::WindowShowState state); - - explicit WindowState(aura::Window* window); - virtual ~WindowState(); - - aura::Window* window() { return window_; } - const aura::Window* window() const { return window_; } - - bool HasDelegate() const; - void SetDelegate(scoped_ptr<WindowStateDelegate> delegate); - - // Returns the window's current show state. - ui::WindowShowState GetShowState() const; - - // Returns the window's current ash show type. - // Refer to WindowShowType definition in wm_types.h as for why Ash - // has its own show type. - WindowShowType window_show_type() const { return window_show_type_; } - - // Predicates to check window state. - bool IsMinimized() const; - bool IsMaximized() const; - bool IsFullscreen() const; - bool IsMaximizedOrFullscreen() const; - // True if the window's show state is SHOW_STATE_NORMAL or - // SHOW_STATE_DEFAULT. - bool IsNormalShowState() const; - bool IsActive() const; - bool IsDocked() const; - bool IsSnapped() const; - - // Checks if the window can change its state accordingly. - bool CanMaximize() const; - bool CanMinimize() const; - bool CanResize() const; - bool CanSnap() const; - bool CanActivate() const; - - // Returns true if the window has restore bounds. - bool HasRestoreBounds() const; - - void Maximize(); - void Minimize(); - void Unminimize(); - void Activate(); - void Deactivate(); - void Restore(); - void ToggleMaximized(); - void ToggleFullscreen(); - void SnapLeft(const gfx::Rect& bounds); - void SnapRight(const gfx::Rect& bounds); - - // Sets the window's bounds in screen coordinates. - void SetBoundsInScreen(const gfx::Rect& bounds_in_screen); - - // Saves the current bounds to be used as a restore bounds. - void SaveCurrentBoundsForRestore(); - - // Same as |GetRestoreBoundsInScreen| except that it returns the - // bounds in the parent's coordinates. - gfx::Rect GetRestoreBoundsInParent() const; - - // Returns the restore bounds property on the window in the virtual screen - // coordinates. The bounds can be NULL if the bounds property does not - // exist for the window. The window owns the bounds object. - gfx::Rect GetRestoreBoundsInScreen() const; - - // Same as |SetRestoreBoundsInScreen| except that the bounds is in the - // parent's coordinates. - void SetRestoreBoundsInParent(const gfx::Rect& bounds_in_parent); - - // Sets the restore bounds property on the window in the virtual screen - // coordinates. Deletes existing bounds value if exists. - void SetRestoreBoundsInScreen(const gfx::Rect& bounds_in_screen); - - // Deletes and clears the restore bounds property on the window. - void ClearRestoreBounds(); - - // Sets whether the window should always be restored to the restore bounds - // (sometimes the workspace layout manager restores the window to its original - // bounds instead of the restore bounds. Setting this key overrides that - // behaviour). The flag is reset to the default value after the window is - // restored. - bool always_restores_to_restore_bounds() const { - return always_restores_to_restore_bounds_; - } - void set_always_restores_to_restore_bounds(bool value) { - always_restores_to_restore_bounds_ = value; - } - - // Gets/sets whether the shelf should be hidden when this window is - // fullscreen. - bool hide_shelf_when_fullscreen() const { - return hide_shelf_when_fullscreen_; - } - - void set_hide_shelf_when_fullscreen(bool value) { - hide_shelf_when_fullscreen_ = value; - } - - // Sets/gets the flag to suppress the cross-fade animation for - // the transition to the fullscreen state. - bool animate_to_fullscreen() const { - return animate_to_fullscreen_; - } - void set_animate_to_fullscreen(bool value) { - animate_to_fullscreen_ = value; - } - - // If the minimum visibilty is true, ash will try to keep a - // minimum amount of the window is always visible on the work area - // when shown. - // TODO(oshima): Consolidate this and window_position_managed - // into single parameter to control the window placement. - bool minimum_visibility() const { - return minimum_visibility_; - } - void set_minimum_visibility(bool minimum_visibility) { - minimum_visibility_ = minimum_visibility; - } - - // Gets/Sets the bounds of the window before it was moved by the auto window - // management. As long as it was not auto-managed, it will return NULL. - const gfx::Rect* pre_auto_manage_window_bounds() const { - return pre_auto_manage_window_bounds_.get(); - } - void SetPreAutoManageWindowBounds(const gfx::Rect& bounds); - - // Layout related properties - - void AddObserver(WindowStateObserver* observer); - void RemoveObserver(WindowStateObserver* observer); - - // Whether the window is being dragged. - bool is_dragged() const { return !!window_resizer_; } - - // Whether or not the window's position can be managed by the - // auto management logic. - bool window_position_managed() const { return window_position_managed_; } - void set_window_position_managed(bool window_position_managed) { - window_position_managed_ = window_position_managed; - } - - // Whether or not the window's position or size was changed by a user. - bool bounds_changed_by_user() const { return bounds_changed_by_user_; } - void set_bounds_changed_by_user(bool bounds_changed_by_user) { - bounds_changed_by_user_ = bounds_changed_by_user; - } - - // True if this window is an attached panel. - bool panel_attached() const { - return panel_attached_; - } - void set_panel_attached(bool panel_attached) { - panel_attached_ = panel_attached; - } - - // Indicates that an in progress drag should be continued after the - // window is reparented to another container. - bool continue_drag_after_reparent() const { - return continue_drag_after_reparent_; - } - void set_continue_drag_after_reparent(bool value) { - continue_drag_after_reparent_ = value; - } - - // True if the window is ignored by the shelf layout manager for - // purposes of darkening the shelf. - bool ignored_by_shelf() const { return ignored_by_shelf_; } - void set_ignored_by_shelf(bool ignored_by_shelf) { - ignored_by_shelf_ = ignored_by_shelf; - } - - // True if the window should be offered a chance to consume special system - // keys such as brightness, volume, etc. that are usually handled by the - // shell. - bool can_consume_system_keys() const { return can_consume_system_keys_; } - void set_can_consume_system_keys(bool can_consume_system_keys) { - can_consume_system_keys_ = can_consume_system_keys; - } - - // True if this window has requested that the top-row keys (back, forward, - // brightness, volume) should be treated as function keys. - bool top_row_keys_are_function_keys() const { - return top_row_keys_are_function_keys_; - } - void set_top_row_keys_are_function_keys(bool value) { - top_row_keys_are_function_keys_ = value; - } - - // Returns or sets a pointer to WindowResizer when resizing is active. - // The pointer to a WindowResizer that is returned is set when a resizer gets - // created and cleared when it gets destroyed. WindowState does not own the - // |window_resizer_| instance and the resizer's lifetime is controlled - // externally. It can be used to avoid creating multiple instances of a - // WindowResizer for the same window. - WindowResizer* window_resizer() const { - return window_resizer_; - } - void set_window_resizer_(WindowResizer* window_resizer) { - window_resizer_ = window_resizer; - } - - // aura::WindowObserver overrides: - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE; - - private: - // Snaps the window to left or right of the desktop with given bounds. - void SnapWindow(WindowShowType left_or_right, - const gfx::Rect& bounds); - - // Sets the window show type and updates the show state if necessary. - void SetWindowShowType(WindowShowType new_window_show_type); - - // The owner of this window settings. - aura::Window* window_; - scoped_ptr<WindowStateDelegate> delegate_; - - bool window_position_managed_; - bool bounds_changed_by_user_; - bool panel_attached_; - bool continue_drag_after_reparent_; - bool ignored_by_shelf_; - bool can_consume_system_keys_; - bool top_row_keys_are_function_keys_; - WindowResizer* window_resizer_; - - bool always_restores_to_restore_bounds_; - bool hide_shelf_when_fullscreen_; - bool animate_to_fullscreen_; - bool minimum_visibility_; - - // A property to remember the window position which was set before the - // auto window position manager changed the window bounds, so that it can get - // restored when only this one window gets shown. - scoped_ptr<gfx::Rect> pre_auto_manage_window_bounds_; - - ObserverList<WindowStateObserver> observer_list_; - - // True when in SetWindowShowType(). This is used to avoid reentrance. - bool in_set_window_show_type_; - - WindowShowType window_show_type_; - - DISALLOW_COPY_AND_ASSIGN(WindowState); -}; - -// Returns the WindowState for active window. Returns |NULL| -// if there is no active window. -ASH_EXPORT WindowState* GetActiveWindowState(); - -// Returns the WindowState for |window|. Creates WindowState -// if it didn't exist. The settings object is owned by |window|. -ASH_EXPORT WindowState* GetWindowState(aura::Window* window); - -// const version of GetWindowState. -ASH_EXPORT const WindowState* -GetWindowState(const aura::Window* window); - -} // namespace wm -} // namespace ash - -#endif // ASH_WM_WINDOW_STATE_H_ diff --git a/chromium/ash/wm/window_state_delegate.cc b/chromium/ash/wm/window_state_delegate.cc deleted file mode 100644 index 00040735ea4..00000000000 --- a/chromium/ash/wm/window_state_delegate.cc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 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/window_state_delegate.h" - -namespace ash { -namespace wm { - -WindowStateDelegate::WindowStateDelegate() { -} - -WindowStateDelegate::~WindowStateDelegate() { -} - -bool WindowStateDelegate::ToggleFullscreen(WindowState* window_state) { - return false; -} - -} // namespace wm -} // namespace ash diff --git a/chromium/ash/wm/window_state_delegate.h b/chromium/ash/wm/window_state_delegate.h deleted file mode 100644 index 53badcf415e..00000000000 --- a/chromium/ash/wm/window_state_delegate.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 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_WINDOW_STATE_DELEGATE_H_ -#define ASH_WM_WINDOW_STATE_DELEGATE_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" - -namespace ash { -namespace wm { -class WindowState; - -class ASH_EXPORT WindowStateDelegate { - public: - WindowStateDelegate(); - virtual ~WindowStateDelegate(); - - // Invoked when the user uses Shift+F4/F4 to toggle the window fullscreen - // state. If the window is not fullscreen and the window supports immersive - // fullscreen ToggleFullscreen() should put the window into immersive - // fullscreen instead of the default fullscreen type. The caller - // (ash::wm::WindowState) falls backs to the default implementation if this - // returns false. - virtual bool ToggleFullscreen(WindowState* window_state); - - private: - DISALLOW_COPY_AND_ASSIGN(WindowStateDelegate); -}; - -} // namespace wm -} // namespace ash - -#endif // ASH_WM_WINDOW_STATE_DELEGATE_H_ diff --git a/chromium/ash/wm/window_state_observer.h b/chromium/ash/wm/window_state_observer.h deleted file mode 100644 index f177d5fbeba..00000000000 --- a/chromium/ash/wm/window_state_observer.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 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_WINDOW_STATE_OBSERVER_H_ -#define ASH_WM_WINDOW_STATE_OBSERVER_H_ - -#include "ash/ash_export.h" -#include "ash/wm/wm_types.h" - -namespace ash { -namespace wm { -class WindowState; - -class ASH_EXPORT WindowStateObserver { - public: - // Called when the window's show type has changed. This is different from - // kWindowShowStatekey property change as this will be invoked when the window - // gets left/right maximized, and auto positioned. |old_type| is the value - // before the change. - virtual void OnWindowShowTypeChanged(WindowState* window_state, - WindowShowType old_type) {} -}; - -} // namespace wm -} // namespace ash - -#endif // ASH_WM_WINDOW_STATE_OBSERVER_H_ diff --git a/chromium/ash/wm/window_util.cc b/chromium/ash/wm/window_util.cc deleted file mode 100644 index def4b6d5bad..00000000000 --- a/chromium/ash/wm/window_util.cc +++ /dev/null @@ -1,145 +0,0 @@ -// 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/window_util.h" - -#include <vector> - -#include "ash/ash_constants.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/wm/window_properties.h" -#include "ash/wm/window_state.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/gfx/display.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/screen.h" -#include "ui/views/corewm/window_util.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace wm { - -// TODO(beng): replace many of these functions with the corewm versions. -void ActivateWindow(aura::Window* window) { - views::corewm::ActivateWindow(window); -} - -void DeactivateWindow(aura::Window* window) { - views::corewm::DeactivateWindow(window); -} - -bool IsActiveWindow(aura::Window* window) { - return views::corewm::IsActiveWindow(window); -} - -aura::Window* GetActiveWindow() { - return aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())-> - GetActiveWindow(); -} - -aura::Window* GetActivatableWindow(aura::Window* window) { - return views::corewm::GetActivatableWindow(window); -} - -bool CanActivateWindow(aura::Window* window) { - return views::corewm::CanActivateWindow(window); -} - -bool IsWindowMinimized(aura::Window* window) { - return window->GetProperty(aura::client::kShowStateKey) == - ui::SHOW_STATE_MINIMIZED; -} - -void CenterWindow(aura::Window* window) { - wm::WindowState* window_state = wm::GetWindowState(window); - if (!window_state->IsNormalShowState()) - return; - const gfx::Display display = - Shell::GetScreen()->GetDisplayNearestWindow(window); - gfx::Rect center = display.work_area(); - gfx::Size size = window->bounds().size(); - if (window_state->IsSnapped()) { - if (window_state->HasRestoreBounds()) - size = window_state->GetRestoreBoundsInScreen().size(); - center.ClampToCenteredSize(size); - window_state->SetRestoreBoundsInScreen(center); - window_state->Restore(); - } else { - center = ScreenAsh::ConvertRectFromScreen(window->parent(), - center); - center.ClampToCenteredSize(size); - window->SetBounds(center); - } -} - -void AdjustBoundsToEnsureMinimumWindowVisibility(const gfx::Rect& visible_area, - gfx::Rect* bounds) { - AdjustBoundsToEnsureWindowVisibility( - visible_area, kMinimumOnScreenArea, kMinimumOnScreenArea, bounds); -} - -void AdjustBoundsToEnsureWindowVisibility(const gfx::Rect& visible_area, - int min_width, - int min_height, - gfx::Rect* bounds) { - 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, visible_area.width()); - min_height = std::min(min_height, visible_area.height()); - - 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 > 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()); - } - if (bounds->y() < 0) - bounds->set_y(0); -} - -bool MoveWindowToEventRoot(aura::Window* window, const ui::Event& event) { - views::View* target = static_cast<views::View*>(event.target()); - if (!target) - return false; - aura::Window* target_root = - target->GetWidget()->GetNativeView()->GetRootWindow(); - if (!target_root || target_root == window->GetRootWindow()) - return false; - aura::Window* window_container = - ash::Shell::GetContainer(target_root, window->parent()->id()); - // Move the window to the target launcher. - window_container->AddChild(window); - return true; -} - -void ReparentChildWithTransientChildren(aura::Window* child, - aura::Window* old_parent, - aura::Window* new_parent) { - if (child->parent() == old_parent) - new_parent->AddChild(child); - ReparentTransientChildrenOfChild(child, old_parent, new_parent); -} - -void ReparentTransientChildrenOfChild(aura::Window* child, - aura::Window* old_parent, - aura::Window* new_parent) { - for (size_t i = 0; i < child->transient_children().size(); ++i) { - ReparentChildWithTransientChildren(child->transient_children()[i], - old_parent, - new_parent); - } -} - -} // namespace wm -} // namespace ash diff --git a/chromium/ash/wm/window_util.h b/chromium/ash/wm/window_util.h deleted file mode 100644 index fd77505c400..00000000000 --- a/chromium/ash/wm/window_util.h +++ /dev/null @@ -1,87 +0,0 @@ -// 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_WINDOW_UTIL_H_ -#define ASH_WM_WINDOW_UTIL_H_ - -#include "ash/ash_export.h" -#include "base/compiler_specific.h" -#include "ui/base/ui_base_types.h" - -namespace aura { -class Window; -} - -namespace gfx { -class Rect; -} - -namespace ui { -class Event; -} - -namespace ash { -// We force at least this many DIPs for any window on the screen. -const int kMinimumOnScreenArea = 10; - -namespace wm { - -// Utility functions for window activation. -ASH_EXPORT void ActivateWindow(aura::Window* window); -ASH_EXPORT void DeactivateWindow(aura::Window* window); -ASH_EXPORT bool IsActiveWindow(aura::Window* window); -ASH_EXPORT aura::Window* GetActiveWindow(); -ASH_EXPORT bool CanActivateWindow(aura::Window* window); - -// Retrieves the activatable window for |window|. If |window| is activatable, -// this will just return it, otherwise it will climb the parent/transient parent -// chain looking for a window that is activatable, per the ActivationController. -// If you're looking for a function to get the activatable "top level" window, -// this is probably what you're looking for. -ASH_EXPORT aura::Window* GetActivatableWindow(aura::Window* window); - -// TODO(oshima): remove this. -ASH_EXPORT bool IsWindowMinimized(aura::Window* window); - -// Moves the window to the center of the display. -ASH_EXPORT void CenterWindow(aura::Window* window); - -// Move the given bounds inside the given |visible_area| in parent coordinates, -// including a safety margin given by |kMinimumOnScreenArea|. -// This also ensures that the top of the bounds is visible. -ASH_EXPORT void AdjustBoundsToEnsureMinimumWindowVisibility( - const gfx::Rect& visible_area, - gfx::Rect* bounds); - -// Move the given bounds inside the given |visible_area| in parent coordinates, -// including a safety margin given by |min_width| and |min_height|. -// This also ensures that the top of the bounds is visible. -ASH_EXPORT void AdjustBoundsToEnsureWindowVisibility( - const gfx::Rect& visible_area, - int min_width, - int min_height, - gfx::Rect* bounds); - -// Moves |window| to the root window where the |event| occured if it is not -// already in the same root window. Returns true if |window| was moved. -ASH_EXPORT bool MoveWindowToEventRoot(aura::Window* window, - const ui::Event& event); - -// Changes the parent of a |child| and all its transient children that are -// themselves children of |old_parent| to |new_parent|. -void ReparentChildWithTransientChildren(aura::Window* child, - aura::Window* old_parent, - aura::Window* new_parent); - -// Changes the parent of all transient children of a |child| to |new_parent|. -// Does not change parent of the transient children that are not themselves -// children of |old_parent|. -void ReparentTransientChildrenOfChild(aura::Window* child, - aura::Window* old_parent, - aura::Window* new_parent); - -} // namespace wm -} // namespace ash - -#endif // ASH_WM_WINDOW_UTIL_H_ diff --git a/chromium/ash/wm/window_util_unittest.cc b/chromium/ash/wm/window_util_unittest.cc deleted file mode 100644 index 8073a38cc87..00000000000 --- a/chromium/ash/wm/window_util_unittest.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2013 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/window_util.h" - -#include "ash/screen_ash.h" -#include "ash/test/ash_test_base.h" -#include "ui/aura/window.h" - -namespace ash { - -typedef test::AshTestBase WindowUtilTest; - -TEST_F(WindowUtilTest, CenterWindow) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("500x400, 600x400"); - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(12, 20, 100, 100))); - wm::CenterWindow(window.get()); - EXPECT_EQ("200,126 100x100", window->bounds().ToString()); - EXPECT_EQ("200,126 100x100", window->GetBoundsInScreen().ToString()); - window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100), - ScreenAsh::GetSecondaryDisplay()); - wm::CenterWindow(window.get()); - EXPECT_EQ("250,126 100x100", window->bounds().ToString()); - EXPECT_EQ("750,126 100x100", window->GetBoundsInScreen().ToString()); -} - -} // namespace ash diff --git a/chromium/ash/wm/wm_types.cc b/chromium/ash/wm/wm_types.cc deleted file mode 100644 index c7f45ce7cb3..00000000000 --- a/chromium/ash/wm/wm_types.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 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/wm_types.h" - -#include "base/basictypes.h" -#include "base/logging.h" - -namespace ash { -namespace wm { - -// This is to catch the change to WindowShowState. -COMPILE_ASSERT( - ui::SHOW_STATE_END == static_cast<ui::WindowShowState>(SHOW_TYPE_END), - show_enum_mismatch); - -WindowShowType ToWindowShowType(ui::WindowShowState state) { - return static_cast<WindowShowType>(state); -} - -ui::WindowShowState ToWindowShowState(WindowShowType type) { - switch (type) { - case SHOW_TYPE_DEFAULT: - return ui::SHOW_STATE_DEFAULT; - case SHOW_TYPE_NORMAL: - case SHOW_TYPE_RIGHT_SNAPPED: - case SHOW_TYPE_LEFT_SNAPPED: - case SHOW_TYPE_AUTO_POSITIONED: - return ui::SHOW_STATE_NORMAL; - case SHOW_TYPE_MINIMIZED: - return ui::SHOW_STATE_MINIMIZED; - case SHOW_TYPE_MAXIMIZED: - return ui::SHOW_STATE_MAXIMIZED; - case SHOW_TYPE_INACTIVE: - return ui::SHOW_STATE_INACTIVE; - case SHOW_TYPE_FULLSCREEN: - return ui::SHOW_STATE_FULLSCREEN; - case SHOW_TYPE_DETACHED: - return ui::SHOW_STATE_DETACHED; - case SHOW_TYPE_END: - NOTREACHED(); - } - NOTREACHED(); - return ui::SHOW_STATE_DEFAULT; -} - -} // namespace wm -} // namespace ash diff --git a/chromium/ash/wm/wm_types.h b/chromium/ash/wm/wm_types.h deleted file mode 100644 index da3db00bde1..00000000000 --- a/chromium/ash/wm/wm_types.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2013 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_WM_TYPES_H_ -#define ASH_WM_WM_TYPES_H_ - -#include "ui/base/ui_base_types.h" - -namespace ash { -namespace wm { - -// This enum defines both common show state copied from -// ui::WindowShowState as well as new states intoruduced in ash. -// The separate enum is defined here because we don't want to leak -// these type to ui/base until they're stable and we know for sure -// that they'll persist over time. -enum WindowShowType { - // Common state - SHOW_TYPE_DEFAULT = 0, - - // Normal represents a state where the position/size has been - // specified by a use. - SHOW_TYPE_NORMAL, - SHOW_TYPE_MINIMIZED, - SHOW_TYPE_MAXIMIZED, - SHOW_TYPE_INACTIVE, - SHOW_TYPE_FULLSCREEN, - SHOW_TYPE_DETACHED, - SHOW_TYPE_END, // to avoid using SHOW_STATE_END - - // Ash specific states: - - SHOW_TYPE_LEFT_SNAPPED, - SHOW_TYPE_RIGHT_SNAPPED, - - // A window is in this state when it is automatically placed and - // sized by the window manager. (it's newly opened, or pushed to the side - // due to new window, for example). - SHOW_TYPE_AUTO_POSITIONED, -}; - -// Utility functions to convert WindowShowType <-> ui::WindowShowState. -// Note: LEFT/RIGHT MAXIMIZED, AUTO_POSITIONED type will be lost when -// converting to ui::WindowShowState. -WindowShowType ToWindowShowType(ui::WindowShowState state); -ui::WindowShowState ToWindowShowState(WindowShowType type); - -} // namespace -} // namespace - -#endif // ASH_WM_WM_TYPES_H_ diff --git a/chromium/ash/wm/workspace/magnetism_matcher.cc b/chromium/ash/wm/workspace/magnetism_matcher.cc deleted file mode 100644 index e7d674b850c..00000000000 --- a/chromium/ash/wm/workspace/magnetism_matcher.cc +++ /dev/null @@ -1,194 +0,0 @@ -// 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/workspace/magnetism_matcher.h" - -#include <algorithm> -#include <cmath> - -namespace ash { -namespace internal { - -namespace { - -// Returns true if |a| is close enough to |b| that the two edges snap. -bool IsCloseEnough(int a, int b) { - return abs(a - b) <= MagnetismMatcher::kMagneticDistance; -} - -// Returns true if the specified SecondaryMagnetismEdge can be matched with a -// primary edge of |primary|. |edges| is a bitmask of the allowed -// MagnetismEdges. -bool CanMatchSecondaryEdge(MagnetismEdge primary, - SecondaryMagnetismEdge secondary, - uint32 edges) { - // Convert |secondary| to a MagnetismEdge so we can compare it to |edges|. - MagnetismEdge secondary_as_magnetism_edge = MAGNETISM_EDGE_TOP; - switch (primary) { - case MAGNETISM_EDGE_TOP: - case MAGNETISM_EDGE_BOTTOM: - if (secondary == SECONDARY_MAGNETISM_EDGE_LEADING) - secondary_as_magnetism_edge = MAGNETISM_EDGE_LEFT; - else if (secondary == SECONDARY_MAGNETISM_EDGE_TRAILING) - secondary_as_magnetism_edge = MAGNETISM_EDGE_RIGHT; - else - NOTREACHED(); - break; - case MAGNETISM_EDGE_LEFT: - case MAGNETISM_EDGE_RIGHT: - if (secondary == SECONDARY_MAGNETISM_EDGE_LEADING) - secondary_as_magnetism_edge = MAGNETISM_EDGE_TOP; - else if (secondary == SECONDARY_MAGNETISM_EDGE_TRAILING) - secondary_as_magnetism_edge = MAGNETISM_EDGE_BOTTOM; - else - NOTREACHED(); - break; - } - return (edges & secondary_as_magnetism_edge) != 0; -} - -} // namespace - -// MagnetismEdgeMatcher -------------------------------------------------------- - -MagnetismEdgeMatcher::MagnetismEdgeMatcher(const gfx::Rect& bounds, - MagnetismEdge edge) - : bounds_(bounds), - edge_(edge) { - ranges_.push_back(GetSecondaryRange(bounds_)); -} - -MagnetismEdgeMatcher::~MagnetismEdgeMatcher() { -} - -bool MagnetismEdgeMatcher::ShouldAttach(const gfx::Rect& bounds) { - if (is_edge_obscured()) - return false; - - if (IsCloseEnough(GetPrimaryCoordinate(bounds_, edge_), - GetPrimaryCoordinate(bounds, FlipEdge(edge_)))) { - const Range range(GetSecondaryRange(bounds)); - Ranges::const_iterator i = - std::lower_bound(ranges_.begin(), ranges_.end(), range); - // Close enough, but only attach if some portion of the edge is visible. - if ((i != ranges_.begin() && RangesIntersect(*(i - 1), range)) || - (i != ranges_.end() && RangesIntersect(*i, range))) { - return true; - } - } - // NOTE: this checks against the current bounds, we may want to allow some - // flexibility here. - const Range primary_range(GetPrimaryRange(bounds)); - if (primary_range.first <= GetPrimaryCoordinate(bounds_, edge_) && - primary_range.second >= GetPrimaryCoordinate(bounds_, edge_)) { - UpdateRanges(GetSecondaryRange(bounds)); - } - return false; -} - -void MagnetismEdgeMatcher::UpdateRanges(const Range& range) { - Ranges::const_iterator it = - std::lower_bound(ranges_.begin(), ranges_.end(), range); - if (it != ranges_.begin() && RangesIntersect(*(it - 1), range)) - --it; - if (it == ranges_.end()) - return; - - for (size_t i = it - ranges_.begin(); - i < ranges_.size() && RangesIntersect(ranges_[i], range); ) { - if (range.first <= ranges_[i].first && - range.second >= ranges_[i].second) { - ranges_.erase(ranges_.begin() + i); - } else if (range.first < ranges_[i].first) { - DCHECK_GT(range.second, ranges_[i].first); - ranges_[i] = Range(range.second, ranges_[i].second); - ++i; - } else { - Range existing(ranges_[i]); - ranges_[i].second = range.first; - ++i; - if (existing.second > range.second) { - ranges_.insert(ranges_.begin() + i, - Range(range.second, existing.second)); - ++i; - } - } - } -} - -// MagnetismMatcher ------------------------------------------------------------ - -// static -const int MagnetismMatcher::kMagneticDistance = 8; - -MagnetismMatcher::MagnetismMatcher(const gfx::Rect& bounds, uint32 edges) - : edges_(edges) { - if (edges & MAGNETISM_EDGE_TOP) - matchers_.push_back(new MagnetismEdgeMatcher(bounds, MAGNETISM_EDGE_TOP)); - if (edges & MAGNETISM_EDGE_LEFT) - matchers_.push_back(new MagnetismEdgeMatcher(bounds, MAGNETISM_EDGE_LEFT)); - if (edges & MAGNETISM_EDGE_BOTTOM) { - matchers_.push_back(new MagnetismEdgeMatcher(bounds, - MAGNETISM_EDGE_BOTTOM)); - } - if (edges & MAGNETISM_EDGE_RIGHT) - matchers_.push_back(new MagnetismEdgeMatcher(bounds, MAGNETISM_EDGE_RIGHT)); -} - -MagnetismMatcher::~MagnetismMatcher() { -} - -bool MagnetismMatcher::ShouldAttach(const gfx::Rect& bounds, - MatchedEdge* edge) { - for (size_t i = 0; i < matchers_.size(); ++i) { - if (matchers_[i]->ShouldAttach(bounds)) { - edge->primary_edge = matchers_[i]->edge(); - AttachToSecondaryEdge(bounds, edge->primary_edge, - &(edge->secondary_edge)); - return true; - } - } - return false; -} - -bool MagnetismMatcher::AreEdgesObscured() const { - for (size_t i = 0; i < matchers_.size(); ++i) { - if (!matchers_[i]->is_edge_obscured()) - return false; - } - return true; -} - -void MagnetismMatcher::AttachToSecondaryEdge( - const gfx::Rect& bounds, - MagnetismEdge edge, - SecondaryMagnetismEdge* secondary_edge) const { - const gfx::Rect& src_bounds(matchers_[0]->bounds()); - if (edge == MAGNETISM_EDGE_LEFT || edge == MAGNETISM_EDGE_RIGHT) { - if (CanMatchSecondaryEdge(edge, SECONDARY_MAGNETISM_EDGE_LEADING, edges_) && - IsCloseEnough(bounds.y(), src_bounds.y())) { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_LEADING; - } else if (CanMatchSecondaryEdge(edge, SECONDARY_MAGNETISM_EDGE_TRAILING, - edges_) && - IsCloseEnough(bounds.bottom(), src_bounds.bottom())) { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_TRAILING; - } else { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_NONE; - } - } else { - if (CanMatchSecondaryEdge(edge, SECONDARY_MAGNETISM_EDGE_LEADING, edges_) && - IsCloseEnough(bounds.x(), src_bounds.x())) { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_LEADING; - } else if (CanMatchSecondaryEdge(edge, SECONDARY_MAGNETISM_EDGE_TRAILING, - edges_) && - IsCloseEnough(bounds.right(), src_bounds.right())) { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_TRAILING; - } else { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_NONE; - } - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/magnetism_matcher.h b/chromium/ash/wm/workspace/magnetism_matcher.h deleted file mode 100644 index ff1f52810e9..00000000000 --- a/chromium/ash/wm/workspace/magnetism_matcher.h +++ /dev/null @@ -1,191 +0,0 @@ -// 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_WORKSPACE_MAGNETISM_MATCHER_H_ -#define ASH_WM_WORKSPACE_MAGNETISM_MATCHER_H_ - -#include <utility> -#include <vector> - -#include "ash/ash_export.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/memory/scoped_vector.h" -#include "ui/gfx/rect.h" - -namespace ash { -namespace internal { - -enum MagnetismEdge { - MAGNETISM_EDGE_TOP = 1 << 0, - MAGNETISM_EDGE_LEFT = 1 << 1, - MAGNETISM_EDGE_BOTTOM = 1 << 2, - MAGNETISM_EDGE_RIGHT = 1 << 3, -}; - -const uint32 kAllMagnetismEdges = - MAGNETISM_EDGE_TOP | MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_BOTTOM | - MAGNETISM_EDGE_RIGHT; - -// MagnetismEdgeMatcher is used for matching a particular edge of a window. You -// shouldn't need to use this directly, instead use MagnetismMatcher which takes -// care of all edges. -// MagnetismEdgeMatcher maintains a range of the visible portions of the -// edge. As ShouldAttach() is invoked the visible range is updated. -class MagnetismEdgeMatcher { - public: - MagnetismEdgeMatcher(const gfx::Rect& bounds, MagnetismEdge edge); - ~MagnetismEdgeMatcher(); - - MagnetismEdge edge() const { return edge_; } - const gfx::Rect& bounds() const { return bounds_; } - - // Returns true if the edge is completely obscured. If true ShouldAttach() - // will return false. - bool is_edge_obscured() const { return ranges_.empty(); } - - // Returns true if should attach to the specified bounds. - bool ShouldAttach(const gfx::Rect& bounds); - - private: - typedef std::pair<int,int> Range; - typedef std::vector<Range> Ranges; - - // Removes |range| from |ranges_|. - void UpdateRanges(const Range& range); - - static int GetPrimaryCoordinate(const gfx::Rect& bounds, MagnetismEdge edge) { - switch (edge) { - case MAGNETISM_EDGE_TOP: - return bounds.y(); - case MAGNETISM_EDGE_LEFT: - return bounds.x(); - case MAGNETISM_EDGE_BOTTOM: - return bounds.bottom(); - case MAGNETISM_EDGE_RIGHT: - return bounds.right(); - } - NOTREACHED(); - return 0; - } - - static MagnetismEdge FlipEdge(MagnetismEdge edge) { - switch (edge) { - case MAGNETISM_EDGE_TOP: - return MAGNETISM_EDGE_BOTTOM; - case MAGNETISM_EDGE_BOTTOM: - return MAGNETISM_EDGE_TOP; - case MAGNETISM_EDGE_LEFT: - return MAGNETISM_EDGE_RIGHT; - case MAGNETISM_EDGE_RIGHT: - return MAGNETISM_EDGE_LEFT; - } - NOTREACHED(); - return MAGNETISM_EDGE_LEFT; - } - - Range GetPrimaryRange(const gfx::Rect& bounds) const { - switch (edge_) { - case MAGNETISM_EDGE_TOP: - case MAGNETISM_EDGE_BOTTOM: - return Range(bounds.y(), bounds.bottom()); - case MAGNETISM_EDGE_LEFT: - case MAGNETISM_EDGE_RIGHT: - return Range(bounds.x(), bounds.right()); - } - NOTREACHED(); - return Range(); - } - - Range GetSecondaryRange(const gfx::Rect& bounds) const { - switch (edge_) { - case MAGNETISM_EDGE_TOP: - case MAGNETISM_EDGE_BOTTOM: - return Range(bounds.x(), bounds.right()); - case MAGNETISM_EDGE_LEFT: - case MAGNETISM_EDGE_RIGHT: - return Range(bounds.y(), bounds.bottom()); - } - NOTREACHED(); - return Range(); - } - - static bool RangesIntersect(const Range& r1, const Range& r2) { - return r2.first < r1.second && r2.second > r1.first; - } - - // The bounds of window. - const gfx::Rect bounds_; - - // The edge this matcher checks. - const MagnetismEdge edge_; - - // Visible ranges of the edge. Initialized with GetSecondaryRange() and - // updated as ShouldAttach() is invoked. When empty the edge is completely - // obscured by other bounds. - Ranges ranges_; - - DISALLOW_COPY_AND_ASSIGN(MagnetismEdgeMatcher); -}; - -enum SecondaryMagnetismEdge { - SECONDARY_MAGNETISM_EDGE_LEADING, - SECONDARY_MAGNETISM_EDGE_TRAILING, - SECONDARY_MAGNETISM_EDGE_NONE, -}; - -// Used to identify a matched edge. |primary_edge| is relative to the source and -// indicates the edge the two are to share. For example, if |primary_edge| is -// MAGNETISM_EDGE_RIGHT then the right edge of the source should snap to to the -// left edge of the target. |secondary_edge| indicates one of the edges along -// the opposite axis should should also be aligned. For example, if -// |primary_edge| is MAGNETISM_EDGE_RIGHT and |secondary_edge| is -// SECONDARY_MAGNETISM_EDGE_LEADING then the source should snap to the left top -// corner of the target. -struct MatchedEdge { - MagnetismEdge primary_edge; - SecondaryMagnetismEdge secondary_edge; -}; - -// MagnetismMatcher is used to test if a window should snap to another window. -// To use MagnetismMatcher do the following: -// . Create it with the bounds of the window being dragged. -// . Iterate over the child windows checking if the window being dragged should -// attach to it using ShouldAttach(). -// . Use AreEdgesObscured() to test if no other windows can match (because all -// edges are completely obscured). -class ASH_EXPORT MagnetismMatcher { - public: - static const int kMagneticDistance; - - // |edges| is a bitmask of MagnetismEdges to match against. - MagnetismMatcher(const gfx::Rect& bounds, uint32 edges); - ~MagnetismMatcher(); - - // Returns true if |bounds| is close enough to the initial bounds that the two - // should be attached. If true is returned |edge| is set to indicates how the - // two should snap together. See description of MatchedEdge for details. - bool ShouldAttach(const gfx::Rect& bounds, MatchedEdge* edge); - - // Returns true if no other matches are possible. - bool AreEdgesObscured() const; - - private: - // Sets |secondary_edge| based on whether the secondary edges should snap. - void AttachToSecondaryEdge(const gfx::Rect& bounds, - MagnetismEdge edge, - SecondaryMagnetismEdge* secondary_edge) const; - - // The edges to match against. - const int32 edges_; - - ScopedVector<MagnetismEdgeMatcher> matchers_; - - DISALLOW_COPY_AND_ASSIGN(MagnetismMatcher); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_MAGNETISM_MATCHER_H_ diff --git a/chromium/ash/wm/workspace/magnetism_matcher_unittest.cc b/chromium/ash/wm/workspace/magnetism_matcher_unittest.cc deleted file mode 100644 index 054622ff572..00000000000 --- a/chromium/ash/wm/workspace/magnetism_matcher_unittest.cc +++ /dev/null @@ -1,171 +0,0 @@ -// 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/workspace/magnetism_matcher.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace ash { -namespace internal { - -// Trivial test case verifying assertions on left edge. -TEST(MagnetismMatcherTest, TrivialLeft) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 50, 60); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - EXPECT_FALSE(matcher.AreEdgesObscured()); - MatchedEdge edge; - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - distance - 10, - initial_bounds.y() - distance - 10, 2, 3), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - 2, initial_bounds.y(), 1, 1), - &edge)); - EXPECT_EQ(MAGNETISM_EDGE_LEFT, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_LEADING, edge.secondary_edge); - - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - 2, - initial_bounds.y() + distance + 1 , 1, 1), - &edge)); - EXPECT_EQ(MAGNETISM_EDGE_LEFT, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); -} - -// Trivial test case verifying assertions on bottom edge. -TEST(MagnetismMatcherTest, TrivialBottom) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 50, 60); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - EXPECT_FALSE(matcher.AreEdgesObscured()); - MatchedEdge edge; - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - distance - 10, - initial_bounds.y() - distance - 10, 2, 3), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - 2, - initial_bounds.bottom() + 4, 10, 1), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_BOTTOM, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_LEADING, edge.secondary_edge); - - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() + distance + 1, - initial_bounds.bottom() + 4, 10, 1), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_BOTTOM, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); - - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.right() - 10 - 1, - initial_bounds.bottom() + 4, 10, 1), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_BOTTOM, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_TRAILING, edge.secondary_edge); -} - -// Verifies we don't match an obscured corner. -TEST(MagnetismMatcherTest, ObscureLeading) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 150, 160); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - MatchedEdge edge; - // Overlap with the upper right corner. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.right() - distance * 2, - initial_bounds.y() - distance - 2, - distance * 3, - (distance + 2) * 2), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - // Verify doesn't match the following which is obscured by first. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.right() + 1, - initial_bounds.y(), - distance, - 5), &edge)); - // Should match the following which extends into non-overlapping region. - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.right() + 1, - initial_bounds.y() + distance + 1, - distance, - 15), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_RIGHT, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); -} - -// Verifies obscuring one side doesn't obscure the other. -TEST(MagnetismMatcherTest, DontObscureOtherSide) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 150, 160); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - MatchedEdge edge; - // Overlap with the left side. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - distance + 1, - initial_bounds.y() + 2, - distance * 2 + 2, - initial_bounds.height() + distance * 4), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - // Should match the right side since it isn't obscured. - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.right() - 1, - initial_bounds.y() + distance + 1, - distance, - 5), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_RIGHT, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); -} - -// Verifies we don't match an obscured center. -TEST(MagnetismMatcherTest, ObscureCenter) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 150, 160); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - MatchedEdge edge; - // Overlap with the center bottom edge. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(100, initial_bounds.bottom() - distance - 2, - 20, - (distance + 2) * 2), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - // Verify doesn't match the following which is obscured by first. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(110, initial_bounds.bottom() + 1, - 10, 5), &edge)); - // Should match the following which extends into non-overlapping region. - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(90, - initial_bounds.bottom() + 1, - 10, 5), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_BOTTOM, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); -} - -// Verifies we don't match an obscured trailing edge. -TEST(MagnetismMatcherTest, ObscureTrailing) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 150, 160); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - MatchedEdge edge; - // Overlap with the trailing left edge. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - distance - 2, - 150, - (distance + 2) * 2, - 50), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - // Verify doesn't match the following which is obscured by first. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - 4, - 160, 3, 20), &edge)); - // Should match the following which extends into non-overlapping region. - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - 4, - 140, 3, 20), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_LEFT, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); -} - -} // namespace internal -} // namespace ash - diff --git a/chromium/ash/wm/workspace/multi_window_resize_controller.cc b/chromium/ash/wm/workspace/multi_window_resize_controller.cc deleted file mode 100644 index 597acbf88ec..00000000000 --- a/chromium/ash/wm/workspace/multi_window_resize_controller.cc +++ /dev/null @@ -1,545 +0,0 @@ -// 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/workspace/multi_window_resize_controller.h" - -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/workspace/workspace_event_handler.h" -#include "ash/wm/workspace/workspace_window_resizer.h" -#include "grit/ash_resources.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/screen.h" -#include "ui/views/corewm/compound_event_filter.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -using aura::Window; - -namespace ash { -namespace internal { - -namespace { - -// Delay before showing. -const int kShowDelayMS = 400; - -// Delay before hiding. -const int kHideDelayMS = 500; - -// Padding from the bottom/right edge the resize widget is shown at. -const int kResizeWidgetPadding = 15; - -bool ContainsX(Window* window, int x) { - return window->bounds().x() <= x && window->bounds().right() >= x; -} - -bool ContainsY(Window* window, int y) { - return window->bounds().y() <= y && window->bounds().bottom() >= y; -} - -bool Intersects(int x1, int max_1, int x2, int max_2) { - return x2 <= max_1 && max_2 > x1; -} - -} // namespace - -// View contained in the widget. Passes along mouse events to the -// MultiWindowResizeController so that it can start/stop the resize loop. -class MultiWindowResizeController::ResizeView : public views::View { - public: - explicit ResizeView(MultiWindowResizeController* controller, - Direction direction) - : controller_(controller), - direction_(direction), - image_(NULL) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - int image_id = - direction == TOP_BOTTOM ? IDR_AURA_MULTI_WINDOW_RESIZE_H : - IDR_AURA_MULTI_WINDOW_RESIZE_V; - image_ = rb.GetImageNamed(image_id).ToImageSkia(); - } - - // views::View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE { - return gfx::Size(image_->width(), image_->height()); - } - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { - canvas->DrawImageInt(*image_, 0, 0); - } - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { - gfx::Point location(event.location()); - views::View::ConvertPointToScreen(this, &location); - controller_->StartResize(location); - return true; - } - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE { - gfx::Point location(event.location()); - views::View::ConvertPointToScreen(this, &location); - controller_->Resize(location, event.flags()); - return true; - } - virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE { - controller_->CompleteResize(event.flags()); - } - virtual void OnMouseCaptureLost() OVERRIDE { - controller_->CancelResize(); - } - virtual gfx::NativeCursor GetCursor( - const ui::MouseEvent& event) OVERRIDE { - int component = (direction_ == LEFT_RIGHT) ? HTRIGHT : HTBOTTOM; - return views::corewm::CompoundEventFilter::CursorForWindowComponent( - component); - } - - private: - MultiWindowResizeController* controller_; - const Direction direction_; - const gfx::ImageSkia* image_; - - DISALLOW_COPY_AND_ASSIGN(ResizeView); -}; - -// MouseWatcherHost implementation for MultiWindowResizeController. Forwards -// Contains() to MultiWindowResizeController. -class MultiWindowResizeController::ResizeMouseWatcherHost : - public views::MouseWatcherHost { - public: - ResizeMouseWatcherHost(MultiWindowResizeController* host) : host_(host) {} - - // MouseWatcherHost overrides: - virtual bool Contains(const gfx::Point& point_in_screen, - MouseEventType type) OVERRIDE { - return host_->IsOverWindows(point_in_screen); - } - - private: - MultiWindowResizeController* host_; - - DISALLOW_COPY_AND_ASSIGN(ResizeMouseWatcherHost); -}; - -MultiWindowResizeController::ResizeWindows::ResizeWindows() - : window1(NULL), - window2(NULL), - direction(TOP_BOTTOM){ -} - -MultiWindowResizeController::ResizeWindows::~ResizeWindows() { -} - -bool MultiWindowResizeController::ResizeWindows::Equals( - const ResizeWindows& other) const { - return window1 == other.window1 && - window2 == other.window2 && - direction == other.direction; -} - -MultiWindowResizeController::MultiWindowResizeController() { -} - -MultiWindowResizeController::~MultiWindowResizeController() { - window_resizer_.reset(); - Hide(); -} - -void MultiWindowResizeController::Show(Window* window, - int component, - const gfx::Point& point_in_window) { - // When the resize widget is showing we ignore Show() requests. Instead we - // only care about mouse movements from MouseWatcher. This is necessary as - // WorkspaceEventHandler only sees mouse movements over the windows, not all - // windows or over the desktop. - if (resize_widget_) - return; - - ResizeWindows windows(DetermineWindows(window, component, point_in_window)); - if (IsShowing()) { - if (windows_.Equals(windows)) - return; // Over the same windows. - DelayedHide(); - } - - if (!windows.is_valid()) - return; - Hide(); - windows_ = windows; - windows_.window1->AddObserver(this); - windows_.window2->AddObserver(this); - show_location_in_parent_ = point_in_window; - Window::ConvertPointToTarget( - window, window->parent(), &show_location_in_parent_); - if (show_timer_.IsRunning()) - return; - show_timer_.Start( - FROM_HERE, base::TimeDelta::FromMilliseconds(kShowDelayMS), - this, &MultiWindowResizeController::ShowIfValidMouseLocation); -} - -void MultiWindowResizeController::Hide() { - hide_timer_.Stop(); - if (window_resizer_) - return; // Ignore hides while actively resizing. - - if (windows_.window1) { - windows_.window1->RemoveObserver(this); - windows_.window1 = NULL; - } - if (windows_.window2) { - windows_.window2->RemoveObserver(this); - windows_.window2 = NULL; - } - - show_timer_.Stop(); - - if (!resize_widget_) - return; - - for (size_t i = 0; i < windows_.other_windows.size(); ++i) - windows_.other_windows[i]->RemoveObserver(this); - mouse_watcher_.reset(); - resize_widget_.reset(); - windows_ = ResizeWindows(); -} - -void MultiWindowResizeController::MouseMovedOutOfHost() { - Hide(); -} - -void MultiWindowResizeController::OnWindowDestroying( - aura::Window* window) { - // Have to explicitly reset the WindowResizer, otherwise Hide() does nothing. - window_resizer_.reset(); - Hide(); -} - -MultiWindowResizeController::ResizeWindows -MultiWindowResizeController::DetermineWindowsFromScreenPoint( - aura::Window* window) const { - gfx::Point mouse_location( - gfx::Screen::GetScreenFor(window)->GetCursorScreenPoint()); - wm::ConvertPointFromScreen(window, &mouse_location); - const int component = - window->delegate()->GetNonClientComponent(mouse_location); - return DetermineWindows(window, component, mouse_location); -} - -MultiWindowResizeController::ResizeWindows -MultiWindowResizeController::DetermineWindows( - Window* window, - int window_component, - const gfx::Point& point) const { - ResizeWindows result; - gfx::Point point_in_parent(point); - Window::ConvertPointToTarget(window, window->parent(), &point_in_parent); - switch (window_component) { - case HTRIGHT: - result.direction = LEFT_RIGHT; - result.window1 = window; - result.window2 = FindWindowByEdge( - window, HTLEFT, window->bounds().right(), point_in_parent.y()); - break; - case HTLEFT: - result.direction = LEFT_RIGHT; - result.window1 = FindWindowByEdge( - window, HTRIGHT, window->bounds().x(), point_in_parent.y()); - result.window2 = window; - break; - case HTTOP: - result.direction = TOP_BOTTOM; - result.window1 = FindWindowByEdge( - window, HTBOTTOM, point_in_parent.x(), window->bounds().y()); - result.window2 = window; - break; - case HTBOTTOM: - result.direction = TOP_BOTTOM; - result.window1 = window; - result.window2 = FindWindowByEdge( - window, HTTOP, point_in_parent.x(), window->bounds().bottom()); - break; - default: - break; - } - return result; -} - -Window* MultiWindowResizeController::FindWindowByEdge( - Window* window_to_ignore, - int edge_want, - int x, - int y) const { - Window* parent = window_to_ignore->parent(); - const Window::Windows& windows(parent->children()); - for (Window::Windows::const_reverse_iterator i = windows.rbegin(); - i != windows.rend(); ++i) { - Window* window = *i; - if (window == window_to_ignore || !window->IsVisible()) - continue; - switch (edge_want) { - case HTLEFT: - if (ContainsY(window, y) && window->bounds().x() == x) - return window; - break; - case HTRIGHT: - if (ContainsY(window, y) && window->bounds().right() == x) - return window; - break; - case HTTOP: - if (ContainsX(window, x) && window->bounds().y() == y) - return window; - break; - case HTBOTTOM: - if (ContainsX(window, x) && window->bounds().bottom() == y) - return window; - break; - default: - NOTREACHED(); - } - // Window doesn't contain the edge, but if window contains |point| - // it's obscuring any other window that could be at the location. - if (window->bounds().Contains(x, y)) - return NULL; - } - return NULL; -} - -aura::Window* MultiWindowResizeController::FindWindowTouching( - aura::Window* window, - Direction direction) const { - int right = window->bounds().right(); - int bottom = window->bounds().bottom(); - Window* parent = window->parent(); - const Window::Windows& windows(parent->children()); - for (Window::Windows::const_reverse_iterator i = windows.rbegin(); - i != windows.rend(); ++i) { - Window* other = *i; - if (other == window || !other->IsVisible()) - continue; - switch (direction) { - case TOP_BOTTOM: - if (other->bounds().y() == bottom && - Intersects(other->bounds().x(), other->bounds().right(), - window->bounds().x(), window->bounds().right())) { - return other; - } - break; - case LEFT_RIGHT: - if (other->bounds().x() == right && - Intersects(other->bounds().y(), other->bounds().bottom(), - window->bounds().y(), window->bounds().bottom())) { - return other; - } - break; - default: - NOTREACHED(); - } - } - return NULL; -} - -void MultiWindowResizeController::FindWindowsTouching( - aura::Window* start, - Direction direction, - std::vector<aura::Window*>* others) const { - while (start) { - start = FindWindowTouching(start, direction); - if (start) - others->push_back(start); - } -} - -void MultiWindowResizeController::DelayedHide() { - if (hide_timer_.IsRunning()) - return; - - hide_timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds(kHideDelayMS), - this, &MultiWindowResizeController::Hide); -} - -void MultiWindowResizeController::ShowIfValidMouseLocation() { - if (DetermineWindowsFromScreenPoint(windows_.window1).Equals(windows_) || - DetermineWindowsFromScreenPoint(windows_.window2).Equals(windows_)) { - ShowNow(); - } else { - Hide(); - } -} - -void MultiWindowResizeController::ShowNow() { - DCHECK(!resize_widget_.get()); - DCHECK(windows_.is_valid()); - show_timer_.Stop(); - resize_widget_.reset(new views::Widget); - views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = Shell::GetContainer( - Shell::GetTargetRootWindow(), - internal::kShellWindowId_AlwaysOnTopContainer); - params.can_activate = false; - ResizeView* view = new ResizeView(this, windows_.direction); - resize_widget_->set_focus_on_creation(false); - resize_widget_->Init(params); - views::corewm::SetWindowVisibilityAnimationType( - resize_widget_->GetNativeWindow(), - views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); - resize_widget_->GetNativeWindow()->SetName("MultiWindowResizeController"); - resize_widget_->SetContentsView(view); - show_bounds_in_screen_ = ScreenAsh::ConvertRectToScreen( - windows_.window1->parent(), - CalculateResizeWidgetBounds(show_location_in_parent_)); - resize_widget_->SetBounds(show_bounds_in_screen_); - resize_widget_->Show(); - mouse_watcher_.reset(new views::MouseWatcher( - new ResizeMouseWatcherHost(this), - this)); - mouse_watcher_->set_notify_on_exit_time( - base::TimeDelta::FromMilliseconds(kHideDelayMS)); - mouse_watcher_->Start(); -} - -bool MultiWindowResizeController::IsShowing() const { - return resize_widget_.get() || show_timer_.IsRunning(); -} - -void MultiWindowResizeController::StartResize( - const gfx::Point& location_in_screen) { - DCHECK(!window_resizer_.get()); - DCHECK(windows_.is_valid()); - hide_timer_.Stop(); - gfx::Point location_in_parent(location_in_screen); - aura::client::GetScreenPositionClient(windows_.window2->GetRootWindow())-> - ConvertPointFromScreen(windows_.window2->parent(), &location_in_parent); - std::vector<aura::Window*> windows; - windows.push_back(windows_.window2); - DCHECK(windows_.other_windows.empty()); - FindWindowsTouching(windows_.window2, windows_.direction, - &windows_.other_windows); - for (size_t i = 0; i < windows_.other_windows.size(); ++i) { - windows_.other_windows[i]->AddObserver(this); - windows.push_back(windows_.other_windows[i]); - } - int component = windows_.direction == LEFT_RIGHT ? HTRIGHT : HTBOTTOM; - window_resizer_.reset(WorkspaceWindowResizer::Create( - windows_.window1, - location_in_parent, - component, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, - windows)); -} - -void MultiWindowResizeController::Resize(const gfx::Point& location_in_screen, - int event_flags) { - gfx::Point location_in_parent(location_in_screen); - aura::client::GetScreenPositionClient(windows_.window1->GetRootWindow())-> - ConvertPointFromScreen(windows_.window1->parent(), &location_in_parent); - window_resizer_->Drag(location_in_parent, event_flags); - gfx::Rect bounds = ScreenAsh::ConvertRectToScreen( - windows_.window1->parent(), - CalculateResizeWidgetBounds(location_in_parent)); - - if (windows_.direction == LEFT_RIGHT) - bounds.set_y(show_bounds_in_screen_.y()); - else - bounds.set_x(show_bounds_in_screen_.x()); - resize_widget_->SetBounds(bounds); -} - -void MultiWindowResizeController::CompleteResize(int event_flags) { - window_resizer_->CompleteDrag(event_flags); - window_resizer_.reset(); - - // Mouse may still be over resizer, if not hide. - gfx::Point screen_loc = Shell::GetScreen()->GetCursorScreenPoint(); - if (!resize_widget_->GetWindowBoundsInScreen().Contains(screen_loc)) { - Hide(); - } else { - // If the mouse is over the resizer we need to remove observers on any of - // the |other_windows|. If we start another resize we'll recalculate the - // |other_windows| and invoke AddObserver() as necessary. - for (size_t i = 0; i < windows_.other_windows.size(); ++i) - windows_.other_windows[i]->RemoveObserver(this); - windows_.other_windows.clear(); - } -} - -void MultiWindowResizeController::CancelResize() { - if (!window_resizer_) - return; // Happens if window was destroyed and we nuked the WindowResizer. - window_resizer_->RevertDrag(); - window_resizer_.reset(); - Hide(); -} - -gfx::Rect MultiWindowResizeController::CalculateResizeWidgetBounds( - const gfx::Point& location_in_parent) const { - gfx::Size pref = resize_widget_->GetContentsView()->GetPreferredSize(); - int x = 0, y = 0; - if (windows_.direction == LEFT_RIGHT) { - x = windows_.window1->bounds().right() - pref.width() / 2; - y = location_in_parent.y() + kResizeWidgetPadding; - if (y + pref.height() / 2 > windows_.window1->bounds().bottom() && - y + pref.height() / 2 > windows_.window2->bounds().bottom()) { - y = location_in_parent.y() - kResizeWidgetPadding - pref.height(); - } - } else { - x = location_in_parent.x() + kResizeWidgetPadding; - if (x + pref.height() / 2 > windows_.window1->bounds().right() && - x + pref.height() / 2 > windows_.window2->bounds().right()) { - x = location_in_parent.x() - kResizeWidgetPadding - pref.width(); - } - y = windows_.window1->bounds().bottom() - pref.height() / 2; - } - return gfx::Rect(x, y, pref.width(), pref.height()); -} - -bool MultiWindowResizeController::IsOverWindows( - const gfx::Point& location_in_screen) const { - if (window_resizer_) - return true; // Ignore hides while actively resizing. - - if (resize_widget_->GetWindowBoundsInScreen().Contains(location_in_screen)) - return true; - - int hit1, hit2; - if (windows_.direction == TOP_BOTTOM) { - hit1 = HTBOTTOM; - hit2 = HTTOP; - } else { - hit1 = HTRIGHT; - hit2 = HTLEFT; - } - - return IsOverWindow(windows_.window1, location_in_screen, hit1) || - IsOverWindow(windows_.window2, location_in_screen, hit2); -} - -bool MultiWindowResizeController::IsOverWindow( - aura::Window* window, - const gfx::Point& location_in_screen, - int component) const { - if (!window->delegate()) - return false; - - gfx::Point window_loc(location_in_screen); - aura::Window::ConvertPointToTarget( - window->GetRootWindow(), window, &window_loc); - return window->HitTest(window_loc) && - window->delegate()->GetNonClientComponent(window_loc) == component; -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/multi_window_resize_controller.h b/chromium/ash/wm/workspace/multi_window_resize_controller.h deleted file mode 100644 index 02eeb2511a4..00000000000 --- a/chromium/ash/wm/workspace/multi_window_resize_controller.h +++ /dev/null @@ -1,186 +0,0 @@ -// 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_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_ -#define ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_ - -#include <vector> - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/timer/timer.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/rect.h" -#include "ui/views/mouse_watcher.h" - -namespace aura { -class Window; -} - -namespace views { -class Widget; -} - -namespace ash { -namespace internal { - -class MultiWindowResizeControllerTest; -class WorkspaceWindowResizer; - -// Two directions resizes happen in. -enum Direction { - TOP_BOTTOM, - LEFT_RIGHT, -}; - -// MultiWindowResizeController is responsible for determining and showing a -// widget that allows resizing multiple windows at the same time. -// MultiWindowResizeController is driven by WorkspaceEventFilter. -class ASH_EXPORT MultiWindowResizeController : - public views::MouseWatcherListener, public aura::WindowObserver { - public: - MultiWindowResizeController(); - virtual ~MultiWindowResizeController(); - - // If necessary, shows the resize widget. |window| is the window the mouse - // is over, |component| the edge and |point| the location of the mouse. - void Show(aura::Window* window, int component, const gfx::Point& point); - - // Hides the resize widget. - void Hide(); - - // MouseWatcherListenre overrides: - virtual void MouseMovedOutOfHost() OVERRIDE; - - // WindowObserver overrides: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - private: - friend class MultiWindowResizeControllerTest; - - // Used to track the two resizable windows and direction. - struct ResizeWindows { - ResizeWindows(); - ~ResizeWindows(); - - // Returns true if |other| equals this ResizeWindows. This does *not* - // consider the windows in |other_windows|. - bool Equals(const ResizeWindows& other) const; - - // Returns true if this ResizeWindows is valid. - bool is_valid() const { return window1 && window2; } - - // The left/top window to resize. - aura::Window* window1; - - // Other window to resize. - aura::Window* window2; - - // Direction - Direction direction; - - // Windows after |window2| that are to be resized. Determined at the time - // the resize starts. - std::vector<aura::Window*> other_windows; - }; - - class ResizeMouseWatcherHost; - class ResizeView; - - // Returns a ResizeWindows based on the specified arguments. Use is_valid() - // to test if the return value is a valid multi window resize location. - ResizeWindows DetermineWindows(aura::Window* window, - int window_component, - const gfx::Point& point) const; - - // Variant of DetermineWindows() that uses the current location of the mouse - // to determine the resize windows. - ResizeWindows DetermineWindowsFromScreenPoint(aura::Window* window) const; - - // Finds a window by edge (one of the constants HitTestCompat. - aura::Window* FindWindowByEdge(aura::Window* window_to_ignore, - int edge_want, - int x, - int y) const; - - // Returns the first window touching |window|. - aura::Window* FindWindowTouching(aura::Window* window, - Direction direction) const; - - // Places any windows touching |start| into |others|. - void FindWindowsTouching(aura::Window* start, - Direction direction, - std::vector<aura::Window*>* others) const; - - // Hides the window after a delay. - void DelayedHide(); - - // Shows the resizer if the mouse is still at a valid location. This is called - // from the |show_timer_|. - void ShowIfValidMouseLocation(); - - // Shows the widget immediately. - void ShowNow(); - - // Returns true if the widget is showing. - bool IsShowing() const; - - // Initiates a resize. - void StartResize(const gfx::Point& location_in_screen); - - // Resizes to the new location. - void Resize(const gfx::Point& location_in_screen, int event_flags); - - // Completes the resize. - void CompleteResize(int event_flags); - - // Cancels the resize. - void CancelResize(); - - // Returns the bounds for the resize widget. - gfx::Rect CalculateResizeWidgetBounds( - const gfx::Point& location_in_parent) const; - - // Returns true if |location_in_screen| is over the resize windows - // (or the resize widget itself). - bool IsOverWindows(const gfx::Point& location_in_screen) const; - - // Returns true if |location_in_screen| is over |window|. - bool IsOverWindow(aura::Window* window, - const gfx::Point& location_in_screen, - int component) const; - - // Windows and direction to resize. - ResizeWindows windows_; - - // Timer before hiding. - base::OneShotTimer<MultiWindowResizeController> hide_timer_; - - // Timer used before showing. - base::OneShotTimer<MultiWindowResizeController> show_timer_; - - scoped_ptr<views::Widget> resize_widget_; - - // If non-null we're in a resize loop. - scoped_ptr<WorkspaceWindowResizer> window_resizer_; - - // Mouse coordinate passed to Show() in container's coodinates. - gfx::Point show_location_in_parent_; - - // Bounds the widget was last shown at in screen coordinates. - gfx::Rect show_bounds_in_screen_; - - // Used to detect whether the mouse is over the windows. While - // |resize_widget_| is non-NULL (ie the widget is showing) we ignore calls - // to Show(). - scoped_ptr<views::MouseWatcher> mouse_watcher_; - - DISALLOW_COPY_AND_ASSIGN(MultiWindowResizeController); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_ diff --git a/chromium/ash/wm/workspace/multi_window_resize_controller_unittest.cc b/chromium/ash/wm/workspace/multi_window_resize_controller_unittest.cc deleted file mode 100644 index a4756aa729d..00000000000 --- a/chromium/ash/wm/workspace/multi_window_resize_controller_unittest.cc +++ /dev/null @@ -1,258 +0,0 @@ -// 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/workspace/multi_window_resize_controller.h" - -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/shell_test_api.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace_controller.h" -#include "ash/wm/workspace_controller_test_helper.h" -#include "ash/wm/workspace/workspace_event_handler_test_helper.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.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 { -namespace internal { - -class MultiWindowResizeControllerTest : public test::AshTestBase { - public: - MultiWindowResizeControllerTest() : resize_controller_(NULL) {} - virtual ~MultiWindowResizeControllerTest() {} - - virtual void SetUp() OVERRIDE { - test::AshTestBase::SetUp(); - WorkspaceController* wc = - test::ShellTestApi(Shell::GetInstance()).workspace_controller(); - WorkspaceEventHandler* event_handler = - WorkspaceControllerTestHelper(wc).GetEventHandler(); - resize_controller_ = WorkspaceEventHandlerTestHelper(event_handler). - resize_controller(); - } - - protected: - aura::Window* CreateTestWindow(aura::WindowDelegate* delegate, - const gfx::Rect& bounds) { - aura::Window* window = new aura::Window(delegate); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - ParentWindowInPrimaryRootWindow(window); - window->SetBounds(bounds); - window->Show(); - return window; - } - - void ShowNow() { - resize_controller_->ShowNow(); - } - - bool IsShowing() { - return resize_controller_->IsShowing(); - } - - bool HasPendingShow() { - return resize_controller_->show_timer_.IsRunning(); - } - - bool HasPendingHide() { - return resize_controller_->hide_timer_.IsRunning(); - } - - void Hide() { - resize_controller_->Hide(); - } - - bool HasTarget(aura::Window* window) { - if (!resize_controller_->windows_.is_valid()) - return false; - if ((resize_controller_->windows_.window1 == window || - resize_controller_->windows_.window2 == window)) - return true; - for (size_t i = 0; - i < resize_controller_->windows_.other_windows.size(); ++i) { - if (resize_controller_->windows_.other_windows[i] == window) - return true; - } - return false; - } - - bool IsOverWindows(const gfx::Point& loc) { - return resize_controller_->IsOverWindows(loc); - } - - views::Widget* resize_widget() { - return resize_controller_->resize_widget_.get(); - } - - MultiWindowResizeController* resize_controller_; - - private: - DISALLOW_COPY_AND_ASSIGN(MultiWindowResizeControllerTest); -}; - -// Assertions around moving mouse over 2 windows. -TEST_F(MultiWindowResizeControllerTest, BasicTests) { - aura::test::TestWindowDelegate delegate1; - scoped_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); - delegate1.set_window_component(HTRIGHT); - aura::test::TestWindowDelegate delegate2; - scoped_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); - delegate2.set_window_component(HTRIGHT); - aura::test::EventGenerator generator(w1->GetRootWindow()); - generator.MoveMouseTo(99, 50); - EXPECT_TRUE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Force a show now. - ShowNow(); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - EXPECT_FALSE(IsOverWindows(gfx::Point(200, 200))); - - // Have to explicitly invoke this as MouseWatcher listens for native events. - resize_controller_->MouseMovedOutOfHost(); - EXPECT_FALSE(HasPendingShow()); - EXPECT_FALSE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); -} - -// Makes sure deleting a window hides. -TEST_F(MultiWindowResizeControllerTest, DeleteWindow) { - aura::test::TestWindowDelegate delegate1; - scoped_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); - delegate1.set_window_component(HTRIGHT); - aura::test::TestWindowDelegate delegate2; - scoped_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); - delegate2.set_window_component(HTRIGHT); - aura::test::EventGenerator generator(w1->GetRootWindow()); - generator.MoveMouseTo(99, 50); - EXPECT_TRUE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Force a show now. - ShowNow(); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Move the mouse over the resize widget. - ASSERT_TRUE(resize_widget()); - gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen()); - generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Move the resize widget - generator.PressLeftButton(); - generator.MoveMouseTo(bounds.x() + 10, bounds.y() + 10); - - // Delete w2. - w2.reset(); - EXPECT_TRUE(resize_widget() == NULL); - EXPECT_FALSE(HasPendingShow()); - EXPECT_FALSE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - EXPECT_FALSE(HasTarget(w1.get())); -} - -// Tests resizing. -TEST_F(MultiWindowResizeControllerTest, Drag) { - aura::test::TestWindowDelegate delegate1; - scoped_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); - delegate1.set_window_component(HTRIGHT); - aura::test::TestWindowDelegate delegate2; - scoped_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); - delegate2.set_window_component(HTRIGHT); - aura::test::EventGenerator generator(w1->GetRootWindow()); - generator.MoveMouseTo(99, 50); - EXPECT_TRUE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Force a show now. - ShowNow(); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Move the mouse over the resize widget. - ASSERT_TRUE(resize_widget()); - gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen()); - generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Move the resize widget - generator.PressLeftButton(); - generator.MoveMouseTo(bounds.x() + 11, bounds.y() + 10); - generator.ReleaseLeftButton(); - - EXPECT_TRUE(resize_widget()); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - EXPECT_EQ("0,0 110x100", w1->bounds().ToString()); - EXPECT_EQ("110,0 100x100", w2->bounds().ToString()); -} - -// Makes sure three windows are picked up. -TEST_F(MultiWindowResizeControllerTest, Three) { - aura::test::TestWindowDelegate delegate1; - scoped_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); - delegate1.set_window_component(HTRIGHT); - aura::test::TestWindowDelegate delegate2; - scoped_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); - delegate2.set_window_component(HTRIGHT); - aura::test::TestWindowDelegate delegate3; - scoped_ptr<aura::Window> w3( - CreateTestWindow(&delegate2, gfx::Rect(200, 0, 100, 100))); - delegate3.set_window_component(HTRIGHT); - - aura::test::EventGenerator generator(w1->GetRootWindow()); - generator.MoveMouseTo(99, 50); - EXPECT_TRUE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - EXPECT_FALSE(HasTarget(w3.get())); - - ShowNow(); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // w3 should be picked up when resize is started. - gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen()); - generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1); - generator.PressLeftButton(); - generator.MoveMouseTo(bounds.x() + 11, bounds.y() + 10); - - EXPECT_TRUE(HasTarget(w3.get())); - - // Release the mouse. The resizer should still be visible and a subsequent - // press should not trigger a DCHECK. - generator.ReleaseLeftButton(); - EXPECT_TRUE(IsShowing()); - generator.PressLeftButton(); -} -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/phantom_window_controller.cc b/chromium/ash/wm/workspace/phantom_window_controller.cc deleted file mode 100644 index 83a0e3fdcb0..00000000000 --- a/chromium/ash/wm/workspace/phantom_window_controller.cc +++ /dev/null @@ -1,214 +0,0 @@ -// 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/workspace/phantom_window_controller.h" - -#include "ash/shell.h" -#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/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/animation/slide_animation.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/skia_util.h" -#include "ui/views/background.h" -#include "ui/views/painter.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -// EdgePainter ---------------------------------------------------------------- - -namespace { - -// Paints the background of the phantom window for window snapping. -class EdgePainter : public views::Painter { - public: - EdgePainter(); - virtual ~EdgePainter(); - - // views::Painter: - virtual gfx::Size GetMinimumSize() const OVERRIDE; - virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(EdgePainter); -}; - -} // namespace - - -EdgePainter::EdgePainter() { -} - -EdgePainter::~EdgePainter() { -} - -gfx::Size EdgePainter::GetMinimumSize() const { - return gfx::Size(); -} - -void EdgePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) { - const int kInsetSize = 4; - int x = kInsetSize; - int y = kInsetSize; - int w = size.width() - kInsetSize * 2; - int h = size.height() - kInsetSize * 2; - bool inset = (w > 0 && h > 0); - if (!inset) { - x = 0; - y = 0; - w = size.width(); - h = size.height(); - } - SkPaint paint; - paint.setColor(SkColorSetARGB(100, 0, 0, 0)); - paint.setStyle(SkPaint::kFill_Style); - paint.setAntiAlias(true); - const int kRoundRectSize = 4; - canvas->sk_canvas()->drawRoundRect( - gfx::RectToSkRect(gfx::Rect(x, y, w, h)), - SkIntToScalar(kRoundRectSize), SkIntToScalar(kRoundRectSize), paint); - if (!inset) - return; - - paint.setColor(SkColorSetARGB(200, 255, 255, 255)); - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(SkIntToScalar(2)); - canvas->sk_canvas()->drawRoundRect( - gfx::RectToSkRect(gfx::Rect(x, y, w, h)), SkIntToScalar(kRoundRectSize), - SkIntToScalar(kRoundRectSize), paint); -} - - -// PhantomWindowController ---------------------------------------------------- - -PhantomWindowController::PhantomWindowController(aura::Window* window) - : window_(window), - phantom_below_window_(NULL), - phantom_widget_(NULL), - phantom_widget_start_(NULL) { -} - -PhantomWindowController::~PhantomWindowController() { - Hide(); -} - -void PhantomWindowController::Show(const gfx::Rect& bounds_in_screen) { - if (bounds_in_screen == bounds_in_screen_) - return; - bounds_in_screen_ = bounds_in_screen; - aura::Window* 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_) - start_bounds_ = window_->GetBoundsInScreen(); - 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::Window* start_root = wm::GetRootWindowMatching(start_bounds_); - if (start_root == target_root) { - aura::Window::Windows 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 gfx::SlideAnimation(this)); - animation_->SetTweenType(gfx::Tween::EASE_IN); - const int kAnimationDurationMS = 200; - animation_->SetSlideDuration(kAnimationDurationMS); - animation_->Show(); -} - -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 { - return phantom_widget_ != NULL; -} - -void PhantomWindowController::AnimationProgressed( - const gfx::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); -} - -views::Widget* PhantomWindowController::CreatePhantomWidget( - aura::Window* root_window, - const gfx::Rect& bounds_in_screen) { - views::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, - 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); - 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); - if (phantom_below_window_) - phantom_widget->StackBelow(phantom_below_window_); - else - phantom_widget->StackAbove(window_); - - // Show the widget after all the setups. - phantom_widget->Show(); - - // Fade the window in. - 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 -} // namespace ash diff --git a/chromium/ash/wm/workspace/phantom_window_controller.h b/chromium/ash/wm/workspace/phantom_window_controller.h deleted file mode 100644 index 77d4a286035..00000000000 --- a/chromium/ash/wm/workspace/phantom_window_controller.h +++ /dev/null @@ -1,103 +0,0 @@ -// 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_WORKSPACE_PHANTOM_WINDOW_CONTROLLER_H_ -#define ASH_WM_WORKSPACE_PHANTOM_WINDOW_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "ui/gfx/animation/animation_delegate.h" -#include "ui/gfx/rect.h" - -namespace aura { -class Window; -} - -namespace gfx { -class SlideAnimation; -} - -namespace views { -class Widget; -} - -namespace ash { -namespace internal { - -// PhantomWindowController is responsible for showing a phantom representation -// of a window. It's used used during dragging a window to show a snap location. -class ASH_EXPORT PhantomWindowController : public gfx::AnimationDelegate { - public: - explicit PhantomWindowController(aura::Window* window); - virtual ~PhantomWindowController(); - - // Bounds last passed to Show(). - const gfx::Rect& bounds_in_screen() const { return bounds_in_screen_; } - - // 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. - // This does not immediately show the window. - void Show(const gfx::Rect& bounds_in_screen); - - // Hides the phantom. - void Hide(); - - // Returns true if the phantom is showing. - bool IsShowing() const; - - // If set, the phantom window is stacked below this window, otherwise it - // is stacked above the window passed to the constructor. - void set_phantom_below_window(aura::Window* phantom_below_window) { - phantom_below_window_ = phantom_below_window; - } - - // gfx::AnimationDelegate overrides: - virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; - - private: - FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomWindowShow); - - // Creates, shows and returns a phantom widget at |bounds| - // with kShellWindowId_ShelfContainer in |root_window| as a parent. - views::Widget* CreatePhantomWidget(aura::Window* root_window, - const gfx::Rect& bounds_in_screen); - - // Window the phantom is placed beneath. - aura::Window* window_; - - // 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. - gfx::Rect start_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<gfx::SlideAnimation> animation_; - - DISALLOW_COPY_AND_ASSIGN(PhantomWindowController); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_PHANTOM_WINDOW_CONTROLLER_H_ diff --git a/chromium/ash/wm/workspace/snap_sizer.cc b/chromium/ash/wm/workspace/snap_sizer.cc deleted file mode 100644 index ba35f6ac3cc..00000000000 --- a/chromium/ash/wm/workspace/snap_sizer.cc +++ /dev/null @@ -1,292 +0,0 @@ -// 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/workspace/snap_sizer.h" - -#include <cmath> - -#include "ash/ash_switches.h" -#include "ash/screen_ash.h" -#include "ash/wm/window_resizer.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/command_line.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/gfx/screen.h" - -namespace ash { -namespace internal { - -namespace { - -// A list of ideal window widths in DIP which will be used to populate the -// |usable_width_| list. -const int kIdealWidth[] = { 1280, 1024, 768, 640 }; - -// Windows are initially snapped to the size in |usable_width_| at index 0. -// The index into |usable_width_| is changed if any of the following happen: -// . The user stops moving the mouse for |kDelayBeforeIncreaseMS| and then -// moves the mouse again. -// . The mouse moves |kPixelsBeforeAdjust| horizontal pixels. -// . The mouse is against the edge of the screen and the mouse is moved -// |kMovesBeforeAdjust| times. -const int kDelayBeforeIncreaseMS = 500; -const int kMovesBeforeAdjust = 25; -const int kPixelsBeforeAdjust = 100; - -// The maximum fraction of the screen width that a snapped window is allowed -// to take up. -const int kMaximumScreenPercent = 90; - -// The width that a window should be snapped to if resizing is disabled in the -// SnapSizer for devices with small screen resolutions. -const int kDefaultWidthSmallScreen = 1024; - -// Returns the minimum width that |window| can be snapped to. The returned width -// may not be in the width list generated by BuildIdealWidthList(). -int GetMinWidth(aura::Window* window) { - return window->delegate() ? window->delegate()->GetMinimumSize().width() : 0; -} - -// Returns the maximum width that |window| can be snapped to. The returned width -// may not be in the width list generated by BuildIdealWidthList(). -// The aura::WindowDelegate's max size is ignored because -// ash::wm::CanSnapWindow() returns false when a max size is specified. -int GetMaxWidth(aura::Window* window) { - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); - return std::max(work_area.width() * kMaximumScreenPercent / 100, - GetMinWidth(window)); -} - -// Returns the width that |window| should be snapped to if resizing is disabled -// in the SnapSizer. -int GetDefaultWidth(aura::Window* window) { - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); - - int width = 0; - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshMultipleSnapWindowWidths)) { - width = work_area.width() / 2; - } else { - width = std::max(kDefaultWidthSmallScreen, work_area.width() / 2); - } - - width = std::min(width, GetMaxWidth(window)); - return std::max(width, GetMinWidth(window)); -} - -// Creates the list of possible width for the current screen configuration: -// Returns a list with items from |kIdealWidth| which fit on the screen and -// supplement it with the 'half of screen' size. Furthermore, add an entry for -// 90% of the screen size if it is smaller than the biggest value in the -// |kIdealWidth| list (to get a step between the values). -std::vector<int> BuildIdealWidthList(aura::Window* window) { - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshMultipleSnapWindowWidths)) { - return std::vector<int>(1u, GetDefaultWidth(window)); - } - - int minimum_width = GetMinWidth(window); - int maximum_width = GetMaxWidth(window); - - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); - int half_width = work_area.width() / 2; - if (half_width < minimum_width || half_width > maximum_width) - half_width = 0; - - std::vector<int> ideal_width_list; - for (size_t i = 0; i < arraysize(kIdealWidth); i++) { - if (kIdealWidth[i] >= minimum_width && kIdealWidth[i] <= maximum_width) { - if (i && !ideal_width_list.size() && maximum_width != kIdealWidth[i]) - ideal_width_list.push_back(maximum_width); - if (half_width > kIdealWidth[i]) - ideal_width_list.push_back(half_width); - if (half_width >= kIdealWidth[i]) - half_width = 0; - ideal_width_list.push_back(kIdealWidth[i]); - } - } - if (half_width) - ideal_width_list.push_back(half_width); - if (ideal_width_list.empty()) { - if (minimum_width > 0) - ideal_width_list.push_back(minimum_width); - else - ideal_width_list.push_back(maximum_width); - } - - return ideal_width_list; -} - -// Changes |window|'s bounds to |snap_bounds| while preserving the restore -// bounds. -void SnapWindowToBounds(wm::WindowState* window_state, - SnapSizer::Edge edge, - const gfx::Rect& snap_bounds) { - if (edge == SnapSizer::LEFT_EDGE) { - window_state->SnapLeft(snap_bounds); - } else { - window_state->SnapRight(snap_bounds); - } -} - -} // namespace - -SnapSizer::SnapSizer(wm::WindowState* window_state, - const gfx::Point& start, - Edge edge, - InputType input_type) - : window_state_(window_state), - edge_(edge), - time_last_update_(base::TimeTicks::Now()), - size_index_(0), - end_of_sequence_(false), - resize_disabled_(false), - num_moves_since_adjust_(0), - last_adjust_x_(start.x()), - last_update_x_(start.x()), - start_x_(start.x()), - input_type_(input_type), - usable_width_(BuildIdealWidthList(window_state->window())) { - DCHECK(!usable_width_.empty()); - target_bounds_ = GetTargetBounds(); -} - -SnapSizer::~SnapSizer() { -} - -void SnapSizer::SnapWindow(wm::WindowState* window_state, - SnapSizer::Edge edge) { - if (!window_state->CanSnap()) - return; - internal::SnapSizer sizer(window_state, gfx::Point(), edge, - internal::SnapSizer::OTHER_INPUT); - SnapWindowToBounds(window_state, edge, - sizer.GetSnapBounds(window_state->window()->bounds())); -} - -void SnapSizer::SnapWindowToTargetBounds() { - SnapWindowToBounds(window_state_, edge_, target_bounds()); -} - -void SnapSizer::Update(const gfx::Point& location) { - // See description above for details on this behavior. - num_moves_since_adjust_++; - if ((base::TimeTicks::Now() - time_last_update_).InMilliseconds() > - kDelayBeforeIncreaseMS) { - ChangeBounds(location.x(), - CalculateIncrement(location.x(), last_update_x_)); - } else { - bool along_edge = AlongEdge(location.x()); - int pixels_before_adjust = kPixelsBeforeAdjust; - if (input_type_ == TOUCH_MAXIMIZE_BUTTON_INPUT) { - const gfx::Rect& workspace_bounds = - window_state_->window()->parent()->bounds(); - if (start_x_ > location.x()) { - pixels_before_adjust = - std::min(pixels_before_adjust, start_x_ / 10); - } else { - pixels_before_adjust = - std::min(pixels_before_adjust, - (workspace_bounds.width() - start_x_) / 10); - } - } - if (std::abs(location.x() - last_adjust_x_) >= pixels_before_adjust || - (along_edge && num_moves_since_adjust_ >= kMovesBeforeAdjust)) { - ChangeBounds(location.x(), - CalculateIncrement(location.x(), last_adjust_x_)); - } - } - last_update_x_ = location.x(); - time_last_update_ = base::TimeTicks::Now(); -} - -gfx::Rect SnapSizer::GetSnapBounds(const gfx::Rect& bounds) { - int current = 0; - if (!resize_disabled_) { - for (current = usable_width_.size() - 1; current >= 0; current--) { - gfx::Rect target = GetTargetBoundsForSize(current); - if (target == bounds) { - ++current; - break; - } - } - } - if (current < 0) - current = 0; - return GetTargetBoundsForSize(current % usable_width_.size()); -} - -void SnapSizer::SelectDefaultSizeAndDisableResize() { - resize_disabled_ = true; - size_index_ = 0; - end_of_sequence_ = false; - target_bounds_ = GetTargetBounds(); -} - -gfx::Rect SnapSizer::GetTargetBoundsForSize(size_t size_index) const { - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_state_->window())); - int y = work_area.y(); - int max_y = work_area.bottom(); - int width = 0; - if (resize_disabled_) { - width = GetDefaultWidth(window_state_->window()); - } else { - DCHECK(size_index < usable_width_.size()); - width = usable_width_[size_index]; - } - - if (edge_ == LEFT_EDGE) { - int x = work_area.x(); - int mid_x = x + width; - return gfx::Rect(x, y, mid_x - x, max_y - y); - } - int max_x = work_area.right(); - int x = max_x - width; - return gfx::Rect(x , y, max_x - x, max_y - y); -} - -int SnapSizer::CalculateIncrement(int x, int reference_x) const { - if (AlongEdge(x)) - return 1; - if (x == reference_x) - return 0; - if (edge_ == LEFT_EDGE) { - if (x < reference_x) - return 1; - return -1; - } - // edge_ == RIGHT_EDGE. - if (x > reference_x) - return 1; - return -1; -} - -void SnapSizer::ChangeBounds(int x, int delta) { - end_of_sequence_ = - delta > 0 && size_index_ == static_cast<int>(usable_width_.size()) - 1; - int index = std::min(static_cast<int>(usable_width_.size()) - 1, - std::max(size_index_ + delta, 0)); - if (index != size_index_) { - size_index_ = index; - target_bounds_ = GetTargetBounds(); - } - num_moves_since_adjust_ = 0; - last_adjust_x_ = x; -} - -gfx::Rect SnapSizer::GetTargetBounds() const { - return GetTargetBoundsForSize(size_index_); -} - -bool SnapSizer::AlongEdge(int x) const { - gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_state_->window())); - return (x <= area.x()) || (x >= area.right() - 1); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/snap_sizer.h b/chromium/ash/wm/workspace/snap_sizer.h deleted file mode 100644 index b32c3c8c310..00000000000 --- a/chromium/ash/wm/workspace/snap_sizer.h +++ /dev/null @@ -1,140 +0,0 @@ -// 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_WORKSPACE_SNAP_SIZER_H_ -#define ASH_WM_WORKSPACE_SNAP_SIZER_H_ - -#include <vector> - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/time/time.h" -#include "ui/gfx/rect.h" - -namespace ash { -namespace wm { -class WindowState; -} - -namespace internal { - -// SnapSizer is responsible for determining the resulting bounds of a window -// that is being snapped to the left or right side of the screen. -// The bounds used in this class are in the container's coordinates. -class ASH_EXPORT SnapSizer { - public: - enum Edge { - LEFT_EDGE, - RIGHT_EDGE - }; - - enum InputType { - TOUCH_MAXIMIZE_BUTTON_INPUT, - OTHER_INPUT - }; - - // Set |input_type| to |TOUCH_MAXIMIZE_BUTTON_INPUT| when called by a touch - // operation by the maximize button. This will allow the user to snap resize - // the window beginning close to the border. - SnapSizer(wm::WindowState* window_state, - const gfx::Point& start, - Edge edge, - InputType input_type); - virtual ~SnapSizer(); - - // Snaps a window left or right. - static void SnapWindow(wm::WindowState* window_state, Edge edge); - - // Snaps |window_| to the target bounds. - void SnapWindowToTargetBounds(); - - // Updates the target bounds based on a mouse move. - void Update(const gfx::Point& location); - - // Bounds to position the window at. - const gfx::Rect& target_bounds() const { return target_bounds_; } - - // Returns the appropriate snap bounds (e.g. if a window is already snapped, - // then it returns the next snap-bounds). - gfx::Rect GetSnapBounds(const gfx::Rect& bounds); - - // Set the snap sizer to the button press default size and prevent resizing. - void SelectDefaultSizeAndDisableResize(); - - // Returns the target bounds based on the edge and the provided |size_index|. - // For unit test purposes this function is not private. - gfx::Rect GetTargetBoundsForSize(size_t size_index) const; - - // Returns true when snapping sequence is at its last (docking) step. - bool end_of_sequence() const { return end_of_sequence_; } - - private: - // Calculates the amount to increment by. This returns one of -1, 0 or 1 and - // is intended to by applied to |size_index_|. |x| is the current - // x-coordinate, and |reference_x| is used to determine whether to increase - // or decrease the position. It's one of |last_adjust_x_| or |last_update_x_|. - int CalculateIncrement(int x, int reference_x) const; - - // Changes the bounds. |x| is the current x-coordinate and |delta| the amount - // to increase by. |delta| comes from CalculateIncrement() and is applied - // to |size_index_|. - void ChangeBounds(int x, int delta); - - // Returns the target bounds based on the edge and |size_index_|. - gfx::Rect GetTargetBounds() const; - - // Returns true if the specified point is along the edge of the screen. - bool AlongEdge(int x) const; - - // WindowState of the window being snapped. - wm::WindowState* window_state_; - - const Edge edge_; - - // Current target bounds for the snap. - gfx::Rect target_bounds_; - - // Time Update() was last invoked. - base::TimeTicks time_last_update_; - - // Index into |kSizes| that dictates the width of the screen the target - // bounds should get. - int size_index_; - - // Set to true when an attempt is made to increment |size_index_| past - // the size of |usable_width_|. - bool end_of_sequence_; - - // If set, |size_index_| will get ignored and the single button default - // setting will be used instead. - bool resize_disabled_; - - // Number of times Update() has been invoked since last ChangeBounds(). - int num_moves_since_adjust_; - - // X-coordinate the last time ChangeBounds() was invoked. - int last_adjust_x_; - - // X-coordinate last supplied to Update(). - int last_update_x_; - - // Initial x-coordinate. - const int start_x_; - - // |TOUCH_MAXIMIZE_BUTTON_INPUT| if the snap sizer was created through a - // touch & drag operation of the maximizer button. It changes the behavior of - // the drag / resize behavior when the dragging starts close to the border. - const InputType input_type_; - - // A list of usable window widths for size. This gets created when the - // sizer gets created. - const std::vector<int> usable_width_; - - DISALLOW_COPY_AND_ASSIGN(SnapSizer); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_SNAP_SIZER_H_ diff --git a/chromium/ash/wm/workspace/snap_sizer_unittest.cc b/chromium/ash/wm/workspace/snap_sizer_unittest.cc deleted file mode 100644 index 81a09f93940..00000000000 --- a/chromium/ash/wm/workspace/snap_sizer_unittest.cc +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2013 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/workspace/snap_sizer.h" - -#include "ash/ash_switches.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/command_line.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/window.h" -#include "ui/gfx/screen.h" - -namespace ash { - -typedef test::AshTestBase SnapSizerTest; - -using internal::SnapSizer; - -// Test that a window gets properly snapped to the display's edges in a -// multi monitor environment. -TEST_F(SnapSizerTest, MultipleDisplays) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("0+0-500x400, 0+500-600x400"); - const gfx::Rect kPrimaryDisplayWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - const gfx::Rect kSecondaryDisplayWorkAreaBounds = - ScreenAsh::GetSecondaryDisplay().work_area(); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - gfx::Rect expected = gfx::Rect( - kPrimaryDisplayWorkAreaBounds.x(), - kPrimaryDisplayWorkAreaBounds.y(), - window->bounds().width(), // No expectation for the width. - kPrimaryDisplayWorkAreaBounds.height()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - // The width should not change when a window switches from being snapped to - // the left edge to being snapped to the right edge. - expected.set_x(kPrimaryDisplayWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Move the window to the secondary display. - window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100), - ScreenAsh::GetSecondaryDisplay()); - - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected = gfx::Rect( - kSecondaryDisplayWorkAreaBounds.right() - window->bounds().width(), - kSecondaryDisplayWorkAreaBounds.y(), - window->bounds().width(), // No expectation for the width. - kSecondaryDisplayWorkAreaBounds.height()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - // The width should not change when a window switches from being snapped to - // the right edge to being snapped to the left edge. - expected.set_x(kSecondaryDisplayWorkAreaBounds.x()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); -} - -// Test how the minimum and maximum size specified by the aura::WindowDelegate -// affect snapping. -TEST_F(SnapSizerTest, MinimumSize) { - if (!SupportsHostWindowResize()) - return; - - UpdateDisplay("0+0-600x800"); - const gfx::Rect kWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - - aura::test::TestWindowDelegate delegate; - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate( - &delegate, -1, gfx::Rect(0, 100, kWorkAreaBounds.width() - 1, 100))); - - // It should be possible to snap a window with a minimum size. - delegate.set_minimum_size(gfx::Size(kWorkAreaBounds.width() - 1, 0)); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - EXPECT_TRUE(window_state->CanSnap()); - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x() + 1, - kWorkAreaBounds.y(), - kWorkAreaBounds.width() - 1, - kWorkAreaBounds.height()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // It should not be possible to snap a window with a maximum size. - delegate.set_minimum_size(gfx::Size()); - delegate.set_maximum_size(gfx::Size(kWorkAreaBounds.width() - 1, INT_MAX)); - EXPECT_FALSE(window_state->CanSnap()); -} - -// Test that repeatedly calling SnapSizer::SnapWindow() when the -// --ash-multiple-snap-window-widths flag is set steps through the ideal widths -// in descending order as well as 90% and 50% of the work area's width. -TEST_F(SnapSizerTest, StepThroughSizes) { - if (!SupportsHostWindowResize()) - return; - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshMultipleSnapWindowWidths); - - UpdateDisplay("1024x800"); - const gfx::Rect kWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - // Make sure that the work area is the size we expect it to be. - EXPECT_GT(kWorkAreaBounds.width() * 0.9, 768); - - // The first width should be 1024 * 0.9 because the larger ideal widths - // (1280, 1024) > 1024 * 0.9. - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(), - kWorkAreaBounds.y(), - kWorkAreaBounds.width() * 0.9, - kWorkAreaBounds.height()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - expected.set_width(768); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - expected.set_width(640); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - expected.set_width(kWorkAreaBounds.width() * 0.5); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Wrap around. - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - expected.set_width(kWorkAreaBounds.width() * 0.9); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Repeat the test snapping right. - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_width(kWorkAreaBounds.width() * 0.9); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_width(768); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_width(640); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_width(kWorkAreaBounds.width() * 0.5); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Wrap around. - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_width(kWorkAreaBounds.width() * 0.9); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); -} - -// Test that a SnapSizer's target bounds always start from the widest possible -// bounds and that calling Update() steps through the ideal widths in descending -// order as well as 90% and 50% of the work area's width. -TEST_F(SnapSizerTest, Update) { - if (!SupportsHostWindowResize()) - return; - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshMultipleSnapWindowWidths); - UpdateDisplay("1024x800"); - const gfx::Rect kWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - - // Make sure that the work area is the size we expect it to be. - EXPECT_GT(kWorkAreaBounds.width() * 0.9, 768); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(), - kWorkAreaBounds.y(), - 768, - kWorkAreaBounds.height()); - - // The SnapSizer's target bounds should always start from the widest bounds - // (instead of the bounds with the next ideal width). - SnapSizer sizer(window_state, gfx::Point(800, 0), SnapSizer::LEFT_EDGE, - SnapSizer::OTHER_INPUT); - sizer.SnapWindowToTargetBounds(); - expected.set_width(kWorkAreaBounds.width() * .9); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - sizer.Update(gfx::Point(600, 0)); - sizer.SnapWindowToTargetBounds(); - expected.set_width(768); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - sizer.Update(gfx::Point(400, 0)); - sizer.SnapWindowToTargetBounds(); - expected.set_width(640); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - sizer.Update(gfx::Point(200, 0)); - sizer.SnapWindowToTargetBounds(); - expected.set_width(kWorkAreaBounds.width() * 0.5); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Do not wrap around. - sizer.Update(gfx::Point(0, 0)); - sizer.SnapWindowToTargetBounds(); - expected.set_width(kWorkAreaBounds.width() * 0.5); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); -} - -// Tests the SnapSizer's target bounds when resizing is disabled and the -// --ash-multiple-snap-window-widths flag is set. -TEST_F(SnapSizerTest, Default) { - if (!SupportsHostWindowResize()) - return; - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshMultipleSnapWindowWidths); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - SnapSizer sizer(wm::GetWindowState(window.get()), gfx::Point(), - SnapSizer::LEFT_EDGE, SnapSizer::OTHER_INPUT); - - // For small workspace widths, we should snap to 90% of the workspace width - // because it is the largest width the window can snap to. - UpdateDisplay("0+0-800x600"); - sizer.SelectDefaultSizeAndDisableResize(); - - gfx::Rect work_area = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - gfx::Rect expected(work_area); - expected.set_width(work_area.width() * 0.9); - EXPECT_EQ(expected.ToString(), - ScreenAsh::ConvertRectToScreen(window->parent(), - sizer.target_bounds()).ToString()); - - // If the largest width the window can snap to is between 1024 and 1280, we - // should snap to 1024. - UpdateDisplay("0+0-1280x800"); - sizer.SelectDefaultSizeAndDisableResize(); - sizer.SnapWindowToTargetBounds(); - EXPECT_EQ(1024, window->bounds().width()); - - // We should snap to a width of 50% of the work area if it is the largest - // width the window can snap to. - UpdateDisplay("0+0-2560x1080"); - work_area = ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - sizer.SelectDefaultSizeAndDisableResize(); - sizer.SnapWindowToTargetBounds(); - EXPECT_EQ(work_area.width() / 2, window->bounds().width()); -} - -// Test that the window only snaps to 50% of the work area width when the -// --ash-multiple-snap-window-widths flag is not set. -TEST_F(SnapSizerTest, SingleSnapWindowWidth) { - if (!SupportsHostWindowResize()) - return; - - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshMultipleSnapWindowWidths)) { - return; - } - - UpdateDisplay("0+0-800x600"); - const gfx::Rect kWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(), - kWorkAreaBounds.y(), - kWorkAreaBounds.width() / 2, - kWorkAreaBounds.height()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Because a window can only be snapped to one size when using the alternate - // caption button style, a second call to SnapSizer::SnapWindow() should have - // no effect. - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // It should still be possible to switch a window from being snapped to the - // left edge to being snapped to the right edge. - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // If resizing is disabled, the window should be snapped to 50% too. - SnapSizer sizer1(window_state, gfx::Point(), SnapSizer::RIGHT_EDGE, - SnapSizer::OTHER_INPUT); - sizer1.SelectDefaultSizeAndDisableResize(); - sizer1.SnapWindowToTargetBounds(); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Snapping to a SnapSizer's initial bounds snaps to 50% too. - SnapSizer sizer2(window_state, gfx::Point(), SnapSizer::LEFT_EDGE, - SnapSizer::OTHER_INPUT); - sizer2.SnapWindowToTargetBounds(); - expected.set_x(kWorkAreaBounds.x()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); -} - -// Test that snapping left/right preserves the restore bounds. -TEST_F(SnapSizerTest, RestoreBounds) { - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - EXPECT_TRUE(window_state->IsNormalShowState()); - - // 1) Start with restored window with restore bounds set. - gfx::Rect restore_bounds = window->GetBoundsInScreen(); - restore_bounds.set_width(restore_bounds.width() + 1); - window_state->SetRestoreBoundsInScreen(restore_bounds); - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - EXPECT_NE(restore_bounds.ToString(), window->GetBoundsInScreen().ToString()); - EXPECT_EQ(restore_bounds.ToString(), - window_state->GetRestoreBoundsInScreen().ToString()); - window_state->Restore(); - EXPECT_EQ(restore_bounds.ToString(), window->GetBoundsInScreen().ToString()); - - // 2) Start with restored bounds set as a result of maximizing the window. - window_state->Maximize(); - gfx::Rect maximized_bounds = window->GetBoundsInScreen(); - EXPECT_NE(maximized_bounds.ToString(), restore_bounds.ToString()); - EXPECT_EQ(restore_bounds.ToString(), - window_state->GetRestoreBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - EXPECT_NE(restore_bounds.ToString(), window->GetBoundsInScreen().ToString()); - EXPECT_NE(maximized_bounds.ToString(), - window->GetBoundsInScreen().ToString()); - EXPECT_EQ(restore_bounds.ToString(), - window_state->GetRestoreBoundsInScreen().ToString()); - - window_state->Restore(); - EXPECT_EQ(restore_bounds.ToString(), window->GetBoundsInScreen().ToString()); -} - -// Test that maximizing an auto managed window, then snapping it puts the window -// at the snapped bounds and not at the auto-managed (centered) bounds. -TEST_F(SnapSizerTest, AutoManaged) { - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0)); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->set_window_position_managed(true); - window->Hide(); - window->SetBounds(gfx::Rect(100, 100, 100, 100)); - window->Show(); - - window_state->Maximize(); - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - - const gfx::Rect kWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - gfx::Rect expected_snapped_bounds( - kWorkAreaBounds.right() - window->bounds().width(), - kWorkAreaBounds.y(), - window->bounds().width(), // No expectation for the width. - kWorkAreaBounds.height()); - EXPECT_EQ(expected_snapped_bounds.ToString(), - window->GetBoundsInScreen().ToString()); - - // The window should still be auto managed despite being right maximized. - EXPECT_TRUE(window_state->window_position_managed()); -} - -} // namespace ash diff --git a/chromium/ash/wm/workspace/snap_types.h b/chromium/ash/wm/workspace/snap_types.h deleted file mode 100644 index 482a7dd583b..00000000000 --- a/chromium/ash/wm/workspace/snap_types.h +++ /dev/null @@ -1,23 +0,0 @@ -// 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_WORKSPACE_SNAP_TYPES_H_ -#define ASH_WM_WORKSPACE_SNAP_TYPES_H_ - -namespace ash { - -// These are the window snap types which can be used for window resizing. -// Their main use case is the class FrameMaximizeButton. -enum SnapType { - SNAP_LEFT, - SNAP_RIGHT, - SNAP_MAXIMIZE, - SNAP_MINIMIZE, - SNAP_RESTORE, - SNAP_NONE -}; - -} // namespace ash - -#endif // ASH_WM_WORKSPACE_SNAP_TYPES_H_ diff --git a/chromium/ash/wm/workspace/workspace_event_handler.cc b/chromium/ash/wm/workspace/workspace_event_handler.cc deleted file mode 100644 index bcd7e9e1d64..00000000000 --- a/chromium/ash/wm/workspace/workspace_event_handler.cc +++ /dev/null @@ -1,180 +0,0 @@ -// 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/workspace/workspace_event_handler.h" - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/touch/touch_uma.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/workspace_window_resizer.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" -#include "ui/gfx/screen.h" - -namespace ash { -namespace { - -void SingleAxisMaximize(wm::WindowState* window_state, - const gfx::Rect& maximize_rect_in_screen) { - window_state->SaveCurrentBoundsForRestore(); - window_state->SetBoundsInScreen(maximize_rect_in_screen); -} - -void SingleAxisUnmaximize(wm::WindowState* window_state, - const gfx::Rect& restore_bounds_in_screen) { - window_state->SetBoundsInScreen(restore_bounds_in_screen); - window_state->ClearRestoreBounds(); -} - -void ToggleMaximizedState(wm::WindowState* window_state) { - if (window_state->HasRestoreBounds()) { - if (window_state->GetShowState() == ui::SHOW_STATE_NORMAL) { - window_state->window()->SetBounds( - window_state->GetRestoreBoundsInParent()); - window_state->ClearRestoreBounds(); - } else { - window_state->Restore(); - } - } else if (window_state->CanMaximize()) { - window_state->Maximize(); - } -} - -} // namespace - -namespace internal { - -WorkspaceEventHandler::WorkspaceEventHandler(aura::Window* owner) - : ToplevelWindowEventHandler(owner) { -} - -WorkspaceEventHandler::~WorkspaceEventHandler() { -} - -void WorkspaceEventHandler::OnMouseEvent(ui::MouseEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - switch (event->type()) { - case ui::ET_MOUSE_MOVED: { - int component = - target->delegate()->GetNonClientComponent(event->location()); - multi_window_resize_controller_.Show(target, component, - event->location()); - break; - } - case ui::ET_MOUSE_ENTERED: - break; - case ui::ET_MOUSE_CAPTURE_CHANGED: - case ui::ET_MOUSE_EXITED: - break; - case ui::ET_MOUSE_PRESSED: { - // Maximize behavior is implemented as post-target handling so the target - // can cancel it. - if (ui::EventCanceledDefaultHandling(*event)) { - ToplevelWindowEventHandler::OnMouseEvent(event); - return; - } - wm::WindowState* target_state = wm::GetWindowState(target); - if (event->flags() & ui::EF_IS_DOUBLE_CLICK && - event->IsOnlyLeftMouseButton() && - target->delegate()->GetNonClientComponent(event->location()) == - HTCAPTION) { - ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( - ash::UMA_TOGGLE_MAXIMIZE_CAPTION_CLICK); - ToggleMaximizedState(target_state); - } - multi_window_resize_controller_.Hide(); - HandleVerticalResizeDoubleClick(target_state, event); - break; - } - default: - break; - } - ToplevelWindowEventHandler::OnMouseEvent(event); -} - -void WorkspaceEventHandler::OnGestureEvent(ui::GestureEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (event->type() == ui::ET_GESTURE_TAP && - target->delegate()->GetNonClientComponent(event->location()) == - HTCAPTION) { - if (event->details().tap_count() == 2) { - ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( - ash::UMA_TOGGLE_MAXIMIZE_CAPTION_GESTURE); - // Note: TouchUMA::GESTURE_FRAMEVIEW_TAP is counted twice each time - // TouchUMA::GESTURE_MAXIMIZE_DOUBLETAP is counted once. - TouchUMA::GetInstance()->RecordGestureAction( - TouchUMA::GESTURE_MAXIMIZE_DOUBLETAP); - ToggleMaximizedState(wm::GetWindowState(target)); - event->StopPropagation(); - return; - } else { - // Note: TouchUMA::GESTURE_FRAMEVIEW_TAP is counted twice for each tap. - TouchUMA::GetInstance()->RecordGestureAction( - TouchUMA::GESTURE_FRAMEVIEW_TAP); - } - } - ToplevelWindowEventHandler::OnGestureEvent(event); -} - -void WorkspaceEventHandler::HandleVerticalResizeDoubleClick( - wm::WindowState* target_state, - ui::MouseEvent* event) { - aura::Window* target = target_state->window(); - gfx::Rect max_size(target->delegate()->GetMaximumSize()); - if (event->flags() & ui::EF_IS_DOUBLE_CLICK && !target_state->IsMaximized()) { - int component = - target->delegate()->GetNonClientComponent(event->location()); - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - target).work_area(); - if (component == HTBOTTOM || component == HTTOP) { - // Don't maximize vertically if the window has a max height defined. - if (max_size.height() != 0) - return; - if (target_state->HasRestoreBounds() && - (target->bounds().height() == work_area.height() && - target->bounds().y() == work_area.y())) { - SingleAxisUnmaximize(target_state, - target_state->GetRestoreBoundsInScreen()); - } else { - gfx::Point origin = target->bounds().origin(); - wm::ConvertPointToScreen(target->parent(), &origin); - SingleAxisMaximize(target_state, - gfx::Rect(origin.x(), - work_area.y(), - target->bounds().width(), - work_area.height())); - } - } else if (component == HTLEFT || component == HTRIGHT) { - // Don't maximize horizontally if the window has a max width defined. - if (max_size.width() != 0) - return; - if (target_state->HasRestoreBounds() && - (target->bounds().width() == work_area.width() && - target->bounds().x() == work_area.x())) { - SingleAxisUnmaximize(target_state, - target_state->GetRestoreBoundsInScreen()); - } else { - gfx::Point origin = target->bounds().origin(); - wm::ConvertPointToScreen(target->parent(), &origin); - SingleAxisMaximize(target_state, - gfx::Rect(work_area.x(), - origin.y(), - work_area.width(), - target->bounds().height())); - } - } - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_event_handler.h b/chromium/ash/wm/workspace/workspace_event_handler.h deleted file mode 100644 index e8507e167bf..00000000000 --- a/chromium/ash/wm/workspace/workspace_event_handler.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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_WORKSPACE_WORKSPACE_EVENT_HANDLER_H_ -#define ASH_WM_WORKSPACE_WORKSPACE_EVENT_HANDLER_H_ - -#include "ash/wm/toplevel_window_event_handler.h" -#include "ash/wm/workspace/multi_window_resize_controller.h" - -namespace aura { -class Window; -} - -namespace ash { -namespace wm { -class WindowState; -} - -namespace internal { - -class WorkspaceEventHandlerTestHelper; - -class WorkspaceEventHandler : public ToplevelWindowEventHandler { - public: - explicit WorkspaceEventHandler(aura::Window* owner); - virtual ~WorkspaceEventHandler(); - - // Overridden from ToplevelWindowEventHandler: - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - private: - friend class WorkspaceEventHandlerTestHelper; - - // Determines if |event| corresponds to a double click on either the top or - // bottom vertical resize edge, and if so toggles the vertical height of the - // window between its restored state and the full available height of the - // workspace. - void HandleVerticalResizeDoubleClick(wm::WindowState* window_state, - ui::MouseEvent* event); - - MultiWindowResizeController multi_window_resize_controller_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceEventHandler); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_WORKSPACE_EVENT_HANDLER_H_ diff --git a/chromium/ash/wm/workspace/workspace_event_handler_test_helper.cc b/chromium/ash/wm/workspace/workspace_event_handler_test_helper.cc deleted file mode 100644 index 55b707b4402..00000000000 --- a/chromium/ash/wm/workspace/workspace_event_handler_test_helper.cc +++ /dev/null @@ -1,19 +0,0 @@ -// 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/workspace/workspace_event_handler_test_helper.h" - -namespace ash { -namespace internal { - -WorkspaceEventHandlerTestHelper::WorkspaceEventHandlerTestHelper( - WorkspaceEventHandler* handler) - : handler_(handler) { -} - -WorkspaceEventHandlerTestHelper::~WorkspaceEventHandlerTestHelper() { -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_event_handler_test_helper.h b/chromium/ash/wm/workspace/workspace_event_handler_test_helper.h deleted file mode 100644 index 21e1adb981b..00000000000 --- a/chromium/ash/wm/workspace/workspace_event_handler_test_helper.h +++ /dev/null @@ -1,31 +0,0 @@ -// 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_WORKSPACE_WORKSPACE_EVENT_HANDLER_TEST_HELPER_H_ -#define ASH_WM_WORKSPACE_WORKSPACE_EVENT_HANDLER_TEST_HELPER_H_ - -#include "ash/wm/workspace/workspace_event_handler.h" - -namespace ash { -namespace internal { - -class WorkspaceEventHandlerTestHelper { - public: - explicit WorkspaceEventHandlerTestHelper(WorkspaceEventHandler* handler); - ~WorkspaceEventHandlerTestHelper(); - - MultiWindowResizeController* resize_controller() { - return &(handler_->multi_window_resize_controller_); - } - - private: - WorkspaceEventHandler* handler_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceEventHandlerTestHelper); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_WORKSPACE_EVENT_HANDLER_TEST_HELPER_H_ diff --git a/chromium/ash/wm/workspace/workspace_event_handler_unittest.cc b/chromium/ash/wm/workspace/workspace_event_handler_unittest.cc deleted file mode 100644 index feec4bdbc6b..00000000000 --- a/chromium/ash/wm/workspace/workspace_event_handler_unittest.cc +++ /dev/null @@ -1,348 +0,0 @@ -// 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/workspace/workspace_event_handler.h" - -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace_controller.h" -#include "ash/wm/workspace_controller_test_helper.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/window.h" -#include "ui/base/hit_test.h" -#include "ui/gfx/screen.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - -namespace ash { -namespace internal { - -class WorkspaceEventHandlerTest : public test::AshTestBase { - public: - WorkspaceEventHandlerTest() {} - virtual ~WorkspaceEventHandlerTest() {} - - protected: - aura::Window* CreateTestWindow(aura::WindowDelegate* delegate, - const gfx::Rect& bounds) { - aura::Window* window = new aura::Window(delegate); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - ParentWindowInPrimaryRootWindow(window); - window->SetBounds(bounds); - window->Show(); - return window; - } - - private: - DISALLOW_COPY_AND_ASSIGN(WorkspaceEventHandlerTest); -}; - -// Keeps track of the properties changed of a particular window. -class WindowPropertyObserver : public aura::WindowObserver { - public: - explicit WindowPropertyObserver(aura::Window* window) - : window_(window) { - window->AddObserver(this); - } - - virtual ~WindowPropertyObserver() { - window_->RemoveObserver(this); - } - - bool DidPropertyChange(const void* property) const { - return std::find(properties_changed_.begin(), - properties_changed_.end(), - property) != properties_changed_.end(); - } - - private: - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE { - properties_changed_.push_back(key); - } - - aura::Window* window_; - std::vector<const void*> properties_changed_; - - DISALLOW_COPY_AND_ASSIGN(WindowPropertyObserver); -}; - -TEST_F(WorkspaceEventHandlerTest, DoubleClickSingleAxisResizeEdge) { - // Double clicking the vertical resize edge of a window should maximize it - // vertically. - gfx::Rect restored_bounds(10, 10, 50, 50); - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, restored_bounds)); - - wm::ActivateWindow(window.get()); - - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window.get()); - - // Double-click the top resize edge. - wd.set_window_component(HTTOP); - // On X a double click actually generates a drag between each press/release. - // Explicitly trigger this path since we had bugs in dealing with it - // correctly. - generator.PressLeftButton(); - generator.ReleaseLeftButton(); - generator.set_flags(ui::EF_IS_DOUBLE_CLICK); - generator.PressLeftButton(); - generator.MoveMouseTo(generator.current_location(), 1); - generator.ReleaseLeftButton(); - gfx::Rect bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.x(), bounds_in_screen.x()); - EXPECT_EQ(restored_bounds.width(), bounds_in_screen.width()); - EXPECT_EQ(work_area.y(), bounds_in_screen.y()); - EXPECT_EQ(work_area.height(), bounds_in_screen.height()); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - // Single-axis maximization is not considered real maximization. - EXPECT_FALSE(window_state->IsMaximized()); - - // Restore. - generator.DoubleClickLeftButton(); - bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.ToString(), bounds_in_screen.ToString()); - // Note that it should not even be restored at this point, it should have - // also cleared the restore rectangle. - EXPECT_FALSE(window_state->HasRestoreBounds()); - - // Double-click the top resize edge again to maximize vertically, then double - // click again to restore. - generator.DoubleClickLeftButton(); - wd.set_window_component(HTCAPTION); - generator.DoubleClickLeftButton(); - EXPECT_FALSE(window_state->IsMaximized()); - bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.ToString(), bounds_in_screen.ToString()); - - // Double clicking the left resize edge should maximize horizontally. - wd.set_window_component(HTLEFT); - generator.DoubleClickLeftButton(); - bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.y(), bounds_in_screen.y()); - EXPECT_EQ(restored_bounds.height(), bounds_in_screen.height()); - EXPECT_EQ(work_area.x(), bounds_in_screen.x()); - EXPECT_EQ(work_area.width(), bounds_in_screen.width()); - // Single-axis maximization is not considered real maximization. - EXPECT_FALSE(window_state->IsMaximized()); - - // Restore. - wd.set_window_component(HTCAPTION); - generator.DoubleClickLeftButton(); - EXPECT_EQ(restored_bounds.ToString(), window->GetBoundsInScreen().ToString()); - -#if defined(OS_WIN) - // Multi display test does not run on Win8 bot. crbug.com/247427. - if (base::win::GetVersion() >= base::win::VERSION_WIN8) - return; -#endif - - // Verify the double clicking the resize edge works on 2nd display too. - UpdateDisplay("200x200,400x300"); - gfx::Rect work_area2 = ScreenAsh::GetSecondaryDisplay().work_area(); - restored_bounds.SetRect(220,20, 50, 50); - window->SetBoundsInScreen(restored_bounds, ScreenAsh::GetSecondaryDisplay()); - aura::Window* second_root = Shell::GetAllRootWindows()[1]; - EXPECT_EQ(second_root, window->GetRootWindow()); - aura::test::EventGenerator generator2(second_root, window.get()); - - // Y-axis maximization. - wd.set_window_component(HTTOP); - generator2.PressLeftButton(); - generator2.ReleaseLeftButton(); - generator2.set_flags(ui::EF_IS_DOUBLE_CLICK); - generator2.PressLeftButton(); - generator2.MoveMouseTo(generator.current_location(), 1); - generator2.ReleaseLeftButton(); - generator.DoubleClickLeftButton(); - bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.x(), bounds_in_screen.x()); - EXPECT_EQ(restored_bounds.width(), bounds_in_screen.width()); - EXPECT_EQ(work_area2.y(), bounds_in_screen.y()); - EXPECT_EQ(work_area2.height(), bounds_in_screen.height()); - EXPECT_FALSE(window_state->IsMaximized()); - - // Restore. - wd.set_window_component(HTCAPTION); - generator2.DoubleClickLeftButton(); - EXPECT_EQ(restored_bounds.ToString(), window->GetBoundsInScreen().ToString()); - - // X-axis maximization. - wd.set_window_component(HTLEFT); - generator2.DoubleClickLeftButton(); - bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.y(), bounds_in_screen.y()); - EXPECT_EQ(restored_bounds.height(), bounds_in_screen.height()); - EXPECT_EQ(work_area2.x(), bounds_in_screen.x()); - EXPECT_EQ(work_area2.width(), bounds_in_screen.width()); - EXPECT_FALSE(window_state->IsMaximized()); - - // Restore. - wd.set_window_component(HTCAPTION); - generator2.DoubleClickLeftButton(); - EXPECT_EQ(restored_bounds.ToString(), window->GetBoundsInScreen().ToString()); -} - -TEST_F(WorkspaceEventHandlerTest, - DoubleClickSingleAxisDoesntResizeVerticalEdgeIfConstrained) { - gfx::Rect restored_bounds(10, 10, 50, 50); - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, restored_bounds)); - - wm::ActivateWindow(window.get()); - - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - - wd.set_maximum_size(gfx::Size(0, 100)); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window.get()); - // Double-click the top resize edge. - wd.set_window_component(HTTOP); - generator.DoubleClickLeftButton(); - - // The size of the window should be unchanged. - EXPECT_EQ(restored_bounds.y(), window->bounds().y()); - EXPECT_EQ(restored_bounds.height(), window->bounds().height()); -} - -TEST_F(WorkspaceEventHandlerTest, - DoubleClickSingleAxisDoesntResizeHorizontalEdgeIfConstrained) { - gfx::Rect restored_bounds(10, 10, 50, 50); - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, restored_bounds)); - - wm::ActivateWindow(window.get()); - - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - - wd.set_maximum_size(gfx::Size(100, 0)); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window.get()); - // Double-click the top resize edge. - wd.set_window_component(HTRIGHT); - generator.DoubleClickLeftButton(); - - // The size of the window should be unchanged. - EXPECT_EQ(restored_bounds.x(), window->bounds().x()); - EXPECT_EQ(restored_bounds.width(), window->bounds().width()); -} - -TEST_F(WorkspaceEventHandlerTest, DoubleClickCaptionTogglesMaximize) { - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> window( - CreateTestWindow(&wd, gfx::Rect(1, 2, 30, 40))); - window->SetProperty(aura::client::kCanMaximizeKey, true); - wd.set_window_component(HTCAPTION); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - EXPECT_FALSE(window_state->IsMaximized()); - aura::Window* root = Shell::GetPrimaryRootWindow(); - aura::test::EventGenerator generator(root, window.get()); - generator.DoubleClickLeftButton(); - EXPECT_NE("1,2 30x40", window->bounds().ToString()); - - EXPECT_TRUE(window_state->IsMaximized()); - generator.DoubleClickLeftButton(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_EQ("1,2 30x40", window->bounds().ToString()); - - // Double-clicking the middle button shouldn't toggle the maximized state. - WindowPropertyObserver observer(window.get()); - ui::MouseEvent press(ui::ET_MOUSE_PRESSED, generator.current_location(), - generator.current_location(), - ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK); - aura::WindowEventDispatcher* dispatcher = root->GetDispatcher(); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&press); - ui::MouseEvent release(ui::ET_MOUSE_RELEASED, generator.current_location(), - generator.current_location(), - ui::EF_IS_DOUBLE_CLICK); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&release); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_EQ("1,2 30x40", window->bounds().ToString()); - EXPECT_FALSE(observer.DidPropertyChange(aura::client::kShowStateKey)); -} - -TEST_F(WorkspaceEventHandlerTest, DoubleTapCaptionTogglesMaximize) { - aura::test::TestWindowDelegate wd; - gfx::Rect bounds(10, 20, 30, 40); - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, bounds)); - window->SetProperty(aura::client::kCanMaximizeKey, true); - wd.set_window_component(HTCAPTION); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - EXPECT_FALSE(window_state->IsMaximized()); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window.get()); - generator.GestureTapAt(gfx::Point(25, 25)); - generator.GestureTapAt(gfx::Point(25, 25)); - RunAllPendingInMessageLoop(); - EXPECT_NE(bounds.ToString(), window->bounds().ToString()); - EXPECT_TRUE(window_state->IsMaximized()); - - generator.GestureTapAt(gfx::Point(5, 5)); - generator.GestureTapAt(gfx::Point(10, 10)); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); -} - -// Verifies deleting the window while dragging doesn't crash. -TEST_F(WorkspaceEventHandlerTest, DeleteWhenDragging) { - // Create a large window in the background. This is necessary so that when we - // delete |window| WorkspaceEventHandler is still the active event handler. - aura::test::TestWindowDelegate wd2; - scoped_ptr<aura::Window> window2( - CreateTestWindow(&wd2, gfx::Rect(0, 0, 500, 500))); - - aura::test::TestWindowDelegate wd; - const gfx::Rect bounds(10, 20, 30, 40); - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, bounds)); - wd.set_window_component(HTCAPTION); - aura::test::EventGenerator generator(window->GetRootWindow()); - generator.MoveMouseToCenterOf(window.get()); - generator.PressLeftButton(); - generator.MoveMouseTo(generator.current_location() + gfx::Vector2d(50, 50)); - DCHECK_NE(bounds.origin().ToString(), window->bounds().origin().ToString()); - window.reset(); - generator.MoveMouseTo(generator.current_location() + gfx::Vector2d(50, 50)); -} - -// Verifies deleting the window while in a run loop doesn't crash. -TEST_F(WorkspaceEventHandlerTest, DeleteWhileInRunLoop) { - aura::test::TestWindowDelegate wd; - const gfx::Rect bounds(10, 20, 30, 40); - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, bounds)); - wd.set_window_component(HTCAPTION); - - ASSERT_TRUE(aura::client::GetWindowMoveClient(window->parent())); - base::MessageLoop::current()->DeleteSoon(FROM_HERE, window.get()); - aura::client::GetWindowMoveClient(window->parent()) - ->RunMoveLoop(window.release(), - gfx::Vector2d(), - aura::client::WINDOW_MOVE_SOURCE_MOUSE); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_layout_manager.cc b/chromium/ash/wm/workspace/workspace_layout_manager.cc deleted file mode 100644 index fe7d748d19b..00000000000 --- a/chromium/ash/wm/workspace/workspace_layout_manager.cc +++ /dev/null @@ -1,436 +0,0 @@ -// 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/workspace/workspace_layout_manager.h" - -#include "ash/display/display_controller.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/wm/always_on_top_controller.h" -#include "ash/wm/base_layout_manager.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_positioner.h" -#include "ash/wm/window_properties.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/base/ui_base_types.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/events/event.h" -#include "ui/views/corewm/window_util.h" - -using aura::Window; - -namespace ash { - -namespace internal { - -namespace { - -// This specifies how much percent 30% of a window rect (width / height) -// must be visible when the window is added to the workspace. -const float kMinimumPercentOnScreenArea = 0.3f; - -void MoveToDisplayForRestore(wm::WindowState* window_state) { - if (!window_state->HasRestoreBounds()) - return; - const gfx::Rect& restore_bounds = window_state->GetRestoreBoundsInScreen(); - - // Move only if the restore bounds is outside of - // 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. - gfx::Rect display_area = Shell::GetScreen()->GetDisplayNearestWindow( - window_state->window()).bounds(); - - if (!display_area.Intersects(restore_bounds)) { - DisplayController* display_controller = - Shell::GetInstance()->display_controller(); - const gfx::Display& display = - display_controller->GetDisplayMatching(restore_bounds); - aura::Window* new_root = - display_controller->GetRootWindowForDisplayId(display.id()); - if (new_root != window_state->window()->GetRootWindow()) { - aura::Window* new_container = - Shell::GetContainer(new_root, window_state->window()->parent()->id()); - new_container->AddChild(window_state->window()); - } - } -} - -} // namespace - -WorkspaceLayoutManager::WorkspaceLayoutManager(aura::Window* window) - : BaseLayoutManager(window->GetRootWindow()), - shelf_(NULL), - window_(window), - work_area_in_parent_(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window->parent())), - is_fullscreen_(GetRootWindowController( - window->GetRootWindow())->GetWindowForFullscreenMode() != NULL) { -} - -WorkspaceLayoutManager::~WorkspaceLayoutManager() { -} - -void WorkspaceLayoutManager::SetShelf(internal::ShelfLayoutManager* shelf) { - shelf_ = shelf; -} - -void WorkspaceLayoutManager::OnWindowAddedToLayout(Window* child) { - AdjustWindowBoundsWhenAdded(wm::GetWindowState(child)); - BaseLayoutManager::OnWindowAddedToLayout(child); - UpdateShelfVisibility(); - UpdateFullscreenState(); - WindowPositioner::RearrangeVisibleWindowOnShow(child); -} - -void WorkspaceLayoutManager::OnWillRemoveWindowFromLayout(Window* child) { - BaseLayoutManager::OnWillRemoveWindowFromLayout(child); - if (child->TargetVisibility()) - WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child); -} - -void WorkspaceLayoutManager::OnWindowRemovedFromLayout(Window* child) { - BaseLayoutManager::OnWindowRemovedFromLayout(child); - UpdateShelfVisibility(); - UpdateFullscreenState(); -} - -void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(Window* child, - bool visible) { - BaseLayoutManager::OnChildWindowVisibilityChanged(child, visible); - if (child->TargetVisibility()) { - WindowPositioner::RearrangeVisibleWindowOnShow(child); - } else { - if (wm::GetWindowState(child)->IsFullscreen()) - UpdateFullscreenState(); - WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child); - } - UpdateShelfVisibility(); -} - -void WorkspaceLayoutManager::SetChildBounds( - Window* child, - const gfx::Rect& requested_bounds) { - wm::WindowState* window_state = wm::GetWindowState(child); - if (window_state->is_dragged()) { - SetChildBoundsDirect(child, requested_bounds); - } else if (!SetMaximizedOrFullscreenBounds(window_state)) { - // Some windows rely on this to set their initial bounds. - // Non-maximized/full-screen windows have their size constrained to the - // work-area. - gfx::Rect child_bounds(requested_bounds); - child_bounds.set_width(std::min(work_area_in_parent_.width(), - child_bounds.width())); - child_bounds.set_height(std::min(work_area_in_parent_.height(), - child_bounds.height())); - AdjustSnappedBounds(window_state, &child_bounds); - SetChildBoundsDirect(child, child_bounds); - } - UpdateShelfVisibility(); -} - -void WorkspaceLayoutManager::OnDisplayWorkAreaInsetsChanged() { - const gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_->parent())); - if (work_area != work_area_in_parent_) { - AdjustAllWindowsBoundsForWorkAreaChange( - ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED); - } -} - -void WorkspaceLayoutManager::OnWindowPropertyChanged(Window* window, - const void* key, - intptr_t old) { - if (key == aura::client::kAlwaysOnTopKey && - window->GetProperty(aura::client::kAlwaysOnTopKey)) { - GetRootWindowController(window->GetRootWindow())-> - always_on_top_controller()->GetContainer(window)->AddChild(window); - } -} - -void WorkspaceLayoutManager::OnWindowStackingChanged(aura::Window* window) { - BaseLayoutManager::OnWindowStackingChanged(window); - UpdateShelfVisibility(); - UpdateFullscreenState(); -} - -void WorkspaceLayoutManager::OnWindowShowTypeChanged( - wm::WindowState* window_state, - wm::WindowShowType old_type) { - ui::WindowShowState old_state = ToWindowShowState(old_type); - ui::WindowShowState new_state = window_state->GetShowState(); - if (old_state != ui::SHOW_STATE_MINIMIZED && - !window_state->HasRestoreBounds() && - window_state->IsMaximizedOrFullscreen() && - !wm::WindowState::IsMaximizedOrFullscreenState(old_state)) { - window_state->SaveCurrentBoundsForRestore(); - } - // When restoring from a minimized state, we want to restore to the - // previous (maybe L/R maximized) state. Since we do also want to keep the - // restore rectangle, we set the restore rectangle to the rectangle we want - // to restore to and restore it after we switched so that it is preserved. - gfx::Rect restore; - if (old_state == ui::SHOW_STATE_MINIMIZED && - (new_state == ui::SHOW_STATE_NORMAL || - new_state == ui::SHOW_STATE_DEFAULT) && - window_state->HasRestoreBounds() && - !window_state->always_restores_to_restore_bounds()) { - restore = window_state->GetRestoreBoundsInScreen(); - window_state->SaveCurrentBoundsForRestore(); - } - // Notify observers that fullscreen state may be changing. - if (old_state != new_state && - (new_state == ui::SHOW_STATE_FULLSCREEN || - old_state == ui::SHOW_STATE_FULLSCREEN)) { - UpdateFullscreenState(); - } - - UpdateBoundsFromShowState(window_state, old_state); - ShowStateChanged(window_state, old_state); - - // Set the restore rectangle to the previously set restore rectangle. - if (!restore.IsEmpty()) - window_state->SetRestoreBoundsInScreen(restore); -} - -void WorkspaceLayoutManager::ShowStateChanged( - wm::WindowState* state, - ui::WindowShowState last_show_state) { - BaseLayoutManager::ShowStateChanged(state, last_show_state); - UpdateShelfVisibility(); -} - -void WorkspaceLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange( - AdjustWindowReason reason) { - work_area_in_parent_ = - ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_->parent()); - BaseLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange(reason); -} - -void WorkspaceLayoutManager::AdjustWindowBoundsForWorkAreaChange( - wm::WindowState* window_state, - AdjustWindowReason reason) { - if (window_state->is_dragged()) - return; - - // Do not cross fade here: the window's layer hierarchy may be messed up for - // the transition between mirroring and extended. See also: crbug.com/267698 - // TODO(oshima): Differentiate display change and shelf visibility change, and - // bring back CrossFade animation. - if (window_state->IsMaximized() && - reason == ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED) { - SetChildBoundsDirect(window_state->window(), - ScreenAsh::GetMaximizedWindowBoundsInParent( - window_state->window()->parent()->parent())); - return; - } - - if (SetMaximizedOrFullscreenBounds(window_state)) - return; - - gfx::Rect bounds = window_state->window()->bounds(); - switch (reason) { - case ADJUST_WINDOW_DISPLAY_SIZE_CHANGED: - // The work area may be smaller than the full screen. Put as much of the - // window as possible within the display area. - bounds.AdjustToFit(work_area_in_parent_); - break; - case ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED: - ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( - work_area_in_parent_, &bounds); - break; - } - AdjustSnappedBounds(window_state, &bounds); - if (window_state->window()->bounds() != bounds) - SetChildBoundsAnimated(window_state->window(), bounds); -} - -void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded( - wm::WindowState* window_state) { - // 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_state->window()->bounds().IsEmpty()) - return; - - if (window_state->is_dragged()) - return; - - if (SetMaximizedOrFullscreenBounds(window_state)) - return; - - Window* window = window_state->window(); - 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 = ScreenAsh::GetDisplayBoundsInParent(window); - - ash::wm::AdjustBoundsToEnsureWindowVisibility( - display_area, min_width, min_height, &bounds); - AdjustSnappedBounds(window_state, &bounds); - if (window->bounds() != bounds) - window->SetBounds(bounds); -} - -void WorkspaceLayoutManager::UpdateShelfVisibility() { - if (shelf_) - shelf_->UpdateVisibilityState(); -} - -void WorkspaceLayoutManager::UpdateFullscreenState() { - bool is_fullscreen = GetRootWindowController( - window_->GetRootWindow())->GetWindowForFullscreenMode() != NULL; - if (is_fullscreen != is_fullscreen_) { - ash::Shell::GetInstance()->NotifyFullscreenStateChange( - is_fullscreen, window_->GetRootWindow()); - is_fullscreen_ = is_fullscreen; - } -} - -void WorkspaceLayoutManager::UpdateBoundsFromShowState( - wm::WindowState* window_state, - ui::WindowShowState last_show_state) { - aura::Window* window = window_state->window(); - // See comment in SetMaximizedOrFullscreenBounds() as to why we use parent in - // these calculation. - // TODO(varkha): Change the switch statement below to use wm::WindowShowType. - switch (window_state->GetShowState()) { - case ui::SHOW_STATE_DEFAULT: - case ui::SHOW_STATE_NORMAL: { - // Make sure that the part of the window is always visible - // when restored. - gfx::Rect bounds_in_parent; - if (window_state->HasRestoreBounds()) { - bounds_in_parent = window_state->GetRestoreBoundsInParent(); - ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( - work_area_in_parent_, &bounds_in_parent); - } else { - // Minimized windows have no restore bounds. - // Use the current bounds instead. - bounds_in_parent = window->bounds(); - ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( - work_area_in_parent_, &bounds_in_parent); - // Don't start animation if the bounds didn't change. - if (bounds_in_parent == window->bounds()) - bounds_in_parent.SetRect(0, 0, 0, 0); - } - if (!bounds_in_parent.IsEmpty()) { - if ((last_show_state == ui::SHOW_STATE_DEFAULT || - last_show_state == ui::SHOW_STATE_NORMAL) && - window_state->IsSnapped()) { - AdjustSnappedBounds(window_state, &bounds_in_parent); - SetChildBoundsAnimated(window, bounds_in_parent); - } else { - gfx::Rect new_bounds = BaseLayoutManager::BoundsWithScreenEdgeVisible( - window->parent()->parent(), - bounds_in_parent); - if (last_show_state == ui::SHOW_STATE_MINIMIZED) - SetChildBoundsDirect(window, new_bounds); - else - CrossFadeToBounds(window, new_bounds); - } - } - window_state->ClearRestoreBounds(); - break; - } - - case ui::SHOW_STATE_MAXIMIZED: { - MoveToDisplayForRestore(window_state); - gfx::Rect new_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent( - window->parent()->parent()); - // If the window is restored from minimized state, do not make the cross - // fade animation and set the child bounds directly. The restoring - // animation will be done by ash/wm/window_animations.cc. - if (last_show_state == ui::SHOW_STATE_MINIMIZED) - SetChildBoundsDirect(window, new_bounds); - else - CrossFadeToBounds(window, new_bounds); - break; - } - - case ui::SHOW_STATE_FULLSCREEN: { - MoveToDisplayForRestore(window_state); - gfx::Rect new_bounds = ScreenAsh::GetDisplayBoundsInParent( - window->parent()->parent()); - if (window_state->animate_to_fullscreen() && - last_show_state != ui::SHOW_STATE_MINIMIZED) { - CrossFadeToBounds(window, new_bounds); - } else { - SetChildBoundsDirect(window, new_bounds); - } - break; - } - - default: - break; - } -} - -bool WorkspaceLayoutManager::SetMaximizedOrFullscreenBounds( - wm::WindowState* window_state) { - DCHECK(!window_state->is_dragged()); - - // During animations there is a transform installed on the workspace - // windows. For this reason this code uses the parent so that the transform is - // ignored. - if (window_state->IsMaximized()) { - SetChildBoundsDirect( - window_state->window(), ScreenAsh::GetMaximizedWindowBoundsInParent( - window_state->window()->parent()->parent())); - return true; - } - if (window_state->IsFullscreen()) { - SetChildBoundsDirect( - window_state->window(), - ScreenAsh::GetDisplayBoundsInParent( - window_state->window()->parent()->parent())); - return true; - } - return false; -} - -void WorkspaceLayoutManager::AdjustSnappedBounds(wm::WindowState* window_state, - gfx::Rect* bounds) { - if (window_state->is_dragged() || !window_state->IsSnapped()) - return; - gfx::Rect maximized_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent( - window_state->window()->parent()->parent()); - if (window_state->window_show_type() == wm::SHOW_TYPE_LEFT_SNAPPED) - bounds->set_x(maximized_bounds.x()); - else if (window_state->window_show_type() == wm::SHOW_TYPE_RIGHT_SNAPPED) - bounds->set_x(maximized_bounds.right() - bounds->width()); - bounds->set_y(maximized_bounds.y()); - // TODO(varkha): Set width to 50% here for snapped windows. - bounds->set_height(maximized_bounds.height()); -} - -void WorkspaceLayoutManager::SetChildBoundsAnimated(Window* child, - const gfx::Rect& bounds) { - const int kBoundsChangeSlideDurationMs = 120; - - ui::Layer* layer = child->layer(); - ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator()); - slide_settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - slide_settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kBoundsChangeSlideDurationMs)); - SetChildBoundsDirect(child, bounds); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_layout_manager.h b/chromium/ash/wm/workspace/workspace_layout_manager.h deleted file mode 100644 index ab4876c5b2e..00000000000 --- a/chromium/ash/wm/workspace/workspace_layout_manager.h +++ /dev/null @@ -1,115 +0,0 @@ -// 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_WORKSPACE_WORKSPACE_LAYOUT_MANAGER_H_ -#define ASH_WM_WORKSPACE_WORKSPACE_LAYOUT_MANAGER_H_ - -#include <set> - -#include "ash/shell_observer.h" -#include "ash/wm/base_layout_manager.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/base/ui_base_types.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/rect.h" - -namespace aura { -class RootWindow; -class Window; -} - -namespace ui { -class Layer; -} - -namespace ash { - -namespace internal { - -class ShelfLayoutManager; - -// LayoutManager used on the window created for a workspace. -class ASH_EXPORT WorkspaceLayoutManager : public BaseLayoutManager { - public: - explicit WorkspaceLayoutManager(aura::Window* window); - virtual ~WorkspaceLayoutManager(); - - void SetShelf(internal::ShelfLayoutManager* shelf); - - // Overridden from aura::LayoutManager: - virtual void OnWindowResized() OVERRIDE {} - virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; - virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; - virtual void OnChildWindowVisibilityChanged(aura::Window* child, - bool visibile) OVERRIDE; - virtual void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) OVERRIDE; - - // ash::ShellObserver overrides: - virtual void OnDisplayWorkAreaInsetsChanged() OVERRIDE; - - // Overriden from WindowObserver: - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE; - virtual void OnWindowStackingChanged(aura::Window* window) OVERRIDE; - - // WindowStateObserver overrides: - virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType old_type) OVERRIDE; - - private: - // Overridden from BaseLayoutManager: - virtual void ShowStateChanged(wm::WindowState* window_state, - ui::WindowShowState last_show_state) OVERRIDE; - virtual void AdjustAllWindowsBoundsForWorkAreaChange( - AdjustWindowReason reason) OVERRIDE; - virtual void AdjustWindowBoundsForWorkAreaChange( - wm::WindowState* window_state, - AdjustWindowReason reason) OVERRIDE; - - void AdjustWindowBoundsWhenAdded(wm::WindowState* window_state); - - // Updates the visibility state of the shelf. - void UpdateShelfVisibility(); - - // Updates the fullscreen state of the workspace and notifies Shell if it - // has changed. - void UpdateFullscreenState(); - - // Updates the bounds of the window for a show state change from - // |last_show_state|. - void UpdateBoundsFromShowState(wm::WindowState* window_state, - ui::WindowShowState last_show_state); - - // If |window_state| is maximized or fullscreen the bounds of the - // window are set and true is returned. Does nothing otherwise. - bool SetMaximizedOrFullscreenBounds(wm::WindowState* window_state); - - // Adjusts the |bounds| so that they are flush with the edge of the - // workspace if the window represented by |window_state| is side snapped. - void AdjustSnappedBounds(wm::WindowState* window_state, gfx::Rect* bounds); - - // Animates the window bounds to |bounds|. - void SetChildBoundsAnimated(aura::Window* child, const gfx::Rect& bounds); - - internal::ShelfLayoutManager* shelf_; - aura::Window* window_; - - // The work area. Cached to avoid unnecessarily moving windows during a - // workspace switch. - gfx::Rect work_area_in_parent_; - - // True if this workspace is currently in fullscreen mode. - bool is_fullscreen_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManager); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_WORKSPACE_LAYOUT_MANAGER_H_ diff --git a/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc b/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc deleted file mode 100644 index d12fb15bb79..00000000000 --- a/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc +++ /dev/null @@ -1,481 +0,0 @@ -// 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/workspace/workspace_layout_manager.h" - -#include "ash/display/display_layout.h" -#include "ash/display/display_manager.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/shell_observer.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/gfx/insets.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -namespace { - -class MaximizeDelegateView : public views::WidgetDelegateView { - public: - MaximizeDelegateView(const gfx::Rect& initial_bounds) - : initial_bounds_(initial_bounds) { - } - virtual ~MaximizeDelegateView() {} - - virtual bool GetSavedWindowPlacement( - const views::Widget* widget, - gfx::Rect* bounds, - ui::WindowShowState* show_state) const OVERRIDE { - *bounds = initial_bounds_; - *show_state = ui::SHOW_STATE_MAXIMIZED; - return true; - } - - private: - const gfx::Rect initial_bounds_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeDelegateView); -}; - -class TestShellObserver : public ShellObserver { - public: - TestShellObserver() : call_count_(0), - is_fullscreen_(false) { - Shell::GetInstance()->AddShellObserver(this); - } - - virtual ~TestShellObserver() { - Shell::GetInstance()->RemoveShellObserver(this); - } - - virtual void OnFullscreenStateChanged(bool is_fullscreen, - aura::Window* root_window) OVERRIDE { - call_count_++; - is_fullscreen_ = is_fullscreen; - } - - int call_count() const { - return call_count_; - } - - bool is_fullscreen() const { - return is_fullscreen_; - } - - private: - int call_count_; - bool is_fullscreen_; - - DISALLOW_COPY_AND_ASSIGN(TestShellObserver); -}; - -} // namespace - -typedef test::AshTestBase WorkspaceLayoutManagerTest; - -// Verifies that a window containing a restore coordinate will be restored to -// to the size prior to minimize, keeping the restore rectangle in tact (if -// there is one). -TEST_F(WorkspaceLayoutManagerTest, RestoreFromMinimizeKeepsRestore) { - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 3, 4))); - gfx::Rect bounds(10, 15, 25, 35); - window->SetBounds(bounds); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - // This will not be used for un-minimizing window. - window_state->SetRestoreBoundsInScreen(gfx::Rect(0, 0, 100, 100)); - window_state->Minimize(); - window_state->Restore(); - EXPECT_EQ("0,0 100x100", window_state->GetRestoreBoundsInScreen().ToString()); - EXPECT_EQ("10,15 25x35", window.get()->bounds().ToString()); - - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("400x300,500x400"); - window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100), - ScreenAsh::GetSecondaryDisplay()); - EXPECT_EQ(Shell::GetAllRootWindows()[1], window->GetRootWindow()); - window_state->Minimize(); - // This will not be used for un-minimizing window. - window_state->SetRestoreBoundsInScreen(gfx::Rect(0, 0, 100, 100)); - window_state->Restore(); - EXPECT_EQ("600,0 100x100", window->GetBoundsInScreen().ToString()); - - // Make sure the unminimized window moves inside the display when - // 2nd display is disconnected. - window_state->Minimize(); - UpdateDisplay("400x300"); - window_state->Restore(); - EXPECT_EQ(Shell::GetPrimaryRootWindow(), window->GetRootWindow()); - EXPECT_TRUE( - Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); -} - -TEST_F(WorkspaceLayoutManagerTest, KeepMinimumVisibilityInDisplays) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("300x400,400x500"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - DisplayLayout layout(DisplayLayout::TOP, 0); - Shell::GetInstance()->display_manager()-> - SetLayoutForCurrentDisplays(layout); - EXPECT_EQ("0,-500 400x500", root_windows[1]->GetBoundsInScreen().ToString()); - - scoped_ptr<aura::Window> window1( - CreateTestWindowInShellWithBounds(gfx::Rect(10, -400, 200, 200))); - EXPECT_EQ("10,-400 200x200", window1->GetBoundsInScreen().ToString()); - - // Make sure the caption is visible. - scoped_ptr<aura::Window> window2( - CreateTestWindowInShellWithBounds(gfx::Rect(10, -600, 200, 200))); - EXPECT_EQ("10,-500 200x200", window2->GetBoundsInScreen().ToString()); -} - -TEST_F(WorkspaceLayoutManagerTest, KeepRestoredWindowInDisplay) { - if (!SupportsHostWindowResize()) - return; - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - // Maximized -> Normal transition. - window_state->Maximize(); - window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 30, 40)); - window_state->Restore(); - EXPECT_TRUE( - Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); - // Y bounds should not be negative. - EXPECT_EQ("-20,0 30x40", window->bounds().ToString()); - - // Minimized -> Normal transition. - window->SetBounds(gfx::Rect(-100, -100, 30, 40)); - window_state->Minimize(); - EXPECT_FALSE( - Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); - EXPECT_EQ("-100,-100 30x40", window->bounds().ToString()); - window->Show(); - EXPECT_TRUE( - Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); - // Y bounds should not be negative. - EXPECT_EQ("-20,0 30x40", window->bounds().ToString()); - - // Fullscreen -> Normal transition. - window->SetBounds(gfx::Rect(0, 0, 30, 40)); // reset bounds. - ASSERT_EQ("0,0 30x40", window->bounds().ToString()); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - EXPECT_EQ(window->bounds(), window->GetRootWindow()->bounds()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 30, 40)); - window_state->Restore(); - EXPECT_TRUE( - Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); - // Y bounds should not be negative. - EXPECT_EQ("-20,0 30x40", window->bounds().ToString()); -} - -TEST_F(WorkspaceLayoutManagerTest, MaximizeInDisplayToBeRestored) { - if (!SupportsMultipleDisplays()) - return; - UpdateDisplay("300x400,400x500"); - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40)); - // Maximize the window in 2nd display as the restore bounds - // is inside 2nd display. - window_state->Maximize(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("300,0 400x453", window->GetBoundsInScreen().ToString()); - - window_state->Restore(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString()); - - // If the restore bounds intersects with the current display, - // don't move. - window_state->SetRestoreBoundsInScreen(gfx::Rect(280, 0, 30, 40)); - window_state->Maximize(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("300,0 400x453", window->GetBoundsInScreen().ToString()); - - window_state->Restore(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("280,0 30x40", window->GetBoundsInScreen().ToString()); - - // Restoring widget state. - scoped_ptr<views::Widget> w1(new views::Widget); - views::Widget::InitParams params; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.delegate = new MaximizeDelegateView(gfx::Rect(400, 0, 30, 40)); - params.context = root_windows[0]; - w1->Init(params); - w1->Show(); - EXPECT_TRUE(w1->IsMaximized()); - EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow()); - EXPECT_EQ("300,0 400x453", w1->GetWindowBoundsInScreen().ToString()); - w1->Restore(); - EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow()); - EXPECT_EQ("400,0 30x40", w1->GetWindowBoundsInScreen().ToString()); -} - -TEST_F(WorkspaceLayoutManagerTest, FullscreenInDisplayToBeRestored) { - if (!SupportsMultipleDisplays()) - return; - UpdateDisplay("300x400,400x500"); - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40)); - // Maximize the window in 2nd display as the restore bounds - // is inside 2nd display. - window->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString()); - - window_state->Restore(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString()); - - // If the restore bounds intersects with the current display, - // don't move. - window_state->SetRestoreBoundsInScreen(gfx::Rect(280, 0, 30, 40)); - window->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString()); - - window_state->Restore(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("280,0 30x40", window->GetBoundsInScreen().ToString()); -} - -// WindowObserver implementation used by DontClobberRestoreBoundsWindowObserver. -// This code mirrors what BrowserFrameAsh does. In particular when this code -// sees the window was maximized it changes the bounds of a secondary -// window. The secondary window mirrors the status window. -class DontClobberRestoreBoundsWindowObserver : public aura::WindowObserver { - public: - DontClobberRestoreBoundsWindowObserver() : window_(NULL) {} - - void set_window(aura::Window* window) { window_ = window; } - - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE { - if (!window_) - return; - - if (wm::GetWindowState(window)->IsMaximized()) { - aura::Window* w = window_; - window_ = NULL; - - gfx::Rect shelf_bounds(Shell::GetPrimaryRootWindowController()-> - GetShelfLayoutManager()->GetIdealBounds()); - const gfx::Rect& window_bounds(w->bounds()); - w->SetBounds(gfx::Rect(window_bounds.x(), shelf_bounds.y() - 1, - window_bounds.width(), window_bounds.height())); - } - } - - private: - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(DontClobberRestoreBoundsWindowObserver); -}; - -// Creates a window, maximized the window and from within the maximized -// notification sets the bounds of a window to overlap the shelf. Verifies this -// doesn't effect the restore bounds. -TEST_F(WorkspaceLayoutManagerTest, DontClobberRestoreBounds) { - DontClobberRestoreBoundsWindowObserver window_observer; - scoped_ptr<aura::Window> window(new aura::Window(NULL)); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - window->SetBounds(gfx::Rect(10, 20, 30, 40)); - // NOTE: for this test to exercise the failure the observer needs to be added - // before the parent set. This mimics what BrowserFrameAsh does. - window->AddObserver(&window_observer); - ParentWindowInPrimaryRootWindow(window.get()); - window->Show(); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->Activate(); - - scoped_ptr<aura::Window> window2( - CreateTestWindowInShellWithBounds(gfx::Rect(12, 20, 30, 40))); - window->AddTransientChild(window2.get()); - window2->Show(); - - window_observer.set_window(window2.get()); - window_state->Maximize(); - EXPECT_EQ("10,20 30x40", - window_state->GetRestoreBoundsInScreen().ToString()); - window->RemoveObserver(&window_observer); -} - -// Verifies when a window is maximized all descendant windows have a size. -TEST_F(WorkspaceLayoutManagerTest, ChildBoundsResetOnMaximize) { - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(10, 20, 30, 40))); - window->Show(); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->Activate(); - scoped_ptr<aura::Window> child_window( - aura::test::CreateTestWindowWithBounds(gfx::Rect(5, 6, 7, 8), - window.get())); - child_window->Show(); - window_state->Maximize(); - EXPECT_EQ("5,6 7x8", child_window->bounds().ToString()); -} - -TEST_F(WorkspaceLayoutManagerTest, WindowShouldBeOnScreenWhenAdded) { - // Normal window bounds shouldn't be changed. - gfx::Rect window_bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(window_bounds)); - EXPECT_EQ(window_bounds, window->bounds()); - - // If the window is out of the workspace, it would be moved on screen. - gfx::Rect root_window_bounds = - Shell::GetInstance()->GetPrimaryRootWindow()->bounds(); - window_bounds.Offset(root_window_bounds.width(), root_window_bounds.height()); - ASSERT_FALSE(window_bounds.Intersects(root_window_bounds)); - scoped_ptr<aura::Window> out_window( - CreateTestWindowInShellWithBounds(window_bounds)); - EXPECT_EQ(window_bounds.size(), out_window->bounds().size()); - gfx::Rect bounds = out_window->bounds(); - bounds.Intersect(root_window_bounds); - - // 30% of the window edge must be visible. - 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::GetWindowState(window.get())->set_bounds_changed_by_user(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); - bounds = window_bounds; - bounds.Intersect(root_window_bounds); - - // Make sure that the initial bounds' visible area is less than 26% - // so that the auto adjustment logic kicks in. - ASSERT_LT(bounds.width(), out_window->bounds().width() * 0.26); - ASSERT_LT(bounds.height(), out_window->bounds().height() * 0.26); - ASSERT_TRUE(window_bounds.Intersects(root_window_bounds)); - - scoped_ptr<aura::Window> partially_out_window( - CreateTestWindowInShellWithBounds(window_bounds)); - EXPECT_EQ(window_bounds.size(), partially_out_window->bounds().size()); - bounds = partially_out_window->bounds(); - bounds.Intersect(root_window_bounds); - EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29); - EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29); - - // Make sure the window whose 30% width/height is bigger than display - // will be placed correctly. - window_bounds.SetRect(-1900, -1900, 3000, 3000); - scoped_ptr<aura::Window> window_bigger_than_display( - CreateTestWindowInShellWithBounds(window_bounds)); - EXPECT_GE(root_window_bounds.width(), - window_bigger_than_display->bounds().width()); - EXPECT_GE(root_window_bounds.height(), - window_bigger_than_display->bounds().height()); - - bounds = window_bigger_than_display->bounds(); - bounds.Intersect(root_window_bounds); - EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29); - EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29); -} - -// Verifies the size of a window is enforced to be smaller than the work area. -TEST_F(WorkspaceLayoutManagerTest, SizeToWorkArea) { - // Normal window bounds shouldn't be changed. - gfx::Size work_area( - Shell::GetScreen()->GetPrimaryDisplay().work_area().size()); - const gfx::Rect window_bounds( - 100, 101, work_area.width() + 1, work_area.height() + 2); - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(window_bounds)); - EXPECT_EQ(gfx::Rect(gfx::Point(100, 101), work_area).ToString(), - window->bounds().ToString()); - - // Directly setting the bounds triggers a slightly different code path. Verify - // that too. - window->SetBounds(window_bounds); - EXPECT_EQ(gfx::Rect(gfx::Point(100, 101), work_area).ToString(), - window->bounds().ToString()); -} - -TEST_F(WorkspaceLayoutManagerTest, NotifyFullscreenChanges) { - TestShellObserver observer; - scoped_ptr<aura::Window> window1( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); - scoped_ptr<aura::Window> window2( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); - wm::WindowState* window_state1 = wm::GetWindowState(window1.get()); - wm::WindowState* window_state2 = wm::GetWindowState(window2.get()); - window_state2->Activate(); - - window_state2->ToggleFullscreen(); - EXPECT_EQ(1, observer.call_count()); - EXPECT_TRUE(observer.is_fullscreen()); - - // When window1 moves to the front the fullscreen state should change. - window_state1->Activate(); - EXPECT_EQ(2, observer.call_count()); - EXPECT_FALSE(observer.is_fullscreen()); - - // It should change back if window2 becomes active again. - window_state2->Activate(); - EXPECT_EQ(3, observer.call_count()); - EXPECT_TRUE(observer.is_fullscreen()); - - window_state2->ToggleFullscreen(); - EXPECT_EQ(4, observer.call_count()); - EXPECT_FALSE(observer.is_fullscreen()); - - window_state2->ToggleFullscreen(); - EXPECT_EQ(5, observer.call_count()); - EXPECT_TRUE(observer.is_fullscreen()); - - // Closing the window should change the fullscreen state. - window2.reset(); - EXPECT_EQ(6, observer.call_count()); - EXPECT_FALSE(observer.is_fullscreen()); -} - -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_types.h b/chromium/ash/wm/workspace/workspace_types.h deleted file mode 100644 index 9572a328d8b..00000000000 --- a/chromium/ash/wm/workspace/workspace_types.h +++ /dev/null @@ -1,27 +0,0 @@ -// 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_WORKSPACE_WORKSPACE_TYPES_H_ -#define ASH_WM_WORKSPACE_WORKSPACE_TYPES_H_ - -namespace ash { - -// Enumeration of the possible window states. -enum WorkspaceWindowState { - // There's a full screen window. - WORKSPACE_WINDOW_STATE_FULL_SCREEN, - - // There's a maximized window. - WORKSPACE_WINDOW_STATE_MAXIMIZED, - - // At least one window overlaps the shelf. - WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF, - - // None of the windows are fullscreen, maximized or touch the shelf. - WORKSPACE_WINDOW_STATE_DEFAULT, -}; - -} // namespace ash - -#endif // ASH_WM_WORKSPACE_WORKSPACE_TYPES_H_ diff --git a/chromium/ash/wm/workspace/workspace_window_resizer.cc b/chromium/ash/wm/workspace/workspace_window_resizer.cc deleted file mode 100644 index b8cd5049448..00000000000 --- a/chromium/ash/wm/workspace/workspace_window_resizer.cc +++ /dev/null @@ -1,1051 +0,0 @@ -// 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/workspace/workspace_window_resizer.h" - -#include <algorithm> -#include <cmath> -#include <utility> -#include <vector> - -#include "ash/ash_switches.h" -#include "ash/display/display_controller.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/default_window_resizer.h" -#include "ash/wm/dock/docked_window_layout_manager.h" -#include "ash/wm/dock/docked_window_resizer.h" -#include "ash/wm/drag_window_resizer.h" -#include "ash/wm/panels/panel_window_resizer.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/phantom_window_controller.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "base/command_line.h" -#include "base/memory/weak_ptr.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/client/window_types.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/compositor/layer.h" -#include "ui/gfx/screen.h" -#include "ui/gfx/transform.h" - -namespace ash { - -scoped_ptr<WindowResizer> CreateWindowResizer( - aura::Window* window, - const gfx::Point& point_in_parent, - int window_component, - aura::client::WindowMoveSource source) { - DCHECK(window); - wm::WindowState* window_state = wm::GetWindowState(window); - // No need to return a resizer when the window cannot get resized or when a - // resizer already exists for this window. - if ((!window_state->CanResize() && window_component != HTCAPTION) || - window_state->window_resizer()) { - return scoped_ptr<WindowResizer>(); - } - - // TODO(varkha): The chaining of window resizers causes some of the logic - // to be repeated and the logic flow difficult to control. With some windows - // classes using reparenting during drag operations it becomes challenging to - // implement proper transition from one resizer to another during or at the - // end of the drag. This also causes http://crbug.com/247085. - // It seems the only thing the panel or dock resizer needs to do is notify the - // layout manager when a docked window is being dragged. We should have a - // better way of doing this, perhaps by having a way of observing drags or - // having a generic drag window wrapper which informs a layout manager that a - // drag has started or stopped. - // It may be possible to refactor and eliminate chaining. - WindowResizer* window_resizer = NULL; - if (window->parent() && - (window->parent()->id() == internal::kShellWindowId_DefaultContainer || - window->parent()->id() == internal::kShellWindowId_DockedContainer || - window->parent()->id() == internal::kShellWindowId_PanelContainer)) { - // Allow dragging maximized windows if it's not tracked by workspace. This - // is set by tab dragging code. - if (!window_state->IsNormalShowState() && - (window_component != HTCAPTION || - !window_state->is_dragged())) { - return scoped_ptr<WindowResizer>(); - } - window_resizer = internal::WorkspaceWindowResizer::Create( - window, - point_in_parent, - window_component, - source, - std::vector<aura::Window*>()); - } else if (window_state->IsNormalShowState()) { - window_resizer = DefaultWindowResizer::Create( - window, point_in_parent, window_component, source); - } - if (window_resizer) { - window_resizer = internal::DragWindowResizer::Create( - window_resizer, window, point_in_parent, window_component, source); - } - if (window_resizer && window->type() == aura::client::WINDOW_TYPE_PANEL) { - window_resizer = PanelWindowResizer::Create( - window_resizer, window, point_in_parent, window_component, source); - } - if (switches::UseDockedWindows() && - window_resizer && window->parent() && - !window->transient_parent() && - (window->parent()->id() == internal::kShellWindowId_DefaultContainer || - window->parent()->id() == internal::kShellWindowId_DockedContainer || - window->parent()->id() == internal::kShellWindowId_PanelContainer)) { - window_resizer = internal::DockedWindowResizer::Create( - window_resizer, window, point_in_parent, window_component, source); - } - window_state->set_window_resizer_(window_resizer); - return make_scoped_ptr<WindowResizer>(window_resizer); -} - -namespace internal { - -namespace { - -// Snapping distance used instead of WorkspaceWindowResizer::kScreenEdgeInset -// when resizing a window using touchscreen. -const int kScreenEdgeInsetForTouchResize = 32; - -// Returns true if the window should stick to the edge. -bool ShouldStickToEdge(int distance_from_edge, int sticky_size) { - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshEnableStickyEdges)) { - // TODO(varkha): Consider keeping snapping behavior for touch drag. - return distance_from_edge < 0 && - distance_from_edge > -sticky_size; - } - return distance_from_edge < sticky_size && - distance_from_edge > -sticky_size * 2; -} - -// Returns the coordinate along the secondary axis to snap to. -int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge, - int leading, - int trailing, - int none) { - switch (edge) { - case SECONDARY_MAGNETISM_EDGE_LEADING: - return leading; - case SECONDARY_MAGNETISM_EDGE_TRAILING: - return trailing; - case SECONDARY_MAGNETISM_EDGE_NONE: - return none; - } - NOTREACHED(); - return none; -} - -// Returns the origin for |src| when magnetically attaching to |attach_to| along -// the edges |edges|. |edges| is a bitmask of the MagnetismEdges. -gfx::Point OriginForMagneticAttach(const gfx::Rect& src, - const gfx::Rect& attach_to, - const MatchedEdge& edge) { - int x = 0, y = 0; - switch (edge.primary_edge) { - case MAGNETISM_EDGE_TOP: - y = attach_to.bottom(); - break; - case MAGNETISM_EDGE_LEFT: - x = attach_to.right(); - break; - case MAGNETISM_EDGE_BOTTOM: - y = attach_to.y() - src.height(); - break; - case MAGNETISM_EDGE_RIGHT: - x = attach_to.x() - src.width(); - break; - } - switch (edge.primary_edge) { - case MAGNETISM_EDGE_TOP: - case MAGNETISM_EDGE_BOTTOM: - x = CoordinateAlongSecondaryAxis( - edge.secondary_edge, attach_to.x(), attach_to.right() - src.width(), - src.x()); - break; - case MAGNETISM_EDGE_LEFT: - case MAGNETISM_EDGE_RIGHT: - y = CoordinateAlongSecondaryAxis( - edge.secondary_edge, attach_to.y(), attach_to.bottom() - src.height(), - src.y()); - break; - } - return gfx::Point(x, y); -} - -// Returns the bounds for a magnetic attach when resizing. |src| is the bounds -// of window being resized, |attach_to| the bounds of the window to attach to -// and |edge| identifies the edge to attach to. -gfx::Rect BoundsForMagneticResizeAttach(const gfx::Rect& src, - const gfx::Rect& attach_to, - const MatchedEdge& edge) { - int x = src.x(); - int y = src.y(); - int w = src.width(); - int h = src.height(); - gfx::Point attach_origin(OriginForMagneticAttach(src, attach_to, edge)); - switch (edge.primary_edge) { - case MAGNETISM_EDGE_LEFT: - x = attach_origin.x(); - w = src.right() - x; - break; - case MAGNETISM_EDGE_RIGHT: - w += attach_origin.x() - src.x(); - break; - case MAGNETISM_EDGE_TOP: - y = attach_origin.y(); - h = src.bottom() - y; - break; - case MAGNETISM_EDGE_BOTTOM: - h += attach_origin.y() - src.y(); - break; - } - switch (edge.primary_edge) { - case MAGNETISM_EDGE_LEFT: - case MAGNETISM_EDGE_RIGHT: - if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_LEADING) { - y = attach_origin.y(); - h = src.bottom() - y; - } else if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_TRAILING) { - h += attach_origin.y() - src.y(); - } - break; - case MAGNETISM_EDGE_TOP: - case MAGNETISM_EDGE_BOTTOM: - if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_LEADING) { - x = attach_origin.x(); - w = src.right() - x; - } else if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_TRAILING) { - w += attach_origin.x() - src.x(); - } - break; - } - return gfx::Rect(x, y, w, h); -} - -// Converts a window component edge to the magnetic edge to snap to. -uint32 WindowComponentToMagneticEdge(int window_component) { - switch (window_component) { - case HTTOPLEFT: - return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_TOP; - case HTTOPRIGHT: - return MAGNETISM_EDGE_TOP | MAGNETISM_EDGE_RIGHT; - case HTBOTTOMLEFT: - return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_BOTTOM; - case HTBOTTOMRIGHT: - return MAGNETISM_EDGE_RIGHT | MAGNETISM_EDGE_BOTTOM; - case HTTOP: - return MAGNETISM_EDGE_TOP; - case HTBOTTOM: - return MAGNETISM_EDGE_BOTTOM; - case HTRIGHT: - return MAGNETISM_EDGE_RIGHT; - case HTLEFT: - return MAGNETISM_EDGE_LEFT; - default: - break; - } - return 0; -} - -} // namespace - -// static -const int WorkspaceWindowResizer::kMinOnscreenSize = 20; - -// static -const int WorkspaceWindowResizer::kMinOnscreenHeight = 32; - -// static -const int WorkspaceWindowResizer::kScreenEdgeInset = 8; - -// static -const int WorkspaceWindowResizer::kStickyDistancePixels = 64; - -// static -WorkspaceWindowResizer* WorkspaceWindowResizer::instance_ = NULL; - -// 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 { - public: - WindowSize(int size, int min, int max) - : size_(size), - min_(min), - max_(max) { - // Grow the min/max bounds to include the starting size. - if (is_underflowing()) - min_ = size_; - if (is_overflowing()) - max_ = size_; - } - - bool is_at_capacity(bool shrinking) { - return size_ == (shrinking ? min_ : max_); - } - - int size() const { - return size_; - } - - bool has_min() const { - return min_ != 0; - } - - bool has_max() const { - return max_ != 0; - } - - bool is_valid() const { - return !is_overflowing() && !is_underflowing(); - } - - bool is_overflowing() const { - return has_max() && size_ > max_; - } - - bool is_underflowing() const { - return has_min() && size_ < min_; - } - - // Add |amount| to this WindowSize not exceeding min or max size constraints. - // Returns by how much |size_| + |amount| exceeds the min/max constraints. - int Add(int amount) { - DCHECK(is_valid()); - int new_value = size_ + amount; - - if (has_min() && new_value < min_) { - size_ = min_; - return new_value - min_; - } - - if (has_max() && new_value > max_) { - size_ = max_; - return new_value - max_; - } - - size_ = new_value; - return 0; - } - - private: - int size_; - int min_; - int max_; -}; - -WorkspaceWindowResizer::~WorkspaceWindowResizer() { - if (did_lock_cursor_) { - Shell* shell = Shell::GetInstance(); - shell->cursor_manager()->UnlockCursor(); - } - if (instance_ == this) - instance_ = NULL; -} - -// static -WorkspaceWindowResizer* WorkspaceWindowResizer::Create( - aura::Window* window, - const gfx::Point& location_in_parent, - int window_component, - aura::client::WindowMoveSource source, - const std::vector<aura::Window*>& attached_windows) { - Details details(window, location_in_parent, window_component, source); - return details.is_resizable ? - new WorkspaceWindowResizer(details, attached_windows) : NULL; -} - -void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent, - int event_flags) { - last_mouse_location_ = location_in_parent; - - int sticky_size; - if (event_flags & ui::EF_CONTROL_DOWN) { - sticky_size = 0; - } else if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshEnableStickyEdges)) { - sticky_size = kStickyDistancePixels; - } else if ((details_.bounds_change & kBoundsChange_Resizes) && - details_.source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { - sticky_size = kScreenEdgeInsetForTouchResize; - } else { - sticky_size = kScreenEdgeInset; - } - // |bounds| is in |window()->parent()|'s coordinates. - gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent); - if (window_state()->IsNormalShowState()) - AdjustBoundsForMainWindow(sticky_size, &bounds); - - if (bounds != window()->bounds()) { - if (!did_move_or_resize_) { - if (!details_.restore_bounds.IsEmpty()) - window_state()->ClearRestoreBounds(); - RestackWindows(); - } - did_move_or_resize_ = true; - } - - gfx::Point location_in_screen = location_in_parent; - wm::ConvertPointToScreen(window()->parent(), &location_in_screen); - - aura::Window* root = NULL; - gfx::Display display = - ScreenAsh::FindDisplayContainingPoint(location_in_screen); - // Track the last screen that the pointer was on to keep the snap phantom - // window there. - if (display.is_valid()) { - root = Shell::GetInstance()->display_controller()-> - GetRootWindowForDisplayId(display.id()); - } - if (!attached_windows_.empty()) - LayoutAttachedWindows(&bounds); - if (bounds != window()->bounds()) { - // SetBounds needs to be called to update the layout which affects where the - // phantom window is drawn. Keep track if the window was destroyed during - // the drag and quit early if so. - base::WeakPtr<WorkspaceWindowResizer> resizer( - weak_ptr_factory_.GetWeakPtr()); - window()->SetBounds(bounds); - if (!resizer) - return; - } - const bool in_original_root = !root || root == window()->GetRootWindow(); - // Hide a phantom window for snapping if the cursor is in another root window. - if (in_original_root) { - UpdateSnapPhantomWindow(location_in_parent, bounds); - } else { - snap_type_ = SNAP_NONE; - snap_phantom_window_controller_.reset(); - snap_sizer_.reset(); - SetDraggedWindowDocked(false); - } -} - -void WorkspaceWindowResizer::CompleteDrag(int event_flags) { - window_state()->set_bounds_changed_by_user(true); - snap_phantom_window_controller_.reset(); - if (!did_move_or_resize_ || details_.window_component != HTCAPTION) - return; - - bool snapped = false; - // When the window is not in the normal show state, we do not snap the window. - // This happens when the user minimizes or maximizes the window by keyboard - // shortcut while dragging it. If the window is the result of dragging a tab - // out of a maximized window, it's already in the normal show state when this - // is called, so it does not matter. - if (window_state()->IsNormalShowState() && - (window()->type() != aura::client::WINDOW_TYPE_PANEL || - !window_state()->panel_attached() || - dock_layout_->is_dragged_window_docked()) && - (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { - if (!window_state()->HasRestoreBounds()) { - gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( - window()->parent(), details_.initial_bounds_in_parent); - window_state()->SetRestoreBoundsInScreen( - details_.restore_bounds.IsEmpty() ? - initial_bounds : - details_.restore_bounds); - } - DCHECK(snap_sizer_); - if (window_state()->CanResize() && - !dock_layout_->is_dragged_window_docked()) { - snap_sizer_->SnapWindowToTargetBounds(); - snapped = true; - } - } - if (window_state()->IsSnapped() && !snapped) - window_state()->Restore(); -} - -void WorkspaceWindowResizer::RevertDrag() { - window_state()->set_bounds_changed_by_user(initial_bounds_changed_by_user_); - snap_phantom_window_controller_.reset(); - - if (!did_move_or_resize_) - return; - - window()->SetBounds(details_.initial_bounds_in_parent); - if (!details_.restore_bounds.IsEmpty()) { - window_state()->SetRestoreBoundsInScreen(details_.restore_bounds); - } - - if (details_.window_component == HTRIGHT) { - int last_x = details_.initial_bounds_in_parent.right(); - for (size_t i = 0; i < attached_windows_.size(); ++i) { - gfx::Rect bounds(attached_windows_[i]->bounds()); - bounds.set_x(last_x); - bounds.set_width(initial_size_[i]); - attached_windows_[i]->SetBounds(bounds); - last_x = attached_windows_[i]->bounds().right(); - } - } else { - int last_y = details_.initial_bounds_in_parent.bottom(); - for (size_t i = 0; i < attached_windows_.size(); ++i) { - gfx::Rect bounds(attached_windows_[i]->bounds()); - bounds.set_y(last_y); - bounds.set_height(initial_size_[i]); - attached_windows_[i]->SetBounds(bounds); - last_y = attached_windows_[i]->bounds().bottom(); - } - } -} - -aura::Window* WorkspaceWindowResizer::GetTarget() { - return details_.window; -} - -const gfx::Point& WorkspaceWindowResizer::GetInitialLocation() const { - return details_.initial_location_in_parent; -} - -WorkspaceWindowResizer::WorkspaceWindowResizer( - const Details& details, - const std::vector<aura::Window*>& attached_windows) - : details_(details), - attached_windows_(attached_windows), - did_lock_cursor_(false), - did_move_or_resize_(false), - initial_bounds_changed_by_user_( - details.window_state->bounds_changed_by_user()), - total_min_(0), - total_initial_size_(0), - snap_type_(SNAP_NONE), - num_mouse_moves_since_bounds_change_(0), - magnetism_window_(NULL), - weak_ptr_factory_(this) { - DCHECK(details_.is_resizable); - - // A mousemove should still show the cursor even if the window is - // being moved or resized with touch, so do not lock the cursor. - if (details.source != aura::client::WINDOW_MOVE_SOURCE_TOUCH) { - Shell* shell = Shell::GetInstance(); - shell->cursor_manager()->LockCursor(); - did_lock_cursor_ = true; - } - - aura::Window* dock_container = Shell::GetContainer( - window()->GetRootWindow(), kShellWindowId_DockedContainer); - dock_layout_ = static_cast<DockedWindowLayoutManager*>( - dock_container->layout_manager()); - - // Only support attaching to the right/bottom. - DCHECK(attached_windows_.empty() || - (details.window_component == HTRIGHT || - details.window_component == HTBOTTOM)); - - // TODO: figure out how to deal with window going off the edge. - - // Calculate sizes so that we can maintain the ratios if we need to resize. - int total_available = 0; - for (size_t i = 0; i < attached_windows_.size(); ++i) { - gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); - int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); - initial_size_.push_back(initial_size); - // If current size is smaller than the min, use the current size as the min. - // This way we don't snap on resize. - int min_size = std::min(initial_size, - std::max(PrimaryAxisSize(min), kMinOnscreenSize)); - total_min_ += min_size; - total_initial_size_ += initial_size; - total_available += std::max(min_size, initial_size) - min_size; - } - instance_ = this; -} - -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 bounds; -} - -void WorkspaceWindowResizer::LayoutAttachedWindows( - gfx::Rect* bounds) { - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); - int initial_size = PrimaryAxisSize(details_.initial_bounds_in_parent.size()); - int current_size = PrimaryAxisSize(bounds->size()); - int start = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); - int end = PrimaryAxisCoordinate(work_area.right(), work_area.bottom()); - - int delta = current_size - initial_size; - int available_size = end - start; - std::vector<int> sizes; - int leftovers = CalculateAttachedSizes(delta, available_size, &sizes); - - // leftovers > 0 means that the attached windows can't grow to compensate for - // the shrinkage of the main window. This line causes the attached windows to - // be moved so they are still flush against the main window, rather than the - // main window being prevented from shrinking. - leftovers = std::min(0, leftovers); - // Reallocate any leftover pixels back into the main window. This is - // necessary when, for example, the main window shrinks, but none of the - // attached windows can grow without exceeding their max size constraints. - // Adding the pixels back to the main window effectively prevents the main - // window from resizing too far. - if (details_.window_component == HTRIGHT) - bounds->set_width(bounds->width() + leftovers); - else - bounds->set_height(bounds->height() + leftovers); - - DCHECK_EQ(attached_windows_.size(), sizes.size()); - int last = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); - for (size_t i = 0; i < attached_windows_.size(); ++i) { - gfx::Rect attached_bounds(attached_windows_[i]->bounds()); - if (details_.window_component == HTRIGHT) { - attached_bounds.set_x(last); - attached_bounds.set_width(sizes[i]); - } else { - attached_bounds.set_y(last); - attached_bounds.set_height(sizes[i]); - } - attached_windows_[i]->SetBounds(attached_bounds); - last += sizes[i]; - } -} - -int WorkspaceWindowResizer::CalculateAttachedSizes( - int delta, - int available_size, - std::vector<int>* sizes) const { - std::vector<WindowSize> window_sizes; - CreateBucketsForAttached(&window_sizes); - - // How much we need to grow the attached by (collectively). - int grow_attached_by = 0; - if (delta > 0) { - // If the attached windows don't fit when at their initial size, we will - // have to shrink them by how much they overflow. - if (total_initial_size_ >= available_size) - grow_attached_by = available_size - total_initial_size_; - } else { - // If we're shrinking, we grow the attached so the total size remains - // constant. - grow_attached_by = -delta; - } - - int leftover_pixels = 0; - while (grow_attached_by != 0) { - int leftovers = GrowFairly(grow_attached_by, window_sizes); - if (leftovers == grow_attached_by) { - leftover_pixels = leftovers; - break; - } - grow_attached_by = leftovers; - } - - for (size_t i = 0; i < window_sizes.size(); ++i) - sizes->push_back(window_sizes[i].size()); - - return leftover_pixels; -} - -int WorkspaceWindowResizer::GrowFairly( - int pixels, - std::vector<WindowSize>& sizes) const { - bool shrinking = pixels < 0; - std::vector<WindowSize*> nonfull_windows; - for (size_t i = 0; i < sizes.size(); ++i) { - if (!sizes[i].is_at_capacity(shrinking)) - nonfull_windows.push_back(&sizes[i]); - } - std::vector<float> ratios; - CalculateGrowthRatios(nonfull_windows, &ratios); - - int remaining_pixels = pixels; - bool add_leftover_pixels_to_last = true; - for (size_t i = 0; i < nonfull_windows.size(); ++i) { - int grow_by = pixels * ratios[i]; - // Put any leftover pixels into the last window. - if (i == nonfull_windows.size() - 1 && add_leftover_pixels_to_last) - grow_by = remaining_pixels; - int remainder = nonfull_windows[i]->Add(grow_by); - int consumed = grow_by - remainder; - remaining_pixels -= consumed; - if (nonfull_windows[i]->is_at_capacity(shrinking) && remainder > 0) { - // Because this window overflowed, some of the pixels in - // |remaining_pixels| aren't there due to rounding errors. Rather than - // unfairly giving all those pixels to the last window, we refrain from - // allocating them so that this function can be called again to distribute - // the pixels fairly. - add_leftover_pixels_to_last = false; - } - } - return remaining_pixels; -} - -void WorkspaceWindowResizer::CalculateGrowthRatios( - const std::vector<WindowSize*>& sizes, - std::vector<float>* out_ratios) const { - DCHECK(out_ratios->empty()); - int total_value = 0; - for (size_t i = 0; i < sizes.size(); ++i) - total_value += sizes[i]->size(); - - for (size_t i = 0; i < sizes.size(); ++i) - out_ratios->push_back( - (static_cast<float>(sizes[i]->size())) / total_value); -} - -void WorkspaceWindowResizer::CreateBucketsForAttached( - std::vector<WindowSize>* sizes) const { - for (size_t i = 0; i < attached_windows_.size(); i++) { - int initial_size = initial_size_[i]; - aura::WindowDelegate* delegate = attached_windows_[i]->delegate(); - int min = PrimaryAxisSize(delegate->GetMinimumSize()); - int max = PrimaryAxisSize(delegate->GetMaximumSize()); - - sizes->push_back(WindowSize(initial_size, min, max)); - } -} - -void WorkspaceWindowResizer::MagneticallySnapToOtherWindows(gfx::Rect* bounds) { - if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) { - gfx::Point point = OriginForMagneticAttach( - ScreenAsh::ConvertRectToScreen(window()->parent(), *bounds), - magnetism_window_->GetBoundsInScreen(), - magnetism_edge_); - aura::client::GetScreenPositionClient(window()->GetRootWindow())-> - ConvertPointFromScreen(window()->parent(), &point); - bounds->set_origin(point); - } -} - -void WorkspaceWindowResizer::MagneticallySnapResizeToOtherWindows( - gfx::Rect* bounds) { - const uint32 edges = WindowComponentToMagneticEdge(details_.window_component); - if (UpdateMagnetismWindow(*bounds, edges)) { - *bounds = ScreenAsh::ConvertRectFromScreen( - window()->parent(), - BoundsForMagneticResizeAttach( - ScreenAsh::ConvertRectToScreen(window()->parent(), *bounds), - magnetism_window_->GetBoundsInScreen(), - magnetism_edge_)); - } -} - -bool WorkspaceWindowResizer::UpdateMagnetismWindow(const gfx::Rect& bounds, - uint32 edges) { - // |bounds| are in coordinates of original window's parent. - gfx::Rect bounds_in_screen = - ScreenAsh::ConvertRectToScreen(window()->parent(), bounds); - MagnetismMatcher matcher(bounds_in_screen, edges); - - // If we snapped to a window then check it first. That way we don't bounce - // around when close to multiple edges. - if (magnetism_window_) { - if (window_tracker_.Contains(magnetism_window_) && - matcher.ShouldAttach(magnetism_window_->GetBoundsInScreen(), - &magnetism_edge_)) { - return true; - } - window_tracker_.Remove(magnetism_window_); - magnetism_window_ = NULL; - } - - // Avoid magnetically snapping windows that are not resizable. - // TODO(oshima): change this to window.type() == TYPE_NORMAL. - if (!window_state()->CanResize()) - return false; - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - for (aura::Window::Windows::iterator iter = root_windows.begin(); - iter != root_windows.end(); ++iter) { - const aura::Window* root_window = *iter; - // Test all children from the desktop in each root window. - const aura::Window::Windows& children = Shell::GetContainer( - root_window, kShellWindowId_DefaultContainer)->children(); - for (aura::Window::Windows::const_reverse_iterator i = children.rbegin(); - i != children.rend() && !matcher.AreEdgesObscured(); ++i) { - wm::WindowState* other_state = wm::GetWindowState(*i); - if (other_state->window() == window() || - !other_state->window()->IsVisible() || - !other_state->IsNormalShowState() || - !other_state->CanResize()) { - continue; - } - if (matcher.ShouldAttach( - other_state->window()->GetBoundsInScreen(), &magnetism_edge_)) { - magnetism_window_ = other_state->window(); - window_tracker_.Add(magnetism_window_); - return true; - } - } - } - return false; -} - -void WorkspaceWindowResizer::AdjustBoundsForMainWindow( - int sticky_size, - gfx::Rect* bounds) { - gfx::Point last_mouse_location_in_screen = last_mouse_location_; - wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen); - gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint( - last_mouse_location_in_screen); - gfx::Rect work_area = - ScreenAsh::ConvertRectFromScreen(window()->parent(), display.work_area()); - if (details_.window_component == HTCAPTION) { - // Adjust the bounds to the work area where the mouse cursor is located. - // Always keep kMinOnscreenHeight or the window height (whichever is less) - // on the bottom. - int max_y = work_area.bottom() - std::min(kMinOnscreenHeight, - bounds->height()); - if (bounds->y() > max_y) { - bounds->set_y(max_y); - } else if (bounds->y() <= work_area.y()) { - // Don't allow dragging above the top of the display until the mouse - // cursor reaches the work area above if any. - bounds->set_y(work_area.y()); - } - - 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))) { - MagneticallySnapToOtherWindows(bounds); - } - } - } else if (sticky_size > 0) { - MagneticallySnapResizeToOtherWindows(bounds); - if (!magnetism_window_ && sticky_size > 0) - StickToWorkAreaOnResize(work_area, sticky_size, bounds); - } - - if (attached_windows_.empty()) - return; - - if (details_.window_component == HTRIGHT) { - bounds->set_width(std::min(bounds->width(), - work_area.right() - total_min_ - bounds->x())); - } else { - DCHECK_EQ(HTBOTTOM, details_.window_component); - bounds->set_height(std::min(bounds->height(), - work_area.bottom() - total_min_ - bounds->y())); - } -} - -bool WorkspaceWindowResizer::StickToWorkAreaOnMove( - const gfx::Rect& work_area, - int sticky_size, - gfx::Rect* bounds) const { - const int left_edge = work_area.x(); - const int right_edge = work_area.right(); - const int top_edge = work_area.y(); - const int bottom_edge = work_area.bottom(); - bool updated = false; - if (ShouldStickToEdge(bounds->x() - left_edge, sticky_size)) { - bounds->set_x(left_edge); - updated = true; - } else if (ShouldStickToEdge(right_edge - bounds->right(), sticky_size)) { - bounds->set_x(right_edge - bounds->width()); - updated = true; - } - if (ShouldStickToEdge(bounds->y() - top_edge, sticky_size)) { - bounds->set_y(top_edge); - updated = true; - } else if (ShouldStickToEdge(bottom_edge - bounds->bottom(), sticky_size) && - bounds->height() < (bottom_edge - top_edge)) { - // Only snap to the bottom if the window is smaller than the work area. - // Doing otherwise can lead to window snapping in weird ways as it bounces - // between snapping to top then bottom. - bounds->set_y(bottom_edge - bounds->height()); - updated = true; - } - return updated; -} - -void WorkspaceWindowResizer::StickToWorkAreaOnResize( - const gfx::Rect& work_area, - int sticky_size, - gfx::Rect* bounds) const { - const uint32 edges = WindowComponentToMagneticEdge(details_.window_component); - const int left_edge = work_area.x(); - const int right_edge = work_area.right(); - const int top_edge = work_area.y(); - const int bottom_edge = work_area.bottom(); - if (edges & MAGNETISM_EDGE_TOP && - ShouldStickToEdge(bounds->y() - top_edge, sticky_size)) { - bounds->set_height(bounds->bottom() - top_edge); - bounds->set_y(top_edge); - } - if (edges & MAGNETISM_EDGE_LEFT && - ShouldStickToEdge(bounds->x() - left_edge, sticky_size)) { - bounds->set_width(bounds->right() - left_edge); - bounds->set_x(left_edge); - } - if (edges & MAGNETISM_EDGE_BOTTOM && - ShouldStickToEdge(bottom_edge - bounds->bottom(), sticky_size)) { - bounds->set_height(bottom_edge - bounds->y()); - } - if (edges & MAGNETISM_EDGE_RIGHT && - ShouldStickToEdge(right_edge - bounds->right(), sticky_size)) { - bounds->set_width(right_edge - bounds->x()); - } -} - -int WorkspaceWindowResizer::PrimaryAxisSize(const gfx::Size& size) const { - return PrimaryAxisCoordinate(size.width(), size.height()); -} - -int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { - switch (details_.window_component) { - case HTRIGHT: - return x; - case HTBOTTOM: - return y; - default: - NOTREACHED(); - } - return 0; -} - -void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, - const gfx::Rect& bounds) { - if (!did_move_or_resize_ || details_.window_component != HTCAPTION) - return; - - SnapType last_type = snap_type_; - snap_type_ = GetSnapType(location); - if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { - snap_phantom_window_controller_.reset(); - snap_sizer_.reset(); - if (snap_type_ == SNAP_NONE) { - SetDraggedWindowDocked(false); - return; - } - } - const bool can_dock = dock_layout_->CanDockWindow(window(), snap_type_); - const bool can_snap = window_state()->CanSnap(); - if (!can_snap && !can_dock) { - snap_type_ = SNAP_NONE; - snap_phantom_window_controller_.reset(); - snap_sizer_.reset(); - SetDraggedWindowDocked(false); - return; - } - SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ? - SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; - if (!snap_sizer_) { - snap_sizer_.reset(new SnapSizer(window_state(), - location, - edge, - internal::SnapSizer::OTHER_INPUT)); - } else { - snap_sizer_->Update(location); - } - - // Update phantom window with snapped or docked guide bounds. - // Windows that cannot be snapped or are less wide than kMaxDockWidth can get - // docked without going through a snapping sequence. - gfx::Rect phantom_bounds; - if (can_snap && - (!can_dock || - window()->bounds().width() > DockedWindowLayoutManager::kMaxDockWidth)) - phantom_bounds = snap_sizer_->target_bounds(); - const bool should_dock = can_dock && - (phantom_bounds.IsEmpty() || - snap_sizer_->end_of_sequence() || - dock_layout_->is_dragged_window_docked()); - SetDraggedWindowDocked(should_dock); - snap_type_ = GetSnapType(location); - if (dock_layout_->is_dragged_window_docked()) { - phantom_bounds = ScreenAsh::ConvertRectFromScreen( - window()->parent(), dock_layout_->dragged_bounds()); - } - - if (phantom_bounds.IsEmpty()) { - snap_phantom_window_controller_.reset(); - return; - } - - if (!snap_phantom_window_controller_) { - snap_phantom_window_controller_.reset( - new PhantomWindowController(window())); - } - snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( - window()->parent(), phantom_bounds)); -} - -void WorkspaceWindowResizer::RestackWindows() { - if (attached_windows_.empty()) - return; - // Build a map from index in children to window, returning if there is a - // window with a different parent. - typedef std::map<size_t, aura::Window*> IndexToWindowMap; - IndexToWindowMap map; - aura::Window* parent = window()->parent(); - const aura::Window::Windows& windows(parent->children()); - map[std::find(windows.begin(), windows.end(), window()) - - windows.begin()] = window(); - for (std::vector<aura::Window*>::const_iterator i = - attached_windows_.begin(); i != attached_windows_.end(); ++i) { - if ((*i)->parent() != parent) - return; - size_t index = - std::find(windows.begin(), windows.end(), *i) - windows.begin(); - map[index] = *i; - } - - // Reorder the windows starting at the topmost. - parent->StackChildAtTop(map.rbegin()->second); - for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); - i != map.rend(); ) { - aura::Window* window = i->second; - ++i; - if (i != map.rend()) - parent->StackChildBelow(i->second, window); - } -} - -SnapType WorkspaceWindowResizer::GetSnapType( - const gfx::Point& location) const { - // TODO: this likely only wants total display area, not the area of a single - // display. - gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); - if (details_.source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { - // Increase tolerance for touch-snapping near the screen edges. This is only - // necessary when the work area left or right edge is same as screen edge. - gfx::Rect display_bounds(ScreenAsh::GetDisplayBoundsInParent(window())); - int inset_left = 0; - if (area.x() == display_bounds.x()) - inset_left = kScreenEdgeInsetForTouchResize; - int inset_right = 0; - if (area.right() == display_bounds.right()) - inset_right = kScreenEdgeInsetForTouchResize; - area.Inset(inset_left, 0, inset_right, 0); - } - if (location.x() <= area.x()) - return SNAP_LEFT; - if (location.x() >= area.right() - 1) - return SNAP_RIGHT; - return SNAP_NONE; -} - -void WorkspaceWindowResizer::SetDraggedWindowDocked(bool should_dock) { - if (should_dock && - dock_layout_->GetAlignmentOfWindow(window()) != DOCKED_ALIGNMENT_NONE) { - if (!dock_layout_->is_dragged_window_docked()) { - window_state()->set_bounds_changed_by_user(false); - dock_layout_->DockDraggedWindow(window()); - } - } else { - if (dock_layout_->is_dragged_window_docked()) { - dock_layout_->UndockDraggedWindow(); - window_state()->set_bounds_changed_by_user(true); - } - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_window_resizer.h b/chromium/ash/wm/workspace/workspace_window_resizer.h deleted file mode 100644 index 015e96ddb36..00000000000 --- a/chromium/ash/wm/workspace/workspace_window_resizer.h +++ /dev/null @@ -1,236 +0,0 @@ -// 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_WORKSPACE_WINDOW_RESIZER_H_ -#define ASH_WM_WORKSPACE_WINDOW_RESIZER_H_ - -#include <vector> - -#include "ash/wm/window_resizer.h" -#include "ash/wm/workspace/magnetism_matcher.h" -#include "ash/wm/workspace/snap_types.h" -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "ui/aura/window_tracker.h" - -namespace ash { -namespace wm { -class WindowState; -} - -namespace internal { - -class DockedWindowLayoutManager; -class PhantomWindowController; -class SnapSizer; -class WindowSize; - -// WindowResizer implementation for workspaces. This enforces that windows are -// not allowed to vertically move or resize outside of the work area. As windows -// are moved outside the work area they are shrunk. We remember the height of -// the window before it was moved so that if the window is again moved up we -// attempt to restore the old height. -class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { - public: - // When dragging an attached window this is the min size we'll make sure is - // visible. In the vertical direction we take the max of this and that from - // the delegate. - static const int kMinOnscreenSize; - - // Min height we'll force on screen when dragging the caption. - // TODO: this should come from a property on the window. - static const int kMinOnscreenHeight; - - // Snap region when dragging close to the edges. That is, as the window gets - // 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( - aura::Window* window, - const gfx::Point& location_in_parent, - int window_component, - aura::client::WindowMoveSource source, - const std::vector<aura::Window*>& attached_windows); - - // WindowResizer: - virtual void Drag(const gfx::Point& location_in_parent, - int event_flags) OVERRIDE; - virtual void CompleteDrag(int event_flags) OVERRIDE; - virtual void RevertDrag() OVERRIDE; - virtual aura::Window* GetTarget() OVERRIDE; - virtual const gfx::Point& GetInitialLocation() const OVERRIDE; - - private: - WorkspaceWindowResizer(const Details& details, - const std::vector<aura::Window*>& attached_windows); - - private: - friend class WorkspaceWindowResizerTest; - - // Returns the final bounds to place the window at. This differs from - // the current when snapping. - gfx::Rect GetFinalBounds(const gfx::Rect& bounds) const; - - // Lays out the attached windows. |bounds| is the bounds of the main window. - void LayoutAttachedWindows(gfx::Rect* bounds); - - // Calculates the new sizes of the attached windows, given that the main - // window has been resized (along the primary axis) by |delta|. - // |available_size| is the maximum length of the space that the attached - // windows are allowed to occupy (ie: the distance between the right/bottom - // edge of the primary window and the right/bottom of the desktop area). - // Populates |sizes| with the desired sizes of the attached windows, and - // returns the number of pixels that couldn't be allocated to the attached - // windows (due to min/max size constraints). - // Note the return value can be positive or negative, a negative value - // indicating that that many pixels couldn't be removed from the attached - // windows. - int CalculateAttachedSizes( - int delta, - int available_size, - std::vector<int>* sizes) const; - - // Divides |amount| evenly between |sizes|. If |amount| is negative it - // indicates how many pixels |sizes| should be shrunk by. - // Returns how many pixels failed to be allocated/removed from |sizes|. - int GrowFairly(int amount, std::vector<WindowSize>& sizes) const; - - // Calculate the ratio of pixels that each WindowSize in |sizes| should - // receive when growing or shrinking. - void CalculateGrowthRatios(const std::vector<WindowSize*>& sizes, - std::vector<float>* out_ratios) const; - - // Adds a WindowSize to |sizes| for each attached window. - void CreateBucketsForAttached(std::vector<WindowSize>* sizes) const; - - // If possible snaps the window to a neary window. Updates |bounds| if there - // was a close enough window. - void MagneticallySnapToOtherWindows(gfx::Rect* bounds); - - // If possible snaps the resize to a neary window. Updates |bounds| if there - // was a close enough window. - void MagneticallySnapResizeToOtherWindows(gfx::Rect* bounds); - - // Finds the neareset window to magentically snap to. Updates - // |magnetism_window_| and |magnetism_edge_| appropriately. |edges| is a - // bitmask of the MagnetismEdges to match again. Returns true if a match is - // found. - bool UpdateMagnetismWindow(const gfx::Rect& bounds, uint32 edges); - - // Adjusts the bounds of the window: magnetically snapping, ensuring the - // window has enough on screen... |snap_size| is the distance from an edge of - // the work area before the window is snapped. A value of 0 results in no - // snapping. - void AdjustBoundsForMainWindow(int snap_size, gfx::Rect* bounds); - - // Stick the window bounds to the work area during a move. - bool StickToWorkAreaOnMove(const gfx::Rect& work_area, - int sticky_size, - gfx::Rect* bounds) const; - - // Stick the window bounds to the work area during a resize. - void StickToWorkAreaOnResize(const gfx::Rect& work_area, - int sticky_size, - gfx::Rect* bounds) const; - - // Returns a coordinate along the primary axis. Used to share code for - // left/right multi window resize and top/bottom resize. - int PrimaryAxisSize(const gfx::Size& size) const; - int PrimaryAxisCoordinate(int x, int y) const; - - // Updates the bounds of the phantom window for window snapping. - void UpdateSnapPhantomWindow(const gfx::Point& location, - const gfx::Rect& bounds); - - // Restacks the windows z-order position so that one of the windows is at the - // top of the z-order, and the rest directly underneath it. - void RestackWindows(); - - // Returns the SnapType for the specified point. SNAP_NONE is used if no - // snapping should be used. - SnapType GetSnapType(const gfx::Point& location) const; - - // Docks the dragged window if |should_dock| and the window can be docked. - // Undocks the window if |should_dock| is false. - void SetDraggedWindowDocked(bool should_dock); - - aura::Window* window() const { return details_.window; } - - wm::WindowState* window_state() { return details_.window_state; } - - const Details details_; - - const std::vector<aura::Window*> attached_windows_; - - bool did_lock_cursor_; - - // Set to true once Drag() is invoked and the bounds of the window change. - bool did_move_or_resize_; - - // True if the window initially had |bounds_changed_by_user_| set in state. - bool initial_bounds_changed_by_user_; - - // The initial size of each of the windows in |attached_windows_| along the - // primary axis. - std::vector<int> initial_size_; - - // Sum of the minimum sizes of the attached windows. - int total_min_; - - // Sum of the sizes in |initial_size_|. - int total_initial_size_; - - // Gives a previews of where the the window will end up. Only used if there - // is a grid and the caption is being dragged. - scoped_ptr<PhantomWindowController> snap_phantom_window_controller_; - - // Used to determine the target position of a snap. - scoped_ptr<SnapSizer> snap_sizer_; - - // Last SnapType. - SnapType snap_type_; - - // Number of mouse moves since the last bounds change. Only used for phantom - // placement to track when the mouse is moved while pushed against the edge of - // the screen. - int num_mouse_moves_since_bounds_change_; - - // The mouse location passed to Drag(). - gfx::Point last_mouse_location_; - - // Window the drag has magnetically attached to. - aura::Window* magnetism_window_; - - // Used to verify |magnetism_window_| is still valid. - aura::WindowTracker window_tracker_; - - // If |magnetism_window_| is non-NULL this indicates how the two windows - // should attach. - MatchedEdge magnetism_edge_; - - // Dock container window layout manager. - DockedWindowLayoutManager* dock_layout_; - - // Used to determine if this has been deleted during a drag such as when a tab - // gets dragged into another browser window. - base::WeakPtrFactory<WorkspaceWindowResizer> weak_ptr_factory_; - - // Current instance for use by the WorkspaceWindowResizerTest. - static WorkspaceWindowResizer* instance_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizer); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_WINDOW_RESIZER_H_ diff --git a/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc b/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc deleted file mode 100644 index 599c4ea98e8..00000000000 --- a/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc +++ /dev/null @@ -1,2027 +0,0 @@ -// 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/workspace/workspace_window_resizer.h" - -#include "ash/ash_constants.h" -#include "ash/ash_switches.h" -#include "ash/display/display_manager.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/phantom_window_controller.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "ash/wm/workspace_controller.h" -#include "base/command_line.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/gfx/insets.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" - -namespace gfx { - -// Class to provide access to SlideAnimation internals for testing. -// TODO: this should be next to SlideAnimation, not here. -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 { - -const int kRootHeight = 600; - -// A simple window delegate that returns the specified min size. -class TestWindowDelegate : public aura::test::TestWindowDelegate { - public: - TestWindowDelegate() { - } - virtual ~TestWindowDelegate() {} - - void set_min_size(const gfx::Size& size) { - min_size_ = size; - } - - void set_max_size(const gfx::Size& size) { - max_size_ = size; - } - - private: - // Overridden from aura::Test::TestWindowDelegate: - virtual gfx::Size GetMinimumSize() const OVERRIDE { - return min_size_; - } - - virtual gfx::Size GetMaximumSize() const OVERRIDE { - return max_size_; - } - - gfx::Size min_size_; - gfx::Size max_size_; - - DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate); -}; - -} // namespace - -class WorkspaceWindowResizerTest : public test::AshTestBase { - public: - WorkspaceWindowResizerTest() : workspace_resizer_(NULL) {} - virtual ~WorkspaceWindowResizerTest() {} - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - UpdateDisplay(base::StringPrintf("800x%d", kRootHeight)); - - aura::Window* root = Shell::GetPrimaryRootWindow(); - gfx::Rect root_bounds(root->bounds()); -#if defined(OS_WIN) - // RootWindow and Display can't resize on Windows Ash. - // http://crbug.com/165962 - EXPECT_EQ(kRootHeight, root_bounds.height()); -#endif - EXPECT_EQ(800, root_bounds.width()); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - window_.reset(new aura::Window(&delegate_)); - window_->SetType(aura::client::WINDOW_TYPE_NORMAL); - window_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(window_.get()); - window_->set_id(1); - - window2_.reset(new aura::Window(&delegate2_)); - window2_->SetType(aura::client::WINDOW_TYPE_NORMAL); - window2_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(window2_.get()); - window2_->set_id(2); - - window3_.reset(new aura::Window(&delegate3_)); - window3_->SetType(aura::client::WINDOW_TYPE_NORMAL); - window3_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(window3_.get()); - window3_->set_id(3); - - window4_.reset(new aura::Window(&delegate4_)); - window4_->SetType(aura::client::WINDOW_TYPE_NORMAL); - window4_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(window4_.get()); - window4_->set_id(4); - } - - virtual void TearDown() OVERRIDE { - window_.reset(); - window2_.reset(); - window3_.reset(); - window4_.reset(); - touch_resize_window_.reset(); - AshTestBase::TearDown(); - } - - // Returns a string identifying the z-order of each of the known child windows - // of |parent|. The returned string constains the id of the known windows and - // is ordered from topmost to bottomost windows. - std::string WindowOrderAsString(aura::Window* parent) const { - std::string result; - const aura::Window::Windows& windows = parent->children(); - for (aura::Window::Windows::const_reverse_iterator i = windows.rbegin(); - i != windows.rend(); ++i) { - if (*i == window_ || *i == window2_ || *i == window3_) { - if (!result.empty()) - result += " "; - result += base::IntToString((*i)->id()); - } - } - return result; - } - - protected: - WindowResizer* CreateResizerForTest( - aura::Window* window, - const gfx::Point& point_in_parent, - int window_component) { - WindowResizer* resizer = CreateWindowResizer( - window, - point_in_parent, - window_component, - aura::client::WINDOW_MOVE_SOURCE_MOUSE).release(); - workspace_resizer_ = WorkspaceWindowResizer::instance_; - return resizer; - } - - PhantomWindowController* snap_phantom_window_controller() const { - return workspace_resizer_->snap_phantom_window_controller_.get(); - } - - gfx::Point CalculateDragPoint(const WindowResizer& resizer, - int delta_x, - int delta_y) const { - gfx::Point location = resizer.GetInitialLocation(); - location.set_x(location.x() + delta_x); - location.set_y(location.y() + delta_y); - return location; - } - - std::vector<aura::Window*> empty_windows() const { - return std::vector<aura::Window*>(); - } - - internal::ShelfLayoutManager* shelf_layout_manager() { - return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); - } - - void InitTouchResizeWindow(const gfx::Rect& bounds, int window_component) { - touch_resize_delegate_.set_window_component(window_component); - touch_resize_window_.reset( - CreateTestWindowInShellWithDelegate(&touch_resize_delegate_, 0, - bounds)); - gfx::Insets mouse_outer_insets(-ash::kResizeOutsideBoundsSize, - -ash::kResizeOutsideBoundsSize, - -ash::kResizeOutsideBoundsSize, - -ash::kResizeOutsideBoundsSize); - gfx::Insets touch_outer_insets = mouse_outer_insets.Scale( - ash::kResizeOutsideBoundsScaleForTouch); - touch_resize_window_->SetHitTestBoundsOverrideOuter(mouse_outer_insets, - touch_outer_insets); - } - - // Simulate running the animation. - void RunAnimationTillComplete(gfx::SlideAnimation* animation) { - gfx::SlideAnimation::TestApi test_api(animation); - test_api.RunTillComplete(); - } - - TestWindowDelegate delegate_; - TestWindowDelegate delegate2_; - TestWindowDelegate delegate3_; - TestWindowDelegate delegate4_; - scoped_ptr<aura::Window> window_; - scoped_ptr<aura::Window> window2_; - scoped_ptr<aura::Window> window3_; - scoped_ptr<aura::Window> window4_; - - TestWindowDelegate touch_resize_delegate_; - scoped_ptr<aura::Window> touch_resize_window_; - WorkspaceWindowResizer* workspace_resizer_; - - private: - DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTest); -}; - -class WorkspaceWindowResizerTestSticky : public WorkspaceWindowResizerTest { - public: - WorkspaceWindowResizerTestSticky() {} - virtual ~WorkspaceWindowResizerTestSticky() {} - - virtual void SetUp() OVERRIDE { - CommandLine::ForCurrentProcess()->AppendSwitch( - ash::switches::kAshEnableStickyEdges); - WorkspaceWindowResizerTest::SetUp(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTestSticky); -}; - -// Assertions around attached window resize dragging from the right with 2 -// windows. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_2) { - window_->SetBounds(gfx::Rect(0, 300, 400, 300)); - window2_->SetBounds(gfx::Rect(400, 200, 100, 200)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the right, which should expand w1 and push w2. - resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0); - EXPECT_EQ("0,300 500x300", window_->bounds().ToString()); - EXPECT_EQ("500,200 100x200", window2_->bounds().ToString()); - - // Push off the screen, w2 should be resized to its min. - delegate2_.set_min_size(gfx::Size(20, 20)); - resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0); - EXPECT_EQ("0,300 780x300", window_->bounds().ToString()); - EXPECT_EQ("780,200 20x200", window2_->bounds().ToString()); - - // Move back to 100 and verify w2 gets its original size. - resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0); - EXPECT_EQ("0,300 500x300", window_->bounds().ToString()); - EXPECT_EQ("500,200 100x200", window2_->bounds().ToString()); - - // Revert and make sure everything moves back. - resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0); - resizer->RevertDrag(); - EXPECT_EQ("0,300 400x300", window_->bounds().ToString()); - EXPECT_EQ("400,200 100x200", window2_->bounds().ToString()); -} - -// Assertions around collapsing and expanding. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_Compress) { - window_->SetBounds(gfx::Rect( 0, 300, 400, 300)); - window2_->SetBounds(gfx::Rect(400, 200, 100, 200)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the left, which should expand w2 and collapse w1. - resizer->Drag(CalculateDragPoint(*resizer, -100, 10), 0); - EXPECT_EQ("0,300 300x300", window_->bounds().ToString()); - EXPECT_EQ("300,200 200x200", window2_->bounds().ToString()); - - // Collapse all the way to w1's min. - delegate_.set_min_size(gfx::Size(20, 20)); - resizer->Drag(CalculateDragPoint(*resizer, -800, 20), 0); - EXPECT_EQ("0,300 20x300", window_->bounds().ToString()); - EXPECT_EQ("20,200 480x200", window2_->bounds().ToString()); - - // Move 100 to the left. - resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0); - EXPECT_EQ("0,300 500x300", window_->bounds().ToString()); - EXPECT_EQ("500,200 100x200", window2_->bounds().ToString()); - - // Back to -100. - resizer->Drag(CalculateDragPoint(*resizer, -100, 20), 0); - EXPECT_EQ("0,300 300x300", window_->bounds().ToString()); - EXPECT_EQ("300,200 200x200", window2_->bounds().ToString()); -} - -// Assertions around attached window resize dragging from the right with 3 -// windows. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3) { - window_->SetBounds(gfx::Rect( 100, 300, 200, 300)); - window2_->SetBounds(gfx::Rect(300, 300, 150, 200)); - window3_->SetBounds(gfx::Rect(450, 300, 100, 200)); - delegate2_.set_min_size(gfx::Size(52, 50)); - delegate3_.set_min_size(gfx::Size(38, 50)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the right, which should expand w1 and push w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0); - EXPECT_EQ("100,300 300x300", window_->bounds().ToString()); - EXPECT_EQ("400,300 150x200", window2_->bounds().ToString()); - EXPECT_EQ("550,300 100x200", window3_->bounds().ToString()); - - // Move it 300, things should compress. - resizer->Drag(CalculateDragPoint(*resizer, 300, -10), 0); - EXPECT_EQ("100,300 500x300", window_->bounds().ToString()); - EXPECT_EQ("600,300 120x200", window2_->bounds().ToString()); - EXPECT_EQ("720,300 80x200", window3_->bounds().ToString()); - - // Move it so much the last two end up at their min. - resizer->Drag(CalculateDragPoint(*resizer, 800, 50), 0); - EXPECT_EQ("100,300 610x300", window_->bounds().ToString()); - EXPECT_EQ("710,300 52x200", window2_->bounds().ToString()); - EXPECT_EQ("762,300 38x200", window3_->bounds().ToString()); - - // Revert and make sure everything moves back. - resizer->RevertDrag(); - EXPECT_EQ("100,300 200x300", window_->bounds().ToString()); - EXPECT_EQ("300,300 150x200", window2_->bounds().ToString()); - EXPECT_EQ("450,300 100x200", window3_->bounds().ToString()); -} - -// Assertions around attached window resizing (collapsing and expanding) with -// 3 windows. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3_Compress) { - window_->SetBounds(gfx::Rect( 100, 300, 200, 300)); - window2_->SetBounds(gfx::Rect(300, 300, 200, 200)); - window3_->SetBounds(gfx::Rect(450, 300, 100, 200)); - delegate2_.set_min_size(gfx::Size(52, 50)); - delegate3_.set_min_size(gfx::Size(38, 50)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it -100 to the right, which should collapse w1 and expand w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0); - EXPECT_EQ("100,300 100x300", window_->bounds().ToString()); - EXPECT_EQ("200,300 266x200", window2_->bounds().ToString()); - EXPECT_EQ("466,300 134x200", window3_->bounds().ToString()); - - // Move it 100 to the right. - resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0); - EXPECT_EQ("100,300 300x300", window_->bounds().ToString()); - EXPECT_EQ("400,300 200x200", window2_->bounds().ToString()); - EXPECT_EQ("600,300 100x200", window3_->bounds().ToString()); - - // 100 to the left again. - resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0); - EXPECT_EQ("100,300 100x300", window_->bounds().ToString()); - EXPECT_EQ("200,300 266x200", window2_->bounds().ToString()); - EXPECT_EQ("466,300 134x200", window3_->bounds().ToString()); -} - -// Assertions around collapsing and expanding from the bottom. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_Compress) { - window_->SetBounds(gfx::Rect( 0, 100, 400, 300)); - window2_->SetBounds(gfx::Rect(400, 400, 100, 200)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it up 100, which should expand w2 and collapse w1. - resizer->Drag(CalculateDragPoint(*resizer, 10, -100), 0); - EXPECT_EQ("0,100 400x200", window_->bounds().ToString()); - EXPECT_EQ("400,300 100x300", window2_->bounds().ToString()); - - // Collapse all the way to w1's min. - delegate_.set_min_size(gfx::Size(20, 20)); - resizer->Drag(CalculateDragPoint(*resizer, 20, -800), 0); - EXPECT_EQ("0,100 400x20", window_->bounds().ToString()); - EXPECT_EQ("400,120 100x480", window2_->bounds().ToString()); - - // Move 100 down. - resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0); - EXPECT_EQ("0,100 400x400", window_->bounds().ToString()); - EXPECT_EQ("400,500 100x100", window2_->bounds().ToString()); - - // Back to -100. - resizer->Drag(CalculateDragPoint(*resizer, 20, -100), 0); - EXPECT_EQ("0,100 400x200", window_->bounds().ToString()); - EXPECT_EQ("400,300 100x300", window2_->bounds().ToString()); -} - -// Assertions around attached window resize dragging from the bottom with 2 -// windows. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_2) { - window_->SetBounds(gfx::Rect( 0, 50, 400, 200)); - window2_->SetBounds(gfx::Rect(0, 250, 200, 100)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the bottom, which should expand w1 and push w2. - resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0); - EXPECT_EQ("0,50 400x300", window_->bounds().ToString()); - EXPECT_EQ("0,350 200x100", window2_->bounds().ToString()); - - // Push off the screen, w2 should be resized to its min. - delegate2_.set_min_size(gfx::Size(20, 20)); - resizer->Drag(CalculateDragPoint(*resizer, 50, 820), 0); - EXPECT_EQ("0,50 400x530", window_->bounds().ToString()); - EXPECT_EQ("0,580 200x20", window2_->bounds().ToString()); - - // Move back to 100 and verify w2 gets its original size. - resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0); - EXPECT_EQ("0,50 400x300", window_->bounds().ToString()); - EXPECT_EQ("0,350 200x100", window2_->bounds().ToString()); - - // Revert and make sure everything moves back. - resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0); - resizer->RevertDrag(); - EXPECT_EQ("0,50 400x200", window_->bounds().ToString()); - EXPECT_EQ("0,250 200x100", window2_->bounds().ToString()); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_AttachedResize_BOTTOM_3 DISABLED_AttachedResize_BOTTOM_3 -#else -#define MAYBE_AttachedResize_BOTTOM_3 AttachedResize_BOTTOM_3 -#endif - -// Assertions around attached window resize dragging from the bottom with 3 -// windows. -TEST_F(WorkspaceWindowResizerTest, MAYBE_AttachedResize_BOTTOM_3) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - window_->SetBounds(gfx::Rect( 300, 100, 300, 200)); - window2_->SetBounds(gfx::Rect(300, 300, 200, 150)); - window3_->SetBounds(gfx::Rect(300, 450, 200, 100)); - delegate2_.set_min_size(gfx::Size(50, 52)); - delegate3_.set_min_size(gfx::Size(50, 38)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 down, which should expand w1 and push w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, -10, 100), 0); - EXPECT_EQ("300,100 300x300", window_->bounds().ToString()); - EXPECT_EQ("300,400 200x150", window2_->bounds().ToString()); - EXPECT_EQ("300,550 200x100", window3_->bounds().ToString()); - - // Move it 296 things should compress. - resizer->Drag(CalculateDragPoint(*resizer, -10, 296), 0); - EXPECT_EQ("300,100 300x496", window_->bounds().ToString()); - EXPECT_EQ("300,596 200x123", window2_->bounds().ToString()); - EXPECT_EQ("300,719 200x81", window3_->bounds().ToString()); - - // Move it so much everything ends up at its min. - resizer->Drag(CalculateDragPoint(*resizer, 50, 798), 0); - EXPECT_EQ("300,100 300x610", window_->bounds().ToString()); - EXPECT_EQ("300,710 200x52", window2_->bounds().ToString()); - EXPECT_EQ("300,762 200x38", window3_->bounds().ToString()); - - // Revert and make sure everything moves back. - resizer->RevertDrag(); - EXPECT_EQ("300,100 300x200", window_->bounds().ToString()); - EXPECT_EQ("300,300 200x150", window2_->bounds().ToString()); - EXPECT_EQ("300,450 200x100", window3_->bounds().ToString()); -} - -// Assertions around attached window resizing (collapsing and expanding) with -// 3 windows. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_3_Compress) { - window_->SetBounds(gfx::Rect( 0, 0, 200, 200)); - window2_->SetBounds(gfx::Rect(10, 200, 200, 200)); - window3_->SetBounds(gfx::Rect(20, 400, 100, 100)); - delegate2_.set_min_size(gfx::Size(52, 50)); - delegate3_.set_min_size(gfx::Size(38, 50)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 up, which should collapse w1 and expand w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0); - EXPECT_EQ("0,0 200x100", window_->bounds().ToString()); - EXPECT_EQ("10,100 200x266", window2_->bounds().ToString()); - EXPECT_EQ("20,366 100x134", window3_->bounds().ToString()); - - // Move it 100 down. - resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0); - EXPECT_EQ("0,0 200x300", window_->bounds().ToString()); - EXPECT_EQ("10,300 200x200", window2_->bounds().ToString()); - EXPECT_EQ("20,500 100x100", window3_->bounds().ToString()); - - // 100 up again. - resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0); - EXPECT_EQ("0,0 200x100", window_->bounds().ToString()); - EXPECT_EQ("10,100 200x266", window2_->bounds().ToString()); - EXPECT_EQ("20,366 100x134", window3_->bounds().ToString()); -} - -// Tests that touch-dragging a window does not lock the mouse cursor -// and therefore shows the cursor on a mousemove. -TEST_F(WorkspaceWindowResizerTest, MouseMoveWithTouchDrag) { - window_->SetBounds(gfx::Rect(0, 300, 400, 300)); - window2_->SetBounds(gfx::Rect(400, 200, 100, 200)); - - Shell* shell = Shell::GetInstance(); - aura::test::EventGenerator generator(window_->GetRootWindow()); - - // The cursor should not be locked initially. - EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked()); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_TOUCH, windows)); - ASSERT_TRUE(resizer.get()); - - // Creating a WorkspaceWindowResizer should not lock the cursor. - EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked()); - - // The cursor should be hidden after touching the screen and - // starting a drag. - EXPECT_TRUE(shell->cursor_manager()->IsCursorVisible()); - generator.PressTouch(); - resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0); - EXPECT_FALSE(shell->cursor_manager()->IsCursorVisible()); - EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked()); - - // Moving the mouse should show the cursor. - generator.MoveMouseBy(1, 1); - EXPECT_TRUE(shell->cursor_manager()->IsCursorVisible()); - EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked()); - - resizer->RevertDrag(); -} - -// Assertions around dragging to the left/right edge of the screen. -TEST_F(WorkspaceWindowResizerTest, Edge) { - if (!SupportsHostWindowResize()) - return; - - // Resize host window to force insets update. - UpdateDisplay("800x700"); - // TODO(varkha): Insets are reset after every drag because of - // http://crbug.com/292238. - // Window is wide enough not to get docked right away. - window_->SetBounds(gfx::Rect(20, 30, 400, 60)); - wm::WindowState* window_state = wm::GetWindowState(window_.get()); - - { - internal::SnapSizer snap_sizer(window_state, gfx::Point(), - internal::SnapSizer::LEFT_EDGE, internal::SnapSizer::OTHER_INPUT); - gfx::Rect expected_bounds(snap_sizer.target_bounds()); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 10), 0); - resizer->CompleteDrag(0); - - EXPECT_EQ(expected_bounds.ToString(), window_->bounds().ToString()); - ASSERT_TRUE(window_state->HasRestoreBounds()); - EXPECT_EQ("20,30 400x60", - window_state->GetRestoreBoundsInScreen().ToString()); - } - // Try the same with the right side. - { - internal::SnapSizer snap_sizer(window_state, gfx::Point(), - internal::SnapSizer::RIGHT_EDGE, internal::SnapSizer::OTHER_INPUT); - gfx::Rect expected_bounds(snap_sizer.target_bounds()); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0); - resizer->CompleteDrag(0); - EXPECT_EQ(expected_bounds.ToString(), window_->bounds().ToString()); - ASSERT_TRUE(window_state->HasRestoreBounds()); - EXPECT_EQ("20,30 400x60", - window_state->GetRestoreBoundsInScreen().ToString()); - } - - // Test if the restore bounds is correct in multiple displays. - if (!SupportsMultipleDisplays()) - return; - - // Restore the window to clear snapped state. - window_state->Restore(); - - UpdateDisplay("800x600,500x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - // Window is wide enough not to get docked right away. - window_->SetBoundsInScreen(gfx::Rect(800, 10, 400, 60), - ScreenAsh::GetSecondaryDisplay()); - EXPECT_EQ(root_windows[1], window_->GetRootWindow()); - { - EXPECT_EQ("800,10 400x60", window_->GetBoundsInScreen().ToString()); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 499, 0), 0); - int bottom = - ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_.get()).bottom(); - resizer->CompleteDrag(0); - // With the resolution of 500x600 we will hit in this case the 50% screen - // size setting. - // TODO(varkha): Insets are updated because of http://crbug.com/292238 - EXPECT_EQ("250,0 250x" + base::IntToString(bottom), - window_->bounds().ToString()); - EXPECT_EQ("800,10 400x60", - window_state->GetRestoreBoundsInScreen().ToString()); - } -} - -// Check that non resizable windows will not get resized. -TEST_F(WorkspaceWindowResizerTest, NonResizableWindows) { - window_->SetBounds(gfx::Rect(20, 30, 50, 60)); - window_->SetProperty(aura::client::kCanResizeKey, false); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, -20, 0), 0); - resizer->CompleteDrag(0); - EXPECT_EQ("0,30 50x60", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, CancelSnapPhantom) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("800x600,800x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - ASSERT_EQ(2U, root_windows.size()); - - window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); - { - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - EXPECT_FALSE(snap_phantom_window_controller()); - - // The pointer is on the edge but not shared. The snap phantom window - // controller should be non-NULL. - resizer->Drag(CalculateDragPoint(*resizer, 799, 0), 0); - EXPECT_TRUE(snap_phantom_window_controller()); - - // Move the cursor across the edge. Now the snap phantom window controller - // should be canceled. - resizer->Drag(CalculateDragPoint(*resizer, 800, 0), 0); - EXPECT_FALSE(snap_phantom_window_controller()); - } -} - -// Verifies windows are correctly restacked when reordering multiple windows. -TEST_F(WorkspaceWindowResizerTest, RestackAttached) { - window_->SetBounds(gfx::Rect( 0, 0, 200, 300)); - window2_->SetBounds(gfx::Rect(200, 0, 100, 200)); - window3_->SetBounds(gfx::Rect(300, 0, 100, 100)); - - { - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the right, which should expand w1 and push w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0); - - // 2 should be topmost since it's initially the highest in the stack. - EXPECT_EQ("2 1 3", WindowOrderAsString(window_->parent())); - } - - { - std::vector<aura::Window*> windows; - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window2_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the right, which should expand w1 and push w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0); - - // 2 should be topmost since it's initially the highest in the stack. - EXPECT_EQ("2 3 1", WindowOrderAsString(window_->parent())); - } -} - -// Makes sure we don't allow dragging below the work area. -TEST_F(WorkspaceWindowResizerTest, DontDragOffBottom) { - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0)); - - ASSERT_EQ(1, Shell::GetScreen()->GetNumDisplays()); - - window_->SetBounds(gfx::Rect(100, 200, 300, 400)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600), 0); - int expected_y = - kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10; - EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400", - window_->bounds().ToString()); -} - -// Makes sure we don't allow dragging on the work area with multidisplay. -TEST_F(WorkspaceWindowResizerTest, DontDragOffBottomWithMultiDisplay) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("800x600,800x600"); - ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays()); - - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0)); - - // Positions the secondary display at the bottom the primary display. - Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays( - ash::DisplayLayout(ash::DisplayLayout::BOTTOM, 0)); - - { - window_->SetBounds(gfx::Rect(100, 200, 300, 20)); - DCHECK_LT(window_->bounds().height(), - WorkspaceWindowResizer::kMinOnscreenHeight); - // Drag down avoiding dragging along the edge as that would side-snap. - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(10, 0), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0); - int expected_y = kRootHeight - window_->bounds().height() - 10; - // When the mouse cursor is in the primary display, the window cannot move - // on non-work area but can get all the way towards the bottom, - // restricted only by the window height. - EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x20", - window_->bounds().ToString()); - // Revert the drag in order to not remember the restore bounds. - resizer->RevertDrag(); - } - - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0)); - { - window_->SetBounds(gfx::Rect(100, 200, 300, 400)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(10, 0), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Drag down avoiding dragging along the edge as that would side-snap. - resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0); - int expected_y = - kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10; - // When the mouse cursor is in the primary display, the window cannot move - // on non-work area with kMinOnscreenHeight margin. - EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400", - window_->bounds().ToString()); - resizer->CompleteDrag(0); - } - - { - window_->SetBounds(gfx::Rect(100, 200, 300, 400)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), window_->bounds().origin(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Drag down avoiding getting stuck against the shelf on the bottom screen. - resizer->Drag(CalculateDragPoint(*resizer, 0, 500), 0); - // The window can move to the secondary display beyond non-work area of - // the primary display. - EXPECT_EQ("100,700 300x400", window_->bounds().ToString()); - resizer->CompleteDrag(0); - } -} - -// Makes sure we don't allow dragging off the top of the work area. -TEST_F(WorkspaceWindowResizerTest, DontDragOffTop) { - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(10, 0, 0, 0)); - - window_->SetBounds(gfx::Rect(100, 200, 300, 400)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, -600), 0); - EXPECT_EQ("100,10 300x400", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, ResizeBottomOutsideWorkArea) { - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); - - window_->SetBounds(gfx::Rect(100, 200, 300, 380)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOP)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 8, 0), 0); - EXPECT_EQ("100,200 300x380", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideLeftWorkArea) { - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); - int left = ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_.get()).x(); - int pixels_to_left_border = 50; - int window_width = 300; - int window_x = left - window_width + pixels_to_left_border; - window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(pixels_to_left_border, 0), HTRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, -window_width, 0), 0); - EXPECT_EQ(base::IntToString(window_x) + ",100 " + - base::IntToString(kMinimumOnScreenArea - window_x) + - "x380", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideRightWorkArea) { - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); - int right = ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get()).right(); - int pixels_to_right_border = 50; - int window_width = 300; - int window_x = right - pixels_to_right_border; - window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(window_x, 0), HTLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0); - EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) + - ",100 " + - base::IntToString(window_width - pixels_to_right_border + - kMinimumOnScreenArea) + - "x380", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideBottomWorkArea) { - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); - int bottom = ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get()).bottom(); - int delta_to_bottom = 50; - int height = 380; - window_->SetBounds(gfx::Rect(100, bottom - delta_to_bottom, 300, height)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(0, bottom - delta_to_bottom), HTTOP)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, bottom), 0); - EXPECT_EQ("100," + - base::IntToString(bottom - kMinimumOnScreenArea) + - " 300x" + - base::IntToString(height - (delta_to_bottom - - kMinimumOnScreenArea)), - window_->bounds().ToString()); -} - -// Verifies that 'outside' check of the resizer take into account the extended -// desktop in case of repositions. -TEST_F(WorkspaceWindowResizerTest, DragWindowOutsideRightToSecondaryDisplay) { - // Only primary display. Changes the window position to fit within the - // display. - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); - int right = ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get()).right(); - int pixels_to_right_border = 50; - int window_width = 300; - int window_x = right - pixels_to_right_border; - window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(window_x, 0), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0); - EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) + - ",100 " + - base::IntToString(window_width) + - "x380", window_->bounds().ToString()); - - if (!SupportsMultipleDisplays()) - return; - - // With secondary display. Operation itself is same but doesn't change - // the position because the window is still within the secondary display. - UpdateDisplay("1000x600,600x400"); - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); - window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380)); - resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0); - EXPECT_EQ(base::IntToString(window_x + window_width) + - ",100 " + - base::IntToString(window_width) + - "x380", window_->bounds().ToString()); -} - -// Verifies snapping to edges works. -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<WindowResizer> resizer(CreateResizerForTest( - window_.get(), - window_->bounds().origin() + gfx::Vector2d(50, 0), - HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move to an x-coordinate of 15, which should not snap. - resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0); - // An x-coordinate of 7 should snap. - resizer->Drag(CalculateDragPoint(*resizer, 7 - 96, 0), 0); - EXPECT_EQ("0,112 320x160", window_->bounds().ToString()); - // Move to -15, should still snap to 0. - resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0); - EXPECT_EQ("0,112 320x160", window_->bounds().ToString()); - // At -32 should move past snap points. - resizer->Drag(CalculateDragPoint(*resizer, -32 - 96, 0), 0); - EXPECT_EQ("-32,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, -33 - 96, 0), 0); - EXPECT_EQ("-33,112 320x160", window_->bounds().ToString()); - - // Right side should similarly snap. - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 15, 0), 0); - EXPECT_EQ("465,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 7, 0), 0); - EXPECT_EQ("480,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 15, 0), 0); - EXPECT_EQ("480,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 32, 0), 0); - EXPECT_EQ("512,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 33, 0), 0); - EXPECT_EQ("513,112 320x160", window_->bounds().ToString()); - - // And the bottom should snap too. - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 - 7), 0); - EXPECT_EQ("96,437 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 + 15), 0); - EXPECT_EQ("96,437 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 32), 0); - EXPECT_EQ("96,470 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 33), 0); - EXPECT_EQ("96,471 320x160", window_->bounds().ToString()); - - // And the top should snap too. - resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 20), 0); - EXPECT_EQ("96,20 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 7), 0); - EXPECT_EQ("96,0 320x160", window_->bounds().ToString()); - - // And bottom/left should snap too. - resizer->Drag( - CalculateDragPoint(*resizer, 7 - 96, 600 - 160 - 112 - 3 - 7), 0); - EXPECT_EQ("0,437 320x160", window_->bounds().ToString()); - resizer->Drag( - CalculateDragPoint(*resizer, -15 - 96, 600 - 160 - 112 - 3 + 15), 0); - EXPECT_EQ("0,437 320x160", window_->bounds().ToString()); - // should move past snap points. - resizer->Drag( - CalculateDragPoint(*resizer, -32 - 96, 600 - 160 - 112 - 2 + 32), 0); - EXPECT_EQ("-32,470 320x160", window_->bounds().ToString()); - resizer->Drag( - CalculateDragPoint(*resizer, -33 - 96, 600 - 160 - 112 - 2 + 33), 0); - EXPECT_EQ("-33,471 320x160", window_->bounds().ToString()); - - // No need to test dragging < 0 as we force that to 0. -} - -// Verifies a resize snap when dragging TOPLEFT. -TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, -98, -199), 0); - EXPECT_EQ("0,0 120x230", window_->bounds().ToString()); -} - -// Verifies a resize snap when dragging TOPRIGHT. -TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag( - CalculateDragPoint(*resizer, work_area.right() - 120 - 1, -199), 0); - EXPECT_EQ(100, window_->bounds().x()); - EXPECT_EQ(work_area.y(), window_->bounds().y()); - EXPECT_EQ(work_area.right() - 100, window_->bounds().width()); - EXPECT_EQ(230, window_->bounds().height()); -} - -// Verifies a resize snap when dragging BOTTOMRIGHT. -TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag( - CalculateDragPoint(*resizer, work_area.right() - 120 - 1, - work_area.bottom() - 220 - 2), 0); - EXPECT_EQ(100, window_->bounds().x()); - EXPECT_EQ(200, window_->bounds().y()); - EXPECT_EQ(work_area.right() - 100, window_->bounds().width()); - EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height()); -} - -// Verifies a resize snap when dragging BOTTOMLEFT. -TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag( - CalculateDragPoint(*resizer, -98, work_area.bottom() - 220 - 2), 0); - EXPECT_EQ(0, window_->bounds().x()); - EXPECT_EQ(200, window_->bounds().y()); - EXPECT_EQ(120, window_->bounds().width()); - EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height()); -} - -// Verifies sticking to edges works. -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<WindowResizer> resizer(CreateResizerForTest( - window_.get(), - window_->bounds().origin() + gfx::Vector2d(50, 0), - HTCAPTION)); - 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("0,112 320x160", window_->bounds().ToString()); - // At -100 should move past edge. - resizer->Drag(CalculateDragPoint(*resizer, -100 - 96, 0), 0); - EXPECT_EQ("-100,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, -101 - 96, 0), 0); - EXPECT_EQ("-101,112 320x160", window_->bounds().ToString()); - - // Right side should similarly stick. - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 15, 0), 0); - EXPECT_EQ("465,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 15, 0), 0); - EXPECT_EQ("480,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 100, 0), 0); - EXPECT_EQ("580,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 101, 0), 0); - EXPECT_EQ("581,112 320x160", window_->bounds().ToString()); - - // And the bottom should stick too. - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 + 15), 0); - EXPECT_EQ("96,437 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 100), 0); - EXPECT_EQ("96,538 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 101), 0); - EXPECT_EQ("96,539 320x160", window_->bounds().ToString()); - - // 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<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - 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)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, -15 - 100, -15 -200), 0); - EXPECT_EQ("0,0 120x230", window_->bounds().ToString()); -} - -// Verifies a resize sticks when dragging TOPRIGHT. -TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_TOPRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, work_area.right() - 100 + 20, - -200 - 15), 0); - EXPECT_EQ(100, window_->bounds().x()); - EXPECT_EQ(work_area.y(), window_->bounds().y()); - EXPECT_EQ(work_area.right() - 100, window_->bounds().width()); - EXPECT_EQ(230, window_->bounds().height()); -} - -// Verifies a resize snap when dragging BOTTOMRIGHT. -TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_BOTTOMRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, work_area.right() - 100 - 20 + 15, - work_area.bottom() - 200 - 30 + 15), 0); - EXPECT_EQ(100, window_->bounds().x()); - EXPECT_EQ(200, window_->bounds().y()); - EXPECT_EQ(work_area.right() - 100, window_->bounds().width()); - EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height()); -} - -// Verifies a resize snap when dragging BOTTOMLEFT. -TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_BOTTOMLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, -15 - 100, - work_area.bottom() - 200 - 30 + 15), 0); - EXPECT_EQ(0, window_->bounds().x()); - EXPECT_EQ(200, window_->bounds().y()); - EXPECT_EQ(120, window_->bounds().width()); - EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height()); -} - -TEST_F(WorkspaceWindowResizerTest, CtrlDragResizeToExactPosition) { - window_->SetBounds(gfx::Rect(96, 112, 320, 160)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - ASSERT_TRUE(resizer.get()); - // Resize the right bottom to add 10 in width, 12 in height. - resizer->Drag(CalculateDragPoint(*resizer, 10, 12), ui::EF_CONTROL_DOWN); - // Both bottom and right sides to resize to exact size requested. - EXPECT_EQ("96,112 330x172", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, CtrlCompleteDragMoveToExactPosition) { - window_->SetBounds(gfx::Rect(96, 112, 320, 160)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Ctrl + drag the window to new poistion by adding (10, 12) to its origin, - // the window should move to the exact position. - resizer->Drag(CalculateDragPoint(*resizer, 10, 12), 0); - resizer->CompleteDrag(ui::EF_CONTROL_DOWN); - EXPECT_EQ("106,124 320x160", window_->bounds().ToString()); -} - -// Verifies that a dragged window will restore to its pre-maximized size. -TEST_F(WorkspaceWindowResizerTest, RestoreToPreMaximizeCoordinates) { - window_->SetBounds(gfx::Rect(0, 0, 1000, 1000)); - wm::WindowState* window_state = wm::GetWindowState(window_.get()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(96, 112, 320, 160)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Drag the window to new position by adding (10, 10) to original point, - // the window should get restored. - resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0); - resizer->CompleteDrag(0); - EXPECT_EQ("10,10 320x160", window_->bounds().ToString()); - // The restore rectangle should get cleared as well. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Verifies that a dragged window will restore to its pre-maximized size. -TEST_F(WorkspaceWindowResizerTest, RevertResizeOperation) { - const gfx::Rect initial_bounds(0, 0, 200, 400); - window_->SetBounds(initial_bounds); - - wm::WindowState* window_state = wm::GetWindowState(window_.get()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(96, 112, 320, 160)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Drag the window to new poistion by adding (180, 16) to original point, - // the window should get restored. - resizer->Drag(CalculateDragPoint(*resizer, 180, 16), 0); - resizer->RevertDrag(); - EXPECT_EQ(initial_bounds.ToString(), window_->bounds().ToString()); - EXPECT_EQ("96,112 320x160", - window_state->GetRestoreBoundsInScreen().ToString()); -} - -// Check that only usable sizes get returned by the resizer. -TEST_F(WorkspaceWindowResizerTest, MagneticallyAttach) { - window_->SetBounds(gfx::Rect(10, 10, 20, 30)); - window2_->SetBounds(gfx::Rect(150, 160, 25, 20)); - window2_->Show(); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move |window| one pixel to the left of |window2|. Should snap to right and - // top. - resizer->Drag(CalculateDragPoint(*resizer, 119, 145), 0); - EXPECT_EQ("130,160 20x30", window_->bounds().ToString()); - - // Move |window| one pixel to the right of |window2|. Should snap to left and - // top. - resizer->Drag(CalculateDragPoint(*resizer, 164, 145), 0); - EXPECT_EQ("175,160 20x30", window_->bounds().ToString()); - - // Move |window| one pixel above |window2|. Should snap to top and left. - resizer->Drag(CalculateDragPoint(*resizer, 142, 119), 0); - EXPECT_EQ("150,130 20x30", window_->bounds().ToString()); - - // Move |window| one pixel above the bottom of |window2|. Should snap to - // bottom and left. - resizer->Drag(CalculateDragPoint(*resizer, 142, 169), 0); - EXPECT_EQ("150,180 20x30", window_->bounds().ToString()); -} - -// The following variants verify magnetic snapping during resize when dragging a -// particular edge. -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOP) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->SetBounds(gfx::Rect(99, 179, 10, 20)); - window2_->Show(); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOP)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,199 20x31", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->SetBounds(gfx::Rect(99, 179, 10, 20)); - window2_->Show(); - - { - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("99,199 21x31", window_->bounds().ToString()); - resizer->RevertDrag(); - } - - { - window2_->SetBounds(gfx::Rect(88, 201, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("98,201 22x29", window_->bounds().ToString()); - resizer->RevertDrag(); - } -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->Show(); - - { - window2_->SetBounds(gfx::Rect(111, 179, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,199 21x31", window_->bounds().ToString()); - resizer->RevertDrag(); - } - - { - window2_->SetBounds(gfx::Rect(121, 199, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,199 21x31", window_->bounds().ToString()); - resizer->RevertDrag(); - } -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_RIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->SetBounds(gfx::Rect(121, 199, 10, 20)); - window2_->Show(); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,200 21x30", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->Show(); - - { - window2_->SetBounds(gfx::Rect(122, 212, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,200 22x32", window_->bounds().ToString()); - resizer->RevertDrag(); - } - - { - window2_->SetBounds(gfx::Rect(111, 233, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,200 21x33", window_->bounds().ToString()); - resizer->RevertDrag(); - } -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOM) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->SetBounds(gfx::Rect(111, 233, 10, 20)); - window2_->Show(); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOM)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,200 20x33", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->Show(); - - { - window2_->SetBounds(gfx::Rect(99, 231, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("99,200 21x31", window_->bounds().ToString()); - resizer->RevertDrag(); - } - - { - window2_->SetBounds(gfx::Rect(89, 209, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("99,200 21x29", window_->bounds().ToString()); - resizer->RevertDrag(); - } -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_LEFT) { - window2_->SetBounds(gfx::Rect(89, 209, 10, 20)); - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->Show(); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("99,200 21x30", window_->bounds().ToString()); -} - -// Test that the user user moved window flag is getting properly set. -TEST_F(WorkspaceWindowResizerTest, CheckUserWindowManagedFlags) { - window_->SetBounds(gfx::Rect( 0, 50, 400, 200)); - - std::vector<aura::Window*> no_attached_windows; - // Check that an abort doesn't change anything. - { - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the bottom. - resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0); - EXPECT_EQ("0,150 400x200", window_->bounds().ToString()); - resizer->RevertDrag(); - - EXPECT_FALSE(wm::GetWindowState(window_.get())->bounds_changed_by_user()); - } - - // Check that a completed move / size does change the user coordinates. - { - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the bottom. - resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0); - EXPECT_EQ("0,150 400x200", window_->bounds().ToString()); - resizer->CompleteDrag(0); - EXPECT_TRUE(wm::GetWindowState(window_.get())->bounds_changed_by_user()); - } -} - -// Test that a window with a specified max size doesn't exceed it when dragged. -TEST_F(WorkspaceWindowResizerTest, TestMaxSizeEnforced) { - window_->SetBounds(gfx::Rect(0, 0, 400, 300)); - delegate_.set_max_size(gfx::Size(401, 301)); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0); - EXPECT_EQ(401, window_->bounds().width()); - EXPECT_EQ(301, window_->bounds().height()); -} - -// Test that a window with a specified max width doesn't restrict its height. -TEST_F(WorkspaceWindowResizerTest, TestPartialMaxSizeEnforced) { - window_->SetBounds(gfx::Rect(0, 0, 400, 300)); - delegate_.set_max_size(gfx::Size(401, 0)); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0); - EXPECT_EQ(401, window_->bounds().width()); - EXPECT_EQ(302, window_->bounds().height()); -} - -// Test that a window with a specified max size can't be snapped. -TEST_F(WorkspaceWindowResizerTest, PhantomSnapMaxSize) { - { - // With max size not set we get a phantom window controller for dragging off - // the right hand side. - // Make the window wider than maximum docked width. - window_->SetBounds(gfx::Rect(0, 0, 400, 200)); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - EXPECT_FALSE(snap_phantom_window_controller()); - resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0); - EXPECT_TRUE(snap_phantom_window_controller()); - resizer->RevertDrag(); - } - { - // With max size defined, we get no phantom window for snapping but we still - // get a phantom window (docking guide). - window_->SetBounds(gfx::Rect(0, 0, 400, 200)); - delegate_.set_max_size(gfx::Size(400, 200)); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0); - if (switches::UseDockedWindows()) - EXPECT_TRUE(snap_phantom_window_controller()); - else - EXPECT_FALSE(snap_phantom_window_controller()); - resizer->RevertDrag(); - } - { - // With max size defined, we get no phantom window for snapping. - window_->SetBounds(gfx::Rect(0, 0, 400, 200)); - delegate_.set_max_size(gfx::Size(400, 200)); - // With min size defined, we get no phantom window for docking. - delegate_.set_min_size(gfx::Size(400, 200)); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0); - EXPECT_FALSE(snap_phantom_window_controller()); - resizer->RevertDrag(); - } -} - -TEST_F(WorkspaceWindowResizerTest, DontRewardRightmostWindowForOverflows) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Four 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - window4_->SetBounds(gfx::Rect(400, 100, 100, 100)); - delegate2_.set_max_size(gfx::Size(101, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 51 to the left, which should contract w1 and expand w2-4. - // w2 will hit its max size straight away, and in doing so will leave extra - // pixels that a naive implementation may award to the rightmost window. A - // fair implementation will give 25 pixels to each of the other windows. - resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0); - EXPECT_EQ("100,100 49x100", window_->bounds().ToString()); - EXPECT_EQ("149,100 101x100", window2_->bounds().ToString()); - EXPECT_EQ("250,100 125x100", window3_->bounds().ToString()); - EXPECT_EQ("375,100 125x100", window4_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, DontExceedMaxWidth) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Four 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - window4_->SetBounds(gfx::Rect(400, 100, 100, 100)); - delegate2_.set_max_size(gfx::Size(101, 0)); - delegate3_.set_max_size(gfx::Size(101, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 52 to the left, which should contract w1 and expand w2-4. - resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0); - EXPECT_EQ("100,100 48x100", window_->bounds().ToString()); - EXPECT_EQ("148,100 101x100", window2_->bounds().ToString()); - EXPECT_EQ("249,100 101x100", window3_->bounds().ToString()); - EXPECT_EQ("350,100 150x100", window4_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, DontExceedMaxHeight) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Four 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(100, 200, 100, 100)); - window3_->SetBounds(gfx::Rect(100, 300, 100, 100)); - window4_->SetBounds(gfx::Rect(100, 400, 100, 100)); - delegate2_.set_max_size(gfx::Size(0, 101)); - delegate3_.set_max_size(gfx::Size(0, 101)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 52 up, which should contract w1 and expand w2-4. - resizer->Drag(CalculateDragPoint(*resizer, 0, -52), 0); - EXPECT_EQ("100,100 100x48", window_->bounds().ToString()); - EXPECT_EQ("100,148 100x101", window2_->bounds().ToString()); - EXPECT_EQ("100,249 100x101", window3_->bounds().ToString()); - EXPECT_EQ("100,350 100x150", window4_->bounds().ToString()); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_DontExceedMinHeight DISABLED_DontExceedMinHeight -#else -#define MAYBE_DontExceedMinHeight DontExceedMinHeight -#endif - -TEST_F(WorkspaceWindowResizerTest, MAYBE_DontExceedMinHeight) { - UpdateDisplay("600x500"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Four 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(100, 200, 100, 100)); - window3_->SetBounds(gfx::Rect(100, 300, 100, 100)); - window4_->SetBounds(gfx::Rect(100, 400, 100, 100)); - delegate2_.set_min_size(gfx::Size(0, 99)); - delegate3_.set_min_size(gfx::Size(0, 99)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 52 down, which should expand w1 and contract w2-4. - resizer->Drag(CalculateDragPoint(*resizer, 0, 52), 0); - EXPECT_EQ("100,100 100x152", window_->bounds().ToString()); - EXPECT_EQ("100,252 100x99", window2_->bounds().ToString()); - EXPECT_EQ("100,351 100x99", window3_->bounds().ToString()); - EXPECT_EQ("100,450 100x50", window4_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, DontExpandRightmostPastMaxWidth) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Three 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - delegate3_.set_max_size(gfx::Size(101, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 51 to the left, which should contract w1 and expand w2-3. - resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0); - EXPECT_EQ("100,100 49x100", window_->bounds().ToString()); - EXPECT_EQ("149,100 150x100", window2_->bounds().ToString()); - EXPECT_EQ("299,100 101x100", window3_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, MoveAttachedWhenGrownToMaxSize) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Three 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - delegate2_.set_max_size(gfx::Size(101, 0)); - delegate3_.set_max_size(gfx::Size(101, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 52 to the left, which should contract w1 and expand and move w2-3. - resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0); - EXPECT_EQ("100,100 48x100", window_->bounds().ToString()); - EXPECT_EQ("148,100 101x100", window2_->bounds().ToString()); - EXPECT_EQ("249,100 101x100", window3_->bounds().ToString()); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_MainWindowHonoursMaxWidth DISABLED_MainWindowHonoursMaxWidth -#else -#define MAYBE_MainWindowHonoursMaxWidth MainWindowHonoursMaxWidth -#endif - -TEST_F(WorkspaceWindowResizerTest, MAYBE_MainWindowHonoursMaxWidth) { - UpdateDisplay("400x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Three 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - delegate_.set_max_size(gfx::Size(102, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 50 to the right, which should expand w1 and contract w2-3, as they - // won't fit in the root window in their original sizes. - resizer->Drag(CalculateDragPoint(*resizer, 50, 0), 0); - EXPECT_EQ("100,100 102x100", window_->bounds().ToString()); - EXPECT_EQ("202,100 99x100", window2_->bounds().ToString()); - EXPECT_EQ("301,100 99x100", window3_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, MainWindowHonoursMinWidth) { - UpdateDisplay("400x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Three 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - delegate_.set_min_size(gfx::Size(98, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 50 to the left, which should contract w1 and expand w2-3. - resizer->Drag(CalculateDragPoint(*resizer, -50, 0), 0); - EXPECT_EQ("100,100 98x100", window_->bounds().ToString()); - EXPECT_EQ("198,100 101x100", window2_->bounds().ToString()); - EXPECT_EQ("299,100 101x100", window3_->bounds().ToString()); -} - -// The following variants test that windows are resized correctly to the edges -// of the screen using touch, when touch point is off of the window border. -TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_RIGHT) { - shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN); - - InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTRIGHT); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - touch_resize_window_.get()); - - // Drag out of the right border a bit and check if the border is aligned with - // the touch point. - generator.GestureScrollSequence(gfx::Point(715, kRootHeight / 2), - gfx::Point(725, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 625, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag more, but stop before being snapped to the edge. - generator.GestureScrollSequence(gfx::Point(725, kRootHeight / 2), - gfx::Point(760, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 660, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag even more to snap to the edge. - generator.GestureScrollSequence(gfx::Point(760, kRootHeight / 2), - gfx::Point(775, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 700, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_LEFT) { - shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN); - - InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTLEFT); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - touch_resize_window_.get()); - - // Drag out of the left border a bit and check if the border is aligned with - // the touch point. - generator.GestureScrollSequence(gfx::Point(85, kRootHeight / 2), - gfx::Point(75, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(75, 100, 625, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag more, but stop before being snapped to the edge. - generator.GestureScrollSequence(gfx::Point(75, kRootHeight / 2), - gfx::Point(40, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(40, 100, 660, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag even more to snap to the edge. - generator.GestureScrollSequence(gfx::Point(40, kRootHeight / 2), - gfx::Point(25, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(0, 100, 700, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_TOP) { - shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN); - - InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTTOP); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - touch_resize_window_.get()); - - // Drag out of the top border a bit and check if the border is aligned with - // the touch point. - generator.GestureScrollSequence(gfx::Point(400, 85), - gfx::Point(400, 75), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 75, 600, kRootHeight - 175).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag more, but stop before being snapped to the edge. - generator.GestureScrollSequence(gfx::Point(400, 75), - gfx::Point(400, 40), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 40, 600, kRootHeight - 140).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag even more to snap to the edge. - generator.GestureScrollSequence(gfx::Point(400, 40), - gfx::Point(400, 25), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 0, 600, kRootHeight - 100).ToString(), - touch_resize_window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_BOTTOM) { - shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN); - - InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTBOTTOM); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - touch_resize_window_.get()); - - // Drag out of the bottom border a bit and check if the border is aligned with - // the touch point. - generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 85), - gfx::Point(400, kRootHeight - 75), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 175).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag more, but stop before being snapped to the edge. - generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 75), - gfx::Point(400, kRootHeight - 40), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 140).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag even more to snap to the edge. - generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 40), - gfx::Point(400, kRootHeight - 25), - base::TimeDelta::FromMilliseconds(10), - 5); - 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()); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - EXPECT_FALSE(snap_phantom_window_controller()); - - // The pointer is on the edge but not shared. The snap phantom window - // controller should be non-NULL. - resizer->Drag(CalculateDragPoint(*resizer, -1, 0), 0); - EXPECT_TRUE(snap_phantom_window_controller()); - PhantomWindowController* phantom_controller(snap_phantom_window_controller()); - - // 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 deleted file mode 100644 index 1b9fd854a17..00000000000 --- a/chromium/ash/wm/workspace_controller.cc +++ /dev/null @@ -1,145 +0,0 @@ -// 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/workspace_controller.h" - -#include "ash/root_window_controller.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/base_layout_manager.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/workspace_event_handler.h" -#include "ash/wm/workspace/workspace_layout_manager.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/views/corewm/visibility_controller.h" -#include "ui/views/corewm/window_animations.h" - -namespace ash { -namespace internal { -namespace { - -// Amount of time to pause before animating anything. Only used during initial -// animation (when logging in). -const int kInitialPauseTimeMS = 750; - -// Returns true if there are visible docked windows in the same screen as the -// |shelf|. -bool IsDockedAreaVisible(const ShelfLayoutManager* shelf) { - return shelf->dock_bounds().width() > 0; -} - -} // namespace - -WorkspaceController::WorkspaceController(aura::Window* viewport) - : viewport_(viewport), - shelf_(NULL), - event_handler_(new WorkspaceEventHandler(viewport_)) { - SetWindowVisibilityAnimationTransition( - viewport_, views::corewm::ANIMATE_NONE); - - // The layout-manager cannot be created in the initializer list since it - // depends on the window to have been initialized. - layout_manager_ = new WorkspaceLayoutManager(viewport_); - viewport_->SetLayoutManager(layout_manager_); - - viewport_->Show(); -} - -WorkspaceController::~WorkspaceController() { - viewport_->SetLayoutManager(NULL); - viewport_->SetEventFilter(NULL); - viewport_->RemovePreTargetHandler(event_handler_.get()); - viewport_->RemovePostTargetHandler(event_handler_.get()); -} - -WorkspaceWindowState WorkspaceController::GetWindowState() const { - if (!shelf_) - return WORKSPACE_WINDOW_STATE_DEFAULT; - const aura::Window* topmost_fullscreen_window = GetRootWindowController( - viewport_->GetRootWindow())->GetWindowForFullscreenMode(); - if (topmost_fullscreen_window && - !wm::GetWindowState(topmost_fullscreen_window)->ignored_by_shelf()) { - return WORKSPACE_WINDOW_STATE_FULL_SCREEN; - } - - // These are the container ids of containers which may contain windows that - // may overlap the launcher shelf and affect its transparency. - const int kWindowContainerIds[] = { - internal::kShellWindowId_DefaultContainer, - internal::kShellWindowId_DockedContainer, - }; - const gfx::Rect shelf_bounds(shelf_->GetIdealBounds()); - bool window_overlaps_launcher = false; - for (size_t idx = 0; idx < arraysize(kWindowContainerIds); idx++) { - const aura::Window* container = Shell::GetContainer( - viewport_->GetRootWindow(), kWindowContainerIds[idx]); - const aura::Window::Windows& windows(container->children()); - for (aura::Window::Windows::const_iterator i = windows.begin(); - i != windows.end(); ++i) { - wm::WindowState* window_state = wm::GetWindowState(*i); - if (window_state->ignored_by_shelf()) - continue; - ui::Layer* layer = (*i)->layer(); - if (!layer->GetTargetVisibility()) - continue; - if (window_state->IsMaximized()) - return WORKSPACE_WINDOW_STATE_MAXIMIZED; - if (!window_overlaps_launcher && - ((*i)->bounds().Intersects(shelf_bounds))) { - window_overlaps_launcher = true; - } - } - } - - return (window_overlaps_launcher || IsDockedAreaVisible(shelf_)) ? - WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF : - WORKSPACE_WINDOW_STATE_DEFAULT; -} - -void WorkspaceController::SetShelf(ShelfLayoutManager* shelf) { - shelf_ = shelf; - layout_manager_->SetShelf(shelf); -} - -void WorkspaceController::DoInitialAnimation() { - viewport_->Show(); - - viewport_->layer()->SetOpacity(0.0f); - SetTransformForScaleAnimation( - viewport_->layer(), LAYER_SCALE_ANIMATION_ABOVE); - - // In order for pause to work we need to stop animations. - viewport_->layer()->GetAnimator()->StopAnimating(); - - { - ui::ScopedLayerAnimationSettings settings( - viewport_->layer()->GetAnimator()); - - settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION); - viewport_->layer()->GetAnimator()->SchedulePauseForProperties( - base::TimeDelta::FromMilliseconds(kInitialPauseTimeMS), - ui::LayerAnimationElement::TRANSFORM, - ui::LayerAnimationElement::OPACITY, - ui::LayerAnimationElement::BRIGHTNESS, - ui::LayerAnimationElement::VISIBILITY, - -1); - - settings.SetTweenType(gfx::Tween::EASE_OUT); - settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kCrossFadeDurationMS)); - viewport_->layer()->SetTransform(gfx::Transform()); - viewport_->layer()->SetOpacity(1.0f); - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace_controller.h b/chromium/ash/wm/workspace_controller.h deleted file mode 100644 index 84df41c91d3..00000000000 --- a/chromium/ash/wm/workspace_controller.h +++ /dev/null @@ -1,55 +0,0 @@ -// 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_WORKSPACE_CONTROLLER_H_ -#define ASH_WM_WORKSPACE_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "ash/wm/workspace/workspace_types.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" - -namespace aura { -class Window; -} - -namespace ash { -namespace internal { - -class ShelfLayoutManager; -class WorkspaceControllerTestHelper; -class WorkspaceEventHandler; -class WorkspaceLayoutManager; - -// WorkspaceController acts as a central place that ties together all the -// various workspace pieces. -class ASH_EXPORT WorkspaceController { - public: - explicit WorkspaceController(aura::Window* viewport); - virtual ~WorkspaceController(); - - // Returns the current window state. - WorkspaceWindowState GetWindowState() const; - - void SetShelf(ShelfLayoutManager* shelf); - - // Starts the animation that occurs on first login. - void DoInitialAnimation(); - - private: - friend class WorkspaceControllerTestHelper; - - aura::Window* viewport_; - - internal::ShelfLayoutManager* shelf_; - scoped_ptr<internal::WorkspaceEventHandler> event_handler_; - internal::WorkspaceLayoutManager* layout_manager_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceController); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_CONTROLLER_H_ diff --git a/chromium/ash/wm/workspace_controller_test_helper.cc b/chromium/ash/wm/workspace_controller_test_helper.cc deleted file mode 100644 index 5ecfa2f5edf..00000000000 --- a/chromium/ash/wm/workspace_controller_test_helper.cc +++ /dev/null @@ -1,32 +0,0 @@ -// 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/workspace_controller_test_helper.h" - -#include "ash/wm/workspace_controller.h" -#include "ash/wm/workspace/workspace_event_handler_test_helper.h" -#include "ui/aura/window.h" - -namespace ash { -namespace internal { - -WorkspaceControllerTestHelper::WorkspaceControllerTestHelper( - WorkspaceController* controller) - : controller_(controller) { -} - -WorkspaceControllerTestHelper::~WorkspaceControllerTestHelper() { -} - -WorkspaceEventHandler* WorkspaceControllerTestHelper::GetEventHandler() { - return controller_->event_handler_.get(); -} - -MultiWindowResizeController* -WorkspaceControllerTestHelper::GetMultiWindowResizeController() { - return WorkspaceEventHandlerTestHelper(GetEventHandler()).resize_controller(); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace_controller_test_helper.h b/chromium/ash/wm/workspace_controller_test_helper.h deleted file mode 100644 index ecdccccca07..00000000000 --- a/chromium/ash/wm/workspace_controller_test_helper.h +++ /dev/null @@ -1,33 +0,0 @@ -// 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_WORKSPACE_CONTROLLER_TEST_HELPER_H_ -#define ASH_WM_WORKSPACE_CONTROLLER_TEST_HELPER_H_ - -#include "ash/wm/workspace_controller.h" - -namespace ash { -namespace internal { - -class MultiWindowResizeController; -class WorkspaceEventHandler; - -class WorkspaceControllerTestHelper { - public: - explicit WorkspaceControllerTestHelper(WorkspaceController* controller); - ~WorkspaceControllerTestHelper(); - - WorkspaceEventHandler* GetEventHandler(); - MultiWindowResizeController* GetMultiWindowResizeController(); - - private: - WorkspaceController* controller_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceControllerTestHelper); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_CONTROLLER_TEST_HELPER_H_ diff --git a/chromium/ash/wm/workspace_controller_unittest.cc b/chromium/ash/wm/workspace_controller_unittest.cc deleted file mode 100644 index dbf114e0d0e..00000000000 --- a/chromium/ash/wm/workspace_controller_unittest.cc +++ /dev/null @@ -1,1316 +0,0 @@ -// Copyright 2013 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/workspace_controller.h" - -#include <map> - -#include "ash/ash_switches.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/system/status_area_widget.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/shell_test_api.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/command_line.h" -#include "base/strings/string_number_conversions.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_types.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" -#include "ui/gfx/screen.h" -#include "ui/views/corewm/window_animations.h" -#include "ui/views/widget/widget.h" - -using aura::Window; - -namespace ash { -namespace internal { - -// Returns a string containing the names of all the children of |window| (in -// order). Each entry is separated by a space. -std::string GetWindowNames(const aura::Window* window) { - std::string result; - for (size_t i = 0; i < window->children().size(); ++i) { - if (i != 0) - result += " "; - result += window->children()[i]->name(); - } - return result; -} - -// Returns a string containing the names of windows corresponding to each of the -// child layers of |window|'s layer. Any layers that don't correspond to a child -// Window of |window| are ignored. The result is ordered based on the layer -// ordering. -std::string GetLayerNames(const aura::Window* window) { - typedef std::map<const ui::Layer*, std::string> LayerToWindowNameMap; - LayerToWindowNameMap window_names; - for (size_t i = 0; i < window->children().size(); ++i) { - window_names[window->children()[i]->layer()] = - window->children()[i]->name(); - } - - std::string result; - const std::vector<ui::Layer*>& layers(window->layer()->children()); - for (size_t i = 0; i < layers.size(); ++i) { - LayerToWindowNameMap::iterator layer_i = - window_names.find(layers[i]); - if (layer_i != window_names.end()) { - if (!result.empty()) - result += " "; - result += layer_i->second; - } - } - return result; -} - -class WorkspaceControllerTest : public test::AshTestBase { - public: - WorkspaceControllerTest() {} - virtual ~WorkspaceControllerTest() {} - - aura::Window* CreateTestWindowUnparented() { - aura::Window* window = new aura::Window(NULL); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - return window; - } - - aura::Window* CreateTestWindow() { - aura::Window* window = new aura::Window(NULL); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - ParentWindowInPrimaryRootWindow(window); - return window; - } - - aura::Window* CreateBrowserLikeWindow(const gfx::Rect& bounds) { - aura::Window* window = CreateTestWindow(); - window->SetBounds(bounds); - wm::WindowState* window_state = wm::GetWindowState(window); - window_state->set_window_position_managed(true); - window->Show(); - return window; - } - - aura::Window* CreatePopupLikeWindow(const gfx::Rect& bounds) { - aura::Window* window = CreateTestWindowInShellWithBounds(bounds); - window->Show(); - return window; - } - - aura::Window* GetDesktop() { - return Shell::GetContainer(Shell::GetPrimaryRootWindow(), - kShellWindowId_DefaultContainer); - } - - gfx::Rect GetFullscreenBounds(aura::Window* window) { - return Shell::GetScreen()->GetDisplayNearestWindow(window).bounds(); - } - - ShelfWidget* shelf_widget() { - return Shell::GetPrimaryRootWindowController()->shelf(); - } - - ShelfLayoutManager* shelf_layout_manager() { - return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); - } - - bool GetWindowOverlapsShelf() { - return shelf_layout_manager()->window_overlaps_shelf(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(WorkspaceControllerTest); -}; - -// Assertions around adding a normal window. -TEST_F(WorkspaceControllerTest, AddNormalWindowWhenEmpty) { - scoped_ptr<Window> w1(CreateTestWindow()); - w1->SetBounds(gfx::Rect(0, 0, 250, 251)); - - wm::WindowState* window_state = wm::GetWindowState(w1.get()); - - EXPECT_FALSE(window_state->HasRestoreBounds()); - - w1->Show(); - - EXPECT_FALSE(window_state->HasRestoreBounds()); - - ASSERT_TRUE(w1->layer() != NULL); - EXPECT_TRUE(w1->layer()->visible()); - - EXPECT_EQ("0,0 250x251", w1->bounds().ToString()); - - EXPECT_EQ(w1.get(), GetDesktop()->children()[0]); -} - -// Assertions around maximizing/unmaximizing. -TEST_F(WorkspaceControllerTest, SingleMaximizeWindow) { - scoped_ptr<Window> w1(CreateTestWindow()); - w1->SetBounds(gfx::Rect(0, 0, 250, 251)); - - w1->Show(); - wm::ActivateWindow(w1.get()); - - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - - ASSERT_TRUE(w1->layer() != NULL); - EXPECT_TRUE(w1->layer()->visible()); - - EXPECT_EQ("0,0 250x251", w1->bounds().ToString()); - - // Maximize the window. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - - EXPECT_TRUE(wm::IsActiveWindow(w1.get())); - - EXPECT_EQ(w1.get(), GetDesktop()->children()[0]); - EXPECT_EQ(ScreenAsh::GetMaximizedWindowBoundsInParent(w1.get()).width(), - w1->bounds().width()); - EXPECT_EQ(ScreenAsh::GetMaximizedWindowBoundsInParent(w1.get()).height(), - w1->bounds().height()); - - // Restore the window. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - - EXPECT_EQ(w1.get(), GetDesktop()->children()[0]); - EXPECT_EQ("0,0 250x251", w1->bounds().ToString()); -} - -// Assertions around two windows and toggling one to be fullscreen. -TEST_F(WorkspaceControllerTest, FullscreenWithNormalWindow) { - scoped_ptr<Window> w1(CreateTestWindow()); - scoped_ptr<Window> w2(CreateTestWindow()); - w1->SetBounds(gfx::Rect(0, 0, 250, 251)); - w1->Show(); - - ASSERT_TRUE(w1->layer() != NULL); - EXPECT_TRUE(w1->layer()->visible()); - - w2->SetBounds(gfx::Rect(0, 0, 50, 51)); - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - w2->Show(); - wm::ActivateWindow(w2.get()); - - // Both windows should be in the same workspace. - EXPECT_EQ(w1.get(), GetDesktop()->children()[0]); - EXPECT_EQ(w2.get(), GetDesktop()->children()[1]); - - gfx::Rect work_area( - ScreenAsh::GetMaximizedWindowBoundsInParent(w1.get())); - EXPECT_EQ(work_area.width(), w2->bounds().width()); - EXPECT_EQ(work_area.height(), w2->bounds().height()); - - // Restore w2, which should then go back to one workspace. - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(50, w2->bounds().width()); - EXPECT_EQ(51, w2->bounds().height()); - EXPECT_TRUE(wm::IsActiveWindow(w2.get())); -} - -// Makes sure requests to change the bounds of a normal window go through. -TEST_F(WorkspaceControllerTest, ChangeBoundsOfNormalWindow) { - scoped_ptr<Window> w1(CreateTestWindow()); - w1->Show(); - - // Setting the bounds should go through since the window is in the normal - // workspace. - w1->SetBounds(gfx::Rect(0, 0, 200, 500)); - EXPECT_EQ(200, w1->bounds().width()); - EXPECT_EQ(500, w1->bounds().height()); -} - -// Verifies the bounds is not altered when showing and grid is enabled. -TEST_F(WorkspaceControllerTest, SnapToGrid) { - scoped_ptr<Window> w1(CreateTestWindowUnparented()); - w1->SetBounds(gfx::Rect(1, 6, 25, 30)); - ParentWindowInPrimaryRootWindow(w1.get()); - // We are not aligning this anymore this way. When the window gets shown - // the window is expected to be handled differently, but this cannot be - // tested with this test. So the result of this test should be that the - // bounds are exactly as passed in. - EXPECT_EQ("1,6 25x30", w1->bounds().ToString()); -} - -// Assertions around a fullscreen window. -TEST_F(WorkspaceControllerTest, SingleFullscreenWindow) { - scoped_ptr<Window> w1(CreateTestWindow()); - w1->SetBounds(gfx::Rect(0, 0, 250, 251)); - // Make the window fullscreen. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - w1->Show(); - wm::ActivateWindow(w1.get()); - - EXPECT_EQ(w1.get(), GetDesktop()->children()[0]); - EXPECT_EQ(GetFullscreenBounds(w1.get()).width(), w1->bounds().width()); - EXPECT_EQ(GetFullscreenBounds(w1.get()).height(), w1->bounds().height()); - - // Restore the window. Use SHOW_STATE_DEFAULT as that is what we'll end up - // with when using views::Widget. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_DEFAULT); - EXPECT_EQ("0,0 250x251", w1->bounds().ToString()); - - EXPECT_EQ(w1.get(), GetDesktop()->children()[0]); - EXPECT_EQ(250, w1->bounds().width()); - EXPECT_EQ(251, w1->bounds().height()); - - // Back to fullscreen. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - EXPECT_EQ(w1.get(), GetDesktop()->children()[0]); - EXPECT_EQ(GetFullscreenBounds(w1.get()).width(), w1->bounds().width()); - EXPECT_EQ(GetFullscreenBounds(w1.get()).height(), w1->bounds().height()); - wm::WindowState* window_state = wm::GetWindowState(w1.get()); - - ASSERT_TRUE(window_state->HasRestoreBounds()); - EXPECT_EQ("0,0 250x251", window_state->GetRestoreBoundsInScreen().ToString()); -} - -// Assertions around minimizing a single window. -TEST_F(WorkspaceControllerTest, MinimizeSingleWindow) { - scoped_ptr<Window> w1(CreateTestWindow()); - - w1->Show(); - - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - EXPECT_FALSE(w1->layer()->IsDrawn()); - - // Show the window. - w1->Show(); - EXPECT_TRUE(wm::GetWindowState(w1.get())->IsNormalShowState()); - EXPECT_TRUE(w1->layer()->IsDrawn()); -} - -// Assertions around minimizing a fullscreen window. -TEST_F(WorkspaceControllerTest, MinimizeFullscreenWindow) { - // Two windows, w1 normal, w2 fullscreen. - scoped_ptr<Window> w1(CreateTestWindow()); - scoped_ptr<Window> w2(CreateTestWindow()); - w1->Show(); - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - w2->Show(); - - wm::WindowState* w1_state = wm::GetWindowState(w1.get()); - wm::WindowState* w2_state = wm::GetWindowState(w2.get()); - - w2_state->Activate(); - - // Minimize w2. - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - EXPECT_TRUE(w1->layer()->IsDrawn()); - EXPECT_FALSE(w2->layer()->IsDrawn()); - - // Show the window, which should trigger unminimizing. - w2->Show(); - w2_state->Activate(); - - EXPECT_TRUE(w2_state->IsFullscreen()); - EXPECT_TRUE(w1->layer()->IsDrawn()); - EXPECT_TRUE(w2->layer()->IsDrawn()); - - // Minimize the window, which should hide the window. - EXPECT_TRUE(w2_state->IsActive()); - w2_state->Minimize(); - EXPECT_FALSE(w2_state->IsActive()); - EXPECT_FALSE(w2->layer()->IsDrawn()); - EXPECT_TRUE(w1_state->IsActive()); - - // Make the window normal. - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(w1.get(), GetDesktop()->children()[0]); - EXPECT_EQ(w2.get(), GetDesktop()->children()[1]); - EXPECT_TRUE(w2->layer()->IsDrawn()); -} - -// Verifies ShelfLayoutManager's visibility/auto-hide state is correctly -// updated. -TEST_F(WorkspaceControllerTest, ShelfStateUpdated) { - // Since ShelfLayoutManager queries for mouse location, move the mouse so - // it isn't over the shelf. - aura::test::EventGenerator generator( - Shell::GetPrimaryRootWindow(), gfx::Point()); - generator.MoveMouseTo(0, 0); - - scoped_ptr<Window> w1(CreateTestWindow()); - const gfx::Rect w1_bounds(0, 1, 101, 102); - ShelfLayoutManager* shelf = shelf_layout_manager(); - shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - const gfx::Rect touches_shelf_bounds( - 0, shelf->GetIdealBounds().y() - 10, 101, 102); - // Move |w1| to overlap the shelf. - w1->SetBounds(touches_shelf_bounds); - EXPECT_FALSE(GetWindowOverlapsShelf()); - - // A visible ignored window should not trigger the overlap. - scoped_ptr<Window> w_ignored(CreateTestWindow()); - w_ignored->SetBounds(touches_shelf_bounds); - wm::GetWindowState(&(*w_ignored))->set_ignored_by_shelf(true); - w_ignored->Show(); - EXPECT_FALSE(GetWindowOverlapsShelf()); - - // Make it visible, since visible shelf overlaps should be true. - w1->Show(); - EXPECT_TRUE(GetWindowOverlapsShelf()); - - wm::ActivateWindow(w1.get()); - w1->SetBounds(w1_bounds); - w1->Show(); - wm::ActivateWindow(w1.get()); - - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); - - // Maximize the window. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); - EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); - - // Restore. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); - EXPECT_EQ("0,1 101x102", w1->bounds().ToString()); - - // Fullscreen. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state()); - - // Normal. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); - EXPECT_EQ("0,1 101x102", w1->bounds().ToString()); - EXPECT_FALSE(GetWindowOverlapsShelf()); - - // Move window so it obscures shelf. - w1->SetBounds(touches_shelf_bounds); - EXPECT_TRUE(GetWindowOverlapsShelf()); - - // Move it back. - w1->SetBounds(w1_bounds); - EXPECT_FALSE(GetWindowOverlapsShelf()); - - // Maximize again. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); - EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); - - // Minimize. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); - - // Since the restore from minimize will restore to the pre-minimize - // state (tested elsewhere), we abandon the current size and restore - // rect and set them to the window. - wm::WindowState* window_state = wm::GetWindowState(w1.get()); - - gfx::Rect restore = window_state->GetRestoreBoundsInScreen(); - EXPECT_EQ("0,0 800x597", w1->bounds().ToString()); - EXPECT_EQ("0,1 101x102", restore.ToString()); - window_state->ClearRestoreBounds(); - w1->SetBounds(restore); - - // Restore. - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); - EXPECT_EQ("0,1 101x102", w1->bounds().ToString()); - - // Create another window, maximized. - scoped_ptr<Window> w2(CreateTestWindow()); - w2->SetBounds(gfx::Rect(10, 11, 250, 251)); - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - w2->Show(); - wm::ActivateWindow(w2.get()); - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); - EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); - EXPECT_EQ("0,1 101x102", w1->bounds().ToString()); - - // Switch to w1. - wm::ActivateWindow(w1.get()); - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); - EXPECT_EQ("0,1 101x102", w1->bounds().ToString()); - EXPECT_EQ(ScreenAsh::GetMaximizedWindowBoundsInParent( - w2->parent()).ToString(), - w2->bounds().ToString()); - - // Switch to w2. - wm::ActivateWindow(w2.get()); - EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); - EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); - EXPECT_EQ("0,1 101x102", w1->bounds().ToString()); - EXPECT_EQ(ScreenAsh::GetMaximizedWindowBoundsInParent(w2.get()).ToString(), - w2->bounds().ToString()); - - // Turn off auto-hide, switch back to w2 (maximized) and verify overlap. - shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); - wm::ActivateWindow(w2.get()); - EXPECT_FALSE(GetWindowOverlapsShelf()); - - // Move w1 to overlap shelf, it shouldn't change window overlaps shelf since - // the window isn't in the visible workspace. - w1->SetBounds(touches_shelf_bounds); - EXPECT_FALSE(GetWindowOverlapsShelf()); - - // Activate w1. Although w1 is visible, the overlap state is still false since - // w2 is maximized. - wm::ActivateWindow(w1.get()); - EXPECT_FALSE(GetWindowOverlapsShelf()); - - // Restore w2. - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_TRUE(GetWindowOverlapsShelf()); -} - -// Verifies going from maximized to minimized sets the right state for painting -// the background of the launcher. -TEST_F(WorkspaceControllerTest, MinimizeResetsVisibility) { - scoped_ptr<Window> w1(CreateTestWindow()); - w1->Show(); - wm::ActivateWindow(w1.get()); - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, shelf_widget()->GetBackgroundType()); - - w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - EXPECT_EQ(SHELF_VISIBLE, - shelf_layout_manager()->visibility_state()); - EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, shelf_widget()->GetBackgroundType()); -} - -// Verifies window visibility during various workspace changes. -TEST_F(WorkspaceControllerTest, VisibilityTests) { - scoped_ptr<Window> w1(CreateTestWindow()); - w1->Show(); - EXPECT_TRUE(w1->IsVisible()); - EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity()); - - // Create another window, activate it and make it fullscreen. - scoped_ptr<Window> w2(CreateTestWindow()); - w2->Show(); - wm::ActivateWindow(w2.get()); - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - EXPECT_TRUE(w2->IsVisible()); - EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity()); - EXPECT_TRUE(w1->IsVisible()); - - // Switch to w1. |w1| should be visible on top of |w2|. - wm::ActivateWindow(w1.get()); - EXPECT_TRUE(w1->IsVisible()); - EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity()); - EXPECT_TRUE(w2->IsVisible()); - - // Switch back to |w2|. - wm::ActivateWindow(w2.get()); - EXPECT_TRUE(w2->IsVisible()); - EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity()); - EXPECT_TRUE(w1->IsVisible()); - - // Restore |w2|, both windows should be visible. - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_TRUE(w1->IsVisible()); - EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity()); - EXPECT_TRUE(w2->IsVisible()); - EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity()); - - // Make |w2| fullscreen again, then close it. - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - w2->Hide(); - EXPECT_FALSE(w2->IsVisible()); - EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity()); - EXPECT_TRUE(w1->IsVisible()); - - // Create |w2| and maximize it. - w2.reset(CreateTestWindow()); - w2->Show(); - wm::ActivateWindow(w2.get()); - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - EXPECT_TRUE(w2->IsVisible()); - EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity()); - EXPECT_TRUE(w1->IsVisible()); - - // Close |w2|. - w2.reset(); - EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity()); - EXPECT_TRUE(w1->IsVisible()); -} - -// Verifies windows that are offscreen don't move when switching workspaces. -TEST_F(WorkspaceControllerTest, DontMoveOnSwitch) { - aura::test::EventGenerator generator( - Shell::GetPrimaryRootWindow(), gfx::Point()); - generator.MoveMouseTo(0, 0); - - scoped_ptr<Window> w1(CreateTestWindow()); - ShelfLayoutManager* shelf = shelf_layout_manager(); - const gfx::Rect touches_shelf_bounds( - 0, shelf->GetIdealBounds().y() - 10, 101, 102); - // Move |w1| to overlap the shelf. - w1->SetBounds(touches_shelf_bounds); - w1->Show(); - wm::ActivateWindow(w1.get()); - - // Create another window and maximize it. - scoped_ptr<Window> w2(CreateTestWindow()); - w2->SetBounds(gfx::Rect(10, 11, 250, 251)); - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - w2->Show(); - wm::ActivateWindow(w2.get()); - - // Switch to w1. - wm::ActivateWindow(w1.get()); - EXPECT_EQ(touches_shelf_bounds.ToString(), w1->bounds().ToString()); -} - -// Verifies that windows that are completely offscreen move when switching -// workspaces. -TEST_F(WorkspaceControllerTest, MoveOnSwitch) { - aura::test::EventGenerator generator( - Shell::GetPrimaryRootWindow(), gfx::Point()); - generator.MoveMouseTo(0, 0); - - scoped_ptr<Window> w1(CreateTestWindow()); - ShelfLayoutManager* shelf = shelf_layout_manager(); - const gfx::Rect w1_bounds(0, shelf->GetIdealBounds().y(), 100, 200); - // Move |w1| so that the top edge is the same as the top edge of the shelf. - w1->SetBounds(w1_bounds); - w1->Show(); - wm::ActivateWindow(w1.get()); - EXPECT_EQ(w1_bounds.ToString(), w1->bounds().ToString()); - - // Create another window and maximize it. - scoped_ptr<Window> w2(CreateTestWindow()); - w2->SetBounds(gfx::Rect(10, 11, 250, 251)); - w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - w2->Show(); - wm::ActivateWindow(w2.get()); - - // Increase the size of the WorkAreaInsets. This would make |w1| fall - // completely out of the display work area. - gfx::Insets insets = - Shell::GetScreen()->GetPrimaryDisplay().GetWorkAreaInsets(); - insets.Set(0, 0, insets.bottom() + 30, 0); - Shell::GetInstance()->SetDisplayWorkAreaInsets(w1.get(), insets); - - // Switch to w1. The window should have moved. - wm::ActivateWindow(w1.get()); - EXPECT_NE(w1_bounds.ToString(), w1->bounds().ToString()); -} - -namespace { - -// WindowDelegate used by DontCrashOnChangeAndActivate. -class DontCrashOnChangeAndActivateDelegate - : public aura::test::TestWindowDelegate { - public: - DontCrashOnChangeAndActivateDelegate() : window_(NULL) {} - - void set_window(aura::Window* window) { window_ = window; } - - // WindowDelegate overrides: - virtual void OnBoundsChanged(const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE { - if (window_) { - wm::ActivateWindow(window_); - window_ = NULL; - } - } - - private: - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(DontCrashOnChangeAndActivateDelegate); -}; - -} // namespace - -// Exercises possible crash in W2. Here's the sequence: -// . minimize a maximized window. -// . remove the window (which happens when switching displays). -// . add the window back. -// . show the window and during the bounds change activate it. -TEST_F(WorkspaceControllerTest, DontCrashOnChangeAndActivate) { - // Force the shelf - ShelfLayoutManager* shelf = shelf_layout_manager(); - shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); - - DontCrashOnChangeAndActivateDelegate delegate; - scoped_ptr<Window> w1(CreateTestWindowInShellWithDelegate( - &delegate, 1000, gfx::Rect(10, 11, 250, 251))); - - w1->Show(); - wm::WindowState* w1_state = wm::GetWindowState(w1.get()); - w1_state->Activate(); - w1_state->Maximize(); - w1_state->Minimize(); - - w1->parent()->RemoveChild(w1.get()); - - // Do this so that when we Show() the window a resize occurs and we make the - // window active. - shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - - ParentWindowInPrimaryRootWindow(w1.get()); - delegate.set_window(w1.get()); - w1->Show(); -} - -// Verifies a window with a transient parent not managed by workspace works. -TEST_F(WorkspaceControllerTest, TransientParent) { - // Normal window with no transient parent. - scoped_ptr<Window> w2(CreateTestWindow()); - w2->SetBounds(gfx::Rect(10, 11, 250, 251)); - w2->Show(); - wm::ActivateWindow(w2.get()); - - // Window with a transient parent. We set the transient parent to the root, - // which would never happen but is enough to exercise the bug. - scoped_ptr<Window> w1(CreateTestWindowUnparented()); - Shell::GetInstance()->GetPrimaryRootWindow()->AddTransientChild(w1.get()); - w1->SetBounds(gfx::Rect(10, 11, 250, 251)); - ParentWindowInPrimaryRootWindow(w1.get()); - w1->Show(); - wm::ActivateWindow(w1.get()); - - // The window with the transient parent should get added to the same parent as - // the normal window. - EXPECT_EQ(w2->parent(), w1->parent()); -} - -// Test the placement of newly created windows. -TEST_F(WorkspaceControllerTest, BasicAutoPlacingOnCreate) { - if (!SupportsHostWindowResize()) - return; - UpdateDisplay("1600x1200"); - // Creating a popup handler here to make sure it does not interfere with the - // existing windows. - gfx::Rect source_browser_bounds(16, 32, 640, 320); - scoped_ptr<aura::Window> browser_window(CreateBrowserLikeWindow( - source_browser_bounds)); - - // Creating a popup to make sure it does not interfere with the positioning. - scoped_ptr<aura::Window> browser_popup(CreatePopupLikeWindow( - gfx::Rect(16, 32, 128, 256))); - - browser_window->Show(); - browser_popup->Show(); - - { // With a shown window it's size should get returned. - scoped_ptr<aura::Window> new_browser_window(CreateBrowserLikeWindow( - source_browser_bounds)); - // The position should be right flush. - EXPECT_EQ("960,32 640x320", new_browser_window->bounds().ToString()); - } - - { // With the window shown - but more on the right side then on the left - // side (and partially out of the screen), it should default to the other - // side and inside the screen. - gfx::Rect source_browser_bounds(gfx::Rect(1000, 600, 640, 320)); - browser_window->SetBounds(source_browser_bounds); - - scoped_ptr<aura::Window> new_browser_window(CreateBrowserLikeWindow( - source_browser_bounds)); - // The position should be left & bottom flush. - EXPECT_EQ("0,600 640x320", new_browser_window->bounds().ToString()); - - // If the other window was already beyond the point to get right flush - // it will remain where it is. - EXPECT_EQ("1000,600 640x320", browser_window->bounds().ToString()); - } - - { // Make sure that popups do not get changed. - scoped_ptr<aura::Window> new_popup_window(CreatePopupLikeWindow( - gfx::Rect(50, 100, 300, 150))); - EXPECT_EQ("50,100 300x150", new_popup_window->bounds().ToString()); - } - - browser_window->Hide(); - { // If a window is there but not shown the default should be centered. - scoped_ptr<aura::Window> new_browser_window(CreateBrowserLikeWindow( - gfx::Rect(50, 100, 300, 150))); - EXPECT_EQ("650,100 300x150", new_browser_window->bounds().ToString()); - } -} - -// Test the basic auto placement of one and or two windows in a "simulated -// session" of sequential window operations. -TEST_F(WorkspaceControllerTest, BasicAutoPlacingOnShowHide) { - // Test 1: In case there is no manageable window, no window should shift. - - scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); - window1->SetBounds(gfx::Rect(16, 32, 640, 320)); - gfx::Rect desktop_area = window1->parent()->bounds(); - - scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); - // Trigger the auto window placement function by making it visible. - // Note that the bounds are getting changed while it is invisible. - window2->Hide(); - window2->SetBounds(gfx::Rect(32, 48, 256, 512)); - window2->Show(); - - // Check the initial position of the windows is unchanged. - EXPECT_EQ("16,32 640x320", window1->bounds().ToString()); - EXPECT_EQ("32,48 256x512", window2->bounds().ToString()); - - // Remove the second window and make sure that the first window - // does NOT get centered. - window2.reset(); - EXPECT_EQ("16,32 640x320", window1->bounds().ToString()); - - wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - // Test 2: Set up two managed windows and check their auto positioning. - window1_state->set_window_position_managed(true); - - scoped_ptr<aura::Window> window3(CreateTestWindowInShellWithId(2)); - wm::GetWindowState(window3.get())->set_window_position_managed(true); - // To avoid any auto window manager changes due to SetBounds, the window - // gets first hidden and then shown again. - window3->Hide(); - window3->SetBounds(gfx::Rect(32, 48, 256, 512)); - window3->Show(); - // |window1| should be flush left and |window3| flush right. - EXPECT_EQ("0,32 640x320", window1->bounds().ToString()); - EXPECT_EQ(base::IntToString( - desktop_area.width() - window3->bounds().width()) + - ",48 256x512", window3->bounds().ToString()); - - // After removing |window3|, |window1| should be centered again. - window3.reset(); - EXPECT_EQ( - base::IntToString( - (desktop_area.width() - window1->bounds().width()) / 2) + - ",32 640x320", window1->bounds().ToString()); - - // Test 3: Set up a manageable and a non manageable window and check - // positioning. - scoped_ptr<aura::Window> window4(CreateTestWindowInShellWithId(3)); - // To avoid any auto window manager changes due to SetBounds, the window - // gets first hidden and then shown again. - window1->Hide(); - window1->SetBounds(gfx::Rect(16, 32, 640, 320)); - window4->SetBounds(gfx::Rect(32, 48, 256, 512)); - window1->Show(); - // |window1| should be centered and |window4| untouched. - EXPECT_EQ( - base::IntToString( - (desktop_area.width() - window1->bounds().width()) / 2) + - ",32 640x320", window1->bounds().ToString()); - EXPECT_EQ("32,48 256x512", window4->bounds().ToString()); - - // Test4: A single manageable window should get centered. - window4.reset(); - window1_state->set_bounds_changed_by_user(false); - // Trigger the auto window placement function by showing (and hiding) it. - window1->Hide(); - window1->Show(); - // |window1| should be centered. - EXPECT_EQ( - base::IntToString( - (desktop_area.width() - window1->bounds().width()) / 2) + - ",32 640x320", window1->bounds().ToString()); -} - -// Test the proper usage of user window movement interaction. -TEST_F(WorkspaceControllerTest, TestUserMovedWindowRepositioning) { - scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); - window1->SetBounds(gfx::Rect(16, 32, 640, 320)); - gfx::Rect desktop_area = window1->parent()->bounds(); - scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); - window2->SetBounds(gfx::Rect(32, 48, 256, 512)); - window1->Hide(); - window2->Hide(); - wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - wm::WindowState* window2_state = wm::GetWindowState(window2.get()); - - window1_state->set_window_position_managed(true); - window2_state->set_window_position_managed(true); - EXPECT_FALSE(window1_state->bounds_changed_by_user()); - EXPECT_FALSE(window2_state->bounds_changed_by_user()); - - // Check that the current location gets preserved if the user has - // positioned it previously. - window1_state->set_bounds_changed_by_user(true); - window1->Show(); - EXPECT_EQ("16,32 640x320", window1->bounds().ToString()); - // Flag should be still set. - EXPECT_TRUE(window1_state->bounds_changed_by_user()); - EXPECT_FALSE(window2_state->bounds_changed_by_user()); - - // Turn on the second window and make sure that both windows are now - // positionable again (user movement cleared). - window2->Show(); - - // |window1| should be flush left and |window2| flush right. - EXPECT_EQ("0,32 640x320", window1->bounds().ToString()); - EXPECT_EQ( - base::IntToString(desktop_area.width() - window2->bounds().width()) + - ",48 256x512", window2->bounds().ToString()); - // FLag should now be reset. - EXPECT_FALSE(window1_state->bounds_changed_by_user()); - EXPECT_FALSE(window2_state->bounds_changed_by_user()); - - // Going back to one shown window should keep the state. - window1_state->set_bounds_changed_by_user(true); - window2->Hide(); - EXPECT_EQ("0,32 640x320", window1->bounds().ToString()); - EXPECT_TRUE(window1_state->bounds_changed_by_user()); -} - -// Test if the single window will be restored at original position. -TEST_F(WorkspaceControllerTest, TestSingleWindowsRestoredBounds) { - scoped_ptr<aura::Window> window1( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - scoped_ptr<aura::Window> window2( - CreateTestWindowInShellWithBounds(gfx::Rect(110, 110, 100, 100))); - scoped_ptr<aura::Window> window3( - CreateTestWindowInShellWithBounds(gfx::Rect(120, 120, 100, 100))); - window1->Hide(); - window2->Hide(); - window3->Hide(); - wm::GetWindowState(window1.get())->set_window_position_managed(true); - wm::GetWindowState(window2.get())->set_window_position_managed(true); - wm::GetWindowState(window3.get())->set_window_position_managed(true); - - window1->Show(); - wm::ActivateWindow(window1.get()); - window2->Show(); - wm::ActivateWindow(window2.get()); - window3->Show(); - wm::ActivateWindow(window3.get()); - EXPECT_EQ(0, window1->bounds().x()); - EXPECT_EQ(window2->GetRootWindow()->bounds().right(), - window2->bounds().right()); - EXPECT_EQ(0, window3->bounds().x()); - - window1->Hide(); - EXPECT_EQ(window2->GetRootWindow()->bounds().right(), - window2->bounds().right()); - EXPECT_EQ(0, window3->bounds().x()); - - // Being a single window will retore the original location. - window3->Hide(); - wm::ActivateWindow(window2.get()); - EXPECT_EQ("110,110 100x100", window2->bounds().ToString()); - - // Showing the 3rd will push the 2nd window left. - window3->Show(); - wm::ActivateWindow(window3.get()); - EXPECT_EQ(0, window2->bounds().x()); - EXPECT_EQ(window3->GetRootWindow()->bounds().right(), - window3->bounds().right()); - - // Being a single window will retore the original location. - window2->Hide(); - EXPECT_EQ("120,120 100x100", window3->bounds().ToString()); -} - -// Test that user placed windows go back to their user placement after the user -// closes all other windows. -TEST_F(WorkspaceControllerTest, TestUserHandledWindowRestore) { - scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); - gfx::Rect user_pos = gfx::Rect(16, 42, 640, 320); - window1->SetBounds(user_pos); - wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - - window1_state->SetPreAutoManageWindowBounds(user_pos); - gfx::Rect desktop_area = window1->parent()->bounds(); - - // Create a second window to let the auto manager kick in. - scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); - window2->SetBounds(gfx::Rect(32, 48, 256, 512)); - window1->Hide(); - window2->Hide(); - wm::GetWindowState(window1.get())->set_window_position_managed(true); - wm::GetWindowState(window2.get())->set_window_position_managed(true); - window1->Show(); - EXPECT_EQ(user_pos.ToString(), window1->bounds().ToString()); - window2->Show(); - - // |window1| should be flush left and |window2| flush right. - EXPECT_EQ("0," + base::IntToString(user_pos.y()) + - " 640x320", window1->bounds().ToString()); - EXPECT_EQ( - base::IntToString(desktop_area.width() - window2->bounds().width()) + - ",48 256x512", window2->bounds().ToString()); - window2->Hide(); - - // After the other window get hidden the window has to move back to the - // previous position and the bounds should still be set and unchanged. - EXPECT_EQ(user_pos.ToString(), window1->bounds().ToString()); - ASSERT_TRUE(window1_state->pre_auto_manage_window_bounds()); - EXPECT_EQ(user_pos.ToString(), - window1_state->pre_auto_manage_window_bounds()->ToString()); -} - -// Test that a window from normal to minimize will repos the remaining. -TEST_F(WorkspaceControllerTest, ToMinimizeRepositionsRemaining) { - scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); - wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - window1_state->set_window_position_managed(true); - window1->SetBounds(gfx::Rect(16, 32, 640, 320)); - gfx::Rect desktop_area = window1->parent()->bounds(); - - scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); - wm::WindowState* window2_state = wm::GetWindowState(window2.get()); - window2_state->set_window_position_managed(true); - window2->SetBounds(gfx::Rect(32, 48, 256, 512)); - - window1_state->Minimize(); - - // |window2| should be centered now. - EXPECT_TRUE(window2->IsVisible()); - EXPECT_TRUE(window2_state->IsNormalShowState()); - EXPECT_EQ(base::IntToString( - (desktop_area.width() - window2->bounds().width()) / 2) + - ",48 256x512", window2->bounds().ToString()); - - window1_state->Restore(); - // |window1| should be flush right and |window3| flush left. - EXPECT_EQ(base::IntToString( - desktop_area.width() - window1->bounds().width()) + - ",32 640x320", window1->bounds().ToString()); - EXPECT_EQ("0,48 256x512", window2->bounds().ToString()); -} - -// Test that minimizing an initially maximized window will repos the remaining. -TEST_F(WorkspaceControllerTest, MaxToMinRepositionsRemaining) { - scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); - wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - window1_state->set_window_position_managed(true); - gfx::Rect desktop_area = window1->parent()->bounds(); - - scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); - wm::WindowState* window2_state = wm::GetWindowState(window2.get()); - window2_state->set_window_position_managed(true); - window2->SetBounds(gfx::Rect(32, 48, 256, 512)); - - window1_state->Maximize(); - window1_state->Minimize(); - - // |window2| should be centered now. - EXPECT_TRUE(window2->IsVisible()); - EXPECT_TRUE(window2_state->IsNormalShowState()); - EXPECT_EQ(base::IntToString( - (desktop_area.width() - window2->bounds().width()) / 2) + - ",48 256x512", window2->bounds().ToString()); -} - -// Test that nomral, maximize, minimizing will repos the remaining. -TEST_F(WorkspaceControllerTest, NormToMaxToMinRepositionsRemaining) { - scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); - window1->SetBounds(gfx::Rect(16, 32, 640, 320)); - wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - window1_state->set_window_position_managed(true); - gfx::Rect desktop_area = window1->parent()->bounds(); - - scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); - wm::WindowState* window2_state = wm::GetWindowState(window2.get()); - window2_state->set_window_position_managed(true); - window2->SetBounds(gfx::Rect(32, 40, 256, 512)); - - // Trigger the auto window placement function by showing (and hiding) it. - window1->Hide(); - window1->Show(); - - // |window1| should be flush right and |window3| flush left. - EXPECT_EQ(base::IntToString( - desktop_area.width() - window1->bounds().width()) + - ",32 640x320", window1->bounds().ToString()); - EXPECT_EQ("0,40 256x512", window2->bounds().ToString()); - - window1_state->Maximize(); - window1_state->Minimize(); - - // |window2| should be centered now. - EXPECT_TRUE(window2->IsVisible()); - EXPECT_TRUE(window2_state->IsNormalShowState()); - EXPECT_EQ(base::IntToString( - (desktop_area.width() - window2->bounds().width()) / 2) + - ",40 256x512", window2->bounds().ToString()); -} - -// Test that nomral, maximize, normal will repos the remaining. -TEST_F(WorkspaceControllerTest, NormToMaxToNormRepositionsRemaining) { - scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); - window1->SetBounds(gfx::Rect(16, 32, 640, 320)); - wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - window1_state->set_window_position_managed(true); - gfx::Rect desktop_area = window1->parent()->bounds(); - - scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); - wm::GetWindowState(window2.get())->set_window_position_managed(true); - window2->SetBounds(gfx::Rect(32, 40, 256, 512)); - - // Trigger the auto window placement function by showing (and hiding) it. - window1->Hide(); - window1->Show(); - - // |window1| should be flush right and |window3| flush left. - EXPECT_EQ(base::IntToString( - desktop_area.width() - window1->bounds().width()) + - ",32 640x320", window1->bounds().ToString()); - EXPECT_EQ("0,40 256x512", window2->bounds().ToString()); - - window1_state->Maximize(); - window1_state->Restore(); - - // |window1| should be flush right and |window2| flush left. - EXPECT_EQ(base::IntToString( - desktop_area.width() - window1->bounds().width()) + - ",32 640x320", window1->bounds().ToString()); - EXPECT_EQ("0,40 256x512", window2->bounds().ToString()); -} - -// Test that animations are triggered. -TEST_F(WorkspaceControllerTest, AnimatedNormToMaxToNormRepositionsRemaining) { - ui::ScopedAnimationDurationScaleMode normal_duration_mode( - ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); - scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); - window1->Hide(); - window1->SetBounds(gfx::Rect(16, 32, 640, 320)); - gfx::Rect desktop_area = window1->parent()->bounds(); - scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); - window2->Hide(); - window2->SetBounds(gfx::Rect(32, 48, 256, 512)); - - wm::GetWindowState(window1.get())->set_window_position_managed(true); - wm::GetWindowState(window2.get())->set_window_position_managed(true); - // Make sure nothing is animating. - window1->layer()->GetAnimator()->StopAnimating(); - window2->layer()->GetAnimator()->StopAnimating(); - window2->Show(); - - // The second window should now animate. - EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating()); - EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating()); - window2->layer()->GetAnimator()->StopAnimating(); - - window1->Show(); - EXPECT_TRUE(window1->layer()->GetAnimator()->is_animating()); - EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating()); - - window1->layer()->GetAnimator()->StopAnimating(); - window2->layer()->GetAnimator()->StopAnimating(); - // |window1| should be flush right and |window2| flush left. - EXPECT_EQ(base::IntToString( - desktop_area.width() - window1->bounds().width()) + - ",32 640x320", window1->bounds().ToString()); - EXPECT_EQ("0,48 256x512", window2->bounds().ToString()); -} - -// This tests simulates a browser and an app and verifies the ordering of the -// windows and layers doesn't get out of sync as various operations occur. Its -// really testing code in FocusController, but easier to simulate here. Just as -// with a real browser the browser here has a transient child window -// (corresponds to the status bubble). -TEST_F(WorkspaceControllerTest, VerifyLayerOrdering) { - scoped_ptr<Window> browser( - aura::test::CreateTestWindowWithDelegate( - NULL, - aura::client::WINDOW_TYPE_NORMAL, - gfx::Rect(5, 6, 7, 8), - NULL)); - browser->SetName("browser"); - ParentWindowInPrimaryRootWindow(browser.get()); - browser->Show(); - wm::ActivateWindow(browser.get()); - - // |status_bubble| is made a transient child of |browser| and as a result - // owned by |browser|. - aura::test::TestWindowDelegate* status_bubble_delegate = - aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(); - status_bubble_delegate->set_can_focus(false); - Window* status_bubble = - aura::test::CreateTestWindowWithDelegate( - status_bubble_delegate, - aura::client::WINDOW_TYPE_POPUP, - gfx::Rect(5, 6, 7, 8), - NULL); - browser->AddTransientChild(status_bubble); - ParentWindowInPrimaryRootWindow(status_bubble); - status_bubble->SetName("status_bubble"); - - scoped_ptr<Window> app( - aura::test::CreateTestWindowWithDelegate( - NULL, - aura::client::WINDOW_TYPE_NORMAL, - gfx::Rect(5, 6, 7, 8), - NULL)); - app->SetName("app"); - ParentWindowInPrimaryRootWindow(app.get()); - - aura::Window* parent = browser->parent(); - - app->Show(); - wm::ActivateWindow(app.get()); - EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent)); - - // Minimize the app, focus should go the browser. - app->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - EXPECT_TRUE(wm::IsActiveWindow(browser.get())); - EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent)); - - // Minimize the browser (neither windows are focused). - browser->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); - EXPECT_FALSE(wm::IsActiveWindow(browser.get())); - EXPECT_FALSE(wm::IsActiveWindow(app.get())); - EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent)); - - // Show the browser (which should restore it). - browser->Show(); - EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent)); - - // Activate the browser. - ash::wm::ActivateWindow(browser.get()); - EXPECT_TRUE(wm::IsActiveWindow(browser.get())); - EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent)); - - // Restore the app. This differs from above code for |browser| as internally - // the app code does this. Restoring this way or using Show() should not make - // a difference. - app->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent)); - - // Activate the app. - ash::wm::ActivateWindow(app.get()); - EXPECT_TRUE(wm::IsActiveWindow(app.get())); - EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent)); -} - -namespace { - -// Used by DragMaximizedNonTrackedWindow to track how many times the window -// hierarchy changes affecting the specified window. -class DragMaximizedNonTrackedWindowObserver - : public aura::WindowObserver { - public: - DragMaximizedNonTrackedWindowObserver(aura::Window* window) - : change_count_(0), - window_(window) { - } - - // Number of times OnWindowHierarchyChanged() has been received. - void clear_change_count() { change_count_ = 0; } - int change_count() const { - return change_count_; - } - - // 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.target != window_ || - (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_++; - } - - private: - int change_count_; - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(DragMaximizedNonTrackedWindowObserver); -}; - -} // namespace - -// Verifies that a new maximized window becomes visible after its activation -// is requested, even though it does not become activated because a system -// modal window is active. -TEST_F(WorkspaceControllerTest, SwitchFromModal) { - scoped_ptr<Window> modal_window(CreateTestWindowUnparented()); - modal_window->SetBounds(gfx::Rect(10, 11, 21, 22)); - modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM); - ParentWindowInPrimaryRootWindow(modal_window.get()); - modal_window->Show(); - wm::ActivateWindow(modal_window.get()); - - scoped_ptr<Window> maximized_window(CreateTestWindow()); - maximized_window->SetProperty( - aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); - maximized_window->Show(); - wm::ActivateWindow(maximized_window.get()); - EXPECT_TRUE(maximized_window->IsVisible()); -} - -namespace { - -// Subclass of WorkspaceControllerTest that runs tests with docked windows -// enabled and disabled. -class WorkspaceControllerTestDragging - : public WorkspaceControllerTest, - public testing::WithParamInterface<bool> { - public: - WorkspaceControllerTestDragging() {} - virtual ~WorkspaceControllerTestDragging() {} - - // testing::Test: - virtual void SetUp() OVERRIDE { - WorkspaceControllerTest::SetUp(); - if (docked_windows_enabled()) { - CommandLine::ForCurrentProcess()->AppendSwitch( - ash::switches::kAshEnableDockedWindows); - } - } - - bool docked_windows_enabled() const { return GetParam(); } - - private: - DISALLOW_COPY_AND_ASSIGN(WorkspaceControllerTestDragging); -}; - -} // namespace - -// Verifies that when dragging a window over the shelf overlap is detected -// during and after the drag. -TEST_P(WorkspaceControllerTestDragging, DragWindowOverlapShelf) { - aura::test::TestWindowDelegate delegate; - delegate.set_window_component(HTCAPTION); - scoped_ptr<Window> w1( - aura::test::CreateTestWindowWithDelegate(&delegate, - aura::client::WINDOW_TYPE_NORMAL, - gfx::Rect(5, 5, 100, 50), - NULL)); - ParentWindowInPrimaryRootWindow(w1.get()); - - ShelfLayoutManager* shelf = shelf_layout_manager(); - shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); - - // Drag near the shelf - aura::test::EventGenerator generator( - Shell::GetPrimaryRootWindow(), gfx::Point()); - generator.MoveMouseTo(10, 10); - generator.PressLeftButton(); - generator.MoveMouseTo(100, shelf->GetIdealBounds().y() - 70); - - // Shelf should not be in overlapped state. - EXPECT_FALSE(GetWindowOverlapsShelf()); - - generator.MoveMouseTo(100, shelf->GetIdealBounds().y() - 20); - - // Shelf should detect overlap. Overlap state stays after mouse is released. - EXPECT_TRUE(GetWindowOverlapsShelf()); - generator.ReleaseLeftButton(); - EXPECT_TRUE(GetWindowOverlapsShelf()); -} - -INSTANTIATE_TEST_CASE_P(DockedOrNot, WorkspaceControllerTestDragging, - ::testing::Bool()); - -} // namespace internal -} // namespace ash |