From c33a887b2dde97f8185265f3288a4a7cfd61f95f Mon Sep 17 00:00:00 2001 From: Jay Kamat Date: Fri, 25 May 2018 12:37:30 -0700 Subject: [PATCH 1/3] Add support for following tab selected elements to :follow-selected --- qutebrowser/browser/webengine/webenginetab.py | 2 +- qutebrowser/browser/webkit/webkittab.py | 10 +++++-- qutebrowser/javascript/webelem.js | 11 ++++++-- tests/end2end/features/caret.feature | 26 +++++++++++++++++++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 4ce8b8bdd..edfe1c63b 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -364,7 +364,7 @@ class WebEngineCaret(browsertab.AbstractCaret): else: # click an existing blue selection - js_code = javascript.assemble('webelem', 'find_selected_link') + js_code = javascript.assemble('webelem', 'find_selected_focused_link') self._tab.run_js_async(js_code, lambda jsret: self._follow_selected_cb(jsret, tab)) diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py index 9d5305f10..c47ad10d1 100644 --- a/qutebrowser/browser/webkit/webkittab.py +++ b/qutebrowser/browser/webkit/webkittab.py @@ -377,8 +377,14 @@ class WebKitCaret(browsertab.AbstractCaret): QWebSettings.JavascriptEnabled): if tab: self._tab.data.override_target = usertypes.ClickTarget.tab - self._tab.run_js_async( - 'window.getSelection().anchorNode.parentNode.click()') + self._tab.run_js_async(""" + const aElm = document.activeElement; + if (window.getSelection().anchorNode) { + window.getSelection().anchorNode.parentNode.click(); + } else if (aElm && aElm !== document.body) { + aElm.click(); + } + """) else: selection = self._widget.selectedHtml() if not selection: diff --git a/qutebrowser/javascript/webelem.js b/qutebrowser/javascript/webelem.js index f7ab0f636..b5aec6637 100644 --- a/qutebrowser/javascript/webelem.js +++ b/qutebrowser/javascript/webelem.js @@ -243,6 +243,7 @@ window._qutebrowser.webelem = (function() { }; // Runs a function in a frame until the result is not null, then return + // If no frame succeds, return null function run_frames(func) { for (let i = 0; i < window.frames.length; ++i) { const frame = window.frames[i]; @@ -329,7 +330,8 @@ window._qutebrowser.webelem = (function() { }; // Function for returning a selection to python (so we can click it) - funcs.find_selected_link = () => { + // If there is no selection, get the currently focused element. + funcs.find_selected_focused_link = () => { const elem = window.getSelection().baseNode; if (elem) { return serialize_elem(elem.parentNode); @@ -342,7 +344,12 @@ window._qutebrowser.webelem = (function() { } return null; }); - return serialized_frame_elem; + + if (serialized_frame_elem) { + return serialized_frame_elem; + } + // No selected element, return focused element + return funcs.find_focused(); }; funcs.set_value = (id, value) => { diff --git a/tests/end2end/features/caret.feature b/tests/end2end/features/caret.feature index 803016539..72ff6d085 100644 --- a/tests/end2end/features/caret.feature +++ b/tests/end2end/features/caret.feature @@ -321,6 +321,32 @@ Feature: Caret mode - data/caret.html - data/hello.txt (active) + @qtwebkit_skip: getting focused element not possible without js + Scenario: :follow-selected with link tabbing (without JS) + When I set content.javascript.enabled to false + And I run :fake-key + And I run :follow-selected + Then data/hello.txt should be loaded + + Scenario: :follow-selected with link tabbing (with JS) + When I set content.javascript.enabled to true + And I run :fake-key + And I run :follow-selected + Then data/hello.txt should be loaded + + @qtwebkit_skip: getting focused element not possible without js + Scenario: :follow-selected with link tabbing in a tab (without JS) + When I set content.javascript.enabled to false + And I run :fake-key + And I run :follow-selected --tab + Then data/hello.txt should be loaded + + Scenario: :follow-selected with link tabbing in a tab (with JS) + When I set content.javascript.enabled to true + And I run :fake-key + And I run :follow-selected --tab + Then data/hello.txt should be loaded + # Search + caret mode # https://bugreports.qt.io/browse/QTBUG-60673 From de127497a2869158f28cbc25e28e85eacbb2de8c Mon Sep 17 00:00:00 2001 From: Jay Kamat Date: Sat, 9 Jun 2018 12:11:22 -0700 Subject: [PATCH 2/3] Press enter to follow links instead of using js This codepath may trigger a crash which was fixed by https://github.com/annulen/webkit/commit/0e75f3272d149bc64899c161f150eb341a2417af. However, this commit does not make it more likely to happen, and this patch was backported into arch (at least). In the future, we may be able to use on qtwebkit with js, without triggering this crash --- qutebrowser/browser/webengine/webenginetab.py | 8 +++++++- qutebrowser/browser/webkit/webkittab.py | 5 +++++ qutebrowser/javascript/webelem.js | 8 ++++---- tests/end2end/features/caret.feature | 10 ++++++++-- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index edfe1c63b..0a8e62ecd 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -335,6 +335,11 @@ class WebEngineCaret(browsertab.AbstractCaret): """ if js_elem is None: return + if js_elem == "focused": + # we had a focused element, not a selected one. Just send + self._tab.key_press(Qt.Key_Enter) + return + assert isinstance(js_elem, dict), js_elem elem = webengineelem.WebEngineElement(js_elem, tab=self._tab) if tab: @@ -364,7 +369,8 @@ class WebEngineCaret(browsertab.AbstractCaret): else: # click an existing blue selection - js_code = javascript.assemble('webelem', 'find_selected_focused_link') + js_code = javascript.assemble('webelem', + 'find_selected_focused_link') self._tab.run_js_async(js_code, lambda jsret: self._follow_selected_cb(jsret, tab)) diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py index c47ad10d1..67f04886f 100644 --- a/qutebrowser/browser/webkit/webkittab.py +++ b/qutebrowser/browser/webkit/webkittab.py @@ -388,6 +388,11 @@ class WebKitCaret(browsertab.AbstractCaret): else: selection = self._widget.selectedHtml() if not selection: + # Getting here may mean we crashed, but we can't do anything + # about that: + # https://github.com/annulen/webkit/commit/0e75f3272d149bc64899c161f150eb341a2417af + # TODO find a way to check if something is focused + self._tab.key_press(Qt.Key_Enter) return try: selected_element = xml.etree.ElementTree.fromstring( diff --git a/qutebrowser/javascript/webelem.js b/qutebrowser/javascript/webelem.js index b5aec6637..ad18899f6 100644 --- a/qutebrowser/javascript/webelem.js +++ b/qutebrowser/javascript/webelem.js @@ -329,8 +329,9 @@ window._qutebrowser.webelem = (function() { return serialize_elem(elem); }; - // Function for returning a selection to python (so we can click it) - // If there is no selection, get the currently focused element. + // Function for returning a selection or focus to python (so we can click + // it). If nothing is selected but there is something focused, returns + // "focused" funcs.find_selected_focused_link = () => { const elem = window.getSelection().baseNode; if (elem) { @@ -348,8 +349,7 @@ window._qutebrowser.webelem = (function() { if (serialized_frame_elem) { return serialized_frame_elem; } - // No selected element, return focused element - return funcs.find_focused(); + return funcs.find_focused() && "focused"; }; funcs.set_value = (id, value) => { diff --git a/tests/end2end/features/caret.feature b/tests/end2end/features/caret.feature index 72ff6d085..268828edd 100644 --- a/tests/end2end/features/caret.feature +++ b/tests/end2end/features/caret.feature @@ -321,28 +321,34 @@ Feature: Caret mode - data/caret.html - data/hello.txt (active) - @qtwebkit_skip: getting focused element not possible without js Scenario: :follow-selected with link tabbing (without JS) When I set content.javascript.enabled to false + And I run :leave-mode + And I run :jseval document.activeElement.blur(); And I run :fake-key And I run :follow-selected Then data/hello.txt should be loaded Scenario: :follow-selected with link tabbing (with JS) When I set content.javascript.enabled to true + And I run :leave-mode + And I run :jseval document.activeElement.blur(); And I run :fake-key And I run :follow-selected Then data/hello.txt should be loaded - @qtwebkit_skip: getting focused element not possible without js Scenario: :follow-selected with link tabbing in a tab (without JS) When I set content.javascript.enabled to false + And I run :leave-mode + And I run :jseval document.activeElement.blur(); And I run :fake-key And I run :follow-selected --tab Then data/hello.txt should be loaded Scenario: :follow-selected with link tabbing in a tab (with JS) When I set content.javascript.enabled to true + And I run :leave-mode + And I run :jseval document.activeElement.blur(); And I run :fake-key And I run :follow-selected --tab Then data/hello.txt should be loaded From 315ed519eee40f800ac619197ffecc72f4fc690d Mon Sep 17 00:00:00 2001 From: Jay Kamat Date: Sun, 10 Jun 2018 16:27:56 -0700 Subject: [PATCH 3/3] Use ctrl-enter in all cases --- qutebrowser/browser/webengine/webenginetab.py | 6 ++++-- qutebrowser/browser/webkit/webkittab.py | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 0a8e62ecd..3ea3079aa 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -337,8 +337,10 @@ class WebEngineCaret(browsertab.AbstractCaret): return if js_elem == "focused": # we had a focused element, not a selected one. Just send - self._tab.key_press(Qt.Key_Enter) - return + if tab: + self._tab.key_press(Qt.Key_Enter, modifier=Qt.ControlModifier) + else: + self._tab.key_press(Qt.Key_Enter) assert isinstance(js_elem, dict), js_elem elem = webengineelem.WebEngineElement(js_elem, tab=self._tab) diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py index 67f04886f..36da17dac 100644 --- a/qutebrowser/browser/webkit/webkittab.py +++ b/qutebrowser/browser/webkit/webkittab.py @@ -389,10 +389,14 @@ class WebKitCaret(browsertab.AbstractCaret): selection = self._widget.selectedHtml() if not selection: # Getting here may mean we crashed, but we can't do anything - # about that: + # about that until this commit is released: # https://github.com/annulen/webkit/commit/0e75f3272d149bc64899c161f150eb341a2417af # TODO find a way to check if something is focused - self._tab.key_press(Qt.Key_Enter) + if tab: + self._tab.key_press(Qt.Key_Enter, + modifier=Qt.ControlModifier) + else: + self._tab.key_press(Qt.Key_Enter) return try: selected_element = xml.etree.ElementTree.fromstring(