Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Side by Side Diff: ash/sticky_keys/sticky_keys_overlay.cc

Issue 137373003: Show overlay displaying the state of all sticky keys when it is enabled. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Unit tests for overlay Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 void SetKeyState(StickyKeyState state);
55
56 StickyKeyState state() { return state_; }
James Cook 2014/01/15 22:53:53 nit: const, and usually we put these above the Set
Tim Song 2014/01/16 00:01:59 Done.
57
58 private:
59 virtual void PaintText(gfx::Canvas* canvas,
James Cook 2014/01/15 22:53:53 nit: comment what class you are overriding, like "
Tim Song 2014/01/16 00:01:59 Done.
60 const base::string16& text,
61 const gfx::Rect& text_bounds,
62 int flags) OVERRIDE;
63
64 StickyKeyState state_;
65
66 DISALLOW_COPY_AND_ASSIGN(StickyKeyOverlayLabel);
67 };
68
69 StickyKeyOverlayLabel::StickyKeyOverlayLabel(const std::string& key_name)
70 : state_(STICKY_KEY_STATE_DISABLED) {
71 SetText(base::UTF8ToUTF16(key_name));
72 SetHorizontalAlignment(gfx::ALIGN_LEFT);
73 SetFontList(
74 font_list().DeriveFontListWithSize(18));
75 SetAutoColorReadabilityEnabled(false);
76 SetFocusable(false);
77 SetEnabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
78 SetDisabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
79 set_border(views::Border::CreateEmptyBorder(0, 0, 0, 0));
James Cook 2014/01/15 22:53:53 I'm a bit confused -- this adds an empty, zero-wid
Tim Song 2014/01/16 00:01:59 Done. I wanted to ensure the insets to be zero, bu
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 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
James Cook 2014/01/15 22:53:53 nit: comment what you are overriding
Tim Song 2014/01/16 00:01:59 Done.
128
129 void SetKeyState(StickyKeyModifier modifier, StickyKeyState state);
130
131 StickyKeyState GetKeyState(StickyKeyModifier modifier);
132
133 private:
134 void AddKeyLabel(StickyKeyModifier modifier, const std::string& key_label);
135
136 typedef std::map<StickyKeyModifier, StickyKeyOverlayLabel*> ModifierLabelMap;
137 ModifierLabelMap modifier_label_map_;
138
139 DISALLOW_COPY_AND_ASSIGN(StickyKeysOverlayView);
140 };
141
142 StickyKeysOverlayView::StickyKeysOverlayView() {
143 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
144 kHorizontalBorderSpacing,
145 kVerticalBorderSpacing,
146 kKeyLabelSpacing));
147 AddKeyLabel(STICKY_KEY_CONTROL,
148 l10n_util::GetStringUTF8(IDS_ASH_STICKY_KEY_CONTROL));
149 AddKeyLabel(STICKY_KEY_ALT,
150 l10n_util::GetStringUTF8(IDS_ASH_STICKY_KEY_ALT));
151 AddKeyLabel(STICKY_KEY_SHIFT,
152 l10n_util::GetStringUTF8(IDS_ASH_STICKY_KEY_SHIFT));
153 }
154
155 StickyKeysOverlayView::~StickyKeysOverlayView() {}
156
157 void StickyKeysOverlayView::OnPaint(gfx::Canvas* canvas) {
158 SkPaint paint;
159 paint.setStyle(SkPaint::kFill_Style);
160 paint.setColor(SkColorSetARGB(0xB3, 0x55, 0x55, 0x55));
161 canvas->DrawRoundRect(GetLocalBounds(), 2, paint);
162 views::WidgetDelegateView::OnPaint(canvas);
163 }
164
165 void StickyKeysOverlayView::SetKeyState(StickyKeyModifier modifier,
166 StickyKeyState state) {
167 ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
168 DCHECK(it != modifier_label_map_.end());
169 if (it != modifier_label_map_.end()) {
170 StickyKeyOverlayLabel* label = it->second;
171 label->SetKeyState(state);
172 }
173 }
174
175 StickyKeyState StickyKeysOverlayView::GetKeyState(StickyKeyModifier modifier) {
176 ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
177 DCHECK(it != modifier_label_map_.end());
178 return it->second->state();
179 }
180
181 void StickyKeysOverlayView::AddKeyLabel(StickyKeyModifier modifier,
182 const std::string& key_label) {
183 StickyKeyOverlayLabel* label = new StickyKeyOverlayLabel(key_label);
184 AddChildView(label);
185 modifier_label_map_[modifier] = label;
186 }
187
188 ///////////////////////////////////////////////////////////////////////////////
189 // StickyKeysOverlay
190 StickyKeysOverlay::StickyKeysOverlay()
191 : is_showing_(false),
192 overlay_view_(new StickyKeysOverlayView) {
193 widget_size_ = overlay_view_->GetPreferredSize();
194
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 = gfx::Rect(gfx::Point(0, 0), widget_size_);
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 overlay_widget_->GetLayer()->SetTransform(CalculateOverlayTransform());
215 }
216
217 StickyKeysOverlay::~StickyKeysOverlay() {}
218
219 void StickyKeysOverlay::Show(bool visible) {
220 if (is_showing_ == visible)
221 return;
222
223 is_showing_ = visible;
224 if (is_showing_)
225 overlay_widget_->Show();
226
227 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
228 if (animator)
James Cook 2014/01/15 22:53:53 Is animator ever null? I don't think so, and prob
Tim Song 2014/01/16 00:01:59 Done.
229 animator->AddObserver(this);
230
231 ui::ScopedLayerAnimationSettings settings(animator);
232 settings.SetPreemptionStrategy(
233 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
234 settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
James Cook 2014/01/15 22:53:53 You might want to use EASE_OUT here, or EASE_OUT a
Tim Song 2014/01/16 00:01:59 Done. The mock is using the CSS animation transiti
235 settings.SetTransitionDuration(
236 base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs));
237
238 overlay_widget_->GetLayer()->SetTransform(CalculateOverlayTransform());
239 }
240
241 void StickyKeysOverlay::SetModifierKeyState(StickyKeyModifier modifier,
242 StickyKeyState state) {
243 overlay_view_->SetKeyState(modifier, state);
244 }
245
246 StickyKeyState StickyKeysOverlay::GetModifierKeyState(
247 StickyKeyModifier modifier) {
248 return overlay_view_->GetKeyState(modifier);
249 }
250
251 gfx::Transform StickyKeysOverlay::CalculateOverlayTransform() {
James Cook 2014/01/15 22:53:53 This doesn't seem quite right. It looks like the w
Tim Song 2014/01/16 00:01:59 Done. What about the hidden case? Is it okay to le
James Cook 2014/01/16 00:46:20 I think we generally set it back to the identity t
Tim Song 2014/01/16 01:59:45 Done. The widget bounds is now updated whenever we
252 gfx::Transform transform;
253 if (is_showing_)
254 transform.Translate(kHorizontalBorderSpacing, kVerticalBorderSpacing);
255 else
256 transform.Translate(-widget_size_.width(), kVerticalBorderSpacing);
257 return transform;
258 }
259
260 void StickyKeysOverlay::OnLayerAnimationEnded(
261 ui::LayerAnimationSequence* sequence) {
262 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
263 if (animator)
264 animator->RemoveObserver(this);
265 if (!is_showing_)
266 overlay_widget_->Hide();
267 }
268
269 void StickyKeysOverlay::OnLayerAnimationAborted(
270 ui::LayerAnimationSequence* sequence) {
271 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
272 if (animator)
273 animator->RemoveObserver(this);
274 overlay_widget_->GetLayer()->SetTransform(CalculateOverlayTransform());
275 }
276
277 void StickyKeysOverlay::OnLayerAnimationScheduled(
278 ui::LayerAnimationSequence* sequence) {
279 }
280
281 } // ash
James Cook 2014/01/15 22:53:53 "namespace ash"
Tim Song 2014/01/16 00:01:59 Done.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698