elements containing other
+ elements with "display:block" style, see
+ https://github.com/The-Compiler/qutebrowser/issues/1298
+
Args:
elem: The QWebElement to get the rect for.
elem_geometry: The geometry of the element, or None.
Calling QWebElement::geometry is rather expensive so we
want to avoid doing it twice.
+ adjust_zoom: Whether to adjust the element position based on the
+ current zoom level.
"""
if elem.isNull():
raise IsNullError("Got called on a null element!")
+
+ # First try getting the element rect via JS, as that's usually more
+ # accurate
+ if elem_geometry is None:
+ rects = elem.evaluateJavaScript("this.getClientRects()")
+ text = utils.compact_text(elem.toOuterXml(), 500)
+ log.hints.vdebug("Client rectangles of element '{}': {}".format(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 > 1 and height > 1:
+ # fix coordinates according to zoom level
+ zoom = elem.webFrame().zoomFactor()
+ if not config.get('ui', 'zoom-text-only') and adjust_zoom:
+ rect["left"] *= zoom
+ rect["top"] *= zoom
+ width *= zoom
+ height *= zoom
+ 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
+
+ # No suitable rects found via JS, try via the QWebElement API
if elem_geometry is None:
elem_geometry = elem.geometry()
frame = elem.webFrame()
@@ -386,6 +432,11 @@ def rect_on_view(elem, elem_geometry=None):
rect.translate(frame.geometry().topLeft())
rect.translate(frame.scrollPosition() * -1)
frame = frame.parentFrame()
+ # We deliberately always adjust the zoom here, even with adjust_zoom=False
+ zoom = elem.webFrame().zoomFactor()
+ if not config.get('ui', 'zoom-text-only'):
+ rect.setLeft(rect.left() / zoom)
+ rect.setTop(rect.top() / zoom)
return rect
diff --git a/tests/end2end/features/hints.feature b/tests/end2end/features/hints.feature
index 9d4470ebe..5bccf7ab4 100644
--- a/tests/end2end/features/hints.feature
+++ b/tests/end2end/features/hints.feature
@@ -113,8 +113,6 @@ Feature: Using hints
@xfail_norun
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 "acceptNavigationRequest, url http://localhost:*/data/hello.txt, type NavigationTypeLinkClicked, *" should be logged
diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py
index adaebd168..91519d558 100644
--- a/tests/helpers/stubs.py
+++ b/tests/helpers/stubs.py
@@ -77,7 +77,7 @@ class FakeWebFrame:
"""
def __init__(self, geometry=None, *, scroll=None, plaintext=None,
- html=None, parent=None):
+ html=None, parent=None, zoom=1.0):
"""Constructor.
Args:
@@ -85,6 +85,7 @@ class FakeWebFrame:
scroll: The scroll position as QPoint.
plaintext: Return value of toPlainText
html: Return value of tohtml.
+ zoom: The zoom factor.
parent: The parent frame.
"""
if scroll is None:
@@ -95,6 +96,7 @@ class FakeWebFrame:
self.focus_elem = None
self.toPlainText = mock.Mock(return_value=plaintext)
self.toHtml = mock.Mock(return_value=html)
+ self.zoomFactor = mock.Mock(return_value=zoom)
def findFirstElement(self, selector):
if selector == '*:focus':
diff --git a/tests/manual/hints/issue824.html b/tests/manual/hints/issue824.html
index 510f9758d..881e1b263 100644
--- a/tests/manual/hints/issue824.html
+++ b/tests/manual/hints/issue824.html
@@ -8,5 +8,6 @@
When using hints (f) on this page, the hint should be drawn over the
link.
See #824.
+ This was fixed by #1433.