| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ash/sticky_keys/sticky_keys_controller.h" | 5 #include "ash/sticky_keys/sticky_keys_controller.h" |
| 6 | 6 |
| 7 #if defined(USE_X11) | |
| 8 #include <X11/extensions/XInput2.h> | |
| 9 #include <X11/Xlib.h> | |
| 10 #undef RootWindow | |
| 11 #endif | |
| 12 | |
| 13 #include "ash/sticky_keys/sticky_keys_overlay.h" | 7 #include "ash/sticky_keys/sticky_keys_overlay.h" |
| 14 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 15 #include "base/debug/stack_trace.h" | 9 #include "base/debug/stack_trace.h" |
| 16 #include "ui/aura/window.h" | 10 #include "ui/aura/window.h" |
| 17 #include "ui/aura/window_tracker.h" | 11 #include "ui/aura/window_tracker.h" |
| 18 #include "ui/aura/window_tree_host.h" | 12 #include "ui/aura/window_tree_host.h" |
| 19 #include "ui/events/event.h" | 13 #include "ui/events/event.h" |
| 20 #include "ui/events/event_processor.h" | 14 #include "ui/events/event_processor.h" |
| 21 #include "ui/events/keycodes/keyboard_code_conversion.h" | 15 #include "ui/events/keycodes/keyboard_code_conversion.h" |
| 22 | 16 |
| 23 namespace ash { | 17 namespace ash { |
| 24 | 18 |
| 25 namespace { | 19 namespace { |
| 26 | 20 |
| 27 // Returns true if the type of mouse event should be modified by sticky keys. | 21 // Returns true if the type of mouse event should be modified by sticky keys. |
| 28 bool ShouldModifyMouseEvent(ui::MouseEvent* event) { | 22 bool ShouldModifyMouseEvent(const ui::MouseEvent& event) { |
| 29 ui::EventType type = event->type(); | 23 ui::EventType type = event.type(); |
| 30 return type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED || | 24 return type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED || |
| 31 type == ui::ET_MOUSEWHEEL; | 25 type == ui::ET_MOUSEWHEEL; |
| 32 } | 26 } |
| 33 | 27 |
| 34 // An implementation of StickyKeysHandler::StickyKeysHandlerDelegate. | 28 // Handle the common tail of event rewriting. |
| 35 class StickyKeysHandlerDelegateImpl : | 29 ui::EventRewriteStatus RewriteUpdate(bool consumed, |
| 36 public StickyKeysHandler::StickyKeysHandlerDelegate { | 30 int mod_up_flags, |
| 37 public: | 31 int mod_down_flags, |
| 38 StickyKeysHandlerDelegateImpl(); | 32 int* flags) { |
| 39 virtual ~StickyKeysHandlerDelegateImpl(); | 33 int changed_down_flags = mod_down_flags & ~*flags; |
| 40 | 34 *flags |= mod_down_flags; |
| 41 // StickyKeysHandlerDelegate overrides. | 35 if (consumed) |
| 42 virtual void DispatchKeyEvent(ui::KeyEvent* event, | 36 return ui::EVENT_REWRITE_DISCARD; |
| 43 aura::Window* target) OVERRIDE; | 37 if (mod_up_flags) |
| 44 | 38 return ui::EVENT_REWRITE_DISPATCH_ANOTHER; |
| 45 virtual void DispatchMouseEvent(ui::MouseEvent* event, | 39 if (changed_down_flags) |
| 46 aura::Window* target) OVERRIDE; | 40 return ui::EVENT_REWRITE_REWRITTEN; |
| 47 | 41 return ui::EVENT_REWRITE_CONTINUE; |
| 48 virtual void DispatchScrollEvent(ui::ScrollEvent* event, | |
| 49 aura::Window* target) OVERRIDE; | |
| 50 private: | |
| 51 void DispatchEvent(ui::Event* event, aura::Window* target); | |
| 52 | |
| 53 DISALLOW_COPY_AND_ASSIGN(StickyKeysHandlerDelegateImpl); | |
| 54 }; | |
| 55 | |
| 56 StickyKeysHandlerDelegateImpl::StickyKeysHandlerDelegateImpl() { | |
| 57 } | |
| 58 | |
| 59 StickyKeysHandlerDelegateImpl::~StickyKeysHandlerDelegateImpl() { | |
| 60 } | |
| 61 | |
| 62 void StickyKeysHandlerDelegateImpl::DispatchKeyEvent(ui::KeyEvent* event, | |
| 63 aura::Window* target) { | |
| 64 DispatchEvent(event, target); | |
| 65 } | |
| 66 | |
| 67 void StickyKeysHandlerDelegateImpl::DispatchMouseEvent(ui::MouseEvent* event, | |
| 68 aura::Window* target) { | |
| 69 DCHECK(target); | |
| 70 // We need to send a new, untransformed mouse event to the host. | |
| 71 if (event->IsMouseWheelEvent()) { | |
| 72 aura::Window* source = static_cast<aura::Window*>(event->target()); | |
| 73 ui::MouseWheelEvent new_event(*static_cast<ui::MouseWheelEvent*>(event), | |
| 74 source, | |
| 75 source->GetRootWindow()); | |
| 76 // Transform the location back to host coordinates before dispatching. | |
| 77 new_event.UpdateForRootTransform(source->GetHost()->GetRootTransform()); | |
| 78 DispatchEvent(&new_event, target); | |
| 79 } else { | |
| 80 aura::Window* source = static_cast<aura::Window*>(event->target()); | |
| 81 ui::MouseEvent new_event(*event, source, source->GetRootWindow()); | |
| 82 // Transform the location back to host coordinates before dispatching. | |
| 83 new_event.UpdateForRootTransform(source->GetHost()->GetRootTransform()); | |
| 84 DispatchEvent(&new_event, target); | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 void StickyKeysHandlerDelegateImpl::DispatchScrollEvent( | |
| 89 ui::ScrollEvent* event, | |
| 90 aura::Window* target) { | |
| 91 DispatchEvent(event, target); | |
| 92 } | |
| 93 | |
| 94 void StickyKeysHandlerDelegateImpl::DispatchEvent(ui::Event* event, | |
| 95 aura::Window* target) { | |
| 96 DCHECK(target); | |
| 97 ui::EventDispatchDetails details = | |
| 98 target->GetHost()->event_processor()->OnEventFromSource(event); | |
| 99 if (details.dispatcher_destroyed) | |
| 100 return; | |
| 101 } | 42 } |
| 102 | 43 |
| 103 } // namespace | 44 } // namespace |
| 104 | 45 |
| 105 /////////////////////////////////////////////////////////////////////////////// | 46 /////////////////////////////////////////////////////////////////////////////// |
| 106 // StickyKeys | 47 // StickyKeys |
| 107 StickyKeysController::StickyKeysController() | 48 StickyKeysController::StickyKeysController() |
| 108 : enabled_(false), | 49 : enabled_(false), |
| 109 mod3_enabled_(false), | 50 mod3_enabled_(false), |
| 110 altgr_enabled_(false) { | 51 altgr_enabled_(false) { |
| 111 } | 52 } |
| 112 | 53 |
| 113 StickyKeysController::~StickyKeysController() { | 54 StickyKeysController::~StickyKeysController() { |
| 114 } | 55 } |
| 115 | 56 |
| 116 void StickyKeysController::Enable(bool enabled) { | 57 void StickyKeysController::Enable(bool enabled) { |
| 117 if (enabled_ != enabled) { | 58 if (enabled_ != enabled) { |
| 118 enabled_ = enabled; | 59 enabled_ = enabled; |
| 119 | 60 |
| 120 // Reset key handlers when activating sticky keys to ensure all | 61 // Reset key handlers when activating sticky keys to ensure all |
| 121 // the handlers' states are reset. | 62 // the handlers' states are reset. |
| 122 if (enabled_) { | 63 if (enabled_) { |
| 123 shift_sticky_key_.reset( | 64 shift_sticky_key_.reset(new StickyKeysHandler(ui::EF_SHIFT_DOWN)); |
| 124 new StickyKeysHandler(ui::EF_SHIFT_DOWN, | 65 alt_sticky_key_.reset(new StickyKeysHandler(ui::EF_ALT_DOWN)); |
| 125 new StickyKeysHandlerDelegateImpl())); | 66 altgr_sticky_key_.reset(new StickyKeysHandler(ui::EF_ALTGR_DOWN)); |
| 126 alt_sticky_key_.reset( | 67 ctrl_sticky_key_.reset(new StickyKeysHandler(ui::EF_CONTROL_DOWN)); |
| 127 new StickyKeysHandler(ui::EF_ALT_DOWN, | 68 mod3_sticky_key_.reset(new StickyKeysHandler(ui::EF_MOD3_DOWN)); |
| 128 new StickyKeysHandlerDelegateImpl())); | |
| 129 altgr_sticky_key_.reset( | |
| 130 new StickyKeysHandler(ui::EF_ALTGR_DOWN, | |
| 131 new StickyKeysHandlerDelegateImpl())); | |
| 132 ctrl_sticky_key_.reset( | |
| 133 new StickyKeysHandler(ui::EF_CONTROL_DOWN, | |
| 134 new StickyKeysHandlerDelegateImpl())); | |
| 135 mod3_sticky_key_.reset( | |
| 136 new StickyKeysHandler(ui::EF_MOD3_DOWN, | |
| 137 new StickyKeysHandlerDelegateImpl())); | |
| 138 | 69 |
| 139 overlay_.reset(new StickyKeysOverlay()); | 70 overlay_.reset(new StickyKeysOverlay()); |
| 140 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); | 71 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); |
| 141 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_); | 72 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_); |
| 142 } else if (overlay_) { | 73 } else if (overlay_) { |
| 143 overlay_->Show(false); | 74 overlay_->Show(false); |
| 144 } | 75 } |
| 145 } | 76 } |
| 146 } | 77 } |
| 147 | 78 |
| 148 void StickyKeysController::SetModifiersEnabled(bool mod3_enabled, | 79 void StickyKeysController::SetModifiersEnabled(bool mod3_enabled, |
| 149 bool altgr_enabled) { | 80 bool altgr_enabled) { |
| 150 mod3_enabled_ = mod3_enabled; | 81 mod3_enabled_ = mod3_enabled; |
| 151 altgr_enabled_ = altgr_enabled; | 82 altgr_enabled_ = altgr_enabled; |
| 152 if (overlay_) { | 83 if (overlay_) { |
| 153 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); | 84 overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); |
| 154 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_); | 85 overlay_->SetModifierVisible(ui::EF_MOD3_DOWN, mod3_enabled_); |
| 155 } | 86 } |
| 156 } | 87 } |
| 157 | 88 |
| 158 bool StickyKeysController::HandleKeyEvent(ui::KeyEvent* event) { | 89 bool StickyKeysController::HandleKeyEvent(const ui::KeyEvent& event, |
| 159 return shift_sticky_key_->HandleKeyEvent(event) || | 90 ui::KeyboardCode key_code, |
| 160 alt_sticky_key_->HandleKeyEvent(event) || | 91 int* mod_down_flags, |
| 161 altgr_sticky_key_->HandleKeyEvent(event) || | 92 int* mod_up_flags) { |
| 162 ctrl_sticky_key_->HandleKeyEvent(event) || | 93 return shift_sticky_key_->HandleKeyEvent( |
| 163 mod3_sticky_key_->HandleKeyEvent(event); | 94 event, key_code, mod_down_flags, mod_up_flags) || |
| 95 alt_sticky_key_->HandleKeyEvent( |
| 96 event, key_code, mod_down_flags, mod_up_flags) || |
| 97 altgr_sticky_key_->HandleKeyEvent( |
| 98 event, key_code, mod_down_flags, mod_up_flags) || |
| 99 ctrl_sticky_key_->HandleKeyEvent( |
| 100 event, key_code, mod_down_flags, mod_up_flags) || |
| 101 mod3_sticky_key_->HandleKeyEvent( |
| 102 event, key_code, mod_down_flags, mod_up_flags); |
| 164 } | 103 } |
| 165 | 104 |
| 166 bool StickyKeysController::HandleMouseEvent(ui::MouseEvent* event) { | 105 bool StickyKeysController::HandleMouseEvent(const ui::MouseEvent& event, |
| 167 return shift_sticky_key_->HandleMouseEvent(event) || | 106 int* mod_down_flags, |
| 168 alt_sticky_key_->HandleMouseEvent(event) || | 107 int* mod_up_flags) { |
| 169 altgr_sticky_key_->HandleMouseEvent(event) || | 108 return shift_sticky_key_->HandleMouseEvent( |
| 170 ctrl_sticky_key_->HandleMouseEvent(event) || | 109 event, mod_down_flags, mod_up_flags) || |
| 171 mod3_sticky_key_->HandleMouseEvent(event); | 110 alt_sticky_key_->HandleMouseEvent( |
| 111 event, mod_down_flags, mod_up_flags) || |
| 112 altgr_sticky_key_->HandleMouseEvent( |
| 113 event, mod_down_flags, mod_up_flags) || |
| 114 ctrl_sticky_key_->HandleMouseEvent( |
| 115 event, mod_down_flags, mod_up_flags) || |
| 116 mod3_sticky_key_->HandleMouseEvent( |
| 117 event, mod_down_flags, mod_up_flags); |
| 172 } | 118 } |
| 173 | 119 |
| 174 bool StickyKeysController::HandleScrollEvent(ui::ScrollEvent* event) { | 120 bool StickyKeysController::HandleScrollEvent(const ui::ScrollEvent& event, |
| 175 return shift_sticky_key_->HandleScrollEvent(event) || | 121 int* mod_down_flags, |
| 176 alt_sticky_key_->HandleScrollEvent(event) || | 122 int* mod_up_flags) { |
| 177 altgr_sticky_key_->HandleScrollEvent(event) || | 123 return shift_sticky_key_->HandleScrollEvent( |
| 178 ctrl_sticky_key_->HandleScrollEvent(event) || | 124 event, mod_down_flags, mod_up_flags) || |
| 179 mod3_sticky_key_->HandleScrollEvent(event); | 125 alt_sticky_key_->HandleScrollEvent( |
| 126 event, mod_down_flags, mod_up_flags) || |
| 127 altgr_sticky_key_->HandleScrollEvent( |
| 128 event, mod_down_flags, mod_up_flags) || |
| 129 ctrl_sticky_key_->HandleScrollEvent( |
| 130 event, mod_down_flags, mod_up_flags) || |
| 131 mod3_sticky_key_->HandleScrollEvent( |
| 132 event, mod_down_flags, mod_up_flags); |
| 180 } | 133 } |
| 181 | 134 |
| 182 void StickyKeysController::OnKeyEvent(ui::KeyEvent* event) { | 135 ui::EventRewriteStatus StickyKeysController::RewriteKeyEvent( |
| 183 // Do not consume a translated key event which is generated by an IME. | 136 const ui::KeyEvent& event, |
| 184 if (event->IsTranslated()) | 137 ui::KeyboardCode key_code, |
| 185 return; | 138 int* flags) { |
| 186 | 139 if (!enabled_) |
| 187 if (enabled_) { | 140 return ui::EVENT_REWRITE_CONTINUE; |
| 188 if (HandleKeyEvent(event)) | 141 int mod_down_flags = 0; |
| 189 event->StopPropagation(); | 142 int mod_up_flags = 0; |
| 190 UpdateOverlay(); | 143 bool consumed = |
| 191 } | 144 HandleKeyEvent(event, key_code, &mod_down_flags, &mod_up_flags); |
| 145 UpdateOverlay(); |
| 146 return RewriteUpdate(consumed, mod_up_flags, mod_down_flags, flags); |
| 192 } | 147 } |
| 193 | 148 |
| 194 void StickyKeysController::OnMouseEvent(ui::MouseEvent* event) { | 149 ui::EventRewriteStatus StickyKeysController::RewriteMouseEvent( |
| 195 if (enabled_) { | 150 const ui::MouseEvent& event, |
| 196 if (HandleMouseEvent(event)) | 151 int* flags) { |
| 197 event->StopPropagation(); | 152 if (!enabled_) |
| 198 UpdateOverlay(); | 153 return ui::EVENT_REWRITE_CONTINUE; |
| 199 } | 154 int mod_down_flags = 0; |
| 155 int mod_up_flags = 0; |
| 156 bool consumed = HandleMouseEvent(event, &mod_down_flags, &mod_up_flags); |
| 157 UpdateOverlay(); |
| 158 return RewriteUpdate(consumed, mod_up_flags, mod_down_flags, flags); |
| 200 } | 159 } |
| 201 | 160 |
| 202 void StickyKeysController::OnScrollEvent(ui::ScrollEvent* event) { | 161 ui::EventRewriteStatus StickyKeysController::RewriteScrollEvent( |
| 203 if (enabled_) { | 162 const ui::ScrollEvent& event, |
| 204 if (HandleScrollEvent(event)) | 163 int* flags) { |
| 205 event->StopPropagation(); | 164 if (!enabled_) |
| 206 UpdateOverlay(); | 165 return ui::EVENT_REWRITE_CONTINUE; |
| 207 } | 166 int mod_down_flags = 0; |
| 167 int mod_up_flags = 0; |
| 168 bool consumed = HandleScrollEvent(event, &mod_down_flags, &mod_up_flags); |
| 169 UpdateOverlay(); |
| 170 return RewriteUpdate(consumed, mod_up_flags, mod_down_flags, flags); |
| 171 } |
| 172 |
| 173 ui::EventRewriteStatus StickyKeysController::NextDispatchEvent( |
| 174 scoped_ptr<ui::Event>* new_event) { |
| 175 new_event->reset(); |
| 176 int remaining = shift_sticky_key_->GetModifierUpEvent(new_event) + |
| 177 alt_sticky_key_->GetModifierUpEvent(new_event) + |
| 178 altgr_sticky_key_->GetModifierUpEvent(new_event) + |
| 179 ctrl_sticky_key_->GetModifierUpEvent(new_event) + |
| 180 mod3_sticky_key_->GetModifierUpEvent(new_event); |
| 181 return remaining ? ui::EVENT_REWRITE_DISPATCH_ANOTHER |
| 182 : ui::EVENT_REWRITE_REWRITTEN; |
| 208 } | 183 } |
| 209 | 184 |
| 210 void StickyKeysController::UpdateOverlay() { | 185 void StickyKeysController::UpdateOverlay() { |
| 211 overlay_->SetModifierKeyState( | 186 overlay_->SetModifierKeyState( |
| 212 ui::EF_SHIFT_DOWN, shift_sticky_key_->current_state()); | 187 ui::EF_SHIFT_DOWN, shift_sticky_key_->current_state()); |
| 213 overlay_->SetModifierKeyState( | 188 overlay_->SetModifierKeyState( |
| 214 ui::EF_CONTROL_DOWN, ctrl_sticky_key_->current_state()); | 189 ui::EF_CONTROL_DOWN, ctrl_sticky_key_->current_state()); |
| 215 overlay_->SetModifierKeyState( | 190 overlay_->SetModifierKeyState( |
| 216 ui::EF_ALT_DOWN, alt_sticky_key_->current_state()); | 191 ui::EF_ALT_DOWN, alt_sticky_key_->current_state()); |
| 217 overlay_->SetModifierKeyState( | 192 overlay_->SetModifierKeyState( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 228 | 203 |
| 229 overlay_->Show(enabled_ && key_in_use); | 204 overlay_->Show(enabled_ && key_in_use); |
| 230 } | 205 } |
| 231 | 206 |
| 232 StickyKeysOverlay* StickyKeysController::GetOverlayForTest() { | 207 StickyKeysOverlay* StickyKeysController::GetOverlayForTest() { |
| 233 return overlay_.get(); | 208 return overlay_.get(); |
| 234 } | 209 } |
| 235 | 210 |
| 236 /////////////////////////////////////////////////////////////////////////////// | 211 /////////////////////////////////////////////////////////////////////////////// |
| 237 // StickyKeysHandler | 212 // StickyKeysHandler |
| 238 StickyKeysHandler::StickyKeysHandler(ui::EventFlags modifier_flag, | 213 StickyKeysHandler::StickyKeysHandler(ui::EventFlags modifier_flag) |
| 239 StickyKeysHandlerDelegate* delegate) | |
| 240 : modifier_flag_(modifier_flag), | 214 : modifier_flag_(modifier_flag), |
| 241 current_state_(STICKY_KEY_STATE_DISABLED), | 215 current_state_(STICKY_KEY_STATE_DISABLED), |
| 242 event_from_myself_(false), | |
| 243 preparing_to_enable_(false), | 216 preparing_to_enable_(false), |
| 244 scroll_delta_(0), | 217 scroll_delta_(0) { |
| 245 delegate_(delegate) { | |
| 246 } | 218 } |
| 247 | 219 |
| 248 StickyKeysHandler::~StickyKeysHandler() { | 220 StickyKeysHandler::~StickyKeysHandler() { |
| 249 } | 221 } |
| 250 | 222 |
| 251 StickyKeysHandler::StickyKeysHandlerDelegate::StickyKeysHandlerDelegate() { | 223 bool StickyKeysHandler::HandleKeyEvent(const ui::KeyEvent& event, |
| 252 } | 224 ui::KeyboardCode key_code, |
| 253 | 225 int* mod_down_flags, |
| 254 StickyKeysHandler::StickyKeysHandlerDelegate::~StickyKeysHandlerDelegate() { | 226 int* mod_up_flags) { |
| 255 } | |
| 256 | |
| 257 bool StickyKeysHandler::HandleKeyEvent(ui::KeyEvent* event) { | |
| 258 if (event_from_myself_) | |
| 259 return false; // Do not handle self-generated key event. | |
| 260 switch (current_state_) { | 227 switch (current_state_) { |
| 261 case STICKY_KEY_STATE_DISABLED: | 228 case STICKY_KEY_STATE_DISABLED: |
| 262 return HandleDisabledState(event); | 229 return HandleDisabledState(event, key_code); |
| 263 case STICKY_KEY_STATE_ENABLED: | 230 case STICKY_KEY_STATE_ENABLED: |
| 264 return HandleEnabledState(event); | 231 return HandleEnabledState(event, key_code, mod_down_flags, mod_up_flags); |
| 265 case STICKY_KEY_STATE_LOCKED: | 232 case STICKY_KEY_STATE_LOCKED: |
| 266 return HandleLockedState(event); | 233 return HandleLockedState(event, key_code, mod_down_flags, mod_up_flags); |
| 267 } | 234 } |
| 268 NOTREACHED(); | 235 NOTREACHED(); |
| 269 return false; | 236 return false; |
| 270 } | 237 } |
| 271 | 238 |
| 272 bool StickyKeysHandler::HandleMouseEvent(ui::MouseEvent* event) { | 239 bool StickyKeysHandler::HandleMouseEvent( |
| 240 const ui::MouseEvent& event, |
| 241 int* mod_down_flags, |
| 242 int* mod_up_flags) { |
| 273 if (ShouldModifyMouseEvent(event)) | 243 if (ShouldModifyMouseEvent(event)) |
| 274 preparing_to_enable_ = false; | 244 preparing_to_enable_ = false; |
| 275 | 245 |
| 276 if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED | 246 if (current_state_ == STICKY_KEY_STATE_DISABLED || |
| 277 || !ShouldModifyMouseEvent(event)) { | 247 !ShouldModifyMouseEvent(event)) { |
| 278 return false; | 248 return false; |
| 279 } | 249 } |
| 280 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || | 250 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || |
| 281 current_state_ == STICKY_KEY_STATE_LOCKED); | 251 current_state_ == STICKY_KEY_STATE_LOCKED); |
| 282 | 252 |
| 283 AppendModifier(event); | 253 *mod_down_flags |= modifier_flag_; |
| 284 // Only disable on the mouse released event in normal, non-locked mode. | 254 // Only disable on the mouse released event in normal, non-locked mode. |
| 285 if (current_state_ == STICKY_KEY_STATE_ENABLED && | 255 if (current_state_ == STICKY_KEY_STATE_ENABLED && |
| 286 event->type() != ui::ET_MOUSE_PRESSED) { | 256 event.type() != ui::ET_MOUSE_PRESSED) { |
| 287 current_state_ = STICKY_KEY_STATE_DISABLED; | 257 current_state_ = STICKY_KEY_STATE_DISABLED; |
| 288 DispatchEventAndReleaseModifier(event); | 258 *mod_up_flags |= modifier_flag_; |
| 289 return true; | 259 return false; |
| 290 } | 260 } |
| 291 | 261 |
| 292 return false; | 262 return false; |
| 293 } | 263 } |
| 294 | 264 |
| 295 bool StickyKeysHandler::HandleScrollEvent(ui::ScrollEvent* event) { | 265 bool StickyKeysHandler::HandleScrollEvent( |
| 266 const ui::ScrollEvent& event, |
| 267 int* mod_down_flags, |
| 268 int* mod_up_flags) { |
| 296 preparing_to_enable_ = false; | 269 preparing_to_enable_ = false; |
| 297 if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED) | 270 if (current_state_ == STICKY_KEY_STATE_DISABLED) |
| 298 return false; | 271 return false; |
| 299 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || | 272 DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || |
| 300 current_state_ == STICKY_KEY_STATE_LOCKED); | 273 current_state_ == STICKY_KEY_STATE_LOCKED); |
| 301 | 274 |
| 302 // We detect a direction change if the current |scroll_delta_| is assigned | 275 // We detect a direction change if the current |scroll_delta_| is assigned |
| 303 // and the offset of the current scroll event has the opposing sign. | 276 // and the offset of the current scroll event has the opposing sign. |
| 304 bool direction_changed = false; | 277 bool direction_changed = false; |
| 305 if (current_state_ == STICKY_KEY_STATE_ENABLED && | 278 if (current_state_ == STICKY_KEY_STATE_ENABLED && |
| 306 event->type() == ui::ET_SCROLL) { | 279 event.type() == ui::ET_SCROLL) { |
| 307 int offset = event->y_offset(); | 280 int offset = event.y_offset(); |
| 308 if (scroll_delta_) | 281 if (scroll_delta_) |
| 309 direction_changed = offset * scroll_delta_ <= 0; | 282 direction_changed = offset * scroll_delta_ <= 0; |
| 310 scroll_delta_ = offset; | 283 scroll_delta_ = offset; |
| 311 } | 284 } |
| 312 | 285 |
| 313 if (!direction_changed) | 286 if (!direction_changed) |
| 314 AppendModifier(event); | 287 *mod_down_flags |= modifier_flag_; |
| 315 | 288 |
| 316 // We want to modify all the scroll events in the scroll sequence, which ends | 289 // We want to modify all the scroll events in the scroll sequence, which ends |
| 317 // with a fling start event. We also stop when the scroll sequence changes | 290 // with a fling start event. We also stop when the scroll sequence changes |
| 318 // direction. | 291 // direction. |
| 319 if (current_state_ == STICKY_KEY_STATE_ENABLED && | 292 if (current_state_ == STICKY_KEY_STATE_ENABLED && |
| 320 (event->type() == ui::ET_SCROLL_FLING_START || direction_changed)) { | 293 (event.type() == ui::ET_SCROLL_FLING_START || direction_changed)) { |
| 321 current_state_ = STICKY_KEY_STATE_DISABLED; | 294 current_state_ = STICKY_KEY_STATE_DISABLED; |
| 322 scroll_delta_ = 0; | 295 scroll_delta_ = 0; |
| 323 DispatchEventAndReleaseModifier(event); | 296 *mod_up_flags |= modifier_flag_; |
| 324 return true; | 297 return false; |
| 325 } | 298 } |
| 326 | 299 |
| 327 return false; | 300 return false; |
| 328 } | 301 } |
| 329 | 302 |
| 330 StickyKeysHandler::KeyEventType | 303 int StickyKeysHandler::GetModifierUpEvent(scoped_ptr<ui::Event>* new_event) { |
| 331 StickyKeysHandler::TranslateKeyEvent(ui::KeyEvent* event) { | 304 if (current_state_ != STICKY_KEY_STATE_DISABLED || !modifier_up_event_) |
| 305 return 0; |
| 306 DCHECK(new_event); |
| 307 if (*new_event) |
| 308 return 1; |
| 309 new_event->reset(modifier_up_event_.release()); |
| 310 return 0; |
| 311 } |
| 312 |
| 313 StickyKeysHandler::KeyEventType StickyKeysHandler::TranslateKeyEvent( |
| 314 ui::EventType type, |
| 315 ui::KeyboardCode key_code) { |
| 332 bool is_target_key = false; | 316 bool is_target_key = false; |
| 333 if (event->key_code() == ui::VKEY_SHIFT || | 317 if (key_code == ui::VKEY_SHIFT || |
| 334 event->key_code() == ui::VKEY_LSHIFT || | 318 key_code == ui::VKEY_LSHIFT || |
| 335 event->key_code() == ui::VKEY_RSHIFT) { | 319 key_code == ui::VKEY_RSHIFT) { |
| 336 is_target_key = (modifier_flag_ == ui::EF_SHIFT_DOWN); | 320 is_target_key = (modifier_flag_ == ui::EF_SHIFT_DOWN); |
| 337 } else if (event->key_code() == ui::VKEY_CONTROL || | 321 } else if (key_code == ui::VKEY_CONTROL || |
| 338 event->key_code() == ui::VKEY_LCONTROL || | 322 key_code == ui::VKEY_LCONTROL || |
| 339 event->key_code() == ui::VKEY_RCONTROL) { | 323 key_code == ui::VKEY_RCONTROL) { |
| 340 is_target_key = (modifier_flag_ == ui::EF_CONTROL_DOWN); | 324 is_target_key = (modifier_flag_ == ui::EF_CONTROL_DOWN); |
| 341 } else if (event->key_code() == ui::VKEY_MENU || | 325 } else if (key_code == ui::VKEY_MENU || |
| 342 event->key_code() == ui::VKEY_LMENU || | 326 key_code == ui::VKEY_LMENU || |
| 343 event->key_code() == ui::VKEY_RMENU) { | 327 key_code == ui::VKEY_RMENU) { |
| 344 is_target_key = (modifier_flag_ == ui::EF_ALT_DOWN); | 328 is_target_key = (modifier_flag_ == ui::EF_ALT_DOWN); |
| 345 } else if (event->key_code() == ui::VKEY_ALTGR) { | 329 } else if (key_code == ui::VKEY_ALTGR) { |
| 346 is_target_key = (modifier_flag_ == ui::EF_ALTGR_DOWN); | 330 is_target_key = (modifier_flag_ == ui::EF_ALTGR_DOWN); |
| 347 } else if (event->key_code() == ui::VKEY_OEM_8) { | 331 } else if (key_code == ui::VKEY_OEM_8) { |
| 348 is_target_key = (modifier_flag_ == ui::EF_MOD3_DOWN); | 332 is_target_key = (modifier_flag_ == ui::EF_MOD3_DOWN); |
| 349 } else { | 333 } else { |
| 350 return event->type() == ui::ET_KEY_PRESSED ? | 334 return type == ui::ET_KEY_PRESSED ? |
| 351 NORMAL_KEY_DOWN : NORMAL_KEY_UP; | 335 NORMAL_KEY_DOWN : NORMAL_KEY_UP; |
| 352 } | 336 } |
| 353 | 337 |
| 354 if (is_target_key) { | 338 if (is_target_key) { |
| 355 return event->type() == ui::ET_KEY_PRESSED ? | 339 return type == ui::ET_KEY_PRESSED ? |
| 356 TARGET_MODIFIER_DOWN : TARGET_MODIFIER_UP; | 340 TARGET_MODIFIER_DOWN : TARGET_MODIFIER_UP; |
| 357 } | 341 } |
| 358 return event->type() == ui::ET_KEY_PRESSED ? | 342 return type == ui::ET_KEY_PRESSED ? |
| 359 OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP; | 343 OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP; |
| 360 } | 344 } |
| 361 | 345 |
| 362 bool StickyKeysHandler::HandleDisabledState(ui::KeyEvent* event) { | 346 bool StickyKeysHandler::HandleDisabledState(const ui::KeyEvent& event, |
| 363 switch (TranslateKeyEvent(event)) { | 347 ui::KeyboardCode key_code) { |
| 348 switch (TranslateKeyEvent(event.type(), key_code)) { |
| 364 case TARGET_MODIFIER_UP: | 349 case TARGET_MODIFIER_UP: |
| 365 if (preparing_to_enable_) { | 350 if (preparing_to_enable_) { |
| 366 preparing_to_enable_ = false; | 351 preparing_to_enable_ = false; |
| 367 scroll_delta_ = 0; | 352 scroll_delta_ = 0; |
| 368 current_state_ = STICKY_KEY_STATE_ENABLED; | 353 current_state_ = STICKY_KEY_STATE_ENABLED; |
| 369 modifier_up_event_.reset(new ui::KeyEvent(*event)); | 354 modifier_up_event_.reset(new ui::KeyEvent(event)); |
| 370 return true; | 355 return true; |
| 371 } | 356 } |
| 372 return false; | 357 return false; |
| 373 case TARGET_MODIFIER_DOWN: | 358 case TARGET_MODIFIER_DOWN: |
| 374 preparing_to_enable_ = true; | 359 preparing_to_enable_ = true; |
| 375 return false; | 360 return false; |
| 376 case NORMAL_KEY_DOWN: | 361 case NORMAL_KEY_DOWN: |
| 377 preparing_to_enable_ = false; | 362 preparing_to_enable_ = false; |
| 378 return false; | 363 return false; |
| 379 case NORMAL_KEY_UP: | 364 case NORMAL_KEY_UP: |
| 380 case OTHER_MODIFIER_DOWN: | 365 case OTHER_MODIFIER_DOWN: |
| 381 case OTHER_MODIFIER_UP: | 366 case OTHER_MODIFIER_UP: |
| 382 return false; | 367 return false; |
| 383 } | 368 } |
| 384 NOTREACHED(); | 369 NOTREACHED(); |
| 385 return false; | 370 return false; |
| 386 } | 371 } |
| 387 | 372 |
| 388 bool StickyKeysHandler::HandleEnabledState(ui::KeyEvent* event) { | 373 bool StickyKeysHandler::HandleEnabledState(const ui::KeyEvent& event, |
| 389 switch (TranslateKeyEvent(event)) { | 374 ui::KeyboardCode key_code, |
| 375 int* mod_down_flags, |
| 376 int* mod_up_flags) { |
| 377 switch (TranslateKeyEvent(event.type(), key_code)) { |
| 390 case NORMAL_KEY_UP: | 378 case NORMAL_KEY_UP: |
| 391 case TARGET_MODIFIER_DOWN: | 379 case TARGET_MODIFIER_DOWN: |
| 392 return true; | 380 return false; |
| 393 case TARGET_MODIFIER_UP: | 381 case TARGET_MODIFIER_UP: |
| 394 current_state_ = STICKY_KEY_STATE_LOCKED; | 382 current_state_ = STICKY_KEY_STATE_LOCKED; |
| 395 modifier_up_event_.reset(); | 383 modifier_up_event_.reset(); |
| 396 return true; | 384 return true; |
| 397 case NORMAL_KEY_DOWN: { | 385 case NORMAL_KEY_DOWN: { |
| 398 current_state_ = STICKY_KEY_STATE_DISABLED; | 386 current_state_ = STICKY_KEY_STATE_DISABLED; |
| 399 AppendModifier(event); | 387 *mod_down_flags |= modifier_flag_; |
| 400 DispatchEventAndReleaseModifier(event); | 388 *mod_up_flags |= modifier_flag_; |
| 401 return true; | 389 return false; |
| 402 } | 390 } |
| 403 case OTHER_MODIFIER_DOWN: | 391 case OTHER_MODIFIER_DOWN: |
| 404 case OTHER_MODIFIER_UP: | 392 case OTHER_MODIFIER_UP: |
| 405 return false; | 393 return false; |
| 406 } | 394 } |
| 407 NOTREACHED(); | 395 NOTREACHED(); |
| 408 return false; | 396 return false; |
| 409 } | 397 } |
| 410 | 398 |
| 411 bool StickyKeysHandler::HandleLockedState(ui::KeyEvent* event) { | 399 bool StickyKeysHandler::HandleLockedState(const ui::KeyEvent& event, |
| 412 switch (TranslateKeyEvent(event)) { | 400 ui::KeyboardCode key_code, |
| 401 int* mod_down_flags, |
| 402 int* mod_up_flags) { |
| 403 switch (TranslateKeyEvent(event.type(), key_code)) { |
| 413 case TARGET_MODIFIER_DOWN: | 404 case TARGET_MODIFIER_DOWN: |
| 414 return true; | 405 return true; |
| 415 case TARGET_MODIFIER_UP: | 406 case TARGET_MODIFIER_UP: |
| 416 current_state_ = STICKY_KEY_STATE_DISABLED; | 407 current_state_ = STICKY_KEY_STATE_DISABLED; |
| 417 return false; | 408 return false; |
| 418 case NORMAL_KEY_DOWN: | 409 case NORMAL_KEY_DOWN: |
| 419 case NORMAL_KEY_UP: | 410 case NORMAL_KEY_UP: |
| 420 AppendModifier(event); | 411 *mod_down_flags |= modifier_flag_; |
| 421 return false; | 412 return false; |
| 422 case OTHER_MODIFIER_DOWN: | 413 case OTHER_MODIFIER_DOWN: |
| 423 case OTHER_MODIFIER_UP: | 414 case OTHER_MODIFIER_UP: |
| 424 return false; | 415 return false; |
| 425 } | 416 } |
| 426 NOTREACHED(); | 417 NOTREACHED(); |
| 427 return false; | 418 return false; |
| 428 } | 419 } |
| 429 | 420 |
| 430 void StickyKeysHandler::DispatchEventAndReleaseModifier(ui::Event* event) { | |
| 431 DCHECK(event->IsKeyEvent() || | |
| 432 event->IsMouseEvent() || | |
| 433 event->IsScrollEvent()); | |
| 434 DCHECK(modifier_up_event_.get()); | |
| 435 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
| 436 DCHECK(target); | |
| 437 aura::Window* root_window = target->GetRootWindow(); | |
| 438 DCHECK(root_window); | |
| 439 | |
| 440 aura::WindowTracker window_tracker; | |
| 441 window_tracker.Add(target); | |
| 442 | |
| 443 event_from_myself_ = true; | |
| 444 if (event->IsKeyEvent()) { | |
| 445 delegate_->DispatchKeyEvent(static_cast<ui::KeyEvent*>(event), target); | |
| 446 } else if (event->IsMouseEvent()) { | |
| 447 delegate_->DispatchMouseEvent(static_cast<ui::MouseEvent*>(event), target); | |
| 448 } else { | |
| 449 delegate_->DispatchScrollEvent( | |
| 450 static_cast<ui::ScrollEvent*>(event), target); | |
| 451 } | |
| 452 | |
| 453 // The action triggered above may have destroyed the event target, in which | |
| 454 // case we will dispatch the modifier up event to the root window instead. | |
| 455 aura::Window* modifier_up_target = | |
| 456 window_tracker.Contains(target) ? target : root_window; | |
| 457 delegate_->DispatchKeyEvent(modifier_up_event_.get(), modifier_up_target); | |
| 458 event_from_myself_ = false; | |
| 459 } | |
| 460 | |
| 461 void StickyKeysHandler::AppendNativeEventMask(unsigned int* state) { | |
| 462 #if defined(USE_X11) | |
| 463 unsigned int& state_ref = *state; | |
| 464 switch (modifier_flag_) { | |
| 465 case ui::EF_CONTROL_DOWN: | |
| 466 state_ref |= ControlMask; | |
| 467 break; | |
| 468 case ui::EF_ALT_DOWN: | |
| 469 state_ref |= Mod1Mask; | |
| 470 break; | |
| 471 case ui::EF_ALTGR_DOWN: | |
| 472 state_ref |= Mod5Mask; | |
| 473 break; | |
| 474 case ui::EF_SHIFT_DOWN: | |
| 475 state_ref |= ShiftMask; | |
| 476 break; | |
| 477 case ui::EF_MOD3_DOWN: | |
| 478 state_ref |= Mod3Mask; | |
| 479 break; | |
| 480 default: | |
| 481 NOTREACHED(); | |
| 482 } | |
| 483 #endif | |
| 484 } | |
| 485 | |
| 486 void StickyKeysHandler::AppendModifier(ui::KeyEvent* event) { | |
| 487 #if defined(USE_X11) | |
| 488 XEvent* xev = event->native_event(); | |
| 489 if (xev) { | |
| 490 XKeyEvent* xkey = &(xev->xkey); | |
| 491 AppendNativeEventMask(&xkey->state); | |
| 492 } | |
| 493 #elif defined(USE_OZONE) | |
| 494 NOTIMPLEMENTED() << "Modifier key is not handled"; | |
| 495 #endif | |
| 496 event->set_flags(event->flags() | modifier_flag_); | |
| 497 event->set_character(ui::GetCharacterFromKeyCode(event->key_code(), | |
| 498 event->flags())); | |
| 499 event->NormalizeFlags(); | |
| 500 } | |
| 501 | |
| 502 void StickyKeysHandler::AppendModifier(ui::MouseEvent* event) { | |
| 503 #if defined(USE_X11) | |
| 504 // The native mouse event can either be a classic X button event or an | |
| 505 // XInput2 button event. | |
| 506 XEvent* xev = event->native_event(); | |
| 507 if (xev) { | |
| 508 switch (xev->type) { | |
| 509 case ButtonPress: | |
| 510 case ButtonRelease: { | |
| 511 XButtonEvent* xkey = &(xev->xbutton); | |
| 512 AppendNativeEventMask(&xkey->state); | |
| 513 break; | |
| 514 } | |
| 515 case GenericEvent: { | |
| 516 XIDeviceEvent* xievent = | |
| 517 static_cast<XIDeviceEvent*>(xev->xcookie.data); | |
| 518 CHECK(xievent->evtype == XI_ButtonPress || | |
| 519 xievent->evtype == XI_ButtonRelease); | |
| 520 AppendNativeEventMask( | |
| 521 reinterpret_cast<unsigned int*>(&xievent->mods.effective)); | |
| 522 break; | |
| 523 } | |
| 524 default: | |
| 525 NOTREACHED(); | |
| 526 } | |
| 527 } | |
| 528 #elif defined(USE_OZONE) | |
| 529 NOTIMPLEMENTED() << "Modifier key is not handled"; | |
| 530 #endif | |
| 531 event->set_flags(event->flags() | modifier_flag_); | |
| 532 } | |
| 533 | |
| 534 void StickyKeysHandler::AppendModifier(ui::ScrollEvent* event) { | |
| 535 #if defined(USE_X11) | |
| 536 XEvent* xev = event->native_event(); | |
| 537 if (xev) { | |
| 538 XIDeviceEvent* xievent = | |
| 539 static_cast<XIDeviceEvent*>(xev->xcookie.data); | |
| 540 if (xievent) { | |
| 541 AppendNativeEventMask(reinterpret_cast<unsigned int*>( | |
| 542 &xievent->mods.effective)); | |
| 543 } | |
| 544 } | |
| 545 #elif defined(USE_OZONE) | |
| 546 NOTIMPLEMENTED() << "Modifier key is not handled"; | |
| 547 #endif | |
| 548 event->set_flags(event->flags() | modifier_flag_); | |
| 549 } | |
| 550 | |
| 551 } // namespace ash | 421 } // namespace ash |
| OLD | NEW |