Add tests for listbox form scrolling
Currently, listbox forms do not scroll to the top selected option when
the form is out of focus. A test is added with the current incorrect
functionality, and will be changed in CL [1].
Another test is added to make sure the listbox does not overscroll when
the top index ("TI") is specified to the last element.
[1] https://pdfium-review.googlesource.com/c/pdfium/+/59190
Bug: pdfium:1377
Change-Id: I67b8bb434d2b8cdcd9a66eca44220a4ad9f86d2b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/59890
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdf_formfill_embeddertest.cpp b/fpdfsdk/fpdf_formfill_embeddertest.cpp
index bfcbe8c..33353aa 100644
--- a/fpdfsdk/fpdf_formfill_embeddertest.cpp
+++ b/fpdfsdk/fpdf_formfill_embeddertest.cpp
@@ -368,6 +368,10 @@
// - "Listbox_SingleSelect" - Ff: 0, 3 options with pair values.
// - "Listbox_MultiSelect" - Ff: 2097152, 26 options with single values.
// - "Listbox_ReadOnly" - Ff: 1, 3 options with single values.
+ // - "Listbox_MultiSelectMultipleSelected" - Ff: 2097152, 5 options with
+ // single values.
+ // - "Listbox_SingleSelectLastSelected" - Ff: 0, 10 options with single
+ // values.
return "listbox_form.pdf";
}
@@ -382,6 +386,17 @@
GetFormTypeAtPoint(MultiSelectFirstVisibleOption()));
EXPECT_EQ(GetFormType(),
GetFormTypeAtPoint(MultiSelectSecondVisibleOption()));
+ EXPECT_EQ(
+ GetFormType(),
+ GetFormTypeAtPoint(MultiSelectMultipleSelectedFirstVisibleOption()));
+ EXPECT_EQ(
+ GetFormType(),
+ GetFormTypeAtPoint(MultiSelectMultipleSelectedSecondVisibleOption()));
+ EXPECT_EQ(GetFormType(),
+ GetFormTypeAtPoint(SingleSelectLastSelectedFirstVisibleOption()));
+ EXPECT_EQ(
+ GetFormType(),
+ GetFormTypeAtPoint(SingleSelectLastSelectedSecondVisibleOption()));
}
void ClickOnSingleSelectFormOption(int item_index) {
@@ -408,6 +423,30 @@
}
}
+ void ClickOnMultiSelectMultipleSelectedFormOption(int item_index) {
+ // Only two indices are visible so can only click on those
+ // without scrolling.
+ ASSERT(item_index >= 0);
+ ASSERT(item_index < 2);
+ if (item_index == 0) {
+ ClickOnFormFieldAtPoint(MultiSelectMultipleSelectedFirstVisibleOption());
+ } else {
+ ClickOnFormFieldAtPoint(MultiSelectMultipleSelectedSecondVisibleOption());
+ }
+ }
+
+ void ClickOnSingleSelectLastSelectedFormOption(int item_index) {
+ // Only two indices are visible so can only click on those
+ // without scrolling.
+ ASSERT(item_index >= 0);
+ ASSERT(item_index < 2);
+ if (item_index == 0) {
+ ClickOnFormFieldAtPoint(SingleSelectLastSelectedFirstVisibleOption());
+ } else {
+ ClickOnFormFieldAtPoint(SingleSelectLastSelectedSecondVisibleOption());
+ }
+ }
+
void FocusOnSingleSelectForm() {
FocusOnPoint(SingleSelectFirstVisibleOption());
}
@@ -416,6 +455,14 @@
FocusOnPoint(MultiSelectFirstVisibleOption());
}
+ void FocusOnMultiSelectMultipleSelectedForm() {
+ FocusOnPoint(MultiSelectMultipleSelectedFirstVisibleOption());
+ }
+
+ void FocusOnSingleSelectLastSelectedForm() {
+ FocusOnPoint(SingleSelectLastSelectedFirstVisibleOption());
+ }
+
void FocusOnPoint(const CFX_PointF& point) {
EXPECT_EQ(true, FORM_OnFocus(form_handle(), page(), 0, point.x, point.y));
}
@@ -440,12 +487,40 @@
return point;
}
+ const CFX_PointF& MultiSelectMultipleSelectedFirstVisibleOption() const {
+ static const CFX_PointF point(
+ kFormBeginX, kMultiFormMultipleSelectedYFirstVisibleOption);
+ return point;
+ }
+
+ const CFX_PointF& MultiSelectMultipleSelectedSecondVisibleOption() const {
+ static const CFX_PointF point(
+ kFormBeginX, kMultiFormMultipleSelectedYSecondVisibleOption);
+ return point;
+ }
+
+ const CFX_PointF& SingleSelectLastSelectedFirstVisibleOption() const {
+ static const CFX_PointF point(kFormBeginX,
+ kSingleFormLastSelectedYFirstVisibleOption);
+ return point;
+ }
+
+ const CFX_PointF& SingleSelectLastSelectedSecondVisibleOption() const {
+ static const CFX_PointF point(kFormBeginX,
+ kSingleFormLastSelectedYSecondVisibleOption);
+ return point;
+ }
+
private:
static constexpr float kFormBeginX = 102.0;
static constexpr float kSingleFormYFirstVisibleOption = 371.0;
static constexpr float kSingleFormYSecondVisibleOption = 358.0;
static constexpr float kMultiFormYFirstVisibleOption = 423.0;
static constexpr float kMultiFormYSecondVisibleOption = 408.0;
+ static constexpr float kMultiFormMultipleSelectedYFirstVisibleOption = 223.0;
+ static constexpr float kMultiFormMultipleSelectedYSecondVisibleOption = 208.0;
+ static constexpr float kSingleFormLastSelectedYFirstVisibleOption = 123.0;
+ static constexpr float kSingleFormLastSelectedYSecondVisibleOption = 108.0;
};
TEST_F(FPDFFormFillEmbedderTest, FirstTest) {
@@ -2126,9 +2201,13 @@
CheckIsIndexSelected(i, expected);
}
- ClickOnMultiSelectFormOption(0);
+ // TODO(bug_1377): Behavior should be changed to the one described below.
+ // Multiselect field set to 'Cherry' (index 2), which is index 1 among the
+ // visible form options because the listbox is scrolled down to have 'Banana'
+ // (index 1) at the top.
+ ClickOnMultiSelectFormOption(1);
for (int i = 0; i < 26; i++) {
- bool expected = i == 0;
+ bool expected = i == 1;
CheckIsIndexSelected(i, expected);
}
}
@@ -2263,6 +2342,7 @@
// Check that above actions are interchangeable with click actions, should be
// able to use a combination of both.
+ // TODO(bug_1377): Change to click on form option 0 instead of form option 1
ClickOnMultiSelectFormOption(1);
for (int i = 0; i < 26; i++) {
bool expected = i == 1;
@@ -2271,6 +2351,51 @@
CheckFocusedFieldText(L"Banana");
}
+TEST_F(FPDFFormFillListBoxFormEmbedderTest, CheckIfMultipleSelected) {
+ // Multiselect field set to 'Gamma' (index 2) and 'Epsilon' (index 4) upon
+ // opening.
+ FocusOnMultiSelectMultipleSelectedForm();
+ for (int i = 0; i < 5; i++) {
+ // TODO(bug_1377): Should be selected at index 2 and index 4.
+ bool expected = false;
+ CheckIsIndexSelected(i, expected);
+ }
+}
+
+TEST_F(FPDFFormFillListBoxFormEmbedderTest,
+ CheckIfVerticalScrollIsAtFirstSelected) {
+ // Multiselect field set to 'Gamma' (index 2) and 'Epsilon' (index 4) upon
+ // opening.
+
+ // TODO(bug_1377): Behavior should be changed to the one described below.
+ // The top visible option is 'Gamma' (index 2), so the first selection should
+ // not change. The second selection, 'Epsilon,' should be deselected.
+ ClickOnMultiSelectMultipleSelectedFormOption(0);
+ for (int i = 0; i < 5; i++) {
+ bool expected = i == 0;
+ CheckIsIndexSelected(i, expected);
+ }
+}
+
+TEST_F(FPDFFormFillListBoxFormEmbedderTest, CheckForNoOverscroll) {
+ // Only the last option in the list, 'Saskatchewan', is selected.
+ FocusOnSingleSelectLastSelectedForm();
+ for (int i = 0; i < 10; i++) {
+ bool expected = i == 9;
+ CheckIsIndexSelected(i, expected);
+ }
+
+ // Even though the top index is specified to be at 'Saskatchewan' (index 9),
+ // the top visible option will be the one above it, 'Quebec' (index 8), to
+ // prevent overscrolling. Therefore, clicking on the first visible option of
+ // the list should select 'Quebec' instead of 'Saskatchewan.'
+ ClickOnSingleSelectLastSelectedFormOption(0);
+ for (int i = 0; i < 10; i++) {
+ bool expected = i == 8;
+ CheckIsIndexSelected(i, expected);
+ }
+}
+
TEST_F(FPDFFormFillTextFormEmbedderTest, ReplaceSelection) {
ScopedFPDFWideString text_to_insert = GetFPDFWideString(L"XYZ");
ClickOnFormFieldAtPoint(RegularFormBegin());
diff --git a/testing/resources/listbox_form.in b/testing/resources/listbox_form.in
index 03acd56..334d068 100644
--- a/testing/resources/listbox_form.in
+++ b/testing/resources/listbox_form.in
@@ -3,7 +3,7 @@
<<
/Type /Catalog
/Pages 2 0 R
- /AcroForm << /Fields [ 8 0 R 9 0 R 10 0 R ] /DR 4 0 R >>
+ /AcroForm << /Fields [ 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R ] /DR 4 0 R >>
>>
endobj
{{object 2 0}}
@@ -16,7 +16,7 @@
/Resources 4 0 R
/MediaBox [ 0 0 300 600 ]
/Contents 7 0 R
- /Annots [ 8 0 R 9 0 R 10 0 R ]
+ /Annots [ 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R ]
>>
endobj
{{object 4 0}}
@@ -83,6 +83,35 @@
/Opt [(Dog) (Elephant) (Frog)]
>>
endobj
+{{object 11 0}}
+<<
+ /Type /Annot
+ /FT /Ch
+ /Ff 2097152
+ /T (Listbox_MultiSelectMultipleSelected)
+ /DA (0 0 0 rg /F1 12 Tf)
+ /Rect [ 100 200 200 230 ]
+ /Subtype /Widget
+ /Opt [(Alpha) (Beta) (Gamma) (Delta) (Epsilon)]
+ /V [(Epsilon) (Gamma)]
+>>
+endobj
+{{object 12 0}}
+<<
+ /Type /Annot
+ /FT /Ch
+ /Ff 0
+ /T (Listbox_SingleSelectLastSelected)
+ /DA (0 0 0 rg /F1 12 Tf)
+ /Rect [ 100 100 200 130 ]
+ /Subtype /Widget
+ /Opt [(Alberta) (British Columbia) (Manitoba) (New Brunswick)
+ (Newfoundland and Labrador) (Nova Scotia) (Ontario)
+ (Prince Edward Island) (Quebec) (Saskatchewan) ]
+ /V (Saskatchewan)
+ /TI 9
+>>
+endobj
{{xref}}
{{trailer}}
{{startxref}}
diff --git a/testing/resources/listbox_form.pdf b/testing/resources/listbox_form.pdf
index 7c244d1..51a7fb7 100644
--- a/testing/resources/listbox_form.pdf
+++ b/testing/resources/listbox_form.pdf
@@ -4,7 +4,7 @@
<<
/Type /Catalog
/Pages 2 0 R
- /AcroForm << /Fields [ 8 0 R 9 0 R 10 0 R ] /DR 4 0 R >>
+ /AcroForm << /Fields [ 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R ] /DR 4 0 R >>
>>
endobj
2 0 obj
@@ -17,7 +17,7 @@
/Resources 4 0 R
/MediaBox [ 0 0 300 600 ]
/Contents 7 0 R
- /Annots [ 8 0 R 9 0 R 10 0 R ]
+ /Annots [ 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R ]
>>
endobj
4 0 obj
@@ -84,23 +84,54 @@
/Opt [(Dog) (Elephant) (Frog)]
>>
endobj
+11 0 obj
+<<
+ /Type /Annot
+ /FT /Ch
+ /Ff 2097152
+ /T (Listbox_MultiSelectMultipleSelected)
+ /DA (0 0 0 rg /F1 12 Tf)
+ /Rect [ 100 200 200 230 ]
+ /Subtype /Widget
+ /Opt [(Alpha) (Beta) (Gamma) (Delta) (Epsilon)]
+ /V [(Epsilon) (Gamma)]
+>>
+endobj
+12 0 obj
+<<
+ /Type /Annot
+ /FT /Ch
+ /Ff 0
+ /T (Listbox_SingleSelectLastSelected)
+ /DA (0 0 0 rg /F1 12 Tf)
+ /Rect [ 100 100 200 130 ]
+ /Subtype /Widget
+ /Opt [(Alberta) (British Columbia) (Manitoba) (New Brunswick)
+ (Newfoundland and Labrador) (Nova Scotia) (Ontario)
+ (Prince Edward Island) (Quebec) (Saskatchewan) ]
+ /V (Saskatchewan)
+ /TI 9
+>>
+endobj
xref
-0 11
+0 13
0000000000 65535 f
0000000015 00000 n
-0000000127 00000 n
-0000000186 00000 n
-0000000335 00000 n
-0000000368 00000 n
-0000000399 00000 n
-0000000475 00000 n
-0000000575 00000 n
-0000000782 00000 n
-0000001252 00000 n
+0000000141 00000 n
+0000000200 00000 n
+0000000363 00000 n
+0000000396 00000 n
+0000000427 00000 n
+0000000503 00000 n
+0000000603 00000 n
+0000000810 00000 n
+0000001280 00000 n
+0000001466 00000 n
+0000001719 00000 n
trailer <<
/Root 1 0 R
- /Size 11
+ /Size 13
>>
startxref
-1438
+2097
%%EOF