Flash window by pulsing their launcher icon state indicator


BUG=119965
TEST=BrowserLauncherItemControllerTest.FlashWindow


Review URL: https://chromiumcodereview.appspot.com/10392173

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137993 0039d316-1c4b-4281-b951-d872f2087c98
parent 3e1dc20c
...@@ -73,10 +73,13 @@ class LauncherButton::BarView : public views::ImageView, ...@@ -73,10 +73,13 @@ class LauncherButton::BarView : public views::ImageView,
} }
void ShowAttention(bool show) { void ShowAttention(bool show) {
if (show) if (show) {
// It's less disruptive if we don't start the pulsing at 0.
animation_.Reset(0.375);
animation_.StartThrobbing(-1); animation_.StartThrobbing(-1);
else } else {
animation_.Reset(); animation_.Reset(0.0);
}
} }
private: private:
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "grit/ui_resources.h" #include "grit/ui_resources.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
...@@ -37,10 +38,12 @@ BrowserLauncherItemController::BrowserLauncherItemController( ...@@ -37,10 +38,12 @@ BrowserLauncherItemController::BrowserLauncherItemController(
is_incognito_(tab_model->profile()->GetOriginalProfile() != is_incognito_(tab_model->profile()->GetOriginalProfile() !=
tab_model->profile() && !Profile::IsGuestSession()), tab_model->profile() && !Profile::IsGuestSession()),
item_id_(-1) { item_id_(-1) {
window_->AddObserver(this);
} }
BrowserLauncherItemController::~BrowserLauncherItemController() { BrowserLauncherItemController::~BrowserLauncherItemController() {
tab_model_->RemoveObserver(this); tab_model_->RemoveObserver(this);
window_->RemoveObserver(this);
if (item_id_ != -1) if (item_id_ != -1)
launcher_controller_->LauncherItemClosed(item_id_); launcher_controller_->LauncherItemClosed(item_id_);
} }
...@@ -95,10 +98,7 @@ BrowserLauncherItemController* BrowserLauncherItemController::Create( ...@@ -95,10 +98,7 @@ BrowserLauncherItemController* BrowserLauncherItemController::Create(
} }
void BrowserLauncherItemController::BrowserActivationStateChanged() { void BrowserLauncherItemController::BrowserActivationStateChanged() {
launcher_controller_->SetItemStatus( UpdateItemStatus();
item_id_,
ash::wm::IsActiveWindow(window_) ?
ash::STATUS_ACTIVE : ash::STATUS_RUNNING);
} }
void BrowserLauncherItemController::ActiveTabChanged( void BrowserLauncherItemController::ActiveTabChanged(
...@@ -138,6 +138,29 @@ void BrowserLauncherItemController::FaviconUpdated() { ...@@ -138,6 +138,29 @@ void BrowserLauncherItemController::FaviconUpdated() {
UpdateLauncher(tab_model_->GetActiveTabContents()); UpdateLauncher(tab_model_->GetActiveTabContents());
} }
void BrowserLauncherItemController::OnWindowPropertyChanged(
aura::Window* window,
const void* key,
intptr_t old) {
if (key == aura::client::kDrawAttentionKey)
UpdateItemStatus();
}
void BrowserLauncherItemController::UpdateItemStatus() {
ash::LauncherItemStatus status;
if (ash::wm::IsActiveWindow(window_)) {
// Clear attention state if active.
if (window_->GetProperty(aura::client::kDrawAttentionKey))
window_->SetProperty(aura::client::kDrawAttentionKey, false);
status = ash::STATUS_ACTIVE;
} else if (window_->GetProperty(aura::client::kDrawAttentionKey)) {
status = ash::STATUS_ATTENTION;
} else {
status = ash::STATUS_RUNNING;
}
launcher_controller_->SetItemStatus(item_id_, status);
}
void BrowserLauncherItemController::UpdateLauncher(TabContentsWrapper* tab) { void BrowserLauncherItemController::UpdateLauncher(TabContentsWrapper* tab) {
if (type_ == TYPE_APP_PANEL) if (type_ == TYPE_APP_PANEL)
return; // Maintained entirely by ChromeLauncherController. return; // Maintained entirely by ChromeLauncherController.
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/string16.h" #include "base/string16.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "chrome/browser/ui/views/ash/launcher/launcher_favicon_loader.h" #include "chrome/browser/ui/views/ash/launcher/launcher_favicon_loader.h"
#include "ui/aura/window_observer.h"
class Browser; class Browser;
class ChromeLauncherController; class ChromeLauncherController;
...@@ -32,7 +33,8 @@ class Window; ...@@ -32,7 +33,8 @@ class Window;
// BrowserLauncherItemController is responsible for keeping the launcher // BrowserLauncherItemController is responsible for keeping the launcher
// representation of a window up to date as the active tab changes. // representation of a window up to date as the active tab changes.
class BrowserLauncherItemController : public TabStripModelObserver, class BrowserLauncherItemController : public TabStripModelObserver,
public LauncherFaviconLoader::Delegate { public LauncherFaviconLoader::Delegate,
public aura::WindowObserver {
public: public:
// This API is to be used as part of testing only. // This API is to be used as part of testing only.
class TestApi { class TestApi {
...@@ -96,6 +98,11 @@ class BrowserLauncherItemController : public TabStripModelObserver, ...@@ -96,6 +98,11 @@ class BrowserLauncherItemController : public TabStripModelObserver,
// LauncherFaviconLoader::Delegate overrides: // LauncherFaviconLoader::Delegate overrides:
virtual void FaviconUpdated() OVERRIDE; virtual void FaviconUpdated() OVERRIDE;
// aura::WindowObserver overrides:
virtual void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) OVERRIDE;
private: private:
FRIEND_TEST_ALL_PREFIXES(BrowserLauncherItemControllerTest, PanelItem); FRIEND_TEST_ALL_PREFIXES(BrowserLauncherItemControllerTest, PanelItem);
...@@ -106,6 +113,10 @@ class BrowserLauncherItemController : public TabStripModelObserver, ...@@ -106,6 +113,10 @@ class BrowserLauncherItemController : public TabStripModelObserver,
UPDATE_TAB_INSERTED, UPDATE_TAB_INSERTED,
}; };
// Updates the launcher item status base on the activation and attention
// state of the window.
void UpdateItemStatus();
// Updates the launcher from |tab|. // Updates the launcher from |tab|.
void UpdateLauncher(TabContentsWrapper* tab); void UpdateLauncher(TabContentsWrapper* tab);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "content/test/test_browser_thread.h" #include "content/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/activation_delegate.h" #include "ui/aura/client/activation_delegate.h"
#include "ui/aura/root_window.h" #include "ui/aura/root_window.h"
#include "ui/aura/test/test_activation_client.h" #include "ui/aura/test/test_activation_client.h"
...@@ -362,3 +363,29 @@ TEST_F(BrowserLauncherItemControllerTest, SwitchDirectlyToApp) { ...@@ -362,3 +363,29 @@ TEST_F(BrowserLauncherItemControllerTest, SwitchDirectlyToApp) {
EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model_->items()[index2].status); EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model_->items()[index2].status);
EXPECT_EQ(&state2.window, activation_client_->GetActiveWindow()); EXPECT_EQ(&state2.window, activation_client_->GetActiveWindow());
} }
// Test attention states of windows.
TEST_F(BrowserLauncherItemControllerTest, FlashWindow) {
// App panel first
State app_state(this, "1", BrowserLauncherItemController::TYPE_APP_PANEL);
EXPECT_EQ(ash::STATUS_ACTIVE, app_state.GetUpdaterItem().status);
// Active windows don't show attention.
app_state.window.SetProperty(aura::client::kDrawAttentionKey, true);
EXPECT_EQ(ash::STATUS_ACTIVE, app_state.GetUpdaterItem().status);
// Then browser window
State browser_state(
this, std::string(), BrowserLauncherItemController::TYPE_TABBED);
// First browser is active.
EXPECT_EQ(ash::STATUS_ACTIVE, browser_state.GetUpdaterItem().status);
EXPECT_EQ(ash::STATUS_RUNNING, app_state.GetUpdaterItem().status);
// App window should go to attention state.
app_state.window.SetProperty(aura::client::kDrawAttentionKey, true);
EXPECT_EQ(ash::STATUS_ATTENTION, app_state.GetUpdaterItem().status);
// Activating app window should clear attention state.
activation_client_->ActivateWindow(&app_state.window);
EXPECT_EQ(ash::STATUS_ACTIVE, app_state.GetUpdaterItem().status);
}
...@@ -20,6 +20,7 @@ namespace client { ...@@ -20,6 +20,7 @@ namespace client {
DEFINE_WINDOW_PROPERTY_KEY(bool, kAlwaysOnTopKey, false); DEFINE_WINDOW_PROPERTY_KEY(bool, kAlwaysOnTopKey, false);
DEFINE_WINDOW_PROPERTY_KEY(bool, kAnimationsDisabledKey, false); DEFINE_WINDOW_PROPERTY_KEY(bool, kAnimationsDisabledKey, false);
DEFINE_WINDOW_PROPERTY_KEY(bool, kDrawAttentionKey, false);
DEFINE_WINDOW_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE); DEFINE_WINDOW_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE);
// gfx::Rect object for RestoreBoundsKey property is owned by the window // gfx::Rect object for RestoreBoundsKey property is owned by the window
// and will be freed automatically. // and will be freed automatically.
......
...@@ -26,6 +26,10 @@ AURA_EXPORT extern const WindowProperty<bool>* const kAlwaysOnTopKey; ...@@ -26,6 +26,10 @@ AURA_EXPORT extern const WindowProperty<bool>* const kAlwaysOnTopKey;
// of value is an int. // of value is an int.
AURA_EXPORT extern const WindowProperty<bool>* const kAnimationsDisabledKey; AURA_EXPORT extern const WindowProperty<bool>* const kAnimationsDisabledKey;
// A property key to indicate that a window should show that it deserves
// attention.
AURA_EXPORT extern const aura::WindowProperty<bool>* const kDrawAttentionKey;
// A property key to store the window modality. // A property key to store the window modality.
AURA_EXPORT extern const WindowProperty<ui::ModalType>* const kModalKey; AURA_EXPORT extern const WindowProperty<ui::ModalType>* const kModalKey;
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // 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.
...@@ -35,8 +35,12 @@ void ThrobAnimation::StartThrobbing(int cycles_til_stop) { ...@@ -35,8 +35,12 @@ void ThrobAnimation::StartThrobbing(int cycles_til_stop) {
} }
void ThrobAnimation::Reset() { void ThrobAnimation::Reset() {
Reset(0);
}
void ThrobAnimation::Reset(double value) {
ResetForSlide(); ResetForSlide();
SlideAnimation::Reset(); SlideAnimation::Reset(value);
} }
void ThrobAnimation::Show() { void ThrobAnimation::Show() {
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // 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.
...@@ -31,6 +31,7 @@ class UI_EXPORT ThrobAnimation : public SlideAnimation { ...@@ -31,6 +31,7 @@ class UI_EXPORT ThrobAnimation : public SlideAnimation {
// Overridden to reset to the slide duration. // Overridden to reset to the slide duration.
virtual void Reset() OVERRIDE; virtual void Reset() OVERRIDE;
virtual void Reset(double value) OVERRIDE;
virtual void Show() OVERRIDE; virtual void Show() OVERRIDE;
virtual void Hide() OVERRIDE; virtual void Hide() OVERRIDE;
......
...@@ -618,7 +618,7 @@ void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) { ...@@ -618,7 +618,7 @@ void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) {
} }
void NativeWidgetAura::FlashFrame(bool flash) { void NativeWidgetAura::FlashFrame(bool flash) {
NOTIMPLEMENTED(); window_->SetProperty(aura::client::kDrawAttentionKey, flash);
} }
bool NativeWidgetAura::IsAccessibleWidget() const { bool NativeWidgetAura::IsAccessibleWidget() const {
......
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