Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: ash/system/chromeos/tray_display.cc

Issue 16046007: Shows the display info as a popup when a new display is connected. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: PopupDetailedView -> ShowNotificationView Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ash/system/chromeos/tray_display.h ('k') | ash/system/ime/tray_ime.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/system/chromeos/tray_display.h" 5 #include "ash/system/chromeos/tray_display.h"
6 6
7 #include "ash/display/display_controller.h" 7 #include "ash/display/display_controller.h"
8 #include "ash/display/display_manager.h" 8 #include "ash/display/display_manager.h"
9 #include "ash/screen_ash.h"
10 #include "ash/shell.h" 9 #include "ash/shell.h"
11 #include "ash/system/tray/fixed_sized_image_view.h" 10 #include "ash/system/tray/fixed_sized_image_view.h"
12 #include "ash/system/tray/system_tray.h" 11 #include "ash/system/tray/system_tray.h"
13 #include "ash/system/tray/system_tray_delegate.h" 12 #include "ash/system/tray/system_tray_delegate.h"
14 #include "ash/system/tray/tray_constants.h" 13 #include "ash/system/tray/tray_constants.h"
14 #include "ash/system/tray/tray_notification_view.h"
15 #include "base/chromeos/chromeos_version.h" 15 #include "base/chromeos/chromeos_version.h"
16 #include "base/utf_string_conversions.h" 16 #include "base/utf_string_conversions.h"
17 #include "chromeos/display/output_configurator.h"
18 #include "grit/ash_resources.h" 17 #include "grit/ash_resources.h"
19 #include "grit/ash_strings.h" 18 #include "grit/ash_strings.h"
20 #include "ui/aura/env.h"
21 #include "ui/base/l10n/l10n_util.h" 19 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/resource/resource_bundle.h" 20 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/base/x/x11_util.h"
24 #include "ui/gfx/image/image.h"
25 #include "ui/views/controls/image_view.h"
26 #include "ui/views/controls/label.h" 21 #include "ui/views/controls/label.h"
27 #include "ui/views/layout/box_layout.h" 22 #include "ui/views/layout/box_layout.h"
28 23
29 namespace ash { 24 namespace ash {
30 namespace internal { 25 namespace internal {
26 namespace {
31 27
32 class DisplayView : public ash::internal::ActionableView { 28 TrayDisplayMode GetCurrentTrayDisplayMode() {
29 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
30 if (display_manager->GetNumDisplays() > 1)
31 return TRAY_DISPLAY_EXTENDED;
32
33 if (display_manager->IsMirrored())
34 return TRAY_DISPLAY_MIRRORED;
35
36 int64 first_id = display_manager->first_display_id();
37 if (display_manager->HasInternalDisplay() &&
38 !display_manager->IsInternalDisplayId(first_id)) {
39 return TRAY_DISPLAY_DOCKED;
40 }
41
42 return TRAY_DISPLAY_SINGLE;
43 }
44
45 // Returns the name of the currently connected external display.
46 base::string16 GetExternalDisplayName() {
47 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
48 int64 external_id = display_manager->mirrored_display().id();
49
50 if (external_id == gfx::Display::kInvalidDisplayID) {
51 int64 internal_display_id = gfx::Display::InternalDisplayId();
52 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
53 int64 id = display_manager->GetDisplayAt(i)->id();
54 if (id != internal_display_id) {
55 external_id = id;
56 break;
57 }
58 }
59 }
60 if (external_id != gfx::Display::kInvalidDisplayID)
61 return UTF8ToUTF16(display_manager->GetDisplayNameForId(external_id));
62 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME);
63 }
64
65 class DisplayViewBase {
66 public:
67 DisplayViewBase(user::LoginStatus login_status)
68 : login_status_(login_status) {
69 label_ = new views::Label();
70 label_->SetMultiLine(true);
71 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
72 }
73
74 virtual ~DisplayViewBase() {
75 }
76
77 protected:
78 void OpenSettings() {
79 if (login_status_ == ash::user::LOGGED_IN_USER ||
80 login_status_ == ash::user::LOGGED_IN_OWNER ||
81 login_status_ == ash::user::LOGGED_IN_GUEST) {
82 ash::Shell::GetInstance()->system_tray_delegate()->ShowDisplaySettings();
83 }
84 }
85
86 bool UpdateLabelText() {
87 switch (GetCurrentTrayDisplayMode()) {
88 case TRAY_DISPLAY_SINGLE:
89 // TODO(oshima|mukai): Support single display mode for overscan
90 // alignment.
91 return false;
92 case TRAY_DISPLAY_EXTENDED:
93 if (Shell::GetInstance()->display_manager()->HasInternalDisplay()) {
94 label_->SetText(l10n_util::GetStringFUTF16(
95 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetExternalDisplayName()));
96 } else {
97 label_->SetText(l10n_util::GetStringUTF16(
98 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL));
99 }
100 break;
101 case TRAY_DISPLAY_MIRRORED:
102 if (Shell::GetInstance()->display_manager()->HasInternalDisplay()) {
103 label_->SetText(l10n_util::GetStringFUTF16(
104 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetExternalDisplayName()));
105 } else {
106 label_->SetText(l10n_util::GetStringUTF16(
107 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL));
108 }
109 break;
110 case TRAY_DISPLAY_DOCKED:
111 label_->SetText(l10n_util::GetStringUTF16(
112 IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED));
113 break;
114 }
115 return true;
116 }
117
118 views::Label* label() { return label_; }
119
120 private:
121 user::LoginStatus login_status_;
122 views::Label* label_;
123
124 DISALLOW_COPY_AND_ASSIGN(DisplayViewBase);
125 };
126
127 } // namespace
128
129 class DisplayView : public DisplayViewBase,
130 public ash::internal::ActionableView {
33 public: 131 public:
34 explicit DisplayView(user::LoginStatus login_status) 132 explicit DisplayView(user::LoginStatus login_status)
35 : login_status_(login_status) { 133 : DisplayViewBase(login_status) {
36 SetLayoutManager(new 134 SetLayoutManager(new
37 views::BoxLayout(views::BoxLayout::kHorizontal, 135 views::BoxLayout(views::BoxLayout::kHorizontal,
38 ash::kTrayPopupPaddingHorizontal, 0, 136 ash::kTrayPopupPaddingHorizontal, 0,
39 ash::kTrayPopupPaddingBetweenItems)); 137 ash::kTrayPopupPaddingBetweenItems));
40 138
41 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 139 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
42 image_ = 140 image_ =
43 new ash::internal::FixedSizedImageView(0, ash::kTrayPopupItemHeight); 141 new ash::internal::FixedSizedImageView(0, ash::kTrayPopupItemHeight);
44 image_->SetImage( 142 image_->SetImage(
45 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY).ToImageSkia()); 143 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY).ToImageSkia());
46 AddChildView(image_); 144 AddChildView(image_);
47 label_ = new views::Label(); 145 AddChildView(label());
48 label_->SetMultiLine(true);
49 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
50 AddChildView(label_);
51 Update(); 146 Update();
52 } 147 }
53 148
54 virtual ~DisplayView() {} 149 virtual ~DisplayView() {}
55 150
56 void Update() { 151 void Update() {
57 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 152 SetVisible(UpdateLabelText());
58 if (display_manager->num_connected_displays() == 1) {
59 // TODO(oshima|mukai): Support single display mode for overscan alignment.
60 SetVisible(false);
61 return;
62 }
63 SetVisible(true);
64 if (display_manager->IsMirrored()) {
65 label_->SetText(l10n_util::GetStringFUTF16(
66 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetExternalDisplayName()));
67 } else {
68 label_->SetText(l10n_util::GetStringFUTF16(
69 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetExternalDisplayName()));
70 }
71 }
72
73 chromeos::OutputState InferOutputState() const {
74 return Shell::GetScreen()->GetNumDisplays() == 1 ?
75 chromeos::STATE_SINGLE : chromeos::STATE_DUAL_EXTENDED;
76 } 153 }
77 154
78 private: 155 private:
79 // Returns the name of the currently connected external display.
80 base::string16 GetExternalDisplayName() const {
81 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
82 int64 external_id = display_manager->mirrored_display().id();
83
84 if (external_id == gfx::Display::kInvalidDisplayID) {
85 int64 internal_display_id = gfx::Display::InternalDisplayId();
86 int64 first_display_id = display_manager->first_display_id();
87 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
88 int64 id = display_manager->GetDisplayAt(i)->id();
89 if (id != internal_display_id && id != first_display_id) {
90 external_id = id;
91 break;
92 }
93 }
94 }
95 if (external_id != gfx::Display::kInvalidDisplayID)
96 return UTF8ToUTF16(display_manager->GetDisplayNameForId(external_id));
97 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME);
98 }
99
100 // Overridden from ActionableView. 156 // Overridden from ActionableView.
101 virtual bool PerformAction(const ui::Event& event) OVERRIDE { 157 virtual bool PerformAction(const ui::Event& event) OVERRIDE {
102 if (login_status_ == ash::user::LOGGED_IN_USER || 158 OpenSettings();
103 login_status_ == ash::user::LOGGED_IN_OWNER ||
104 login_status_ == ash::user::LOGGED_IN_GUEST) {
105 ash::Shell::GetInstance()->system_tray_delegate()->ShowDisplaySettings();
106 }
107
108 return true; 159 return true;
109 } 160 }
110 161
111 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE { 162 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE {
112 int label_max_width = bounds().width() - kTrayPopupPaddingHorizontal * 2 - 163 int label_max_width = bounds().width() - kTrayPopupPaddingHorizontal * 2 -
113 kTrayPopupPaddingBetweenItems - image_->GetPreferredSize().width(); 164 kTrayPopupPaddingBetweenItems - image_->GetPreferredSize().width();
114 label_->SizeToFit(label_max_width); 165 label()->SizeToFit(label_max_width);
115 PreferredSizeChanged(); 166 PreferredSizeChanged();
116 } 167 }
117 168
118 user::LoginStatus login_status_;
119 views::ImageView* image_; 169 views::ImageView* image_;
120 views::Label* label_;
121 170
122 DISALLOW_COPY_AND_ASSIGN(DisplayView); 171 DISALLOW_COPY_AND_ASSIGN(DisplayView);
123 }; 172 };
124 173
174 class DisplayNotificationView : public DisplayViewBase,
175 public TrayNotificationView {
176 public:
177 DisplayNotificationView(user::LoginStatus login_status,
178 TrayDisplay* tray_item)
179 : DisplayViewBase(login_status),
180 TrayNotificationView(tray_item, IDR_AURA_UBER_TRAY_DISPLAY) {
181 InitView(label());
182 StartAutoCloseTimer(kTrayPopupAutoCloseDelayForTextInSeconds);
183 Update();
184 }
185
186 virtual ~DisplayNotificationView() {}
187
188 void Update() {
189 if (UpdateLabelText())
190 RestartAutoCloseTimer();
191 else
192 owner()->HideNotificationView();
193 }
194
195 // Overridden from TrayNotificationView:
196 virtual void OnClickAction() OVERRIDE {
197 OpenSettings();
198 }
199
200 private:
201 DISALLOW_COPY_AND_ASSIGN(DisplayNotificationView);
202 };
203
125 TrayDisplay::TrayDisplay(SystemTray* system_tray) 204 TrayDisplay::TrayDisplay(SystemTray* system_tray)
126 : SystemTrayItem(system_tray), 205 : SystemTrayItem(system_tray),
127 default_(NULL) { 206 default_(NULL),
128 Shell::GetScreen()->AddObserver(this); 207 notification_(NULL),
129 Shell::GetInstance()->output_configurator()->AddObserver(this); 208 current_mode_(GetCurrentTrayDisplayMode()) {
209 Shell::GetInstance()->display_controller()->AddObserver(this);
130 } 210 }
131 211
132 TrayDisplay::~TrayDisplay() { 212 TrayDisplay::~TrayDisplay() {
133 Shell::GetScreen()->RemoveObserver(this); 213 Shell::GetInstance()->display_controller()->RemoveObserver(this);
134 Shell::GetInstance()->output_configurator()->RemoveObserver(this);
135 } 214 }
136 215
137 views::View* TrayDisplay::CreateDefaultView(user::LoginStatus status) { 216 views::View* TrayDisplay::CreateDefaultView(user::LoginStatus status) {
217 DCHECK(default_ == NULL);
138 default_ = new DisplayView(status); 218 default_ = new DisplayView(status);
139 return default_; 219 return default_;
140 } 220 }
141 221
222 views::View* TrayDisplay::CreateNotificationView(user::LoginStatus status) {
223 DCHECK(notification_ == NULL);
224 notification_ = new DisplayNotificationView(status, this);
225 return notification_;
226 }
227
142 void TrayDisplay::DestroyDefaultView() { 228 void TrayDisplay::DestroyDefaultView() {
143 default_ = NULL; 229 default_ = NULL;
144 } 230 }
145 231
146 void TrayDisplay::OnDisplayBoundsChanged(const gfx::Display& display) { 232 void TrayDisplay::DestroyNotificationView() {
147 if (default_) 233 notification_ = NULL;
148 default_->Update();
149 } 234 }
150 235
151 void TrayDisplay::OnDisplayAdded(const gfx::Display& new_display) { 236 bool TrayDisplay::ShouldShowLauncher() const {
152 if (default_) 237 return false;
153 default_->Update();
154 } 238 }
155 239
156 void TrayDisplay::OnDisplayRemoved(const gfx::Display& old_display) { 240 void TrayDisplay::OnDisplayConfigurationChanged() {
157 if (default_) 241 TrayDisplayMode new_mode = GetCurrentTrayDisplayMode();
158 default_->Update(); 242 if (current_mode_ != new_mode && new_mode != TRAY_DISPLAY_SINGLE) {
243 if (notification_)
244 notification_->Update();
245 else
246 ShowNotificationView();
247 }
248 current_mode_ = new_mode;
159 } 249 }
160 250
161 #if defined(OS_CHROMEOS)
162 void TrayDisplay::OnDisplayModeChanged() {
163 if (default_)
164 default_->Update();
165 }
166 #endif
167
168 } // namespace internal 251 } // namespace internal
169 } // namespace ash 252 } // namespace ash
OLDNEW
« no previous file with comments | « ash/system/chromeos/tray_display.h ('k') | ash/system/ime/tray_ime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698