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

Unified Diff: ui/events/blink/blink_event_util.cc

Issue 2429953002: Implement compositor thread VSync aligned event queue (Closed)
Patch Set: dtapuska&enne's review: Call |Now()| once per loop; Chromium style; Remove parameterized test Created 4 years, 1 month 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/events/blink/blink_event_util.h ('k') | ui/events/blink/blink_features.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/events/blink/blink_event_util.cc
diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc
index 360ca65c17de6a56d83d1568845873cb11930205..5148bf1600513a3e43c5be21b0fc44c54f5e3cd7 100644
--- a/ui/events/blink/blink_event_util.cc
+++ b/ui/events/blink/blink_event_util.cc
@@ -10,7 +10,9 @@
#include <stddef.h>
#include <algorithm>
+#include <bitset>
#include <cmath>
+#include <limits>
#include "base/time/time.h"
#include "build/build_config.h"
@@ -27,13 +29,18 @@
using blink::WebGestureEvent;
using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
using blink::WebPointerProperties;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
+using std::numeric_limits;
namespace ui {
namespace {
+const int kInvalidTouchIndex = -1;
+
WebInputEvent::Type ToWebTouchEventType(MotionEvent::Action action) {
switch (action) {
case MotionEvent::ACTION_DOWN:
@@ -195,8 +202,243 @@ WebTouchPoint CreateWebTouchPoint(const MotionEvent& event,
return touch;
}
+float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
+ return accelerated_delta * acceleration_ratio;
+}
+
+float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
+ if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
+ return 1.f;
+ return unaccelerated_delta / accelerated_delta;
+}
+
+// Returns |kInvalidTouchIndex| iff |event| lacks a touch with an ID of |id|.
+int GetIndexOfTouchID(const WebTouchEvent& event, int id) {
+ for (unsigned i = 0; i < event.touchesLength; ++i) {
+ if (event.touches[i].id == id)
+ return i;
+ }
+ return kInvalidTouchIndex;
+}
+
+WebInputEvent::DispatchType MergeDispatchTypes(
+ WebInputEvent::DispatchType type_1,
+ WebInputEvent::DispatchType type_2) {
+ static_assert(WebInputEvent::DispatchType::Blocking <
+ WebInputEvent::DispatchType::EventNonBlocking,
+ "Enum not ordered correctly");
+ static_assert(WebInputEvent::DispatchType::EventNonBlocking <
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive,
+ "Enum not ordered correctly");
+ static_assert(
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive <
+ WebInputEvent::DispatchType::ListenersForcedNonBlockingDueToFling,
+ "Enum not ordered correctly");
+ return static_cast<WebInputEvent::DispatchType>(
+ std::min(static_cast<int>(type_1), static_cast<int>(type_2)));
+}
+
+bool CanCoalesce(const WebMouseEvent& event_to_coalesce,
+ const WebMouseEvent& event) {
+ return event.type == event_to_coalesce.type &&
+ event.type == WebInputEvent::MouseMove;
+}
+
+void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) {
+ DCHECK(CanCoalesce(event_to_coalesce, *event));
+ // Accumulate movement deltas.
+ int x = event->movementX;
+ int y = event->movementY;
+ *event = event_to_coalesce;
+ event->movementX += x;
+ event->movementY += y;
+}
+
+bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
+ const WebMouseWheelEvent& event) {
+ return event.modifiers == event_to_coalesce.modifiers &&
+ event.scrollByPage == event_to_coalesce.scrollByPage &&
+ event.phase == event_to_coalesce.phase &&
+ event.momentumPhase == event_to_coalesce.momentumPhase &&
+ event.hasPreciseScrollingDeltas ==
+ event_to_coalesce.hasPreciseScrollingDeltas;
+}
+
+void Coalesce(const WebMouseWheelEvent& event_to_coalesce,
+ WebMouseWheelEvent* event) {
+ DCHECK(CanCoalesce(event_to_coalesce, *event));
+ float unaccelerated_x =
+ GetUnacceleratedDelta(event->deltaX, event->accelerationRatioX) +
+ GetUnacceleratedDelta(event_to_coalesce.deltaX,
+ event_to_coalesce.accelerationRatioX);
+ float unaccelerated_y =
+ GetUnacceleratedDelta(event->deltaY, event->accelerationRatioY) +
+ GetUnacceleratedDelta(event_to_coalesce.deltaY,
+ event_to_coalesce.accelerationRatioY);
+ float old_deltaX = event->deltaX;
+ float old_deltaY = event->deltaY;
+ float old_wheelTicksX = event->wheelTicksX;
+ float old_wheelTicksY = event->wheelTicksY;
+ float old_movementX = event->movementX;
+ float old_movementY = event->movementY;
+ *event = event_to_coalesce;
+ event->deltaX += old_deltaX;
+ event->deltaY += old_deltaY;
+ event->wheelTicksX += old_wheelTicksX;
+ event->wheelTicksY += old_wheelTicksY;
+ event->movementX += old_movementX;
+ event->movementY += old_movementY;
+ event->accelerationRatioX =
+ GetAccelerationRatio(event->deltaX, unaccelerated_x);
+ event->accelerationRatioY =
+ GetAccelerationRatio(event->deltaY, unaccelerated_y);
+}
+
+bool CanCoalesce(const WebTouchEvent& event_to_coalesce,
+ const WebTouchEvent& event) {
+ if (event.type != event_to_coalesce.type ||
+ event.type != WebInputEvent::TouchMove ||
+ event.modifiers != event_to_coalesce.modifiers ||
+ event.touchesLength != event_to_coalesce.touchesLength ||
+ event.touchesLength > WebTouchEvent::kTouchesLengthCap)
+ return false;
+
+ static_assert(WebTouchEvent::kTouchesLengthCap <= sizeof(int32_t) * 8U,
+ "suboptimal kTouchesLengthCap size");
+ // Ensure that we have a 1-to-1 mapping of pointer ids between touches.
+ std::bitset<WebTouchEvent::kTouchesLengthCap> unmatched_event_touches(
+ (1 << event.touchesLength) - 1);
+ for (unsigned i = 0; i < event_to_coalesce.touchesLength; ++i) {
+ int event_touch_index =
+ GetIndexOfTouchID(event, event_to_coalesce.touches[i].id);
+ if (event_touch_index == kInvalidTouchIndex)
+ return false;
+ if (!unmatched_event_touches[event_touch_index])
+ return false;
+ unmatched_event_touches[event_touch_index] = false;
+ }
+ return unmatched_event_touches.none();
+}
+
+void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) {
+ DCHECK(CanCoalesce(event_to_coalesce, *event));
+ // The WebTouchPoints include absolute position information. So it is
+ // sufficient to simply replace the previous event with the new event->
+ // However, it is necessary to make sure that all the points have the
+ // correct state, i.e. the touch-points that moved in the last event, but
+ // didn't change in the current event, will have Stationary state. It is
+ // necessary to change them back to Moved state.
+ WebTouchEvent old_event = *event;
+ *event = event_to_coalesce;
+ for (unsigned i = 0; i < event->touchesLength; ++i) {
+ int i_old = GetIndexOfTouchID(old_event, event->touches[i].id);
+ if (old_event.touches[i_old].state == blink::WebTouchPoint::StateMoved)
+ event->touches[i].state = blink::WebTouchPoint::StateMoved;
+ }
+ event->movedBeyondSlopRegion |= old_event.movedBeyondSlopRegion;
+ event->dispatchType = MergeDispatchTypes(old_event.dispatchType,
+ event_to_coalesce.dispatchType);
+}
+
+bool CanCoalesce(const WebGestureEvent& event_to_coalesce,
+ const WebGestureEvent& event) {
+ if (event.type != event_to_coalesce.type ||
+ event.sourceDevice != event_to_coalesce.sourceDevice ||
+ event.modifiers != event_to_coalesce.modifiers)
+ return false;
+
+ if (event.type == WebInputEvent::GestureScrollUpdate)
+ return true;
+
+ // GesturePinchUpdate scales can be combined only if they share a focal point,
+ // e.g., with double-tap drag zoom.
+ if (event.type == WebInputEvent::GesturePinchUpdate &&
+ event.x == event_to_coalesce.x && event.y == event_to_coalesce.y)
+ return true;
+
+ return false;
+}
+
+void Coalesce(const WebGestureEvent& event_to_coalesce,
+ WebGestureEvent* event) {
+ DCHECK(CanCoalesce(event_to_coalesce, *event));
+ if (event->type == WebInputEvent::GestureScrollUpdate) {
+ event->data.scrollUpdate.deltaX +=
+ event_to_coalesce.data.scrollUpdate.deltaX;
+ event->data.scrollUpdate.deltaY +=
+ event_to_coalesce.data.scrollUpdate.deltaY;
+ DCHECK_EQ(
+ event->data.scrollUpdate.previousUpdateInSequencePrevented,
+ event_to_coalesce.data.scrollUpdate.previousUpdateInSequencePrevented);
+ } else if (event->type == WebInputEvent::GesturePinchUpdate) {
+ event->data.pinchUpdate.scale *= event_to_coalesce.data.pinchUpdate.scale;
+ // Ensure the scale remains bounded above 0 and below Infinity so that
+ // we can reliably perform operations like log on the values.
+ if (event->data.pinchUpdate.scale < numeric_limits<float>::min())
+ event->data.pinchUpdate.scale = numeric_limits<float>::min();
+ else if (event->data.pinchUpdate.scale > numeric_limits<float>::max())
+ event->data.pinchUpdate.scale = numeric_limits<float>::max();
+ }
+}
+
} // namespace
+bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce,
+ const blink::WebInputEvent& event) {
+ if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) &&
+ blink::WebInputEvent::isGestureEventType(event.type)) {
+ return CanCoalesce(
+ static_cast<const blink::WebGestureEvent&>(event_to_coalesce),
+ static_cast<const blink::WebGestureEvent&>(event));
+ }
+ if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) &&
+ blink::WebInputEvent::isMouseEventType(event.type)) {
+ return CanCoalesce(
+ static_cast<const blink::WebMouseEvent&>(event_to_coalesce),
+ static_cast<const blink::WebMouseEvent&>(event));
+ }
+ if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) &&
+ blink::WebInputEvent::isTouchEventType(event.type)) {
+ return CanCoalesce(
+ static_cast<const blink::WebTouchEvent&>(event_to_coalesce),
+ static_cast<const blink::WebTouchEvent&>(event));
+ }
+ if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel &&
+ event.type == blink::WebInputEvent::MouseWheel) {
+ return CanCoalesce(
+ static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce),
+ static_cast<const blink::WebMouseWheelEvent&>(event));
+ }
+ return false;
+}
+
+void Coalesce(const blink::WebInputEvent& event_to_coalesce,
+ blink::WebInputEvent* event) {
+ if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) &&
+ blink::WebInputEvent::isGestureEventType(event->type)) {
+ Coalesce(static_cast<const blink::WebGestureEvent&>(event_to_coalesce),
+ static_cast<blink::WebGestureEvent*>(event));
+ return;
+ }
+ if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) &&
+ blink::WebInputEvent::isMouseEventType(event->type)) {
+ Coalesce(static_cast<const blink::WebMouseEvent&>(event_to_coalesce),
+ static_cast<blink::WebMouseEvent*>(event));
+ return;
+ }
+ if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) &&
+ blink::WebInputEvent::isTouchEventType(event->type)) {
+ Coalesce(static_cast<const blink::WebTouchEvent&>(event_to_coalesce),
+ static_cast<blink::WebTouchEvent*>(event));
+ return;
+ }
+ if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel &&
+ event->type == blink::WebInputEvent::MouseWheel) {
+ Coalesce(static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce),
+ static_cast<blink::WebMouseWheelEvent*>(event));
+ }
+}
+
blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
const MotionEvent& event,
bool moved_beyond_slop_region) {
@@ -616,4 +858,28 @@ blink::WebInputEvent::Modifiers DomCodeToWebInputEventModifiers(DomCode code) {
return static_cast<blink::WebInputEvent::Modifiers>(0);
}
+bool IsGestureScollOrPinch(WebInputEvent::Type type) {
+ switch (type) {
+ case blink::WebGestureEvent::GestureScrollBegin:
+ case blink::WebGestureEvent::GestureScrollUpdate:
+ case blink::WebGestureEvent::GestureScrollEnd:
+ case blink::WebGestureEvent::GesturePinchBegin:
+ case blink::WebGestureEvent::GesturePinchUpdate:
+ case blink::WebGestureEvent::GesturePinchEnd:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool IsContinuousGestureEvent(WebInputEvent::Type type) {
+ switch (type) {
+ case blink::WebGestureEvent::GestureScrollUpdate:
+ case blink::WebGestureEvent::GesturePinchUpdate:
+ return true;
+ default:
+ return false;
+ }
+}
+
} // namespace ui
« no previous file with comments | « ui/events/blink/blink_event_util.h ('k') | ui/events/blink/blink_features.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698