ui::PlatformWindowDelegate::OnClosed() isn't called when a ui::X11Window is closed
[chromium-blink-merge.git] / ash / accelerators / exit_warning_handler.cc
blob275dc5ab9ed5e1634ec470f9a5e36d6e47344f01
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"
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"
28 namespace ash {
29 namespace {
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 ExitWarningWidgetDelegateView : public views::WidgetDelegateView {
42 public:
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);
71 virtual gfx::Size GetPreferredSize() const override {
72 return gfx::Size(width_, height_);
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);
83 virtual void GetAccessibleState(ui::AXViewState* state) override {
84 state->name = accessible_name_;
85 state->role = ui::AX_ROLE_ALERT;
88 private:
89 base::string16 text_;
90 base::string16 accessible_name_;
91 int text_width_;
92 int width_;
93 int height_;
95 DISALLOW_COPY_AND_ASSIGN(ExitWarningWidgetDelegateView);
98 } // namespace
100 ExitWarningHandler::ExitWarningHandler()
101 : state_(IDLE),
102 stub_timer_for_test_(false) {
105 ExitWarningHandler::~ExitWarningHandler() {
106 // Note: If a timer is outstanding, it is stopped in its destructor.
107 Hide();
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;
136 void ExitWarningHandler::TimerAction() {
137 Hide();
138 if (state_ == WAIT_FOR_DOUBLE_PRESS)
139 state_ = IDLE;
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);
151 void ExitWarningHandler::CancelTimer() {
152 timer_.Stop();
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();
182 delegate->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
185 void ExitWarningHandler::Hide() {
186 widget_.reset();
189 } // namespace ash