ProfilePolicyConnectorFactory: Refactoring from Profile to BrowserContext.
[chromium-blink-merge.git] / ash / accelerators / key_hold_detector.cc
blob8326d9adb6b2a91cced19eda7f82b7468d0e66e5
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 <X11/Xlib.h>
9 #undef RootWindow
10 #undef Status
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"
19 namespace ash {
20 namespace {
22 void DispatchPressedEvent(const ui::KeyEvent& key_event,
23 scoped_ptr<aura::WindowTracker> tracker) {
24 // The target window may be gone.
25 if (tracker->windows().empty())
26 return;
27 ui::KeyEvent event(key_event);
28 aura::Window* target = *(tracker->windows().begin());
29 ignore_result(
30 target->GetHost()->event_processor()->OnEventFromSource(&event));
33 void PostPressedEvent(ui::KeyEvent* event) {
34 // Modify RELEASED event to PRESSED event.
35 const ui::KeyEvent pressed_event(
36 ui::ET_KEY_PRESSED,
37 event->key_code(),
38 event->code(),
39 event->flags() | ui::EF_SHIFT_DOWN | ui::EF_IS_SYNTHESIZED);
40 scoped_ptr<aura::WindowTracker> tracker(new aura::WindowTracker);
41 tracker->Add(static_cast<aura::Window*>(event->target()));
43 base::MessageLoopForUI::current()->PostTask(
44 FROM_HERE,
45 base::Bind(&DispatchPressedEvent, pressed_event, base::Passed(&tracker)));
48 } // namespace
50 KeyHoldDetector::KeyHoldDetector(scoped_ptr<Delegate> delegate)
51 : state_(INITIAL),
52 delegate_(delegate.Pass()) {}
54 KeyHoldDetector::~KeyHoldDetector() {}
56 void KeyHoldDetector::OnKeyEvent(ui::KeyEvent* event) {
57 if (!delegate_->ShouldProcessEvent(event))
58 return;
60 if (delegate_->IsStartEvent(event)) {
61 switch (state_) {
62 case INITIAL:
63 // Pass through posted event.
64 if (event->flags() & ui::EF_IS_SYNTHESIZED) {
65 event->set_flags(event->flags() & ~ui::EF_IS_SYNTHESIZED);
66 return;
68 state_ = PRESSED;
69 // Don't process ET_KEY_PRESSED event yet. The ET_KEY_PRESSED
70 // event will be generated upon ET_KEY_RELEASEED event below.
71 event->StopPropagation();
72 break;
73 case PRESSED:
74 state_ = HOLD;
75 // pass through
76 case HOLD:
77 delegate_->OnKeyHold(event);
78 event->StopPropagation();
79 break;
81 } else if (event->type() == ui::ET_KEY_RELEASED) {
82 switch (state_) {
83 case INITIAL:
84 break;
85 case PRESSED: {
86 PostPressedEvent(event);
87 event->StopPropagation();
88 break;
90 case HOLD: {
91 delegate_->OnKeyUnhold(event);
92 event->StopPropagation();
93 break;
96 state_ = INITIAL;
100 } // namespace ash