summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/ash.gyp5
-rw-r--r--ash/ash_strings.grd12
-rw-r--r--ash/sticky_keys/sticky_keys_controller.cc101
-rw-r--r--ash/sticky_keys/sticky_keys_controller.h34
-rw-r--r--ash/sticky_keys/sticky_keys_overlay.cc283
-rw-r--r--ash/sticky_keys/sticky_keys_overlay.h71
-rw-r--r--ash/sticky_keys/sticky_keys_overlay_unittest.cc206
-rw-r--r--ash/sticky_keys/sticky_keys_state.h25
-rw-r--r--ash/sticky_keys/sticky_keys_unittest.cc114
9 files changed, 740 insertions, 111 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index fb332ba..439d41d 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -251,8 +251,11 @@
'shell_delegate.h',
'shell_factory.h',
'shell_window_ids.h',
+ 'sticky_keys/sticky_keys_state.h',
'sticky_keys/sticky_keys_controller.cc',
'sticky_keys/sticky_keys_controller.h',
+ 'sticky_keys/sticky_keys_overlay.cc',
+ 'sticky_keys/sticky_keys_overlay.h',
'system/bluetooth/bluetooth_observer.h',
'system/bluetooth/tray_bluetooth.cc',
'system/bluetooth/tray_bluetooth.h',
@@ -875,6 +878,7 @@
'shell/window_watcher_shelf_item_delegate.h',
'shell/window_watcher_unittest.cc',
'shell_unittest.cc',
+ 'sticky_keys/sticky_keys_overlay_unittest.cc',
'sticky_keys/sticky_keys_unittest.cc',
'system/chromeos/managed/tray_locally_managed_user_unittest.cc',
'system/chromeos/network/network_state_notifier_unittest.cc',
@@ -951,6 +955,7 @@
['exclude', 'ash_root_window_transformer_unittest.cc'],
['exclude', 'magnifier/magnification_controller_unittest.cc'],
['exclude', 'wm/workspace/workspace_window_resizer_unittest.cc'],
+ ['exclude', 'sticky_keys/sticky_keys_overlay_unittest.cc'],
['exclude', 'sticky_keys/sticky_keys_unittest.cc'],
['exclude', 'autoclick/autoclick_unittest.cc'],
],
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index c51d882..dfab164 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -598,6 +598,18 @@ Press Shift + Alt to switch.
<message name="IDS_ASH_LOGOUT_CONFIRMATION_BUTTON" desc="The text for okay button of the logout confirmation dialog.">
Sign out now
</message>
+ <message name="IDS_ASH_CONTROL_KEY" desc="Name of [Ctrl] key name. Shouldn't be translated in many languages actually. This name should be lower case.">
+ ctrl
+ </message>
+ <message name="IDS_ASH_SHIFT_KEY" desc="Name of [Shift] key. Shouldn't be translated in many languages actually. This name should be lower case.">
+ shift
+ </message>
+ <message name="IDS_ASH_ALT_KEY" desc="Name of [Alt] key name. Shouldn't be translated in many languages actually. This name should be lower case.">
+ alt
+ </message>
+ <message name="IDS_ASH_SEARCH_KEY" desc="Name of [Search] key name. Shouldn't be translated in many languages actually. This name should be lower case.">
+ search
+ </message>
<!-- ChromeOS-specific strings -->
<if expr="pp_ifdef('chromeos')">
diff --git a/ash/sticky_keys/sticky_keys_controller.cc b/ash/sticky_keys/sticky_keys_controller.cc
index aad1ee4..abb7906 100644
--- a/ash/sticky_keys/sticky_keys_controller.cc
+++ b/ash/sticky_keys/sticky_keys_controller.cc
@@ -10,6 +10,7 @@
#undef RootWindow
#endif
+#include "ash/sticky_keys/sticky_keys_overlay.h"
#include "base/basictypes.h"
#include "base/debug/stack_trace.h"
#include "ui/aura/root_window.h"
@@ -89,16 +90,7 @@ void StickyKeysHandlerDelegateImpl::DispatchScrollEvent(
///////////////////////////////////////////////////////////////////////////////
// StickyKeys
StickyKeysController::StickyKeysController()
- : enabled_(false),
- shift_sticky_key_(
- new StickyKeysHandler(ui::EF_SHIFT_DOWN,
- new StickyKeysHandlerDelegateImpl())),
- alt_sticky_key_(
- new StickyKeysHandler(ui::EF_ALT_DOWN,
- new StickyKeysHandlerDelegateImpl())),
- ctrl_sticky_key_(
- new StickyKeysHandler(ui::EF_CONTROL_DOWN,
- new StickyKeysHandlerDelegateImpl())) {
+ : enabled_(false) {
}
StickyKeysController::~StickyKeysController() {
@@ -113,13 +105,17 @@ void StickyKeysController::Enable(bool enabled) {
if (enabled_) {
shift_sticky_key_.reset(
new StickyKeysHandler(ui::EF_SHIFT_DOWN,
- new StickyKeysHandlerDelegateImpl()));
+ new StickyKeysHandlerDelegateImpl()));
alt_sticky_key_.reset(
new StickyKeysHandler(ui::EF_ALT_DOWN,
new StickyKeysHandlerDelegateImpl()));
ctrl_sticky_key_.reset(
new StickyKeysHandler(ui::EF_CONTROL_DOWN,
new StickyKeysHandlerDelegateImpl()));
+
+ overlay_.reset(new StickyKeysOverlay());
+ } else if (overlay_.get()) {
+ overlay_->Show(false);
}
}
}
@@ -149,26 +145,55 @@ void StickyKeysController::OnKeyEvent(ui::KeyEvent* event) {
return;
}
- if (enabled_ && HandleKeyEvent(event))
- event->StopPropagation();
+ if (enabled_) {
+ if (HandleKeyEvent(event))
+ event->StopPropagation();
+ UpdateOverlay();
+ }
}
void StickyKeysController::OnMouseEvent(ui::MouseEvent* event) {
- if (enabled_ && HandleMouseEvent(event))
- event->StopPropagation();
+ if (enabled_) {
+ if (HandleMouseEvent(event))
+ event->StopPropagation();
+ UpdateOverlay();
+ }
}
void StickyKeysController::OnScrollEvent(ui::ScrollEvent* event) {
- if (enabled_ && HandleScrollEvent(event))
- event->StopPropagation();
+ if (enabled_) {
+ if (HandleScrollEvent(event))
+ event->StopPropagation();
+ UpdateOverlay();
+ }
+}
+
+void StickyKeysController::UpdateOverlay() {
+ overlay_->SetModifierKeyState(
+ ui::EF_SHIFT_DOWN, shift_sticky_key_->current_state());
+ overlay_->SetModifierKeyState(
+ ui::EF_CONTROL_DOWN, ctrl_sticky_key_->current_state());
+ overlay_->SetModifierKeyState(
+ ui::EF_ALT_DOWN, alt_sticky_key_->current_state());
+
+ bool key_in_use =
+ shift_sticky_key_->current_state() != STICKY_KEY_STATE_DISABLED ||
+ alt_sticky_key_->current_state() != STICKY_KEY_STATE_DISABLED ||
+ ctrl_sticky_key_->current_state() != STICKY_KEY_STATE_DISABLED;
+
+ overlay_->Show(enabled_ && key_in_use);
+}
+
+StickyKeysOverlay* StickyKeysController::GetOverlayForTest() {
+ return overlay_.get();
}
///////////////////////////////////////////////////////////////////////////////
// StickyKeysHandler
-StickyKeysHandler::StickyKeysHandler(ui::EventFlags target_modifier_flag,
+StickyKeysHandler::StickyKeysHandler(ui::EventFlags modifier_flag,
StickyKeysHandlerDelegate* delegate)
- : modifier_flag_(target_modifier_flag),
- current_state_(DISABLED),
+ : modifier_flag_(modifier_flag),
+ current_state_(STICKY_KEY_STATE_DISABLED),
event_from_myself_(false),
preparing_to_enable_(false),
scroll_delta_(0),
@@ -188,11 +213,11 @@ bool StickyKeysHandler::HandleKeyEvent(ui::KeyEvent* event) {
if (event_from_myself_)
return false; // Do not handle self-generated key event.
switch (current_state_) {
- case DISABLED:
+ case STICKY_KEY_STATE_DISABLED:
return HandleDisabledState(event);
- case ENABLED:
+ case STICKY_KEY_STATE_ENABLED:
return HandleEnabledState(event);
- case LOCKED:
+ case STICKY_KEY_STATE_LOCKED:
return HandleLockedState(event);
}
NOTREACHED();
@@ -203,16 +228,18 @@ bool StickyKeysHandler::HandleMouseEvent(ui::MouseEvent* event) {
if (ShouldModifyMouseEvent(event))
preparing_to_enable_ = false;
- if (event_from_myself_ || current_state_ == DISABLED
+ if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED
|| !ShouldModifyMouseEvent(event)) {
return false;
}
- DCHECK(current_state_ == ENABLED || current_state_ == LOCKED);
+ DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED ||
+ current_state_ == STICKY_KEY_STATE_LOCKED);
AppendModifier(event);
// Only disable on the mouse released event in normal, non-locked mode.
- if (current_state_ == ENABLED && event->type() != ui::ET_MOUSE_PRESSED) {
- current_state_ = DISABLED;
+ if (current_state_ == STICKY_KEY_STATE_ENABLED &&
+ event->type() != ui::ET_MOUSE_PRESSED) {
+ current_state_ = STICKY_KEY_STATE_DISABLED;
DispatchEventAndReleaseModifier(event);
return true;
}
@@ -222,14 +249,16 @@ bool StickyKeysHandler::HandleMouseEvent(ui::MouseEvent* event) {
bool StickyKeysHandler::HandleScrollEvent(ui::ScrollEvent* event) {
preparing_to_enable_ = false;
- if (event_from_myself_ || current_state_ == DISABLED)
+ if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED)
return false;
- DCHECK(current_state_ == ENABLED || current_state_ == LOCKED);
+ DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED ||
+ current_state_ == STICKY_KEY_STATE_LOCKED);
// We detect a direction change if the current |scroll_delta_| is assigned
// and the offset of the current scroll event has the opposing sign.
bool direction_changed = false;
- if (current_state_ == ENABLED && event->type() == ui::ET_SCROLL) {
+ if (current_state_ == STICKY_KEY_STATE_ENABLED &&
+ event->type() == ui::ET_SCROLL) {
int offset = event->y_offset();
if (scroll_delta_)
direction_changed = offset * scroll_delta_ <= 0;
@@ -242,9 +271,9 @@ bool StickyKeysHandler::HandleScrollEvent(ui::ScrollEvent* event) {
// We want to modify all the scroll events in the scroll sequence, which ends
// with a fling start event. We also stop when the scroll sequence changes
// direction.
- if (current_state_ == ENABLED &&
+ if (current_state_ == STICKY_KEY_STATE_ENABLED &&
(event->type() == ui::ET_SCROLL_FLING_START || direction_changed)) {
- current_state_ = DISABLED;
+ current_state_ = STICKY_KEY_STATE_DISABLED;
scroll_delta_ = 0;
DispatchEventAndReleaseModifier(event);
return true;
@@ -287,7 +316,7 @@ bool StickyKeysHandler::HandleDisabledState(ui::KeyEvent* event) {
if (preparing_to_enable_) {
preparing_to_enable_ = false;
scroll_delta_ = 0;
- current_state_ = ENABLED;
+ current_state_ = STICKY_KEY_STATE_ENABLED;
modifier_up_event_.reset(new ui::KeyEvent(*event));
return true;
}
@@ -313,11 +342,11 @@ bool StickyKeysHandler::HandleEnabledState(ui::KeyEvent* event) {
case TARGET_MODIFIER_DOWN:
return true;
case TARGET_MODIFIER_UP:
- current_state_ = LOCKED;
+ current_state_ = STICKY_KEY_STATE_LOCKED;
modifier_up_event_.reset();
return true;
case NORMAL_KEY_DOWN: {
- current_state_ = DISABLED;
+ current_state_ = STICKY_KEY_STATE_DISABLED;
AppendModifier(event);
DispatchEventAndReleaseModifier(event);
return true;
@@ -335,7 +364,7 @@ bool StickyKeysHandler::HandleLockedState(ui::KeyEvent* event) {
case TARGET_MODIFIER_DOWN:
return true;
case TARGET_MODIFIER_UP:
- current_state_ = DISABLED;
+ current_state_ = STICKY_KEY_STATE_DISABLED;
return false;
case NORMAL_KEY_DOWN:
case NORMAL_KEY_UP:
diff --git a/ash/sticky_keys/sticky_keys_controller.h b/ash/sticky_keys/sticky_keys_controller.h
index c31eebd..bb75770 100644
--- a/ash/sticky_keys/sticky_keys_controller.h
+++ b/ash/sticky_keys/sticky_keys_controller.h
@@ -6,6 +6,7 @@
#define ASH_STICKY_KEYS_STICKY_KEYS_CONTROLLER_H_
#include "ash/ash_export.h"
+#include "ash/sticky_keys/sticky_keys_state.h"
#include "base/memory/scoped_ptr.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_handler.h"
@@ -22,6 +23,7 @@ class Window;
namespace ash {
+class StickyKeysOverlay;
class StickyKeysHandler;
// StickyKeysController is an accessibility feature for users to be able to
@@ -65,6 +67,15 @@ class ASH_EXPORT StickyKeysController : public ui::EventHandler {
// Activate sticky keys to intercept and modify incoming events.
void Enable(bool enabled);
+ // Overridden from ui::EventHandler:
+ virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
+ virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
+
+ // Returns the StickyKeyOverlay used by the controller. Ownership is not
+ // passed.
+ StickyKeysOverlay* GetOverlayForTest();
+
private:
// Handles keyboard event. Returns true if Sticky key consumes keyboard event.
bool HandleKeyEvent(ui::KeyEvent* event);
@@ -75,10 +86,8 @@ class ASH_EXPORT StickyKeysController : public ui::EventHandler {
// Handles scroll event. Returns true if sticky key consumes scroll event.
bool HandleScrollEvent(ui::ScrollEvent* event);
- // Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
- virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
+ // Updates the overlay UI with the current state of the sticky keys.
+ void UpdateOverlay();
// Whether sticky keys is activated and modifying events.
bool enabled_;
@@ -88,6 +97,8 @@ class ASH_EXPORT StickyKeysController : public ui::EventHandler {
scoped_ptr<StickyKeysHandler> alt_sticky_key_;
scoped_ptr<StickyKeysHandler> ctrl_sticky_key_;
+ scoped_ptr<StickyKeysOverlay> overlay_;
+
DISALLOW_COPY_AND_ASSIGN(StickyKeysController);
};
@@ -139,19 +150,6 @@ class ASH_EXPORT StickyKeysHandler {
virtual void DispatchScrollEvent(ui::ScrollEvent* event,
aura::Window* target) = 0;
};
- // Represents Sticky Key state.
- enum StickyKeyState {
- // The sticky key is disabled. Incomming non modifier key events are not
- // affected.
- DISABLED,
- // The sticky key is enabled. Incomming non modifier key down events are
- // modified with |modifier_flag_|. After that, sticky key state become
- // DISABLED.
- ENABLED,
- // The sticky key is locked. Incomming non modifier key down events are
- // modified with |modifier_flag_|.
- LOCKED,
- };
// This class takes an ownership of |delegate|.
StickyKeysHandler(ui::EventFlags modifier_flag,
@@ -207,7 +205,7 @@ class ASH_EXPORT StickyKeysHandler {
void AppendModifier(ui::MouseEvent* event);
void AppendModifier(ui::ScrollEvent* event);
- // The modifier flag to be monitored and appended.
+ // The modifier flag to be monitored and appended to events.
const ui::EventFlags modifier_flag_;
// The current sticky key status.
diff --git a/ash/sticky_keys/sticky_keys_overlay.cc b/ash/sticky_keys/sticky_keys_overlay.cc
new file mode 100644
index 0000000..19e5acb
--- /dev/null
+++ b/ash/sticky_keys/sticky_keys_overlay.cc
@@ -0,0 +1,283 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/sticky_keys/sticky_keys_overlay.h"
+
+#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
+#include "ash/sticky_keys/sticky_keys_controller.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "grit/ash_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font_list.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+
+namespace ash {
+
+namespace {
+
+// Horizontal offset of the overlay from the top left of the screen.
+const int kHorizontalOverlayOffset = 18;
+
+// Vertical offset of the overlay from the top left of the screen.
+const int kVerticalOverlayOffset = 18;
+
+// Spacing between overlay contents and border.
+const int kHorizontalBorderSpacing = 9;
+const int kVerticalBorderSpacing = 4;
+
+// Spacing between modifier key labels.
+const int kKeyLabelSpacing = 7;
+
+// Duration of slide animation when overlay is shown or hidden.
+const int kSlideAnimationDurationMs = 100;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StickyKeyOverlayLabel
+class StickyKeyOverlayLabel : public views::Label {
+ public:
+ explicit StickyKeyOverlayLabel(const std::string& key_name);
+
+ virtual ~StickyKeyOverlayLabel();
+
+ StickyKeyState state() const { return state_; }
+
+ void SetKeyState(StickyKeyState state);
+
+ private:
+ // views::Label overrides:
+ virtual void PaintText(gfx::Canvas* canvas,
+ const base::string16& text,
+ const gfx::Rect& text_bounds,
+ int flags) OVERRIDE;
+
+ StickyKeyState state_;
+
+ DISALLOW_COPY_AND_ASSIGN(StickyKeyOverlayLabel);
+};
+
+StickyKeyOverlayLabel::StickyKeyOverlayLabel(const std::string& key_name)
+ : state_(STICKY_KEY_STATE_DISABLED) {
+ SetText(base::UTF8ToUTF16(key_name));
+ SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ SetFontList(
+ font_list().DeriveFontListWithSize(18));
+ SetAutoColorReadabilityEnabled(false);
+ SetFocusable(false);
+ SetEnabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
+ SetDisabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
+}
+
+StickyKeyOverlayLabel::~StickyKeyOverlayLabel() {
+}
+
+void StickyKeyOverlayLabel::SetKeyState(StickyKeyState state) {
+ state_ = state;
+ SkColor label_color;
+ int style;
+ switch (state) {
+ case STICKY_KEY_STATE_ENABLED:
+ style = gfx::Font::NORMAL;
+ label_color = SkColorSetA(enabled_color(), 0xFF);
+ break;
+ case STICKY_KEY_STATE_LOCKED:
+ style = gfx::Font::UNDERLINE;
+ label_color = SkColorSetA(enabled_color(), 0xFF);
+ break;
+ default:
+ style = gfx::Font::NORMAL;
+ label_color = SkColorSetA(enabled_color(), 0x80);
+ }
+
+ SetEnabledColor(label_color);
+ SetDisabledColor(label_color);
+ SetFontList(font_list().DeriveFontListWithSizeDeltaAndStyle(0, style));
+}
+
+void StickyKeyOverlayLabel::PaintText(gfx::Canvas* canvas,
+ const base::string16& text,
+ const gfx::Rect& text_bounds,
+ int flags) {
+ views::Label::PaintText(canvas,
+ text,
+ text_bounds,
+ flags | gfx::Canvas::NO_SUBPIXEL_RENDERING);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// StickyKeyOverlayLabel
+class StickyKeysOverlayView : public views::WidgetDelegateView {
+ public:
+ StickyKeysOverlayView();
+
+ virtual ~StickyKeysOverlayView();
+
+ // views::WidgetDelegateView overrides:
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
+
+ void SetKeyState(ui::EventFlags modifier, StickyKeyState state);
+
+ StickyKeyState GetKeyState(ui::EventFlags modifier);
+
+ private:
+ void AddKeyLabel(ui::EventFlags modifier, const std::string& key_label);
+
+ typedef std::map<ui::EventFlags, StickyKeyOverlayLabel*> ModifierLabelMap;
+ ModifierLabelMap modifier_label_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(StickyKeysOverlayView);
+};
+
+StickyKeysOverlayView::StickyKeysOverlayView() {
+ SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
+ kHorizontalBorderSpacing,
+ kVerticalBorderSpacing,
+ kKeyLabelSpacing));
+ AddKeyLabel(ui::EF_CONTROL_DOWN,
+ l10n_util::GetStringUTF8(IDS_ASH_CONTROL_KEY));
+ AddKeyLabel(ui::EF_ALT_DOWN,
+ l10n_util::GetStringUTF8(IDS_ASH_ALT_KEY));
+ AddKeyLabel(ui::EF_SHIFT_DOWN,
+ l10n_util::GetStringUTF8(IDS_ASH_SHIFT_KEY));
+}
+
+StickyKeysOverlayView::~StickyKeysOverlayView() {}
+
+void StickyKeysOverlayView::OnPaint(gfx::Canvas* canvas) {
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(SkColorSetARGB(0xB3, 0x55, 0x55, 0x55));
+ canvas->DrawRoundRect(GetLocalBounds(), 2, paint);
+ views::WidgetDelegateView::OnPaint(canvas);
+}
+
+void StickyKeysOverlayView::SetKeyState(ui::EventFlags modifier,
+ StickyKeyState state) {
+ ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
+ DCHECK(it != modifier_label_map_.end());
+ if (it != modifier_label_map_.end()) {
+ StickyKeyOverlayLabel* label = it->second;
+ label->SetKeyState(state);
+ }
+}
+
+StickyKeyState StickyKeysOverlayView::GetKeyState(ui::EventFlags modifier) {
+ ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
+ DCHECK(it != modifier_label_map_.end());
+ return it->second->state();
+}
+
+void StickyKeysOverlayView::AddKeyLabel(ui::EventFlags modifier,
+ const std::string& key_label) {
+ StickyKeyOverlayLabel* label = new StickyKeyOverlayLabel(key_label);
+ AddChildView(label);
+ modifier_label_map_[modifier] = label;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StickyKeysOverlay
+StickyKeysOverlay::StickyKeysOverlay()
+ : is_visible_(false),
+ overlay_view_(new StickyKeysOverlayView),
+ widget_size_(overlay_view_->GetPreferredSize()) {
+ views::Widget::InitParams params;
+ params.type = views::Widget::InitParams::TYPE_POPUP;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.accept_events = false;
+ params.can_activate = false;
+ params.keep_on_top = true;
+ params.remove_standard_frame = true;
+ params.delegate = overlay_view_;
+ params.bounds = CalculateOverlayBounds();
+ params.parent = Shell::GetContainer(
+ Shell::GetTargetRootWindow(),
+ internal::kShellWindowId_OverlayContainer);
+ overlay_widget_.reset(new views::Widget);
+ overlay_widget_->Init(params);
+ overlay_widget_->SetVisibilityChangedAnimationsEnabled(false);
+ overlay_widget_->SetContentsView(overlay_view_);
+ overlay_widget_->GetNativeView()->SetName("StickyKeysOverlay");
+}
+
+StickyKeysOverlay::~StickyKeysOverlay() {}
+
+void StickyKeysOverlay::Show(bool visible) {
+ if (is_visible_ == visible)
+ return;
+
+ is_visible_ = visible;
+ if (is_visible_)
+ overlay_widget_->Show();
+ overlay_widget_->SetBounds(CalculateOverlayBounds());
+
+ ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
+ animator->AddObserver(this);
+
+ // Ensure transform is correct before beginning animation.
+ if (!animator->is_animating()) {
+ int sign = is_visible_ ? -1 : 1;
+ gfx::Transform transform;
+ transform.Translate(
+ sign * (widget_size_.width() + kHorizontalOverlayOffset), 0);
+ overlay_widget_->GetLayer()->SetTransform(transform);
+ }
+
+ ui::ScopedLayerAnimationSettings settings(animator);
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ settings.SetTweenType(visible ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN);
+ settings.SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs));
+
+ overlay_widget_->GetLayer()->SetTransform(gfx::Transform());
+}
+
+void StickyKeysOverlay::SetModifierKeyState(ui::EventFlags modifier,
+ StickyKeyState state) {
+ overlay_view_->SetKeyState(modifier, state);
+}
+
+StickyKeyState StickyKeysOverlay::GetModifierKeyState(
+ ui::EventFlags modifier) {
+ return overlay_view_->GetKeyState(modifier);
+}
+
+gfx::Rect StickyKeysOverlay::CalculateOverlayBounds() {
+ int x = is_visible_ ? kHorizontalOverlayOffset : -widget_size_.width();
+ return gfx::Rect(gfx::Point(x, kVerticalOverlayOffset), widget_size_);
+}
+
+void StickyKeysOverlay::OnLayerAnimationEnded(
+ ui::LayerAnimationSequence* sequence) {
+ ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
+ if (animator)
+ animator->RemoveObserver(this);
+ if (!is_visible_)
+ overlay_widget_->Hide();
+}
+
+void StickyKeysOverlay::OnLayerAnimationAborted(
+ ui::LayerAnimationSequence* sequence) {
+ ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
+ if (animator)
+ animator->RemoveObserver(this);
+}
+
+void StickyKeysOverlay::OnLayerAnimationScheduled(
+ ui::LayerAnimationSequence* sequence) {
+}
+
+} // namespace ash
diff --git a/ash/sticky_keys/sticky_keys_overlay.h b/ash/sticky_keys/sticky_keys_overlay.h
new file mode 100644
index 0000000..88d195a
--- /dev/null
+++ b/ash/sticky_keys/sticky_keys_overlay.h
@@ -0,0 +1,71 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_STICKY_KEYS_STICKY_KEYS_OVERLAY_H_
+#define ASH_STICKY_KEYS_STICKY_KEYS_OVERLAY_H_
+
+#include "ash/ash_export.h"
+#include "ash/sticky_keys/sticky_keys_state.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/compositor/layer_animation_observer.h"
+#include "ui/events/event_constants.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace gfx {
+class Rect;
+}
+
+namespace views {
+class Widget;
+}
+
+namespace ash {
+
+class StickyKeysOverlayView;
+
+// Controls the overlay UI for sticky keys, an accessibility feature allowing
+// use of modifier keys without holding them down. This overlay will appear as
+// a transparent window on the top left of the screen, showing the state of
+// each sticky key modifier.
+class ASH_EXPORT StickyKeysOverlay : public ui::LayerAnimationObserver {
+ public:
+ StickyKeysOverlay();
+ virtual ~StickyKeysOverlay();
+
+ // Shows or hides the overlay.
+ void Show(bool visible);
+
+ // Updates the overlay with the current state of a sticky key modifier.
+ void SetModifierKeyState(ui::EventFlags modifier,
+ StickyKeyState state);
+
+ // Get the current state of the sticky key modifier in the overlay.
+ StickyKeyState GetModifierKeyState(ui::EventFlags modifier);
+
+ // Returns true if the overlay is currently visible. If the overlay is
+ // animating, the returned value is the target of the animation.
+ bool is_visible() { return is_visible_; }
+
+ private:
+ // Returns the current bounds of the overlay, which is based on visibility.
+ gfx::Rect CalculateOverlayBounds();
+
+ // gfx::LayerAnimationObserver overrides:
+ virtual void OnLayerAnimationEnded(
+ ui::LayerAnimationSequence* sequence) OVERRIDE;
+ virtual void OnLayerAnimationAborted(
+ ui::LayerAnimationSequence* sequence) OVERRIDE;
+ virtual void OnLayerAnimationScheduled(
+ ui::LayerAnimationSequence* sequence) OVERRIDE;
+
+ bool is_visible_;
+ scoped_ptr<views::Widget> overlay_widget_;
+ // Ownership of |overlay_view_| is passed to the view heirarchy.
+ StickyKeysOverlayView* overlay_view_;
+ gfx::Size widget_size_;
+};
+
+} // namespace ash
+
+#endif // ASH_STICKY_KEYS_STICKY_KEYS_OVERLAY_H_
diff --git a/ash/sticky_keys/sticky_keys_overlay_unittest.cc b/ash/sticky_keys/sticky_keys_overlay_unittest.cc
new file mode 100644
index 0000000..de2d980
--- /dev/null
+++ b/ash/sticky_keys/sticky_keys_overlay_unittest.cc
@@ -0,0 +1,206 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/sticky_keys/sticky_keys_overlay.h"
+
+#include "ash/shell.h"
+#include "ash/sticky_keys/sticky_keys_controller.h"
+#include "ash/test/ash_test_base.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window_tree_host_delegate.h"
+#include "ui/events/event.h"
+
+namespace ash {
+
+class StickyKeysOverlayTest : public test::AshTestBase {
+ public:
+ StickyKeysOverlayTest() :
+ controller_(NULL),
+ overlay_(NULL) {}
+
+ virtual ~StickyKeysOverlayTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ test::AshTestBase::SetUp();
+
+ controller_ = Shell::GetInstance()->sticky_keys_controller();
+ controller_->Enable(true);
+ overlay_ = controller_->GetOverlayForTest();
+ ASSERT_TRUE(overlay_);
+ }
+
+ void PressAndReleaseKey(ui::KeyboardCode code) {
+ SendKeyEvent(ui::ET_KEY_PRESSED, code);
+ SendKeyEvent(ui::ET_KEY_RELEASED, code);
+ }
+
+ void SendKeyEvent(ui::EventType type, ui::KeyboardCode code) {
+ ui::KeyEvent event(type, code, 0, false);
+ ui::Event::DispatcherApi dispatcher(&event);
+ dispatcher.set_target(Shell::GetInstance()->GetPrimaryRootWindow());
+
+ aura::WindowTreeHostDelegate* delegate = Shell::GetPrimaryRootWindow()
+ ->GetDispatcher()->AsWindowTreeHostDelegate();
+ delegate->OnHostKeyEvent(&event);
+ }
+
+ StickyKeysController* controller_;
+ StickyKeysOverlay* overlay_;
+};
+
+TEST_F(StickyKeysOverlayTest, OverlayVisibility) {
+ StickyKeysOverlay overlay;
+ EXPECT_FALSE(overlay.is_visible());
+ overlay.Show(true);
+ EXPECT_TRUE(overlay.is_visible());
+}
+
+TEST_F(StickyKeysOverlayTest, ModifierKeyState) {
+ StickyKeysOverlay overlay;
+ overlay.SetModifierKeyState(ui::EF_SHIFT_DOWN, STICKY_KEY_STATE_DISABLED);
+ overlay.SetModifierKeyState(ui::EF_ALT_DOWN, STICKY_KEY_STATE_LOCKED);
+ overlay.SetModifierKeyState(ui::EF_CONTROL_DOWN, STICKY_KEY_STATE_ENABLED);
+
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay.GetModifierKeyState(ui::EF_SHIFT_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
+ overlay.GetModifierKeyState(ui::EF_ALT_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
+ overlay.GetModifierKeyState(ui::EF_CONTROL_DOWN));
+}
+
+TEST_F(StickyKeysOverlayTest, OneModifierEnabled) {
+ EXPECT_FALSE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+
+ // Pressing modifier key should show overlay.
+ PressAndReleaseKey(ui::VKEY_CONTROL);
+ EXPECT_TRUE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+
+ // Pressing a normal key should hide overlay.
+ PressAndReleaseKey(ui::VKEY_T);
+ EXPECT_FALSE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+}
+
+TEST_F(StickyKeysOverlayTest, TwoModifiersEnabled) {
+ EXPECT_FALSE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
+
+ // Pressing two modifiers should show overlay.
+ PressAndReleaseKey(ui::VKEY_SHIFT);
+ PressAndReleaseKey(ui::VKEY_CONTROL);
+ EXPECT_TRUE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
+ overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+
+ // Pressing a normal key should hide overlay.
+ PressAndReleaseKey(ui::VKEY_N);
+ EXPECT_FALSE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
+}
+
+TEST_F(StickyKeysOverlayTest, LockedModifier) {
+ EXPECT_FALSE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
+
+ // Pressing a modifier key twice should lock modifier and show overlay.
+ PressAndReleaseKey(ui::VKEY_LMENU);
+ PressAndReleaseKey(ui::VKEY_LMENU);
+ EXPECT_TRUE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
+ overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
+
+ // Pressing a normal key should not hide overlay.
+ PressAndReleaseKey(ui::VKEY_D);
+ EXPECT_TRUE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
+ overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
+}
+
+TEST_F(StickyKeysOverlayTest, LockedAndNormalModifier) {
+ EXPECT_FALSE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
+
+ // Pressing a modifier key twice should lock modifier and show overlay.
+ PressAndReleaseKey(ui::VKEY_CONTROL);
+ PressAndReleaseKey(ui::VKEY_CONTROL);
+ EXPECT_TRUE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+
+ // Pressing another modifier key should still show overlay.
+ PressAndReleaseKey(ui::VKEY_SHIFT);
+ EXPECT_TRUE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
+ overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
+
+ // Pressing a normal key should not hide overlay but disable normal modifier.
+ PressAndReleaseKey(ui::VKEY_D);
+ EXPECT_TRUE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
+}
+
+TEST_F(StickyKeysOverlayTest, ModifiersDisabled) {
+ EXPECT_FALSE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
+
+ // Enable modifiers.
+ PressAndReleaseKey(ui::VKEY_CONTROL);
+ PressAndReleaseKey(ui::VKEY_SHIFT);
+ PressAndReleaseKey(ui::VKEY_SHIFT);
+ PressAndReleaseKey(ui::VKEY_LMENU);
+
+ EXPECT_TRUE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
+ overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
+ overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
+
+ // Disable modifiers and overlay should be hidden.
+ PressAndReleaseKey(ui::VKEY_CONTROL);
+ PressAndReleaseKey(ui::VKEY_CONTROL);
+ PressAndReleaseKey(ui::VKEY_SHIFT);
+ PressAndReleaseKey(ui::VKEY_LMENU);
+ PressAndReleaseKey(ui::VKEY_LMENU);
+
+ EXPECT_FALSE(overlay_->is_visible());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
+ overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
+}
+
+} // namespace ash
diff --git a/ash/sticky_keys/sticky_keys_state.h b/ash/sticky_keys/sticky_keys_state.h
new file mode 100644
index 0000000..97e99d8
--- /dev/null
+++ b/ash/sticky_keys/sticky_keys_state.h
@@ -0,0 +1,25 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_STICKY_KEYS_STICKY_KEYS_STATE_H_
+#define ASH_STICKY_KEYS_STICKY_KEYS_STATE_H_
+
+namespace ash {
+
+// State of an individual modifier key.
+enum StickyKeyState {
+ // The sticky key is disabled. Incoming non-modifier key events are not
+ // affected.
+ STICKY_KEY_STATE_DISABLED,
+ // The sticky key is enabled. Incoming non-modifier key down events are
+ // modified. After that, sticky key state becomes DISABLED.
+ STICKY_KEY_STATE_ENABLED,
+ // The sticky key is locked. All incoming non modifier key down events are
+ // modified.
+ STICKY_KEY_STATE_LOCKED,
+};
+
+} // namespace ash
+
+#endif // ASH_STICKY_KEYS_STICKY_KEYS_STATE_H_
diff --git a/ash/sticky_keys/sticky_keys_unittest.cc b/ash/sticky_keys/sticky_keys_unittest.cc
index 9474247..c53035c 100644
--- a/ash/sticky_keys/sticky_keys_unittest.cc
+++ b/ash/sticky_keys/sticky_keys_unittest.cc
@@ -293,11 +293,11 @@ TEST_F(StickyKeysTest, BasicOneshotScenarioTest) {
new MockStickyKeysHandlerDelegate(this);
StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// By typing Shift key, internal state become ENABLED.
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
ev.reset(GenerateKey(true, ui::VKEY_A));
sticky_key.HandleKeyEvent(ev.get());
@@ -308,7 +308,7 @@ TEST_F(StickyKeysTest, BasicOneshotScenarioTest) {
ev.reset(GenerateKey(false, ui::VKEY_A));
sticky_key.HandleKeyEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// Making sure Shift up keyboard event is dispatched.
ASSERT_EQ(2U, mock_delegate->GetEventCount());
EXPECT_EQ(ui::ET_KEY_PRESSED, mock_delegate->GetEvent(0)->type());
@@ -336,15 +336,15 @@ TEST_F(StickyKeysTest, BasicLockedScenarioTest) {
new MockStickyKeysHandlerDelegate(this);
StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// By typing shift key, internal state become ENABLED.
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
// By typing shift key again, internal state become LOCKED.
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
// All keyboard events including keyUp become shift modified.
ev.reset(GenerateKey(true, ui::VKEY_A));
@@ -356,7 +356,7 @@ TEST_F(StickyKeysTest, BasicLockedScenarioTest) {
EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN);
// Locked state keeps after normal keyboard event.
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
ev.reset(GenerateKey(true, ui::VKEY_B));
sticky_key.HandleKeyEvent(ev.get());
@@ -366,11 +366,11 @@ TEST_F(StickyKeysTest, BasicLockedScenarioTest) {
sticky_key.HandleKeyEvent(ev.get());
EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN);
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
// By typing shift key again, internal state become back to DISABLED.
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
}
TEST_F(StickyKeysTest, NonTargetModifierTest) {
@@ -379,40 +379,40 @@ TEST_F(StickyKeysTest, NonTargetModifierTest) {
new MockStickyKeysHandlerDelegate(this);
StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// Non target modifier key does not affect internal state
ev.reset(GenerateKey(true, ui::VKEY_MENU));
sticky_key.HandleKeyEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
ev.reset(GenerateKey(false, ui::VKEY_MENU));
sticky_key.HandleKeyEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
// Non target modifier key does not affect internal state
ev.reset(GenerateKey(true, ui::VKEY_MENU));
sticky_key.HandleKeyEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
ev.reset(GenerateKey(false, ui::VKEY_MENU));
sticky_key.HandleKeyEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT);
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
// Non target modifier key does not affect internal state
ev.reset(GenerateKey(true, ui::VKEY_MENU));
sticky_key.HandleKeyEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
ev.reset(GenerateKey(false, ui::VKEY_MENU));
sticky_key.HandleKeyEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
}
TEST_F(StickyKeysTest, NormalShortcutTest) {
@@ -422,7 +422,7 @@ TEST_F(StickyKeysTest, NormalShortcutTest) {
new MockStickyKeysHandlerDelegate(this);
StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// Perform ctrl+n shortcut.
ev.reset(GenerateKey(true, ui::VKEY_CONTROL));
@@ -431,12 +431,12 @@ TEST_F(StickyKeysTest, NormalShortcutTest) {
sticky_key.HandleKeyEvent(ev.get());
ev.reset(GenerateKey(false, ui::VKEY_N));
sticky_key.HandleKeyEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// Sticky keys should not be enabled afterwards.
ev.reset(GenerateKey(false, ui::VKEY_CONTROL));
sticky_key.HandleKeyEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
}
TEST_F(StickyKeysTest, NormalModifiedClickTest) {
@@ -446,7 +446,7 @@ TEST_F(StickyKeysTest, NormalModifiedClickTest) {
new MockStickyKeysHandlerDelegate(this);
StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// Perform ctrl+click.
kev.reset(GenerateKey(true, ui::VKEY_CONTROL));
@@ -459,7 +459,7 @@ TEST_F(StickyKeysTest, NormalModifiedClickTest) {
// Sticky keys should not be enabled afterwards.
kev.reset(GenerateKey(false, ui::VKEY_CONTROL));
sticky_key.HandleKeyEvent(kev.get());
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
}
TEST_F(StickyKeysTest, MouseMovedModifierTest) {
@@ -469,7 +469,7 @@ TEST_F(StickyKeysTest, MouseMovedModifierTest) {
new MockStickyKeysHandlerDelegate(this);
StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// Press ctrl and handle mouse move events.
kev.reset(GenerateKey(true, ui::VKEY_CONTROL));
@@ -482,7 +482,7 @@ TEST_F(StickyKeysTest, MouseMovedModifierTest) {
// Sticky keys should be enabled afterwards.
kev.reset(GenerateKey(false, ui::VKEY_CONTROL));
sticky_key.HandleKeyEvent(kev.get());
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
}
TEST_F(StickyKeysTest, NormalModifiedScrollTest) {
@@ -494,7 +494,7 @@ TEST_F(StickyKeysTest, NormalModifiedScrollTest) {
new MockStickyKeysHandlerDelegate(this);
StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// Perform ctrl+scroll.
kev.reset(GenerateKey(true, ui::VKEY_CONTROL));
@@ -508,7 +508,7 @@ TEST_F(StickyKeysTest, NormalModifiedScrollTest) {
// Sticky keys should not be enabled afterwards.
kev.reset(GenerateKey(false, ui::VKEY_CONTROL));
sticky_key.HandleKeyEvent(kev.get());
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
}
TEST_F(StickyKeysTest, MouseEventOneshot) {
@@ -518,21 +518,21 @@ TEST_F(StickyKeysTest, MouseEventOneshot) {
new MockStickyKeysHandlerDelegate(this);
StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
// We should still be in the ENABLED state until we get the mouse
// release event.
ev.reset(GenerateMouseEvent(true));
sticky_key.HandleMouseEvent(ev.get());
EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
ev.reset(GenerateMouseEvent(false));
sticky_key.HandleMouseEvent(ev.get());
EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// Making sure modifier key release event is dispatched in the right order.
ASSERT_EQ(2u, mock_delegate->GetEventCount());
@@ -559,13 +559,13 @@ TEST_F(StickyKeysTest, MouseEventLocked) {
new MockStickyKeysHandlerDelegate(this);
StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// Pressing modifier key twice should make us enter lock state.
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
// Mouse events should not disable locked mode.
for (int i = 0; i < 3; ++i) {
@@ -575,7 +575,7 @@ TEST_F(StickyKeysTest, MouseEventLocked) {
ev.reset(GenerateMouseEvent(false));
sticky_key.HandleMouseEvent(ev.get());
EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
}
// Test with mouse wheel.
@@ -585,7 +585,7 @@ TEST_F(StickyKeysTest, MouseEventLocked) {
ev.reset(GenerateMouseWheelEvent(-ui::MouseWheelEvent::kWheelDelta));
sticky_key.HandleMouseEvent(ev.get());
EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
}
// Test mixed case with mouse events and key events.
@@ -599,7 +599,7 @@ TEST_F(StickyKeysTest, MouseEventLocked) {
sticky_key.HandleKeyEvent(kev.get());
EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
}
TEST_F(StickyKeysTest, ScrollEventOneshot) {
@@ -618,30 +618,30 @@ TEST_F(StickyKeysTest, ScrollEventOneshot) {
mock_delegate->ClearEvents();
// Enable sticky keys.
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
// Test a scroll sequence. Sticky keys should only be disabled at the end
// of the scroll sequence. Fling cancel event starts the scroll sequence.
ev.reset(GenerateFlingScrollEvent(0, true));
sticky_key.HandleScrollEvent(ev.get());
EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
// Scrolls should all be modified but not disable sticky keys.
for (int j = 0; j < 3; ++j) {
ev.reset(GenerateScrollEvent(scroll_deltas[i]));
sticky_key.HandleScrollEvent(ev.get());
EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
}
// Fling start event ends scroll sequence.
ev.reset(GenerateFlingScrollEvent(scroll_deltas[i], false));
sticky_key.HandleScrollEvent(ev.get());
EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
ASSERT_EQ(2U, mock_delegate->GetEventCount());
EXPECT_EQ(ui::ET_SCROLL_FLING_START, mock_delegate->GetEvent(0)->type());
@@ -670,12 +670,12 @@ TEST_F(StickyKeysTest, ScrollDirectionChanged) {
const int direction_change_values[2] = {0, -10};
for (int i = 0; i < 2; ++i) {
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
// Fling cancel starts scroll sequence.
ev.reset(GenerateFlingScrollEvent(0, true));
sticky_key.HandleScrollEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
// Test that changing directions in a scroll sequence will
// return sticky keys to DISABLED state.
@@ -683,13 +683,13 @@ TEST_F(StickyKeysTest, ScrollDirectionChanged) {
ev.reset(GenerateScrollEvent(10));
sticky_key.HandleScrollEvent(ev.get());
EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
}
ev.reset(GenerateScrollEvent(direction_change_values[i]));
sticky_key.HandleScrollEvent(ev.get());
EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
}
}
@@ -707,7 +707,7 @@ TEST_F(StickyKeysTest, ScrollEventLocked) {
// Lock sticky keys.
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
// Test scroll events are correctly modified in locked state.
for (int i = 0; i < 5; ++i) {
@@ -727,7 +727,7 @@ TEST_F(StickyKeysTest, ScrollEventLocked) {
sticky_key.HandleScrollEvent(ev.get());
}
- EXPECT_EQ(StickyKeysHandler::LOCKED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state());
}
TEST_F(StickyKeysTest, EventTargetDestroyed) {
@@ -739,14 +739,14 @@ TEST_F(StickyKeysTest, EventTargetDestroyed) {
target()->Focus();
// Go into ENABLED state.
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
// CTRL+J is a special shortcut that will destroy the event target.
ev.reset(GenerateKey(true, ui::VKEY_J));
sticky_key.HandleKeyEvent(ev.get());
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
EXPECT_FALSE(target());
}
@@ -760,32 +760,32 @@ TEST_F(StickyKeysTest, SynthesizedEvents) {
// Test non-native key events.
scoped_ptr<ui::KeyEvent> kev;
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
kev.reset(GenerateSynthesizedKeyEvent(true, ui::VKEY_K));
sticky_key.HandleKeyEvent(kev.get());
EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
kev.reset(GenerateSynthesizedKeyEvent(false, ui::VKEY_K));
sticky_key.HandleKeyEvent(kev.get());
EXPECT_FALSE(kev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
// Test non-native mouse events.
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
scoped_ptr<ui::MouseEvent> mev;
mev.reset(GenerateSynthesizedMouseEvent(true));
sticky_key.HandleMouseEvent(mev.get());
EXPECT_TRUE(mev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::ENABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state());
mev.reset(GenerateSynthesizedMouseEvent(false));
sticky_key.HandleMouseEvent(mev.get());
EXPECT_TRUE(mev->flags() & ui::EF_CONTROL_DOWN);
- EXPECT_EQ(StickyKeysHandler::DISABLED, sticky_key.current_state());
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state());
}
TEST_F(StickyKeysTest, KeyEventDispatchImpl) {