Update form field states in PDFiumEngine
This CL updates the form field states in PDFiumEngine. This is done via setting |PDFiumEngine::in_form_text_area_| and |PDFiumEngine::editable_form_text_area_| as per the focused annotation. Unit tests have been added to validate the scenario. Bug: 989040 Change-Id: I27e163819f5ca5f88e6ce10df48f2e7c7a6e97dc Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2086466 Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Kevin Babbitt <kbabbitt@microsoft.com> Commit-Queue: Ankit Kumar 🌪️ <ankk@microsoft.com> Cr-Commit-Position: refs/heads/master@{#765557}
This commit is contained in:
@ -1114,19 +1114,9 @@ bool PDFiumEngine::OnLeftMouseDown(const pp::MouseInputEvent& event) {
|
||||
double page_y;
|
||||
DeviceToPage(page_index, point, &page_x, &page_y);
|
||||
|
||||
bool is_form_text_area = IsFormTextArea(area, form_type);
|
||||
FPDF_PAGE page = pages_[page_index]->GetPage();
|
||||
bool is_editable_form_text_area =
|
||||
is_form_text_area &&
|
||||
IsPointInEditableFormTextArea(page, page_x, page_y, form_type);
|
||||
|
||||
if (event.GetClickCount() == 1) {
|
||||
FORM_OnLButtonDown(form(), page, event.GetModifiers(), page_x, page_y);
|
||||
} else if (event.GetClickCount() == 2) {
|
||||
FORM_OnLButtonDoubleClick(form(), page, event.GetModifiers(), page_x,
|
||||
page_y);
|
||||
}
|
||||
if (form_type != FPDF_FORMFIELD_UNKNOWN) {
|
||||
// FORM_OnLButton*() will trigger a callback to
|
||||
// OnFocusedAnnotationUpdated() which will call SetInFormTextArea().
|
||||
// Destroy SelectionChangeInvalidator object before SetInFormTextArea()
|
||||
// changes plugin's focus to be in form text area. This way, regular text
|
||||
// selection can be cleared when a user clicks into a form text area
|
||||
@ -1134,11 +1124,18 @@ bool PDFiumEngine::OnLeftMouseDown(const pp::MouseInputEvent& event) {
|
||||
// ~SelectionChangeInvalidator() still goes to the Mimehandler
|
||||
// (not the Renderer).
|
||||
selection_invalidator.reset();
|
||||
|
||||
SetInFormTextArea(is_form_text_area);
|
||||
editable_form_text_area_ = is_editable_form_text_area;
|
||||
return true; // Return now before we get into the selection code.
|
||||
}
|
||||
|
||||
FPDF_PAGE page = pages_[page_index]->GetPage();
|
||||
|
||||
if (event.GetClickCount() == 1) {
|
||||
FORM_OnLButtonDown(form(), page, event.GetModifiers(), page_x, page_y);
|
||||
} else if (event.GetClickCount() == 2) {
|
||||
FORM_OnLButtonDoubleClick(form(), page, event.GetModifiers(), page_x,
|
||||
page_y);
|
||||
}
|
||||
if (form_type != FPDF_FORMFIELD_UNKNOWN)
|
||||
return true; // Return now before we get into the selection code.
|
||||
}
|
||||
SetInFormTextArea(false);
|
||||
|
||||
@ -1197,7 +1194,6 @@ bool PDFiumEngine::OnRightMouseDown(const pp::MouseInputEvent& event) {
|
||||
DCHECK_GE(form_type, FPDF_FORMFIELD_UNKNOWN);
|
||||
|
||||
bool is_form_text_area = IsFormTextArea(area, form_type);
|
||||
bool is_editable_form_text_area = false;
|
||||
|
||||
double page_x = -1;
|
||||
double page_y = -1;
|
||||
@ -1207,8 +1203,6 @@ bool PDFiumEngine::OnRightMouseDown(const pp::MouseInputEvent& event) {
|
||||
|
||||
DeviceToPage(page_index, point, &page_x, &page_y);
|
||||
page = pages_[page_index]->GetPage();
|
||||
is_editable_form_text_area =
|
||||
IsPointInEditableFormTextArea(page, page_x, page_y, form_type);
|
||||
}
|
||||
|
||||
// Handle the case when focus starts inside a form text area.
|
||||
@ -1231,8 +1225,6 @@ bool PDFiumEngine::OnRightMouseDown(const pp::MouseInputEvent& event) {
|
||||
selection_.clear();
|
||||
}
|
||||
|
||||
SetInFormTextArea(true);
|
||||
editable_form_text_area_ = is_editable_form_text_area;
|
||||
FORM_OnFocus(form(), page, 0, page_x, page_y);
|
||||
return true;
|
||||
}
|
||||
@ -3593,23 +3585,19 @@ void PDFiumEngine::SetMouseLeftButtonDown(bool is_mouse_left_button_down) {
|
||||
mouse_left_button_down_ = is_mouse_left_button_down;
|
||||
}
|
||||
|
||||
bool PDFiumEngine::IsPointInEditableFormTextArea(FPDF_PAGE page,
|
||||
double page_x,
|
||||
double page_y,
|
||||
int form_type) {
|
||||
bool PDFiumEngine::IsAnnotationAnEditableFormTextArea(FPDF_ANNOTATION annot,
|
||||
int form_type) const {
|
||||
#if defined(PDF_ENABLE_XFA)
|
||||
if (IS_XFA_FORMFIELD(form_type))
|
||||
if (IS_XFA_FORMFIELD(form_type)) {
|
||||
return form_type == FPDF_FORMFIELD_XFA_TEXTFIELD ||
|
||||
form_type == FPDF_FORMFIELD_XFA_COMBOBOX;
|
||||
}
|
||||
#endif // defined(PDF_ENABLE_XFA)
|
||||
|
||||
const FS_POINTF point = {page_x, page_y};
|
||||
ScopedFPDFAnnotation annot(
|
||||
FPDFAnnot_GetFormFieldAtPoint(form(), page, &point));
|
||||
if (!annot)
|
||||
return false;
|
||||
|
||||
int flags = FPDFAnnot_GetFormFieldFlags(form(), annot.get());
|
||||
int flags = FPDFAnnot_GetFormFieldFlags(form(), annot);
|
||||
return CheckIfEditableFormTextArea(flags, form_type);
|
||||
}
|
||||
|
||||
@ -3696,6 +3684,19 @@ void PDFiumEngine::ScrollIntoView(const pp::Rect& rect) {
|
||||
}
|
||||
}
|
||||
|
||||
void PDFiumEngine::OnFocusedAnnotationUpdated(FPDF_ANNOTATION annot) {
|
||||
int form_type = FPDFAnnot_GetFormFieldType(form(), annot);
|
||||
if (form_type <= FPDF_FORMFIELD_UNKNOWN) {
|
||||
SetInFormTextArea(false);
|
||||
return;
|
||||
}
|
||||
bool is_form_text_area =
|
||||
PDFiumPage::FormTypeToArea(form_type) == PDFiumPage::FORM_TEXT_AREA;
|
||||
SetInFormTextArea(is_form_text_area);
|
||||
editable_form_text_area_ =
|
||||
is_form_text_area && IsAnnotationAnEditableFormTextArea(annot, form_type);
|
||||
}
|
||||
|
||||
void PDFiumEngine::SetCaretPosition(const pp::Point& position) {
|
||||
// TODO(dsinclair): Handle caret position ...
|
||||
}
|
||||
|
@ -524,12 +524,10 @@ class PDFiumEngine : public PDFEngine,
|
||||
// Sets whether or not left mouse button is currently being held down.
|
||||
void SetMouseLeftButtonDown(bool is_mouse_left_button_down);
|
||||
|
||||
// Given coordinates on |page| has a form of |form_type| which is known to be
|
||||
// a form text area, check if it is an editable form text area.
|
||||
bool IsPointInEditableFormTextArea(FPDF_PAGE page,
|
||||
double page_x,
|
||||
double page_y,
|
||||
int form_type);
|
||||
// Given an annotation which is a form of |form_type| which is known to be a
|
||||
// form text area, check if it is an editable form text area.
|
||||
bool IsAnnotationAnEditableFormTextArea(FPDF_ANNOTATION annot,
|
||||
int form_type) const;
|
||||
|
||||
bool PageIndexInBounds(int index) const;
|
||||
bool IsPageCharacterIndexInBounds(
|
||||
@ -581,6 +579,8 @@ class PDFiumEngine : public PDFEngine,
|
||||
// already in view.
|
||||
void ScrollIntoView(const pp::Rect& rect);
|
||||
|
||||
void OnFocusedAnnotationUpdated(FPDF_ANNOTATION annot);
|
||||
|
||||
// Fetches and populates the fields of |doc_metadata_|. To be called after the
|
||||
// document is loaded.
|
||||
void LoadDocumentMetadata();
|
||||
|
@ -255,6 +255,10 @@ class PDFiumEngineTabbingTest : public PDFiumTestBase {
|
||||
return engine->last_focused_annot_index_;
|
||||
}
|
||||
|
||||
bool IsInFormTextArea(PDFiumEngine* engine) {
|
||||
return engine->in_form_text_area_;
|
||||
}
|
||||
|
||||
protected:
|
||||
base::test::TaskEnvironment task_environment_{
|
||||
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
|
||||
@ -574,4 +578,39 @@ TEST_F(PDFiumEngineTabbingTest, RestoringAnnotFocusTest) {
|
||||
EXPECT_EQ(1, GetLastFocusedPage(engine.get()));
|
||||
}
|
||||
|
||||
TEST_F(PDFiumEngineTabbingTest, VerifyFormFieldStatesOnTabbing) {
|
||||
/*
|
||||
* Document structure
|
||||
* Document
|
||||
* ++ Page 1
|
||||
* ++++ Annotation (Text Field)
|
||||
* ++++ Annotation (Radio Button)
|
||||
*/
|
||||
TestClient client;
|
||||
std::unique_ptr<PDFiumEngine> engine =
|
||||
InitializeEngine(&client, FILE_PATH_LITERAL("annots.pdf"));
|
||||
ASSERT_TRUE(engine);
|
||||
ASSERT_EQ(1, engine->GetNumberOfPages());
|
||||
|
||||
ASSERT_TRUE(HandleTabEvent(engine.get(), 0));
|
||||
EXPECT_EQ(PDFiumEngine::FocusElementType::kDocument,
|
||||
GetFocusedElementType(engine.get()));
|
||||
|
||||
// Bring focus to the text field.
|
||||
ASSERT_TRUE(HandleTabEvent(engine.get(), 0));
|
||||
EXPECT_EQ(PDFiumEngine::FocusElementType::kPage,
|
||||
GetFocusedElementType(engine.get()));
|
||||
EXPECT_EQ(0, GetLastFocusedPage(engine.get()));
|
||||
EXPECT_TRUE(IsInFormTextArea(engine.get()));
|
||||
EXPECT_TRUE(engine->CanEditText());
|
||||
|
||||
// Bring focus to the button.
|
||||
ASSERT_TRUE(HandleTabEvent(engine.get(), 0));
|
||||
EXPECT_EQ(PDFiumEngine::FocusElementType::kPage,
|
||||
GetFocusedElementType(engine.get()));
|
||||
EXPECT_EQ(0, GetLastFocusedPage(engine.get()));
|
||||
EXPECT_FALSE(IsInFormTextArea(engine.get()));
|
||||
EXPECT_FALSE(engine->CanEditText());
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
@ -293,6 +293,8 @@ void PDFiumFormFiller::Form_OnFocusChange(FPDF_FORMFILLINFO* param,
|
||||
engine->layout_.options().default_page_orientation());
|
||||
|
||||
engine->ScrollIntoView(screen_rect);
|
||||
|
||||
engine->OnFocusedAnnotationUpdated(annot);
|
||||
}
|
||||
|
||||
// static
|
||||
|
Reference in New Issue
Block a user