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

Unified Diff: ash/touch/touch_exploration_controller.cc

Issue 225143007: First crack at implementing the touch explaration mode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Minor changes 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
Index: ash/touch/touch_exploration_controller.cc
diff --git a/ash/touch/touch_exploration_controller.cc b/ash/touch/touch_exploration_controller.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3661d1dbebe822d4174a530dc2f8600949f61b0b
--- /dev/null
+++ b/ash/touch/touch_exploration_controller.cc
@@ -0,0 +1,174 @@
+// 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 "ash/touch/touch_exploration_controller.h"
+
+#include "ash/root_window_settings.h"
+#include "ash/shell.h"
+#include "ash/wm/coordinate_conversion.h"
+#include "base/logging.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/event.h"
+#include "ui/events/event_processor.h"
+#include "ui/gfx/point.h"
+
+namespace ash {
+namespace internal {
+
+TouchExplorationController::TouchExplorationController(
+ aura::Window* root_window) :
+ display_id_(GetRootWindowSettings(root_window)->display_id),
+ root_window_(root_window) {
+ Shell::GetInstance()->display_controller()->AddObserver(this);
+ root_window_->AddPreTargetHandler(this);
+}
+
+TouchExplorationController::~TouchExplorationController() {
+ Shell::GetInstance()->display_controller()->RemoveObserver(this);
+ if (root_window_)
+ root_window_->RemovePreTargetHandler(this);
+}
+
+void TouchExplorationController::OnTouchEvent(ui::TouchEvent* event) {
+ ui::EventType type = event->type();
+ if (type == ui::ET_TOUCH_PRESSED) {
+ LOG(ERROR) << "ET_TOUCH_PRESSED";
+ // If this is the first and only finger touching - we are entering the
+ // mouse move mode.
+ if (touch_ids_.size() == 0) {
+ // 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
+ // and send them along with the synthesized mouse event - is that correct?
+ GenerateMouseEvent(
+ ui::ET_MOUSE_ENTERED, event->location(), event->flags());
+ event->SetHandled();
+ 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
+ }
+ // If this is the second finger - we should exit the mouse move mode (which
+ // we should have entered when the first finger touch started), and we
+ // should let this touch go through as is.
+ if (touch_ids_.size() == 1) {
+ // Generate ET_MOUSE_EXITED in the location of the _first_ touch.
+ int first_touch_id = touch_ids_.at(0);
+ gfx::Point first_touch_location = touch_locations_[first_touch_id];
+ GenerateMouseEvent(
sadrul 2014/04/14 20:22:11 WindowEventDispatcher takes care of dispatching mo
+ ui::ET_MOUSE_EXITED, first_touch_location, event->flags());
+ }
+ touch_ids_.push_back(event->touch_id());
+ touch_locations_.insert(
+ std::pair<int, gfx::Point>(event->touch_id(), event->location()));
+ // Ignore the synthesized release events - we are synthesizing them below.
+ } else if ((type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)
+ && !(event->flags() & ui::EF_IS_SYNTHESIZED)) {
+ LOG(ERROR) << (type == ui::ET_TOUCH_RELEASED ?
+ "ET_TOUCH_RELEASED" : "ET_TOUCH_CANCELLED");
+ int touch_id = event->touch_id();
+ std::vector<int>::iterator it =
+ std::find(touch_ids_.begin(), touch_ids_.end(), touch_id);
+ if (it != touch_ids_.end()) {
+ // If it was the first finger that was lifted, we need to do a few
+ // things depending on how many fingers were on the screen:
+ // 1. If only one finger was on the screen, this is simply equivalent to
+ // the end of the mouse move.
+ // 2. If there were multiple fingers on the screen, this is equivalent
+ // to lifting the _second_ finger. Also, if there were exactly two
+ // fingers touching, we are only left with one, so we are entering the
+ // mouse move mode, and so we should also generate ET_MOUSE_ENTERED.
+ if (it == touch_ids_.begin()) {
+ if (touch_ids_.size() == 1) {
+ GenerateMouseEvent(
+ ui::ET_MOUSE_EXITED, event->location(), event->flags());
+ } else {
+ LOG(ERROR) << "Generating touch release event";
+ // Generate a touch release event for the second finger.
+ int second_touch_id = touch_ids_.at(1);
+ gfx::Point second_touch_location = touch_locations_[second_touch_id];
+ aura::Window* root = wm::GetRootWindowAt(second_touch_location);
+ DCHECK(root)
+ << "Root window not found while generating touch release event.";
+ aura::WindowTreeHost* host = root->GetHost();
+ // TODO: Should I use another constructor to pass in the flags?
mfomitchev 2014/04/11 21:00:58 Question here
+ ui::TouchEvent touch_event(ui::ET_TOUCH_RELEASED,
+ second_touch_location,
+ second_touch_id,
+ event->time_stamp());
+ host->event_processor()->OnEventFromSource(&touch_event);
+ // If there were exactly two fingers touching - generate
+ // ET_MOUSE_ENTERED.
+ if (touch_ids_.size() == 2) {
+ GenerateMouseEvent(
+ ui::ET_MOUSE_ENTERED, second_touch_location, event->flags());
+ }
+ }
+ event->SetHandled();
+ event->StopPropagation();
+ }
+ touch_ids_.erase(it);
+ touch_locations_.erase(touch_id);
+ } else {
+ NOTREACHED();
+ }
+ } else if (type == ui::ET_TOUCH_MOVED) {
+ LOG(ERROR) << "ET_TOUCH_MOVED";
+ // Consume if it is the first finger.
+ // If it is the only finger - generate a mouse move event.
+ std::vector<int>::iterator it =
+ std::find(touch_ids_.begin(), touch_ids_.end(), event->touch_id());
+ if (it != touch_ids_.end()) {
+ if (it == touch_ids_.begin()) {
+ if (touch_ids_.size() == 1) {
+ GenerateMouseEvent(
+ ui::ET_MOUSE_MOVED, event->location(), event->flags());
+ }
+ event->SetHandled();
+ event->StopPropagation();
+ }
+ touch_locations_[*it] = event->location();
+ } else {
+ NOTREACHED();
+ }
+ }
+}
+
+void TouchExplorationController::OnDisplaysInitialized() {
+ OnDisplayConfigurationChanged();
+}
+
+void TouchExplorationController::OnDisplayConfigurationChanging() {
+ if (!root_window_)
+ return;
+
+ root_window_->RemovePreTargetHandler(this);
+ root_window_ = NULL;
+}
+
+void TouchExplorationController::OnDisplayConfigurationChanged() {
+ if (root_window_)
+ return;
+
+ root_window_ = Shell::GetInstance()->display_controller()->
+ GetRootWindowForDisplayId(display_id_);
+ root_window_->AddPreTargetHandler(this);
+}
+
+void TouchExplorationController::GenerateMouseEvent(ui::EventType event_type,
+ gfx::Point location,
+ int flags) {
+ aura::Window* root_window = wm::GetRootWindowAt(location);
+ DCHECK(root_window)
+ << "Root window not found while converting touch to mouse event.";
+ aura::WindowTreeHost* host = root_window->GetHost();
+
+ LOG(ERROR) << "Generating mouse event: type=" << event_type;
+ ui::MouseEvent mouse_event(event_type,
+ location,
+ location,
+ ui::EF_IS_SYNTHESIZED | flags,
+ 0);
+
+ // 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.
+ host->event_processor()->OnEventFromSource(&mouse_event);
+}
+
+} // namespace internal
+} // namespace ash

Powered by Google App Engine
This is Rietveld 408576698