Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / ash / sticky_keys / sticky_keys_overlay.cc
1 // Copyright 2014 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/sticky_keys/sticky_keys_overlay.h"
6
7 #include "ash/shell.h"
8 #include "ash/shell_window_ids.h"
9 #include "ash/sticky_keys/sticky_keys_controller.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "grit/ash_strings.h"
13 #include "ui/base/l10n/l10n_util.h"
14 #include "ui/compositor/scoped_layer_animation_settings.h"
15 #include "ui/gfx/canvas.h"
16 #include "ui/gfx/font_list.h"
17 #include "ui/views/border.h"
18 #include "ui/views/controls/label.h"
19 #include "ui/views/layout/box_layout.h"
20 #include "ui/views/view.h"
21 #include "ui/views/widget/widget.h"
22 #include "ui/views/widget/widget_delegate.h"
23
24 namespace ash {
25
26 namespace {
27
28 // Horizontal offset of the overlay from the top left of the screen.
29 const int kHorizontalOverlayOffset = 18;
30
31 // Vertical offset of the overlay from the top left of the screen.
32 const int kVerticalOverlayOffset = 18;
33
34 // Spacing between overlay contents and border.
35 const int kHorizontalBorderSpacing = 9;
36 const int kVerticalBorderSpacing = 4;
37
38 // Spacing between modifier key labels.
39 const int kKeyLabelSpacing = 7;
40
41 // Duration of slide animation when overlay is shown or hidden.
42 const int kSlideAnimationDurationMs = 100;
43
44 }
45
46 ///////////////////////////////////////////////////////////////////////////////
47 //  StickyKeyOverlayLabel
48 class StickyKeyOverlayLabel : public views::Label {
49  public:
50   explicit StickyKeyOverlayLabel(const std::string& key_name);
51
52   virtual ~StickyKeyOverlayLabel();
53
54   StickyKeyState state() const { return state_; }
55
56   void SetKeyState(StickyKeyState state);
57
58  private:
59   // views::Label overrides:
60   virtual void PaintText(gfx::Canvas* canvas,
61                          const base::string16& text,
62                          const gfx::Rect& text_bounds,
63                          int flags) OVERRIDE;
64
65   StickyKeyState state_;
66
67   DISALLOW_COPY_AND_ASSIGN(StickyKeyOverlayLabel);
68 };
69
70 StickyKeyOverlayLabel::StickyKeyOverlayLabel(const std::string& key_name)
71     : state_(STICKY_KEY_STATE_DISABLED) {
72   SetText(base::UTF8ToUTF16(key_name));
73   SetHorizontalAlignment(gfx::ALIGN_LEFT);
74   SetFontList(
75       font_list().DeriveFontListWithSize(18));
76   SetAutoColorReadabilityEnabled(false);
77   SetFocusable(false);
78   SetEnabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
79   SetDisabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
80 }
81
82 StickyKeyOverlayLabel::~StickyKeyOverlayLabel() {
83 }
84
85 void StickyKeyOverlayLabel::SetKeyState(StickyKeyState state) {
86   state_ = state;
87   SkColor label_color;
88   int style;
89   switch (state) {
90     case STICKY_KEY_STATE_ENABLED:
91       style = gfx::Font::NORMAL;
92       label_color = SkColorSetA(enabled_color(), 0xFF);
93       break;
94     case STICKY_KEY_STATE_LOCKED:
95       style = gfx::Font::UNDERLINE;
96       label_color = SkColorSetA(enabled_color(), 0xFF);
97       break;
98     default:
99       style = gfx::Font::NORMAL;
100       label_color = SkColorSetA(enabled_color(), 0x80);
101   }
102
103   SetEnabledColor(label_color);
104   SetDisabledColor(label_color);
105   SetFontList(font_list().DeriveFontListWithSizeDeltaAndStyle(0, style));
106 }
107
108 void StickyKeyOverlayLabel::PaintText(gfx::Canvas* canvas,
109                                       const base::string16& text,
110                                       const gfx::Rect& text_bounds,
111                                       int flags) {
112   views::Label::PaintText(canvas,
113                           text,
114                           text_bounds,
115                           flags | gfx::Canvas::NO_SUBPIXEL_RENDERING);
116 }
117
118
119 ///////////////////////////////////////////////////////////////////////////////
120 //  StickyKeyOverlayLabel
121 class StickyKeysOverlayView : public views::WidgetDelegateView {
122  public:
123   StickyKeysOverlayView();
124
125   virtual ~StickyKeysOverlayView();
126
127   // views::WidgetDelegateView overrides:
128   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
129
130   void SetKeyState(ui::EventFlags modifier, StickyKeyState state);
131
132   StickyKeyState GetKeyState(ui::EventFlags modifier);
133
134  private:
135   void AddKeyLabel(ui::EventFlags modifier, const std::string& key_label);
136
137   typedef std::map<ui::EventFlags, StickyKeyOverlayLabel*> ModifierLabelMap;
138   ModifierLabelMap modifier_label_map_;
139
140   DISALLOW_COPY_AND_ASSIGN(StickyKeysOverlayView);
141 };
142
143 StickyKeysOverlayView::StickyKeysOverlayView() {
144   SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
145                                         kHorizontalBorderSpacing,
146                                         kVerticalBorderSpacing,
147                                         kKeyLabelSpacing));
148   AddKeyLabel(ui::EF_CONTROL_DOWN,
149               l10n_util::GetStringUTF8(IDS_ASH_CONTROL_KEY));
150   AddKeyLabel(ui::EF_ALT_DOWN,
151               l10n_util::GetStringUTF8(IDS_ASH_ALT_KEY));
152   AddKeyLabel(ui::EF_SHIFT_DOWN,
153               l10n_util::GetStringUTF8(IDS_ASH_SHIFT_KEY));
154 }
155
156 StickyKeysOverlayView::~StickyKeysOverlayView() {}
157
158 void StickyKeysOverlayView::OnPaint(gfx::Canvas* canvas) {
159   SkPaint paint;
160   paint.setStyle(SkPaint::kFill_Style);
161   paint.setColor(SkColorSetARGB(0xB3, 0x55, 0x55, 0x55));
162   canvas->DrawRoundRect(GetLocalBounds(), 2, paint);
163   views::WidgetDelegateView::OnPaint(canvas);
164 }
165
166 void StickyKeysOverlayView::SetKeyState(ui::EventFlags modifier,
167                                         StickyKeyState state) {
168   ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
169   DCHECK(it != modifier_label_map_.end());
170   if (it != modifier_label_map_.end()) {
171     StickyKeyOverlayLabel* label = it->second;
172     label->SetKeyState(state);
173   }
174 }
175
176 StickyKeyState StickyKeysOverlayView::GetKeyState(ui::EventFlags modifier) {
177   ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
178   DCHECK(it != modifier_label_map_.end());
179   return it->second->state();
180 }
181
182 void StickyKeysOverlayView::AddKeyLabel(ui::EventFlags modifier,
183                                         const std::string& key_label) {
184   StickyKeyOverlayLabel* label = new StickyKeyOverlayLabel(key_label);
185   AddChildView(label);
186   modifier_label_map_[modifier] = label;
187 }
188
189 ///////////////////////////////////////////////////////////////////////////////
190 //  StickyKeysOverlay
191 StickyKeysOverlay::StickyKeysOverlay()
192     : is_visible_(false),
193       overlay_view_(new StickyKeysOverlayView),
194       widget_size_(overlay_view_->GetPreferredSize()) {
195   views::Widget::InitParams params;
196   params.type = views::Widget::InitParams::TYPE_POPUP;
197   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
198   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
199   params.accept_events = false;
200   params.can_activate = false;
201   params.keep_on_top = true;
202   params.remove_standard_frame = true;
203   params.delegate = overlay_view_;
204   params.bounds = CalculateOverlayBounds();
205   params.parent = Shell::GetContainer(
206       Shell::GetTargetRootWindow(),
207       internal::kShellWindowId_OverlayContainer);
208   overlay_widget_.reset(new views::Widget);
209   overlay_widget_->Init(params);
210   overlay_widget_->SetVisibilityChangedAnimationsEnabled(false);
211   overlay_widget_->SetContentsView(overlay_view_);
212   overlay_widget_->GetNativeView()->SetName("StickyKeysOverlay");
213 }
214
215 StickyKeysOverlay::~StickyKeysOverlay() {}
216
217 void StickyKeysOverlay::Show(bool visible) {
218   if (is_visible_ == visible)
219     return;
220
221   is_visible_ = visible;
222   if (is_visible_)
223     overlay_widget_->Show();
224   overlay_widget_->SetBounds(CalculateOverlayBounds());
225
226   ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
227   animator->AddObserver(this);
228
229   // Ensure transform is correct before beginning animation.
230   if (!animator->is_animating()) {
231     int sign = is_visible_ ? -1 : 1;
232     gfx::Transform transform;
233     transform.Translate(
234         sign * (widget_size_.width() + kHorizontalOverlayOffset), 0);
235     overlay_widget_->GetLayer()->SetTransform(transform);
236   }
237
238   ui::ScopedLayerAnimationSettings settings(animator);
239   settings.SetPreemptionStrategy(
240       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
241   settings.SetTweenType(visible ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN);
242   settings.SetTransitionDuration(
243       base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs));
244
245   overlay_widget_->GetLayer()->SetTransform(gfx::Transform());
246 }
247
248 void StickyKeysOverlay::SetModifierKeyState(ui::EventFlags modifier,
249                                             StickyKeyState state) {
250   overlay_view_->SetKeyState(modifier, state);
251 }
252
253 StickyKeyState StickyKeysOverlay::GetModifierKeyState(
254     ui::EventFlags modifier) {
255   return overlay_view_->GetKeyState(modifier);
256 }
257
258 gfx::Rect StickyKeysOverlay::CalculateOverlayBounds() {
259   int x = is_visible_ ? kHorizontalOverlayOffset : -widget_size_.width();
260   return gfx::Rect(gfx::Point(x, kVerticalOverlayOffset), widget_size_);
261 }
262
263 void StickyKeysOverlay::OnLayerAnimationEnded(
264     ui::LayerAnimationSequence* sequence) {
265   ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
266   if (animator)
267     animator->RemoveObserver(this);
268   if (!is_visible_)
269     overlay_widget_->Hide();
270 }
271
272 void StickyKeysOverlay::OnLayerAnimationAborted(
273     ui::LayerAnimationSequence* sequence) {
274   ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
275   if (animator)
276     animator->RemoveObserver(this);
277 }
278
279 void StickyKeysOverlay::OnLayerAnimationScheduled(
280     ui::LayerAnimationSequence* sequence) {
281 }
282
283 }  // namespace ash