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.
5 #include "ash/accelerators/exit_warning_handler.h"
7 #include "ash/metrics/user_metrics_recorder.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"
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;
41 class ExitWarningLabel
: public views::Label
{
45 virtual ~ExitWarningLabel() {}
48 virtual void PaintText(gfx::Canvas
* canvas
,
49 const base::string16
& text
,
50 const gfx::Rect
& text_bounds
,
52 // Turn off subpixel rendering.
53 views::Label::PaintText(canvas
,
56 flags
| gfx::Canvas::NO_SUBPIXEL_RENDERING
);
59 DISALLOW_COPY_AND_ASSIGN(ExitWarningLabel
);
62 class ExitWarningWidgetDelegateView
: public views::WidgetDelegateView
{
64 ExitWarningWidgetDelegateView() : text_width_(0), width_(0), height_(0) {
65 text_
= l10n_util::GetStringUTF16(IDS_ASH_EXIT_WARNING_POPUP_TEXT
);
67 l10n_util::GetStringUTF16(IDS_ASH_EXIT_WARNING_POPUP_TEXT_ACCESSIBLE
);
68 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
69 const gfx::FontList
& font_list
=
70 rb
.GetFontList(ui::ResourceBundle::LargeFont
);
71 text_width_
= gfx::GetStringWidth(text_
, font_list
);
72 width_
= text_width_
+ kHorizontalMarginAroundText
;
73 height_
= font_list
.GetHeight() + kVerticalMarginAroundText
;
74 views::Label
* label
= new ExitWarningLabel
;
75 label
->SetText(text_
);
76 label
->SetHorizontalAlignment(gfx::ALIGN_CENTER
);
77 label
->SetFontList(font_list
);
78 label
->SetEnabledColor(kTextColor
);
79 label
->SetDisabledColor(kTextColor
);
80 label
->SetAutoColorReadabilityEnabled(false);
82 SetLayoutManager(new views::FillLayout
);
85 virtual gfx::Size
GetPreferredSize() OVERRIDE
{
86 return gfx::Size(width_
, height_
);
89 virtual void OnPaint(gfx::Canvas
* canvas
) OVERRIDE
{
91 paint
.setStyle(SkPaint::kFill_Style
);
92 paint
.setColor(kWindowBackgroundColor
);
93 canvas
->DrawRoundRect(GetLocalBounds(), kWindowCornerRadius
, paint
);
94 views::WidgetDelegateView::OnPaint(canvas
);
97 virtual void GetAccessibleState(ui::AXViewState
* state
) OVERRIDE
{
98 state
->name
= accessible_name_
;
99 state
->role
= ui::AX_ROLE_ALERT
;
103 base::string16 text_
;
104 base::string16 accessible_name_
;
109 DISALLOW_COPY_AND_ASSIGN(ExitWarningWidgetDelegateView
);
114 ExitWarningHandler::ExitWarningHandler()
116 stub_timer_for_test_(false) {
119 ExitWarningHandler::~ExitWarningHandler() {
120 // Note: If a timer is outstanding, it is stopped in its destructor.
124 void ExitWarningHandler::HandleAccelerator() {
125 ShellDelegate
* shell_delegate
= Shell::GetInstance()->delegate();
128 state_
= WAIT_FOR_DOUBLE_PRESS
;
131 Shell::GetInstance()->
132 metrics()->RecordUserMetricsAction(UMA_ACCEL_EXIT_FIRST_Q
);
134 case WAIT_FOR_DOUBLE_PRESS
:
138 Shell::GetInstance()->
139 metrics()->RecordUserMetricsAction(UMA_ACCEL_EXIT_SECOND_Q
);
140 shell_delegate
->Exit();
150 void ExitWarningHandler::TimerAction() {
152 if (state_
== WAIT_FOR_DOUBLE_PRESS
)
156 void ExitWarningHandler::StartTimer() {
157 if (stub_timer_for_test_
)
159 timer_
.Start(FROM_HERE
,
160 base::TimeDelta::FromMilliseconds(kTimeOutMilliseconds
),
162 &ExitWarningHandler::TimerAction
);
165 void ExitWarningHandler::CancelTimer() {
169 void ExitWarningHandler::Show() {
172 aura::Window
* root_window
= Shell::GetTargetRootWindow();
173 ExitWarningWidgetDelegateView
* delegate
= new ExitWarningWidgetDelegateView
;
174 gfx::Size rs
= root_window
->bounds().size();
175 gfx::Size ps
= delegate
->GetPreferredSize();
176 gfx::Rect
bounds((rs
.width() - ps
.width()) / 2,
177 (rs
.height() - ps
.height()) / 3,
178 ps
.width(), ps
.height());
179 views::Widget::InitParams params
;
180 params
.type
= views::Widget::InitParams::TYPE_POPUP
;
181 params
.opacity
= views::Widget::InitParams::TRANSLUCENT_WINDOW
;
182 params
.ownership
= views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
183 params
.accept_events
= false;
184 params
.can_activate
= false;
185 params
.keep_on_top
= true;
186 params
.remove_standard_frame
= true;
187 params
.delegate
= delegate
;
188 params
.bounds
= bounds
;
189 params
.parent
= Shell::GetContainer(
191 internal::kShellWindowId_SettingBubbleContainer
);
192 widget_
.reset(new views::Widget
);
193 widget_
->Init(params
);
194 widget_
->SetContentsView(delegate
);
195 widget_
->GetNativeView()->SetName("ExitWarningWindow");
198 delegate
->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT
, true);
201 void ExitWarningHandler::Hide() {