Add FORM_OnMouseWheel(). PDFium has scroll wheel support internally in many form widget implementations, but none of it is hooked up via a public API. Add an experimental public API and hook it up to pdfium_test. In pdfium_test, add a way to specify wheel events using the following syntax: mousewheel,pointer_x,pointer_y,delta_x,delta_y[,modifiers] Use the new event to test scrolling a list widget in a pixel test. Bug: pdfium:1452 Change-Id: I87f40243399aa79b50177e8b833e4504becc8039 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/68470 Commit-Queue: Lei Zhang <thestig@chromium.org> Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/fpdf_formfill.cpp b/fpdfsdk/fpdf_formfill.cpp index 96e4c20..ac09b2e 100644 --- a/fpdfsdk/fpdf_formfill.cpp +++ b/fpdfsdk/fpdf_formfill.cpp
@@ -379,6 +379,20 @@ return pPageView->OnMouseMove(CFX_PointF(page_x, page_y), modifier); } +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FORM_OnMouseWheel(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + const FS_POINTF* page_coord, + int delta_x, + int delta_y) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView || !page_coord) + return false; + return pPageView->OnMouseWheel(delta_x, delta_y, + CFXPointFFromFSPointF(*page_coord), modifier); +} + FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnFocus(FPDF_FORMHANDLE hHandle, FPDF_PAGE page, int modifier,
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c index b7353aa..38f302d 100644 --- a/fpdfsdk/fpdf_view_c_api_test.c +++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -258,6 +258,7 @@ CHK(FORM_OnLButtonDown); CHK(FORM_OnLButtonUp); CHK(FORM_OnMouseMove); + CHK(FORM_OnMouseWheel); CHK(FORM_OnRButtonDown); CHK(FORM_OnRButtonUp); CHK(FORM_Redo);
diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h index 84537e4..1f656b0 100644 --- a/public/fpdf_formfill.h +++ b/public/fpdf_formfill.h
@@ -1272,6 +1272,39 @@ double page_y); /* + * Experimental API + * Function: FORM_OnMouseWheel + * Call this member function when the user scrolls the mouse wheel. + * Parameters: + * hHandle - Handle to the form fill module, as returned by + * FPDFDOC_InitFormFillEnvironment(). + * page - Handle to the page, as returned by FPDF_LoadPage(). + * modifier - Indicates whether various virtual keys are down. + * page_coord - Specifies the coordinates of the cursor in PDF user + * space. + * delta_x - Specifies the amount of wheel movement on the x-axis, + * in units of platform-agnostic wheel deltas. Negative + * values mean left. + * delta_y - Specifies the amount of wheel movement on the y-axis, + * in units of platform-agnostic wheel deltas. Negative + * values mean down. + * Return Value: + * True indicates success; otherwise false. + * Comments: + * For |delta_x| and |delta_y|, the caller must normalize + * platform-specific wheel deltas. e.g. On Windows, a delta value of 240 + * for a WM_MOUSEWHEEL event normalizes to 2, since Windows defines + * WHEEL_DELTA as 120. + */ +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnMouseWheel( + FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + const FS_POINTF* page_coord, + int delta_x, + int delta_y); + +/* * Function: FORM_OnFocus * This function focuses the form annotation at a given point. If the * annotation at the point already has focus, nothing happens. If there @@ -1299,7 +1332,7 @@ * Call this member function when the user presses the left * mouse button. * Parameters: - * hHandle - Handle to the form fill module. as returned by + * hHandle - Handle to the form fill module, as returned by * FPDFDOC_InitFormFillEnvironment(). * page - Handle to the page, as returned by FPDF_LoadPage(). * modifier - Indicates whether various virtual keys are down. @@ -1335,7 +1368,7 @@ * Parameters: * hHandle - Handle to the form fill module, as returned by * FPDFDOC_InitFormFillEnvironment(). - * page - Handle to the page. as returned by FPDF_LoadPage(). + * page - Handle to the page, as returned by FPDF_LoadPage(). * modifier - Indicates whether various virtual keys are down. * page_x - Specifies the x-coordinate of the cursor in device. * page_y - Specifies the y-coordinate of the cursor in device. @@ -1536,7 +1569,7 @@ * Function: FORM_Undo * Make the current focussed widget perform an undo operation. * Parameters: - * hHandle - Handle to the form fill module. as returned by + * hHandle - Handle to the form fill module, as returned by * FPDFDOC_InitFormFillEnvironment(). * page - Handle to the page, as returned by FPDF_LoadPage(). * Return Value:
diff --git a/samples/pdfium_test_event_helper.cc b/samples/pdfium_test_event_helper.cc index 2e1abe9..f45063d 100644 --- a/samples/pdfium_test_event_helper.cc +++ b/samples/pdfium_test_event_helper.cc
@@ -56,7 +56,7 @@ void SendMouseDownEvent(FPDF_FORMHANDLE form, FPDF_PAGE page, const std::vector<std::string>& tokens) { - if (tokens.size() != 4 && tokens.size() != 5) { + if (tokens.size() < 4 && tokens.size() > 5) { fprintf(stderr, "mousedown: bad args\n"); return; } @@ -76,7 +76,7 @@ void SendMouseUpEvent(FPDF_FORMHANDLE form, FPDF_PAGE page, const std::vector<std::string>& tokens) { - if (tokens.size() != 4 && tokens.size() != 5) { + if (tokens.size() < 4 && tokens.size() > 5) { fprintf(stderr, "mouseup: bad args\n"); return; } @@ -95,7 +95,7 @@ void SendMouseDoubleClickEvent(FPDF_FORMHANDLE form, FPDF_PAGE page, const std::vector<std::string>& tokens) { - if (tokens.size() != 4 && tokens.size() != 5) { + if (tokens.size() < 4 && tokens.size() > 5) { fprintf(stderr, "mousedoubleclick: bad args\n"); return; } @@ -123,6 +123,21 @@ FORM_OnMouseMove(form, page, 0, x, y); } +void SendMouseWheelEvent(FPDF_FORMHANDLE form, + FPDF_PAGE page, + const std::vector<std::string>& tokens) { + if (tokens.size() < 5 && tokens.size() > 6) { + fprintf(stderr, "mousewheel: bad args\n"); + return; + } + + const FS_POINTF point = {atoi(tokens[1].c_str()), atoi(tokens[2].c_str())}; + int delta_x = atoi(tokens[3].c_str()); + int delta_y = atoi(tokens[4].c_str()); + int modifiers = tokens.size() >= 6 ? GetModifiers(tokens[5]) : 0; + FORM_OnMouseWheel(form, page, modifiers, &point, delta_x, delta_y); +} + void SendFocusEvent(FPDF_FORMHANDLE form, FPDF_PAGE page, const std::vector<std::string>& tokens) { @@ -135,6 +150,7 @@ int y = atoi(tokens[2].c_str()); FORM_OnFocus(form, page, 0, x, y); } + } // namespace void SendPageEvents(FPDF_FORMHANDLE form, @@ -158,6 +174,8 @@ SendMouseDoubleClickEvent(form, page, tokens); } else if (tokens[0] == "mousemove") { SendMouseMoveEvent(form, page, tokens); + } else if (tokens[0] == "mousewheel") { + SendMouseWheelEvent(form, page, tokens); } else if (tokens[0] == "focus") { SendFocusEvent(form, page, tokens); } else {
diff --git a/testing/resources/pixel/scrollable_widgets1.evt b/testing/resources/pixel/scrollable_widgets1.evt new file mode 100644 index 0000000..c595cd7 --- /dev/null +++ b/testing/resources/pixel/scrollable_widgets1.evt
@@ -0,0 +1,29 @@ +# Must move the mouse and click to give widget focus. +mousemove,150,415 +mousedown,left,150,415 +# Scroll all the way down. +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1
diff --git a/testing/resources/pixel/scrollable_widgets1.in b/testing/resources/pixel/scrollable_widgets1.in new file mode 100644 index 0000000..9453b7c --- /dev/null +++ b/testing/resources/pixel/scrollable_widgets1.in
@@ -0,0 +1,52 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /AcroForm << + /Fields [5 0 R] + /DR << + /Font << + /F1 4 0 R + >> + >> + >> +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [3 0 R] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /MediaBox [0 0 300 600] + /Annots [5 0 R] +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 5 0}} << + /Type /Annot + /Subtype /Widget + /FT /Ch + /Ff 2097152 + /T (Listbox_MultiSelect) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [100 400 200 430] + /Opt [(Apple) (Banana) (Cherry) (Date) (Elderberry) (Fig) (Guava) (Honeydew) + (Indian Fig) (Jackfruit) (Kiwi) (Lemon) (Mango) (Nectarine) (Orange) + (Persimmon) (Quince) (Raspberry) (Strawberry) (Tamarind) (Ugli Fruit) + (Voavanga) (Wolfberry) (Xigua) (Yangmei) (Zucchini)] + /V (Banana) +>> +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF
diff --git a/testing/resources/pixel/scrollable_widgets1_expected.pdf.0.png b/testing/resources/pixel/scrollable_widgets1_expected.pdf.0.png new file mode 100644 index 0000000..4405a36 --- /dev/null +++ b/testing/resources/pixel/scrollable_widgets1_expected.pdf.0.png Binary files differ
diff --git a/testing/resources/pixel/scrollable_widgets1_expected_mac.pdf.0.png b/testing/resources/pixel/scrollable_widgets1_expected_mac.pdf.0.png new file mode 100644 index 0000000..723e851 --- /dev/null +++ b/testing/resources/pixel/scrollable_widgets1_expected_mac.pdf.0.png Binary files differ
diff --git a/testing/resources/pixel/scrollable_widgets1_expected_win.pdf.0.png b/testing/resources/pixel/scrollable_widgets1_expected_win.pdf.0.png new file mode 100644 index 0000000..25b95ec --- /dev/null +++ b/testing/resources/pixel/scrollable_widgets1_expected_win.pdf.0.png Binary files differ
diff --git a/testing/resources/pixel/scrollable_widgets2.evt b/testing/resources/pixel/scrollable_widgets2.evt new file mode 100644 index 0000000..59b8a4b --- /dev/null +++ b/testing/resources/pixel/scrollable_widgets2.evt
@@ -0,0 +1,34 @@ +# Must move the mouse and click to give widget focus. +mousemove,150,415 +mousedown,left,150,415 +# Scroll all the way down and then scroll back up a bit. +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,-1 +mousewheel,150,415,0,1 +mousewheel,150,415,0,1 +mousewheel,150,415,0,1 +mousewheel,150,415,0,1 +mousewheel,150,415,0,1
diff --git a/testing/resources/pixel/scrollable_widgets2.in b/testing/resources/pixel/scrollable_widgets2.in new file mode 100644 index 0000000..9453b7c --- /dev/null +++ b/testing/resources/pixel/scrollable_widgets2.in
@@ -0,0 +1,52 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /AcroForm << + /Fields [5 0 R] + /DR << + /Font << + /F1 4 0 R + >> + >> + >> +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [3 0 R] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /MediaBox [0 0 300 600] + /Annots [5 0 R] +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 5 0}} << + /Type /Annot + /Subtype /Widget + /FT /Ch + /Ff 2097152 + /T (Listbox_MultiSelect) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [100 400 200 430] + /Opt [(Apple) (Banana) (Cherry) (Date) (Elderberry) (Fig) (Guava) (Honeydew) + (Indian Fig) (Jackfruit) (Kiwi) (Lemon) (Mango) (Nectarine) (Orange) + (Persimmon) (Quince) (Raspberry) (Strawberry) (Tamarind) (Ugli Fruit) + (Voavanga) (Wolfberry) (Xigua) (Yangmei) (Zucchini)] + /V (Banana) +>> +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF
diff --git a/testing/resources/pixel/scrollable_widgets2_expected.pdf.0.png b/testing/resources/pixel/scrollable_widgets2_expected.pdf.0.png new file mode 100644 index 0000000..b965ffc --- /dev/null +++ b/testing/resources/pixel/scrollable_widgets2_expected.pdf.0.png Binary files differ
diff --git a/testing/resources/pixel/scrollable_widgets2_expected_mac.pdf.0.png b/testing/resources/pixel/scrollable_widgets2_expected_mac.pdf.0.png new file mode 100644 index 0000000..385f87f --- /dev/null +++ b/testing/resources/pixel/scrollable_widgets2_expected_mac.pdf.0.png Binary files differ
diff --git a/testing/resources/pixel/scrollable_widgets2_expected_win.pdf.0.png b/testing/resources/pixel/scrollable_widgets2_expected_win.pdf.0.png new file mode 100644 index 0000000..292c873 --- /dev/null +++ b/testing/resources/pixel/scrollable_widgets2_expected_win.pdf.0.png Binary files differ