Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / ash / accelerators / key_hold_detector.cc
blob46c17eadcb3702b6e3fa440ee5b32cf7cfaa9980
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"
7 #include "ash/shell.h"
8 #include "base/message_loop/message_loop.h"
9 #include "ui/aura/window_tracker.h"
10 #include "ui/aura/window_tree_host.h"
11 #include "ui/events/event_dispatcher.h"
12 #include "ui/events/event_processor.h"
14 namespace ash {
15 namespace {
17 void DispatchPressedEvent(const ui::KeyEvent& key_event,
18 scoped_ptr<aura::WindowTracker> tracker) {
19 // The target window may be gone.
20 if (tracker->windows().empty())
21 return;
22 ui::KeyEvent event(key_event);
23 aura::Window* target = *(tracker->windows().begin());
24 ignore_result(
25 target->GetHost()->event_processor()->OnEventFromSource(&event));
28 void PostPressedEvent(ui::KeyEvent* event) {
29 // Modify RELEASED event to PRESSED event.
30 const ui::KeyEvent pressed_event(
31 ui::ET_KEY_PRESSED,
32 event->key_code(),
33 event->code(),
34 event->flags() | ui::EF_SHIFT_DOWN | ui::EF_IS_SYNTHESIZED);
35 scoped_ptr<aura::WindowTracker> tracker(new aura::WindowTracker);
36 tracker->Add(static_cast<aura::Window*>(event->target()));
38 base::MessageLoopForUI::current()->PostTask(
39 FROM_HERE,
40 base::Bind(&DispatchPressedEvent, pressed_event, base::Passed(&tracker)));
43 } // namespace
45 KeyHoldDetector::KeyHoldDetector(scoped_ptr<Delegate> delegate)
46 : state_(INITIAL),
47 delegate_(delegate.Pass()) {}
49 KeyHoldDetector::~KeyHoldDetector() {}
51 void KeyHoldDetector::OnKeyEvent(ui::KeyEvent* event) {
52 if (!delegate_->ShouldProcessEvent(event))
53 return;
55 if (delegate_->IsStartEvent(event)) {
56 switch (state_) {
57 case INITIAL:
58 // Pass through posted event.
59 if (event->flags() & ui::EF_IS_SYNTHESIZED) {
60 event->set_flags(event->flags() & ~ui::EF_IS_SYNTHESIZED);
61 return;
63 state_ = PRESSED;
64 // Don't process ET_KEY_PRESSED event yet. The ET_KEY_PRESSED
65 // event will be generated upon ET_KEY_RELEASEED event below.
66 event->StopPropagation();
67 break;
68 case PRESSED:
69 state_ = HOLD;
70 // pass through
71 case HOLD:
72 delegate_->OnKeyHold(event);
73 event->StopPropagation();
74 break;
76 } else if (event->type() == ui::ET_KEY_RELEASED) {
77 switch (state_) {
78 case INITIAL:
79 break;
80 case PRESSED: {
81 PostPressedEvent(event);
82 event->StopPropagation();
83 break;
85 case HOLD: {
86 delegate_->OnKeyUnhold(event);
87 event->StopPropagation();
88 break;
91 state_ = INITIAL;
95 } // namespace ash