• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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/accelerators/exit_warning_handler.h"
6 
7 #include "ash/metrics/user_metrics_recorder.h"
8 #include "ash/shell.h"
9 #include "ash/shell_delegate.h"
10 #include "ash/shell_window_ids.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/time/time.h"
13 #include "base/timer/timer.h"
14 #include "grit/ash_strings.h"
15 #include "ui/accessibility/ax_view_state.h"
16 #include "ui/aura/window.h"
17 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/font_list.h"
21 #include "ui/gfx/text_utils.h"
22 #include "ui/views/controls/label.h"
23 #include "ui/views/layout/fill_layout.h"
24 #include "ui/views/view.h"
25 #include "ui/views/widget/widget.h"
26 #include "ui/views/widget/widget_delegate.h"
27 
28 namespace ash {
29 namespace {
30 
31 const int64 kTimeOutMilliseconds = 2000;
32 // Color of the text of the warning message.
33 const SkColor kTextColor = SK_ColorWHITE;
34 // Color of the window background.
35 const SkColor kWindowBackgroundColor = SkColorSetARGB(0xC0, 0x0, 0x0, 0x0);
36 // Radius of the rounded corners of the window.
37 const int kWindowCornerRadius = 2;
38 const int kHorizontalMarginAroundText = 100;
39 const int kVerticalMarginAroundText = 100;
40 
41 class ExitWarningWidgetDelegateView : public views::WidgetDelegateView {
42  public:
ExitWarningWidgetDelegateView()43   ExitWarningWidgetDelegateView() : text_width_(0), width_(0), height_(0) {
44 #ifdef OS_CHROMEOS
45     text_ = l10n_util::GetStringUTF16(IDS_ASH_SIGN_OUT_WARNING_POPUP_TEXT);
46     accessible_name_ = l10n_util::GetStringUTF16(
47         IDS_ASH_SIGN_OUT_WARNING_POPUP_TEXT_ACCESSIBLE);
48 #else
49     text_ = l10n_util::GetStringUTF16(IDS_ASH_EXIT_WARNING_POPUP_TEXT);
50     accessible_name_ =
51         l10n_util::GetStringUTF16(IDS_ASH_EXIT_WARNING_POPUP_TEXT_ACCESSIBLE);
52 #endif
53     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
54     const gfx::FontList& font_list =
55         rb.GetFontList(ui::ResourceBundle::LargeFont);
56     text_width_ = gfx::GetStringWidth(text_, font_list);
57     width_ = text_width_ + kHorizontalMarginAroundText;
58     height_ = font_list.GetHeight() + kVerticalMarginAroundText;
59     views::Label* label = new views::Label();
60     label->SetText(text_);
61     label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
62     label->SetFontList(font_list);
63     label->SetEnabledColor(kTextColor);
64     label->SetDisabledColor(kTextColor);
65     label->SetAutoColorReadabilityEnabled(false);
66     label->SetSubpixelRenderingEnabled(false);
67     AddChildView(label);
68     SetLayoutManager(new views::FillLayout);
69   }
70 
GetPreferredSize() const71   virtual gfx::Size GetPreferredSize() const OVERRIDE {
72     return gfx::Size(width_, height_);
73   }
74 
OnPaint(gfx::Canvas * canvas)75   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
76     SkPaint paint;
77     paint.setStyle(SkPaint::kFill_Style);
78     paint.setColor(kWindowBackgroundColor);
79     canvas->DrawRoundRect(GetLocalBounds(), kWindowCornerRadius, paint);
80     views::WidgetDelegateView::OnPaint(canvas);
81   }
82 
GetAccessibleState(ui::AXViewState * state)83   virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE {
84     state->name = accessible_name_;
85     state->role = ui::AX_ROLE_ALERT;
86   }
87 
88  private:
89   base::string16 text_;
90   base::string16 accessible_name_;
91   int text_width_;
92   int width_;
93   int height_;
94 
95   DISALLOW_COPY_AND_ASSIGN(ExitWarningWidgetDelegateView);
96 };
97 
98 }  // namespace
99 
ExitWarningHandler()100 ExitWarningHandler::ExitWarningHandler()
101     : state_(IDLE),
102       stub_timer_for_test_(false) {
103 }
104 
~ExitWarningHandler()105 ExitWarningHandler::~ExitWarningHandler() {
106   // Note: If a timer is outstanding, it is stopped in its destructor.
107   Hide();
108 }
109 
HandleAccelerator()110 void ExitWarningHandler::HandleAccelerator() {
111   ShellDelegate* shell_delegate = Shell::GetInstance()->delegate();
112   switch (state_) {
113     case IDLE:
114       state_ = WAIT_FOR_DOUBLE_PRESS;
115       Show();
116       StartTimer();
117       Shell::GetInstance()->
118           metrics()->RecordUserMetricsAction(UMA_ACCEL_EXIT_FIRST_Q);
119       break;
120     case WAIT_FOR_DOUBLE_PRESS:
121       state_ = EXITING;
122       CancelTimer();
123       Hide();
124       Shell::GetInstance()->
125           metrics()->RecordUserMetricsAction(UMA_ACCEL_EXIT_SECOND_Q);
126       shell_delegate->Exit();
127       break;
128     case EXITING:
129       break;
130     default:
131       NOTREACHED();
132       break;
133   }
134 }
135 
TimerAction()136 void ExitWarningHandler::TimerAction() {
137   Hide();
138   if (state_ == WAIT_FOR_DOUBLE_PRESS)
139     state_ = IDLE;
140 }
141 
StartTimer()142 void ExitWarningHandler::StartTimer() {
143   if (stub_timer_for_test_)
144     return;
145   timer_.Start(FROM_HERE,
146                base::TimeDelta::FromMilliseconds(kTimeOutMilliseconds),
147                this,
148                &ExitWarningHandler::TimerAction);
149 }
150 
CancelTimer()151 void ExitWarningHandler::CancelTimer() {
152   timer_.Stop();
153 }
154 
Show()155 void ExitWarningHandler::Show() {
156   if (widget_)
157     return;
158   aura::Window* root_window = Shell::GetTargetRootWindow();
159   ExitWarningWidgetDelegateView* delegate = new ExitWarningWidgetDelegateView;
160   gfx::Size rs = root_window->bounds().size();
161   gfx::Size ps = delegate->GetPreferredSize();
162   gfx::Rect bounds((rs.width() - ps.width()) / 2,
163                    (rs.height() - ps.height()) / 3,
164                    ps.width(), ps.height());
165   views::Widget::InitParams params;
166   params.type = views::Widget::InitParams::TYPE_POPUP;
167   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
168   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
169   params.accept_events = false;
170   params.keep_on_top = true;
171   params.remove_standard_frame = true;
172   params.delegate = delegate;
173   params.bounds = bounds;
174   params.parent =
175       Shell::GetContainer(root_window, kShellWindowId_SettingBubbleContainer);
176   widget_.reset(new views::Widget);
177   widget_->Init(params);
178   widget_->SetContentsView(delegate);
179   widget_->GetNativeView()->SetName("ExitWarningWindow");
180   widget_->Show();
181 
182   delegate->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
183 }
184 
Hide()185 void ExitWarningHandler::Hide() {
186   widget_.reset();
187 }
188 
189 }  // namespace ash
190