tray_display.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 3// found in the LICENSE file. 4 5#include "ash/system/chromeos/tray_display.h" 6 7#include "ash/display/display_controller.h" 8#include "ash/display/display_manager.h" 9#include "ash/screen_ash.h" 10#include "ash/shell.h" 11#include "ash/system/tray/fixed_sized_image_view.h" 12#include "ash/system/tray/system_tray.h" 13#include "ash/system/tray/system_tray_delegate.h" 14#include "ash/system/tray/tray_constants.h" 15#include "base/chromeos/chromeos_version.h" 16#include "base/utf_string_conversions.h" 17#include "grit/ash_resources.h" 18#include "grit/ash_strings.h" 19#include "ui/aura/env.h" 20#include "ui/base/l10n/l10n_util.h" 21#include "ui/base/resource/resource_bundle.h" 22#include "ui/gfx/image/image.h" 23#include "ui/views/controls/image_view.h" 24#include "ui/views/controls/label.h" 25#include "ui/views/layout/box_layout.h" 26 27#if defined(USE_X11) 28#include "chromeos/display/output_configurator.h" 29#include "ui/base/x/x11_util.h" 30#endif 31 32namespace ash { 33namespace internal { 34 35class DisplayView : public ash::internal::ActionableView { 36 public: 37 explicit DisplayView(user::LoginStatus login_status) 38 : login_status_(login_status) { 39 SetLayoutManager(new 40 views::BoxLayout(views::BoxLayout::kHorizontal, 41 ash::kTrayPopupPaddingHorizontal, 0, 42 ash::kTrayPopupPaddingBetweenItems)); 43 44 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 45 image_ = 46 new ash::internal::FixedSizedImageView(0, ash::kTrayPopupItemHeight); 47 image_->SetImage( 48 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY).ToImageSkia()); 49 AddChildView(image_); 50 label_ = new views::Label(); 51 label_->SetMultiLine(true); 52 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 53 AddChildView(label_); 54 Update(); 55 } 56 57 virtual ~DisplayView() {} 58 59 void Update() { 60#if !defined(USE_X11) 61 SetVisible(false); 62#else 63 chromeos::OutputState state = 64 base::chromeos::IsRunningOnChromeOS() ? 65 Shell::GetInstance()->output_configurator()->output_state() : 66 InferOutputState(); 67 switch (state) { 68 case chromeos::STATE_INVALID: 69 case chromeos::STATE_HEADLESS: 70 case chromeos::STATE_SINGLE: 71 SetVisible(false); 72 return; 73 case chromeos::STATE_DUAL_MIRROR: 74 label_->SetText(l10n_util::GetStringFUTF16( 75 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetExternalDisplayName())); 76 SetVisible(true); 77 return; 78 case chromeos::STATE_DUAL_EXTENDED: 79 label_->SetText(l10n_util::GetStringFUTF16( 80 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetExternalDisplayName())); 81 SetVisible(true); 82 return; 83 } 84 NOTREACHED() << "Unhandled state " << state; 85#endif 86 } 87 88 chromeos::OutputState InferOutputState() const { 89 return Shell::GetScreen()->GetNumDisplays() == 1 ? 90 chromeos::STATE_SINGLE : chromeos::STATE_DUAL_EXTENDED; 91 } 92 93 private: 94 // Returns the name of the currently connected external display. 95 base::string16 GetExternalDisplayName() const { 96 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 97 int64 external_id = display_manager->mirrored_display_id(); 98 99 if (external_id == gfx::Display::kInvalidDisplayID) { 100 int64 internal_display_id = gfx::Display::InternalDisplayId(); 101 int64 first_display_id = display_manager->first_display_id(); 102 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { 103 int64 id = display_manager->GetDisplayAt(i)->id(); 104 if (id != internal_display_id && id != first_display_id) { 105 external_id = id; 106 break; 107 } 108 } 109 } 110 if (external_id != gfx::Display::kInvalidDisplayID) 111 return UTF8ToUTF16(display_manager->GetDisplayNameForId(external_id)); 112 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); 113 } 114 115 // Overridden from ActionableView. 116 virtual bool PerformAction(const ui::Event& event) OVERRIDE { 117 if (login_status_ == ash::user::LOGGED_IN_USER || 118 login_status_ == ash::user::LOGGED_IN_OWNER || 119 login_status_ == ash::user::LOGGED_IN_GUEST) { 120 ash::Shell::GetInstance()->system_tray_delegate()->ShowDisplaySettings(); 121 } 122 123 return true; 124 } 125 126 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE { 127 int label_max_width = bounds().width() - kTrayPopupPaddingHorizontal * 2 - 128 kTrayPopupPaddingBetweenItems - image_->GetPreferredSize().width(); 129 label_->SizeToFit(label_max_width); 130 PreferredSizeChanged(); 131 } 132 133 user::LoginStatus login_status_; 134 views::ImageView* image_; 135 views::Label* label_; 136 137 DISALLOW_COPY_AND_ASSIGN(DisplayView); 138}; 139 140TrayDisplay::TrayDisplay(SystemTray* system_tray) 141 : SystemTrayItem(system_tray), 142 default_(NULL) { 143 Shell::GetScreen()->AddObserver(this); 144#if defined(USE_X11) 145 Shell::GetInstance()->output_configurator()->AddObserver(this); 146#endif 147} 148 149TrayDisplay::~TrayDisplay() { 150 Shell::GetScreen()->RemoveObserver(this); 151#if defined(USE_X11) 152 Shell::GetInstance()->output_configurator()->RemoveObserver(this); 153#endif 154} 155 156views::View* TrayDisplay::CreateDefaultView(user::LoginStatus status) { 157 default_ = new DisplayView(status); 158 return default_; 159} 160 161void TrayDisplay::DestroyDefaultView() { 162 default_ = NULL; 163} 164 165void TrayDisplay::OnDisplayBoundsChanged(const gfx::Display& display) { 166 if (default_) 167 default_->Update(); 168} 169 170void TrayDisplay::OnDisplayAdded(const gfx::Display& new_display) { 171 if (default_) 172 default_->Update(); 173} 174 175void TrayDisplay::OnDisplayRemoved(const gfx::Display& old_display) { 176 if (default_) 177 default_->Update(); 178} 179 180#if defined(OS_CHROMEOS) 181void TrayDisplay::OnDisplayModeChanged() { 182 if (default_) 183 default_->Update(); 184} 185#endif 186 187} // namespace internal 188} // namespace ash 189