Skip to content

Commit

Permalink
weblayer: Implement onVerticalOverscroll
Browse files Browse the repository at this point in the history
See java doc for new API for details.

Bug: 1294793
Change-Id: I2312cb105ffa2ec7a5bb82872424d8128941dce4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3520804
Reviewed-by: Scott Violet <sky@chromium.org>
Commit-Queue: Bo Liu <boliu@chromium.org>
Cr-Commit-Position: refs/heads/main@{#981239}
  • Loading branch information
Bo Liu authored and Chromium LUCI CQ committed Mar 15, 2022
1 parent e63069d commit 44e0e74
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 0 deletions.
18 changes: 18 additions & 0 deletions content/browser/android/gesture_listener_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
#include "content/public/android/content_jni_headers/GestureListenerManagerImpl_jni.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "ui/events/android/gesture_event_type.h"
#include "ui/events/blink/did_overscroll_params.h"
#include "ui/gfx/geometry/size_f.h"

using blink::WebGestureEvent;
Expand Down Expand Up @@ -200,6 +202,22 @@ bool GestureListenerManager::FilterInputEvent(const WebInputEvent& event) {
gesture.PositionInWidget().y() * dip_scale);
}

void GestureListenerManager::DidOverscroll(
const ui::DidOverscrollParams& params) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
if (j_obj.is_null())
return;
float x = params.accumulated_overscroll.x();
float y = params.accumulated_overscroll.y();
if (!IsUseZoomForDSFEnabled()) {
float dip_scale = web_contents_->GetNativeView()->GetDipScale();
x *= dip_scale;
y *= dip_scale;
}
return Java_GestureListenerManagerImpl_didOverscroll(env, j_obj, x, y);
}

// All positions and sizes (except |top_shown_pix|) are in CSS pixels.
// Note that viewport_width/height is a best effort based.
void GestureListenerManager::UpdateScrollInfo(const gfx::PointF& scroll_offset,
Expand Down
5 changes: 5 additions & 0 deletions content/browser/android/gesture_listener_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ class SizeF;
class PointF;
} // namespace gfx

namespace ui {
struct DidOverscrollParams;
}

namespace content {

class NavigationHandle;
Expand Down Expand Up @@ -54,6 +58,7 @@ class CONTENT_EXPORT GestureListenerManager : public RenderWidgetHostConnector {
blink::mojom::InputEventResultState ack_result);
void DidStopFlinging();
bool FilterInputEvent(const blink::WebInputEvent& event);
void DidOverscroll(const ui::DidOverscrollParams& params);

// All sizes and offsets are in CSS pixels (except |top_show_pix|)
// as cached by the renderer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2098,6 +2098,9 @@ void RenderWidgetHostViewAndroid::DidOverscroll(
if (!view_.parent() || !is_showing_)
return;

if (gesture_listener_manager_)
gesture_listener_manager_->DidOverscroll(params);

if (overscroll_controller_)
overscroll_controller_->OnOverscrolled(params);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,14 @@ private boolean filterTapOrPressEvent(int type, int x, int y) {
return false;
}

@CalledByNative
private void didOverscroll(float accumulatedOverscrollX, float accumulatedOverscrollY) {
for (mIterator.rewind(); mIterator.hasNext();) {
GestureStateListener listener = mIterator.next();
listener.didOverscroll(accumulatedOverscrollX, accumulatedOverscrollY);
}
}

@SuppressWarnings("unused")
@CalledByNative
private void updateScrollInfo(float scrollOffsetX, float scrollOffsetY, float pageScaleFactor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ public void onWindowFocusChanged(boolean hasWindowFocus) {}
*/
public void onLongPress() {}

/**
* Called on overscroll. This happens when user tries to scroll beyond scroll bounds, or when
* a fling animation hits scroll bounds.
* @param accumulatedOverscrollX see `ui::DidOverscrollParams::accumulated_overscroll`.
* @param accumulatedOverscrollY see `ui::DidOverscrollParams::accumulated_overscroll`.
*/
public void didOverscroll(float accumulatedOverscrollX, float accumulatedOverscrollY) {}

/**
* Called when the gesture source is being destroyed.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.net.Uri;
import android.os.Build;
import android.support.test.InstrumentationRegistry;
import android.view.View;

import androidx.test.filters.SmallTest;

Expand Down Expand Up @@ -423,4 +424,43 @@ public void onScrollNotification(
ScrollNotificationType.DIRECTION_CHANGED_UP, (int) notificationTypes[0]);
Assert.assertTrue(scrollRatio[0] < 0.5);
}

@Test
@SmallTest
@MinWebLayerVersion(101)
public void testOnVerticalOverscroll() throws TimeoutException {
InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank");

float overscrollY[] = new float[1];
CallbackHelper callbackHelper = new CallbackHelper();
TestThreadUtils.runOnUiThreadBlocking(() -> {
Tab tab = activity.getTab();
TabCallback callback = new TabCallback() {
@Override
public void onVerticalOverscroll(float accumulatedOverscrollY) {
overscrollY[0] = accumulatedOverscrollY;
callbackHelper.notifyCalled();
tab.unregisterTabCallback(this);
}
};
tab.registerTabCallback(callback);
});

View decorView[] = new View[1];
int dimension[] = new int[2];
TestThreadUtils.runOnUiThreadBlocking(() -> {
decorView[0] = activity.getWindow().getDecorView();
dimension[0] = decorView[0].getWidth();
dimension[1] = decorView[0].getHeight();
});

int x = dimension[0] / 2;
int fromY = dimension[1] / 3;
int toY = dimension[1] / 3 * 2;

TestTouchUtils.dragCompleteView(InstrumentationRegistry.getInstrumentation(), decorView[0],
/*fromX=*/x, /*toX=*/x, fromY, toY, /*stepCount=*/10);
callbackHelper.waitForFirst();
Assert.assertThat(overscrollY[0], Matchers.lessThan(0f));
}
}
15 changes: 15 additions & 0 deletions weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import org.chromium.components.webapps.AddToHomescreenCoordinator;
import org.chromium.components.webapps.AppBannerManager;
import org.chromium.content_public.browser.GestureListenerManager;
import org.chromium.content_public.browser.GestureStateListener;
import org.chromium.content_public.browser.GestureStateListenerWithScroll;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.NavigationHandle;
Expand Down Expand Up @@ -314,6 +315,20 @@ public void viewportFitChanged(@WebContentsObserver.ViewportFitType int value) {

mMediaSessionHelper = new MediaSessionHelper(
mWebContents, MediaSessionManager.createMediaSessionHelperDelegate(this));

GestureListenerManager.fromWebContents(mWebContents)
.addListener(new GestureStateListener() {
@Override
public void didOverscroll(
float accumulatedOverscrollX, float accumulatedOverscrollY) {
if (WebLayerFactoryImpl.getClientMajorVersion() < 101) return;
try {
mClient.onVerticalOverscroll(accumulatedOverscrollY);
} catch (RemoteException e) {
throw new APICallException(e);
}
}
});
}

private void doInitAfterSettingContainerView() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,7 @@ interface ITabClient {
in IObjectWrapper linkText, in IObjectWrapper titleOrAltText,
in IObjectWrapper srcUrl, in boolean isImage, in boolean isVideo, in boolean canDownload,
in IContextMenuParams contextMenuParams) = 13;

// Added in M101.
void onVerticalOverscroll(float accumulatedOverscrollY) = 14;
}
8 changes: 8 additions & 0 deletions weblayer/public/java/org/chromium/weblayer/Tab.java
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,14 @@ public void onActionItemClicked(
mActionModeCallback.onActionItemClicked(actionModeItemType, selectedString);
}
}

@Override
public void onVerticalOverscroll(float accumulatedOverscrollY) {
StrictModeWorkaround.apply();
for (TabCallback callback : mCallbacks) {
callback.onVerticalOverscroll(accumulatedOverscrollY);
}
}
}

private static final class ErrorPageCallbackClientImpl extends IErrorPageCallbackClient.Stub {
Expand Down
17 changes: 17 additions & 0 deletions weblayer/public/java/org/chromium/weblayer/TabCallback.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,21 @@ public void onBackgroundColorChanged(int color) {}
*/
public void onScrollNotification(
@ScrollNotificationType int notificationType, float currentScrollRatio) {}

/**
* Notification for vertical overscroll. This happens when user tries to touch scroll beyond
* the scroll bounds, or when a fling animation hits scroll bounds.
* A few caveats when using this callback:
* * This should be considered independent and unordered with respect to other scroll callbacks
* such as `onScrollNotification` or `ScrollOffsetCallback.onVerticalScrollOffsetChanged`.
* Client should not assume a certain order between this and other scroll notifications.
* * The value is accumulated scroll, so the magnitude of the value only goes up for a single
* overscroll gesture. However this is not enough to distinguish between two overscroll
* gestures and client must listen to touch events to make such distinction. Similarly there
* is no "end overscroll" event, and client is expected to listen to touch events as well.
* Added in M101.
* @param accumulatedOverscrollY negative for when trying to scroll beyond offset 0, positive
* for when trying to scroll beyond bottom scroll bounds.
*/
public void onVerticalOverscroll(float accumulatedOverscrollY) {}
}

0 comments on commit 44e0e74

Please sign in to comment.