background_view.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2010 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 "chrome/browser/chromeos/login/background_view.h"
6
7#include "app/l10n_util.h"
8#include "app/resource_bundle.h"
9#include "app/x11_util.h"
10#include "base/string_util.h"
11#include "base/utf_string_conversions.h"
12#include "chrome/browser/chromeos/login/helper.h"
13#include "chrome/browser/chromeos/status/clock_menu_button.h"
14#include "chrome/browser/chromeos/status/feedback_menu_button.h"
15#include "chrome/browser/chromeos/status/language_menu_button.h"
16#include "chrome/browser/chromeos/status/network_menu_button.h"
17#include "chrome/browser/chromeos/status/status_area_view.h"
18#include "chrome/browser/chromeos/wm_ipc.h"
19#include "cros/chromeos_wm_ipc_enums.h"
20#include "grit/chromium_strings.h"
21#include "grit/generated_resources.h"
22#include "views/controls/label.h"
23#include "views/screen.h"
24#include "views/widget/widget_gtk.h"
25
26// X Windows headers have "#define Status int". That interferes with
27// NetworkLibrary header which defines enum "Status".
28#include <X11/cursorfont.h>
29#include <X11/Xcursor/Xcursor.h>
30
31using views::WidgetGtk;
32
33namespace chromeos {
34
35BackgroundView::BackgroundView()
36    : status_area_(NULL),
37      os_version_label_(NULL),
38      boot_times_label_(NULL),
39      did_paint_(false) {
40  views::Painter* painter = CreateBackgroundPainter();
41  set_background(views::Background::CreateBackgroundPainter(true, painter));
42  InitStatusArea();
43  InitInfoLabels();
44}
45
46static void ResetXCursor() {
47  // TODO(sky): nuke this once new window manager is in place.
48  // This gets rid of the ugly X default cursor.
49  Display* display = x11_util::GetXDisplay();
50  Cursor cursor = XCreateFontCursor(display, XC_left_ptr);
51  XID root_window = x11_util::GetX11RootWindow();
52  XSetWindowAttributes attr;
53  attr.cursor = cursor;
54  XChangeWindowAttributes(display, root_window, CWCursor, &attr);
55}
56
57// static
58views::Widget* BackgroundView::CreateWindowContainingView(
59    const gfx::Rect& bounds,
60    BackgroundView** view) {
61  ResetXCursor();
62
63  WidgetGtk* window = new WidgetGtk(WidgetGtk::TYPE_WINDOW);
64  window->Init(NULL, bounds);
65  *view = new BackgroundView();
66  window->SetContentsView(*view);
67
68  (*view)->UpdateWindowType();
69
70  // This keeps the window from flashing at startup.
71  GdkWindow* gdk_window = window->GetNativeView()->window;
72  gdk_window_set_back_pixmap(gdk_window, NULL, false);
73
74  return window;
75}
76
77void BackgroundView::SetStatusAreaVisible(bool visible) {
78  status_area_->SetVisible(visible);
79}
80
81void BackgroundView::Paint(gfx::Canvas* canvas) {
82  views::View::Paint(canvas);
83  if (!did_paint_) {
84    did_paint_ = true;
85    UpdateWindowType();
86  }
87}
88
89void BackgroundView::Layout() {
90  int corner_padding = 5;
91  int kInfoLeftPadding = 60;
92  int kInfoBottomPadding = 40;
93  int kInfoBetweenLinesPadding = 4;
94  gfx::Size status_area_size = status_area_->GetPreferredSize();
95  status_area_->SetBounds(
96      width() - status_area_size.width() - corner_padding,
97      corner_padding,
98      status_area_size.width(),
99      status_area_size.height());
100  gfx::Size version_size = os_version_label_->GetPreferredSize();
101  os_version_label_->SetBounds(
102      kInfoLeftPadding,
103      height() -
104          ((2 * version_size.height()) +
105          kInfoBottomPadding +
106          kInfoBetweenLinesPadding),
107      width() - 2 * kInfoLeftPadding,
108      version_size.height());
109  boot_times_label_->SetBounds(
110      kInfoLeftPadding,
111      height() - (version_size.height() + kInfoBottomPadding),
112      width() - 2 * corner_padding,
113      version_size.height());
114}
115
116void BackgroundView::ChildPreferredSizeChanged(View* child) {
117  Layout();
118  SchedulePaint();
119}
120
121gfx::NativeWindow BackgroundView::GetNativeWindow() const {
122  return
123      GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
124}
125
126bool BackgroundView::ShouldOpenButtonOptions(
127    const views::View* button_view) const {
128  if (button_view == status_area_->clock_view() ||
129      button_view == status_area_->feedback_view() ||
130      button_view == status_area_->language_view() ||
131      button_view == status_area_->network_view()) {
132    return false;
133  }
134  return true;
135}
136
137void BackgroundView::OpenButtonOptions(const views::View* button_view) const {
138  // TODO(avayvod): Add some dialog for options or remove them completely.
139}
140
141bool BackgroundView::IsButtonVisible(const views::View* button_view) const {
142  if (button_view == status_area_->feedback_view())
143    return false;
144  return true;
145}
146
147bool BackgroundView::IsBrowserMode() const {
148  return false;
149}
150
151bool BackgroundView::IsScreenLockerMode() const {
152  return false;
153}
154
155void BackgroundView::LocaleChanged() {
156  Layout();
157  SchedulePaint();
158}
159
160void BackgroundView::InitStatusArea() {
161  DCHECK(status_area_ == NULL);
162  status_area_ = new StatusAreaView(this);
163  status_area_->Init();
164  AddChildView(status_area_);
165}
166
167void BackgroundView::InitInfoLabels() {
168  const SkColor kVersionColor = 0xff8eb1f4;
169  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
170
171  os_version_label_ = new views::Label();
172  os_version_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
173  os_version_label_->SetColor(kVersionColor);
174  os_version_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
175  AddChildView(os_version_label_);
176  boot_times_label_ = new views::Label();
177  boot_times_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
178  boot_times_label_->SetColor(kVersionColor);
179  boot_times_label_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
180  AddChildView(boot_times_label_);
181
182  if (CrosLibrary::Get()->EnsureLoaded()) {
183    version_loader_.GetVersion(
184        &version_consumer_, NewCallback(this, &BackgroundView::OnVersion));
185    boot_times_loader_.GetBootTimes(
186        &boot_times_consumer_, NewCallback(this, &BackgroundView::OnBootTimes));
187  } else {
188    os_version_label_->SetText(
189        ASCIIToWide(CrosLibrary::Get()->load_error_string()));
190  }
191}
192
193void BackgroundView::UpdateWindowType() {
194  std::vector<int> params;
195  params.push_back(did_paint_ ? 1 : 0);
196  WmIpc::instance()->SetWindowType(
197      GTK_WIDGET(GetNativeWindow()),
198      WM_IPC_WINDOW_LOGIN_BACKGROUND,
199      &params);
200}
201
202void BackgroundView::OnVersion(
203    VersionLoader::Handle handle, std::string version) {
204  // TODO(jungshik): Is string concatenation OK here?
205  std::string version_text = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
206  version_text += ' ';
207  version_text += l10n_util::GetStringUTF8(IDS_VERSION_FIELD_PREFIX);
208  version_text += ' ';
209  version_text += version;
210  os_version_label_->SetText(UTF8ToWide(version_text));
211}
212
213void BackgroundView::OnBootTimes(
214    BootTimesLoader::Handle handle, BootTimesLoader::BootTimes boot_times) {
215  // TODO(davemoore) if we decide to keep these times visible we will need
216  // to localize the strings.
217  const char* kBootTimesNoChromeExec =
218      "Boot took %.2f seconds (firmware %.2fs, kernel %.2fs, system %.2fs)";
219  const char* kBootTimesChromeExec =
220      "Boot took %.2f seconds "
221      "(firmware %.2fs, kernel %.2fs, system %.2fs, chrome %.2fs)";
222  std::string boot_times_text;
223
224  if (boot_times.chrome > 0) {
225    boot_times_text =
226        StringPrintf(
227            kBootTimesChromeExec,
228            boot_times.total,
229            boot_times.firmware,
230            boot_times.pre_startup,
231            boot_times.system,
232            boot_times.chrome);
233  } else {
234    boot_times_text =
235        StringPrintf(
236            kBootTimesNoChromeExec,
237            boot_times.total,
238            boot_times.firmware,
239            boot_times.pre_startup,
240            boot_times.system);
241  }
242  // Use UTF8ToWide once this string is localized.
243  boot_times_label_->SetText(ASCIIToWide(boot_times_text));
244}
245
246}  // namespace chromeos
247