exit_warning_handler.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. #include "ash/accelerators/exit_warning_handler.h"
  5. #include <memory>
  6. #include "ash/public/cpp/shell_window_ids.h"
  7. #include "ash/session/session_controller_impl.h"
  8. #include "ash/shell.h"
  9. #include "ash/strings/grit/ash_strings.h"
  10. #include "base/metrics/user_metrics.h"
  11. #include "base/strings/utf_string_conversions.h"
  12. #include "base/time/time.h"
  13. #include "base/timer/timer.h"
  14. #include "ui/accessibility/ax_enums.mojom.h"
  15. #include "ui/accessibility/ax_node_data.h"
  16. #include "ui/base/l10n/l10n_util.h"
  17. #include "ui/base/resource/resource_bundle.h"
  18. #include "ui/gfx/canvas.h"
  19. #include "ui/gfx/font_list.h"
  20. #include "ui/gfx/text_utils.h"
  21. #include "ui/views/controls/label.h"
  22. #include "ui/views/layout/fill_layout.h"
  23. #include "ui/views/view.h"
  24. #include "ui/views/widget/widget.h"
  25. #include "ui/views/widget/widget_delegate.h"
  26. namespace ash {
  27. namespace {
  28. const int64_t kTimeOutMilliseconds = 2000;
  29. // Color of the text of the warning message.
  30. const SkColor kTextColor = SK_ColorWHITE;
  31. // Color of the window background.
  32. const SkColor kWindowBackgroundColor = SkColorSetARGB(0xC0, 0x0, 0x0, 0x0);
  33. // Radius of the rounded corners of the window.
  34. const int kWindowCornerRadius = 2;
  35. const int kHorizontalMarginAroundText = 100;
  36. const int kVerticalMarginAroundText = 100;
  37. class ExitWarningWidgetDelegateView : public views::WidgetDelegateView {
  38. public:
  39. ExitWarningWidgetDelegateView()
  40. : text_(l10n_util::GetStringUTF16(IDS_ASH_SIGN_OUT_WARNING_POPUP_TEXT)),
  41. accessible_name_(l10n_util::GetStringUTF16(
  42. IDS_ASH_SIGN_OUT_WARNING_POPUP_TEXT_ACCESSIBLE)),
  43. text_width_(0) {
  44. ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
  45. const gfx::FontList& font_list =
  46. rb.GetFontList(ui::ResourceBundle::LargeFont);
  47. text_width_ = gfx::GetStringWidth(text_, font_list);
  48. SetPreferredSize(
  49. gfx::Size(text_width_ + kHorizontalMarginAroundText,
  50. font_list.GetHeight() + kVerticalMarginAroundText));
  51. auto label = std::make_unique<views::Label>();
  52. label->SetText(text_);
  53. label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
  54. label->SetFontList(font_list);
  55. label->SetEnabledColor(kTextColor);
  56. label->SetAutoColorReadabilityEnabled(false);
  57. label->SetSubpixelRenderingEnabled(false);
  58. AddChildView(std::move(label));
  59. SetLayoutManager(std::make_unique<views::FillLayout>());
  60. }
  61. ExitWarningWidgetDelegateView(const ExitWarningWidgetDelegateView&) = delete;
  62. ExitWarningWidgetDelegateView& operator=(
  63. const ExitWarningWidgetDelegateView&) = delete;
  64. void OnPaint(gfx::Canvas* canvas) override {
  65. cc::PaintFlags flags;
  66. flags.setStyle(cc::PaintFlags::kFill_Style);
  67. flags.setColor(kWindowBackgroundColor);
  68. canvas->DrawRoundRect(GetLocalBounds(), kWindowCornerRadius, flags);
  69. views::WidgetDelegateView::OnPaint(canvas);
  70. }
  71. void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
  72. node_data->role = ax::mojom::Role::kAlert;
  73. node_data->SetName(accessible_name_);
  74. }
  75. private:
  76. std::u16string text_;
  77. std::u16string accessible_name_;
  78. int text_width_;
  79. };
  80. } // namespace
  81. ExitWarningHandler::ExitWarningHandler()
  82. : state_(IDLE), stub_timer_for_test_(false) {}
  83. ExitWarningHandler::~ExitWarningHandler() {
  84. // Note: If a timer is outstanding, it is stopped in its destructor.
  85. Hide();
  86. }
  87. void ExitWarningHandler::HandleAccelerator() {
  88. switch (state_) {
  89. case IDLE:
  90. state_ = WAIT_FOR_DOUBLE_PRESS;
  91. Show();
  92. StartTimer();
  93. base::RecordAction(base::UserMetricsAction("Accel_Exit_First_Q"));
  94. break;
  95. case WAIT_FOR_DOUBLE_PRESS:
  96. state_ = EXITING;
  97. CancelTimer();
  98. Hide();
  99. base::RecordAction(base::UserMetricsAction("Accel_Exit_Second_Q"));
  100. Shell::Get()->session_controller()->RequestSignOut();
  101. break;
  102. case EXITING:
  103. break;
  104. }
  105. }
  106. void ExitWarningHandler::TimerAction() {
  107. Hide();
  108. if (state_ == WAIT_FOR_DOUBLE_PRESS)
  109. state_ = IDLE;
  110. }
  111. void ExitWarningHandler::StartTimer() {
  112. if (stub_timer_for_test_)
  113. return;
  114. timer_.Start(FROM_HERE, base::Milliseconds(kTimeOutMilliseconds), this,
  115. &ExitWarningHandler::TimerAction);
  116. }
  117. void ExitWarningHandler::CancelTimer() {
  118. timer_.Stop();
  119. }
  120. void ExitWarningHandler::Show() {
  121. if (widget_)
  122. return;
  123. aura::Window* root_window = Shell::GetRootWindowForNewWindows();
  124. ExitWarningWidgetDelegateView* delegate = new ExitWarningWidgetDelegateView;
  125. gfx::Size rs = root_window->bounds().size();
  126. gfx::Size ps = delegate->GetPreferredSize();
  127. gfx::Rect bounds((rs.width() - ps.width()) / 2,
  128. (rs.height() - ps.height()) / 3, ps.width(), ps.height());
  129. views::Widget::InitParams params;
  130. params.type = views::Widget::InitParams::TYPE_POPUP;
  131. params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
  132. params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  133. params.accept_events = false;
  134. params.z_order = ui::ZOrderLevel::kFloatingUIElement;
  135. params.delegate = delegate;
  136. params.bounds = bounds;
  137. params.name = "ExitWarningWindow";
  138. params.parent =
  139. root_window->GetChildById(kShellWindowId_SettingBubbleContainer);
  140. widget_ = std::make_unique<views::Widget>();
  141. widget_->Init(std::move(params));
  142. widget_->Show();
  143. delegate->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
  144. }
  145. void ExitWarningHandler::Hide() {
  146. widget_.reset();
  147. }
  148. } // namespace ash