Commit a276ec54 authored by skuhne@chromium.org's avatar skuhne@chromium.org

Avoiding double resize of maximized windows upon user switch due to showing and hiding of the shelf

BUG=385992
TEST=MultiUserWindowManagerChromeOSTest.TestBlackBarCover & visual inspection

Review URL: https://codereview.chromium.org/448493002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287880 0039d316-1c4b-4281-b951-d872f2087c98
parent a375ec49
...@@ -325,6 +325,7 @@ class ShelfWidget::DelegateView : public views::WidgetDelegate, ...@@ -325,6 +325,7 @@ class ShelfWidget::DelegateView : public views::WidgetDelegate,
FocusCycler* focus_cycler() { return focus_cycler_; } FocusCycler* focus_cycler() { return focus_cycler_; }
ui::Layer* opaque_background() { return &opaque_background_; } ui::Layer* opaque_background() { return &opaque_background_; }
ui::Layer* opaque_foreground() { return &opaque_foreground_; }
// Set if the shelf area is dimmed (eg when a window is maximized). // Set if the shelf area is dimmed (eg when a window is maximized).
void SetDimmed(bool dimmed); void SetDimmed(bool dimmed);
...@@ -383,7 +384,12 @@ class ShelfWidget::DelegateView : public views::WidgetDelegate, ...@@ -383,7 +384,12 @@ class ShelfWidget::DelegateView : public views::WidgetDelegate,
scoped_ptr<views::Widget> dimmer_; scoped_ptr<views::Widget> dimmer_;
FocusCycler* focus_cycler_; FocusCycler* focus_cycler_;
int alpha_; int alpha_;
// A black background layer which is shown when a maximized window is visible.
ui::Layer opaque_background_; ui::Layer opaque_background_;
// A black foreground layer which is shown while transitioning between users.
// Note: Since the back- and foreground layers have different functions they
// can be used simultaneously - so no repurposing possible.
ui::Layer opaque_foreground_;
// The view which does the dimming. // The view which does the dimming.
DimmerView* dimmer_view_; DimmerView* dimmer_view_;
...@@ -399,12 +405,16 @@ ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf) ...@@ -399,12 +405,16 @@ ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf)
focus_cycler_(NULL), focus_cycler_(NULL),
alpha_(0), alpha_(0),
opaque_background_(ui::LAYER_SOLID_COLOR), opaque_background_(ui::LAYER_SOLID_COLOR),
opaque_foreground_(ui::LAYER_SOLID_COLOR),
dimmer_view_(NULL), dimmer_view_(NULL),
disable_dimming_animations_for_test_(false) { disable_dimming_animations_for_test_(false) {
set_allow_deactivate_on_esc(true); set_allow_deactivate_on_esc(true);
opaque_background_.SetColor(SK_ColorBLACK); opaque_background_.SetColor(SK_ColorBLACK);
opaque_background_.SetBounds(GetLocalBounds()); opaque_background_.SetBounds(GetLocalBounds());
opaque_background_.SetOpacity(0.0f); opaque_background_.SetOpacity(0.0f);
opaque_foreground_.SetColor(SK_ColorBLACK);
opaque_foreground_.SetBounds(GetLocalBounds());
opaque_foreground_.SetOpacity(0.0f);
} }
ShelfWidget::DelegateView::~DelegateView() { ShelfWidget::DelegateView::~DelegateView() {
...@@ -450,6 +460,7 @@ bool ShelfWidget::DelegateView::GetDimmed() const { ...@@ -450,6 +460,7 @@ bool ShelfWidget::DelegateView::GetDimmed() const {
void ShelfWidget::DelegateView::SetParentLayer(ui::Layer* layer) { void ShelfWidget::DelegateView::SetParentLayer(ui::Layer* layer) {
layer->Add(&opaque_background_); layer->Add(&opaque_background_);
layer->Add(&opaque_foreground_);
ReorderLayers(); ReorderLayers();
} }
...@@ -556,10 +567,12 @@ void ShelfWidget::DelegateView::Layout() { ...@@ -556,10 +567,12 @@ void ShelfWidget::DelegateView::Layout() {
void ShelfWidget::DelegateView::ReorderChildLayers(ui::Layer* parent_layer) { void ShelfWidget::DelegateView::ReorderChildLayers(ui::Layer* parent_layer) {
views::View::ReorderChildLayers(parent_layer); views::View::ReorderChildLayers(parent_layer);
parent_layer->StackAtBottom(&opaque_background_); parent_layer->StackAtBottom(&opaque_background_);
parent_layer->StackAtTop(&opaque_foreground_);
} }
void ShelfWidget::DelegateView::OnBoundsChanged(const gfx::Rect& old_bounds) { void ShelfWidget::DelegateView::OnBoundsChanged(const gfx::Rect& old_bounds) {
opaque_background_.SetBounds(GetLocalBounds()); opaque_background_.SetBounds(GetLocalBounds());
opaque_foreground_.SetBounds(GetLocalBounds());
if (dimmer_) if (dimmer_)
dimmer_->SetBounds(GetBoundsInScreen()); dimmer_->SetBounds(GetBoundsInScreen());
} }
...@@ -678,6 +691,27 @@ ShelfBackgroundType ShelfWidget::GetBackgroundType() const { ...@@ -678,6 +691,27 @@ ShelfBackgroundType ShelfWidget::GetBackgroundType() const {
return SHELF_BACKGROUND_DEFAULT; return SHELF_BACKGROUND_DEFAULT;
} }
void ShelfWidget::HideShelfBehindBlackBar(bool hide, int animation_time_ms) {
if (IsShelfHiddenBehindBlackBar() == hide)
return;
ui::Layer* opaque_foreground = delegate_view_->opaque_foreground();
float target_opacity = hide ? 1.0f : 0.0f;
scoped_ptr<ui::ScopedLayerAnimationSettings> opaque_foreground_animation;
opaque_foreground_animation.reset(new ui::ScopedLayerAnimationSettings(
opaque_foreground->GetAnimator()));
opaque_foreground_animation->SetTransitionDuration(
base::TimeDelta::FromMilliseconds(animation_time_ms));
opaque_foreground_animation->SetPreemptionStrategy(
ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
opaque_foreground->SetOpacity(target_opacity);
}
bool ShelfWidget::IsShelfHiddenBehindBlackBar() const {
return delegate_view_->opaque_foreground()->GetTargetOpacity() != 0.0f;
}
// static // static
bool ShelfWidget::ShelfAlignmentAllowed() { bool ShelfWidget::ShelfAlignmentAllowed() {
user::LoginStatus login_status = user::LoginStatus login_status =
......
...@@ -45,6 +45,11 @@ class ASH_EXPORT ShelfWidget : public views::Widget, ...@@ -45,6 +45,11 @@ class ASH_EXPORT ShelfWidget : public views::Widget,
BackgroundAnimatorChangeType change_type); BackgroundAnimatorChangeType change_type);
ShelfBackgroundType GetBackgroundType() const; ShelfBackgroundType GetBackgroundType() const;
// Hide the shelf behind a black bar during e.g. a user transition when |hide|
// is true. The |animation_time_ms| will be used as animation duration.
void HideShelfBehindBlackBar(bool hide, int animation_time_ms);
bool IsShelfHiddenBehindBlackBar() const;
// Causes shelf items to be slightly dimmed (e.g. when a window is maximized). // Causes shelf items to be slightly dimmed (e.g. when a window is maximized).
void SetDimsShelf(bool dimming); void SetDimsShelf(bool dimming);
bool GetDimsShelf() const; bool GetDimsShelf() const;
......
...@@ -197,6 +197,48 @@ std::string GetPrefForRootWindow(PrefService* pref_service, ...@@ -197,6 +197,48 @@ std::string GetPrefForRootWindow(PrefService* pref_service,
return default_string; return default_string;
} }
// Gets the shelf auto hide behavior from prefs for a root window.
ash::ShelfAutoHideBehavior GetShelfAutoHideBehaviorFromPrefs(
Profile* profile,
aura::Window* root_window) {
// Don't show the shelf in app mode.
if (chrome::IsRunningInAppMode())
return ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN;
// See comment in |kShelfAlignment| as to why we consider two prefs.
const std::string behavior_value(
GetPrefForRootWindow(profile->GetPrefs(),
root_window,
prefs::kShelfAutoHideBehaviorLocal,
prefs::kShelfAutoHideBehavior));
// Note: To maintain sync compatibility with old images of chrome/chromeos
// the set of values that may be encountered includes the now-extinct
// "Default" as well as "Never" and "Always", "Default" should now
// be treated as "Never" (http://crbug.com/146773).
if (behavior_value == ash::kShelfAutoHideBehaviorAlways)
return ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
return ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER;
}
// Gets the shelf alignment from prefs for a root window.
ash::ShelfAlignment GetShelfAlignmentFromPrefs(Profile* profile,
aura::Window* root_window) {
// See comment in |kShelfAlignment| as to why we consider two prefs.
const std::string alignment_value(
GetPrefForRootWindow(profile->GetPrefs(),
root_window,
prefs::kShelfAlignmentLocal,
prefs::kShelfAlignment));
if (alignment_value == ash::kShelfAlignmentLeft)
return ash::SHELF_ALIGNMENT_LEFT;
else if (alignment_value == ash::kShelfAlignmentRight)
return ash::SHELF_ALIGNMENT_RIGHT;
else if (alignment_value == ash::kShelfAlignmentTop)
return ash::SHELF_ALIGNMENT_TOP;
return ash::SHELF_ALIGNMENT_BOTTOM;
}
// If prefs have synced and no user-set value exists at |local_path|, the value // If prefs have synced and no user-set value exists at |local_path|, the value
// from |synced_path| is copied to |local_path|. // from |synced_path| is copied to |local_path|.
void MaybePropagatePrefToLocal(PrefServiceSyncable* pref_service, void MaybePropagatePrefToLocal(PrefServiceSyncable* pref_service,
...@@ -920,24 +962,7 @@ Profile* ChromeLauncherController::profile() { ...@@ -920,24 +962,7 @@ Profile* ChromeLauncherController::profile() {
ash::ShelfAutoHideBehavior ChromeLauncherController::GetShelfAutoHideBehavior( ash::ShelfAutoHideBehavior ChromeLauncherController::GetShelfAutoHideBehavior(
aura::Window* root_window) const { aura::Window* root_window) const {
// Don't show the shelf in app mode. return GetShelfAutoHideBehaviorFromPrefs(profile_, root_window);
if (chrome::IsRunningInAppMode())
return ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN;
// See comment in |kShelfAlignment| as to why we consider two prefs.
const std::string behavior_value(
GetPrefForRootWindow(profile_->GetPrefs(),
root_window,
prefs::kShelfAutoHideBehaviorLocal,
prefs::kShelfAutoHideBehavior));
// Note: To maintain sync compatibility with old images of chrome/chromeos
// the set of values that may be encountered includes the now-extinct
// "Default" as well as "Never" and "Always", "Default" should now
// be treated as "Never" (http://crbug.com/146773).
if (behavior_value == ash::kShelfAutoHideBehaviorAlways)
return ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
return ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER;
} }
bool ChromeLauncherController::CanUserModifyShelfAutoHideBehavior( bool ChromeLauncherController::CanUserModifyShelfAutoHideBehavior(
...@@ -1438,6 +1463,25 @@ bool ChromeLauncherController::IsBrowserFromActiveUser(Browser* browser) { ...@@ -1438,6 +1463,25 @@ bool ChromeLauncherController::IsBrowserFromActiveUser(Browser* browser) {
return multi_user_util::IsProfileFromActiveUser(browser->profile()); return multi_user_util::IsProfileFromActiveUser(browser->profile());
} }
bool ChromeLauncherController::ShelfBoundsChangesProbablyWithUser(
aura::Window* root_window,
const std::string& user_id) const {
Profile* other_profile = multi_user_util::GetProfileFromUserID(user_id);
DCHECK_NE(other_profile, profile_);
// Note: The Auto hide state from preferences is not the same as the actual
// visibility of the shelf. Depending on all the various states (full screen,
// no window on desktop, multi user, ..) the shelf could be shown - or not.
bool currently_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER ==
GetShelfAutoHideBehaviorFromPrefs(profile_, root_window);
bool other_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER ==
GetShelfAutoHideBehaviorFromPrefs(other_profile, root_window);
return currently_shown != other_shown ||
GetShelfAlignmentFromPrefs(profile_, root_window) !=
GetShelfAlignmentFromPrefs(other_profile, root_window);
}
void ChromeLauncherController::LauncherItemClosed(ash::ShelfID id) { void ChromeLauncherController::LauncherItemClosed(ash::ShelfID id) {
IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
CHECK(iter != id_to_item_controller_map_.end()); CHECK(iter != id_to_item_controller_map_.end());
...@@ -1696,20 +1740,8 @@ void ChromeLauncherController::SetShelfAlignmentFromPrefs() { ...@@ -1696,20 +1740,8 @@ void ChromeLauncherController::SetShelfAlignmentFromPrefs() {
for (aura::Window::Windows::const_iterator iter = root_windows.begin(); for (aura::Window::Windows::const_iterator iter = root_windows.begin();
iter != root_windows.end(); ++iter) { iter != root_windows.end(); ++iter) {
// See comment in |kShelfAlignment| as to why we consider two prefs. ash::Shell::GetInstance()->SetShelfAlignment(
const std::string alignment_value( GetShelfAlignmentFromPrefs(profile_, *iter), *iter);
GetPrefForRootWindow(profile_->GetPrefs(),
*iter,
prefs::kShelfAlignmentLocal,
prefs::kShelfAlignment));
ash::ShelfAlignment alignment = ash::SHELF_ALIGNMENT_BOTTOM;
if (alignment_value == ash::kShelfAlignmentLeft)
alignment = ash::SHELF_ALIGNMENT_LEFT;
else if (alignment_value == ash::kShelfAlignmentRight)
alignment = ash::SHELF_ALIGNMENT_RIGHT;
else if (alignment_value == ash::kShelfAlignmentTop)
alignment = ash::SHELF_ALIGNMENT_TOP;
ash::Shell::GetInstance()->SetShelfAlignment(alignment, *iter);
} }
} }
......
...@@ -384,6 +384,13 @@ class ChromeLauncherController : public ash::ShelfDelegate, ...@@ -384,6 +384,13 @@ class ChromeLauncherController : public ash::ShelfDelegate,
// Returns true if |browser| is owned by the active user. // Returns true if |browser| is owned by the active user.
bool IsBrowserFromActiveUser(Browser* browser); bool IsBrowserFromActiveUser(Browser* browser);
// Check if the shelf visibility (location, visibility) will change with a new
// user profile or not. However, since the full visibility calculation of the
// shelf cannot be performed here, this is only a probability used for
// animation predictions.
bool ShelfBoundsChangesProbablyWithUser(aura::Window* root_window,
const std::string& user_id) const;
// Access to the BrowserStatusMonitor for tests. // Access to the BrowserStatusMonitor for tests.
BrowserStatusMonitor* browser_status_monitor_for_test() { BrowserStatusMonitor* browser_status_monitor_for_test() {
return browser_status_monitor_.get(); return browser_status_monitor_.get();
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/shell_window_ids.h" #include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h" #include "ash/test/ash_test_base.h"
...@@ -768,6 +770,9 @@ TEST_F(MultiUserWindowManagerChromeOSTest, AnimationSteps) { ...@@ -768,6 +770,9 @@ TEST_F(MultiUserWindowManagerChromeOSTest, AnimationSteps) {
ash::Shell::GetInstance()->GetShelfAutoHideBehavior( ash::Shell::GetInstance()->GetShelfAutoHideBehavior(
window(0)->GetRootWindow())); window(0)->GetRootWindow()));
EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity()); EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity());
ash::ShelfWidget* shelf = ash::RootWindowController::ForWindow(
window(0))->shelf();
EXPECT_FALSE(shelf->IsShelfHiddenBehindBlackBar());
// Start the animation and see that the old window is becoming invisible, the // Start the animation and see that the old window is becoming invisible, the
// new one visible, the background starts transitionining and the shelf hides. // new one visible, the background starts transitionining and the shelf hides.
...@@ -779,6 +784,7 @@ TEST_F(MultiUserWindowManagerChromeOSTest, AnimationSteps) { ...@@ -779,6 +784,7 @@ TEST_F(MultiUserWindowManagerChromeOSTest, AnimationSteps) {
EXPECT_EQ(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN, EXPECT_EQ(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN,
ash::Shell::GetInstance()->GetShelfAutoHideBehavior( ash::Shell::GetInstance()->GetShelfAutoHideBehavior(
window(0)->GetRootWindow())); window(0)->GetRootWindow()));
EXPECT_FALSE(shelf->IsShelfHiddenBehindBlackBar());
// Staring the next step should show the shelf again, but there are many // Staring the next step should show the shelf again, but there are many
// subsystems missing (preferences system, ChromeLauncherController, ...) // subsystems missing (preferences system, ChromeLauncherController, ...)
...@@ -790,9 +796,11 @@ TEST_F(MultiUserWindowManagerChromeOSTest, AnimationSteps) { ...@@ -790,9 +796,11 @@ TEST_F(MultiUserWindowManagerChromeOSTest, AnimationSteps) {
EXPECT_EQ(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN, EXPECT_EQ(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN,
ash::Shell::GetInstance()->GetShelfAutoHideBehavior( ash::Shell::GetInstance()->GetShelfAutoHideBehavior(
window(0)->GetRootWindow())); window(0)->GetRootWindow()));
EXPECT_FALSE(shelf->IsShelfHiddenBehindBlackBar());
// After the finalize the animation of the wallpaper should be finished. // After the finalize the animation of the wallpaper should be finished.
AdvanceUserTransitionAnimation(); AdvanceUserTransitionAnimation();
EXPECT_FALSE(shelf->IsShelfHiddenBehindBlackBar());
EXPECT_EQ("B", GetWallaperUserIdForTest()); EXPECT_EQ("B", GetWallaperUserIdForTest());
} }
...@@ -990,5 +998,86 @@ TEST_F(MultiUserWindowManagerChromeOSTest, ShowForUserSwitchesDesktop) { ...@@ -990,5 +998,86 @@ TEST_F(MultiUserWindowManagerChromeOSTest, ShowForUserSwitchesDesktop) {
EXPECT_EQ("H[a,b], H[b], S[c]", GetStatus()); EXPECT_EQ("H[a,b], H[b], S[c]", GetStatus());
} }
class TestWindowObserver : public aura::WindowObserver {
public:
TestWindowObserver(): resize_calls_(0) {}
virtual ~TestWindowObserver() {};
virtual void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) OVERRIDE {
resize_calls_++;
}
int resize_calls() { return resize_calls_; }
private:
int resize_calls_;
DISALLOW_COPY_AND_ASSIGN(TestWindowObserver);
};
// Test that switching between users with the shelf in the same place, the shelf
// will get covered with a black bar instead being hidden and re-shown.
TEST_F(MultiUserWindowManagerChromeOSTest, TestBlackBarCover) {
SetUpForThisManyWindows(2);
multi_user_window_manager()->SetWindowOwner(window(0), "A");
multi_user_window_manager()->SetWindowOwner(window(1), "B");
aura::Window* root_window = ash::Shell::GetInstance()->GetPrimaryRootWindow();
// Turn the use of delays and animation on.
multi_user_window_manager()->SetAnimationSpeedForTest(
chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST);
EXPECT_NE(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN,
ash::Shell::GetInstance()->GetShelfAutoHideBehavior(root_window));
ash::ShelfWidget* shelf = ash::RootWindowController::ForWindow(
root_window)->shelf();
EXPECT_FALSE(shelf->IsShelfHiddenBehindBlackBar());
// First test that with no maximized window we show/hide the shelf.
StartUserTransitionAnimation("B");
EXPECT_FALSE(shelf->IsShelfHiddenBehindBlackBar());
EXPECT_EQ(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN,
ash::Shell::GetInstance()->GetShelfAutoHideBehavior(root_window));
// Staring the next step should show the shelf again.
AdvanceUserTransitionAnimation();
EXPECT_FALSE(shelf->IsShelfHiddenBehindBlackBar());
AdvanceUserTransitionAnimation();
EXPECT_FALSE(shelf->IsShelfHiddenBehindBlackBar());
ash::Shell::GetInstance()->SetShelfAutoHideBehavior(
ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER, root_window);
// Now we maximize the windows which will cause the black overlay to show up.
wm::GetWindowState(window(0))->Maximize();
wm::GetWindowState(window(1))->Maximize();
// We set a window observer on both windows to see that no resize is performed
// on our test windows.
TestWindowObserver window_observer;
window(0)->AddObserver(&window_observer);
window(1)->AddObserver(&window_observer);
// Start the animation and see that the shelf gets hidden by the black bar,
// and the AutoHide behavior remains as it was.
StartUserTransitionAnimation("A");
EXPECT_TRUE(shelf->IsShelfHiddenBehindBlackBar());
EXPECT_NE(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN,
ash::Shell::GetInstance()->GetShelfAutoHideBehavior(root_window));
// Staring the next step should show the shelf again.
AdvanceUserTransitionAnimation();
EXPECT_FALSE(shelf->IsShelfHiddenBehindBlackBar());
EXPECT_NE(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN,
ash::Shell::GetInstance()->GetShelfAutoHideBehavior(root_window));
AdvanceUserTransitionAnimation();
EXPECT_FALSE(shelf->IsShelfHiddenBehindBlackBar());
window(0)->RemoveObserver(&window_observer);
window(1)->RemoveObserver(&window_observer);
// No resize should have been done to the window.
EXPECT_EQ(0, window_observer.resize_calls());
}
} // namespace test } // namespace test
} // namespace ash } // namespace ash
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "ash/desktop_background/user_wallpaper_delegate.h" #include "ash/desktop_background/user_wallpaper_delegate.h"
#include "ash/root_window_controller.h" #include "ash/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/wm/mru_window_tracker.h" #include "ash/wm/mru_window_tracker.h"
#include "ash/wm/window_positioner.h" #include "ash/wm/window_positioner.h"
...@@ -53,7 +54,7 @@ UserSwichAnimatorChromeOS::UserSwichAnimatorChromeOS( ...@@ -53,7 +54,7 @@ UserSwichAnimatorChromeOS::UserSwichAnimatorChromeOS(
new_user_id_(new_user_id), new_user_id_(new_user_id),
animation_speed_ms_(animation_speed_ms), animation_speed_ms_(animation_speed_ms),
animation_step_(ANIMATION_STEP_HIDE_OLD_USER), animation_step_(ANIMATION_STEP_HIDE_OLD_USER),
screen_cover_(GetScreenCover()) { screen_cover_(GetScreenCover(NULL)) {
AdvanceUserTransitionAnimation(); AdvanceUserTransitionAnimation();
if (!animation_speed_ms_) { if (!animation_speed_ms_) {
...@@ -156,21 +157,33 @@ void UserSwichAnimatorChromeOS::TransitionWallpaper( ...@@ -156,21 +157,33 @@ void UserSwichAnimatorChromeOS::TransitionWallpaper(
void UserSwichAnimatorChromeOS::TransitionUserShelf( void UserSwichAnimatorChromeOS::TransitionUserShelf(
AnimationStep animation_step) { AnimationStep animation_step) {
ChromeLauncherController* chrome_launcher_controller =
ChromeLauncherController::instance();
// The shelf animation duration override. // The shelf animation duration override.
int duration_override = animation_speed_ms_; int duration_override = animation_speed_ms_;
// Handle the shelf order of items. This is done once the old user is hidden. // Handle the shelf order of items. This is done once the old user is hidden.
if (animation_step == ANIMATION_STEP_SHOW_NEW_USER) { if (animation_step == ANIMATION_STEP_SHOW_NEW_USER) {
// Some unit tests have no ChromeLauncherController. // Some unit tests have no ChromeLauncherController.
if (ChromeLauncherController::instance()) if (chrome_launcher_controller)
ChromeLauncherController::instance()->ActiveUserChanged(new_user_id_); chrome_launcher_controller->ActiveUserChanged(new_user_id_);
// We kicked off the shelf animation in the command above. As such we can // Hide the black rectangle on top of each shelf again.
// disable the override now again. aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
for (aura::Window::Windows::const_iterator iter = root_windows.begin();
iter != root_windows.end(); ++iter) {
ash::ShelfWidget* shelf =
ash::RootWindowController::ForWindow(*iter)->shelf();
shelf->HideShelfBehindBlackBar(false, duration_override);
}
// We kicked off the shelf animation above and the override can be
// removed.
duration_override = 0; duration_override = 0;
} }
if (!animation_speed_ms_ || animation_step == ANIMATION_STEP_FINALIZE) if (!animation_speed_ms_ || animation_step == ANIMATION_STEP_FINALIZE)
return; return;
// Note: The animation duration override will be set before the old user gets
// hidden and reset after the animations for the new user got kicked off.
ash::Shell::RootWindowControllerList controller = ash::Shell::RootWindowControllerList controller =
ash::Shell::GetInstance()->GetAllRootWindowControllers(); ash::Shell::GetInstance()->GetAllRootWindowControllers();
for (ash::Shell::RootWindowControllerList::iterator iter = controller.begin(); for (ash::Shell::RootWindowControllerList::iterator iter = controller.begin();
...@@ -179,11 +192,28 @@ void UserSwichAnimatorChromeOS::TransitionUserShelf( ...@@ -179,11 +192,28 @@ void UserSwichAnimatorChromeOS::TransitionUserShelf(
duration_override); duration_override);
} }
if (animation_step != ANIMATION_STEP_HIDE_OLD_USER)
return;
// For each root window hide the shelf. // For each root window hide the shelf.
if (animation_step == ANIMATION_STEP_HIDE_OLD_USER) {
aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows(); aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
for (aura::Window::Windows::const_iterator iter = root_windows.begin(); for (aura::Window::Windows::const_iterator iter = root_windows.begin();
iter != root_windows.end(); ++iter) { iter != root_windows.end(); ++iter) {
// Hiding the shelf will cause a resize on a maximized window.
// If the shelf is then shown for the following user in the same location,
// the window gets resized again. Since each resize can cause a considerable
// CPU usage and therefore effect jank, we should avoid hiding the shelf if
// the start and end location are the same and cover the shelf instead with
// a black rectangle on top.
if (GetScreenCover(*iter) != NO_USER_COVERS_SCREEN &&
(!chrome_launcher_controller ||
!chrome_launcher_controller->ShelfBoundsChangesProbablyWithUser(
*iter, new_user_id_))) {
ash::ShelfWidget* shelf =
ash::RootWindowController::ForWindow(*iter)->shelf();
shelf->HideShelfBehindBlackBar(true, duration_override);
} else {
// This shelf change is only part of the animation and will be updated by // This shelf change is only part of the animation and will be updated by
// ChromeLauncherController::ActiveUserChanged() to the new users value. // ChromeLauncherController::ActiveUserChanged() to the new users value.
// Note that the user preference will not be changed. // Note that the user preference will not be changed.
...@@ -300,13 +330,15 @@ void UserSwichAnimatorChromeOS::TransitionWindows( ...@@ -300,13 +330,15 @@ void UserSwichAnimatorChromeOS::TransitionWindows(
} }
UserSwichAnimatorChromeOS::TransitioningScreenCover UserSwichAnimatorChromeOS::TransitioningScreenCover
UserSwichAnimatorChromeOS::GetScreenCover() { UserSwichAnimatorChromeOS::GetScreenCover(aura::Window* root_window) {
TransitioningScreenCover cover = NO_USER_COVERS_SCREEN; TransitioningScreenCover cover = NO_USER_COVERS_SCREEN;
for (MultiUserWindowManagerChromeOS::WindowToEntryMap::const_iterator it_map = for (MultiUserWindowManagerChromeOS::WindowToEntryMap::const_iterator it_map =
owner_->window_to_entry().begin(); owner_->window_to_entry().begin();
it_map != owner_->window_to_entry().end(); it_map != owner_->window_to_entry().end();
++it_map) { ++it_map) {
aura::Window* window = it_map->first; aura::Window* window = it_map->first;
if (root_window && window->GetRootWindow() != root_window)
continue;
if (window->IsVisible() && CoversScreen(window)) { if (window->IsVisible() && CoversScreen(window)) {
if (cover == NEW_USER_COVERS_SCREEN) if (cover == NEW_USER_COVERS_SCREEN)
return BOTH_USERS_COVER_SCREEN; return BOTH_USERS_COVER_SCREEN;
......
...@@ -84,8 +84,9 @@ class UserSwichAnimatorChromeOS { ...@@ -84,8 +84,9 @@ class UserSwichAnimatorChromeOS {
void TransitionWindows(AnimationStep animation_step); void TransitionWindows(AnimationStep animation_step);
// Check if a window is maximized / fullscreen / covering the entire screen. // Check if a window is maximized / fullscreen / covering the entire screen.
// TODO(skuhne): We might want to do this on a per screen basis. // If a |root_window| is given, the screen coverage of that root_window is
TransitioningScreenCover GetScreenCover(); // tested, otherwise all screens.
TransitioningScreenCover GetScreenCover(aura::Window* root_window);
// The owning window manager. // The owning window manager.
MultiUserWindowManagerChromeOS* owner_; MultiUserWindowManagerChromeOS* owner_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment