diff options
author | mukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-01 20:56:23 +0000 |
---|---|---|
committer | mukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-01 20:56:23 +0000 |
commit | 18b21b2e9aa6cf49d4ee4556461c028f4d74f0cf (patch) | |
tree | f023a423afa5942d5ff06e5091fc9e98084a999a | |
parent | 7f7c45d5a4a34d36310f41dbe2bfb375056582b4 (diff) | |
download | chromium_src-18b21b2e9aa6cf49d4ee4556461c028f4d74f0cf.zip chromium_src-18b21b2e9aa6cf49d4ee4556461c028f4d74f0cf.tar.gz chromium_src-18b21b2e9aa6cf49d4ee4556461c028f4d74f0cf.tar.bz2 |
Provides more types of errors for display status (2nd)
Note that the text message itself is a placeholder. It has to be replaced
by real sentences.
Previous CL was reverted due to build failures on win aura.
BUG=176011
TBR=jamescook@chromium.org,oshima@chromium.org
TEST=ash_unittests passes on win_aura
Review URL: https://codereview.chromium.org/12387043
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@185592 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ash/ash.gyp | 7 | ||||
-rw-r--r-- | ash/ash_strings.grd | 6 | ||||
-rw-r--r-- | ash/display/display_error_dialog.cc | 80 | ||||
-rw-r--r-- | ash/display/display_error_dialog.h | 44 | ||||
-rw-r--r-- | ash/display/display_error_dialog_unittest.cc | 84 | ||||
-rw-r--r-- | ash/display/output_configurator_animation.cc | 4 | ||||
-rw-r--r-- | ash/display/output_configurator_animation.h | 3 | ||||
-rw-r--r-- | ash/shell.cc | 13 | ||||
-rw-r--r-- | ash/shell.h | 5 | ||||
-rw-r--r-- | chromeos/display/output_configurator.cc | 19 | ||||
-rw-r--r-- | chromeos/display/output_configurator.h | 3 |
11 files changed, 209 insertions, 59 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index ec824a4..6429ed472 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -487,6 +487,8 @@ }, { # else: chromeos!=1 'sources/': [ ['exclude', '/chromeos/'], + ['exclude', 'display/display_error_dialog.cc'], + ['exclude', 'display/display_error_dialog.h'], ['exclude', 'display/output_configurator_animation.cc'], ['exclude', 'display/output_configurator_animation.h'], ], @@ -687,6 +689,11 @@ # are not referenced in code, but are referenced in nibs. 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']}, }], + ['chromeos!=1', { + 'sources/': [ + ['exclude', 'display/display_error_dialog_unittest.cc'], + ], + }], ], }, { diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 4178055..4163c3f 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd @@ -568,6 +568,12 @@ Press Shift + Alt to switch. <message name="IDS_ASH_DISPLAY_FAILURE_ON_MIRRORING" desc="An error message to show that the system failed to enter the mirroring mode."> Can't duplicate image on attached monitors. No matching resolution found. </message> + <message name="IDS_ASH_DISPLAY_FAILURE_ON_EXTENDED" desc="An error message to show that the system failed to enter the extended desktop mode."> + Can't create extended desktop. No output mode found. + </message> + <message name="IDS_ASH_DISPLAY_FAILURE_UNKNOWN" desc="An error message to show that the system failed to enter a wrong output mode."> + Can't enter the new output status. + </message> <message name="IDS_ASH_INTERNAL_DISPLAY_NAME" desc="The name of the internal display which is shown in the display settings."> Internal Display </message> diff --git a/ash/display/display_error_dialog.cc b/ash/display/display_error_dialog.cc index 604d86a..64fe5c3 100644 --- a/ash/display/display_error_dialog.cc +++ b/ash/display/display_error_dialog.cc @@ -27,28 +27,20 @@ const int kDialogMessageWidthPixel = 300; // The margin width from the error message to the edge of the dialog. const int kDialogMessageMarginWidthPixel = 5; -DisplayErrorDialog* g_instance = NULL; - } // namespace // static -void DisplayErrorDialog::ShowDialog() { - if (g_instance) { - DCHECK(g_instance->GetWidget()); - g_instance->GetWidget()->StackAtTop(); - g_instance->GetWidget()->Activate(); - return; - } - +DisplayErrorDialog* DisplayErrorDialog::ShowDialog( + chromeos::OutputState new_state) { gfx::Screen* screen = Shell::GetScreen(); const gfx::Display& target_display = (screen->GetNumDisplays() > 1) ? ScreenAsh::GetSecondaryDisplay() : screen->GetPrimaryDisplay(); - g_instance = new DisplayErrorDialog(); + DisplayErrorDialog* dialog = new DisplayErrorDialog(new_state); views::Widget* widget = new views::Widget; views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); - params.delegate = g_instance; + params.delegate = dialog; // Makes |widget| belong to the target display. Size and location are // fixed by CenterWindow() below. params.bounds = target_display.bounds(); @@ -62,12 +54,37 @@ void DisplayErrorDialog::ShowDialog() { widget->GetNativeView()->SetName("DisplayErrorDialog"); widget->CenterWindow(widget->GetRootView()->GetPreferredSize()); widget->Show(); + return dialog; } -DisplayErrorDialog::DisplayErrorDialog() { +void DisplayErrorDialog::UpdateMessageForState( + chromeos::OutputState new_state) { + int message_id = -1; + switch (new_state) { + case chromeos::STATE_DUAL_MIRROR: + message_id = IDS_ASH_DISPLAY_FAILURE_ON_MIRRORING; + break; + case chromeos::STATE_DUAL_EXTENDED: + message_id = IDS_ASH_DISPLAY_FAILURE_ON_EXTENDED; + break; + default: + // The error dialog would appear only for mirroring or extended. + // It's quite unlikely to happen with other status (single-display / + // invalid / unknown status), but set an unknown error message + // instead of NOTREACHED() just in case for safety. + LOG(ERROR) << "Unexpected failure for new state: " << new_state; + message_id = IDS_ASH_DISPLAY_FAILURE_UNKNOWN; + break; + } + label_->SetText(l10n_util::GetStringUTF16(message_id)); + label_->SizeToFit(kDialogMessageWidthPixel); + Layout(); + SchedulePaint(); +} + +DisplayErrorDialog::DisplayErrorDialog(chromeos::OutputState new_state) { Shell::GetInstance()->display_controller()->AddObserver(this); - label_ = new views::Label( - l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_FAILURE_ON_MIRRORING)); + label_ = new views::Label(); AddChildView(label_); label_->SetMultiLine(true); @@ -77,12 +94,12 @@ DisplayErrorDialog::DisplayErrorDialog() { kDialogMessageMarginWidthPixel, kDialogMessageMarginWidthPixel, kDialogMessageMarginWidthPixel)); - label_->SizeToFit(kDialogMessageWidthPixel); + + UpdateMessageForState(new_state); } DisplayErrorDialog::~DisplayErrorDialog() { Shell::GetInstance()->display_controller()->RemoveObserver(this); - g_instance = NULL; } int DisplayErrorDialog::GetDialogButtons() const { @@ -101,9 +118,32 @@ void DisplayErrorDialog::OnDisplayConfigurationChanging() { GetWidget()->Close(); } -// static -DisplayErrorDialog* DisplayErrorDialog::GetInstanceForTest() { - return g_instance; +DisplayErrorObserver::DisplayErrorObserver() + : dialog_(NULL) { +} + +DisplayErrorObserver::~DisplayErrorObserver() { + DCHECK(!dialog_); +} + +void DisplayErrorObserver::OnDisplayModeChangeFailed( + chromeos::OutputState new_state) { + if (dialog_) { + DCHECK(dialog_->GetWidget()); + dialog_->UpdateMessageForState(new_state); + dialog_->GetWidget()->StackAtTop(); + dialog_->GetWidget()->Activate(); + } else { + dialog_ = DisplayErrorDialog::ShowDialog(new_state); + dialog_->GetWidget()->AddObserver(this); + } +} + +void DisplayErrorObserver::OnWidgetClosing(views::Widget* widget) { + DCHECK(dialog_); + DCHECK_EQ(dialog_->GetWidget(), widget); + widget->RemoveObserver(this); + dialog_ = NULL; } } // namespace internal diff --git a/ash/display/display_error_dialog.h b/ash/display/display_error_dialog.h index cd7829e..541adc3 100644 --- a/ash/display/display_error_dialog.h +++ b/ash/display/display_error_dialog.h @@ -8,7 +8,8 @@ #include "ash/ash_export.h" #include "ash/display/display_controller.h" #include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" +#include "chromeos/display/output_configurator.h" +#include "ui/views/widget/widget_observer.h" #include "ui/views/window/dialog_delegate.h" namespace aura { @@ -32,16 +33,14 @@ namespace internal { class ASH_EXPORT DisplayErrorDialog : public views::DialogDelegateView, public ash::DisplayController::Observer { public: - // Shows the error dialog. - static void ShowDialog(); + // Shows the error dialog for |failed_new_state| and returns it. + static DisplayErrorDialog* ShowDialog(chromeos::OutputState failed_new_state); - private: - FRIEND_TEST_ALL_PREFIXES(DisplayErrorDialogTest, Normal); - FRIEND_TEST_ALL_PREFIXES(DisplayErrorDialogTest, CallTwice); - FRIEND_TEST_ALL_PREFIXES(DisplayErrorDialogTest, SingleDisplay); - FRIEND_TEST_ALL_PREFIXES(DisplayErrorDialogTest, DisplayDisconnected); + // Update the error message for |failed_new_state|. + void UpdateMessageForState(chromeos::OutputState failed_new_state); - DisplayErrorDialog(); + private: + explicit DisplayErrorDialog(chromeos::OutputState failed_new_state); virtual ~DisplayErrorDialog(); // views::DialogDelegate overrides: @@ -56,14 +55,35 @@ class ASH_EXPORT DisplayErrorDialog : public views::DialogDelegateView, // ash::DisplayController::Observer overrides: virtual void OnDisplayConfigurationChanging() OVERRIDE; - // Returns the pointer of the current instance of this dialog. - static DisplayErrorDialog* GetInstanceForTest(); - views::Label* label_; DISALLOW_COPY_AND_ASSIGN(DisplayErrorDialog); }; +// The class to observe the output failures and shows the error dialog when +// necessary. +class ASH_EXPORT DisplayErrorObserver + : public chromeos::OutputConfigurator::Observer, + public views::WidgetObserver { + public: + DisplayErrorObserver(); + virtual ~DisplayErrorObserver(); + + const DisplayErrorDialog* dialog() const { return dialog_; } + + // chromeos::OutputConfigurator::Observer overrides: + virtual void OnDisplayModeChangeFailed( + chromeos::OutputState failed_new_state) OVERRIDE; + + // views::WidgetObserver overrides: + virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE; + + private: + DisplayErrorDialog* dialog_; + + DISALLOW_COPY_AND_ASSIGN(DisplayErrorObserver); +}; + } // namespace internal } // namespace ash diff --git a/ash/display/display_error_dialog_unittest.cc b/ash/display/display_error_dialog_unittest.cc index e4d21d5..16ff625 100644 --- a/ash/display/display_error_dialog_unittest.cc +++ b/ash/display/display_error_dialog_unittest.cc @@ -6,39 +6,98 @@ #include "ash/shell.h" #include "ash/test/ash_test_base.h" +#include "grit/ash_strings.h" #include "ui/aura/window.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/views/controls/label.h" +#include "ui/views/view.h" #include "ui/views/widget/widget.h" namespace ash { namespace internal { +namespace { -typedef test::AshTestBase DisplayErrorDialogTest; +class DisplayErrorDialogTest : public test::AshTestBase { + protected: + DisplayErrorDialogTest() { + } + + virtual ~DisplayErrorDialogTest() { + } + + virtual void SetUp() OVERRIDE { + test::AshTestBase::SetUp(); + observer_.reset(new DisplayErrorObserver()); + } + + virtual void TearDown() OVERRIDE { + if (observer_->dialog()) { + views::Widget* widget = + const_cast<DisplayErrorDialog*>(observer_->dialog())->GetWidget(); + widget->CloseNow(); + } + observer_.reset(); + test::AshTestBase::TearDown(); + } + + DisplayErrorObserver* observer() { return observer_.get(); } + + const string16& GetMessageContents(const DisplayErrorDialog* dialog) { + const views::Label* label = static_cast<const views::Label*>( + static_cast<const views::View*>(dialog)->child_at(0)); + return label->text(); + } + + private: + scoped_ptr<DisplayErrorObserver> observer_; + + DISALLOW_COPY_AND_ASSIGN(DisplayErrorDialogTest); +}; + +} // The test cases in this file usually check if the showing dialog doesn't // cause any crashes, and the code doesn't cause any memory leaks. TEST_F(DisplayErrorDialogTest, Normal) { UpdateDisplay("200x200,300x300"); - DisplayErrorDialog::ShowDialog(); - DisplayErrorDialog* dialog = DisplayErrorDialog::GetInstanceForTest(); + DisplayErrorDialog* dialog = + DisplayErrorDialog::ShowDialog(chromeos::STATE_DUAL_MIRROR); EXPECT_TRUE(dialog); EXPECT_TRUE(dialog->GetWidget()->IsVisible()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_FAILURE_ON_MIRRORING), + GetMessageContents(dialog)); EXPECT_EQ(Shell::GetAllRootWindows()[1], dialog->GetWidget()->GetNativeView()->GetRootWindow()); } TEST_F(DisplayErrorDialogTest, CallTwice) { UpdateDisplay("200x200,300x300"); - DisplayErrorDialog::ShowDialog(); - DisplayErrorDialog* dialog = DisplayErrorDialog::GetInstanceForTest(); + observer()->OnDisplayModeChangeFailed(chromeos::STATE_DUAL_MIRROR); + const DisplayErrorDialog* dialog = observer()->dialog(); + EXPECT_TRUE(dialog); + + observer()->OnDisplayModeChangeFailed(chromeos::STATE_DUAL_MIRROR); + EXPECT_EQ(dialog, observer()->dialog()); +} + +TEST_F(DisplayErrorDialogTest, CallWithDifferentState) { + UpdateDisplay("200x200,300x300"); + observer()->OnDisplayModeChangeFailed(chromeos::STATE_DUAL_MIRROR); + const DisplayErrorDialog* dialog = observer()->dialog(); EXPECT_TRUE(dialog); - DisplayErrorDialog::ShowDialog(); - EXPECT_EQ(dialog, DisplayErrorDialog::GetInstanceForTest()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_FAILURE_ON_MIRRORING), + GetMessageContents(dialog)); + + observer()->OnDisplayModeChangeFailed(chromeos::STATE_DUAL_EXTENDED); + EXPECT_EQ(dialog, observer()->dialog()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_FAILURE_ON_EXTENDED), + GetMessageContents(dialog)); } TEST_F(DisplayErrorDialogTest, SingleDisplay) { UpdateDisplay("200x200"); - DisplayErrorDialog::ShowDialog(); - DisplayErrorDialog* dialog = DisplayErrorDialog::GetInstanceForTest(); + DisplayErrorDialog* dialog = + DisplayErrorDialog::ShowDialog(chromeos::STATE_DUAL_MIRROR); EXPECT_TRUE(dialog); EXPECT_TRUE(dialog->GetWidget()->IsVisible()); EXPECT_EQ(Shell::GetInstance()->GetPrimaryRootWindow(), @@ -47,15 +106,14 @@ TEST_F(DisplayErrorDialogTest, SingleDisplay) { TEST_F(DisplayErrorDialogTest, DisplayDisconnected) { UpdateDisplay("200x200,300x300"); - DisplayErrorDialog::ShowDialog(); - DisplayErrorDialog* dialog = DisplayErrorDialog::GetInstanceForTest(); - EXPECT_TRUE(dialog); + observer()->OnDisplayModeChangeFailed(chromeos::STATE_DUAL_MIRROR); + EXPECT_TRUE(observer()->dialog()); UpdateDisplay("200x200"); // Disconnection will close the dialog but we have to run all pending tasks // to make the effect of the close. RunAllPendingInMessageLoop(); - EXPECT_FALSE(DisplayErrorDialog::GetInstanceForTest()); + EXPECT_FALSE(observer()->dialog()); } } // namespace internal diff --git a/ash/display/output_configurator_animation.cc b/ash/display/output_configurator_animation.cc index 8d47963..6c6d78d 100644 --- a/ash/display/output_configurator_animation.cc +++ b/ash/display/output_configurator_animation.cc @@ -209,10 +209,10 @@ void OutputConfiguratorAnimation::OnDisplayModeChanged() { StartFadeInAnimation(); } -void OutputConfiguratorAnimation::OnDisplayModeChangeFailed() { +void OutputConfiguratorAnimation::OnDisplayModeChangeFailed( + chromeos::OutputState failed_new_state) { if (!hiding_layers_.empty()) StartFadeInAnimation(); - DisplayErrorDialog::ShowDialog(); } void OutputConfiguratorAnimation::ClearHidingLayers() { diff --git a/ash/display/output_configurator_animation.h b/ash/display/output_configurator_animation.h index 9dc99c6..dc70264 100644 --- a/ash/display/output_configurator_animation.h +++ b/ash/display/output_configurator_animation.h @@ -43,7 +43,8 @@ class ASH_EXPORT OutputConfiguratorAnimation protected: // chromeos::OutputConfigurator::Observer overrides: virtual void OnDisplayModeChanged() OVERRIDE; - virtual void OnDisplayModeChangeFailed() OVERRIDE; + virtual void OnDisplayModeChangeFailed( + chromeos::OutputState failed_new_state) OVERRIDE; private: // Clears all hiding layers. Note that in case that this method is called diff --git a/ash/shell.cc b/ash/shell.cc index ffa015a..c6965b2 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -106,6 +106,7 @@ #if defined(OS_CHROMEOS) #include "ash/ash_constants.h" #include "ash/display/display_change_observer_x11.h" +#include "ash/display/display_error_dialog.h" #include "ash/display/output_configurator_animation.h" #include "base/chromeos/chromeos_version.h" #include "base/message_pump_aurax11.h" @@ -303,17 +304,19 @@ Shell::~Shell() { // because they might have registered ActivationChangeObserver. activation_controller_.reset(); - DCHECK(instance_ == this); - instance_ = NULL; - #if defined(OS_CHROMEOS) if (display_change_observer_.get()) output_configurator_->RemoveObserver(display_change_observer_.get()); if (output_configurator_animation_.get()) output_configurator_->RemoveObserver(output_configurator_animation_.get()); + if (display_error_observer_.get()) + output_configurator_->RemoveObserver(display_error_observer_.get()); base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow( output_configurator()); #endif // defined(OS_CHROMEOS) + + DCHECK(instance_ == this); + instance_ = NULL; } // static @@ -418,8 +421,10 @@ void Shell::Init() { // observer gets invoked after the root windows are configured. output_configurator_->AddObserver(display_change_observer_.get()); output_configurator_animation_.reset( - new internal::OutputConfiguratorAnimation()), + new internal::OutputConfiguratorAnimation()); + display_error_observer_.reset(new internal::DisplayErrorObserver()); output_configurator_->AddObserver(output_configurator_animation_.get()); + output_configurator_->AddObserver(display_error_observer_.get()); display_change_observer_->OnDisplayModeChanged(); } #endif diff --git a/ash/shell.h b/ash/shell.h index c6047ea00..5ed4cd7 100644 --- a/ash/shell.h +++ b/ash/shell.h @@ -103,6 +103,7 @@ class ActivationController; class AppListController; class CaptureController; class DisplayChangeObserverX11; +class DisplayErrorObserver; class DisplayManager; class DragDropController; class EventClientImpl; @@ -434,6 +435,9 @@ class ASH_EXPORT Shell internal::OutputConfiguratorAnimation* output_configurator_animation() { return output_configurator_animation_.get(); } + internal::DisplayErrorObserver* display_error_observer() { + return display_error_observer_.get(); + } #endif // defined(OS_CHROMEOS) RootWindowHostFactory* root_window_host_factory() { @@ -579,6 +583,7 @@ class ASH_EXPORT Shell scoped_ptr<chromeos::OutputConfigurator> output_configurator_; scoped_ptr<internal::OutputConfiguratorAnimation> output_configurator_animation_; + scoped_ptr<internal::DisplayErrorObserver> display_error_observer_; // Receives output change events and udpates the display manager. scoped_ptr<internal::DisplayChangeObserverX11> display_change_observer_; diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc index 00c0f72..4357b1a 100644 --- a/chromeos/display/output_configurator.cc +++ b/chromeos/display/output_configurator.cc @@ -654,10 +654,12 @@ bool OutputConfigurator::CycleDisplayMode() { XRRFreeScreenResources(screen); XUngrabServer(display); - if (did_change) + if (did_change) { NotifyOnDisplayChanged(); - else - FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChangeFailed()); + } else { + FOR_EACH_OBSERVER( + Observer, observers_, OnDisplayModeChangeFailed(next_state)); + } return did_change; } @@ -759,10 +761,12 @@ bool OutputConfigurator::SetDisplayMode(OutputState new_state) { XRRFreeScreenResources(screen); XUngrabServer(display); - if (output_state_ == new_state) + if (output_state_ == new_state) { NotifyOnDisplayChanged(); - else - FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChangeFailed()); + } else { + FOR_EACH_OBSERVER( + Observer, observers_, OnDisplayModeChangeFailed(new_state)); + } return true; } @@ -833,6 +837,9 @@ void OutputConfigurator::ConfigureOutputs() { if (success) { output_state_ = new_state; NotifyOnDisplayChanged(); + } else { + FOR_EACH_OBSERVER( + Observer, observers_, OnDisplayModeChangeFailed(new_state)); } chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> SetIsProjecting(is_projecting); diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h index cd3420a..804f856 100644 --- a/chromeos/display/output_configurator.h +++ b/chromeos/display/output_configurator.h @@ -57,7 +57,8 @@ class CHROMEOS_EXPORT OutputConfigurator : public MessageLoop::Dispatcher { virtual void OnDisplayModeChanged() {} // Called when the change of the display mode is issued but failed. - virtual void OnDisplayModeChangeFailed() {} + // |failed_new_state| is the new state which the system failed to enter. + virtual void OnDisplayModeChangeFailed(OutputState failed_new_state) {} }; OutputConfigurator(); |