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 "ui/chromeos/touch_exploration_controller.h" | |
6 | |
7 #include "ui/aura/client/cursor_client.h" | |
8 #include "ui/aura/window.h" | |
9 #include "ui/aura/window_tree_host.h" | |
10 #include "ui/events/event.h" | |
11 | |
12 namespace ui { | |
13 | |
14 TouchExplorationController::TouchExplorationController( | |
15 aura::Window* root_window) | |
16 : root_window_(root_window) { | |
17 CHECK(root_window); | |
18 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); | |
19 } | |
20 | |
21 TouchExplorationController::~TouchExplorationController() { | |
22 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); | |
23 } | |
24 | |
25 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( | |
26 const ui::Event& event, | |
27 scoped_ptr<ui::Event>* rewritten_event) { | |
28 if (!event.IsTouchEvent()) | |
29 return ui::EVENT_REWRITE_CONTINUE; | |
30 | |
31 const ui::TouchEvent& touch_event = | |
32 static_cast<const ui::TouchEvent&>(event); | |
33 const ui::EventType type = touch_event.type(); | |
34 const gfx::Point location = touch_event.location(); | |
35 const int touch_id = touch_event.touch_id(); | |
36 const int flags = touch_event.flags(); | |
37 | |
38 if (type == ui::ET_TOUCH_PRESSED) { | |
39 touch_ids_.push_back(touch_id); | |
40 touch_locations_.insert(std::pair<int, gfx::Point>(touch_id, location)); | |
41 // If this is the first and only finger touching - rewrite the touch as a | |
42 // mouse move. Otherwise let the it go through as is. | |
43 if (touch_ids_.size() == 1) { | |
44 rewritten_event->reset(CreateMouseMoveEvent(location, flags)); | |
45 EnterTouchToMouseMode(); | |
46 return ui::EVENT_REWRITE_REWRITTEN; | |
47 } else { | |
48 return ui::EVENT_REWRITE_CONTINUE; | |
49 } | |
50 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | |
51 std::vector<int>::iterator it = | |
52 std::find(touch_ids_.begin(), touch_ids_.end(), touch_id); | |
dmazzoni
2014/04/30 06:08:35
This can be written as just:
std::vector<int>::it
mfomitchev
2014/04/30 17:06:19
vector doesn't have find(), does it? I get a compi
dmazzoni
2014/04/30 17:45:07
Nevermind, I was thinking of other STL classes tha
| |
53 // We may fail to find the finger if the exploration mode was turned on | |
54 // while the user had some fingers touching the screen. We simply ignore | |
55 // those fingers for the purposes of event transformation. | |
56 if (it == touch_ids_.end()) | |
57 return ui::EVENT_REWRITE_CONTINUE; | |
58 const bool first_finger_released = it == touch_ids_.begin(); | |
59 touch_ids_.erase(it); | |
60 touch_locations_.erase(touch_id); | |
dmazzoni
2014/04/30 06:08:35
Assert / dcheck that touch_locations contains touc
mfomitchev
2014/04/30 17:06:19
Done.
| |
61 const int num_fingers_remaining = touch_ids_.size(); | |
62 | |
63 if (num_fingers_remaining == 0) { | |
64 rewritten_event->reset(CreateMouseMoveEvent(location, flags)); | |
65 return ui::EVENT_REWRITE_REWRITTEN; | |
66 } | |
67 | |
68 // If we are left with one finger - enter the mouse move mode. | |
69 const bool enter_mouse_move_mode = num_fingers_remaining == 1; | |
70 | |
71 if (!enter_mouse_move_mode && !first_finger_released) { | |
72 // No special handling needed. | |
73 return ui::EVENT_REWRITE_CONTINUE; | |
74 } | |
75 | |
76 // If the finger which was released was the first one, - we need to rewrite | |
77 // the release event as a release of the was second / now first finger. | |
78 // This is the finger which will now be getting "substracted". | |
79 if (first_finger_released) { | |
80 int rewritten_release_id = touch_ids_[0]; | |
81 gfx::Point rewritten_release_location = | |
82 touch_locations_[rewritten_release_id]; | |
83 ui::TouchEvent* rewritten_release_event = new ui::TouchEvent( | |
84 ui::ET_TOUCH_RELEASED, | |
85 rewritten_release_location, | |
86 rewritten_release_id, | |
87 event.time_stamp()); | |
88 rewritten_event->reset(rewritten_release_event); | |
89 } else if (enter_mouse_move_mode) { | |
90 // Dispatch the release event as is. | |
91 // TODO(mfomitchev): We can get rid of this clause once we have | |
92 // EVENT_REWRITE_DISPATCH_ANOTHER working without having to set | |
93 // rewritten_event. | |
94 rewritten_event->reset(new ui::TouchEvent(touch_event)); | |
95 } | |
96 | |
97 if (enter_mouse_move_mode) { | |
98 // Since we are entering the mouse move mode - also dispatch a mouse move | |
99 // event at the location of the one remaining finger. (num_fingers == 1) | |
100 gfx::Point mouse_move_location = touch_locations_[touch_ids_[0]]; | |
101 next_dispatch_event_.reset( | |
102 CreateMouseMoveEvent(mouse_move_location, flags)); | |
103 } | |
104 | |
105 if (enter_mouse_move_mode) { | |
106 return ui::EVENT_REWRITE_DISPATCH_ANOTHER; | |
107 } else { // first_finger_released == true | |
108 return ui::EVENT_REWRITE_REWRITTEN; | |
109 } | |
110 } else if (type == ui::ET_TOUCH_MOVED) { | |
111 std::vector<int>::iterator it = | |
112 std::find(touch_ids_.begin(), touch_ids_.end(), touch_id); | |
113 // We may fail to find the finger if the exploration mode was turned on | |
114 // while the user had some fingers touching the screen. We simply ignore | |
115 // those fingers for the purposes of event transformation. | |
116 if (it == touch_ids_.end()) | |
117 return ui::EVENT_REWRITE_CONTINUE; | |
118 touch_locations_[*it] = location; | |
119 if (touch_ids_.size() == 1) { | |
120 // Touch moves are rewritten as mouse moves when there's only one finger | |
121 // touching the screen. | |
122 rewritten_event->reset(CreateMouseMoveEvent(location, flags)); | |
123 return ui::EVENT_REWRITE_REWRITTEN; | |
124 } else if (touch_id == touch_ids_.front()) { | |
125 // Touch moves of the first finger are discarded when there's more than | |
126 // one finger touching. | |
127 return ui::EVENT_REWRITE_DISCARD; | |
128 } else { | |
129 return ui::EVENT_REWRITE_CONTINUE; | |
130 } | |
131 } else if (type == ui::ET_TOUCH_STATIONARY) { | |
132 if (touch_id == touch_ids_.front()) | |
133 return ui::EVENT_REWRITE_DISCARD; | |
134 else | |
135 return ui::EVENT_REWRITE_CONTINUE; | |
136 } | |
137 NOTREACHED(); | |
dmazzoni
2014/04/30 06:08:35
Should you switch on |type| instead? Then not hand
mfomitchev
2014/04/30 17:06:19
Problem is, there's over 40 of values in the Even
dmazzoni
2014/04/30 17:45:07
Got it - the rest are thrown away with event.IsTou
| |
138 return ui::EVENT_REWRITE_CONTINUE; | |
139 } | |
140 | |
141 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( | |
142 const ui::Event& last_event, | |
143 scoped_ptr<ui::Event>* new_event) { | |
144 CHECK(next_dispatch_event_); | |
145 *new_event = next_dispatch_event_.Pass(); | |
146 // Enter the mouse move mode if needed | |
147 if ((*new_event)->IsMouseEvent()) | |
148 EnterTouchToMouseMode(); | |
149 return ui::EVENT_REWRITE_REWRITTEN; | |
150 } | |
151 | |
152 ui::Event* TouchExplorationController::CreateMouseMoveEvent(gfx::Point location, | |
153 int flags) { | |
154 return new ui::MouseEvent(ui::ET_MOUSE_MOVED, | |
155 location, | |
156 location, | |
157 flags | ui::EF_IS_SYNTHESIZED | ui::EF_FROM_TOUCH, | |
158 0); | |
159 } | |
160 | |
161 void TouchExplorationController::EnterTouchToMouseMode() { | |
162 aura::client::CursorClient* cursor_client = | |
163 aura::client::GetCursorClient(root_window_); | |
164 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) | |
165 cursor_client->EnableMouseEvents(); | |
166 if (cursor_client && cursor_client->IsCursorVisible()) | |
167 cursor_client->HideCursor(); | |
168 } | |
169 | |
170 } // namespace ui | |
OLD | NEW |