Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Side by Side Diff: ui/chromeos/touch_exploration_controller.cc

Issue 262483003: Implementation of the Touch Exploration Mode - Part I (ui) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@event_source
Patch Set: Implementing review feedback from dmazzoni@ Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "base/logging.h"
8 #include "ui/aura/client/cursor_client.h"
9 #include "ui/aura/window.h"
10 #include "ui/aura/window_tree_host.h"
11 #include "ui/events/event.h"
12
13 namespace ui {
14
15 TouchExplorationController::TouchExplorationController(
16 aura::Window* root_window)
17 : root_window_(root_window) {
18 CHECK(root_window);
19 root_window->GetHost()->GetEventSource()->AddEventRewriter(this);
20 }
21
22 TouchExplorationController::~TouchExplorationController() {
23 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this);
24 }
25
26 ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
27 const ui::Event& event,
28 scoped_ptr<ui::Event>* rewritten_event) {
29 if (!event.IsTouchEvent())
30 return ui::EVENT_REWRITE_CONTINUE;
31
32 const ui::TouchEvent& touch_event =
33 static_cast<const ui::TouchEvent&>(event);
34 const ui::EventType type = touch_event.type();
35 const gfx::Point location = touch_event.location();
sadrul 2014/04/30 18:51:15 Use location_f() instead?
mfomitchev 2014/04/30 21:33:53 Done.
36 const int touch_id = touch_event.touch_id();
37 const int flags = touch_event.flags();
38
39 if (type == ui::ET_TOUCH_PRESSED) {
40 touch_ids_.push_back(touch_id);
41 touch_locations_.insert(std::pair<int, gfx::Point>(touch_id, location));
42 // If this is the first and only finger touching - rewrite the touch as a
43 // mouse move. Otherwise let the it go through as is.
44 if (touch_ids_.size() == 1) {
45 rewritten_event->reset(CreateMouseMoveEvent(location, flags));
46 EnterTouchToMouseMode();
47 return ui::EVENT_REWRITE_REWRITTEN;
48 } else {
49 return ui::EVENT_REWRITE_CONTINUE;
50 }
51 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
52 std::vector<int>::iterator it =
53 std::find(touch_ids_.begin(), touch_ids_.end(), touch_id);
54 // We may fail to find the finger if the exploration mode was turned on
55 // while the user had some fingers touching the screen. We simply ignore
56 // those fingers for the purposes of event transformation.
57 if (it == touch_ids_.end())
58 return ui::EVENT_REWRITE_CONTINUE;
59 const bool first_finger_released = it == touch_ids_.begin();
60 touch_ids_.erase(it);
61 int num_erased = touch_locations_.erase(touch_id);
62 DCHECK_EQ(num_erased, 1);
63 const int num_fingers_remaining = touch_ids_.size();
64
65 if (num_fingers_remaining == 0) {
66 rewritten_event->reset(CreateMouseMoveEvent(location, flags));
67 return ui::EVENT_REWRITE_REWRITTEN;
68 }
69
70 // If we are left with one finger - enter the mouse move mode.
71 const bool enter_mouse_move_mode = num_fingers_remaining == 1;
72
73 if (!enter_mouse_move_mode && !first_finger_released) {
74 // No special handling needed.
75 return ui::EVENT_REWRITE_CONTINUE;
76 }
77
78 // If the finger which was released was the first one, - we need to rewrite
79 // the release event as a release of the was second / now first finger.
80 // This is the finger which will now be getting "substracted".
81 if (first_finger_released) {
82 int rewritten_release_id = touch_ids_[0];
83 gfx::Point rewritten_release_location =
84 touch_locations_[rewritten_release_id];
85 ui::TouchEvent* rewritten_release_event = new ui::TouchEvent(
86 ui::ET_TOUCH_RELEASED,
87 rewritten_release_location,
88 rewritten_release_id,
89 event.time_stamp());
90 rewritten_event->reset(rewritten_release_event);
91 } else if (enter_mouse_move_mode) {
92 // Dispatch the release event as is.
93 // TODO(mfomitchev): We can get rid of this clause once we have
94 // EVENT_REWRITE_DISPATCH_ANOTHER working without having to set
95 // rewritten_event.
96 rewritten_event->reset(new ui::TouchEvent(touch_event));
97 }
98
99 if (enter_mouse_move_mode) {
100 // Since we are entering the mouse move mode - also dispatch a mouse move
101 // event at the location of the one remaining finger. (num_fingers == 1)
102 gfx::Point mouse_move_location = touch_locations_[touch_ids_[0]];
103 next_dispatch_event_.reset(
104 CreateMouseMoveEvent(mouse_move_location, flags));
sadrul 2014/04/30 18:51:15 return DISPATCH_ANOTHER from here?
mfomitchev 2014/04/30 21:33:53 Done.
105 }
106
107 if (enter_mouse_move_mode) {
108 return ui::EVENT_REWRITE_DISPATCH_ANOTHER;
109 } else { // first_finger_released == true
110 return ui::EVENT_REWRITE_REWRITTEN;
111 }
112 } else if (type == ui::ET_TOUCH_MOVED) {
113 std::vector<int>::iterator it =
114 std::find(touch_ids_.begin(), touch_ids_.end(), touch_id);
115 // We may fail to find the finger if the exploration mode was turned on
116 // while the user had some fingers touching the screen. We simply ignore
117 // those fingers for the purposes of event transformation.
118 if (it == touch_ids_.end())
119 return ui::EVENT_REWRITE_CONTINUE;
120 touch_locations_[*it] = location;
121 if (touch_ids_.size() == 1) {
122 // Touch moves are rewritten as mouse moves when there's only one finger
123 // touching the screen.
124 rewritten_event->reset(CreateMouseMoveEvent(location, flags));
125 return ui::EVENT_REWRITE_REWRITTEN;
126 } else if (touch_id == touch_ids_.front()) {
127 // Touch moves of the first finger are discarded when there's more than
128 // one finger touching.
129 return ui::EVENT_REWRITE_DISCARD;
130 } else {
131 return ui::EVENT_REWRITE_CONTINUE;
132 }
133 } else if (type == ui::ET_TOUCH_STATIONARY) {
134 if (touch_id == touch_ids_.front())
135 return ui::EVENT_REWRITE_DISCARD;
136 else
137 return ui::EVENT_REWRITE_CONTINUE;
138 }
139 NOTREACHED();
140 return ui::EVENT_REWRITE_CONTINUE;
141 }
142
143 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent(
144 const ui::Event& last_event,
145 scoped_ptr<ui::Event>* new_event) {
146 CHECK(next_dispatch_event_);
147 *new_event = next_dispatch_event_.Pass();
148 // Enter the mouse move mode if needed
149 if ((*new_event)->IsMouseEvent())
sadrul 2014/04/30 18:51:15 Should you also check if last_event.IsTouchEvent()
mfomitchev 2014/04/30 21:33:53 Hmm.. As it stands, RewriteEvent() returns EVENT_R
150 EnterTouchToMouseMode();
151 return ui::EVENT_REWRITE_REWRITTEN;
152 }
153
154 ui::Event* TouchExplorationController::CreateMouseMoveEvent(gfx::Point location,
155 int flags) {
156 return new ui::MouseEvent(ui::ET_MOUSE_MOVED,
157 location,
158 location,
159 flags | ui::EF_IS_SYNTHESIZED | ui::EF_FROM_TOUCH,
160 0);
161 }
162
163 void TouchExplorationController::EnterTouchToMouseMode() {
164 aura::client::CursorClient* cursor_client =
165 aura::client::GetCursorClient(root_window_);
166 if (cursor_client && !cursor_client->IsMouseEventsEnabled())
167 cursor_client->EnableMouseEvents();
168 if (cursor_client && cursor_client->IsCursorVisible())
169 cursor_client->HideCursor();
170 }
171
172 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698