1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/accelerators/key_hold_detector.h"
12 #include "ash/shell.h"
13 #include "base/message_loop/message_loop.h"
14 #include "ui/aura/window_tracker.h"
15 #include "ui/aura/window_tree_host.h"
16 #include "ui/events/event_dispatcher.h"
17 #include "ui/events/event_processor.h"
22 void DispatchPressedEvent(XEvent native_event,
23 scoped_ptr<aura::WindowTracker> tracker) {
24 // The target window may be gone.
25 if (tracker->windows().empty())
27 aura::Window* target = *(tracker->windows().begin());
28 ui::KeyEvent event(&native_event);
29 event.set_flags(event.flags() | ui::EF_IS_SYNTHESIZED);
30 ui::EventDispatchDetails result ALLOW_UNUSED =
31 target->GetHost()->event_processor()->OnEventFromSource(&event);
34 void PostPressedEvent(ui::KeyEvent* event) {
35 // Modify RELEASED event to PRESSED event.
36 XEvent xkey = *(event->native_event());
37 xkey.xkey.type = KeyPress;
38 xkey.xkey.state |= ShiftMask;
39 scoped_ptr<aura::WindowTracker> tracker(new aura::WindowTracker);
40 tracker->Add(static_cast<aura::Window*>(event->target()));
42 base::MessageLoopForUI::current()->PostTask(
44 base::Bind(&DispatchPressedEvent, xkey, base::Passed(&tracker)));
49 KeyHoldDetector::KeyHoldDetector(scoped_ptr<Delegate> delegate)
51 delegate_(delegate.Pass()) {}
53 KeyHoldDetector::~KeyHoldDetector() {}
55 void KeyHoldDetector::OnKeyEvent(ui::KeyEvent* event) {
56 if (!delegate_->ShouldProcessEvent(event))
59 if (delegate_->IsStartEvent(event)) {
62 // Pass through posted event.
63 if (event->flags() & ui::EF_IS_SYNTHESIZED) {
64 event->set_flags(event->flags() & ~ui::EF_IS_SYNTHESIZED);
68 // Don't process ET_KEY_PRESSED event yet. The ET_KEY_PRESSED
69 // event will be generated upon ET_KEY_RELEASEED event below.
70 event->StopPropagation();
76 delegate_->OnKeyHold(event);
77 event->StopPropagation();
80 } else if (event->type() == ui::ET_KEY_RELEASED) {
85 PostPressedEvent(event);
86 event->StopPropagation();
90 delegate_->OnKeyUnhold(event);
91 event->StopPropagation();