Add FORM_OnLButtonDoubleClick().

The code for this already exists, but is not hooked up to a public API.
Hook it up and add a test case.

Change-Id: I2ebc8492d8b7347849ff06f664155c6d72ecf76f
Reviewed-on: https://pdfium-review.googlesource.com/c/44130
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.cpp b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
index ac22fe2..7d253c8 100644
--- a/fpdfsdk/cpdfsdk_annothandlermgr.cpp
+++ b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
@@ -145,6 +145,16 @@
       ->OnLButtonUp(pPageView, pAnnot, nFlags, point);
 }
 
+bool CPDFSDK_AnnotHandlerMgr::Annot_OnLButtonDblClk(
+    CPDFSDK_PageView* pPageView,
+    CPDFSDK_Annot::ObservedPtr* pAnnot,
+    uint32_t nFlags,
+    const CFX_PointF& point) {
+  ASSERT(pAnnot->HasObservable());
+  return GetAnnotHandler(pAnnot->Get())
+      ->OnLButtonDblClk(pPageView, pAnnot, nFlags, point);
+}
+
 bool CPDFSDK_AnnotHandlerMgr::Annot_OnMouseMove(
     CPDFSDK_PageView* pPageView,
     CPDFSDK_Annot::ObservedPtr* pAnnot,
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.h b/fpdfsdk/cpdfsdk_annothandlermgr.h
index 690e46c..eb8ef48 100644
--- a/fpdfsdk/cpdfsdk_annothandlermgr.h
+++ b/fpdfsdk/cpdfsdk_annothandlermgr.h
@@ -69,6 +69,10 @@
                          CPDFSDK_Annot::ObservedPtr* pAnnot,
                          uint32_t nFlags,
                          const CFX_PointF& point);
+  bool Annot_OnLButtonDblClk(CPDFSDK_PageView* pPageView,
+                             CPDFSDK_Annot::ObservedPtr* pAnnot,
+                             uint32_t nFlags,
+                             const CFX_PointF& point);
   bool Annot_OnMouseMove(CPDFSDK_PageView* pPageView,
                          CPDFSDK_Annot::ObservedPtr* pAnnot,
                          uint32_t nFlags,
diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp
index 4d9a905..b0b5f8a 100644
--- a/fpdfsdk/cpdfsdk_pageview.cpp
+++ b/fpdfsdk/cpdfsdk_pageview.cpp
@@ -315,6 +315,40 @@
   return true;
 }
 
+bool CPDFSDK_PageView::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
+  CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
+      m_pFormFillEnv->GetAnnotHandlerMgr();
+  CPDFSDK_Annot::ObservedPtr pFXAnnot(GetFXWidgetAtPoint(point));
+  CPDFSDK_Annot::ObservedPtr pFocusAnnot(GetFocusAnnot());
+  if (pFocusAnnot && pFocusAnnot != pFXAnnot) {
+    // Last focus Annot gets a chance to handle the event.
+    if (pAnnotHandlerMgr->Annot_OnLButtonUp(this, &pFocusAnnot, nFlag, point))
+      return true;
+  }
+  return pFXAnnot &&
+         pAnnotHandlerMgr->Annot_OnLButtonUp(this, &pFXAnnot, nFlag, point);
+}
+
+bool CPDFSDK_PageView::OnLButtonDblClk(const CFX_PointF& point,
+                                       uint32_t nFlag) {
+  CPDFSDK_Annot::ObservedPtr pAnnot(GetFXWidgetAtPoint(point));
+  if (!pAnnot) {
+    m_pFormFillEnv->KillFocusAnnot(nFlag);
+    return false;
+  }
+
+  CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
+      m_pFormFillEnv->GetAnnotHandlerMgr();
+  if (!pAnnotHandlerMgr->Annot_OnLButtonDblClk(this, &pAnnot, nFlag, point))
+    return false;
+
+  if (!pAnnot)
+    return false;
+
+  m_pFormFillEnv->SetFocusAnnot(&pAnnot);
+  return true;
+}
+
 #ifdef PDF_ENABLE_XFA
 bool CPDFSDK_PageView::OnRButtonDown(const CFX_PointF& point, uint32_t nFlag) {
   CPDFSDK_Annot::ObservedPtr pAnnot(GetFXWidgetAtPoint(point));
@@ -347,20 +381,6 @@
 }
 #endif  // PDF_ENABLE_XFA
 
-bool CPDFSDK_PageView::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
-  CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
-      m_pFormFillEnv->GetAnnotHandlerMgr();
-  CPDFSDK_Annot::ObservedPtr pFXAnnot(GetFXWidgetAtPoint(point));
-  CPDFSDK_Annot::ObservedPtr pFocusAnnot(GetFocusAnnot());
-  if (pFocusAnnot && pFocusAnnot != pFXAnnot) {
-    // Last focus Annot gets a chance to handle the event.
-    if (pAnnotHandlerMgr->Annot_OnLButtonUp(this, &pFocusAnnot, nFlag, point))
-      return true;
-  }
-  return pFXAnnot &&
-         pAnnotHandlerMgr->Annot_OnLButtonUp(this, &pFXAnnot, nFlag, point);
-}
-
 bool CPDFSDK_PageView::OnMouseMove(const CFX_PointF& point, int nFlag) {
   CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
       m_pFormFillEnv->GetAnnotHandlerMgr();
diff --git a/fpdfsdk/cpdfsdk_pageview.h b/fpdfsdk/cpdfsdk_pageview.h
index 4674c1b..c3cbbc6 100644
--- a/fpdfsdk/cpdfsdk_pageview.h
+++ b/fpdfsdk/cpdfsdk_pageview.h
@@ -65,6 +65,7 @@
   bool OnFocus(const CFX_PointF& point, uint32_t nFlag);
   bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag);
   bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag);
+  bool OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag);
 
 #ifdef PDF_ENABLE_XFA
   bool OnRButtonDown(const CFX_PointF& point, uint32_t nFlag);
diff --git a/fpdfsdk/fpdf_formfill.cpp b/fpdfsdk/fpdf_formfill.cpp
index 7b8215d..4b23ce4 100644
--- a/fpdfsdk/fpdf_formfill.cpp
+++ b/fpdfsdk/fpdf_formfill.cpp
@@ -410,6 +410,22 @@
   return pPageView->OnLButtonUp(CFX_PointF(page_x, page_y), modifier);
 }
 
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FORM_OnLButtonDoubleClick(FPDF_FORMHANDLE hHandle,
+                          FPDF_PAGE page,
+                          int modifier,
+                          double page_x,
+                          double page_y) {
+  CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
+  if (!pPageView)
+    return false;
+#ifdef PDF_ENABLE_CLICK_LOGGING
+  fprintf(stderr, "mousedown,doubleleft,%d,%d\n",
+          static_cast<int>(round(page_x)), static_cast<int>(round(page_y)));
+#endif  // PDF_ENABLE_CLICK_LOGGING
+  return pPageView->OnLButtonDblClk(CFX_PointF(page_x, page_y), modifier);
+}
+
 #ifdef PDF_ENABLE_XFA
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,
                                                        FPDF_PAGE page,
diff --git a/fpdfsdk/fpdf_formfill_embeddertest.cpp b/fpdfsdk/fpdf_formfill_embeddertest.cpp
index e55997c..99d30f3 100644
--- a/fpdfsdk/fpdf_formfill_embeddertest.cpp
+++ b/fpdfsdk/fpdf_formfill_embeddertest.cpp
@@ -64,6 +64,12 @@
     FORM_OnLButtonUp(form_handle(), page_, 0, point.x, point.y);
   }
 
+  void DoubleClickOnFormFieldAtPoint(const CFX_PointF& point) {
+    // Click on the text field or combobox as specified by coordinates.
+    FORM_OnMouseMove(form_handle(), page_, 0, point.x, point.y);
+    FORM_OnLButtonDoubleClick(form_handle(), page_, 0, point.x, point.y);
+  }
+
   void TypeTextIntoTextField(int num_chars, const CFX_PointF& point) {
     EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(point));
     ClickOnFormFieldAtPoint(point);
@@ -1542,6 +1548,23 @@
   CheckSelection(L"ElepHippop");
 }
 
+TEST_F(FPDFFormFillTextFormEmbeddertest, DoubleClickInTextField) {
+  CheckFocusedFieldText(L"");
+  ClickOnFormFieldAtPoint(RegularFormBegin());
+  CheckFocusedFieldText(L"");
+
+  // Test inserting text into empty text field.
+  std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+      GetFPDFWideString(L"Hello World");
+  FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"Hello World");
+
+  // Make sure double clicking selects the entire line.
+  CheckSelection(L"");
+  DoubleClickOnFormFieldAtPoint(RegularFormBegin());
+  CheckSelection(L"Hello World");
+}
+
 TEST_F(FPDFFormFillTextFormEmbeddertest, FocusChanges) {
   static const CFX_PointF kNonFormPoint(1, 1);
   CheckFocusedFieldText(L"");
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
index 3ec51e7..ab184cc 100644
--- a/fpdfsdk/fpdf_view_c_api_test.c
+++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -240,6 +240,7 @@
     CHK(FORM_OnFocus);
     CHK(FORM_OnKeyDown);
     CHK(FORM_OnKeyUp);
+    CHK(FORM_OnLButtonDoubleClick);
     CHK(FORM_OnLButtonDown);
     CHK(FORM_OnLButtonUp);
     CHK(FORM_OnMouseMove);
diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h
index bd8ab3c..ed7db27 100644
--- a/public/fpdf_formfill.h
+++ b/public/fpdf_formfill.h
@@ -1281,17 +1281,17 @@
 /**
  * Function: FORM_OnLButtonDown
  *          You can call this member function when the user presses the left
- *mouse button.
+ *          mouse button.
  * Parameters:
  *          hHandle     -   Handle to the form fill module. Returned by
- *FPDFDOC_InitFormFillEnvironment.
+ *                          FPDFDOC_InitFormFillEnvironment().
  *          page        -   Handle to the page. Returned by FPDF_LoadPage
- *function.
- *          modifier        -   Indicates whether various virtual keys are down.
+ *                          function.
+ *          modifier    -   Indicates whether various virtual keys are down.
  *          page_x      -   Specifies the x-coordinate of the cursor in PDF user
- *space.
+ *                          space.
  *          page_y      -   Specifies the y-coordinate of the cursor in PDF user
- *space.
+ *                          space.
  * Return Value:
  *          TRUE indicates success; otherwise false.
  **/
@@ -1304,10 +1304,10 @@
 /**
  * Function: FORM_OnLButtonUp
  *          You can call this member function when the user releases the left
- *mouse button.
+ *          mouse button.
  * Parameters:
  *          hHandle     -   Handle to the form fill module. Returned by
- *FPDFDOC_InitFormFillEnvironment.
+ *                          FPDFDOC_InitFormFillEnvironment().
  *          page        -   Handle to the page. Returned by FPDF_LoadPage
  *function.
  *          modifier    -   Indicates whether various virtual keys are down.
@@ -1322,6 +1322,30 @@
                                                      double page_x,
                                                      double page_y);
 
+/**
+ * Function: FORM_OnLButtonDoubleClick
+ *          You can call this member function when the user double clicks the
+ *          left mouse button.
+ * Parameters:
+ *          hHandle     -   Handle to the form fill module. Returned by
+ *                          FPDFDOC_InitFormFillEnvironment().
+ *          page        -   Handle to the page. Returned by FPDF_LoadPage
+ *                          function.
+ *          modifier    -   Indicates whether various virtual keys are down.
+ *          page_x      -   Specifies the x-coordinate of the cursor in PDF user
+ *                          space.
+ *          page_y      -   Specifies the y-coordinate of the cursor in PDF user
+ *                          space.
+ * Return Value:
+ *          TRUE indicates success; otherwise false.
+ **/
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FORM_OnLButtonDoubleClick(FPDF_FORMHANDLE hHandle,
+                          FPDF_PAGE page,
+                          int modifier,
+                          double page_x,
+                          double page_y);
+
 #ifdef PDF_ENABLE_XFA
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,
                                                        FPDF_PAGE page,