From a54693351666528c2f279be1c1a5e6ab9afd3b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Mon, 15 Feb 2016 15:48:56 +0100 Subject: [PATCH 01/16] hints: use getClientRects() JS method to get the correct click position --- qutebrowser/browser/hints.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index c9a722dc6..b38fc5c0c 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -26,7 +26,7 @@ import re import string from PyQt5.QtCore import (pyqtSignal, pyqtSlot, QObject, QEvent, Qt, QUrl, - QTimer) + QTimer, QPoint) from PyQt5.QtGui import QMouseEvent from PyQt5.QtWebKit import QWebElement from PyQt5.QtWebKitWidgets import QWebPage @@ -438,14 +438,31 @@ class HintManager(QObject): target_mapping[Target.tab] = usertypes.ClickTarget.tab_bg else: target_mapping[Target.tab] = usertypes.ClickTarget.tab + + action = "Hovering" if context.target == Target.hover else "Clicking" + log.hints.debug("{} on element '{}'".format(action, elem.debug_text())) + # FIXME Instead of clicking the center, we could have nicer heuristics. # e.g. parse (-webkit-)border-radius correctly and click text fields at # the bottom right, and everything else on the top left or so. # https://github.com/The-Compiler/qutebrowser/issues/70 pos = elem.rect_on_view().center() - action = "Hovering" if context.target == Target.hover else "Clicking" - log.hints.debug("{} on '{}' at {}/{}".format( - action, elem, pos.x(), pos.y())) + log.hints.debug("Center position: {}".format(pos)) + boxes = elem.evaluateJavaScript("this.getClientRects()") + log.hints.debug("Bounding boxes: {}".format(boxes)) + for key in sorted(boxes): + box = boxes[key] + width = box.get("width", 0) + height = box.get("height", 0) + # skip boxes with zero dimensions (happens to if they contain + # other elements with display:block style) + # https://github.com/The-Compiler/qutebrowser/issues/1298 + if width > 0 and height > 0: + pos = QPoint(box["left"] + width / 2, box["top"] + height / 2) + log.hints.debug("Updated position: {}".format(pos)) + break + log.hints.debug("Final position is {}".format(pos)) + self.start_hinting.emit(target_mapping[context.target]) if context.target in [Target.tab, Target.tab_fg, Target.tab_bg, Target.window]: From 748ec043fbb9337becd5430ef3c962da289bc94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Mon, 15 Feb 2016 19:02:29 +0100 Subject: [PATCH 02/16] hints: add tests for links known to cause troubles --- tests/integration/data/hello4.txt | 1 + tests/integration/data/hints/link.html | 46 ++++++++++++++++++++++- tests/integration/features/hints.feature | 48 ++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 tests/integration/data/hello4.txt diff --git a/tests/integration/data/hello4.txt b/tests/integration/data/hello4.txt new file mode 100644 index 000000000..a31ec61e8 --- /dev/null +++ b/tests/integration/data/hello4.txt @@ -0,0 +1 @@ +Hello World 4! diff --git a/tests/integration/data/hints/link.html b/tests/integration/data/hints/link.html index ec4f9f38c..2dc96b280 100644 --- a/tests/integration/data/hints/link.html +++ b/tests/integration/data/hints/link.html @@ -3,8 +3,52 @@ A link to use hints on + - Follow me! +

+ Simple test: + Follow me! +

+ +

+ Test <a> containing formatting tags (<br>, <em>, <strong>, <i>, <b>): +
+ + link 2
+ link 2
+ link 2
+ link 2
+ link 2
+ link 2 +
+

+ +

+ Test <a> containing <span style="display: block;">: + + + link 3 + + +

+ +

+ Test <a> containing <span style="display: table;">: + + + link 4 + + +

+ +
+

Test links wrapped across multiple lines:

+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +
+
diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index d95cdf868..ad4cde293 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -18,3 +18,51 @@ Feature: Using hints And I run :hint links normal And I run :follow-hint xyz Then the error "No hint xyz!" should be shown + + ### Hinting problematic links + + Scenario: Following a hint (link containing formatting tags) + When I open data/hints/link.html + # bypass Qt cache + And I run :reload --force + And I run :hint links normal + And I run :follow-hint s + And I wait until data/hello2.txt is loaded + Then the requests should be: + data/hints/link.html + data/hello2.txt + + Scenario: Following a hint (link containing tag with display:block style) + When I open data/hints/link.html + # bypass Qt cache + And I run :reload --force + And I run :hint links normal + And I run :follow-hint d + And I wait until data/hello3.txt is loaded + Then the requests should be: + data/hints/link.html + data/hello3.txt + + Scenario: Following a hint (link containing tag with display:table style) + When I open data/hints/link.html + # bypass Qt cache + And I run :reload --force + And I run :hint links normal + And I run :follow-hint f + And I wait until data/hello4.txt is loaded + Then the requests should be: + data/hints/link.html + data/hello4.txt + + Scenario: Following a link wrapped across multiple lines. + When I open data/hints/link.html + # bypass Qt cache + And I run :reload --force + And I run :hint links normal + And I run :follow-hint g + And I wait until data/hello.txt is loaded + # bypass Qt cache + And I run :reload --force + Then the requests should be: + data/hints/link.html + data/hello.txt From 239b7497e913dba56854319f6a286fb300204ae7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Mon, 15 Feb 2016 20:41:54 +0100 Subject: [PATCH 03/16] hints: simplify tests and make them more reliable --- tests/integration/features/hints.feature | 35 ++++-------------------- 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index ad4cde293..15b694945 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -4,10 +4,7 @@ Feature: Using hints When I open data/hints/link.html And I run :hint links normal And I run :follow-hint a - And I wait until data/hello.txt is loaded - Then the requests should be: - data/hints/link.html - data/hello.txt + Then data/hello.txt should be loaded Scenario: Using :follow-hint outside of hint mode (issue 1105) When I run :follow-hint @@ -23,46 +20,24 @@ Feature: Using hints Scenario: Following a hint (link containing formatting tags) When I open data/hints/link.html - # bypass Qt cache - And I run :reload --force And I run :hint links normal And I run :follow-hint s - And I wait until data/hello2.txt is loaded - Then the requests should be: - data/hints/link.html - data/hello2.txt + Then data/hello2.txt should be loaded Scenario: Following a hint (link containing tag with display:block style) When I open data/hints/link.html - # bypass Qt cache - And I run :reload --force And I run :hint links normal And I run :follow-hint d - And I wait until data/hello3.txt is loaded - Then the requests should be: - data/hints/link.html - data/hello3.txt + Then data/hello3.txt should be loaded Scenario: Following a hint (link containing tag with display:table style) When I open data/hints/link.html - # bypass Qt cache - And I run :reload --force And I run :hint links normal And I run :follow-hint f - And I wait until data/hello4.txt is loaded - Then the requests should be: - data/hints/link.html - data/hello4.txt + Then data/hello4.txt should be loaded Scenario: Following a link wrapped across multiple lines. When I open data/hints/link.html - # bypass Qt cache - And I run :reload --force And I run :hint links normal And I run :follow-hint g - And I wait until data/hello.txt is loaded - # bypass Qt cache - And I run :reload --force - Then the requests should be: - data/hints/link.html - data/hello.txt + Then data/hello.txt should be loaded From dd594b0ecac6595067d6c932ce9d87d9019fe5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Mon, 15 Feb 2016 22:24:08 +0100 Subject: [PATCH 04/16] hints: split getClientRects() into separate method this will be useful for positioning the hint label --- qutebrowser/browser/hints.py | 53 ++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index b38fc5c0c..12cd16651 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -26,7 +26,7 @@ import re import string from PyQt5.QtCore import (pyqtSignal, pyqtSlot, QObject, QEvent, Qt, QUrl, - QTimer, QPoint) + QTimer, QRect) from PyQt5.QtGui import QMouseEvent from PyQt5.QtWebKit import QWebElement from PyQt5.QtWebKitWidgets import QWebPage @@ -420,6 +420,32 @@ class HintManager(QObject): message.error(self._win_id, "No suitable link found for this element.", immediately=True) + def _get_first_rectangle(self, elem): + """Return the element's first client rectangle with positive size. + + Uses the getClientRects() JavaScript method to obtain the collection of + rectangles containing the element and returns the first with positive + dimensions. Falls back to elem.rect_on_view() in case all rectangles + returned by getClientRects() have zero dimensions. + + Skipping of rectangles with zero dimensions is due to elements + containing other elements with "display:block" style, see + https://github.com/The-Compiler/qutebrowser/issues/1298 + + Args: + elem: The QWebElement of interest. + """ + rects = elem.evaluateJavaScript("this.getClientRects()") + log.hints.debug("Client rectangles of element '{}': {}" + .format(elem.debug_text(), rects)) + for i in range(int(rects.get("length", 0))): + rect = rects[str(i)] + width = rect.get("width", 0) + height = rect.get("height", 0) + if width > 0 and height > 0: + return QRect(rect["left"], rect["top"], width, height) + return elem.rect_on_view() + def _click(self, elem, context): """Click an element. @@ -439,29 +465,16 @@ class HintManager(QObject): else: target_mapping[Target.tab] = usertypes.ClickTarget.tab - action = "Hovering" if context.target == Target.hover else "Clicking" - log.hints.debug("{} on element '{}'".format(action, elem.debug_text())) - # FIXME Instead of clicking the center, we could have nicer heuristics. # e.g. parse (-webkit-)border-radius correctly and click text fields at # the bottom right, and everything else on the top left or so. # https://github.com/The-Compiler/qutebrowser/issues/70 - pos = elem.rect_on_view().center() - log.hints.debug("Center position: {}".format(pos)) - boxes = elem.evaluateJavaScript("this.getClientRects()") - log.hints.debug("Bounding boxes: {}".format(boxes)) - for key in sorted(boxes): - box = boxes[key] - width = box.get("width", 0) - height = box.get("height", 0) - # skip boxes with zero dimensions (happens to if they contain - # other elements with display:block style) - # https://github.com/The-Compiler/qutebrowser/issues/1298 - if width > 0 and height > 0: - pos = QPoint(box["left"] + width / 2, box["top"] + height / 2) - log.hints.debug("Updated position: {}".format(pos)) - break - log.hints.debug("Final position is {}".format(pos)) + rect = self._get_first_rectangle(elem) + pos = rect.center() + + action = "Hovering" if context.target == Target.hover else "Clicking" + log.hints.debug("{} on '{}' at position {}".format( + action, elem.debug_text(), pos)) self.start_hinting.emit(target_mapping[context.target]) if context.target in [Target.tab, Target.tab_fg, Target.tab_bg, From 9799c30c2b84bb018916212ac051e65b19b76c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Mon, 15 Feb 2016 23:31:49 +0100 Subject: [PATCH 05/16] hints: add precision tests for different zoom levels --- qutebrowser/browser/hints.py | 10 ++++++++-- tests/integration/data/hints/link.html | 7 +++++++ tests/integration/features/hints.feature | 18 ++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index 12cd16651..e3619110d 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -472,9 +472,15 @@ class HintManager(QObject): rect = self._get_first_rectangle(elem) pos = rect.center() + # fix coordinates according to zoom level + zoom = elem.webFrame().zoomFactor() + if not config.get('ui', 'zoom-text-only'): + pos.setX(pos.x() * zoom) + pos.setY(pos.y() * zoom) + action = "Hovering" if context.target == Target.hover else "Clicking" - log.hints.debug("{} on '{}' at position {}".format( - action, elem.debug_text(), pos)) + log.hints.debug("{} on '{}' at position {} (zoom = {})".format( + action, elem.debug_text(), pos, zoom)) self.start_hinting.emit(target_mapping[context.target]) if context.target in [Target.tab, Target.tab_fg, Target.tab_bg, diff --git a/tests/integration/data/hints/link.html b/tests/integration/data/hints/link.html index 2dc96b280..8075cc821 100644 --- a/tests/integration/data/hints/link.html +++ b/tests/integration/data/hints/link.html @@ -50,5 +50,12 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + +
+

Test precision with different zoom levels:

+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +
+
diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index 15b694945..c8cc8b77d 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -41,3 +41,21 @@ Feature: Using hints And I run :hint links normal And I run :follow-hint g Then data/hello.txt should be loaded + + Scenario: Following a link with zoom 125%. + When I open data/hints/link.html + And I run :zoom 125 + And I run :hint links normal + And I run :follow-hint h + And I run :zoom 100 + Then data/hello.txt should be loaded + + Scenario: Following a link with zoom 125% and zoom-text-only == True. + When I open data/hints/link.html + And I run :set ui zoom-text-only true + And I run :zoom 125 + And I run :hint links normal + And I run :follow-hint h + And I run :zoom 100 + And I run :set ui zoom-text-only false + Then data/hello.txt should be loaded From 97d2038528c8bb05cc60bcc57bab90addc74a8b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Tue, 16 Feb 2016 00:05:58 +0100 Subject: [PATCH 06/16] hints: make sure that all hints stay visible in tests --- tests/integration/features/hints.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index c8cc8b77d..e02f4efc1 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -44,7 +44,7 @@ Feature: Using hints Scenario: Following a link with zoom 125%. When I open data/hints/link.html - And I run :zoom 125 + And I run :zoom 75 And I run :hint links normal And I run :follow-hint h And I run :zoom 100 @@ -53,7 +53,7 @@ Feature: Using hints Scenario: Following a link with zoom 125% and zoom-text-only == True. When I open data/hints/link.html And I run :set ui zoom-text-only true - And I run :zoom 125 + And I run :zoom 75 And I run :hint links normal And I run :follow-hint h And I run :zoom 100 From 1cff16b3b4b709f417766836b4fc966fe6c63952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Fri, 19 Feb 2016 21:15:56 +0100 Subject: [PATCH 07/16] hints: fix bug in the correction of coordinates based on zoom level --- qutebrowser/browser/hints.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index e3619110d..709914dde 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -443,6 +443,13 @@ class HintManager(QObject): width = rect.get("width", 0) height = rect.get("height", 0) if width > 0 and height > 0: + # fix coordinates according to zoom level + zoom = elem.webFrame().zoomFactor() + if not config.get('ui', 'zoom-text-only'): + rect["left"] *= zoom + rect["top"] *= zoom + width *= zoom + height *= zoom return QRect(rect["left"], rect["top"], width, height) return elem.rect_on_view() @@ -472,15 +479,9 @@ class HintManager(QObject): rect = self._get_first_rectangle(elem) pos = rect.center() - # fix coordinates according to zoom level - zoom = elem.webFrame().zoomFactor() - if not config.get('ui', 'zoom-text-only'): - pos.setX(pos.x() * zoom) - pos.setY(pos.y() * zoom) - action = "Hovering" if context.target == Target.hover else "Clicking" - log.hints.debug("{} on '{}' at position {} (zoom = {})".format( - action, elem.debug_text(), pos, zoom)) + log.hints.debug("{} on '{}' at position {}".format( + action, elem.debug_text(), pos)) self.start_hinting.emit(target_mapping[context.target]) if context.target in [Target.tab, Target.tab_fg, Target.tab_bg, From 52a9405f746e136e331fa43b2e75e013d5fb2c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Sun, 21 Feb 2016 12:53:03 +0100 Subject: [PATCH 08/16] hints: fix descriptions of zoom tests --- tests/integration/features/hints.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index e02f4efc1..a2d4d3985 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -42,7 +42,7 @@ Feature: Using hints And I run :follow-hint g Then data/hello.txt should be loaded - Scenario: Following a link with zoom 125%. + Scenario: Following a link with zoom 75%. When I open data/hints/link.html And I run :zoom 75 And I run :hint links normal @@ -50,7 +50,7 @@ Feature: Using hints And I run :zoom 100 Then data/hello.txt should be loaded - Scenario: Following a link with zoom 125% and zoom-text-only == True. + Scenario: Following a link with zoom 75% and zoom-text-only == True. When I open data/hints/link.html And I run :set ui zoom-text-only true And I run :zoom 75 From 35ed70cfe077bc4c14ca22cc0bbd62fba9735b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Tue, 23 Feb 2016 18:14:37 +0100 Subject: [PATCH 09/16] hints: split tests into individual HTML files --- tests/integration/data/hello4.txt | 1 - .../data/hints/html/nested_block_style.html | 17 ++++++ .../hints/html/nested_formatting_tags.html | 20 ++++++ .../data/hints/html/nested_table_style.html | 17 ++++++ .../integration/data/hints/html/wrapped.html | 15 +++++ .../data/hints/html/zoom_precision.html | 15 +++++ tests/integration/data/hints/link.html | 61 ------------------- tests/integration/features/hints.feature | 42 ++----------- 8 files changed, 90 insertions(+), 98 deletions(-) delete mode 100644 tests/integration/data/hello4.txt create mode 100644 tests/integration/data/hints/html/nested_block_style.html create mode 100644 tests/integration/data/hints/html/nested_formatting_tags.html create mode 100644 tests/integration/data/hints/html/nested_table_style.html create mode 100644 tests/integration/data/hints/html/wrapped.html create mode 100644 tests/integration/data/hints/html/zoom_precision.html delete mode 100644 tests/integration/data/hints/link.html diff --git a/tests/integration/data/hello4.txt b/tests/integration/data/hello4.txt deleted file mode 100644 index a31ec61e8..000000000 --- a/tests/integration/data/hello4.txt +++ /dev/null @@ -1 +0,0 @@ -Hello World 4! diff --git a/tests/integration/data/hints/html/nested_block_style.html b/tests/integration/data/hints/html/nested_block_style.html new file mode 100644 index 000000000..9ee1ff603 --- /dev/null +++ b/tests/integration/data/hints/html/nested_block_style.html @@ -0,0 +1,17 @@ + + + + + + + + Link containing an element with "display: block" style + + + + + link + + + + diff --git a/tests/integration/data/hints/html/nested_formatting_tags.html b/tests/integration/data/hints/html/nested_formatting_tags.html new file mode 100644 index 000000000..66c3d6e04 --- /dev/null +++ b/tests/integration/data/hints/html/nested_formatting_tags.html @@ -0,0 +1,20 @@ + + + + + + + + Link containing formatting tags + + + + link
+ link
+ link
+ link
+ link
+ link +
+ + diff --git a/tests/integration/data/hints/html/nested_table_style.html b/tests/integration/data/hints/html/nested_table_style.html new file mode 100644 index 000000000..a6a1a2b8f --- /dev/null +++ b/tests/integration/data/hints/html/nested_table_style.html @@ -0,0 +1,17 @@ + + + + + + + + Link containing an element with "display: table" style + + + + + link + + + + diff --git a/tests/integration/data/hints/html/wrapped.html b/tests/integration/data/hints/html/wrapped.html new file mode 100644 index 000000000..dcc05c8c7 --- /dev/null +++ b/tests/integration/data/hints/html/wrapped.html @@ -0,0 +1,15 @@ + + + + + + + + Link wrapped across multiple lines + + +
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +
+ + diff --git a/tests/integration/data/hints/html/zoom_precision.html b/tests/integration/data/hints/html/zoom_precision.html new file mode 100644 index 000000000..5b9b73f99 --- /dev/null +++ b/tests/integration/data/hints/html/zoom_precision.html @@ -0,0 +1,15 @@ + + + + + + + + Test hinting precision with different zoom levels + + +
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +
+ + diff --git a/tests/integration/data/hints/link.html b/tests/integration/data/hints/link.html deleted file mode 100644 index 8075cc821..000000000 --- a/tests/integration/data/hints/link.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - A link to use hints on - - - -

- Simple test: - Follow me! -

- -

- Test <a> containing formatting tags (<br>, <em>, <strong>, <i>, <b>): -
- - link 2
- link 2
- link 2
- link 2
- link 2
- link 2 -
-

- -

- Test <a> containing <span style="display: block;">: - - - link 3 - - -

- -

- Test <a> containing <span style="display: table;">: - - - link 4 - - -

- -
-

Test links wrapped across multiple lines:

-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -
-
- -
-

Test precision with different zoom levels:

-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -
-
- - diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index a2d4d3985..7eb64b87e 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -1,61 +1,31 @@ Feature: Using hints - Scenario: Following a hint. - When I open data/hints/link.html - And I run :hint links normal - And I run :follow-hint a - Then data/hello.txt should be loaded - Scenario: Using :follow-hint outside of hint mode (issue 1105) When I run :follow-hint Then the error "follow-hint: This command is only allowed in hint mode." should be shown Scenario: Using :follow-hint with an invalid index. - When I open data/hints/link.html + When I open data/hints/html/simple.html And I run :hint links normal And I run :follow-hint xyz Then the error "No hint xyz!" should be shown - ### Hinting problematic links - - Scenario: Following a hint (link containing formatting tags) - When I open data/hints/link.html - And I run :hint links normal - And I run :follow-hint s - Then data/hello2.txt should be loaded - - Scenario: Following a hint (link containing tag with display:block style) - When I open data/hints/link.html - And I run :hint links normal - And I run :follow-hint d - Then data/hello3.txt should be loaded - - Scenario: Following a hint (link containing tag with display:table style) - When I open data/hints/link.html - And I run :hint links normal - And I run :follow-hint f - Then data/hello4.txt should be loaded - - Scenario: Following a link wrapped across multiple lines. - When I open data/hints/link.html - And I run :hint links normal - And I run :follow-hint g - Then data/hello.txt should be loaded + ### TODO: use test_hints_html.py for zoom tests Scenario: Following a link with zoom 75%. - When I open data/hints/link.html + When I open data/hints/html/zoom_precision.html And I run :zoom 75 And I run :hint links normal - And I run :follow-hint h + And I run :follow-hint a And I run :zoom 100 Then data/hello.txt should be loaded Scenario: Following a link with zoom 75% and zoom-text-only == True. - When I open data/hints/link.html + When I open data/hints/html/zoom_precision.html And I run :set ui zoom-text-only true And I run :zoom 75 And I run :hint links normal - And I run :follow-hint h + And I run :follow-hint a And I run :zoom 100 And I run :set ui zoom-text-only false Then data/hello.txt should be loaded From 891a31a0cacc26fd867199769636f5360dcc5411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Tue, 23 Feb 2016 18:51:32 +0100 Subject: [PATCH 10/16] hints: move zoom tests to test_hints_html.py --- tests/integration/features/hints.feature | 20 -------------------- tests/integration/test_hints_html.py | 11 ++++++++++- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index 7eb64b87e..f15858d76 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -9,23 +9,3 @@ Feature: Using hints And I run :hint links normal And I run :follow-hint xyz Then the error "No hint xyz!" should be shown - - ### TODO: use test_hints_html.py for zoom tests - - Scenario: Following a link with zoom 75%. - When I open data/hints/html/zoom_precision.html - And I run :zoom 75 - And I run :hint links normal - And I run :follow-hint a - And I run :zoom 100 - Then data/hello.txt should be loaded - - Scenario: Following a link with zoom 75% and zoom-text-only == True. - When I open data/hints/html/zoom_precision.html - And I run :set ui zoom-text-only true - And I run :zoom 75 - And I run :hint links normal - And I run :follow-hint a - And I run :zoom 100 - And I run :set ui zoom-text-only false - Then data/hello.txt should be loaded diff --git a/tests/integration/test_hints_html.py b/tests/integration/test_hints_html.py index cc668193d..a6ea22b9d 100644 --- a/tests/integration/test_hints_html.py +++ b/tests/integration/test_hints_html.py @@ -35,7 +35,9 @@ def collect_tests(): @pytest.mark.parametrize('test_name', collect_tests()) -def test_hints(test_name, quteproc): +@pytest.mark.parametrize('zoom_text_only', [True, False]) +@pytest.mark.parametrize('zoom_level', [100, 66, 33]) +def test_hints(test_name, zoom_text_only, zoom_level, quteproc): file_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data', 'hints', 'html', test_name) url_path = 'data/hints/html/{}'.format(test_name) @@ -50,7 +52,14 @@ def test_hints(test_name, quteproc): assert set(parsed.keys()) == {'target'} + # setup + quteproc.send_cmd(':set ui zoom-text-only {}'.format(zoom_text_only)) + quteproc.send_cmd(':zoom {}'.format(zoom_level)) + # follow hint quteproc.send_cmd(':hint links normal') quteproc.wait_for(message='hints: a', category='hints') quteproc.send_cmd(':follow-hint a') quteproc.wait_for_load_finished('data/' + parsed['target']) + # reset + quteproc.send_cmd(':zoom 100') + quteproc.send_cmd(':set ui zoom-text-only false') From d630f966e7a3e680018dc362f67ebc53e8bc8c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Tue, 23 Feb 2016 20:23:11 +0100 Subject: [PATCH 11/16] hints: ignore too small rectangles returned by getClientRects() Apparently we can have a '1px x 1px' rectangle at some zoom levels and '0px x 0px' at others. We can't reliably click these, so let's ignore them. --- qutebrowser/browser/hints.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index b5695badc..ef2f37f6c 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -424,12 +424,12 @@ class HintManager(QObject): """Return the element's first client rectangle with positive size. Uses the getClientRects() JavaScript method to obtain the collection of - rectangles containing the element and returns the first with positive - dimensions. Falls back to elem.rect_on_view() in case all rectangles - returned by getClientRects() have zero dimensions. + rectangles containing the element and returns the first rectangle which + is large enough (larger than 1px times 1px). If all rectangles returned + by getClientRects() are too small, falls back to elem.rect_on_view(). - Skipping of rectangles with zero dimensions is due to elements - containing other elements with "display:block" style, see + Skipping of small rectangles is due to elements containing other + elements with "display:block" style, see https://github.com/The-Compiler/qutebrowser/issues/1298 Args: @@ -442,7 +442,7 @@ class HintManager(QObject): rect = rects[str(i)] width = rect.get("width", 0) height = rect.get("height", 0) - if width > 0 and height > 0: + if width > 1 and height > 1: # fix coordinates according to zoom level zoom = elem.webFrame().zoomFactor() if not config.get('ui', 'zoom-text-only'): From b1207650b08639e0d852fa8aae4290417eb77a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Wed, 24 Feb 2016 22:56:06 +0100 Subject: [PATCH 12/16] hints: translate client rectangles into parent frames --- qutebrowser/browser/hints.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index ef2f37f6c..df033bb0c 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -450,7 +450,14 @@ class HintManager(QObject): rect["top"] *= zoom width *= zoom height *= zoom - return QRect(rect["left"], rect["top"], width, height) + rect = QRect(rect["left"], rect["top"], width, height) + frame = elem.webFrame() + while frame is not None: + # Translate to parent frames' position + # (scroll position is taken care of inside getClientRects) + rect.translate(frame.geometry().topLeft()) + frame = frame.parentFrame() + return rect return elem.rect_on_view() def _click(self, elem, context): From d4ea62a834bd48186d6f2c9f9b6287aa867e0785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Wed, 24 Feb 2016 23:15:13 +0100 Subject: [PATCH 13/16] hints: add xfailed tests for hinting inside iframes --- tests/integration/data/hints/iframe.html | 11 ++++++++++ .../integration/data/hints/iframe_scroll.html | 11 ++++++++++ tests/integration/features/hints.feature | 21 +++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 tests/integration/data/hints/iframe.html create mode 100644 tests/integration/data/hints/iframe_scroll.html diff --git a/tests/integration/data/hints/iframe.html b/tests/integration/data/hints/iframe.html new file mode 100644 index 000000000..269b689a2 --- /dev/null +++ b/tests/integration/data/hints/iframe.html @@ -0,0 +1,11 @@ + + + + + + Hinting inside an iframe + + + + + diff --git a/tests/integration/data/hints/iframe_scroll.html b/tests/integration/data/hints/iframe_scroll.html new file mode 100644 index 000000000..4c3f56453 --- /dev/null +++ b/tests/integration/data/hints/iframe_scroll.html @@ -0,0 +1,11 @@ + + + + + + Scrolling inside an iframe + + + + + diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index f15858d76..13346aa37 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -9,3 +9,24 @@ Feature: Using hints And I run :hint links normal And I run :follow-hint xyz Then the error "No hint xyz!" should be shown + + ### iframes + + @xfail + Scenario: Using :follow-hint inside an iframe + When I open data/hints/iframe.html + And I run :hint all normal + And I run :follow-hint a + And I run :hint links normal + And I run :follow-hint a + Then data/hello.txt should be loaded + + @xfail + Scenario: Using :follow-hint inside a scrolled iframe + When I open data/hints/iframe_scroll.html + And I run :hint all normal + And I run :follow-hint a + And I run :scroll bottom + And I run :hint links normal + And I run :follow-hint a + Then data/hello2.txt should be loaded From 164df521c16f9fe8686b42ea660382b1b54f0188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Wed, 16 Mar 2016 20:59:46 +0100 Subject: [PATCH 14/16] hints: add verifications for iframe tests --- tests/integration/features/hints.feature | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index 13346aa37..8b58ad3f9 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -12,16 +12,14 @@ Feature: Using hints ### iframes - @xfail Scenario: Using :follow-hint inside an iframe When I open data/hints/iframe.html And I run :hint all normal And I run :follow-hint a And I run :hint links normal And I run :follow-hint a - Then data/hello.txt should be loaded + Then "acceptNavigationRequest, url http://localhost:*/data/hello.txt, type NavigationTypeLinkClicked, *" should be logged - @xfail Scenario: Using :follow-hint inside a scrolled iframe When I open data/hints/iframe_scroll.html And I run :hint all normal @@ -29,4 +27,4 @@ Feature: Using hints And I run :scroll bottom And I run :hint links normal And I run :follow-hint a - Then data/hello2.txt should be loaded + Then "acceptNavigationRequest, url http://localhost:*/data/hello2.txt, type NavigationTypeLinkClicked, *" should be logged From e121bd764fb056fe335e6d71207b34533dd0a613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Wed, 16 Mar 2016 21:47:58 +0100 Subject: [PATCH 15/16] hints: add another iframe test --- tests/integration/data/hints/iframe_target.html | 14 ++++++++++++++ tests/integration/features/hints.feature | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/integration/data/hints/iframe_target.html diff --git a/tests/integration/data/hints/iframe_target.html b/tests/integration/data/hints/iframe_target.html new file mode 100644 index 000000000..db8afad27 --- /dev/null +++ b/tests/integration/data/hints/iframe_target.html @@ -0,0 +1,14 @@ + + + + + + Opening links in a specific iframe + + + +

+ A link to be opened in the iframe above. +

+ + diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index 8b58ad3f9..3db462371 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -28,3 +28,17 @@ Feature: Using hints And I run :hint links normal And I run :follow-hint a Then "acceptNavigationRequest, url http://localhost:*/data/hello2.txt, type NavigationTypeLinkClicked, *" should be logged + + Scenario: Opening a link inside a specific iframe + When I open data/hints/iframe_target.html + And I run :hint links normal + And I run :follow-hint a + Then "acceptNavigationRequest, url http://localhost:*/data/hello.txt, type NavigationTypeLinkClicked, *" should be logged + + Scenario: Opening a link with specific target frame in a new tab + When I open data/hints/iframe_target.html + And I run :hint links tab + And I run :follow-hint a + Then the following tabs should be open: + - data/hints/iframe_target.html + - data/hello.txt (active) From 0eab4225400530534d57e430fa04ab7c04f45bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Fri, 15 Apr 2016 23:19:08 +0200 Subject: [PATCH 16/16] tests: replace paths to data/hints/link.html an adjustment due to 35ed70cfe077bc4c14ca22cc0bbd62fba9735b73 --- tests/integration/features/hints.feature | 2 +- tests/integration/features/tabs.feature | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/integration/features/hints.feature b/tests/integration/features/hints.feature index 456ed65bc..4c6bc3424 100644 --- a/tests/integration/features/hints.feature +++ b/tests/integration/features/hints.feature @@ -40,7 +40,7 @@ Feature: Using hints @xfail Scenario: Using :hint spawn with flags (issue 797) - When I open data/hints/link.html + When I open data/hints/html/simple.html And I run :hint all spawn -v echo And I run :follow-hint a Then the message "Command exited successfully" should be shown diff --git a/tests/integration/features/tabs.feature b/tests/integration/features/tabs.feature index 6603817d9..a8a3c927e 100644 --- a/tests/integration/features/tabs.feature +++ b/tests/integration/features/tabs.feature @@ -677,64 +677,64 @@ Feature: Tab management Scenario: opening links with tabs->background-tabs true When I set tabs -> background-tabs to true - And I open data/hints/link.html + And I open data/hints/html/simple.html And I run :hint all tab And I run :follow-hint a And I wait until data/hello.txt is loaded Then the following tabs should be open: - - data/hints/link.html (active) + - data/hints/html/simple.html (active) - data/hello.txt Scenario: opening tab with tabs->new-tab-position left When I set tabs -> new-tab-position to left And I set tabs -> background-tabs to false And I open about:blank - And I open data/hints/link.html in a new tab + And I open data/hints/html/simple.html in a new tab And I run :hint all tab And I run :follow-hint a And I wait until data/hello.txt is loaded Then the following tabs should be open: - about:blank - data/hello.txt (active) - - data/hints/link.html + - data/hints/html/simple.html Scenario: opening tab with tabs->new-tab-position right When I set tabs -> new-tab-position to right And I set tabs -> background-tabs to false And I open about:blank - And I open data/hints/link.html in a new tab + And I open data/hints/html/simple.html in a new tab And I run :hint all tab And I run :follow-hint a And I wait until data/hello.txt is loaded Then the following tabs should be open: - about:blank - - data/hints/link.html + - data/hints/html/simple.html - data/hello.txt (active) Scenario: opening tab with tabs->new-tab-position first When I set tabs -> new-tab-position to first And I set tabs -> background-tabs to false And I open about:blank - And I open data/hints/link.html in a new tab + And I open data/hints/html/simple.html in a new tab And I run :hint all tab And I run :follow-hint a And I wait until data/hello.txt is loaded Then the following tabs should be open: - data/hello.txt (active) - about:blank - - data/hints/link.html + - data/hints/html/simple.html Scenario: opening tab with tabs->new-tab-position last When I set tabs -> new-tab-position to last And I set tabs -> background-tabs to false - And I open data/hints/link.html + And I open data/hints/html/simple.html And I open about:blank in a new tab And I run :tab-focus last And I run :hint all tab And I run :follow-hint a And I wait until data/hello.txt is loaded Then the following tabs should be open: - - data/hints/link.html + - data/hints/html/simple.html - about:blank - data/hello.txt (active)