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();