Commit 85d78e60 authored by Ankit Kumar's avatar Ankit Kumar Committed by Commit Bot

Maintain viewport when focus is restored in PDF

This CL ensures that when focus is restored to PDF, we maintain the
viewport and do not scroll even if the focused annotation is out of
viewport.

Bug: 1085614
Change-Id: Ifc4015b6d393dd1678d839a6636fbd4b335528ef
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2224946Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarKevin Babbitt <kbabbitt@microsoft.com>
Commit-Queue: Ankit Kumar 🌪️ <ankk@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#775202}
parent c4b44be1
...@@ -947,6 +947,7 @@ void PDFiumEngine::KillFormFocus() { ...@@ -947,6 +947,7 @@ void PDFiumEngine::KillFormFocus() {
} }
void PDFiumEngine::UpdateFocus(bool has_focus) { void PDFiumEngine::UpdateFocus(bool has_focus) {
base::AutoReset<bool> updating_focus_guard(&updating_focus_, true);
if (has_focus) { if (has_focus) {
UpdateFocusItemType(last_focused_item_type_); UpdateFocusItemType(last_focused_item_type_);
if (focus_item_type_ == FocusElementType::kPage && if (focus_item_type_ == FocusElementType::kPage &&
......
...@@ -724,6 +724,9 @@ class PDFiumEngine : public PDFEngine, ...@@ -724,6 +724,9 @@ class PDFiumEngine : public PDFEngine,
// Set to true when handling long touch press. // Set to true when handling long touch press.
bool handling_long_press_ = false; bool handling_long_press_ = false;
// Set to true when updating plugin focus.
bool updating_focus_ = false;
// The focus item type for the currently focused object. // The focus item type for the currently focused object.
FocusElementType focus_item_type_ = FocusElementType::kNone; FocusElementType focus_item_type_ = FocusElementType::kNone;
......
...@@ -24,9 +24,11 @@ namespace chrome_pdf { ...@@ -24,9 +24,11 @@ namespace chrome_pdf {
namespace { namespace {
using ::testing::InSequence; using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::IsEmpty; using ::testing::IsEmpty;
using ::testing::NiceMock; using ::testing::NiceMock;
using ::testing::Return; using ::testing::Return;
using ::testing::StrictMock;
MATCHER_P2(LayoutWithSize, width, height, "") { MATCHER_P2(LayoutWithSize, width, height, "") {
return arg.size() == pp::Size(width, height); return arg.size() == pp::Size(width, height);
...@@ -801,4 +803,69 @@ TEST_F(PDFiumEngineTabbingTest, RetainSelectionOnFocusNotInFormTextArea) { ...@@ -801,4 +803,69 @@ TEST_F(PDFiumEngineTabbingTest, RetainSelectionOnFocusNotInFormTextArea) {
EXPECT_EQ(1u, GetSelectionSize(engine.get())); EXPECT_EQ(1u, GetSelectionSize(engine.get()));
} }
class ScrollingTestClient : public TestClient {
public:
ScrollingTestClient() = default;
~ScrollingTestClient() override = default;
ScrollingTestClient(const ScrollingTestClient&) = delete;
ScrollingTestClient& operator=(const ScrollingTestClient&) = delete;
// Mock PDFEngine::Client methods.
MOCK_METHOD1(ScrollToX, void(int));
MOCK_METHOD2(ScrollToY, void(int, bool));
};
TEST_F(PDFiumEngineTabbingTest, MaintainViewportWhenFocusIsUpdated) {
StrictMock<ScrollingTestClient> client;
std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
&client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
ASSERT_TRUE(engine);
ASSERT_EQ(2, engine->GetNumberOfPages());
engine->PluginSizeUpdated(pp::Size(60, 40));
{
InSequence sequence;
static constexpr PP_Point kScrollValue = {510, 478};
EXPECT_CALL(client, ScrollToY(kScrollValue.y, false))
.WillOnce(Invoke(
[&engine]() { engine->ScrolledToYPosition(kScrollValue.y); }));
EXPECT_CALL(client, ScrollToX(kScrollValue.x)).WillOnce(Invoke([&engine]() {
engine->ScrolledToXPosition(kScrollValue.x);
}));
}
EXPECT_EQ(PDFiumEngine::FocusElementType::kNone,
GetFocusedElementType(engine.get()));
EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
// Tabbing to bring the document into focus.
ASSERT_TRUE(HandleTabEvent(engine.get(), 0));
EXPECT_EQ(PDFiumEngine::FocusElementType::kDocument,
GetFocusedElementType(engine.get()));
// Tab to an annotation.
ASSERT_TRUE(HandleTabEvent(engine.get(), 0));
EXPECT_EQ(PDFiumEngine::FocusElementType::kPage,
GetFocusedElementType(engine.get()));
// Scroll focused annotation out of viewport.
static constexpr PP_Point kScrollPosition = {242, 746};
engine->ScrolledToXPosition(kScrollPosition.x);
engine->ScrolledToYPosition(kScrollPosition.y);
engine->UpdateFocus(/*has_focus=*/false);
EXPECT_EQ(PDFiumEngine::FocusElementType::kPage,
GetLastFocusedElementType(engine.get()));
EXPECT_EQ(0, GetLastFocusedPage(engine.get()));
EXPECT_EQ(PDFiumEngine::FocusElementType::kPage,
GetFocusedElementType(engine.get()));
EXPECT_EQ(1, GetLastFocusedAnnotationIndex(engine.get()));
// Restore focus, we shouldn't have any calls to scroll viewport.
engine->UpdateFocus(/*has_focus=*/true);
EXPECT_EQ(PDFiumEngine::FocusElementType::kPage,
GetFocusedElementType(engine.get()));
EXPECT_EQ(0, GetLastFocusedPage(engine.get()));
}
} // namespace chrome_pdf } // namespace chrome_pdf
...@@ -283,16 +283,19 @@ void PDFiumFormFiller::Form_OnFocusChange(FPDF_FORMFILLINFO* param, ...@@ -283,16 +283,19 @@ void PDFiumFormFiller::Form_OnFocusChange(FPDF_FORMFILLINFO* param,
if (!engine->PageIndexInBounds(page_index)) if (!engine->PageIndexInBounds(page_index))
return; return;
FS_RECTF annot_rect; // Maintain viewport if we are updating focus. This is to ensure that we don't
if (!FPDFAnnot_GetRect(annot, &annot_rect)) // scroll the focused annotation into view when focus is regained.
return; if (!engine->updating_focus_) {
FS_RECTF annot_rect;
pp::Rect screen_rect = engine->pages_[page_index]->PageToScreen( if (!FPDFAnnot_GetRect(annot, &annot_rect))
pp::Point(), /*zoom=*/1.0, annot_rect.left, annot_rect.top, return;
annot_rect.right, annot_rect.bottom,
engine->layout_.options().default_page_orientation()); pp::Rect screen_rect = engine->pages_[page_index]->PageToScreen(
pp::Point(), /*zoom=*/1.0, annot_rect.left, annot_rect.top,
engine->ScrollIntoView(screen_rect); annot_rect.right, annot_rect.bottom,
engine->layout_.options().default_page_orientation());
engine->ScrollIntoView(screen_rect);
}
engine->OnFocusedAnnotationUpdated(annot, page_index); engine->OnFocusedAnnotationUpdated(annot, page_index);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment