Add keyboard tabbing for links & highlights

This CL contains following changes to support tabbing over links and
highlights.
1. Three new public APIs FPDFAnnot_SetFocusableSubtypes,
FPDFAnnot_GetFocusableSubtypesCount and FPDFAnnot_GetFocusableSubtypes
are added which allows the caller to set the focusable annotation
subtypes, get the count of focusable annotation subtypes and get the
focusable annotation subtypes.

2. To add the capability of tabbing over links & highlights along with
widgets, CPDFSDK_Annotiterator should now accept vector of
annotation subtypes (CPDF_Annot::Subtype :- widget + highlight + link),
so that it can return vector of annotations of the given subtypes in
the right order.

3. Implementation of BAAnnotHandler - Invalidating rect during killing
focus and setting focus. OnDraw() will draw the rect over the focused
annotation.

4. List of focusable annotation subtypes will be passed from host side
(https://crrev.com/c/1783695) and pdfium will act according to the
input annotation subtypes.

5. CL related to test cases
(https://pdfium-review.googlesource.com/c/pdfium/+/62950) is already
merged

Bug: chromium:994500
Change-Id: I09fc4d9d902884ecd659b2573582fbd4992c29d3
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/60011
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Neha Gupta <negupta@microsoft.com>
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.cpp b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
index d79b9ff..e5e0313 100644
--- a/fpdfsdk/cpdfsdk_annothandlermgr.cpp
+++ b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
@@ -325,9 +325,11 @@
     return static_cast<CPDFXFA_Page*>(pPage)->GetNextXFAAnnot(pSDKAnnot, bNext);
   }
 #endif  // PDF_ENABLE_XFA
+  CPDFSDK_FormFillEnvironment* pFormFillEnv =
+      pSDKAnnot->GetPageView()->GetFormFillEnv();
 
   // For PDF annots.
-  CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pSDKAnnot);
-  CPDFSDK_AnnotIterator ai(pWidget->GetPageView(), pWidget->GetAnnotSubtype());
-  return bNext ? ai.GetNextAnnot(pWidget) : ai.GetPrevAnnot(pWidget);
+  CPDFSDK_AnnotIterator ai(pSDKAnnot->GetPageView(),
+                           pFormFillEnv->GetFocusableAnnotSubtypes());
+  return bNext ? ai.GetNextAnnot(pSDKAnnot) : ai.GetPrevAnnot(pSDKAnnot);
 }
diff --git a/fpdfsdk/cpdfsdk_annotiterator.cpp b/fpdfsdk/cpdfsdk_annotiterator.cpp
index f1919ab..c1db6bb 100644
--- a/fpdfsdk/cpdfsdk_annotiterator.cpp
+++ b/fpdfsdk/cpdfsdk_annotiterator.cpp
@@ -41,8 +41,15 @@
 
 CPDFSDK_AnnotIterator::CPDFSDK_AnnotIterator(CPDFSDK_PageView* pPageView,
                                              CPDF_Annot::Subtype nAnnotSubtype)
+    : CPDFSDK_AnnotIterator(
+          pPageView,
+          std::vector<CPDF_Annot::Subtype>(1, nAnnotSubtype)) {}
+
+CPDFSDK_AnnotIterator::CPDFSDK_AnnotIterator(
+    CPDFSDK_PageView* pPageView,
+    const std::vector<CPDF_Annot::Subtype>& subtypes_to_iterate)
     : m_pPageView(pPageView),
-      m_nAnnotSubtype(nAnnotSubtype),
+      m_subtypes(subtypes_to_iterate),
       m_eTabOrder(GetTabOrder(pPageView)) {
   GenerateResults();
 }
@@ -78,7 +85,7 @@
 
 void CPDFSDK_AnnotIterator::CollectAnnots(std::vector<CPDFSDK_Annot*>* pArray) {
   for (auto* pAnnot : m_pPageView->GetAnnotList()) {
-    if (pAnnot->GetAnnotSubtype() == m_nAnnotSubtype &&
+    if (pdfium::ContainsValue(m_subtypes, pAnnot->GetAnnotSubtype()) &&
         !pAnnot->IsSignatureWidget()) {
       pArray->push_back(pAnnot);
     }
diff --git a/fpdfsdk/cpdfsdk_annotiterator.h b/fpdfsdk/cpdfsdk_annotiterator.h
index fd7cbdc..5a0ca8a 100644
--- a/fpdfsdk/cpdfsdk_annotiterator.h
+++ b/fpdfsdk/cpdfsdk_annotiterator.h
@@ -23,6 +23,11 @@
 
   CPDFSDK_AnnotIterator(CPDFSDK_PageView* pPageView,
                         CPDF_Annot::Subtype nAnnotSubtype);
+
+  CPDFSDK_AnnotIterator(
+      CPDFSDK_PageView* pPageView,
+      const std::vector<CPDF_Annot::Subtype>& subtypes_to_iterate);
+
   ~CPDFSDK_AnnotIterator();
 
   CPDFSDK_Annot* GetFirstAnnot();
@@ -38,7 +43,7 @@
                            std::vector<size_t>* aSelect);
 
   UnownedPtr<CPDFSDK_PageView> const m_pPageView;
-  CPDF_Annot::Subtype m_nAnnotSubtype;
+  const std::vector<CPDF_Annot::Subtype> m_subtypes;
   const TabOrder m_eTabOrder;
   std::vector<CPDFSDK_Annot*> m_Annots;
 };
diff --git a/fpdfsdk/cpdfsdk_baannothandler.cpp b/fpdfsdk/cpdfsdk_baannothandler.cpp
index d83dfba..42a0704 100644
--- a/fpdfsdk/cpdfsdk_baannothandler.cpp
+++ b/fpdfsdk/cpdfsdk_baannothandler.cpp
@@ -7,13 +7,14 @@
 #include "fpdfsdk/cpdfsdk_baannothandler.h"
 
 #include <memory>
-#include <vector>
 
 #include "core/fpdfapi/page/cpdf_page.h"
 #include "core/fpdfapi/parser/cpdf_document.h"
 #include "core/fpdfdoc/cpdf_interactiveform.h"
+#include "core/fxge/cfx_drawutils.h"
 #include "fpdfsdk/cpdfsdk_annot.h"
 #include "fpdfsdk/cpdfsdk_baannot.h"
+#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
 #include "fpdfsdk/cpdfsdk_pageview.h"
 #include "fpdfsdk/formfiller/cffl_formfiller.h"
 
@@ -40,7 +41,7 @@
 
 void CPDFSDK_BAAnnotHandler::SetFormFillEnvironment(
     CPDFSDK_FormFillEnvironment* pFormFillEnv) {
-  // CPDFSDK_BAAnnotHandler does not need it.
+  form_fill_environment_ = pFormFillEnv;
 }
 
 bool CPDFSDK_BAAnnotHandler::CanAnswer(CPDFSDK_Annot* pAnnot) {
@@ -66,9 +67,26 @@
   if (pAnnot->AsXFAWidget())
     return;
 
-  if (bDrawAnnots && pAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::POPUP) {
+  if (!pAnnot->AsBAAnnot()->IsVisible())
+    return;
+
+  const CPDF_Annot::Subtype annot_type = pAnnot->GetAnnotSubtype();
+  if (bDrawAnnots && annot_type == CPDF_Annot::Subtype::POPUP) {
     pAnnot->AsBAAnnot()->DrawAppearance(pDevice, mtUser2Device,
                                         CPDF_Annot::Normal, nullptr);
+    return;
+  }
+
+  if (is_annotation_focused_ && IsFocusableAnnot(annot_type) &&
+      pAnnot == form_fill_environment_->GetFocusAnnot()) {
+    CFX_FloatRect view_bounding_box =
+        GetViewBBox(pPageView, pAnnot->AsBAAnnot());
+    if (view_bounding_box.IsEmpty())
+      return;
+
+    view_bounding_box.Normalize();
+
+    CFX_DrawUtils::DrawFocusRect(pDevice, mtUser2Device, view_bounding_box);
   }
 }
 
@@ -165,14 +183,44 @@
 
 void CPDFSDK_BAAnnotHandler::OnLoad(CPDFSDK_Annot* pAnnot) {}
 
+bool CPDFSDK_BAAnnotHandler::IsFocusableAnnot(
+    const CPDF_Annot::Subtype& annot_type) const {
+  ASSERT(annot_type != CPDF_Annot::Subtype::WIDGET);
+
+  return pdfium::ContainsValue(
+      form_fill_environment_->GetFocusableAnnotSubtypes(), annot_type);
+}
+
+void CPDFSDK_BAAnnotHandler::InvalidateRect(CPDFSDK_Annot* annot) {
+  CPDFSDK_BAAnnot* ba_annot = annot->AsBAAnnot();
+  CPDFSDK_PageView* page_view = ba_annot->GetPageView();
+  CFX_FloatRect view_bounding_box = GetViewBBox(page_view, ba_annot);
+  if (!view_bounding_box.IsEmpty()) {
+    view_bounding_box.Inflate(1, 1);
+    view_bounding_box.Normalize();
+    FX_RECT rect = view_bounding_box.GetOuterRect();
+    form_fill_environment_->Invalidate(ba_annot->GetPage(), rect);
+  }
+}
+
 bool CPDFSDK_BAAnnotHandler::OnSetFocus(ObservedPtr<CPDFSDK_Annot>* pAnnot,
                                         uint32_t nFlag) {
-  return false;
+  if (!IsFocusableAnnot(pAnnot->Get()->GetAnnotSubtype()))
+    return false;
+
+  is_annotation_focused_ = true;
+  InvalidateRect(pAnnot->Get());
+  return true;
 }
 
 bool CPDFSDK_BAAnnotHandler::OnKillFocus(ObservedPtr<CPDFSDK_Annot>* pAnnot,
                                          uint32_t nFlag) {
-  return false;
+  if (!IsFocusableAnnot(pAnnot->Get()->GetAnnotSubtype()))
+    return false;
+
+  is_annotation_focused_ = false;
+  InvalidateRect(pAnnot->Get());
+  return true;
 }
 
 bool CPDFSDK_BAAnnotHandler::SetIndexSelected(
diff --git a/fpdfsdk/cpdfsdk_baannothandler.h b/fpdfsdk/cpdfsdk_baannothandler.h
index 22607bf..03a6b9f 100644
--- a/fpdfsdk/cpdfsdk_baannothandler.h
+++ b/fpdfsdk/cpdfsdk_baannothandler.h
@@ -99,6 +99,13 @@
                         int index,
                         bool selected) override;
   bool IsIndexSelected(ObservedPtr<CPDFSDK_Annot>* pAnnot, int index) override;
+
+ private:
+  void InvalidateRect(CPDFSDK_Annot* annot);
+  bool IsFocusableAnnot(const CPDF_Annot::Subtype& annot_type) const;
+
+  UnownedPtr<CPDFSDK_FormFillEnvironment> form_fill_environment_;
+  bool is_annotation_focused_ = false;
 };
 
 #endif  // FPDFSDK_CPDFSDK_BAANNOTHANDLER_H_
diff --git a/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp b/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp
index 9a26e83..6d7fd2e 100644
--- a/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp
+++ b/fpdfsdk/cpdfsdk_baannothandler_embeddertest.cpp
@@ -70,19 +70,3 @@
 
   EXPECT_FALSE(GetBAAnnotHandler()->OnKillFocus(&pNonWidgetAnnot, 0));
 }
-
-TEST_F(CPDFSDK_BAAnnotHandlerTest, TabToInvalidAnnot) {
-  // TODO(crbug.com/994500): Create annot iterator with list of supported
-  // focusable subtypes as provided by host.
-  CPDFSDK_AnnotIterator ai(GetPageView(), CPDF_Annot::Subtype::WIDGET);
-  CPDFSDK_Annot* pAnnot = ai.GetFirstAnnot();
-  ASSERT_TRUE(pAnnot);
-  EXPECT_EQ(pAnnot->GetAnnotSubtype(), CPDF_Annot::Subtype::WIDGET);
-
-  ObservedPtr<CPDFSDK_Annot> pWidgetAnnot(pAnnot);
-
-  // Passing wrong subtype to BAAnnotHandler, API should return false.
-  EXPECT_FALSE(GetBAAnnotHandler()->OnSetFocus(&pWidgetAnnot, 0));
-
-  EXPECT_FALSE(GetBAAnnotHandler()->OnKillFocus(&pWidgetAnnot, 0));
-}
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.h b/fpdfsdk/cpdfsdk_formfillenvironment.h
index d7ccc23..b3dbdb1 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.h
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.h
@@ -201,6 +201,14 @@
 
   CPDFSDK_AnnotHandlerMgr* GetAnnotHandlerMgr();  // Always present.
 
+  void SetFocusableAnnotSubtypes(
+      const std::vector<CPDF_Annot::Subtype>& focusableAnnotTypes) {
+    m_FocusableAnnotTypes = focusableAnnotTypes;
+  }
+  const std::vector<CPDF_Annot::Subtype>& GetFocusableAnnotSubtypes() const {
+    return m_FocusableAnnotTypes;
+  }
+
   // Creates if not present.
   CFFL_InteractiveFormFiller* GetInteractiveFormFiller();
   IJS_Runtime* GetIJSRuntime();                   // Creates if not present.
@@ -222,6 +230,11 @@
   std::unique_ptr<CFFL_InteractiveFormFiller> m_pFormFiller;
   bool m_bChangeMask = false;
   bool m_bBeingDestroyed = false;
+
+  // Holds the list of focusable annot types.
+  // Annotations of type WIDGET are by default focusable.
+  std::vector<CPDF_Annot::Subtype> m_FocusableAnnotTypes = {
+      CPDF_Annot::Subtype::WIDGET};
 };
 
 #endif  // FPDFSDK_CPDFSDK_FORMFILLENVIRONMENT_H_
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index c08ba5a..20ac0e6 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -28,6 +28,7 @@
 #include "core/fpdfdoc/cpdf_interactiveform.h"
 #include "core/fpdfdoc/cpvt_generateap.h"
 #include "core/fxge/cfx_color.h"
+#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
 #include "fpdfsdk/cpdfsdk_helpers.h"
 #include "fpdfsdk/cpdfsdk_interactiveform.h"
 #include "third_party/base/ptr_util.h"
@@ -1065,3 +1066,64 @@
   CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl);
   return pWidget && pWidget->IsChecked();
 }
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_SetFocusableSubtypes(FPDF_FORMHANDLE hHandle,
+                               const FPDF_ANNOTATION_SUBTYPE* subtypes,
+                               size_t count) {
+  CPDFSDK_FormFillEnvironment* pFormFillEnv =
+      CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
+  if (!pFormFillEnv)
+    return false;
+
+  if (count > 0 && !subtypes)
+    return false;
+
+  std::vector<CPDF_Annot::Subtype> focusable_annot_types;
+  focusable_annot_types.reserve(count);
+  for (size_t i = 0; i < count; ++i) {
+    focusable_annot_types.push_back(
+        static_cast<CPDF_Annot::Subtype>(subtypes[i]));
+  }
+
+  pFormFillEnv->SetFocusableAnnotSubtypes(focusable_annot_types);
+  return true;
+}
+
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFAnnot_GetFocusableSubtypesCount(FPDF_FORMHANDLE hHandle) {
+  CPDFSDK_FormFillEnvironment* pFormFillEnv =
+      CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
+  if (!pFormFillEnv)
+    return -1;
+
+  return pdfium::CollectionSize<int>(pFormFillEnv->GetFocusableAnnotSubtypes());
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_GetFocusableSubtypes(FPDF_FORMHANDLE hHandle,
+                               FPDF_ANNOTATION_SUBTYPE* subtypes,
+                               size_t count) {
+  CPDFSDK_FormFillEnvironment* pFormFillEnv =
+      CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
+  if (!pFormFillEnv)
+    return false;
+
+  if (!subtypes)
+    return false;
+
+  const std::vector<CPDF_Annot::Subtype>& focusable_annot_types =
+      pFormFillEnv->GetFocusableAnnotSubtypes();
+
+  // Host should allocate enough memory to get the list of currently supported
+  // focusable subtypes.
+  if (count < focusable_annot_types.size())
+    return false;
+
+  for (size_t i = 0; i < focusable_annot_types.size(); ++i) {
+    subtypes[i] =
+        static_cast<FPDF_ANNOTATION_SUBTYPE>(focusable_annot_types[i]);
+  }
+
+  return true;
+}
diff --git a/fpdfsdk/fpdf_annot_embeddertest.cpp b/fpdfsdk/fpdf_annot_embeddertest.cpp
index 3cdf20e..c45ab50 100644
--- a/fpdfsdk/fpdf_annot_embeddertest.cpp
+++ b/fpdfsdk/fpdf_annot_embeddertest.cpp
@@ -2382,3 +2382,87 @@
   }
   UnloadPage(page);
 }
+
+TEST_F(FPDFAnnotEmbedderTest, SetFocusableAnnotSubtypes) {
+  ASSERT_TRUE(OpenDocument("text_form.pdf"));
+  FPDF_PAGE page = LoadPage(0);
+  ASSERT_TRUE(page);
+
+  // Annotations of type FPDF_ANNOT_WIDGET are by default focusable.
+  EXPECT_EQ(1, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
+
+  EXPECT_TRUE(FPDFAnnot_SetFocusableSubtypes(form_handle(), nullptr, 0));
+  EXPECT_EQ(0, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
+
+  constexpr FPDF_ANNOTATION_SUBTYPE kFocusableSubtypes[] = {FPDF_ANNOT_WIDGET};
+  constexpr size_t kSubtypeCount = FX_ArraySize(kFocusableSubtypes);
+
+  EXPECT_FALSE(FPDFAnnot_SetFocusableSubtypes(nullptr, kFocusableSubtypes,
+                                              kSubtypeCount));
+  EXPECT_FALSE(
+      FPDFAnnot_SetFocusableSubtypes(form_handle(), nullptr, kSubtypeCount));
+
+  EXPECT_TRUE(FPDFAnnot_SetFocusableSubtypes(form_handle(), kFocusableSubtypes,
+                                             kSubtypeCount));
+  EXPECT_EQ(static_cast<int>(kSubtypeCount),
+            FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
+
+  EXPECT_TRUE(
+      FPDFAnnot_SetFocusableSubtypes(form_handle(), kFocusableSubtypes, 0));
+  EXPECT_EQ(0, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
+
+  UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbedderTest, GetFocusableAnnotSubtypesCount) {
+  ASSERT_TRUE(OpenDocument("text_form.pdf"));
+  FPDF_PAGE page = LoadPage(0);
+  ASSERT_TRUE(page);
+
+  EXPECT_EQ(-1, FPDFAnnot_GetFocusableSubtypesCount(nullptr));
+
+  // FPDF_ANNOT_WIDGET is default annot subtype which is focusable,
+  // hence 1 is default count.
+  EXPECT_EQ(1, FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
+
+  constexpr FPDF_ANNOTATION_SUBTYPE kFocusableSubtypes[] = {FPDF_ANNOT_WIDGET,
+                                                            FPDF_ANNOT_LINK};
+  constexpr size_t kSubtypeCount = FX_ArraySize(kFocusableSubtypes);
+
+  FPDFAnnot_SetFocusableSubtypes(form_handle(), kFocusableSubtypes,
+                                 kSubtypeCount);
+
+  EXPECT_EQ(static_cast<int>(kSubtypeCount),
+            FPDFAnnot_GetFocusableSubtypesCount(form_handle()));
+
+  UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbedderTest, GetFocusableAnnotSubtypes) {
+  ASSERT_TRUE(OpenDocument("text_form.pdf"));
+  FPDF_PAGE page = LoadPage(0);
+  ASSERT_TRUE(page);
+
+  constexpr FPDF_ANNOTATION_SUBTYPE kFocusableSubtypes[] = {FPDF_ANNOT_WIDGET};
+  constexpr size_t kSubtypeCount = FX_ArraySize(kFocusableSubtypes);
+
+  FPDFAnnot_SetFocusableSubtypes(form_handle(), kFocusableSubtypes,
+                                 kSubtypeCount);
+
+  int count = FPDFAnnot_GetFocusableSubtypesCount(form_handle());
+  ASSERT_EQ(1, count);
+  EXPECT_FALSE(FPDFAnnot_GetFocusableSubtypes(form_handle(), nullptr, count));
+
+  std::vector<FPDF_ANNOTATION_SUBTYPE> subtypes(count, FPDF_ANNOT_UNKNOWN);
+  EXPECT_FALSE(FPDFAnnot_GetFocusableSubtypes(form_handle(), subtypes.data(),
+                                              count - 1));
+
+  EXPECT_TRUE(
+      FPDFAnnot_GetFocusableSubtypes(form_handle(), subtypes.data(), count));
+
+  for (int i = 0; i < count; ++i) {
+    EXPECT_EQ(kFocusableSubtypes[i], subtypes[i]);
+  }
+
+  UnloadPage(page);
+}
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
index 60bd6fd..0cf0e1c 100644
--- a/fpdfsdk/fpdf_view_c_api_test.c
+++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -46,6 +46,8 @@
     CHK(FPDFAnnot_GetAttachmentPoints);
     CHK(FPDFAnnot_GetColor);
     CHK(FPDFAnnot_GetFlags);
+    CHK(FPDFAnnot_GetFocusableSubtypes);
+    CHK(FPDFAnnot_GetFocusableSubtypesCount);
     CHK(FPDFAnnot_GetFontSize);
     CHK(FPDFAnnot_GetFormFieldAtPoint);
     CHK(FPDFAnnot_GetFormFieldFlags);
@@ -72,6 +74,7 @@
     CHK(FPDFAnnot_SetAttachmentPoints);
     CHK(FPDFAnnot_SetColor);
     CHK(FPDFAnnot_SetFlags);
+    CHK(FPDFAnnot_SetFocusableSubtypes);
     CHK(FPDFAnnot_SetRect);
     CHK(FPDFAnnot_SetStringValue);
     CHK(FPDFAnnot_UpdateObject);
diff --git a/public/fpdf_annot.h b/public/fpdf_annot.h
index 58da809..b10f249 100644
--- a/public/fpdf_annot.h
+++ b/public/fpdf_annot.h
@@ -656,6 +656,51 @@
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_IsChecked(FPDF_FORMHANDLE hHandle,
                                                         FPDF_ANNOTATION annot);
 
+// Experimental API.
+// Set the list of focusable annotation subtypes. Annotations of subtype
+// FPDF_ANNOT_WIDGET are by default focusable. New subtypes set using this API
+// will override the existing subtypes.
+//
+//   hHandle  - handle to the form fill module, returned by
+//              FPDFDOC_InitFormFillEnvironment.
+//   subtypes - list of annotation subtype which can be tabbed over.
+//   count    - total number of annotation subtype in list.
+// Returns true if list of annotation subtype is set successfully, false
+// otherwise.
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_SetFocusableSubtypes(FPDF_FORMHANDLE hHandle,
+                               const FPDF_ANNOTATION_SUBTYPE* subtypes,
+                               size_t count);
+
+// Experimental API.
+// Get the count of focusable annotation subtypes as set by host
+// for a |hHandle|.
+//
+//   hHandle  - handle to the form fill module, returned by
+//              FPDFDOC_InitFormFillEnvironment.
+// Returns the count of focusable annotation subtypes or -1 on error.
+// Note : Annotations of type FPDF_ANNOT_WIDGET are by default focusable.
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFAnnot_GetFocusableSubtypesCount(FPDF_FORMHANDLE hHandle);
+
+// Experimental API.
+// Get the list of focusable annotation subtype as set by host.
+//
+//   hHandle  - handle to the form fill module, returned by
+//              FPDFDOC_InitFormFillEnvironment.
+//   subtypes - receives the list of annotation subtype which can be tabbed
+//              over. Caller must have allocated |subtypes| more than or
+//              equal to the count obtained from
+//              FPDFAnnot_GetFocusableSubtypesCount() API.
+//   count    - size of |subtypes|.
+// Returns true on success and set list of annotation subtype to |subtypes|,
+// false otherwise.
+// Note : Annotations of type FPDF_ANNOT_WIDGET are by default focusable.
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_GetFocusableSubtypes(FPDF_FORMHANDLE hHandle,
+                               FPDF_ANNOTATION_SUBTYPE* subtypes,
+                               size_t count);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif  // __cplusplus