Home | History | Annotate | Download | only in accelerators
      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:
     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 
     71   virtual gfx::Size GetPreferredSize() const OVERRIDE {
     72     return gfx::Size(width_, height_);
     73   }
     74 
     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 
     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 
    100 ExitWarningHandler::ExitWarningHandler()
    101     : state_(IDLE),
    102       stub_timer_for_test_(false) {
    103 }
    104 
    105 ExitWarningHandler::~ExitWarningHandler() {
    106   // Note: If a timer is outstanding, it is stopped in its destructor.
    107   Hide();
    108 }
    109 
    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 
    136 void ExitWarningHandler::TimerAction() {
    137   Hide();
    138   if (state_ == WAIT_FOR_DOUBLE_PRESS)
    139     state_ = IDLE;
    140 }
    141 
    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 
    151 void ExitWarningHandler::CancelTimer() {
    152   timer_.Stop();
    153 }
    154 
    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 
    185 void ExitWarningHandler::Hide() {
    186   widget_.reset();
    187 }
    188 
    189 }  // namespace ash
    190