diff options
author | mukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-22 03:11:47 +0000 |
---|---|---|
committer | mukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-22 03:11:47 +0000 |
commit | 1e5ad60eceff290a927113bc4fff6373d432a45e (patch) | |
tree | 279f43e8e9db0503ea0d6f07b007fb631cf67dd3 /ash | |
parent | 5ad0c7075a4047d608e79588f1242c0986b6ebeb (diff) | |
download | chromium_src-1e5ad60eceff290a927113bc4fff6373d432a45e.zip chromium_src-1e5ad60eceff290a927113bc4fff6373d432a45e.tar.gz chromium_src-1e5ad60eceff290a927113bc4fff6373d432a45e.tar.bz2 |
Updates the display message in the uber tray.
This CL contains the following fixes:
- shows the notification for display rotation / ui_scale
- adds (width x height) annotation to the display if something
has been edited
- shows the internal display's status if something for the internal
display has been edited and no external display is connected
- shows the tooltip text to provide the status of both internal and
extrenal displays at the same time
This CL does not contain:
- the feature to prevent notification when the settings change happens
from chrome://settings/display
I think we can achieve this by suppressing the notification when
the current active tab is chrome://settings/display, but anyways
it'll be done in another CL. That is marked as a TODO.
BUG=250650, 246271
Review URL: https://chromiumcodereview.appspot.com/17445002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207998 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/ash.gyp | 1 | ||||
-rw-r--r-- | ash/ash_strings.grd | 9 | ||||
-rw-r--r-- | ash/system/chromeos/tray_display.cc | 286 | ||||
-rw-r--r-- | ash/system/chromeos/tray_display.h | 47 | ||||
-rw-r--r-- | ash/system/chromeos/tray_display_unittest.cc | 340 | ||||
-rw-r--r-- | ash/test/ash_test_base.cc | 12 |
6 files changed, 580 insertions, 115 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index 6821ed0..32e8cfd 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -698,6 +698,7 @@ 'shell/window_watcher_unittest.cc', 'system/chromeos/network/network_state_notifier_unittest.cc', 'system/chromeos/power/tray_power_unittest.cc', + 'system/chromeos/tray_display_unittest.cc', 'system/tray/system_tray_unittest.cc', 'system/user/tray_user_unittest.cc', 'system/web_notification/web_notification_tray_unittest.cc', diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 53b2547..d16238a 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd @@ -321,6 +321,15 @@ Press Ctrl+Alt+Z to disable. <message name="IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED" desc="The label used in the tray to show that the current status is docked mode."> Dock mode </message> + <message name="IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED" desc="The label used in the tray to notify that the display resolution settings has changed."> + <ph name="DISPLAY_NAME">$1</ph> has been resized to <ph name="RESOLUTION">$2</ph> + </message> + <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED" desc="The label used in the tray to notify that the display rotation settings has changed."> + <ph name="DISPLAY_NAME">$1</ph> has been rotated + </message> + <message name="IDS_ASH_STATUS_TRAY_DISPLAY_SINGLE_DISPLAY" desc="The label used in the tray to show the current display's configuration if there is a single display"> + <ph name="DISPLAY_NAME">$1</ph>: <ph name="RESOLUTION">$2</ph> + </message> <message name="IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME" desc="Label shown in tray for a display whose name is unknown."> Unknown Display </message> diff --git a/ash/system/chromeos/tray_display.cc b/ash/system/chromeos/tray_display.cc index cf3ca84..484e0d2 100644 --- a/ash/system/chromeos/tray_display.cc +++ b/ash/system/chromeos/tray_display.cc @@ -7,6 +7,7 @@ #include "ash/display/display_controller.h" #include "ash/display/display_manager.h" #include "ash/shell.h" +#include "ash/system/tray/actionable_view.h" #include "ash/system/tray/fixed_sized_image_view.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_delegate.h" @@ -17,6 +18,7 @@ #include "grit/ash_strings.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" @@ -24,26 +26,34 @@ namespace ash { namespace internal { namespace { -TrayDisplayMode GetCurrentTrayDisplayMode() { - DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - if (display_manager->GetNumDisplays() > 1) - return TRAY_DISPLAY_EXTENDED; +bool display_notifications_disabled = false; - if (display_manager->IsMirrored()) - return TRAY_DISPLAY_MIRRORED; +DisplayManager* GetDisplayManager() { + return Shell::GetInstance()->display_manager(); +} - int64 first_id = display_manager->first_display_id(); - if (display_manager->HasInternalDisplay() && - !display_manager->IsInternalDisplayId(first_id)) { - return TRAY_DISPLAY_DOCKED; - } +base::string16 GetDisplayName(int64 display_id) { + return UTF8ToUTF16(GetDisplayManager()->GetDisplayNameForId(display_id)); +} + +base::string16 GetDisplaySize(int64 display_id) { + return UTF8ToUTF16( + GetDisplayManager()->GetDisplayForId(display_id).size().ToString()); +} + +bool ShouldShowResolution(int64 display_id) { + if (!GetDisplayManager()->GetDisplayForId(display_id).is_valid()) + return false; - return TRAY_DISPLAY_SINGLE; + const DisplayInfo& display_info = + GetDisplayManager()->GetDisplayInfo(display_id); + return display_info.rotation() != gfx::Display::ROTATE_0 || + display_info.ui_scale() != 1.0f; } // Returns the name of the currently connected external display. base::string16 GetExternalDisplayName() { - DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + DisplayManager* display_manager = GetDisplayManager(); int64 external_id = display_manager->mirrored_display().id(); if (external_id == gfx::Display::kInvalidDisplayID) { @@ -56,82 +66,64 @@ base::string16 GetExternalDisplayName() { } } } - if (external_id != gfx::Display::kInvalidDisplayID) - return UTF8ToUTF16(display_manager->GetDisplayNameForId(external_id)); - return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); -} -class DisplayViewBase { - public: - DisplayViewBase(user::LoginStatus login_status) - : login_status_(login_status) { - label_ = new views::Label(); - label_->SetMultiLine(true); - label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - } + if (external_id == gfx::Display::kInvalidDisplayID) + return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); - virtual ~DisplayViewBase() { - } + // The external display name may have an annotation of "(width x height)" in + // case that the display is rotated or its resolution is changed. + base::string16 name = GetDisplayName(external_id); + if (ShouldShowResolution(external_id)) + name += UTF8ToUTF16(" (") + GetDisplaySize(external_id) + UTF8ToUTF16(")"); - protected: - void OpenSettings() { - if (login_status_ == ash::user::LOGGED_IN_USER || - login_status_ == ash::user::LOGGED_IN_OWNER || - login_status_ == ash::user::LOGGED_IN_GUEST) { - ash::Shell::GetInstance()->system_tray_delegate()->ShowDisplaySettings(); + return name; +} + +base::string16 GetTrayDisplayMessage() { + DisplayManager* display_manager = GetDisplayManager(); + if (display_manager->GetNumDisplays() > 1) { + if (GetDisplayManager()->HasInternalDisplay()) { + return l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetExternalDisplayName()); } + return l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL); } - bool UpdateLabelText() { - switch (GetCurrentTrayDisplayMode()) { - case TRAY_DISPLAY_SINGLE: - // TODO(oshima|mukai): Support single display mode for overscan - // alignment. - return false; - case TRAY_DISPLAY_EXTENDED: - if (Shell::GetInstance()->display_manager()->HasInternalDisplay()) { - label_->SetText(l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetExternalDisplayName())); - } else { - label_->SetText(l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL)); - } - break; - case TRAY_DISPLAY_MIRRORED: - if (Shell::GetInstance()->display_manager()->HasInternalDisplay()) { - label_->SetText(l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetExternalDisplayName())); - } else { - label_->SetText(l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL)); - } - break; - case TRAY_DISPLAY_DOCKED: - label_->SetText(l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED)); - break; + if (display_manager->IsMirrored()) { + if (GetDisplayManager()->HasInternalDisplay()) { + return l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetExternalDisplayName()); } - return true; + return l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL); } - views::Label* label() { return label_; } + int64 first_id = display_manager->first_display_id(); + if (display_manager->HasInternalDisplay() && + !display_manager->IsInternalDisplayId(first_id)) { + return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED); + } - private: - user::LoginStatus login_status_; - views::Label* label_; + return base::string16(); +} - DISALLOW_COPY_AND_ASSIGN(DisplayViewBase); -}; +void OpenSettings(user::LoginStatus login_status) { + if (login_status == ash::user::LOGGED_IN_USER || + login_status == ash::user::LOGGED_IN_OWNER || + login_status == ash::user::LOGGED_IN_GUEST) { + ash::Shell::GetInstance()->system_tray_delegate()->ShowDisplaySettings(); + } +} } // namespace -class DisplayView : public DisplayViewBase, - public ash::internal::ActionableView { +class DisplayView : public ash::internal::ActionableView { public: explicit DisplayView(user::LoginStatus login_status) - : DisplayViewBase(login_status) { - SetLayoutManager(new - views::BoxLayout(views::BoxLayout::kHorizontal, + : login_status_(login_status) { + SetLayoutManager(new views::BoxLayout( + views::BoxLayout::kHorizontal, ash::kTrayPopupPaddingHorizontal, 0, ash::kTrayPopupPaddingBetweenItems)); @@ -141,70 +133,111 @@ class DisplayView : public DisplayViewBase, image_->SetImage( bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY).ToImageSkia()); AddChildView(image_); - AddChildView(label()); + + label_ = new views::Label(); + label_->SetMultiLine(true); + label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + AddChildView(label_); Update(); } virtual ~DisplayView() {} void Update() { - SetVisible(UpdateLabelText()); + base::string16 message = GetTrayDisplayMessage(); + if (message.empty()) + message = GetInternalDisplayInfo(); + SetVisible(!message.empty()); + label_->SetText(message); + } + + views::Label* label() { return label_; } + + // Overridden from views::View. + virtual bool GetTooltipText(const gfx::Point& p, + base::string16* tooltip) const OVERRIDE { + base::string16 tray_message = GetTrayDisplayMessage(); + base::string16 internal_message = GetInternalDisplayInfo(); + if (tray_message.empty() && internal_message.empty()) + return false; + + *tooltip = tray_message + ASCIIToUTF16("\n") + internal_message; + return true; } private: + base::string16 GetInternalDisplayInfo() const { + int64 first_id = GetDisplayManager()->first_display_id(); + if (!ShouldShowResolution(first_id)) + return base::string16(); + + return l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_SINGLE_DISPLAY, + GetDisplayName(first_id), + GetDisplaySize(first_id)); + } + // Overridden from ActionableView. virtual bool PerformAction(const ui::Event& event) OVERRIDE { - OpenSettings(); + OpenSettings(login_status_); return true; } virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE { int label_max_width = bounds().width() - kTrayPopupPaddingHorizontal * 2 - kTrayPopupPaddingBetweenItems - image_->GetPreferredSize().width(); - label()->SizeToFit(label_max_width); + label_->SizeToFit(label_max_width); PreferredSizeChanged(); } + user::LoginStatus login_status_; views::ImageView* image_; + views::Label* label_; DISALLOW_COPY_AND_ASSIGN(DisplayView); }; -class DisplayNotificationView : public DisplayViewBase, - public TrayNotificationView { +class DisplayNotificationView : public TrayNotificationView { public: DisplayNotificationView(user::LoginStatus login_status, - TrayDisplay* tray_item) - : DisplayViewBase(login_status), - TrayNotificationView(tray_item, IDR_AURA_UBER_TRAY_DISPLAY) { - InitView(label()); + TrayDisplay* tray_item, + const base::string16& message) + : TrayNotificationView(tray_item, IDR_AURA_UBER_TRAY_DISPLAY), + login_status_(login_status) { StartAutoCloseTimer(kTrayPopupAutoCloseDelayForTextInSeconds); - Update(); + Update(message); } virtual ~DisplayNotificationView() {} - void Update() { - if (UpdateLabelText()) - RestartAutoCloseTimer(); - else + void Update(const base::string16& message) { + if (message.empty()) { owner()->HideNotificationView(); + } else { + views::Label* label = new views::Label(message); + label->SetMultiLine(true); + label->SetHorizontalAlignment(gfx::ALIGN_LEFT); + UpdateView(label); + RestartAutoCloseTimer(); + } } // Overridden from TrayNotificationView: virtual void OnClickAction() OVERRIDE { - OpenSettings(); + OpenSettings(login_status_); } private: + user::LoginStatus login_status_; + DISALLOW_COPY_AND_ASSIGN(DisplayNotificationView); }; TrayDisplay::TrayDisplay(SystemTray* system_tray) : SystemTrayItem(system_tray), default_(NULL), - notification_(NULL), - current_mode_(GetCurrentTrayDisplayMode()) { + notification_(NULL) { + current_message_ = GetDisplayMessageForNotification(); Shell::GetInstance()->display_controller()->AddObserver(this); } @@ -212,6 +245,45 @@ TrayDisplay::~TrayDisplay() { Shell::GetInstance()->display_controller()->RemoveObserver(this); } +base::string16 TrayDisplay::GetDisplayMessageForNotification() { + DisplayManager* display_manager = GetDisplayManager(); + DisplayInfoMap old_info; + old_info.swap(display_info_); + for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { + int64 id = display_manager->GetDisplayAt(i)->id(); + display_info_[id] = display_manager->GetDisplayInfo(id); + } + + // Display is added or removed. Use the same message as the one in + // the system tray. + if (display_info_.size() != old_info.size()) + return GetTrayDisplayMessage(); + + for (DisplayInfoMap::const_iterator iter = display_info_.begin(); + iter != display_info_.end(); ++iter) { + DisplayInfoMap::const_iterator old_iter = old_info.find(iter->first); + // A display is removed and added at the same time. It won't happen + // in the actual environment, but falls back to the system tray's + // message just in case. + if (old_iter == old_info.end()) + return GetTrayDisplayMessage(); + + if (iter->second.ui_scale() != old_iter->second.ui_scale()) { + return l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, + GetDisplayName(iter->first), + GetDisplaySize(iter->first)); + } + if (iter->second.rotation() != old_iter->second.rotation()) { + return l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetDisplayName(iter->first)); + } + } + + // Found nothing special + return base::string16(); +} + views::View* TrayDisplay::CreateDefaultView(user::LoginStatus status) { DCHECK(default_ == NULL); default_ = new DisplayView(status); @@ -220,7 +292,7 @@ views::View* TrayDisplay::CreateDefaultView(user::LoginStatus status) { views::View* TrayDisplay::CreateNotificationView(user::LoginStatus status) { DCHECK(notification_ == NULL); - notification_ = new DisplayNotificationView(status, this); + notification_ = new DisplayNotificationView(status, this, current_message_); return notification_; } @@ -237,14 +309,28 @@ bool TrayDisplay::ShouldShowLauncher() const { } void TrayDisplay::OnDisplayConfigurationChanged() { - TrayDisplayMode new_mode = GetCurrentTrayDisplayMode(); - if (current_mode_ != new_mode && new_mode != TRAY_DISPLAY_SINGLE) { - if (notification_) - notification_->Update(); - else - ShowNotificationView(); - } - current_mode_ = new_mode; + if (display_notifications_disabled) + return; + + // TODO(mukai): do not show the notification when the configuration changed + // due to the user operation on display settings page. + current_message_ = GetDisplayMessageForNotification(); + if (notification_) + notification_->Update(current_message_); + else if (!current_message_.empty()) + ShowNotificationView(); +} + +// static +void TrayDisplay::SetDisplayNotificationsDisabledForTest(bool disabled) { + display_notifications_disabled = disabled; +} + +base::string16 TrayDisplay::GetDefaultViewMessage() { + if (!default_ || !default_->visible()) + return base::string16(); + + return static_cast<DisplayView*>(default_)->label()->text(); } } // namespace internal diff --git a/ash/system/chromeos/tray_display.h b/ash/system/chromeos/tray_display.h index 0265704..4c2faa73 100644 --- a/ash/system/chromeos/tray_display.h +++ b/ash/system/chromeos/tray_display.h @@ -5,33 +5,40 @@ #ifndef ASH_SYSTEM_CHROMEOS_TRAY_DISPLAY_H_ #define ASH_SYSTEM_CHROMEOS_TRAY_DISPLAY_H_ +#include <map> + +#include "ash/ash_export.h" #include "ash/display/display_controller.h" +#include "ash/display/display_info.h" #include "ash/system/tray/system_tray_item.h" +#include "base/strings/string16.h" +#include "ui/views/view.h" -namespace views { -class View; +namespace ash { +namespace test { +class AshTestBase; } -namespace ash { namespace internal { -enum TrayDisplayMode { - TRAY_DISPLAY_SINGLE, - TRAY_DISPLAY_EXTENDED, - TRAY_DISPLAY_MIRRORED, - TRAY_DISPLAY_DOCKED, -}; - -class DisplayView; class DisplayNotificationView; -class TrayDisplay : public SystemTrayItem, - public DisplayController::Observer { +class ASH_EXPORT TrayDisplay : public SystemTrayItem, + public DisplayController::Observer { public: explicit TrayDisplay(SystemTray* system_tray); virtual ~TrayDisplay(); private: + friend class test::AshTestBase; + friend class TrayDisplayTest; + + typedef std::map<int64, DisplayInfo> DisplayInfoMap; + + // Checks the current display settings and determine what message should be + // shown for notification. + base::string16 GetDisplayMessageForNotification(); + // Overridden from SystemTrayItem. virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE; virtual views::View* CreateNotificationView( @@ -43,9 +50,19 @@ class TrayDisplay : public SystemTrayItem, // Overridden from DisplayControllerObserver: virtual void OnDisplayConfigurationChanged() OVERRIDE; - DisplayView* default_; + // Call this with |diabled| = false when the test case wants to see the + // display notification. + static void SetDisplayNotificationsDisabledForTest(bool disabled); + + // Test accessors. + base::string16 GetDefaultViewMessage(); + views::View* default_view() { return default_; } + const string16& current_message() const { return current_message_; } + + views::View* default_; DisplayNotificationView* notification_; - TrayDisplayMode current_mode_; + string16 current_message_; + DisplayInfoMap display_info_; DISALLOW_COPY_AND_ASSIGN(TrayDisplay); }; diff --git a/ash/system/chromeos/tray_display_unittest.cc b/ash/system/chromeos/tray_display_unittest.cc new file mode 100644 index 0000000..8c2ec5b --- /dev/null +++ b/ash/system/chromeos/tray_display_unittest.cc @@ -0,0 +1,340 @@ +// 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/system/chromeos/tray_display.h" + +#include "ash/display/display_manager.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/test/ash_test_base.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "grit/ash_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/display.h" +#include "ui/views/controls/label.h" + +namespace ash { +namespace internal { + +base::string16 GetTooltipText(const base::string16& line1, + const base::string16& line2) { + return line1 + ASCIIToUTF16("\n") + line2; +} + +base::string16 GetTooltipText1(const base::string16& line1) { + return GetTooltipText(line1, base::string16()); +} + +base::string16 GetTooltipText2(const base::string16& line2) { + return GetTooltipText(base::string16(), line2); +} + +base::string16 GetFirstDisplayName() { + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + return UTF8ToUTF16(display_manager->GetDisplayNameForId( + display_manager->first_display_id())); +} + +base::string16 GetSecondDisplayName() { + return UTF8ToUTF16( + Shell::GetInstance()->display_manager()->GetDisplayNameForId( + ScreenAsh::GetSecondaryDisplay().id())); +} + +base::string16 GetMirroredDisplayName() { + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + return UTF8ToUTF16(display_manager->GetDisplayNameForId( + display_manager->mirrored_display().id())); +} + +class TrayDisplayTest : public ash::test::AshTestBase { + public: + TrayDisplayTest(); + virtual ~TrayDisplayTest(); + + virtual void SetUp() OVERRIDE; + + protected: + SystemTray* tray() { return tray_; } + + void CloseNotification(); + bool IsDisplayVisibleInTray(); + base::string16 GetTrayDisplayText(); + base::string16 GetTrayDisplayTooltipText(); + base::string16 GetDisplayNotificationText(); + + private: + // Weak reference, owned by Shell. + SystemTray* tray_; + + // Weak reference, owned by |tray_|. + TrayDisplay* tray_display_; + + DISALLOW_COPY_AND_ASSIGN(TrayDisplayTest); +}; + +TrayDisplayTest::TrayDisplayTest() : tray_(NULL), tray_display_(NULL) { +} + +TrayDisplayTest::~TrayDisplayTest() { +} + +void TrayDisplayTest::SetUp() { + ash::test::AshTestBase::SetUp(); + tray_ = Shell::GetPrimaryRootWindowController()->GetSystemTray(); + tray_display_ = new TrayDisplay(tray_); + tray_->AddTrayItem(tray_display_); + TrayDisplay::SetDisplayNotificationsDisabledForTest(false); +} + +void TrayDisplayTest::CloseNotification() { + tray()->CloseNotificationBubbleForTest(); + tray_display_->HideNotificationView(); + RunAllPendingInMessageLoop(); +} + +bool TrayDisplayTest::IsDisplayVisibleInTray() { + return tray_display_->default_view() && + tray_display_->default_view()->visible(); +} + +base::string16 TrayDisplayTest::GetTrayDisplayText() { + return tray_display_->GetDefaultViewMessage(); +} + +base::string16 TrayDisplayTest::GetTrayDisplayTooltipText() { + if (!tray_display_->default_view()) + return base::string16(); + + base::string16 tooltip; + if (!tray_display_->default_view()->GetTooltipText(gfx::Point(), &tooltip)) + return base::string16(); + return tooltip; +} + +base::string16 TrayDisplayTest::GetDisplayNotificationText() { + return tray_display_->current_message(); +} + +TEST_F(TrayDisplayTest, NoInternalDisplay) { + UpdateDisplay("400x400"); + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_FALSE(IsDisplayVisibleInTray()); + + UpdateDisplay("400x400,200x200"); + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_TRUE(IsDisplayVisibleInTray()); + base::string16 expected = l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL); + EXPECT_EQ(expected, GetTrayDisplayText()); + EXPECT_EQ(GetTooltipText1(expected), GetTrayDisplayTooltipText()); + + // mirroring + Shell::GetInstance()->display_manager()->SetSoftwareMirroring(true); + UpdateDisplay("400x400,200x200"); + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_TRUE(IsDisplayVisibleInTray()); + expected = l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL); + EXPECT_EQ(expected, GetTrayDisplayText()); + EXPECT_EQ(GetTooltipText1(expected), GetTrayDisplayTooltipText()); +} + +TEST_F(TrayDisplayTest, InternalDisplay) { + UpdateDisplay("400x400"); + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + gfx::Display::SetInternalDisplayId(display_manager->first_display_id()); + + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_FALSE(IsDisplayVisibleInTray()); + + // Extended + UpdateDisplay("400x400,200x200"); + string16 expected = l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetSecondDisplayName()); + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_TRUE(IsDisplayVisibleInTray()); + EXPECT_EQ(expected, GetTrayDisplayText()); + EXPECT_EQ(GetTooltipText1(expected), GetTrayDisplayTooltipText()); + + // Mirroring + display_manager->SetSoftwareMirroring(true); + UpdateDisplay("400x400,200x200"); + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_TRUE(IsDisplayVisibleInTray()); + + expected = l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroredDisplayName()); + EXPECT_EQ(expected, GetTrayDisplayText()); + EXPECT_EQ(GetTooltipText1(expected), GetTrayDisplayTooltipText()); + + // TODO(mukai): add test case for docked mode here. +} + +TEST_F(TrayDisplayTest, InternalDisplayResized) { + UpdateDisplay("400x400@1.5"); + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + gfx::Display::SetInternalDisplayId(display_manager->first_display_id()); + + // Shows the tray_display even though there's a single-display. + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_TRUE(IsDisplayVisibleInTray()); + base::string16 internal_info = l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_SINGLE_DISPLAY, + GetFirstDisplayName(), + UTF8ToUTF16("600x600")); + EXPECT_EQ(internal_info, GetTrayDisplayText()); + EXPECT_EQ(GetTooltipText2(internal_info), GetTrayDisplayTooltipText()); + + // Extended + UpdateDisplay("400x400@1.5,200x200"); + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_TRUE(IsDisplayVisibleInTray()); + base::string16 expected = l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetSecondDisplayName()); + EXPECT_EQ(expected, GetTrayDisplayText()); + EXPECT_EQ(GetTooltipText(expected, internal_info), + GetTrayDisplayTooltipText()); + + // Mirroring + display_manager->SetSoftwareMirroring(true); + UpdateDisplay("400x400@1.5,200x200"); + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_TRUE(IsDisplayVisibleInTray()); + expected = l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroredDisplayName()); + EXPECT_EQ(expected, GetTrayDisplayText()); + EXPECT_EQ(GetTooltipText(expected, internal_info), + GetTrayDisplayTooltipText()); +} + +TEST_F(TrayDisplayTest, ExternalDisplayResized) { + UpdateDisplay("400x400"); + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + gfx::Display::SetInternalDisplayId(display_manager->first_display_id()); + + // Shows the tray_display even though there's a single-display. + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_FALSE(IsDisplayVisibleInTray()); + + // Extended + UpdateDisplay("400x400,200x200@1.5"); + const gfx::Display& secondary_display = ScreenAsh::GetSecondaryDisplay(); + base::string16 secondary_annotation = UTF8ToUTF16( + " (" + secondary_display.size().ToString() + ")"); + + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_TRUE(IsDisplayVisibleInTray()); + base::string16 expected = l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, + GetSecondDisplayName() + secondary_annotation); + EXPECT_EQ(expected, GetTrayDisplayText()); + EXPECT_EQ(GetTooltipText1(expected), GetTrayDisplayTooltipText()); + + // Mirroring: in mirroring, it's not possible to lookup the DisplayInfo. + display_manager->SetSoftwareMirroring(true); + UpdateDisplay("400x400,200x200@1.5"); + tray()->ShowDefaultView(BUBBLE_USE_EXISTING); + EXPECT_TRUE(IsDisplayVisibleInTray()); + expected = l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroredDisplayName()); + EXPECT_EQ(expected, GetTrayDisplayText()); + EXPECT_EQ(GetTooltipText1(expected), GetTrayDisplayTooltipText()); +} + +TEST_F(TrayDisplayTest, DisplayNotifications) { + UpdateDisplay("400x400"); + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + gfx::Display::SetInternalDisplayId(display_manager->first_display_id()); + EXPECT_FALSE(tray()->HasNotificationBubble()); + + // rotation. + UpdateDisplay("400x400/r"); + EXPECT_TRUE(tray()->HasNotificationBubble()); + base::string16 rotation_message = l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName()); + EXPECT_EQ(rotation_message, GetDisplayNotificationText()); + + CloseNotification(); + UpdateDisplay("400x400"); + EXPECT_TRUE(tray()->HasNotificationBubble()); + EXPECT_EQ(rotation_message, GetDisplayNotificationText()); + + // UI-scale + CloseNotification(); + UpdateDisplay("400x400@1.5"); + EXPECT_TRUE(tray()->HasNotificationBubble()); + EXPECT_EQ( + l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, + GetFirstDisplayName(), UTF8ToUTF16("600x600")), + GetDisplayNotificationText()); + + // UI-scale to 1.0 + CloseNotification(); + UpdateDisplay("400x400"); + EXPECT_TRUE(tray()->HasNotificationBubble()); + EXPECT_EQ( + l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, + GetFirstDisplayName(), UTF8ToUTF16("400x400")), + GetDisplayNotificationText()); + + // No-update + CloseNotification(); + UpdateDisplay("400x400"); + EXPECT_FALSE(tray()->HasNotificationBubble()); + + // Extended. + CloseNotification(); + UpdateDisplay("400x400,200x200"); + EXPECT_TRUE(tray()->HasNotificationBubble()); + EXPECT_EQ( + l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetSecondDisplayName()), + GetDisplayNotificationText()); + + // Mirroring. + CloseNotification(); + display_manager->SetSoftwareMirroring(true); + UpdateDisplay("400x400,200x200"); + EXPECT_TRUE(tray()->HasNotificationBubble()); + EXPECT_EQ( + l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroredDisplayName()), + GetDisplayNotificationText()); + + // Back to extended. + CloseNotification(); + display_manager->SetSoftwareMirroring(false); + UpdateDisplay("400x400,200x200"); + EXPECT_TRUE(tray()->HasNotificationBubble()); + EXPECT_EQ( + l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetSecondDisplayName()), + GetDisplayNotificationText()); + + // Resize the first display. + UpdateDisplay("400x400@1.5,200x200"); + EXPECT_TRUE(tray()->HasNotificationBubble()); + EXPECT_EQ( + l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, + GetFirstDisplayName(), UTF8ToUTF16("600x600")), + GetDisplayNotificationText()); + + // rotate the second. + UpdateDisplay("400x400@1.5,200x200/r"); + EXPECT_TRUE(tray()->HasNotificationBubble()); + EXPECT_EQ( + l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetSecondDisplayName()), + GetDisplayNotificationText()); +} + +} // namespace internal +} // namespace ash diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc index 7c03586..079f135 100644 --- a/ash/test/ash_test_base.cc +++ b/ash/test/ash_test_base.cc @@ -30,6 +30,10 @@ #include "ui/gfx/point.h" #include "ui/gfx/screen.h" +#if defined(OS_CHROMEOS) +#include "ash/system/chromeos/tray_display.h" +#endif + #if defined(OS_WIN) #include "ash/test/test_metro_viewer_process_host.h" #include "base/test/test_process_killer_win.h" @@ -114,6 +118,14 @@ void AshTestBase::SetUp() { Shell::GetPrimaryRootWindow()->MoveCursorTo(gfx::Point(-1000, -1000)); ash::Shell::GetInstance()->cursor_manager()->EnableMouseEvents(); +#if defined(OS_CHROMEOS) + // We do not want to see the notification for display configuration change, + // since it may trap mouse events unexpectedly. + // TODO(mukai): remove this code when the display notification code is moved + // to the message center. + internal::TrayDisplay::SetDisplayNotificationsDisabledForTest(true); +#endif + #if defined(OS_WIN) if (base::win::GetVersion() >= base::win::VERSION_WIN8 && !CommandLine::ForCurrentProcess()->HasSwitch( |