Index: trunk/src/ash/sticky_keys/sticky_keys_controller.cc |
=================================================================== |
--- trunk/src/ash/sticky_keys/sticky_keys_controller.cc (revision 278418) |
+++ trunk/src/ash/sticky_keys/sticky_keys_controller.cc (working copy) |
@@ -4,6 +4,12 @@ |
#include "ash/sticky_keys/sticky_keys_controller.h" |
+#if defined(USE_X11) |
+#include <X11/extensions/XInput2.h> |
+#include <X11/Xlib.h> |
+#undef RootWindow |
+#endif |
+ |
#include "ash/sticky_keys/sticky_keys_overlay.h" |
#include "base/basictypes.h" |
#include "base/debug/stack_trace.h" |
@@ -19,28 +25,81 @@ |
namespace { |
// Returns true if the type of mouse event should be modified by sticky keys. |
-bool ShouldModifyMouseEvent(const ui::MouseEvent& event) { |
- ui::EventType type = event.type(); |
+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; |
} |
-// Handle the common tail of event rewriting. |
-ui::EventRewriteStatus RewriteUpdate(bool consumed, |
- bool released, |
- int mod_down_flags, |
- int* flags) { |
- int changed_down_flags = mod_down_flags & ~*flags; |
- *flags |= mod_down_flags; |
- if (consumed) |
- return ui::EVENT_REWRITE_DISCARD; |
- if (released) |
- return ui::EVENT_REWRITE_DISPATCH_ANOTHER; |
- if (changed_down_flags) |
- return ui::EVENT_REWRITE_REWRITTEN; |
- return ui::EVENT_REWRITE_CONTINUE; |
+// 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: |
+ void DispatchEvent(ui::Event* event, aura::Window* target); |
+ |
+ DISALLOW_COPY_AND_ASSIGN(StickyKeysHandlerDelegateImpl); |
+}; |
+ |
+StickyKeysHandlerDelegateImpl::StickyKeysHandlerDelegateImpl() { |
} |
+StickyKeysHandlerDelegateImpl::~StickyKeysHandlerDelegateImpl() { |
+} |
+ |
+void StickyKeysHandlerDelegateImpl::DispatchKeyEvent(ui::KeyEvent* event, |
+ aura::Window* target) { |
+ DispatchEvent(event, target); |
+} |
+ |
+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()) { |
+ aura::Window* source = static_cast<aura::Window*>(event->target()); |
+ ui::MouseWheelEvent new_event(*static_cast<ui::MouseWheelEvent*>(event), |
+ source, |
+ source->GetRootWindow()); |
+ // Transform the location back to host coordinates before dispatching. |
+ new_event.UpdateForRootTransform(source->GetHost()->GetRootTransform()); |
+ DispatchEvent(&new_event, target); |
+ } else { |
+ aura::Window* source = static_cast<aura::Window*>(event->target()); |
+ ui::MouseEvent new_event(*event, source, source->GetRootWindow()); |
+ // Transform the location back to host coordinates before dispatching. |
+ new_event.UpdateForRootTransform(source->GetHost()->GetRootTransform()); |
+ DispatchEvent(&new_event, target); |
+ } |
+} |
+ |
+void StickyKeysHandlerDelegateImpl::DispatchScrollEvent( |
+ ui::ScrollEvent* event, |
+ aura::Window* target) { |
+ DispatchEvent(event, target); |
+} |
+ |
+void StickyKeysHandlerDelegateImpl::DispatchEvent(ui::Event* event, |
+ aura::Window* target) { |
+ DCHECK(target); |
+ ui::EventDispatchDetails details = |
+ target->GetHost()->event_processor()->OnEventFromSource(event); |
+ if (details.dispatcher_destroyed) |
+ return; |
+} |
+ |
} // namespace |
/////////////////////////////////////////////////////////////////////////////// |
@@ -61,11 +120,21 @@ |
// 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)); |
- alt_sticky_key_.reset(new StickyKeysHandler(ui::EF_ALT_DOWN)); |
- altgr_sticky_key_.reset(new StickyKeysHandler(ui::EF_ALTGR_DOWN)); |
- ctrl_sticky_key_.reset(new StickyKeysHandler(ui::EF_CONTROL_DOWN)); |
- mod3_sticky_key_.reset(new StickyKeysHandler(ui::EF_MOD3_DOWN)); |
+ shift_sticky_key_.reset( |
+ new StickyKeysHandler(ui::EF_SHIFT_DOWN, |
+ new StickyKeysHandlerDelegateImpl())); |
+ alt_sticky_key_.reset( |
+ new StickyKeysHandler(ui::EF_ALT_DOWN, |
+ new StickyKeysHandlerDelegateImpl())); |
+ altgr_sticky_key_.reset( |
+ new StickyKeysHandler(ui::EF_ALTGR_DOWN, |
+ new StickyKeysHandlerDelegateImpl())); |
+ ctrl_sticky_key_.reset( |
+ new StickyKeysHandler(ui::EF_CONTROL_DOWN, |
+ new StickyKeysHandlerDelegateImpl())); |
+ mod3_sticky_key_.reset( |
+ new StickyKeysHandler(ui::EF_MOD3_DOWN, |
+ new StickyKeysHandlerDelegateImpl())); |
overlay_.reset(new StickyKeysOverlay()); |
overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_); |
@@ -86,103 +155,56 @@ |
} |
} |
-bool StickyKeysController::HandleKeyEvent(const ui::KeyEvent& event, |
- ui::KeyboardCode key_code, |
- int* mod_down_flags, |
- bool* released) { |
- return shift_sticky_key_->HandleKeyEvent( |
- event, key_code, mod_down_flags, released) || |
- alt_sticky_key_->HandleKeyEvent( |
- event, key_code, mod_down_flags, released) || |
- altgr_sticky_key_->HandleKeyEvent( |
- event, key_code, mod_down_flags, released) || |
- ctrl_sticky_key_->HandleKeyEvent( |
- event, key_code, mod_down_flags, released) || |
- mod3_sticky_key_->HandleKeyEvent( |
- event, key_code, mod_down_flags, released); |
+bool StickyKeysController::HandleKeyEvent(ui::KeyEvent* event) { |
+ return shift_sticky_key_->HandleKeyEvent(event) || |
+ alt_sticky_key_->HandleKeyEvent(event) || |
+ altgr_sticky_key_->HandleKeyEvent(event) || |
+ ctrl_sticky_key_->HandleKeyEvent(event) || |
+ mod3_sticky_key_->HandleKeyEvent(event); |
} |
-bool StickyKeysController::HandleMouseEvent(const ui::MouseEvent& event, |
- int* mod_down_flags, |
- bool* released) { |
- return shift_sticky_key_->HandleMouseEvent( |
- event, mod_down_flags, released) || |
- alt_sticky_key_->HandleMouseEvent( |
- event, mod_down_flags, released) || |
- altgr_sticky_key_->HandleMouseEvent( |
- event, mod_down_flags, released) || |
- ctrl_sticky_key_->HandleMouseEvent( |
- event, mod_down_flags, released) || |
- mod3_sticky_key_->HandleMouseEvent( |
- event, mod_down_flags, released); |
+bool StickyKeysController::HandleMouseEvent(ui::MouseEvent* event) { |
+ return shift_sticky_key_->HandleMouseEvent(event) || |
+ alt_sticky_key_->HandleMouseEvent(event) || |
+ altgr_sticky_key_->HandleMouseEvent(event) || |
+ ctrl_sticky_key_->HandleMouseEvent(event) || |
+ mod3_sticky_key_->HandleMouseEvent(event); |
} |
-bool StickyKeysController::HandleScrollEvent(const ui::ScrollEvent& event, |
- int* mod_down_flags, |
- bool* released) { |
- return shift_sticky_key_->HandleScrollEvent( |
- event, mod_down_flags, released) || |
- alt_sticky_key_->HandleScrollEvent( |
- event, mod_down_flags, released) || |
- altgr_sticky_key_->HandleScrollEvent( |
- event, mod_down_flags, released) || |
- ctrl_sticky_key_->HandleScrollEvent( |
- event, mod_down_flags, released) || |
- mod3_sticky_key_->HandleScrollEvent( |
- event, mod_down_flags, released); |
+bool StickyKeysController::HandleScrollEvent(ui::ScrollEvent* event) { |
+ return shift_sticky_key_->HandleScrollEvent(event) || |
+ alt_sticky_key_->HandleScrollEvent(event) || |
+ altgr_sticky_key_->HandleScrollEvent(event) || |
+ ctrl_sticky_key_->HandleScrollEvent(event) || |
+ mod3_sticky_key_->HandleScrollEvent(event); |
} |
-ui::EventRewriteStatus StickyKeysController::RewriteKeyEvent( |
- const ui::KeyEvent& event, |
- ui::KeyboardCode key_code, |
- int* flags) { |
- if (!enabled_) |
- return ui::EVENT_REWRITE_CONTINUE; |
- int mod_down_flags = 0; |
- bool released = false; |
- bool consumed = HandleKeyEvent(event, key_code, &mod_down_flags, &released); |
- UpdateOverlay(); |
- return RewriteUpdate(consumed, released, mod_down_flags, flags); |
-} |
+void StickyKeysController::OnKeyEvent(ui::KeyEvent* event) { |
+ // Do not consume a translated key event which is generated by an IME. |
+ if (event->IsTranslated()) |
+ return; |
-ui::EventRewriteStatus StickyKeysController::RewriteMouseEvent( |
- const ui::MouseEvent& event, |
- int* flags) { |
- if (!enabled_) |
- return ui::EVENT_REWRITE_CONTINUE; |
- int mod_down_flags = 0; |
- bool released = false; |
- bool consumed = HandleMouseEvent(event, &mod_down_flags, &released); |
- UpdateOverlay(); |
- return RewriteUpdate(consumed, released, mod_down_flags, flags); |
+ if (enabled_) { |
+ if (HandleKeyEvent(event)) |
+ event->StopPropagation(); |
+ UpdateOverlay(); |
+ } |
} |
-ui::EventRewriteStatus StickyKeysController::RewriteScrollEvent( |
- const ui::ScrollEvent& event, |
- int* flags) { |
- if (!enabled_) |
- return ui::EVENT_REWRITE_CONTINUE; |
- int mod_down_flags = 0; |
- bool released = false; |
- bool consumed = HandleScrollEvent(event, &mod_down_flags, &released); |
- UpdateOverlay(); |
- return RewriteUpdate(consumed, released, mod_down_flags, flags); |
+void StickyKeysController::OnMouseEvent(ui::MouseEvent* event) { |
+ if (enabled_) { |
+ if (HandleMouseEvent(event)) |
+ event->StopPropagation(); |
+ UpdateOverlay(); |
+ } |
} |
-ui::EventRewriteStatus StickyKeysController::NextDispatchEvent( |
- scoped_ptr<ui::Event>* new_event) { |
- DCHECK(new_event); |
- new_event->reset(); |
- int remaining = shift_sticky_key_->GetModifierUpEvent(new_event) + |
- alt_sticky_key_->GetModifierUpEvent(new_event) + |
- altgr_sticky_key_->GetModifierUpEvent(new_event) + |
- ctrl_sticky_key_->GetModifierUpEvent(new_event) + |
- mod3_sticky_key_->GetModifierUpEvent(new_event); |
- if (!new_event) |
- return ui::EVENT_REWRITE_CONTINUE; |
- if (remaining) |
- return ui::EVENT_REWRITE_DISPATCH_ANOTHER; |
- return ui::EVENT_REWRITE_REWRITTEN; |
+void StickyKeysController::OnScrollEvent(ui::ScrollEvent* event) { |
+ if (enabled_) { |
+ if (HandleScrollEvent(event)) |
+ event->StopPropagation(); |
+ UpdateOverlay(); |
+ } |
} |
void StickyKeysController::UpdateOverlay() { |
@@ -213,64 +235,66 @@ |
/////////////////////////////////////////////////////////////////////////////// |
// StickyKeysHandler |
-StickyKeysHandler::StickyKeysHandler(ui::EventFlags modifier_flag) |
+StickyKeysHandler::StickyKeysHandler(ui::EventFlags modifier_flag, |
+ StickyKeysHandlerDelegate* delegate) |
: modifier_flag_(modifier_flag), |
current_state_(STICKY_KEY_STATE_DISABLED), |
+ event_from_myself_(false), |
preparing_to_enable_(false), |
- scroll_delta_(0) { |
+ scroll_delta_(0), |
+ delegate_(delegate) { |
} |
StickyKeysHandler::~StickyKeysHandler() { |
} |
-bool StickyKeysHandler::HandleKeyEvent(const ui::KeyEvent& event, |
- ui::KeyboardCode key_code, |
- int* mod_down_flags, |
- bool* released) { |
+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 STICKY_KEY_STATE_DISABLED: |
- return HandleDisabledState(event, key_code); |
+ return HandleDisabledState(event); |
case STICKY_KEY_STATE_ENABLED: |
- return HandleEnabledState(event, key_code, mod_down_flags, released); |
+ return HandleEnabledState(event); |
case STICKY_KEY_STATE_LOCKED: |
- return HandleLockedState(event, key_code, mod_down_flags, released); |
+ return HandleLockedState(event); |
} |
NOTREACHED(); |
return false; |
} |
-bool StickyKeysHandler::HandleMouseEvent( |
- const ui::MouseEvent& event, |
- int* mod_down_flags, |
- bool* released) { |
+bool StickyKeysHandler::HandleMouseEvent(ui::MouseEvent* event) { |
if (ShouldModifyMouseEvent(event)) |
preparing_to_enable_ = false; |
- if (current_state_ == STICKY_KEY_STATE_DISABLED || |
- !ShouldModifyMouseEvent(event)) { |
+ if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED |
+ || !ShouldModifyMouseEvent(event)) { |
return false; |
} |
DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || |
current_state_ == STICKY_KEY_STATE_LOCKED); |
- *mod_down_flags |= modifier_flag_; |
+ AppendModifier(event); |
// Only disable on the mouse released event in normal, non-locked mode. |
if (current_state_ == STICKY_KEY_STATE_ENABLED && |
- event.type() != ui::ET_MOUSE_PRESSED) { |
+ event->type() != ui::ET_MOUSE_PRESSED) { |
current_state_ = STICKY_KEY_STATE_DISABLED; |
- *released = true; |
- return false; |
+ DispatchEventAndReleaseModifier(event); |
+ return true; |
} |
return false; |
} |
-bool StickyKeysHandler::HandleScrollEvent( |
- const ui::ScrollEvent& event, |
- int* mod_down_flags, |
- bool* released) { |
+bool StickyKeysHandler::HandleScrollEvent(ui::ScrollEvent* event) { |
preparing_to_enable_ = false; |
- if (current_state_ == STICKY_KEY_STATE_DISABLED) |
+ if (event_from_myself_ || current_state_ == STICKY_KEY_STATE_DISABLED) |
return false; |
DCHECK(current_state_ == STICKY_KEY_STATE_ENABLED || |
current_state_ == STICKY_KEY_STATE_LOCKED); |
@@ -279,82 +303,70 @@ |
// and the offset of the current scroll event has the opposing sign. |
bool direction_changed = false; |
if (current_state_ == STICKY_KEY_STATE_ENABLED && |
- event.type() == ui::ET_SCROLL) { |
- int offset = event.y_offset(); |
+ 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) |
- *mod_down_flags |= modifier_flag_; |
+ 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_ == STICKY_KEY_STATE_ENABLED && |
- (event.type() == ui::ET_SCROLL_FLING_START || direction_changed)) { |
+ (event->type() == ui::ET_SCROLL_FLING_START || direction_changed)) { |
current_state_ = STICKY_KEY_STATE_DISABLED; |
scroll_delta_ = 0; |
- *released = true; |
- return false; |
+ DispatchEventAndReleaseModifier(event); |
+ return true; |
} |
return false; |
} |
-int StickyKeysHandler::GetModifierUpEvent(scoped_ptr<ui::Event>* new_event) { |
- if (current_state_ != STICKY_KEY_STATE_DISABLED || !modifier_up_event_) |
- return 0; |
- DCHECK(new_event); |
- if (*new_event) |
- return 1; |
- new_event->reset(modifier_up_event_.release()); |
- return 0; |
-} |
- |
-StickyKeysHandler::KeyEventType StickyKeysHandler::TranslateKeyEvent( |
- ui::EventType type, |
- ui::KeyboardCode key_code) { |
+StickyKeysHandler::KeyEventType |
+ StickyKeysHandler::TranslateKeyEvent(ui::KeyEvent* event) { |
bool is_target_key = false; |
- if (key_code == ui::VKEY_SHIFT || |
- key_code == ui::VKEY_LSHIFT || |
- key_code == ui::VKEY_RSHIFT) { |
+ 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 (key_code == ui::VKEY_CONTROL || |
- key_code == ui::VKEY_LCONTROL || |
- key_code == ui::VKEY_RCONTROL) { |
+ } 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 (key_code == ui::VKEY_MENU || |
- key_code == ui::VKEY_LMENU || |
- key_code == ui::VKEY_RMENU) { |
+ } 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 if (key_code == ui::VKEY_ALTGR) { |
+ } else if (event->key_code() == ui::VKEY_ALTGR) { |
is_target_key = (modifier_flag_ == ui::EF_ALTGR_DOWN); |
- } else if (key_code == ui::VKEY_OEM_8) { |
+ } else if (event->key_code() == ui::VKEY_OEM_8) { |
is_target_key = (modifier_flag_ == ui::EF_MOD3_DOWN); |
} else { |
- return type == ui::ET_KEY_PRESSED ? |
+ return event->type() == ui::ET_KEY_PRESSED ? |
NORMAL_KEY_DOWN : NORMAL_KEY_UP; |
} |
if (is_target_key) { |
- return type == ui::ET_KEY_PRESSED ? |
+ return event->type() == ui::ET_KEY_PRESSED ? |
TARGET_MODIFIER_DOWN : TARGET_MODIFIER_UP; |
} |
- return type == ui::ET_KEY_PRESSED ? |
+ return event->type() == ui::ET_KEY_PRESSED ? |
OTHER_MODIFIER_DOWN : OTHER_MODIFIER_UP; |
} |
-bool StickyKeysHandler::HandleDisabledState(const ui::KeyEvent& event, |
- ui::KeyboardCode key_code) { |
- switch (TranslateKeyEvent(event.type(), key_code)) { |
+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_ = STICKY_KEY_STATE_ENABLED; |
- modifier_up_event_.reset(new ui::KeyEvent(event)); |
+ modifier_up_event_.reset(new ui::KeyEvent(*event)); |
return true; |
} |
return false; |
@@ -373,23 +385,20 @@ |
return false; |
} |
-bool StickyKeysHandler::HandleEnabledState(const ui::KeyEvent& event, |
- ui::KeyboardCode key_code, |
- int* mod_down_flags, |
- bool* released) { |
- switch (TranslateKeyEvent(event.type(), key_code)) { |
+bool StickyKeysHandler::HandleEnabledState(ui::KeyEvent* event) { |
+ switch (TranslateKeyEvent(event)) { |
case NORMAL_KEY_UP: |
case TARGET_MODIFIER_DOWN: |
- return false; |
+ return true; |
case TARGET_MODIFIER_UP: |
current_state_ = STICKY_KEY_STATE_LOCKED; |
modifier_up_event_.reset(); |
return true; |
case NORMAL_KEY_DOWN: { |
current_state_ = STICKY_KEY_STATE_DISABLED; |
- *mod_down_flags |= modifier_flag_; |
- *released = true; |
- return false; |
+ AppendModifier(event); |
+ DispatchEventAndReleaseModifier(event); |
+ return true; |
} |
case OTHER_MODIFIER_DOWN: |
case OTHER_MODIFIER_UP: |
@@ -399,11 +408,8 @@ |
return false; |
} |
-bool StickyKeysHandler::HandleLockedState(const ui::KeyEvent& event, |
- ui::KeyboardCode key_code, |
- int* mod_down_flags, |
- bool* released) { |
- switch (TranslateKeyEvent(event.type(), key_code)) { |
+bool StickyKeysHandler::HandleLockedState(ui::KeyEvent* event) { |
+ switch (TranslateKeyEvent(event)) { |
case TARGET_MODIFIER_DOWN: |
return true; |
case TARGET_MODIFIER_UP: |
@@ -411,7 +417,7 @@ |
return false; |
case NORMAL_KEY_DOWN: |
case NORMAL_KEY_UP: |
- *mod_down_flags |= modifier_flag_; |
+ AppendModifier(event); |
return false; |
case OTHER_MODIFIER_DOWN: |
case OTHER_MODIFIER_UP: |
@@ -421,4 +427,125 @@ |
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) { |
+#if defined(USE_X11) |
+ 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_ALTGR_DOWN: |
+ state_ref |= Mod5Mask; |
+ break; |
+ case ui::EF_SHIFT_DOWN: |
+ state_ref |= ShiftMask; |
+ break; |
+ case ui::EF_MOD3_DOWN: |
+ state_ref |= Mod3Mask; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+#endif |
+} |
+ |
+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) |
+ // The native mouse event can either be a classic X button event or an |
+ // XInput2 button event. |
+ XEvent* xev = event->native_event(); |
+ if (xev) { |
+ switch (xev->type) { |
+ case ButtonPress: |
+ case ButtonRelease: { |
+ XButtonEvent* xkey = &(xev->xbutton); |
+ AppendNativeEventMask(&xkey->state); |
+ break; |
+ } |
+ case GenericEvent: { |
+ XIDeviceEvent* xievent = |
+ static_cast<XIDeviceEvent*>(xev->xcookie.data); |
+ CHECK(xievent->evtype == XI_ButtonPress || |
+ xievent->evtype == XI_ButtonRelease); |
+ AppendNativeEventMask( |
+ reinterpret_cast<unsigned int*>(&xievent->mods.effective)); |
+ break; |
+ } |
+ default: |
+ NOTREACHED(); |
+ } |
+ } |
+#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 |