diff options
Diffstat (limited to 'chromium/ash/wm/sticky_keys.cc')
-rw-r--r-- | chromium/ash/wm/sticky_keys.cc | 445 |
1 files changed, 0 insertions, 445 deletions
diff --git a/chromium/ash/wm/sticky_keys.cc b/chromium/ash/wm/sticky_keys.cc deleted file mode 100644 index 9e2cc2a92de..00000000000 --- a/chromium/ash/wm/sticky_keys.cc +++ /dev/null @@ -1,445 +0,0 @@ -// Copyright 2013 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/wm/sticky_keys.h" - -#if defined(USE_X11) -#include <X11/extensions/XInput2.h> -#include <X11/Xlib.h> -#undef RootWindow -#endif - -#include "base/basictypes.h" -#include "base/debug/stack_trace.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_tracker.h" -#include "ui/events/event.h" -#include "ui/events/keycodes/keyboard_code_conversion.h" - -namespace ash { - -namespace { - -// Returns true if the type of mouse event should be modified by sticky keys. -bool ShouldModifyMouseEvent(ui::MouseEvent* event) { - ui::EventType type = event->type(); - return type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED || - type == ui::ET_MOUSEWHEEL; -} - -// An implementation of StickyKeysHandler::StickyKeysHandlerDelegate. -class StickyKeysHandlerDelegateImpl : - public StickyKeysHandler::StickyKeysHandlerDelegate { - public: - StickyKeysHandlerDelegateImpl(); - virtual ~StickyKeysHandlerDelegateImpl(); - - // StickyKeysHandlerDelegate overrides. - virtual void DispatchKeyEvent(ui::KeyEvent* event, - aura::Window* target) OVERRIDE; - - virtual void DispatchMouseEvent(ui::MouseEvent* event, - aura::Window* target) OVERRIDE; - - virtual void DispatchScrollEvent(ui::ScrollEvent* event, - aura::Window* target) OVERRIDE; - private: - DISALLOW_COPY_AND_ASSIGN(StickyKeysHandlerDelegateImpl); -}; - -StickyKeysHandlerDelegateImpl::StickyKeysHandlerDelegateImpl() { -} - -StickyKeysHandlerDelegateImpl::~StickyKeysHandlerDelegateImpl() { -} - -void StickyKeysHandlerDelegateImpl::DispatchKeyEvent(ui::KeyEvent* event, - aura::Window* target) { - DCHECK(target); - target->GetDispatcher()->AsRootWindowHostDelegate()->OnHostKeyEvent(event); -} - -void StickyKeysHandlerDelegateImpl::DispatchMouseEvent(ui::MouseEvent* event, - aura::Window* target) { - DCHECK(target); - // We need to send a new, untransformed mouse event to the host. - if (event->IsMouseWheelEvent()) { - ui::MouseWheelEvent new_event(*static_cast<ui::MouseWheelEvent*>(event)); - target->GetDispatcher()->AsRootWindowHostDelegate() - ->OnHostMouseEvent(&new_event); - } else { - ui::MouseEvent new_event(*event, target, target->GetRootWindow()); - target->GetDispatcher()->AsRootWindowHostDelegate() - ->OnHostMouseEvent(&new_event); - } -} - -void StickyKeysHandlerDelegateImpl::DispatchScrollEvent( - ui::ScrollEvent* event, - aura::Window* target) { - DCHECK(target); - target->GetDispatcher()->AsRootWindowHostDelegate() - ->OnHostScrollEvent(event); -} - -} // namespace - -/////////////////////////////////////////////////////////////////////////////// -// StickyKeys -StickyKeys::StickyKeys() - : 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())) { -} - -StickyKeys::~StickyKeys() { -} - -void StickyKeys::Enable(bool enabled) { - if (enabled_ != enabled) { - enabled_ = enabled; - - // Reset key handlers when activating sticky keys to ensure all - // the handlers' states are reset. - if (enabled_) { - shift_sticky_key_.reset( - new StickyKeysHandler(ui::EF_SHIFT_DOWN, - 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())); - } - } -} - -bool StickyKeys::HandleKeyEvent(ui::KeyEvent* event) { - return shift_sticky_key_->HandleKeyEvent(event) || - alt_sticky_key_->HandleKeyEvent(event) || - ctrl_sticky_key_->HandleKeyEvent(event); - return ctrl_sticky_key_->HandleKeyEvent(event); -} - -bool StickyKeys::HandleMouseEvent(ui::MouseEvent* event) { - return shift_sticky_key_->HandleMouseEvent(event) || - alt_sticky_key_->HandleMouseEvent(event) || - ctrl_sticky_key_->HandleMouseEvent(event); -} - -bool StickyKeys::HandleScrollEvent(ui::ScrollEvent* event) { - return shift_sticky_key_->HandleScrollEvent(event) || - alt_sticky_key_->HandleScrollEvent(event) || - ctrl_sticky_key_->HandleScrollEvent(event); -} - -void StickyKeys::OnKeyEvent(ui::KeyEvent* event) { - // Do not consume a translated key event which is generated by an IME. - if (event->type() == ui::ET_TRANSLATED_KEY_PRESS || - event->type() == ui::ET_TRANSLATED_KEY_RELEASE) { - return; - } - - if (enabled_ && HandleKeyEvent(event)) - event->StopPropagation(); -} - -void StickyKeys::OnMouseEvent(ui::MouseEvent* event) { - if (enabled_ && HandleMouseEvent(event)) - event->StopPropagation(); -} - -void StickyKeys::OnScrollEvent(ui::ScrollEvent* event) { - if (enabled_ && HandleScrollEvent(event)) - event->StopPropagation(); -} - -/////////////////////////////////////////////////////////////////////////////// -// StickyKeysHandler -StickyKeysHandler::StickyKeysHandler(ui::EventFlags target_modifier_flag, - StickyKeysHandlerDelegate* delegate) - : modifier_flag_(target_modifier_flag), - current_state_(DISABLED), - event_from_myself_(false), - preparing_to_enable_(false), - scroll_delta_(0), - delegate_(delegate) { -} - -StickyKeysHandler::~StickyKeysHandler() { -} - -StickyKeysHandler::StickyKeysHandlerDelegate::StickyKeysHandlerDelegate() { -} - -StickyKeysHandler::StickyKeysHandlerDelegate::~StickyKeysHandlerDelegate() { -} - -bool StickyKeysHandler::HandleKeyEvent(ui::KeyEvent* event) { - if (event_from_myself_) - return false; // Do not handle self-generated key event. - switch (current_state_) { - case DISABLED: - return HandleDisabledState(event); - case ENABLED: - return HandleEnabledState(event); - case LOCKED: - return HandleLockedState(event); - } - NOTREACHED(); - return false; -} - -bool StickyKeysHandler::HandleMouseEvent(ui::MouseEvent* event) { - preparing_to_enable_ = false; - if (event_from_myself_ || current_state_ == DISABLED - || !ShouldModifyMouseEvent(event)) { - return false; - } - DCHECK(current_state_ == ENABLED || current_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; - DispatchEventAndReleaseModifier(event); - return true; - } - - return false; -} - -bool StickyKeysHandler::HandleScrollEvent(ui::ScrollEvent* event) { - preparing_to_enable_ = false; - if (event_from_myself_ || current_state_ == DISABLED) - return false; - DCHECK(current_state_ == ENABLED || current_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) { - int offset = event->y_offset(); - if (scroll_delta_) - direction_changed = offset * scroll_delta_ <= 0; - scroll_delta_ = offset; - } - - if (!direction_changed) - AppendModifier(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 && - (event->type() == ui::ET_SCROLL_FLING_START || direction_changed)) { - current_state_ = DISABLED; - scroll_delta_ = 0; - DispatchEventAndReleaseModifier(event); - return true; - } - - return false; -} - -StickyKeysHandler::KeyEventType - StickyKeysHandler::TranslateKeyEvent(ui::KeyEvent* event) { - bool is_target_key = false; - if (event->key_code() == ui::VKEY_SHIFT || - event->key_code() == ui::VKEY_LSHIFT || - event->key_code() == ui::VKEY_RSHIFT) { - is_target_key = (modifier_flag_ == ui::EF_SHIFT_DOWN); - } else if (event->key_code() == ui::VKEY_CONTROL || - event->key_code() == ui::VKEY_LCONTROL || - event->key_code() == ui::VKEY_RCONTROL) { - is_target_key = (modifier_flag_ == ui::EF_CONTROL_DOWN); - } else if (event->key_code() == ui::VKEY_MENU || - event->key_code() == ui::VKEY_LMENU || - event->key_code() == ui::VKEY_RMENU) { - is_target_key = (modifier_flag_ == ui::EF_ALT_DOWN); - } else { - return event->type() == ui::ET_KEY_PRESSED ? - NORMAL_KEY_DOWN : NORMAL_KEY_UP; - } - - if (is_target_key) { - return event->type() == ui::ET_KEY_PRESSED ? - TARGET_MODIFIER_DOWN : TARGET_MODIFIER_UP; - } - return event->type() == ui::ET_KEY_PRESSED ? - OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP; -} - -bool StickyKeysHandler::HandleDisabledState(ui::KeyEvent* event) { - switch (TranslateKeyEvent(event)) { - case TARGET_MODIFIER_UP: - if (preparing_to_enable_) { - preparing_to_enable_ = false; - scroll_delta_ = 0; - current_state_ = ENABLED; - modifier_up_event_.reset(new ui::KeyEvent(*event)); - return true; - } - return false; - case TARGET_MODIFIER_DOWN: - preparing_to_enable_ = true; - return false; - case NORMAL_KEY_DOWN: - preparing_to_enable_ = false; - return false; - case NORMAL_KEY_UP: - case OTHER_MODIFIER_DOWN: - case OTHER_MODIFIER_UP: - return false; - } - NOTREACHED(); - return false; -} - -bool StickyKeysHandler::HandleEnabledState(ui::KeyEvent* event) { - switch (TranslateKeyEvent(event)) { - case NORMAL_KEY_UP: - case TARGET_MODIFIER_DOWN: - return true; - case TARGET_MODIFIER_UP: - current_state_ = LOCKED; - modifier_up_event_.reset(); - return true; - case NORMAL_KEY_DOWN: { - current_state_ = DISABLED; - AppendModifier(event); - DispatchEventAndReleaseModifier(event); - return true; - } - case OTHER_MODIFIER_DOWN: - case OTHER_MODIFIER_UP: - return false; - } - NOTREACHED(); - return false; -} - -bool StickyKeysHandler::HandleLockedState(ui::KeyEvent* event) { - switch (TranslateKeyEvent(event)) { - case TARGET_MODIFIER_DOWN: - return true; - case TARGET_MODIFIER_UP: - current_state_ = DISABLED; - return false; - case NORMAL_KEY_DOWN: - case NORMAL_KEY_UP: - AppendModifier(event); - return false; - case OTHER_MODIFIER_DOWN: - case OTHER_MODIFIER_UP: - return false; - } - NOTREACHED(); - return false; -} - -void StickyKeysHandler::DispatchEventAndReleaseModifier(ui::Event* event) { - DCHECK(event->IsKeyEvent() || - event->IsMouseEvent() || - event->IsScrollEvent()); - DCHECK(modifier_up_event_.get()); - aura::Window* target = static_cast<aura::Window*>(event->target()); - DCHECK(target); - aura::Window* root_window = target->GetRootWindow(); - DCHECK(root_window); - - aura::WindowTracker window_tracker; - window_tracker.Add(target); - - event_from_myself_ = true; - if (event->IsKeyEvent()) { - delegate_->DispatchKeyEvent(static_cast<ui::KeyEvent*>(event), target); - } else if (event->IsMouseEvent()) { - delegate_->DispatchMouseEvent(static_cast<ui::MouseEvent*>(event), target); - } else { - delegate_->DispatchScrollEvent( - static_cast<ui::ScrollEvent*>(event), target); - } - - // The action triggered above may have destroyed the event target, in which - // case we will dispatch the modifier up event to the root window instead. - aura::Window* modifier_up_target = - window_tracker.Contains(target) ? target : root_window; - delegate_->DispatchKeyEvent(modifier_up_event_.get(), modifier_up_target); - event_from_myself_ = false; -} - -void StickyKeysHandler::AppendNativeEventMask(unsigned int* state) { - unsigned int& state_ref = *state; - switch (modifier_flag_) { - case ui::EF_CONTROL_DOWN: - state_ref |= ControlMask; - break; - case ui::EF_ALT_DOWN: - state_ref |= Mod1Mask; - break; - case ui::EF_SHIFT_DOWN: - state_ref |= ShiftMask; - break; - default: - NOTREACHED(); - } -} - -void StickyKeysHandler::AppendModifier(ui::KeyEvent* event) { -#if defined(USE_X11) - XEvent* xev = event->native_event(); - if (xev) { - XKeyEvent* xkey = &(xev->xkey); - AppendNativeEventMask(&xkey->state); - } -#elif defined(USE_OZONE) - NOTIMPLEMENTED() << "Modifier key is not handled"; -#endif - event->set_flags(event->flags() | modifier_flag_); - event->set_character(ui::GetCharacterFromKeyCode(event->key_code(), - event->flags())); - event->NormalizeFlags(); -} - -void StickyKeysHandler::AppendModifier(ui::MouseEvent* event) { -#if defined(USE_X11) - XEvent* xev = event->native_event(); - if (xev) { - XButtonEvent* xkey = &(xev->xbutton); - AppendNativeEventMask(&xkey->state); - } -#elif defined(USE_OZONE) - NOTIMPLEMENTED() << "Modifier key is not handled"; -#endif - event->set_flags(event->flags() | modifier_flag_); -} - -void StickyKeysHandler::AppendModifier(ui::ScrollEvent* event) { -#if defined(USE_X11) - XEvent* xev = event->native_event(); - if (xev) { - XIDeviceEvent* xievent = - static_cast<XIDeviceEvent*>(xev->xcookie.data); - if (xievent) { - AppendNativeEventMask(reinterpret_cast<unsigned int*>( - &xievent->mods.effective)); - } - } -#elif defined(USE_OZONE) - NOTIMPLEMENTED() << "Modifier key is not handled"; -#endif - event->set_flags(event->flags() | modifier_flag_); -} - -} // namespace ash |