blob: 8326d9adb6b2a91cced19eda7f82b7468d0e66e5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/accelerators/key_hold_detector.h"
#include <X11/Xlib.h>
#undef RootWindow
#undef Status
#include "ash/shell.h"
#include "base/message_loop/message_loop.h"
#include "ui/aura/window_tracker.h"
#include "ui/aura/window_tree_host.h"
#include "ui/events/event_dispatcher.h"
#include "ui/events/event_processor.h"
namespace ash {
namespace {
void DispatchPressedEvent(const ui::KeyEvent& key_event,
scoped_ptr<aura::WindowTracker> tracker) {
// The target window may be gone.
if (tracker->windows().empty())
return;
ui::KeyEvent event(key_event);
aura::Window* target = *(tracker->windows().begin());
ignore_result(
target->GetHost()->event_processor()->OnEventFromSource(&event));
}
void PostPressedEvent(ui::KeyEvent* event) {
// Modify RELEASED event to PRESSED event.
const ui::KeyEvent pressed_event(
ui::ET_KEY_PRESSED,
event->key_code(),
event->code(),
event->flags() | ui::EF_SHIFT_DOWN | ui::EF_IS_SYNTHESIZED);
scoped_ptr<aura::WindowTracker> tracker(new aura::WindowTracker);
tracker->Add(static_cast<aura::Window*>(event->target()));
base::MessageLoopForUI::current()->PostTask(
FROM_HERE,
base::Bind(&DispatchPressedEvent, pressed_event, base::Passed(&tracker)));
}
} // namespace
KeyHoldDetector::KeyHoldDetector(scoped_ptr<Delegate> delegate)
: state_(INITIAL),
delegate_(delegate.Pass()) {}
KeyHoldDetector::~KeyHoldDetector() {}
void KeyHoldDetector::OnKeyEvent(ui::KeyEvent* event) {
if (!delegate_->ShouldProcessEvent(event))
return;
if (delegate_->IsStartEvent(event)) {
switch (state_) {
case INITIAL:
// Pass through posted event.
if (event->flags() & ui::EF_IS_SYNTHESIZED) {
event->set_flags(event->flags() & ~ui::EF_IS_SYNTHESIZED);
return;
}
state_ = PRESSED;
// Don't process ET_KEY_PRESSED event yet. The ET_KEY_PRESSED
// event will be generated upon ET_KEY_RELEASEED event below.
event->StopPropagation();
break;
case PRESSED:
state_ = HOLD;
// pass through
case HOLD:
delegate_->OnKeyHold(event);
event->StopPropagation();
break;
}
} else if (event->type() == ui::ET_KEY_RELEASED) {
switch (state_) {
case INITIAL:
break;
case PRESSED: {
PostPressedEvent(event);
event->StopPropagation();
break;
}
case HOLD: {
delegate_->OnKeyUnhold(event);
event->StopPropagation();
break;
}
}
state_ = INITIAL;
}
}
} // namespace ash
|