OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "ash/touch/touch_exploration_controller.h" | |
6 | |
7 #include "ash/root_window_settings.h" | |
8 #include "ash/shell.h" | |
9 #include "ash/wm/coordinate_conversion.h" | |
10 #include "base/logging.h" | |
11 #include "ui/aura/window_tree_host.h" | |
12 #include "ui/events/event.h" | |
13 #include "ui/events/event_processor.h" | |
14 #include "ui/gfx/point.h" | |
15 | |
16 namespace ash { | |
17 namespace internal { | |
18 | |
19 TouchExplorationController::TouchExplorationController( | |
20 aura::Window* root_window) : | |
21 display_id_(GetRootWindowSettings(root_window)->display_id), | |
22 root_window_(root_window) { | |
23 Shell::GetInstance()->display_controller()->AddObserver(this); | |
24 root_window_->AddPreTargetHandler(this); | |
25 } | |
26 | |
27 TouchExplorationController::~TouchExplorationController() { | |
28 Shell::GetInstance()->display_controller()->RemoveObserver(this); | |
29 if (root_window_) | |
30 root_window_->RemovePreTargetHandler(this); | |
31 } | |
32 | |
33 void TouchExplorationController::OnTouchEvent(ui::TouchEvent* event) { | |
34 ui::EventType type = event->type(); | |
35 if (type == ui::ET_TOUCH_PRESSED) { | |
36 LOG(ERROR) << "ET_TOUCH_PRESSED"; | |
37 // If this is the first and only finger touching - we are entering the | |
38 // mouse move mode. | |
39 if (touch_ids_.size() == 0) { | |
40 // TODO: Here and in other cases we take the flags from the touch event | |
mfomitchev
2014/04/11 21:00:58
Question here
sadrul
2014/04/14 20:22:11
Yes. The EventRewriter implementation should do th
| |
41 // and send them along with the synthesized mouse event - is that correct? | |
42 GenerateMouseEvent( | |
43 ui::ET_MOUSE_ENTERED, event->location(), event->flags()); | |
44 event->SetHandled(); | |
45 event->StopPropagation(); | |
mfomitchev
2014/04/11 21:00:58
If I don't call StopPropagation() (here and in oth
sadrul
2014/04/14 20:22:11
Yeah. We need to stop propagating the touch-event
| |
46 } | |
47 // If this is the second finger - we should exit the mouse move mode (which | |
48 // we should have entered when the first finger touch started), and we | |
49 // should let this touch go through as is. | |
50 if (touch_ids_.size() == 1) { | |
51 // Generate ET_MOUSE_EXITED in the location of the _first_ touch. | |
52 int first_touch_id = touch_ids_.at(0); | |
53 gfx::Point first_touch_location = touch_locations_[first_touch_id]; | |
54 GenerateMouseEvent( | |
sadrul
2014/04/14 20:22:11
WindowEventDispatcher takes care of dispatching mo
| |
55 ui::ET_MOUSE_EXITED, first_touch_location, event->flags()); | |
56 } | |
57 touch_ids_.push_back(event->touch_id()); | |
58 touch_locations_.insert( | |
59 std::pair<int, gfx::Point>(event->touch_id(), event->location())); | |
60 // Ignore the synthesized release events - we are synthesizing them below. | |
61 } else if ((type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) | |
62 && !(event->flags() & ui::EF_IS_SYNTHESIZED)) { | |
63 LOG(ERROR) << (type == ui::ET_TOUCH_RELEASED ? | |
64 "ET_TOUCH_RELEASED" : "ET_TOUCH_CANCELLED"); | |
65 int touch_id = event->touch_id(); | |
66 std::vector<int>::iterator it = | |
67 std::find(touch_ids_.begin(), touch_ids_.end(), touch_id); | |
68 if (it != touch_ids_.end()) { | |
69 // If it was the first finger that was lifted, we need to do a few | |
70 // things depending on how many fingers were on the screen: | |
71 // 1. If only one finger was on the screen, this is simply equivalent to | |
72 // the end of the mouse move. | |
73 // 2. If there were multiple fingers on the screen, this is equivalent | |
74 // to lifting the _second_ finger. Also, if there were exactly two | |
75 // fingers touching, we are only left with one, so we are entering the | |
76 // mouse move mode, and so we should also generate ET_MOUSE_ENTERED. | |
77 if (it == touch_ids_.begin()) { | |
78 if (touch_ids_.size() == 1) { | |
79 GenerateMouseEvent( | |
80 ui::ET_MOUSE_EXITED, event->location(), event->flags()); | |
81 } else { | |
82 LOG(ERROR) << "Generating touch release event"; | |
83 // Generate a touch release event for the second finger. | |
84 int second_touch_id = touch_ids_.at(1); | |
85 gfx::Point second_touch_location = touch_locations_[second_touch_id]; | |
86 aura::Window* root = wm::GetRootWindowAt(second_touch_location); | |
87 DCHECK(root) | |
88 << "Root window not found while generating touch release event."; | |
89 aura::WindowTreeHost* host = root->GetHost(); | |
90 // TODO: Should I use another constructor to pass in the flags? | |
mfomitchev
2014/04/11 21:00:58
Question here
| |
91 ui::TouchEvent touch_event(ui::ET_TOUCH_RELEASED, | |
92 second_touch_location, | |
93 second_touch_id, | |
94 event->time_stamp()); | |
95 host->event_processor()->OnEventFromSource(&touch_event); | |
96 // If there were exactly two fingers touching - generate | |
97 // ET_MOUSE_ENTERED. | |
98 if (touch_ids_.size() == 2) { | |
99 GenerateMouseEvent( | |
100 ui::ET_MOUSE_ENTERED, second_touch_location, event->flags()); | |
101 } | |
102 } | |
103 event->SetHandled(); | |
104 event->StopPropagation(); | |
105 } | |
106 touch_ids_.erase(it); | |
107 touch_locations_.erase(touch_id); | |
108 } else { | |
109 NOTREACHED(); | |
110 } | |
111 } else if (type == ui::ET_TOUCH_MOVED) { | |
112 LOG(ERROR) << "ET_TOUCH_MOVED"; | |
113 // Consume if it is the first finger. | |
114 // If it is the only finger - generate a mouse move event. | |
115 std::vector<int>::iterator it = | |
116 std::find(touch_ids_.begin(), touch_ids_.end(), event->touch_id()); | |
117 if (it != touch_ids_.end()) { | |
118 if (it == touch_ids_.begin()) { | |
119 if (touch_ids_.size() == 1) { | |
120 GenerateMouseEvent( | |
121 ui::ET_MOUSE_MOVED, event->location(), event->flags()); | |
122 } | |
123 event->SetHandled(); | |
124 event->StopPropagation(); | |
125 } | |
126 touch_locations_[*it] = event->location(); | |
127 } else { | |
128 NOTREACHED(); | |
129 } | |
130 } | |
131 } | |
132 | |
133 void TouchExplorationController::OnDisplaysInitialized() { | |
134 OnDisplayConfigurationChanged(); | |
135 } | |
136 | |
137 void TouchExplorationController::OnDisplayConfigurationChanging() { | |
138 if (!root_window_) | |
139 return; | |
140 | |
141 root_window_->RemovePreTargetHandler(this); | |
142 root_window_ = NULL; | |
143 } | |
144 | |
145 void TouchExplorationController::OnDisplayConfigurationChanged() { | |
146 if (root_window_) | |
147 return; | |
148 | |
149 root_window_ = Shell::GetInstance()->display_controller()-> | |
150 GetRootWindowForDisplayId(display_id_); | |
151 root_window_->AddPreTargetHandler(this); | |
152 } | |
153 | |
154 void TouchExplorationController::GenerateMouseEvent(ui::EventType event_type, | |
155 gfx::Point location, | |
156 int flags) { | |
157 aura::Window* root_window = wm::GetRootWindowAt(location); | |
158 DCHECK(root_window) | |
159 << "Root window not found while converting touch to mouse event."; | |
160 aura::WindowTreeHost* host = root_window->GetHost(); | |
161 | |
162 LOG(ERROR) << "Generating mouse event: type=" << event_type; | |
163 ui::MouseEvent mouse_event(event_type, | |
164 location, | |
165 location, | |
166 ui::EF_IS_SYNTHESIZED | flags, | |
167 0); | |
168 | |
169 // TODO: Should I use WindowEventDispatcher instead? | |
mfomitchev
2014/04/11 21:00:58
Question here
sadrul
2014/04/14 20:22:11
This is fine.
| |
170 host->event_processor()->OnEventFromSource(&mouse_event); | |
171 } | |
172 | |
173 } // namespace internal | |
174 } // namespace ash | |
OLD | NEW |