blob: eb9ca9b1ddd57d89b8594678ee686e69e22e77fc [file] [log] [blame]
// Copyright 2019 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.
package org.chromium.weblayer_private;
import android.view.MotionEvent;
import android.view.View;
import org.chromium.content_public.browser.GestureListenerManager;
import org.chromium.content_public.browser.GestureStateListener;
import org.chromium.content_public.browser.WebContents;
/**
* WebContentsGestureStateTracker is responsible for tracking when a scroll/gesture is in progress
* and notifying when the state changes.
*/
// TODO(sky): refactor TabGestureStateListener and this to a common place.
public final class WebContentsGestureStateTracker {
private GestureListenerManager mGestureListenerManager;
private GestureStateListener mGestureListener;
private final OnGestureStateChangedListener mListener;
private boolean mScrolling;
private boolean mIsInGesture;
/**
* The View events are tracked on.
*/
private View mContentView;
/**
* Notified when the gesture state changes.
*/
public interface OnGestureStateChangedListener {
/**
* Called when the value of isInGestureOrScroll() changes.
*/
public void onGestureStateChanged();
}
public WebContentsGestureStateTracker(
View contentView, WebContents webContents, OnGestureStateChangedListener listener) {
mListener = listener;
mGestureListenerManager = GestureListenerManager.fromWebContents(webContents);
mContentView = contentView;
mContentView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
final int eventAction = event.getActionMasked();
final boolean oldState = isInGestureOrScroll();
if (eventAction == MotionEvent.ACTION_DOWN
|| eventAction == MotionEvent.ACTION_POINTER_DOWN) {
mIsInGesture = true;
} else if (eventAction == MotionEvent.ACTION_CANCEL
|| eventAction == MotionEvent.ACTION_UP) {
mIsInGesture = false;
}
if (isInGestureOrScroll() != oldState) {
mListener.onGestureStateChanged();
}
return false;
}
});
mGestureListener = new GestureStateListener() {
@Override
public void onFlingStartGesture(int scrollOffsetY, int scrollExtentY) {
onScrollingStateChanged();
}
@Override
public void onFlingEndGesture(int scrollOffsetY, int scrollExtentY) {
onScrollingStateChanged();
}
@Override
public void onScrollStarted(int scrollOffsetY, int scrollExtentY) {
onScrollingStateChanged();
}
@Override
public void onScrollEnded(int scrollOffsetY, int scrollExtentY) {
onScrollingStateChanged();
}
private void onScrollingStateChanged() {
final boolean oldState = isInGestureOrScroll();
mScrolling = mGestureListenerManager.isScrollInProgress();
if (oldState != isInGestureOrScroll()) {
mListener.onGestureStateChanged();
}
}
};
mGestureListenerManager.addListener(mGestureListener);
}
public void destroy() {
mGestureListenerManager.removeListener(mGestureListener);
mGestureListener = null;
mGestureListenerManager = null;
mContentView.setOnTouchListener(null);
}
/**
* Returns true if the user has touched the target view, or is scrolling.
*/
public boolean isInGestureOrScroll() {
return mIsInGesture || mScrolling;
}
}