[WebLayer] Add WebContentsDelegate::ShouldPinTopControlsToContentTop()
This CL defines WebContentsDelegate::ShouldPinTopControlsToContentTop(), which embedders can use to tell BrowserControlsOffsetManager to only show the top browser controls if the page is scrolled to the top. WebLayer's Browser#setTopView pinToContentTop parameter is hooked up to this new method. Bug: 1069498 Change-Id: I7a19656c0ee3219936c3279bfb89591b1f3abb56 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2284138 Commit-Queue: Robbie McElrath <rmcelrath@chromium.org> Reviewed-by: John Abd-El-Malek <jam@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Reviewed-by: Bo <boliu@chromium.org> Reviewed-by: David Bokan <bokan@chromium.org> Cr-Commit-Position: refs/heads/master@{#790985}
This commit is contained in:

committed by
Commit Bot

parent
fa60a76aa5
commit
c727f0eb0f
cc
input
browser_controls_offset_manager.ccbrowser_controls_offset_manager_client.hbrowser_controls_offset_manager_unittest.cc
ipc
trees
content
browser
renderer_host
web_contents
public
weblayer
browser
shell
android
shell_apk
@@ -7,6 +7,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "base/check_op.h"
|
#include "base/check_op.h"
|
||||||
#include "base/memory/ptr_util.h"
|
#include "base/memory/ptr_util.h"
|
||||||
@@ -369,7 +370,21 @@ gfx::Vector2dF BrowserControlsOffsetManager::ScrollBy(
|
|||||||
pending_delta.y() < 0))
|
pending_delta.y() < 0))
|
||||||
return pending_delta;
|
return pending_delta;
|
||||||
|
|
||||||
accumulated_scroll_delta_ += pending_delta.y();
|
// Scroll the page up before expanding the browser controls if
|
||||||
|
// ShouldPinTopControlsToContentTop() returns true.
|
||||||
|
float viewport_offset_y = client_->ViewportScrollOffset().y();
|
||||||
|
if (client_->ShouldPinTopControlsToContentTop() && pending_delta.y() < 0 &&
|
||||||
|
viewport_offset_y > 0) {
|
||||||
|
// Reset the baseline so the controls will immediately begin to scroll
|
||||||
|
// once we're at the top.
|
||||||
|
ResetBaseline();
|
||||||
|
// Only scroll the controls by the amount remaining after the page contents
|
||||||
|
// have been scrolled to the top.
|
||||||
|
accumulated_scroll_delta_ =
|
||||||
|
std::min(0.f, pending_delta.y() + viewport_offset_y);
|
||||||
|
} else {
|
||||||
|
accumulated_scroll_delta_ += pending_delta.y();
|
||||||
|
}
|
||||||
|
|
||||||
// We want to base our calculations on top or bottom controls. After consuming
|
// We want to base our calculations on top or bottom controls. After consuming
|
||||||
// the scroll delta, we will calculate a shown ratio for the controls. The
|
// the scroll delta, we will calculate a shown ratio for the controls. The
|
||||||
|
@@ -5,6 +5,10 @@
|
|||||||
#ifndef CC_INPUT_BROWSER_CONTROLS_OFFSET_MANAGER_CLIENT_H_
|
#ifndef CC_INPUT_BROWSER_CONTROLS_OFFSET_MANAGER_CLIENT_H_
|
||||||
#define CC_INPUT_BROWSER_CONTROLS_OFFSET_MANAGER_CLIENT_H_
|
#define CC_INPUT_BROWSER_CONTROLS_OFFSET_MANAGER_CLIENT_H_
|
||||||
|
|
||||||
|
namespace gfx {
|
||||||
|
class ScrollOffset;
|
||||||
|
}
|
||||||
|
|
||||||
namespace cc {
|
namespace cc {
|
||||||
|
|
||||||
class CC_EXPORT BrowserControlsOffsetManagerClient {
|
class CC_EXPORT BrowserControlsOffsetManagerClient {
|
||||||
@@ -17,7 +21,9 @@ class CC_EXPORT BrowserControlsOffsetManagerClient {
|
|||||||
float bottom_ratio) = 0;
|
float bottom_ratio) = 0;
|
||||||
virtual float CurrentTopControlsShownRatio() const = 0;
|
virtual float CurrentTopControlsShownRatio() const = 0;
|
||||||
virtual float CurrentBottomControlsShownRatio() const = 0;
|
virtual float CurrentBottomControlsShownRatio() const = 0;
|
||||||
|
virtual gfx::ScrollOffset ViewportScrollOffset() const = 0;
|
||||||
virtual void DidChangeBrowserControlsPosition() = 0;
|
virtual void DidChangeBrowserControlsPosition() = 0;
|
||||||
|
virtual bool ShouldPinTopControlsToContentTop() const = 0;
|
||||||
virtual bool HaveRootScrollNode() const = 0;
|
virtual bool HaveRootScrollNode() const = 0;
|
||||||
virtual void SetNeedsCommit() = 0;
|
virtual void SetNeedsCommit() = 0;
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "base/time/time.h"
|
#include "base/time/time.h"
|
||||||
@@ -30,7 +31,8 @@ class MockBrowserControlsOffsetManagerClient
|
|||||||
: host_impl_(&task_runner_provider_, &task_graph_runner_),
|
: host_impl_(&task_runner_provider_, &task_graph_runner_),
|
||||||
redraw_needed_(false),
|
redraw_needed_(false),
|
||||||
update_draw_properties_needed_(false),
|
update_draw_properties_needed_(false),
|
||||||
browser_controls_params_({top_controls_height, 0, 0, 0, false, false}),
|
browser_controls_params_(
|
||||||
|
{top_controls_height, 0, 0, 0, false, false, false}),
|
||||||
bottom_controls_shown_ratio_(1.f),
|
bottom_controls_shown_ratio_(1.f),
|
||||||
top_controls_shown_ratio_(1.f),
|
top_controls_shown_ratio_(1.f),
|
||||||
browser_controls_show_threshold_(browser_controls_show_threshold),
|
browser_controls_show_threshold_(browser_controls_show_threshold),
|
||||||
@@ -66,6 +68,14 @@ class MockBrowserControlsOffsetManagerClient
|
|||||||
return browser_controls_params_.top_controls_min_height;
|
return browser_controls_params_.top_controls_min_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShouldPinTopControlsToContentTop() const override {
|
||||||
|
return browser_controls_params_.pin_top_controls_to_content_top;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::ScrollOffset ViewportScrollOffset() const override {
|
||||||
|
return viewport_scroll_offset_;
|
||||||
|
}
|
||||||
|
|
||||||
void SetCurrentBrowserControlsShownRatio(float top_ratio,
|
void SetCurrentBrowserControlsShownRatio(float top_ratio,
|
||||||
float bottom_ratio) override {
|
float bottom_ratio) override {
|
||||||
AssertAndClamp(&top_ratio);
|
AssertAndClamp(&top_ratio);
|
||||||
@@ -110,6 +120,15 @@ class MockBrowserControlsOffsetManagerClient
|
|||||||
params.animate_browser_controls_height_changes);
|
params.animate_browser_controls_height_changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetViewportScrollOffset(float x, float y) {
|
||||||
|
viewport_scroll_offset_ = gfx::ScrollOffset(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollVerticallyBy(float dy) {
|
||||||
|
gfx::Vector2dF viewport_scroll_delta = manager()->ScrollBy({0.f, dy});
|
||||||
|
viewport_scroll_offset_.Add(gfx::ScrollOffset(viewport_scroll_delta));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FakeImplTaskRunnerProvider task_runner_provider_;
|
FakeImplTaskRunnerProvider task_runner_provider_;
|
||||||
TestTaskGraphRunner task_graph_runner_;
|
TestTaskGraphRunner task_graph_runner_;
|
||||||
@@ -125,6 +144,7 @@ class MockBrowserControlsOffsetManagerClient
|
|||||||
float top_controls_shown_ratio_;
|
float top_controls_shown_ratio_;
|
||||||
float browser_controls_show_threshold_;
|
float browser_controls_show_threshold_;
|
||||||
float browser_controls_hide_threshold_;
|
float browser_controls_hide_threshold_;
|
||||||
|
gfx::ScrollOffset viewport_scroll_offset_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(BrowserControlsOffsetManagerTest, EnsureScrollThresholdApplied) {
|
TEST(BrowserControlsOffsetManagerTest, EnsureScrollThresholdApplied) {
|
||||||
@@ -1143,5 +1163,44 @@ TEST(BrowserControlsOffsetManagerTest,
|
|||||||
EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
|
EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(BrowserControlsOffsetManagerTest, PinTopControlsToContentTop) {
|
||||||
|
MockBrowserControlsOffsetManagerClient client(0.f, 0.5f, 0.5f);
|
||||||
|
client.SetBrowserControlsParams({/*top_controls_height=*/100.f, 0, 0, 0,
|
||||||
|
false, false,
|
||||||
|
/*pin_top_controls_to_content_top=*/true});
|
||||||
|
BrowserControlsOffsetManager* manager = client.manager();
|
||||||
|
|
||||||
|
// Scroll down to hide the controls entirely.
|
||||||
|
manager->ScrollBegin();
|
||||||
|
client.ScrollVerticallyBy(150.f);
|
||||||
|
EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
|
||||||
|
EXPECT_FLOAT_EQ(50.f, client.ViewportScrollOffset().y());
|
||||||
|
manager->ScrollEnd();
|
||||||
|
|
||||||
|
manager->ScrollBegin();
|
||||||
|
|
||||||
|
// Scroll back up a bit and ensure the controls don't move until we're at
|
||||||
|
// the top.
|
||||||
|
client.ScrollVerticallyBy(-20.f);
|
||||||
|
EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
|
||||||
|
EXPECT_FLOAT_EQ(30.f, client.ViewportScrollOffset().y());
|
||||||
|
|
||||||
|
client.ScrollVerticallyBy(-10.f);
|
||||||
|
EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
|
||||||
|
EXPECT_FLOAT_EQ(20.f, client.ViewportScrollOffset().y());
|
||||||
|
|
||||||
|
// After scrolling past the top, the top controls should start showing.
|
||||||
|
client.ScrollVerticallyBy(-30.f);
|
||||||
|
EXPECT_FLOAT_EQ(-90.f, manager->ControlsTopOffset());
|
||||||
|
EXPECT_FLOAT_EQ(0.f, client.ViewportScrollOffset().y());
|
||||||
|
|
||||||
|
client.ScrollVerticallyBy(-50.f);
|
||||||
|
EXPECT_FLOAT_EQ(-40.f, manager->ControlsTopOffset());
|
||||||
|
// The final offset is greater than gtest's epsilon.
|
||||||
|
EXPECT_GT(0.0001f, client.ViewportScrollOffset().y());
|
||||||
|
|
||||||
|
manager->ScrollEnd();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace cc
|
} // namespace cc
|
||||||
|
@@ -32,6 +32,7 @@ IPC_STRUCT_TRAITS_BEGIN(cc::BrowserControlsParams)
|
|||||||
IPC_STRUCT_TRAITS_MEMBER(bottom_controls_min_height)
|
IPC_STRUCT_TRAITS_MEMBER(bottom_controls_min_height)
|
||||||
IPC_STRUCT_TRAITS_MEMBER(animate_browser_controls_height_changes)
|
IPC_STRUCT_TRAITS_MEMBER(animate_browser_controls_height_changes)
|
||||||
IPC_STRUCT_TRAITS_MEMBER(browser_controls_shrink_blink_size)
|
IPC_STRUCT_TRAITS_MEMBER(browser_controls_shrink_blink_size)
|
||||||
|
IPC_STRUCT_TRAITS_MEMBER(pin_top_controls_to_content_top)
|
||||||
IPC_STRUCT_TRAITS_END()
|
IPC_STRUCT_TRAITS_END()
|
||||||
|
|
||||||
#endif // CC_IPC_CC_PARAM_TRAITS_MACROS_H_
|
#endif // CC_IPC_CC_PARAM_TRAITS_MACROS_H_
|
||||||
|
@@ -15,7 +15,9 @@ bool BrowserControlsParams::operator==(
|
|||||||
animate_browser_controls_height_changes ==
|
animate_browser_controls_height_changes ==
|
||||||
other.animate_browser_controls_height_changes &&
|
other.animate_browser_controls_height_changes &&
|
||||||
browser_controls_shrink_blink_size ==
|
browser_controls_shrink_blink_size ==
|
||||||
other.browser_controls_shrink_blink_size;
|
other.browser_controls_shrink_blink_size &&
|
||||||
|
pin_top_controls_to_content_top ==
|
||||||
|
other.pin_top_controls_to_content_top;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BrowserControlsParams::operator!=(
|
bool BrowserControlsParams::operator!=(
|
||||||
|
@@ -35,6 +35,11 @@ struct CC_EXPORT BrowserControlsParams {
|
|||||||
// URL-bar (always false on platforms where URL-bar hiding isn't supported).
|
// URL-bar (always false on platforms where URL-bar hiding isn't supported).
|
||||||
bool browser_controls_shrink_blink_size = false;
|
bool browser_controls_shrink_blink_size = false;
|
||||||
|
|
||||||
|
// Whether or not the top controls should be pinned to the top of the page
|
||||||
|
// contents. If true, collapsed top controls won't begin scrolling into view
|
||||||
|
// until the page is scrolled to the top.
|
||||||
|
bool pin_top_controls_to_content_top = false;
|
||||||
|
|
||||||
bool operator==(const BrowserControlsParams& other) const;
|
bool operator==(const BrowserControlsParams& other) const;
|
||||||
bool operator!=(const BrowserControlsParams& other) const;
|
bool operator!=(const BrowserControlsParams& other) const;
|
||||||
};
|
};
|
||||||
|
@@ -3049,6 +3049,10 @@ void LayerTreeHostImpl::DidLoseLayerTreeFrameSink() {
|
|||||||
client_->DidLoseLayerTreeFrameSinkOnImplThread();
|
client_->DidLoseLayerTreeFrameSinkOnImplThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LayerTreeHostImpl::ShouldPinTopControlsToContentTop() const {
|
||||||
|
return active_tree_->pin_top_controls_to_content_top();
|
||||||
|
}
|
||||||
|
|
||||||
bool LayerTreeHostImpl::HaveRootScrollNode() const {
|
bool LayerTreeHostImpl::HaveRootScrollNode() const {
|
||||||
return InnerViewportScrollNode();
|
return InnerViewportScrollNode();
|
||||||
}
|
}
|
||||||
@@ -3779,6 +3783,10 @@ float LayerTreeHostImpl::CurrentBottomControlsShownRatio() const {
|
|||||||
return active_tree_->CurrentBottomControlsShownRatio();
|
return active_tree_->CurrentBottomControlsShownRatio();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfx::ScrollOffset LayerTreeHostImpl::ViewportScrollOffset() const {
|
||||||
|
return viewport_->TotalScrollOffset();
|
||||||
|
}
|
||||||
|
|
||||||
void LayerTreeHostImpl::BindToClient(InputHandlerClient* client) {
|
void LayerTreeHostImpl::BindToClient(InputHandlerClient* client) {
|
||||||
DCHECK(input_handler_client_ == nullptr);
|
DCHECK(input_handler_client_ == nullptr);
|
||||||
input_handler_client_ = client;
|
input_handler_client_ = client;
|
||||||
|
@@ -345,9 +345,11 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
|
|||||||
float bottom_ratio) override;
|
float bottom_ratio) override;
|
||||||
float CurrentTopControlsShownRatio() const override;
|
float CurrentTopControlsShownRatio() const override;
|
||||||
float CurrentBottomControlsShownRatio() const override;
|
float CurrentBottomControlsShownRatio() const override;
|
||||||
|
gfx::ScrollOffset ViewportScrollOffset() const override;
|
||||||
void DidChangeBrowserControlsPosition() override;
|
void DidChangeBrowserControlsPosition() override;
|
||||||
void DidObserveScrollDelay(base::TimeDelta scroll_delay,
|
void DidObserveScrollDelay(base::TimeDelta scroll_delay,
|
||||||
base::TimeTicks scroll_timestamp);
|
base::TimeTicks scroll_timestamp);
|
||||||
|
bool ShouldPinTopControlsToContentTop() const override;
|
||||||
bool HaveRootScrollNode() const override;
|
bool HaveRootScrollNode() const override;
|
||||||
void SetNeedsCommit() override;
|
void SetNeedsCommit() override;
|
||||||
|
|
||||||
|
@@ -644,6 +644,9 @@ class CC_EXPORT LayerTreeImpl {
|
|||||||
float bottom_controls_min_height() const {
|
float bottom_controls_min_height() const {
|
||||||
return browser_controls_params_.bottom_controls_min_height;
|
return browser_controls_params_.bottom_controls_min_height;
|
||||||
}
|
}
|
||||||
|
bool pin_top_controls_to_content_top() const {
|
||||||
|
return browser_controls_params_.pin_top_controls_to_content_top;
|
||||||
|
}
|
||||||
|
|
||||||
void set_overscroll_behavior(const OverscrollBehavior& behavior);
|
void set_overscroll_behavior(const OverscrollBehavior& behavior);
|
||||||
OverscrollBehavior overscroll_behavior() const {
|
OverscrollBehavior overscroll_behavior() const {
|
||||||
|
@@ -38,6 +38,10 @@ bool RenderViewHostDelegateView::DoBrowserControlsShrinkRendererSize() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RenderViewHostDelegateView::ShouldPinTopControlsToContentTop() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void RenderViewHostDelegateView::GestureEventAck(
|
void RenderViewHostDelegateView::GestureEventAck(
|
||||||
const blink::WebGestureEvent& event,
|
const blink::WebGestureEvent& event,
|
||||||
blink::mojom::InputEventResultState ack_result) {}
|
blink::mojom::InputEventResultState ack_result) {}
|
||||||
|
@@ -93,6 +93,10 @@ class CONTENT_EXPORT RenderViewHostDelegateView {
|
|||||||
// Returns true if the browser controls resize the renderer's view size.
|
// Returns true if the browser controls resize the renderer's view size.
|
||||||
virtual bool DoBrowserControlsShrinkRendererSize() const;
|
virtual bool DoBrowserControlsShrinkRendererSize() const;
|
||||||
|
|
||||||
|
// Returns true if the top controls should be pinned to the top of the page,
|
||||||
|
// so they'll only be visible if the page is scrolled to the top.
|
||||||
|
virtual bool ShouldPinTopControlsToContentTop() const;
|
||||||
|
|
||||||
// Do post-event tasks for gesture events.
|
// Do post-event tasks for gesture events.
|
||||||
virtual void GestureEventAck(const blink::WebGestureEvent& event,
|
virtual void GestureEventAck(const blink::WebGestureEvent& event,
|
||||||
blink::mojom::InputEventResultState ack_result);
|
blink::mojom::InputEventResultState ack_result);
|
||||||
|
@@ -871,6 +871,8 @@ blink::VisualProperties RenderWidgetHostImpl::GetVisualProperties() {
|
|||||||
visual_properties.browser_controls_params
|
visual_properties.browser_controls_params
|
||||||
.animate_browser_controls_height_changes =
|
.animate_browser_controls_height_changes =
|
||||||
rvh_delegate_view->ShouldAnimateBrowserControlsHeightChanges();
|
rvh_delegate_view->ShouldAnimateBrowserControlsHeightChanges();
|
||||||
|
visual_properties.browser_controls_params.pin_top_controls_to_content_top =
|
||||||
|
rvh_delegate_view->ShouldPinTopControlsToContentTop();
|
||||||
|
|
||||||
float top_controls_height = rvh_delegate_view->GetTopControlsHeight();
|
float top_controls_height = rvh_delegate_view->GetTopControlsHeight();
|
||||||
float top_controls_min_height = rvh_delegate_view->GetTopControlsMinHeight();
|
float top_controls_min_height = rvh_delegate_view->GetTopControlsMinHeight();
|
||||||
|
@@ -518,6 +518,11 @@ bool WebContentsViewAndroid::DoBrowserControlsShrinkRendererSize() const {
|
|||||||
delegate->DoBrowserControlsShrinkRendererSize(web_contents_);
|
delegate->DoBrowserControlsShrinkRendererSize(web_contents_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WebContentsViewAndroid::ShouldPinTopControlsToContentTop() const {
|
||||||
|
auto* delegate = web_contents_->GetDelegate();
|
||||||
|
return delegate && delegate->ShouldPinTopControlsToContentTop();
|
||||||
|
}
|
||||||
|
|
||||||
bool WebContentsViewAndroid::OnTouchEvent(const ui::MotionEventAndroid& event) {
|
bool WebContentsViewAndroid::OnTouchEvent(const ui::MotionEventAndroid& event) {
|
||||||
if (event.GetAction() == ui::MotionEventAndroid::Action::DOWN &&
|
if (event.GetAction() == ui::MotionEventAndroid::Action::DOWN &&
|
||||||
ShouldRequestUnbufferedDispatch()) {
|
ShouldRequestUnbufferedDispatch()) {
|
||||||
|
@@ -109,6 +109,7 @@ class WebContentsViewAndroid : public WebContentsView,
|
|||||||
int GetBottomControlsMinHeight() const override;
|
int GetBottomControlsMinHeight() const override;
|
||||||
bool ShouldAnimateBrowserControlsHeightChanges() const override;
|
bool ShouldAnimateBrowserControlsHeightChanges() const override;
|
||||||
bool DoBrowserControlsShrinkRendererSize() const override;
|
bool DoBrowserControlsShrinkRendererSize() const override;
|
||||||
|
bool ShouldPinTopControlsToContentTop() const override;
|
||||||
|
|
||||||
// ui::EventHandlerAndroid implementation.
|
// ui::EventHandlerAndroid implementation.
|
||||||
bool OnTouchEvent(const ui::MotionEventAndroid& event) override;
|
bool OnTouchEvent(const ui::MotionEventAndroid& event) override;
|
||||||
|
@@ -320,6 +320,10 @@ bool WebContentsDelegate::DoBrowserControlsShrinkRendererSize(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WebContentsDelegate::ShouldPinTopControlsToContentTop() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
PictureInPictureResult WebContentsDelegate::EnterPictureInPicture(
|
PictureInPictureResult WebContentsDelegate::EnterPictureInPicture(
|
||||||
WebContents* web_contents,
|
WebContents* web_contents,
|
||||||
const viz::SurfaceId&,
|
const viz::SurfaceId&,
|
||||||
|
@@ -643,6 +643,9 @@ class CONTENT_EXPORT WebContentsDelegate {
|
|||||||
virtual bool ShouldAnimateBrowserControlsHeightChanges();
|
virtual bool ShouldAnimateBrowserControlsHeightChanges();
|
||||||
virtual bool DoBrowserControlsShrinkRendererSize(
|
virtual bool DoBrowserControlsShrinkRendererSize(
|
||||||
const WebContents* web_contents);
|
const WebContents* web_contents);
|
||||||
|
// Returns true if the top controls should be pinned to the top of the page,
|
||||||
|
// so they'll only be visible if the page is scrolled to the top.
|
||||||
|
virtual bool ShouldPinTopControlsToContentTop();
|
||||||
|
|
||||||
// Propagates to the browser that gesture scrolling has changed state. This is
|
// Propagates to the browser that gesture scrolling has changed state. This is
|
||||||
// used by the browser to assist in controlling the behavior of sliding the
|
// used by the browser to assist in controlling the behavior of sliding the
|
||||||
|
@@ -278,6 +278,46 @@ public class BrowserControlsTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disabled on L bots due to unexplained flakes. See crbug.com/1035894.
|
||||||
|
@MinAndroidSdkLevel(Build.VERSION_CODES.M)
|
||||||
|
@Test
|
||||||
|
@SmallTest
|
||||||
|
public void testPinTopControlsToContentTop() throws Exception {
|
||||||
|
InstrumentationActivity activity = mActivityTestRule.getActivity();
|
||||||
|
View topContents = activity.getTopContentsContainer();
|
||||||
|
TestThreadUtils.runOnUiThreadBlocking(
|
||||||
|
() -> activity.getBrowser().setTopView(topContents, 0, /*pinToContentTop=*/true));
|
||||||
|
|
||||||
|
// Scroll down past the top-controls, which should collapse the top-controls and change the
|
||||||
|
// page height.
|
||||||
|
EventUtils.simulateDragFromCenterOfView(
|
||||||
|
activity.getWindow().getDecorView(), 0, -2 * mTopViewHeight);
|
||||||
|
CriteriaHelper.pollInstrumentationThread(() -> {
|
||||||
|
Criteria.checkThat(
|
||||||
|
getVisiblePageHeight(), Matchers.greaterThan(mPageHeightWithTopView));
|
||||||
|
Criteria.checkThat(activity.getTopContentsContainer().getVisibility(),
|
||||||
|
Matchers.is(View.INVISIBLE));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Scroll part of the way up again, which should not show the top controls.
|
||||||
|
int scrolledPageHeight = getVisiblePageHeight();
|
||||||
|
EventUtils.simulateDragFromCenterOfView(
|
||||||
|
activity.getWindow().getDecorView(), 0, mTopViewHeight);
|
||||||
|
CriteriaHelper.pollInstrumentationThread(() -> {
|
||||||
|
Criteria.checkThat(getVisiblePageHeight(), Matchers.is(scrolledPageHeight));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Scroll to the top to show the top controls.
|
||||||
|
EventUtils.simulateDragFromCenterOfView(
|
||||||
|
activity.getWindow().getDecorView(), 0, 2 * mTopViewHeight);
|
||||||
|
CriteriaHelper.pollInstrumentationThread(() -> {
|
||||||
|
Criteria.checkThat(getVisiblePageHeight(), Matchers.is(mPageHeightWithTopView));
|
||||||
|
Criteria.checkThat(
|
||||||
|
activity.getTopContentsContainer().getVisibility(), Matchers.is(View.VISIBLE));
|
||||||
|
Criteria.checkThat(topContents.getTranslationY(), Matchers.is(0.f));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes sure that the top controls are shown when a js dialog is shown.
|
* Makes sure that the top controls are shown when a js dialog is shown.
|
||||||
*
|
*
|
||||||
|
@@ -199,6 +199,7 @@ public class BrowserImpl extends IBrowser.Stub implements View.OnAttachStateChan
|
|||||||
|
|
||||||
getViewController().setTopView(ObjectWrapper.unwrap(viewWrapper, View.class));
|
getViewController().setTopView(ObjectWrapper.unwrap(viewWrapper, View.class));
|
||||||
getViewController().setTopControlsMinHeight(minHeight);
|
getViewController().setTopControlsMinHeight(minHeight);
|
||||||
|
getViewController().setPinTopControlsToContentTop(pinToContentTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -57,6 +57,7 @@ public final class BrowserViewController
|
|||||||
private final ModalDialogManager mModalDialogManager;
|
private final ModalDialogManager mModalDialogManager;
|
||||||
|
|
||||||
private int mTopControlsMinHeight;
|
private int mTopControlsMinHeight;
|
||||||
|
private boolean mPinToContentTop;
|
||||||
|
|
||||||
private TabImpl mTab;
|
private TabImpl mTab;
|
||||||
|
|
||||||
@@ -210,6 +211,11 @@ public final class BrowserViewController
|
|||||||
updateActiveTabScrollBehavior();
|
updateActiveTabScrollBehavior();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPinTopControlsToContentTop(boolean pinToContentTop) {
|
||||||
|
mPinToContentTop = pinToContentTop;
|
||||||
|
updateActiveTabScrollBehavior();
|
||||||
|
}
|
||||||
|
|
||||||
public void setBottomView(View view) {
|
public void setBottomView(View view) {
|
||||||
mBottomControlsContainerView.setView(view);
|
mBottomControlsContainerView.setView(view);
|
||||||
}
|
}
|
||||||
@@ -303,6 +309,7 @@ public final class BrowserViewController
|
|||||||
private void updateActiveTabScrollBehavior() {
|
private void updateActiveTabScrollBehavior() {
|
||||||
if (mTab != null) {
|
if (mTab != null) {
|
||||||
mTab.setTopControlsMinHeight(mTopControlsMinHeight);
|
mTab.setTopControlsMinHeight(mTopControlsMinHeight);
|
||||||
|
mTab.setPinTopControlsToContentTop(mPinToContentTop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -871,6 +871,10 @@ public final class TabImpl extends ITab.Stub implements LoginPrompt.Observer {
|
|||||||
TabImplJni.get().setTopControlsMinHeight(mNativeTab, minHeight);
|
TabImplJni.get().setTopControlsMinHeight(mNativeTab, minHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* package */ void setPinTopControlsToContentTop(boolean pinToContentTop) {
|
||||||
|
TabImplJni.get().setPinTopControlsToContentTop(mNativeTab, pinToContentTop);
|
||||||
|
}
|
||||||
|
|
||||||
@CalledByNative
|
@CalledByNative
|
||||||
private boolean doBrowserControlsShrinkRendererSize() {
|
private boolean doBrowserControlsShrinkRendererSize() {
|
||||||
BrowserViewController viewController = getViewController();
|
BrowserViewController viewController = getViewController();
|
||||||
@@ -993,5 +997,6 @@ public final class TabImpl extends ITab.Stub implements LoginPrompt.Observer {
|
|||||||
boolean canTranslate(long nativeTabImpl);
|
boolean canTranslate(long nativeTabImpl);
|
||||||
void showTranslateUi(long nativeTabImpl);
|
void showTranslateUi(long nativeTabImpl);
|
||||||
void setTopControlsMinHeight(long nativeTabImpl, int minHeight);
|
void setTopControlsMinHeight(long nativeTabImpl, int minHeight);
|
||||||
|
void setPinTopControlsToContentTop(long nativeTabImpl, boolean pinToContentTop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -780,6 +780,12 @@ void TabImpl::ShowTranslateUi(JNIEnv* env) {
|
|||||||
void TabImpl::SetTopControlsMinHeight(JNIEnv* env, int min_height) {
|
void TabImpl::SetTopControlsMinHeight(JNIEnv* env, int min_height) {
|
||||||
top_controls_min_height_ = min_height;
|
top_controls_min_height_ = min_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabImpl::SetPinTopControlsToContentTop(
|
||||||
|
JNIEnv* env,
|
||||||
|
jboolean pin_top_controls_to_content_top) {
|
||||||
|
pin_top_controls_to_content_top_ = pin_top_controls_to_content_top;
|
||||||
|
}
|
||||||
#endif // OS_ANDROID
|
#endif // OS_ANDROID
|
||||||
|
|
||||||
content::WebContents* TabImpl::OpenURLFromTab(
|
content::WebContents* TabImpl::OpenURLFromTab(
|
||||||
@@ -920,6 +926,14 @@ bool TabImpl::DoBrowserControlsShrinkRendererSize(
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TabImpl::ShouldPinTopControlsToContentTop() {
|
||||||
|
#if defined(OS_ANDROID)
|
||||||
|
return pin_top_controls_to_content_top_;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool TabImpl::EmbedsFullscreenWidget() {
|
bool TabImpl::EmbedsFullscreenWidget() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -194,6 +194,8 @@ class TabImpl : public Tab,
|
|||||||
jboolean CanTranslate(JNIEnv* env);
|
jboolean CanTranslate(JNIEnv* env);
|
||||||
void ShowTranslateUi(JNIEnv* env);
|
void ShowTranslateUi(JNIEnv* env);
|
||||||
void SetTopControlsMinHeight(JNIEnv* env, int min_height);
|
void SetTopControlsMinHeight(JNIEnv* env, int min_height);
|
||||||
|
void SetPinTopControlsToContentTop(JNIEnv* env,
|
||||||
|
jboolean pin_top_controls_to_content_top);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ErrorPageDelegate* error_page_delegate() { return error_page_delegate_; }
|
ErrorPageDelegate* error_page_delegate() { return error_page_delegate_; }
|
||||||
@@ -262,6 +264,7 @@ class TabImpl : public Tab,
|
|||||||
int GetBottomControlsHeight() override;
|
int GetBottomControlsHeight() override;
|
||||||
bool DoBrowserControlsShrinkRendererSize(
|
bool DoBrowserControlsShrinkRendererSize(
|
||||||
const content::WebContents* web_contents) override;
|
const content::WebContents* web_contents) override;
|
||||||
|
bool ShouldPinTopControlsToContentTop() override;
|
||||||
bool EmbedsFullscreenWidget() override;
|
bool EmbedsFullscreenWidget() override;
|
||||||
void RequestMediaAccessPermission(
|
void RequestMediaAccessPermission(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
@@ -367,6 +370,7 @@ class TabImpl : public Tab,
|
|||||||
std::unique_ptr<BrowserControlsNavigationStateHandler>
|
std::unique_ptr<BrowserControlsNavigationStateHandler>
|
||||||
browser_controls_navigation_state_handler_;
|
browser_controls_navigation_state_handler_;
|
||||||
int top_controls_min_height_ = 0;
|
int top_controls_min_height_ = 0;
|
||||||
|
bool pin_top_controls_to_content_top_ = false;
|
||||||
|
|
||||||
// Last value supplied to UpdateBrowserControlsConstraint(). This *constraint*
|
// Last value supplied to UpdateBrowserControlsConstraint(). This *constraint*
|
||||||
// can be SHOWN, if for example a modal dialog is forcing the controls to be
|
// can be SHOWN, if for example a modal dialog is forcing the controls to be
|
||||||
|
@@ -15,9 +15,16 @@
|
|||||||
<item android:id="@+id/toggle_bottom_view_id"
|
<item android:id="@+id/toggle_bottom_view_id"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
android:title="Bottom view" />
|
android:title="Bottom view" />
|
||||||
<item android:id="@+id/toggle_top_view_min_height_id"
|
<item android:title="Scrolling">
|
||||||
android:checkable="true"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
android:title="Set top view min height" />
|
<item android:id="@+id/toggle_top_view_min_height_id"
|
||||||
|
android:checkable="true"
|
||||||
|
android:title="Set top view min height" />
|
||||||
|
<item android:id="@+id/toggle_top_view_pinned_to_top_id"
|
||||||
|
android:checkable="true"
|
||||||
|
android:title="Pin top view to content top" />
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
<item android:id="@+id/site_settings_menu_id"
|
<item android:id="@+id/site_settings_menu_id"
|
||||||
android:title="Site Settings" />
|
android:title="Site Settings" />
|
||||||
<item android:id="@+id/translate_menu_id"
|
<item android:id="@+id/translate_menu_id"
|
||||||
|
@@ -140,6 +140,7 @@ public class WebLayerShellActivity extends FragmentActivity {
|
|||||||
private Runnable mExitFullscreenRunnable;
|
private Runnable mExitFullscreenRunnable;
|
||||||
private View mBottomView;
|
private View mBottomView;
|
||||||
private int mTopViewMinHeight;
|
private int mTopViewMinHeight;
|
||||||
|
private boolean mTopViewPinnedToContentTop;
|
||||||
private boolean mInIncognitoMode;
|
private boolean mInIncognitoMode;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -181,8 +182,12 @@ public class WebLayerShellActivity extends FragmentActivity {
|
|||||||
popup.getMenuInflater().inflate(R.menu.app_menu, popup.getMenu());
|
popup.getMenuInflater().inflate(R.menu.app_menu, popup.getMenu());
|
||||||
MenuItem bottomMenuItem = popup.getMenu().findItem(R.id.toggle_bottom_view_id);
|
MenuItem bottomMenuItem = popup.getMenu().findItem(R.id.toggle_bottom_view_id);
|
||||||
bottomMenuItem.setChecked(mBottomView != null);
|
bottomMenuItem.setChecked(mBottomView != null);
|
||||||
MenuItem topMenuItem = popup.getMenu().findItem(R.id.toggle_top_view_min_height_id);
|
popup.getMenu()
|
||||||
topMenuItem.setChecked(mTopViewMinHeight > 0);
|
.findItem(R.id.toggle_top_view_min_height_id)
|
||||||
|
.setChecked(mTopViewMinHeight > 0);
|
||||||
|
popup.getMenu()
|
||||||
|
.findItem(R.id.toggle_top_view_pinned_to_top_id)
|
||||||
|
.setChecked(mTopViewPinnedToContentTop);
|
||||||
popup.getMenu()
|
popup.getMenu()
|
||||||
.findItem(R.id.translate_menu_id)
|
.findItem(R.id.translate_menu_id)
|
||||||
.setVisible(mBrowser.getActiveTab().canTranslate());
|
.setVisible(mBrowser.getActiveTab().canTranslate());
|
||||||
@@ -219,7 +224,15 @@ public class WebLayerShellActivity extends FragmentActivity {
|
|||||||
|
|
||||||
if (item.getItemId() == R.id.toggle_top_view_min_height_id) {
|
if (item.getItemId() == R.id.toggle_top_view_min_height_id) {
|
||||||
mTopViewMinHeight = (mTopViewMinHeight == 0) ? 50 : 0;
|
mTopViewMinHeight = (mTopViewMinHeight == 0) ? 50 : 0;
|
||||||
mBrowser.setTopView(mTopContentsContainer, mTopViewMinHeight, false);
|
mBrowser.setTopView(
|
||||||
|
mTopContentsContainer, mTopViewMinHeight, mTopViewPinnedToContentTop);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.getItemId() == R.id.toggle_top_view_pinned_to_top_id) {
|
||||||
|
mTopViewPinnedToContentTop = !mTopViewPinnedToContentTop;
|
||||||
|
mBrowser.setTopView(
|
||||||
|
mTopContentsContainer, mTopViewMinHeight, mTopViewPinnedToContentTop);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +307,7 @@ public class WebLayerShellActivity extends FragmentActivity {
|
|||||||
mProfile.setBooleanSetting(SettingType.UKM_ENABLED, true);
|
mProfile.setBooleanSetting(SettingType.UKM_ENABLED, true);
|
||||||
setTabCallbacks(mBrowser.getActiveTab(), fragment);
|
setTabCallbacks(mBrowser.getActiveTab(), fragment);
|
||||||
|
|
||||||
mBrowser.setTopView(mTopContentsContainer);
|
mBrowser.setTopView(mTopContentsContainer, /*minHeight=*/0, /*pinToContentTop=*/false);
|
||||||
mTabListCallback = new TabListCallback() {
|
mTabListCallback = new TabListCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onActiveTabChanged(Tab activeTab) {
|
public void onActiveTabChanged(Tab activeTab) {
|
||||||
|
Reference in New Issue
Block a user