Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: pdf/pdfium/pdfium_engine.cc

Issue 969513002: PDF: Handle hit tests for form controls and links consistently. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "pdf/pdfium/pdfium_engine.h" 5 #include "pdf/pdfium/pdfium_engine.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 1596 matching lines...) Expand 10 before | Expand all | Expand 10 after
1607 1607
1608 void PDFiumEngine::SaveSelectedFormForPrint() { 1608 void PDFiumEngine::SaveSelectedFormForPrint() {
1609 FORM_ForceToKillFocus(form_); 1609 FORM_ForceToKillFocus(form_);
1610 client_->FormTextFieldFocusChange(false); 1610 client_->FormTextFieldFocusChange(false);
1611 } 1611 }
1612 1612
1613 void PDFiumEngine::PrintEnd() { 1613 void PDFiumEngine::PrintEnd() {
1614 FORM_DoDocumentAAction(form_, FPDFDOC_AACTION_DP); 1614 FORM_DoDocumentAAction(form_, FPDFDOC_AACTION_DP);
1615 } 1615 }
1616 1616
1617 PDFiumPage::Area PDFiumEngine::GetCharIndex( 1617 PDFiumPage::Area PDFiumEngine::GetCharIndex(const pp::MouseInputEvent& event,
1618 const pp::MouseInputEvent& event, int* page_index, 1618 int* page_index,
1619 int* char_index, PDFiumPage::LinkTarget* target) { 1619 int* char_index,
1620 int* form_type,
1621 PDFiumPage::LinkTarget* target) {
1620 // First figure out which page this is in. 1622 // First figure out which page this is in.
1621 pp::Point mouse_point = event.GetPosition(); 1623 pp::Point mouse_point = event.GetPosition();
1622 pp::Point point( 1624 return GetCharIndex(mouse_point, page_index, char_index, form_type, target);
1623 static_cast<int>((mouse_point.x() + position_.x()) / current_zoom_),
1624 static_cast<int>((mouse_point.y() + position_.y()) / current_zoom_));
1625 return GetCharIndex(point, page_index, char_index, target);
1626 } 1625 }
1627 1626
1628 PDFiumPage::Area PDFiumEngine::GetCharIndex( 1627 PDFiumPage::Area PDFiumEngine::GetCharIndex(const pp::Point& point,
1629 const pp::Point& point, 1628 int* page_index,
1630 int* page_index, 1629 int* char_index,
1631 int* char_index, 1630 int* form_type,
1632 PDFiumPage::LinkTarget* target) { 1631 PDFiumPage::LinkTarget* target) {
1633 int page = -1; 1632 int page = -1;
1633 pp::Point point_in_page(
1634 static_cast<int>((point.x() + position_.x()) / current_zoom_),
1635 static_cast<int>((point.y() + position_.y()) / current_zoom_));
1634 for (size_t i = 0; i < visible_pages_.size(); ++i) { 1636 for (size_t i = 0; i < visible_pages_.size(); ++i) {
1635 if (pages_[visible_pages_[i]]->rect().Contains(point)) { 1637 if (pages_[visible_pages_[i]]->rect().Contains(point_in_page)) {
1636 page = visible_pages_[i]; 1638 page = visible_pages_[i];
1637 break; 1639 break;
1638 } 1640 }
1639 } 1641 }
1640 if (page == -1) 1642 if (page == -1)
1641 return PDFiumPage::NONSELECTABLE_AREA; 1643 return PDFiumPage::NONSELECTABLE_AREA;
1642 1644
1643 // If the page hasn't finished rendering, calling into the page sometimes 1645 // If the page hasn't finished rendering, calling into the page sometimes
1644 // leads to hangs. 1646 // leads to hangs.
1645 for (size_t i = 0; i < progressive_paints_.size(); ++i) { 1647 for (size_t i = 0; i < progressive_paints_.size(); ++i) {
1646 if (progressive_paints_[i].page_index == page) 1648 if (progressive_paints_[i].page_index == page)
1647 return PDFiumPage::NONSELECTABLE_AREA; 1649 return PDFiumPage::NONSELECTABLE_AREA;
1648 } 1650 }
1649 1651
1650 *page_index = page; 1652 *page_index = page;
1651 return pages_[page]->GetCharIndex(point, current_rotation_, char_index, 1653 return pages_[page]->GetCharIndex(
1652 target); 1654 point_in_page, current_rotation_, char_index, form_type, target);
1653 } 1655 }
1654 1656
1655 bool PDFiumEngine::OnMouseDown(const pp::MouseInputEvent& event) { 1657 bool PDFiumEngine::OnMouseDown(const pp::MouseInputEvent& event) {
1656 if (event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_LEFT &&
1657 event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_RIGHT) {
1658 return false;
1659 }
1660 if (event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_RIGHT) { 1658 if (event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_RIGHT) {
1661 if (!selection_.size()) 1659 if (!selection_.size())
1662 return false; 1660 return false;
1663 std::vector<pp::Rect> selection_rect_vector; 1661 std::vector<pp::Rect> selection_rect_vector;
1664 GetAllScreenRectsUnion(&selection_, GetVisibleRect().point(), 1662 GetAllScreenRectsUnion(&selection_, GetVisibleRect().point(),
1665 &selection_rect_vector); 1663 &selection_rect_vector);
1666 pp::Point point = event.GetPosition(); 1664 pp::Point point = event.GetPosition();
1667 for (size_t i = 0; i < selection_rect_vector.size(); ++i) { 1665 for (size_t i = 0; i < selection_rect_vector.size(); ++i) {
1668 if (selection_rect_vector[i].Contains(point.x(), point.y())) 1666 if (selection_rect_vector[i].Contains(point.x(), point.y()))
1669 return false; 1667 return false;
1670 } 1668 }
1671 SelectionChangeInvalidator selection_invalidator(this); 1669 SelectionChangeInvalidator selection_invalidator(this);
1672 selection_.clear(); 1670 selection_.clear();
1673 return true; 1671 return true;
1674 } 1672 }
1673 if (event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_LEFT)
1674 return false;
1675 1675
1676 SelectionChangeInvalidator selection_invalidator(this); 1676 SelectionChangeInvalidator selection_invalidator(this);
1677 selection_.clear(); 1677 selection_.clear();
1678 1678
1679 int page_index = -1; 1679 int page_index = -1;
1680 int char_index = -1; 1680 int char_index = -1;
1681 int form_type = FPDF_FORMFIELD_UNKNOWN;
1681 PDFiumPage::LinkTarget target; 1682 PDFiumPage::LinkTarget target;
1682 PDFiumPage::Area area = GetCharIndex(event, &page_index, 1683 PDFiumPage::Area area =
1683 &char_index, &target); 1684 GetCharIndex(event, &page_index, &char_index, &form_type, &target);
1684 mouse_down_state_.Set(area, target); 1685 mouse_down_state_.Set(area, target);
1685 1686
1686 // Decide whether to open link or not based on user action in mouse up and 1687 // Decide whether to open link or not based on user action in mouse up and
1687 // mouse move events. 1688 // mouse move events.
1688 if (area == PDFiumPage::WEBLINK_AREA) 1689 if (area == PDFiumPage::WEBLINK_AREA)
1689 return true; 1690 return true;
1690 1691
1691 if (area == PDFiumPage::DOCLINK_AREA) { 1692 if (area == PDFiumPage::DOCLINK_AREA) {
1692 client_->ScrollToPage(target.page); 1693 client_->ScrollToPage(target.page);
1693 client_->FormTextFieldFocusChange(false); 1694 client_->FormTextFieldFocusChange(false);
1694 return true; 1695 return true;
1695 } 1696 }
1696 1697
1697 if (page_index != -1) { 1698 if (page_index != -1) {
1698 last_page_mouse_down_ = page_index; 1699 last_page_mouse_down_ = page_index;
1699 double page_x, page_y; 1700 double page_x, page_y;
1700 pp::Point point = event.GetPosition(); 1701 pp::Point point = event.GetPosition();
1701 DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y); 1702 DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y);
1702 1703
1703 FORM_OnLButtonDown(form_, pages_[page_index]->GetPage(), 0, page_x, page_y); 1704 FORM_OnLButtonDown(form_, pages_[page_index]->GetPage(), 0, page_x, page_y);
1704 int control = FPDPage_HasFormFieldAtPoint( 1705 if (form_type > FPDF_FORMFIELD_UNKNOWN) { // returns -1 sometimes...
1705 form_, pages_[page_index]->GetPage(), page_x, page_y); 1706 mouse_down_state_.Set(PDFiumPage::NONSELECTABLE_AREA, target);
1706 if (control > FPDF_FORMFIELD_UNKNOWN) { // returns -1 sometimes... 1707 bool is_valid_control = (form_type == FPDF_FORMFIELD_TEXTFIELD ||
1708 form_type == FPDF_FORMFIELD_COMBOBOX);
1707 #ifdef PDF_USE_XFA 1709 #ifdef PDF_USE_XFA
1708 client_->FormTextFieldFocusChange(control == FPDF_FORMFIELD_TEXTFIELD || 1710 is_valid_control |= (form_type == FPDF_FORMFIELD_XFA);
1709 control == FPDF_FORMFIELD_COMBOBOX || control == FPDF_FORMFIELD_XFA);
1710 #else
1711 client_->FormTextFieldFocusChange(control == FPDF_FORMFIELD_TEXTFIELD ||
1712 control == FPDF_FORMFIELD_COMBOBOX);
1713 #endif 1711 #endif
1712 client_->FormTextFieldFocusChange(is_valid_control);
1714 return true; // Return now before we get into the selection code. 1713 return true; // Return now before we get into the selection code.
1715 } 1714 }
1716 } 1715 }
1717 1716
1718 client_->FormTextFieldFocusChange(false); 1717 client_->FormTextFieldFocusChange(false);
1719 1718
1720 if (area != PDFiumPage::TEXT_AREA) 1719 if (area != PDFiumPage::TEXT_AREA)
1721 return true; // Return true so WebKit doesn't do its own highlighting. 1720 return true; // Return true so WebKit doesn't do its own highlighting.
1722 1721
1723 if (event.GetClickCount() == 1) { 1722 if (event.GetClickCount() == 1) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1762 selection_.push_back(PDFiumRange( 1761 selection_.push_back(PDFiumRange(
1763 pages_[page_index], start_index, end_index - start_index)); 1762 pages_[page_index], start_index, end_index - start_index));
1764 } 1763 }
1765 1764
1766 bool PDFiumEngine::OnMouseUp(const pp::MouseInputEvent& event) { 1765 bool PDFiumEngine::OnMouseUp(const pp::MouseInputEvent& event) {
1767 if (event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_LEFT) 1766 if (event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_LEFT)
1768 return false; 1767 return false;
1769 1768
1770 int page_index = -1; 1769 int page_index = -1;
1771 int char_index = -1; 1770 int char_index = -1;
1771 int form_type = FPDF_FORMFIELD_UNKNOWN;
1772 PDFiumPage::LinkTarget target; 1772 PDFiumPage::LinkTarget target;
1773 PDFiumPage::Area area = 1773 PDFiumPage::Area area =
1774 GetCharIndex(event, &page_index, &char_index, &target); 1774 GetCharIndex(event, &page_index, &char_index, &form_type, &target);
1775 1775
1776 // Open link on mouse up for same link for which mouse down happened earlier. 1776 // Open link on mouse up for same link for which mouse down happened earlier.
1777 if (mouse_down_state_.Matches(area, target)) { 1777 if (mouse_down_state_.Matches(area, target)) {
1778 if (area == PDFiumPage::WEBLINK_AREA) { 1778 if (area == PDFiumPage::WEBLINK_AREA) {
1779 bool open_in_new_tab = !!(event.GetModifiers() & kDefaultKeyModifier); 1779 bool open_in_new_tab = !!(event.GetModifiers() & kDefaultKeyModifier);
1780 client_->NavigateTo(target.url, open_in_new_tab); 1780 client_->NavigateTo(target.url, open_in_new_tab);
1781 client_->FormTextFieldFocusChange(false); 1781 client_->FormTextFieldFocusChange(false);
1782 return true; 1782 return true;
1783 } 1783 }
1784 } 1784 }
1785 1785
1786 if (page_index != -1) { 1786 if (page_index != -1) {
1787 double page_x, page_y; 1787 double page_x, page_y;
1788 pp::Point point = event.GetPosition(); 1788 pp::Point point = event.GetPosition();
1789 DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y); 1789 DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y);
1790 FORM_OnLButtonUp( 1790 FORM_OnLButtonUp(
1791 form_, pages_[page_index]->GetPage(), 0, page_x, page_y); 1791 form_, pages_[page_index]->GetPage(), 0, page_x, page_y);
1792 } 1792 }
1793 1793
1794 if (!selecting_) 1794 if (!selecting_)
1795 return false; 1795 return false;
1796 1796
1797 SetSelecting(false); 1797 SetSelecting(false);
1798 return true; 1798 return true;
1799 } 1799 }
1800 1800
1801 bool PDFiumEngine::OnMouseMove(const pp::MouseInputEvent& event) { 1801 bool PDFiumEngine::OnMouseMove(const pp::MouseInputEvent& event) {
1802 int page_index = -1; 1802 int page_index = -1;
1803 int char_index = -1; 1803 int char_index = -1;
1804 int form_type = FPDF_FORMFIELD_UNKNOWN;
1804 PDFiumPage::LinkTarget target; 1805 PDFiumPage::LinkTarget target;
1805 PDFiumPage::Area area = 1806 PDFiumPage::Area area =
1806 GetCharIndex(event, &page_index, &char_index, &target); 1807 GetCharIndex(event, &page_index, &char_index, &form_type, &target);
1807 1808
1808 // Clear |mouse_down_state_| if mouse moves away from where the mouse down 1809 // Clear |mouse_down_state_| if mouse moves away from where the mouse down
1809 // happened. 1810 // happened.
1810 if (!mouse_down_state_.Matches(area, target)) 1811 if (!mouse_down_state_.Matches(area, target))
1811 mouse_down_state_.Reset(); 1812 mouse_down_state_.Reset();
1812 1813
1813 if (!selecting_) { 1814 if (!selecting_) {
1814 PP_CursorType_Dev cursor; 1815 PP_CursorType_Dev cursor;
1815 switch (area) { 1816 switch (area) {
1816 case PDFiumPage::TEXT_AREA: 1817 case PDFiumPage::TEXT_AREA:
1817 cursor = PP_CURSORTYPE_IBEAM; 1818 cursor = PP_CURSORTYPE_IBEAM;
1818 break; 1819 break;
1819 case PDFiumPage::WEBLINK_AREA: 1820 case PDFiumPage::WEBLINK_AREA:
1820 case PDFiumPage::DOCLINK_AREA: 1821 case PDFiumPage::DOCLINK_AREA:
1821 cursor = PP_CURSORTYPE_HAND; 1822 cursor = PP_CURSORTYPE_HAND;
1822 break; 1823 break;
1823 case PDFiumPage::NONSELECTABLE_AREA: 1824 case PDFiumPage::NONSELECTABLE_AREA:
1824 default: 1825 default:
1825 cursor = PP_CURSORTYPE_POINTER; 1826 switch (form_type) {
1827 case FPDF_FORMFIELD_PUSHBUTTON:
1828 case FPDF_FORMFIELD_CHECKBOX:
1829 case FPDF_FORMFIELD_RADIOBUTTON:
1830 case FPDF_FORMFIELD_COMBOBOX:
1831 case FPDF_FORMFIELD_LISTBOX:
1832 cursor = PP_CURSORTYPE_HAND;
1833 break;
1834 case FPDF_FORMFIELD_TEXTFIELD:
1835 cursor = PP_CURSORTYPE_IBEAM;
1836 break;
1837 default:
1838 cursor = PP_CURSORTYPE_POINTER;
1839 break;
1840 }
1826 break; 1841 break;
1827 } 1842 }
1828 1843
1829 if (page_index != -1) { 1844 if (page_index != -1) {
1830 double page_x, page_y; 1845 double page_x, page_y;
1831 pp::Point point = event.GetPosition(); 1846 pp::Point point = event.GetPosition();
1832 DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y); 1847 DeviceToPage(page_index, point.x(), point.y(), &page_x, &page_y);
1833
1834 FORM_OnMouseMove(form_, pages_[page_index]->GetPage(), 0, page_x, page_y); 1848 FORM_OnMouseMove(form_, pages_[page_index]->GetPage(), 0, page_x, page_y);
1835 int control = FPDPage_HasFormFieldAtPoint(
1836 form_, pages_[page_index]->GetPage(), page_x, page_y);
1837 switch (control) {
1838 case FPDF_FORMFIELD_PUSHBUTTON:
1839 case FPDF_FORMFIELD_CHECKBOX:
1840 case FPDF_FORMFIELD_RADIOBUTTON:
1841 case FPDF_FORMFIELD_COMBOBOX:
1842 case FPDF_FORMFIELD_LISTBOX:
1843 cursor = PP_CURSORTYPE_HAND;
1844 break;
1845 case FPDF_FORMFIELD_TEXTFIELD:
1846 cursor = PP_CURSORTYPE_IBEAM;
1847 break;
1848 default:
1849 break;
1850 }
1851 } 1849 }
1852 1850
1853 client_->UpdateCursor(cursor); 1851 client_->UpdateCursor(cursor);
1854 pp::Point point = event.GetPosition(); 1852 pp::Point point = event.GetPosition();
1855 std::string url = GetLinkAtPosition(event.GetPosition()); 1853 std::string url = GetLinkAtPosition(event.GetPosition());
1856 if (url != link_under_cursor_) { 1854 if (url != link_under_cursor_) {
1857 link_under_cursor_ = url; 1855 link_under_cursor_ = url;
1858 pp::PDF::SetLinkUnderCursor(GetPluginInstance(), url.c_str()); 1856 pp::PDF::SetLinkUnderCursor(GetPluginInstance(), url.c_str());
1859 } 1857 }
1860 // No need to swallow the event, since this might interfere with the 1858 // No need to swallow the event, since this might interfere with the
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
2314 result.append(selection_[i].GetText()); 2312 result.append(selection_[i].GetText());
2315 } 2313 }
2316 } 2314 }
2317 2315
2318 FormatStringWithHyphens(&result); 2316 FormatStringWithHyphens(&result);
2319 FormatStringForOS(&result); 2317 FormatStringForOS(&result);
2320 return base::UTF16ToUTF8(result); 2318 return base::UTF16ToUTF8(result);
2321 } 2319 }
2322 2320
2323 std::string PDFiumEngine::GetLinkAtPosition(const pp::Point& point) { 2321 std::string PDFiumEngine::GetLinkAtPosition(const pp::Point& point) {
2322 std::string url;
2324 int temp; 2323 int temp;
2324 int page_index = -1;
2325 int form_type = FPDF_FORMFIELD_UNKNOWN;
2325 PDFiumPage::LinkTarget target; 2326 PDFiumPage::LinkTarget target;
2326 pp::Point point_in_page( 2327 PDFiumPage::Area area =
2327 static_cast<int>((point.x() + position_.x()) / current_zoom_), 2328 GetCharIndex(point, &page_index, &temp, &form_type, &target);
2328 static_cast<int>((point.y() + position_.y()) / current_zoom_));
2329 PDFiumPage::Area area = GetCharIndex(point_in_page, &temp, &temp, &target);
2330 if (area == PDFiumPage::WEBLINK_AREA) 2329 if (area == PDFiumPage::WEBLINK_AREA)
2331 return target.url; 2330 url = target.url;
2332 return std::string(); 2331 return url;
2333 } 2332 }
2334 2333
2335 bool PDFiumEngine::IsSelecting() { 2334 bool PDFiumEngine::IsSelecting() {
2336 return selecting_; 2335 return selecting_;
2337 } 2336 }
2338 2337
2339 bool PDFiumEngine::HasPermission(DocumentPermission permission) const { 2338 bool PDFiumEngine::HasPermission(DocumentPermission permission) const {
2340 switch (permission) { 2339 switch (permission) {
2341 case PERMISSION_COPY: 2340 case PERMISSION_COPY:
2342 return (permissions_ & kPDFPermissionCopyMask) != 0; 2341 return (permissions_ & kPDFPermissionCopyMask) != 0;
(...skipping 1657 matching lines...) Expand 10 before | Expand all | Expand 10 after
4000 double* height) { 3999 double* height) {
4001 FPDF_DOCUMENT doc = FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, NULL); 4000 FPDF_DOCUMENT doc = FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, NULL);
4002 if (!doc) 4001 if (!doc)
4003 return false; 4002 return false;
4004 bool success = FPDF_GetPageSizeByIndex(doc, page_number, width, height) != 0; 4003 bool success = FPDF_GetPageSizeByIndex(doc, page_number, width, height) != 0;
4005 FPDF_CloseDocument(doc); 4004 FPDF_CloseDocument(doc);
4006 return success; 4005 return success;
4007 } 4006 }
4008 4007
4009 } // namespace chrome_pdf 4008 } // namespace chrome_pdf
OLDNEW
« no previous file with comments | « pdf/pdfium/pdfium_engine.h ('k') | pdf/pdfium/pdfium_page.h » ('j') | pdf/pdfium/pdfium_page.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698