Chromium Code Reviews| 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 |