summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/ash.gyp1
-rw-r--r--ash/ash_strings.grd9
-rw-r--r--ash/system/chromeos/tray_display.cc286
-rw-r--r--ash/system/chromeos/tray_display.h47
-rw-r--r--ash/system/chromeos/tray_display_unittest.cc340
-rw-r--r--ash/test/ash_test_base.cc12
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(