| // Copyright 2013 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 "content/common/input/synthetic_web_input_event_builders.h" |
| |
| #include "base/logging.h" |
| #include "content/common/input/web_mouse_wheel_event_traits.h" |
| #include "content/common/input/web_touch_event_traits.h" |
| #include "ui/events/base_event_utils.h" |
| #include "ui/events/event.h" |
| #include "ui/events/keycodes/keyboard_codes.h" |
| |
| namespace content { |
| |
| using blink::WebInputEvent; |
| using blink::WebKeyboardEvent; |
| using blink::WebGestureEvent; |
| using blink::WebMouseEvent; |
| using blink::WebMouseWheelEvent; |
| using blink::WebTouchEvent; |
| using blink::WebTouchPoint; |
| |
| WebMouseEvent SyntheticWebMouseEventBuilder::Build( |
| blink::WebInputEvent::Type type) { |
| return WebMouseEvent(type, WebInputEvent::kNoModifiers, |
| ui::EventTimeForNow()); |
| } |
| |
| WebMouseEvent SyntheticWebMouseEventBuilder::Build( |
| blink::WebInputEvent::Type type, |
| float window_x, |
| float window_y, |
| int modifiers, |
| blink::WebPointerProperties::PointerType pointer_type) { |
| DCHECK(WebInputEvent::IsMouseEventType(type)); |
| WebMouseEvent result(type, modifiers, ui::EventTimeForNow()); |
| result.SetPositionInWidget(window_x, window_y); |
| result.SetPositionInScreen(window_x, window_y); |
| result.SetModifiers(modifiers); |
| result.pointer_type = pointer_type; |
| result.id = ui::MouseEvent::kMousePointerId; |
| return result; |
| } |
| |
| WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build( |
| WebMouseWheelEvent::Phase phase) { |
| WebMouseWheelEvent result(WebInputEvent::kMouseWheel, |
| WebInputEvent::kNoModifiers, ui::EventTimeForNow()); |
| result.phase = phase; |
| result.event_action = WebMouseWheelEventTraits::GetEventAction(result); |
| return result; |
| } |
| |
| WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build( |
| float x, |
| float y, |
| float dx, |
| float dy, |
| int modifiers, |
| bool precise, |
| bool scroll_by_page) { |
| return Build(x, y, 0, 0, dx, dy, modifiers, precise, scroll_by_page); |
| } |
| |
| WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build( |
| float x, |
| float y, |
| float global_x, |
| float global_y, |
| float dx, |
| float dy, |
| int modifiers, |
| bool precise, |
| bool scroll_by_page) { |
| WebMouseWheelEvent result(WebInputEvent::kMouseWheel, modifiers, |
| ui::EventTimeForNow()); |
| result.SetPositionInScreen(global_x, global_y); |
| result.SetPositionInWidget(x, y); |
| result.delta_x = dx; |
| result.delta_y = dy; |
| if (dx) |
| result.wheel_ticks_x = dx > 0.0f ? 1.0f : -1.0f; |
| if (dy) |
| result.wheel_ticks_y = dy > 0.0f ? 1.0f : -1.0f; |
| result.has_precise_scrolling_deltas = precise; |
| result.scroll_by_page = scroll_by_page; |
| result.event_action = WebMouseWheelEventTraits::GetEventAction(result); |
| return result; |
| } |
| |
| WebKeyboardEvent SyntheticWebKeyboardEventBuilder::Build( |
| WebInputEvent::Type type) { |
| DCHECK(WebInputEvent::IsKeyboardEventType(type)); |
| WebKeyboardEvent result(type, WebInputEvent::kNoModifiers, |
| ui::EventTimeForNow()); |
| result.windows_key_code = ui::VKEY_L; // non-null made up value. |
| return result; |
| } |
| |
| WebGestureEvent SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type type, |
| blink::WebGestureDevice source_device, |
| int modifiers) { |
| DCHECK(WebInputEvent::IsGestureEventType(type)); |
| WebGestureEvent result(type, modifiers, ui::EventTimeForNow(), source_device); |
| if (type == WebInputEvent::kGestureTap || |
| type == WebInputEvent::kGestureTapUnconfirmed || |
| type == WebInputEvent::kGestureDoubleTap) { |
| result.data.tap.tap_count = 1; |
| result.data.tap.width = 10; |
| result.data.tap.height = 10; |
| } |
| |
| result.SetNeedsWheelEvent(result.IsTouchpadZoomEvent()); |
| |
| return result; |
| } |
| |
| WebGestureEvent SyntheticWebGestureEventBuilder::BuildScrollBegin( |
| float dx_hint, |
| float dy_hint, |
| blink::WebGestureDevice source_device, |
| int pointer_count) { |
| WebGestureEvent result = |
| Build(WebInputEvent::kGestureScrollBegin, source_device); |
| result.data.scroll_begin.delta_x_hint = dx_hint; |
| result.data.scroll_begin.delta_y_hint = dy_hint; |
| result.data.scroll_begin.pointer_count = pointer_count; |
| return result; |
| } |
| |
| WebGestureEvent SyntheticWebGestureEventBuilder::BuildScrollUpdate( |
| float dx, |
| float dy, |
| int modifiers, |
| blink::WebGestureDevice source_device) { |
| WebGestureEvent result = |
| Build(WebInputEvent::kGestureScrollUpdate, source_device, modifiers); |
| result.data.scroll_update.delta_x = dx; |
| result.data.scroll_update.delta_y = dy; |
| return result; |
| } |
| |
| WebGestureEvent SyntheticWebGestureEventBuilder::BuildPinchUpdate( |
| float scale, |
| float anchor_x, |
| float anchor_y, |
| int modifiers, |
| blink::WebGestureDevice source_device) { |
| WebGestureEvent result = |
| Build(WebInputEvent::kGesturePinchUpdate, source_device, modifiers); |
| result.data.pinch_update.scale = scale; |
| result.SetPositionInWidget(blink::WebFloatPoint(anchor_x, anchor_y)); |
| result.SetPositionInScreen(blink::WebFloatPoint(anchor_x, anchor_y)); |
| return result; |
| } |
| |
| WebGestureEvent SyntheticWebGestureEventBuilder::BuildFling( |
| float velocity_x, |
| float velocity_y, |
| blink::WebGestureDevice source_device) { |
| WebGestureEvent result = |
| Build(WebInputEvent::kGestureFlingStart, source_device); |
| result.data.fling_start.velocity_x = velocity_x; |
| result.data.fling_start.velocity_y = velocity_y; |
| return result; |
| } |
| |
| SyntheticWebTouchEvent::SyntheticWebTouchEvent() : WebTouchEvent() { |
| unique_touch_event_id = ui::GetNextTouchEventId(); |
| SetTimestamp(ui::EventTimeForNow()); |
| pointer_id_ = 0; |
| } |
| |
| void SyntheticWebTouchEvent::ResetPoints() { |
| int activePointCount = 0; |
| unsigned count = 0; |
| for (unsigned int i = 0; i < kTouchesLengthCap; ++i) { |
| switch (touches[i].state) { |
| case WebTouchPoint::kStatePressed: |
| case WebTouchPoint::kStateMoved: |
| case WebTouchPoint::kStateStationary: |
| touches[i].state = WebTouchPoint::kStateStationary; |
| ++activePointCount; |
| ++count; |
| break; |
| case WebTouchPoint::kStateReleased: |
| case WebTouchPoint::kStateCancelled: |
| touches[i] = WebTouchPoint(); |
| ++count; |
| break; |
| case WebTouchPoint::kStateUndefined: |
| break; |
| } |
| if (count >= touches_length) |
| break; |
| } |
| touches_length = activePointCount; |
| type_ = WebInputEvent::kUndefined; |
| moved_beyond_slop_region = false; |
| unique_touch_event_id = ui::GetNextTouchEventId(); |
| } |
| |
| int SyntheticWebTouchEvent::PressPoint(float x, float y) { |
| int index = FirstFreeIndex(); |
| if (index == -1) |
| return -1; |
| WebTouchPoint& point = touches[index]; |
| point.id = pointer_id_++; |
| point.SetPositionInWidget(x, y); |
| point.SetPositionInScreen(x, y); |
| point.state = WebTouchPoint::kStatePressed; |
| // Use radius != default(25.f) to test the value is propagated correctly |
| point.radius_x = point.radius_y = 20.f; |
| point.rotation_angle = 1.f; |
| point.force = 1.f; |
| point.tilt_x = point.tilt_y = 0; |
| point.pointer_type = blink::WebPointerProperties::PointerType::kTouch; |
| ++touches_length; |
| WebTouchEventTraits::ResetType(WebInputEvent::kTouchStart, TimeStamp(), this); |
| return index; |
| } |
| |
| void SyntheticWebTouchEvent::MovePoint(int index, float x, float y) { |
| CHECK_GE(index, 0); |
| CHECK_LT(index, kTouchesLengthCap); |
| // Always set this bit to avoid otherwise unexpected touchmove suppression. |
| // The caller can opt-out explicitly, if necessary. |
| moved_beyond_slop_region = true; |
| WebTouchPoint& point = touches[index]; |
| point.SetPositionInWidget(x, y); |
| point.SetPositionInScreen(x, y); |
| touches[index].state = WebTouchPoint::kStateMoved; |
| WebTouchEventTraits::ResetType(WebInputEvent::kTouchMove, TimeStamp(), this); |
| } |
| |
| void SyntheticWebTouchEvent::ReleasePoint(int index) { |
| CHECK_GE(index, 0); |
| CHECK_LT(index, kTouchesLengthCap); |
| touches[index].state = WebTouchPoint::kStateReleased; |
| touches[index].force = 0.f; |
| WebTouchEventTraits::ResetType(WebInputEvent::kTouchEnd, TimeStamp(), this); |
| } |
| |
| void SyntheticWebTouchEvent::CancelPoint(int index) { |
| CHECK_GE(index, 0); |
| CHECK_LT(index, kTouchesLengthCap); |
| touches[index].state = WebTouchPoint::kStateCancelled; |
| WebTouchEventTraits::ResetType(WebInputEvent::kTouchCancel, TimeStamp(), |
| this); |
| } |
| |
| void SyntheticWebTouchEvent::SetTimestamp(base::TimeTicks timestamp) { |
| SetTimeStamp(timestamp); |
| } |
| |
| int SyntheticWebTouchEvent::FirstFreeIndex() { |
| for (size_t i = 0; i < kTouchesLengthCap; ++i) { |
| if (touches[i].state == WebTouchPoint::kStateUndefined) |
| return i; |
| } |
| return -1; |
| } |
| |
| } // namespace content |