blob: 48e20c9d91bbfb0f2fc8e075fb7013e3ec7ea446 [file] [log] [blame]
// Copyright 2015 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 "components/html_viewer/touch_handler.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebWidget.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/events/gesture_detection/motion_event_generic.h"
#include "ui/mojo/events/input_events.mojom.h"
namespace html_viewer {
namespace {
// TODO(rjkroege): Gesture recognition currently happens in the html_viewer.
// In phase2, it will be relocated to MUS. Update this code at that time.
void SetPropertiesFromEvent(const mojo::Event& event,
ui::PointerProperties* properties) {
if (event.pointer_data) {
properties->id = event.pointer_data->pointer_id;
if (event.pointer_data->location) {
properties->x = event.pointer_data->location->x;
properties->y = event.pointer_data->location->y;
properties->raw_x = event.pointer_data->location->screen_x;
properties->raw_y = event.pointer_data->location->screen_y;
}
}
if (event.pointer_data && event.pointer_data->brush_data &&
(event.pointer_data->kind == mojo::POINTER_KIND_TOUCH ||
event.pointer_data->kind == mojo::POINTER_KIND_PEN)) {
properties->pressure = event.pointer_data->brush_data->pressure;
// TODO(rjkroege): vary orientation for width, height.
properties->SetAxesAndOrientation(event.pointer_data->brush_data->width,
event.pointer_data->brush_data->height,
0.0);
} else {
if (event.flags & mojo::EVENT_FLAGS_LEFT_MOUSE_BUTTON ||
event.flags & mojo::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON ||
event.flags & mojo::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON) {
properties->pressure = 0.5;
} else {
properties->pressure = 0.0;
}
}
// TODO(sky): Add support for tool_type.
}
} // namespace
TouchHandler::TouchHandler(blink::WebWidget* web_widget)
: web_widget_(web_widget),
gesture_provider_(ui::GetGestureProviderConfig(
ui::GestureProviderConfigType::CURRENT_PLATFORM),
this) {
}
TouchHandler::~TouchHandler() {
}
void TouchHandler::OnTouchEvent(const mojo::Event& event) {
if (!UpdateMotionEvent(event))
return;
SendMotionEventToGestureProvider();
PostProcessMotionEvent(event);
}
void TouchHandler::OnGestureEvent(const ui::GestureEventData& gesture) {
blink::WebGestureEvent web_gesture =
CreateWebGestureEventFromGestureEventData(gesture);
// TODO(jdduke): Remove this workaround after Android fixes UiAutomator to
// stop providing shift meta values to synthetic MotionEvents. This prevents
// unintended shift+click interpretation of all accessibility clicks.
// See crbug.com/443247.
if (web_gesture.type == blink::WebInputEvent::GestureTap &&
web_gesture.modifiers == blink::WebInputEvent::ShiftKey) {
web_gesture.modifiers = 0;
}
web_widget_->handleInputEvent(web_gesture);
}
bool TouchHandler::UpdateMotionEvent(const mojo::Event& event) {
ui::PointerProperties properties;
SetPropertiesFromEvent(event, &properties);
const base::TimeTicks timestamp(
base::TimeTicks::FromInternalValue(event.time_stamp));
if (current_motion_event_.get()) {
current_motion_event_->set_unique_event_id(ui::GetNextTouchEventId());
current_motion_event_->set_event_time(timestamp);
}
switch (event.action) {
case mojo::EVENT_TYPE_POINTER_DOWN:
if (!current_motion_event_.get()) {
current_motion_event_.reset(new ui::MotionEventGeneric(
ui::MotionEvent::ACTION_DOWN, timestamp, properties));
} else {
const int index =
current_motion_event_->FindPointerIndexOfId(properties.id);
if (index != -1) {
DVLOG(1) << "pointer down and pointer already down id="
<< properties.id;
return false;
}
current_motion_event_->PushPointer(properties);
current_motion_event_->set_action(ui::MotionEvent::ACTION_POINTER_DOWN);
current_motion_event_->set_action_index(static_cast<int>(index));
}
return true;
case mojo::EVENT_TYPE_POINTER_UP: {
if (!current_motion_event_.get()) {
DVLOG(1) << "pointer up with no event, id=" << properties.id;
return false;
}
const int index =
current_motion_event_->FindPointerIndexOfId(properties.id);
if (index == -1) {
DVLOG(1) << "pointer up and pointer not down id=" << properties.id;
return false;
}
current_motion_event_->pointer(index) = properties;
current_motion_event_->set_action(
current_motion_event_->GetPointerCount() == 1
? ui::MotionEvent::ACTION_UP
: ui::MotionEvent::ACTION_POINTER_UP);
current_motion_event_->set_action_index(static_cast<int>(index));
return true;
}
case mojo::EVENT_TYPE_POINTER_MOVE: {
if (!current_motion_event_.get()) {
DVLOG(1) << "pointer move with no event, id=" << properties.id;
return false;
}
const int index =
current_motion_event_->FindPointerIndexOfId(properties.id);
if (index == -1) {
DVLOG(1) << "pointer move and pointer not down id=" << properties.id;
return false;
}
current_motion_event_->pointer(index) = properties;
current_motion_event_->set_action(ui::MotionEvent::ACTION_MOVE);
current_motion_event_->set_action_index(static_cast<int>(index));
return true;
}
case mojo::EVENT_TYPE_POINTER_CANCEL: {
if (!current_motion_event_.get()) {
DVLOG(1) << "canel with no event, id=" << properties.id;
return false;
}
const int index =
current_motion_event_->FindPointerIndexOfId(properties.id);
if (index == -1) {
DVLOG(1) << "cancel and pointer not down id=" << properties.id;
return false;
}
current_motion_event_->pointer(index) = properties;
current_motion_event_->set_action(ui::MotionEvent::ACTION_CANCEL);
current_motion_event_->set_action_index(0);
return true;
}
default:
NOTREACHED();
}
return false;
}
void TouchHandler::SendMotionEventToGestureProvider() {
ui::FilteredGestureProvider::TouchHandlingResult result =
gesture_provider_.OnTouchEvent(*current_motion_event_);
if (!result.succeeded)
return;
blink::WebTouchEvent web_event = ui::CreateWebTouchEventFromMotionEvent(
*current_motion_event_, result.did_generate_scroll);
gesture_provider_.OnTouchEventAck(web_event.uniqueTouchEventId,
web_widget_->handleInputEvent(web_event));
}
void TouchHandler::PostProcessMotionEvent(const mojo::Event& event) {
switch (event.action) {
case mojo::EVENT_TYPE_POINTER_UP: {
if (event.pointer_data) {
const int index = current_motion_event_->FindPointerIndexOfId(
event.pointer_data->pointer_id);
current_motion_event_->RemovePointerAt(index);
}
if (current_motion_event_->GetPointerCount() == 0)
current_motion_event_.reset();
break;
}
case mojo::EVENT_TYPE_POINTER_CANCEL:
current_motion_event_.reset();
break;
default:
break;
}
}
} // namespace html_viewer