Commit 0ad537cd authored by thestig's avatar thestig Committed by Commit bot

PDF: Handle hit tests for form controls and links consistently.

BUG=434064

Review URL: https://codereview.chromium.org/969513002

Cr-Commit-Position: refs/heads/master@{#318748}
parent f265c257
...@@ -1614,25 +1614,27 @@ void PDFiumEngine::PrintEnd() { ...@@ -1614,25 +1614,27 @@ void PDFiumEngine::PrintEnd() {
FORM_DoDocumentAAction(form_, FPDFDOC_AACTION_DP); FORM_DoDocumentAAction(form_, FPDFDOC_AACTION_DP);
} }
PDFiumPage::Area PDFiumEngine::GetCharIndex( PDFiumPage::Area PDFiumEngine::GetCharIndex(const pp::MouseInputEvent& event,
const pp::MouseInputEvent& event, int* page_index, int* page_index,
int* char_index, PDFiumPage::LinkTarget* target) { int* char_index,
int* form_type,
PDFiumPage::LinkTarget* target) {
// First figure out which page this is in. // First figure out which page this is in.
pp::Point mouse_point = event.GetPosition(); pp::Point mouse_point = event.GetPosition();
pp::Point point( return GetCharIndex(mouse_point, page_index, char_index, form_type, target);
static_cast<int>((mouse_point.x() + position_.x()) / current_zoom_),
static_cast<int>((mouse_point.y() + position_.y()) / current_zoom_));
return GetCharIndex(point, page_index, char_index, target);
} }
PDFiumPage::Area PDFiumEngine::GetCharIndex( PDFiumPage::Area PDFiumEngine::GetCharIndex(const pp::Point& point,
const pp::Point& point, int* page_index,
int* page_index, int* char_index,
int* char_index, int* form_type,
PDFiumPage::LinkTarget* target) { PDFiumPage::LinkTarget* target) {
int page = -1; int page = -1;
pp::Point point_in_page(
static_cast<int>((point.x() + position_.x()) / current_zoom_),
static_cast<int>((point.y() + position_.y()) / current_zoom_));
for (size_t i = 0; i < visible_pages_.size(); ++i) { for (size_t i = 0; i < visible_pages_.size(); ++i) {
if (pages_[visible_pages_[i]]->rect().Contains(point)) { if (pages_[visible_pages_[i]]->rect().Contains(point_in_page)) {
page = visible_pages_[i]; page = visible_pages_[i];
break; break;
} }
...@@ -1648,15 +1650,11 @@ PDFiumPage::Area PDFiumEngine::GetCharIndex( ...@@ -1648,15 +1650,11 @@ PDFiumPage::Area PDFiumEngine::GetCharIndex(
} }
*page_index = page; *page_index = page;
return pages_[page]->GetCharIndex(point, current_rotation_, char_index, return pages_[page]->GetCharIndex(
target); point_in_page, current_rotation_, char_index, form_type, target);
} }
bool PDFiumEngine::OnMouseDown(const pp::MouseInputEvent& event) { bool PDFiumEngine::OnMouseDown(const pp::MouseInputEvent& event) {
if (event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_LEFT &&
event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_RIGHT) {
return false;
}
if (event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_RIGHT) { if (event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_RIGHT) {
if (!selection_.size()) if (!selection_.size())
return false; return false;
...@@ -1672,15 +1670,18 @@ bool PDFiumEngine::OnMouseDown(const pp::MouseInputEvent& event) { ...@@ -1672,15 +1670,18 @@ bool PDFiumEngine::OnMouseDown(const pp::MouseInputEvent& event) {
selection_.clear(); selection_.clear();
return true; return true;
} }
if (event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_LEFT)
return false;
SelectionChangeInvalidator selection_invalidator(this); SelectionChangeInvalidator selection_invalidator(this);
selection_.clear(); selection_.clear();
int page_index = -1; int page_index = -1;
int char_index = -1; int char_index = -1;
int form_type = FPDF_FORMFIELD_UNKNOWN;
PDFiumPage::LinkTarget target; PDFiumPage::LinkTarget target;
PDFiumPage::Area area = GetCharIndex(event, &page_index, PDFiumPage::Area area =
&char_index, &target); GetCharIndex(event, &page_index, &char_index, &form_type, &target);
mouse_down_state_.Set(area, target); mouse_down_state_.Set(area, target);
// Decide whether to open link or not based on user action in mouse up and // Decide whether to open link or not based on user action in mouse up and
...@@ -1701,16 +1702,14 @@ bool PDFiumEngine::OnMouseDown(const pp::MouseInputEvent& event) { ...@@ -1701,16 +1702,14 @@ bool PDFiumEngine::OnMouseDown(const pp::MouseInputEvent& event) {
DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y); DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y);
FORM_OnLButtonDown(form_, pages_[page_index]->GetPage(), 0, page_x, page_y); FORM_OnLButtonDown(form_, pages_[page_index]->GetPage(), 0, page_x, page_y);
int control = FPDPage_HasFormFieldAtPoint( if (form_type > FPDF_FORMFIELD_UNKNOWN) { // returns -1 sometimes...
form_, pages_[page_index]->GetPage(), page_x, page_y); mouse_down_state_.Set(PDFiumPage::NONSELECTABLE_AREA, target);
if (control > FPDF_FORMFIELD_UNKNOWN) { // returns -1 sometimes... bool is_valid_control = (form_type == FPDF_FORMFIELD_TEXTFIELD ||
form_type == FPDF_FORMFIELD_COMBOBOX);
#ifdef PDF_USE_XFA #ifdef PDF_USE_XFA
client_->FormTextFieldFocusChange(control == FPDF_FORMFIELD_TEXTFIELD || is_valid_control |= (form_type == FPDF_FORMFIELD_XFA);
control == FPDF_FORMFIELD_COMBOBOX || control == FPDF_FORMFIELD_XFA);
#else
client_->FormTextFieldFocusChange(control == FPDF_FORMFIELD_TEXTFIELD ||
control == FPDF_FORMFIELD_COMBOBOX);
#endif #endif
client_->FormTextFieldFocusChange(is_valid_control);
return true; // Return now before we get into the selection code. return true; // Return now before we get into the selection code.
} }
} }
...@@ -1769,9 +1768,10 @@ bool PDFiumEngine::OnMouseUp(const pp::MouseInputEvent& event) { ...@@ -1769,9 +1768,10 @@ bool PDFiumEngine::OnMouseUp(const pp::MouseInputEvent& event) {
int page_index = -1; int page_index = -1;
int char_index = -1; int char_index = -1;
int form_type = FPDF_FORMFIELD_UNKNOWN;
PDFiumPage::LinkTarget target; PDFiumPage::LinkTarget target;
PDFiumPage::Area area = PDFiumPage::Area area =
GetCharIndex(event, &page_index, &char_index, &target); GetCharIndex(event, &page_index, &char_index, &form_type, &target);
// Open link on mouse up for same link for which mouse down happened earlier. // Open link on mouse up for same link for which mouse down happened earlier.
if (mouse_down_state_.Matches(area, target)) { if (mouse_down_state_.Matches(area, target)) {
...@@ -1801,9 +1801,10 @@ bool PDFiumEngine::OnMouseUp(const pp::MouseInputEvent& event) { ...@@ -1801,9 +1801,10 @@ bool PDFiumEngine::OnMouseUp(const pp::MouseInputEvent& event) {
bool PDFiumEngine::OnMouseMove(const pp::MouseInputEvent& event) { bool PDFiumEngine::OnMouseMove(const pp::MouseInputEvent& event) {
int page_index = -1; int page_index = -1;
int char_index = -1; int char_index = -1;
int form_type = FPDF_FORMFIELD_UNKNOWN;
PDFiumPage::LinkTarget target; PDFiumPage::LinkTarget target;
PDFiumPage::Area area = PDFiumPage::Area area =
GetCharIndex(event, &page_index, &char_index, &target); GetCharIndex(event, &page_index, &char_index, &form_type, &target);
// Clear |mouse_down_state_| if mouse moves away from where the mouse down // Clear |mouse_down_state_| if mouse moves away from where the mouse down
// happened. // happened.
...@@ -1822,7 +1823,21 @@ bool PDFiumEngine::OnMouseMove(const pp::MouseInputEvent& event) { ...@@ -1822,7 +1823,21 @@ bool PDFiumEngine::OnMouseMove(const pp::MouseInputEvent& event) {
break; break;
case PDFiumPage::NONSELECTABLE_AREA: case PDFiumPage::NONSELECTABLE_AREA:
default: default:
cursor = PP_CURSORTYPE_POINTER; switch (form_type) {
case FPDF_FORMFIELD_PUSHBUTTON:
case FPDF_FORMFIELD_CHECKBOX:
case FPDF_FORMFIELD_RADIOBUTTON:
case FPDF_FORMFIELD_COMBOBOX:
case FPDF_FORMFIELD_LISTBOX:
cursor = PP_CURSORTYPE_HAND;
break;
case FPDF_FORMFIELD_TEXTFIELD:
cursor = PP_CURSORTYPE_IBEAM;
break;
default:
cursor = PP_CURSORTYPE_POINTER;
break;
}
break; break;
} }
...@@ -1830,24 +1845,7 @@ bool PDFiumEngine::OnMouseMove(const pp::MouseInputEvent& event) { ...@@ -1830,24 +1845,7 @@ bool PDFiumEngine::OnMouseMove(const pp::MouseInputEvent& event) {
double page_x, page_y; double page_x, page_y;
pp::Point point = event.GetPosition(); pp::Point point = event.GetPosition();
DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y); DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y);
FORM_OnMouseMove(form_, pages_[page_index]->GetPage(), 0, page_x, page_y); FORM_OnMouseMove(form_, pages_[page_index]->GetPage(), 0, page_x, page_y);
int control = FPDPage_HasFormFieldAtPoint(
form_, pages_[page_index]->GetPage(), page_x, page_y);
switch (control) {
case FPDF_FORMFIELD_PUSHBUTTON:
case FPDF_FORMFIELD_CHECKBOX:
case FPDF_FORMFIELD_RADIOBUTTON:
case FPDF_FORMFIELD_COMBOBOX:
case FPDF_FORMFIELD_LISTBOX:
cursor = PP_CURSORTYPE_HAND;
break;
case FPDF_FORMFIELD_TEXTFIELD:
cursor = PP_CURSORTYPE_IBEAM;
break;
default:
break;
}
} }
client_->UpdateCursor(cursor); client_->UpdateCursor(cursor);
...@@ -2321,15 +2319,16 @@ std::string PDFiumEngine::GetSelectedText() { ...@@ -2321,15 +2319,16 @@ std::string PDFiumEngine::GetSelectedText() {
} }
std::string PDFiumEngine::GetLinkAtPosition(const pp::Point& point) { std::string PDFiumEngine::GetLinkAtPosition(const pp::Point& point) {
std::string url;
int temp; int temp;
int page_index = -1;
int form_type = FPDF_FORMFIELD_UNKNOWN;
PDFiumPage::LinkTarget target; PDFiumPage::LinkTarget target;
pp::Point point_in_page( PDFiumPage::Area area =
static_cast<int>((point.x() + position_.x()) / current_zoom_), GetCharIndex(point, &page_index, &temp, &form_type, &target);
static_cast<int>((point.y() + position_.y()) / current_zoom_));
PDFiumPage::Area area = GetCharIndex(point_in_page, &temp, &temp, &target);
if (area == PDFiumPage::WEBLINK_AREA) if (area == PDFiumPage::WEBLINK_AREA)
return target.url; url = target.url;
return std::string(); return url;
} }
bool PDFiumEngine::IsSelecting() { bool PDFiumEngine::IsSelecting() {
......
...@@ -310,10 +310,12 @@ class PDFiumEngine : public PDFEngine, ...@@ -310,10 +310,12 @@ class PDFiumEngine : public PDFEngine,
PDFiumPage::Area GetCharIndex(const pp::MouseInputEvent& event, PDFiumPage::Area GetCharIndex(const pp::MouseInputEvent& event,
int* page_index, int* page_index,
int* char_index, int* char_index,
int* form_type,
PDFiumPage::LinkTarget* target); PDFiumPage::LinkTarget* target);
PDFiumPage::Area GetCharIndex(const pp::Point& point, PDFiumPage::Area GetCharIndex(const pp::Point& point,
int* page_index, int* page_index,
int* char_index, int* char_index,
int* form_type,
PDFiumPage::LinkTarget* target); PDFiumPage::LinkTarget* target);
void OnSingleClick(int page_index, int char_index); void OnSingleClick(int page_index, int char_index);
......
...@@ -258,6 +258,7 @@ base::Value* PDFiumPage::CreateURLNode(std::string text, std::string url) { ...@@ -258,6 +258,7 @@ base::Value* PDFiumPage::CreateURLNode(std::string text, std::string url) {
PDFiumPage::Area PDFiumPage::GetCharIndex(const pp::Point& point, PDFiumPage::Area PDFiumPage::GetCharIndex(const pp::Point& point,
int rotation, int rotation,
int* char_index, int* char_index,
int* form_type,
LinkTarget* target) { LinkTarget* target) {
if (!available_) if (!available_)
return NONSELECTABLE_AREA; return NONSELECTABLE_AREA;
...@@ -270,6 +271,13 @@ PDFiumPage::Area PDFiumPage::GetCharIndex(const pp::Point& point, ...@@ -270,6 +271,13 @@ PDFiumPage::Area PDFiumPage::GetCharIndex(const pp::Point& point,
GetTextPage(), new_x, new_y, kTolerance, kTolerance); GetTextPage(), new_x, new_y, kTolerance, kTolerance);
*char_index = rv; *char_index = rv;
int control =
FPDPage_HasFormFieldAtPoint(engine_->form(), GetPage(), new_x, new_y);
if (control > FPDF_FORMFIELD_UNKNOWN) {
*form_type = control;
return PDFiumPage::NONSELECTABLE_AREA;
}
FPDF_LINK link = FPDFLink_GetLinkAtPoint(GetPage(), new_x, new_y); FPDF_LINK link = FPDFLink_GetLinkAtPoint(GetPage(), new_x, new_y);
if (link) { if (link) {
// We don't handle all possible link types of the PDF. For example, // We don't handle all possible link types of the PDF. For example,
......
...@@ -64,7 +64,7 @@ class PDFiumPage { ...@@ -64,7 +64,7 @@ class PDFiumPage {
// Target is optional. It will be filled in for WEBLINK_AREA or // Target is optional. It will be filled in for WEBLINK_AREA or
// DOCLINK_AREA only. // DOCLINK_AREA only.
Area GetCharIndex(const pp::Point& point, int rotation, int* char_index, Area GetCharIndex(const pp::Point& point, int rotation, int* char_index,
LinkTarget* target); int* form_type, LinkTarget* target);
// Gets the character at the given index. // Gets the character at the given index.
base::char16 GetCharAtIndex(int index); base::char16 GetCharAtIndex(int index);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment