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