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

Unified Diff: ui/chromeos/touch_exploration_controller.cc

Issue 240333007: wip: Second crack at implementing the touch exploration mode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding a flag to disable the touch exploration mode. Created 6 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/chromeos/touch_exploration_controller.h ('k') | ui/chromeos/ui_chromeos.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/chromeos/touch_exploration_controller.cc
diff --git a/ui/chromeos/touch_exploration_controller.cc b/ui/chromeos/touch_exploration_controller.cc
new file mode 100644
index 0000000000000000000000000000000000000000..03c63b0fe4eadf8b53c80c022783e5877c4750e5
--- /dev/null
+++ b/ui/chromeos/touch_exploration_controller.cc
@@ -0,0 +1,170 @@
+// 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 "ui/chromeos/touch_exploration_controller.h"
+
+#include "ui/aura/client/cursor_client.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/event.h"
+
+namespace ui {
+
+TouchExplorationController::TouchExplorationController(
+ aura::Window* root_window)
+ : root_window_(root_window) {
+ CHECK(root_window);
+ root_window->GetHost()->GetEventSource()->AddEventRewriter(this);
+}
+
+TouchExplorationController::~TouchExplorationController() {
+ root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this);
+}
+
+ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
+ const ui::Event& event,
+ scoped_ptr<ui::Event>* rewritten_event) {
+ if (!event.IsTouchEvent())
+ return ui::EVENT_REWRITE_CONTINUE;
+
+ const ui::TouchEvent& touch_event =
+ static_cast<const ui::TouchEvent&>(event);
+ const ui::EventType type = touch_event.type();
+ const gfx::Point location = touch_event.location();
+ const int touch_id = touch_event.touch_id();
+ const int flags = touch_event.flags();
+
+ if (type == ui::ET_TOUCH_PRESSED) {
+ touch_ids_.push_back(touch_id);
+ touch_locations_.insert(std::pair<int, gfx::Point>(touch_id, location));
+ // If this is the first and only finger touching - rewrite the touch as a
+ // mouse move. Otherwise let the it go through as is.
+ if (touch_ids_.size() == 1) {
+ rewritten_event->reset(CreateMouseMoveEvent(location, flags));
+ EnterTouchToMouseMode();
+ return ui::EVENT_REWRITE_REWRITTEN;
+ } else {
+ return ui::EVENT_REWRITE_CONTINUE;
+ }
+ } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
+ std::vector<int>::iterator it =
+ std::find(touch_ids_.begin(), touch_ids_.end(), touch_id);
+ // We may fail to find the finger if the exploration mode was turned on
+ // while the user had some fingers touching the screen. We simply ignore
+ // those fingers for the purposes of event transformation.
+ if (it == touch_ids_.end())
+ return ui::EVENT_REWRITE_CONTINUE;
+ const bool first_finger_released = it == touch_ids_.begin();
+ touch_ids_.erase(it);
+ touch_locations_.erase(touch_id);
+ const int num_fingers_remaining = touch_ids_.size();
+
+ if (num_fingers_remaining == 0) {
+ rewritten_event->reset(CreateMouseMoveEvent(location, flags));
+ return ui::EVENT_REWRITE_REWRITTEN;
+ }
+
+ // If we are left with one finger - enter the mouse move mode.
+ const bool enter_mouse_move_mode = num_fingers_remaining == 1;
+
+ if (!enter_mouse_move_mode && !first_finger_released) {
+ // No special handling needed.
+ return ui::EVENT_REWRITE_CONTINUE;
+ }
+
+ // If the finger which was released was the first one, - we need to rewrite
+ // the release event as a release of the was second / now first finger.
+ // This is the finger which will now be getting "substracted".
+ if (first_finger_released) {
+ int rewritten_release_id = touch_ids_[0];
+ gfx::Point rewritten_release_location =
+ touch_locations_[rewritten_release_id];
+ ui::TouchEvent* rewritten_release_event = new ui::TouchEvent(
+ ui::ET_TOUCH_RELEASED,
+ rewritten_release_location,
+ rewritten_release_id,
+ event.time_stamp());
+ rewritten_event->reset(rewritten_release_event);
+ } else if (enter_mouse_move_mode) {
+ // Dispatch the release event as is.
+ // TODO(mfomitchev): We can get rid of this clause once we have
+ // EVENT_REWRITE_DISPATCH_ANOTHER working without having to set
+ // rewritten_event.
+ rewritten_event->reset(new ui::TouchEvent(touch_event));
+ }
+
+ if (enter_mouse_move_mode) {
+ // Since we are entering the mouse move mode - also dispatch a mouse move
+ // event at the location of the one remaining finger. (num_fingers == 1)
+ gfx::Point mouse_move_location = touch_locations_[touch_ids_[0]];
+ next_dispatch_event_.reset(
+ CreateMouseMoveEvent(mouse_move_location, flags));
+ }
+
+ if (enter_mouse_move_mode) {
+ return ui::EVENT_REWRITE_DISPATCH_ANOTHER;
+ } else { // first_finger_released == true
+ return ui::EVENT_REWRITE_REWRITTEN;
+ }
+ } else if (type == ui::ET_TOUCH_MOVED) {
+ std::vector<int>::iterator it =
+ std::find(touch_ids_.begin(), touch_ids_.end(), touch_id);
+ // We may fail to find the finger if the exploration mode was turned on
+ // while the user had some fingers touching the screen. We simply ignore
+ // those fingers for the purposes of event transformation.
+ if (it == touch_ids_.end())
+ return ui::EVENT_REWRITE_CONTINUE;
+ touch_locations_[*it] = location;
+ if (touch_ids_.size() == 1) {
+ // Touch moves are rewritten as mouse moves when there's only one finger
+ // touching the screen.
+ rewritten_event->reset(CreateMouseMoveEvent(location, flags));
+ return ui::EVENT_REWRITE_REWRITTEN;
+ } else if (touch_id == touch_ids_.front()) {
+ // Touch moves of the first finger are discarded when there's more than
+ // one finger touching.
+ return ui::EVENT_REWRITE_DISCARD;
+ } else {
+ return ui::EVENT_REWRITE_CONTINUE;
+ }
+ } else if (type == ui::ET_TOUCH_STATIONARY) {
+ if (touch_id == touch_ids_.front())
+ return ui::EVENT_REWRITE_DISCARD;
+ else
+ return ui::EVENT_REWRITE_CONTINUE;
+ }
+ NOTREACHED();
+ return ui::EVENT_REWRITE_CONTINUE;
+}
+
+ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent(
+ const ui::Event& last_event,
+ scoped_ptr<ui::Event>* new_event) {
+ CHECK(next_dispatch_event_);
+ *new_event = next_dispatch_event_.Pass();
+ // Enter the mouse move mode if needed
+ if ((*new_event)->IsMouseEvent())
+ EnterTouchToMouseMode();
+ return ui::EVENT_REWRITE_REWRITTEN;
+}
+
+ui::Event* TouchExplorationController::CreateMouseMoveEvent(gfx::Point location,
+ int flags) {
+ return new ui::MouseEvent(ui::ET_MOUSE_MOVED,
+ location,
+ location,
+ flags | ui::EF_IS_SYNTHESIZED | ui::EF_FROM_TOUCH,
+ 0);
+}
+
+void TouchExplorationController::EnterTouchToMouseMode() {
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root_window_);
+ if (cursor_client && !cursor_client->IsMouseEventsEnabled())
+ cursor_client->EnableMouseEvents();
+ if (cursor_client && cursor_client->IsCursorVisible())
+ cursor_client->HideCursor();
+}
+
+} // namespace ui
« no previous file with comments | « ui/chromeos/touch_exploration_controller.h ('k') | ui/chromeos/ui_chromeos.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698