Notify PDF UI about the focused state of PDF document
When focus transitions to or out of the PDF document, notify the PDF UI of the same. PDF UI needs the information to draw/hide the focus rectangle around the PDF document. Unit tests have been added to validate the scenario. Bug: 1069370 Change-Id: Ic25d79139ebf361d85168891580d14187610b0e0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2061928 Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Kevin Babbitt <kbabbitt@microsoft.com> Commit-Queue: Ankit Kumar 🌪️ <ankk@microsoft.com> Cr-Commit-Position: refs/heads/master@{#771295}
This commit is contained in:
chrome/browser/resources/pdf
pdf
@ -1291,6 +1291,9 @@ export class PDFViewer {
|
||||
type: 'touchSelectionOccurred',
|
||||
});
|
||||
return;
|
||||
case 'documentFocusChanged':
|
||||
// TODO(crbug.com/1069370): Draw a focus rect around plugin.
|
||||
return;
|
||||
}
|
||||
assertNotReached('Unknown message type received: ' + data.type);
|
||||
}
|
||||
|
@ -186,6 +186,10 @@ constexpr char kJSIsSelecting[] = "isSelecting";
|
||||
constexpr char kJSFieldFocusType[] = "formFocusChange";
|
||||
constexpr char kJSFieldFocus[] = "focused";
|
||||
|
||||
// Notify when document is focused (Plugin -> Page)
|
||||
constexpr char kJSDocumentFocusChangedType[] = "documentFocusChanged";
|
||||
constexpr char kJSDocumentHasFocus[] = "hasFocus";
|
||||
|
||||
constexpr int kFindResultCooldownMs = 100;
|
||||
|
||||
// Do not save forms with over 100 MB. This cap should be kept in sync with and
|
||||
@ -1934,6 +1938,13 @@ float OutOfProcessInstance::GetToolbarHeightInScreenCoords() {
|
||||
return top_toolbar_height_in_viewport_coords_ * device_scale_;
|
||||
}
|
||||
|
||||
void OutOfProcessInstance::DocumentFocusChanged(bool document_has_focus) {
|
||||
pp::VarDictionary message;
|
||||
message.Set(pp::Var(kType), pp::Var(kJSDocumentFocusChangedType));
|
||||
message.Set(pp::Var(kJSDocumentHasFocus), pp::Var(document_has_focus));
|
||||
PostMessage(message);
|
||||
}
|
||||
|
||||
void OutOfProcessInstance::ProcessPreviewPageInfo(const std::string& url,
|
||||
int dest_page_index) {
|
||||
DCHECK(IsPrintPreview());
|
||||
|
@ -146,6 +146,7 @@ class OutOfProcessInstance : public pp::Instance,
|
||||
void SelectionChanged(const pp::Rect& left, const pp::Rect& right) override;
|
||||
void IsEditModeChanged(bool is_edit_mode) override;
|
||||
float GetToolbarHeightInScreenCoords() override;
|
||||
void DocumentFocusChanged(bool document_has_focus) override;
|
||||
|
||||
// PreviewModeClient::Client implementation.
|
||||
void PreviewDocumentLoadComplete() override;
|
||||
|
@ -266,6 +266,9 @@ class PDFEngine {
|
||||
// Gets the height of the top toolbar in screen coordinates. This is
|
||||
// independent of whether it is hidden or not at the moment.
|
||||
virtual float GetToolbarHeightInScreenCoords() = 0;
|
||||
|
||||
// Notifies the client about focus changes for the document.
|
||||
virtual void DocumentFocusChanged(bool document_has_focus) {}
|
||||
};
|
||||
|
||||
struct AccessibilityLinkInfo {
|
||||
|
@ -947,7 +947,7 @@ void PDFiumEngine::KillFormFocus() {
|
||||
|
||||
void PDFiumEngine::UpdateFocus(bool has_focus) {
|
||||
if (has_focus) {
|
||||
focus_item_type_ = last_focused_item_type_;
|
||||
UpdateFocusItemType(last_focused_item_type_);
|
||||
if (focus_item_type_ == FocusElementType::kPage &&
|
||||
PageIndexInBounds(last_focused_page_) &&
|
||||
last_focused_annot_index_ != -1) {
|
||||
@ -961,7 +961,7 @@ void PDFiumEngine::UpdateFocus(bool has_focus) {
|
||||
} else {
|
||||
last_focused_item_type_ = focus_item_type_;
|
||||
if (focus_item_type_ == FocusElementType::kDocument) {
|
||||
focus_item_type_ = FocusElementType::kNone;
|
||||
UpdateFocusItemType(FocusElementType::kNone);
|
||||
} else if (focus_item_type_ == FocusElementType::kPage) {
|
||||
FPDF_ANNOTATION last_focused_annot = nullptr;
|
||||
FPDF_BOOL ret = FORM_GetFocusedAnnot(form(), &last_focused_page_,
|
||||
@ -1119,7 +1119,7 @@ bool PDFiumEngine::OnLeftMouseDown(const pp::MouseInputEvent& event) {
|
||||
return true;
|
||||
|
||||
if (page_index != -1) {
|
||||
focus_item_type_ = FocusElementType::kPage;
|
||||
UpdateFocusItemType(FocusElementType::kPage);
|
||||
last_focused_page_ = page_index;
|
||||
double page_x;
|
||||
double page_y;
|
||||
@ -3849,7 +3849,7 @@ bool PDFiumEngine::HandleTabEventWithModifiers(uint32_t modifiers) {
|
||||
|
||||
bool PDFiumEngine::HandleTabForward(uint32_t modifiers) {
|
||||
if (focus_item_type_ == FocusElementType::kNone) {
|
||||
focus_item_type_ = FocusElementType::kDocument;
|
||||
UpdateFocusItemType(FocusElementType::kDocument);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3867,17 +3867,17 @@ bool PDFiumEngine::HandleTabForward(uint32_t modifiers) {
|
||||
|
||||
if (did_tab_forward) {
|
||||
last_focused_page_ = page_index;
|
||||
focus_item_type_ = FocusElementType::kPage;
|
||||
UpdateFocusItemType(FocusElementType::kPage);
|
||||
} else {
|
||||
last_focused_page_ = -1;
|
||||
focus_item_type_ = FocusElementType::kNone;
|
||||
UpdateFocusItemType(FocusElementType::kNone);
|
||||
}
|
||||
return did_tab_forward;
|
||||
}
|
||||
|
||||
bool PDFiumEngine::HandleTabBackward(uint32_t modifiers) {
|
||||
if (focus_item_type_ == FocusElementType::kDocument) {
|
||||
focus_item_type_ = FocusElementType::kNone;
|
||||
UpdateFocusItemType(FocusElementType::kNone);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3895,7 +3895,7 @@ bool PDFiumEngine::HandleTabBackward(uint32_t modifiers) {
|
||||
|
||||
if (did_tab_backward) {
|
||||
last_focused_page_ = page_index;
|
||||
focus_item_type_ = FocusElementType::kPage;
|
||||
UpdateFocusItemType(FocusElementType::kPage);
|
||||
} else {
|
||||
// No focusable annotation found in pages. Possible scenarios:
|
||||
// Case 1: |focus_item_type_| is None. Since no object in any page can take
|
||||
@ -3908,11 +3908,11 @@ bool PDFiumEngine::HandleTabBackward(uint32_t modifiers) {
|
||||
case FocusElementType::kNone:
|
||||
did_tab_backward = true;
|
||||
last_focused_page_ = -1;
|
||||
focus_item_type_ = FocusElementType::kDocument;
|
||||
UpdateFocusItemType(FocusElementType::kDocument);
|
||||
KillFormFocus();
|
||||
break;
|
||||
case FocusElementType::kDocument:
|
||||
focus_item_type_ = FocusElementType::kNone;
|
||||
UpdateFocusItemType(FocusElementType::kNone);
|
||||
break;
|
||||
default:
|
||||
NOTREACHED();
|
||||
@ -3922,6 +3922,16 @@ bool PDFiumEngine::HandleTabBackward(uint32_t modifiers) {
|
||||
return did_tab_backward;
|
||||
}
|
||||
|
||||
void PDFiumEngine::UpdateFocusItemType(FocusElementType focus_item_type) {
|
||||
if (focus_item_type_ == focus_item_type)
|
||||
return;
|
||||
if (focus_item_type_ == FocusElementType::kDocument)
|
||||
client_->DocumentFocusChanged(false);
|
||||
focus_item_type_ = focus_item_type;
|
||||
if (focus_item_type_ == FocusElementType::kDocument)
|
||||
client_->DocumentFocusChanged(true);
|
||||
}
|
||||
|
||||
#if defined(PDF_ENABLE_XFA)
|
||||
void PDFiumEngine::UpdatePageCount() {
|
||||
InvalidateAllPages();
|
||||
|
@ -606,6 +606,10 @@ class PDFiumEngine : public PDFEngine,
|
||||
bool HandleTabForward(uint32_t modifiers);
|
||||
bool HandleTabBackward(uint32_t modifiers);
|
||||
|
||||
// Updates the currently focused object stored in |focus_item_type_|. Notifies
|
||||
// |client_| about document focus change, if any.
|
||||
void UpdateFocusItemType(FocusElementType focus_item_type);
|
||||
|
||||
void UpdateLinkUnderCursor(const std::string& target_url);
|
||||
void SetLinkUnderCursorForAnnotation(FPDF_ANNOTATION annot, int page_index);
|
||||
|
||||
|
@ -227,6 +227,17 @@ TEST_F(PDFiumEngineTest, GetBadPdfVersion) {
|
||||
|
||||
} // namespace
|
||||
|
||||
class TabbingTestClient : public TestClient {
|
||||
public:
|
||||
TabbingTestClient() = default;
|
||||
~TabbingTestClient() override = default;
|
||||
TabbingTestClient(const TabbingTestClient&) = delete;
|
||||
TabbingTestClient& operator=(const TabbingTestClient&) = delete;
|
||||
|
||||
// Mock PDFEngine::Client methods.
|
||||
MOCK_METHOD1(DocumentFocusChanged, void(bool));
|
||||
};
|
||||
|
||||
class PDFiumEngineTabbingTest : public PDFiumTestBase {
|
||||
public:
|
||||
PDFiumEngineTabbingTest() = default;
|
||||
@ -376,13 +387,20 @@ TEST_F(PDFiumEngineTabbingTest, TabbingForwardTest) {
|
||||
* ++ Page 2
|
||||
* ++++ Annotation
|
||||
*/
|
||||
TestClient client;
|
||||
TabbingTestClient client;
|
||||
std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
|
||||
&client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
|
||||
ASSERT_TRUE(engine);
|
||||
|
||||
ASSERT_EQ(2, engine->GetNumberOfPages());
|
||||
|
||||
static constexpr bool kExpectedFocusState[] = {true, false};
|
||||
{
|
||||
InSequence sequence;
|
||||
for (auto focused : kExpectedFocusState)
|
||||
EXPECT_CALL(client, DocumentFocusChanged(focused));
|
||||
}
|
||||
|
||||
ASSERT_EQ(PDFiumEngine::FocusElementType::kNone,
|
||||
GetFocusedElementType(engine.get()));
|
||||
EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
|
||||
@ -421,13 +439,20 @@ TEST_F(PDFiumEngineTabbingTest, TabbingBackwardTest) {
|
||||
* ++ Page 2
|
||||
* ++++ Annotation
|
||||
*/
|
||||
TestClient client;
|
||||
TabbingTestClient client;
|
||||
std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
|
||||
&client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
|
||||
ASSERT_TRUE(engine);
|
||||
|
||||
ASSERT_EQ(2, engine->GetNumberOfPages());
|
||||
|
||||
static constexpr bool kExpectedFocusState[] = {true, false};
|
||||
{
|
||||
InSequence sequence;
|
||||
for (auto focused : kExpectedFocusState)
|
||||
EXPECT_CALL(client, DocumentFocusChanged(focused));
|
||||
}
|
||||
|
||||
ASSERT_EQ(PDFiumEngine::FocusElementType::kNone,
|
||||
GetFocusedElementType(engine.get()));
|
||||
EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
|
||||
@ -510,13 +535,20 @@ TEST_F(PDFiumEngineTabbingTest, NoFocusableItemTabbingTest) {
|
||||
* ++ Page 1
|
||||
* ++ Page 2
|
||||
*/
|
||||
TestClient client;
|
||||
TabbingTestClient client;
|
||||
std::unique_ptr<PDFiumEngine> engine =
|
||||
InitializeEngine(&client, FILE_PATH_LITERAL("hello_world2.pdf"));
|
||||
ASSERT_TRUE(engine);
|
||||
|
||||
ASSERT_EQ(2, engine->GetNumberOfPages());
|
||||
|
||||
static constexpr bool kExpectedFocusState[] = {true, false, true, false};
|
||||
{
|
||||
InSequence sequence;
|
||||
for (auto focused : kExpectedFocusState)
|
||||
EXPECT_CALL(client, DocumentFocusChanged(focused));
|
||||
}
|
||||
|
||||
ASSERT_EQ(PDFiumEngine::FocusElementType::kNone,
|
||||
GetFocusedElementType(engine.get()));
|
||||
EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
|
||||
@ -550,13 +582,20 @@ TEST_F(PDFiumEngineTabbingTest, RestoringDocumentFocusTest) {
|
||||
* ++ Page 2
|
||||
* ++++ Annotation
|
||||
*/
|
||||
TestClient client;
|
||||
TabbingTestClient client;
|
||||
std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
|
||||
&client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
|
||||
ASSERT_TRUE(engine);
|
||||
|
||||
ASSERT_EQ(2, engine->GetNumberOfPages());
|
||||
|
||||
static constexpr bool kExpectedFocusState[] = {true, false, true};
|
||||
{
|
||||
InSequence sequence;
|
||||
for (auto focused : kExpectedFocusState)
|
||||
EXPECT_CALL(client, DocumentFocusChanged(focused));
|
||||
}
|
||||
|
||||
EXPECT_EQ(PDFiumEngine::FocusElementType::kNone,
|
||||
GetFocusedElementType(engine.get()));
|
||||
EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
|
||||
@ -588,13 +627,20 @@ TEST_F(PDFiumEngineTabbingTest, RestoringAnnotFocusTest) {
|
||||
* ++ Page 2
|
||||
* ++++ Annotation
|
||||
*/
|
||||
TestClient client;
|
||||
TabbingTestClient client;
|
||||
std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
|
||||
&client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
|
||||
ASSERT_TRUE(engine);
|
||||
|
||||
ASSERT_EQ(2, engine->GetNumberOfPages());
|
||||
|
||||
static constexpr bool kExpectedFocusState[] = {true, false};
|
||||
{
|
||||
InSequence sequence;
|
||||
for (auto focused : kExpectedFocusState)
|
||||
EXPECT_CALL(client, DocumentFocusChanged(focused));
|
||||
}
|
||||
|
||||
EXPECT_EQ(PDFiumEngine::FocusElementType::kNone,
|
||||
GetFocusedElementType(engine.get()));
|
||||
EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
|
||||
|
Reference in New Issue
Block a user