Attached is a patch adding a config option "input->rocker-gestures", which
disables the context menu and replaces it with Opera-like rocker gestures.
Specifically, holding the right mouse button and pressing the left button will
go back in history. Holding the left mouse button and pressing the right button
moves forward (It is very easy to get used to this. I can't live without it
anymore, hence the patch).
I'm not sure if there is any interest in merging this, but I thought I'd at
least share the patch.
best regards
diff --git a/qutebrowser/browser/webview.py b/qutebrowser/browser/webview.py
index 13b2cbb..644e349 100644
--- a/qutebrowser/browser/webview.py
+++ b/qutebrowser/browser/webview.py
@@ -42,6 +42,7 @@ LoadStatus = usertypes.enum('LoadStatus', ['none', 'success', 'error', 'warn',
tab_id_gen = itertools.count(0)
+
class WebView(QWebView):
"""One browser tab in TabbedBrowser.
@@ -86,6 +87,10 @@ class WebView(QWebView):
url_text_changed = pyqtSignal(str)
shutting_down = pyqtSignal()
+ #Mouse button states for rocker gestures
+ left_pressed = False
+ right_pressed = False
+
def __init__(self, win_id, parent=None):
super().__init__(parent)
if sys.platform == 'darwin' and qtutils.version_check('5.4'):
@@ -143,6 +148,8 @@ class WebView(QWebView):
self.setZoomFactor(float(config.get('ui', 'default-zoom')) / 100)
self._default_zoom_changed = False
objreg.get('config').changed.connect(self.on_config_changed)
+ if config.get('input', 'rocker-gestures'):
+ self.setContextMenuPolicy(Qt.PreventContextMenu)
def __repr__(self):
url = utils.elide(self.url().toDisplayString(), 50)
@@ -178,6 +185,12 @@ class WebView(QWebView):
100)
self._default_zoom_changed = False
self.init_neighborlist()
+ if section == 'input' and option == 'rocker-gestures':
+ if config.get('input','rocker-gestures'):
+ self.setContextMenuPolicy(Qt.PreventContextMenu)
+ else:
+ self.setContextMenuPolicy(Qt.DefaultContextMenu)
+
def init_neighborlist(self):
"""Initialize the _zoom neighborlist."""
@@ -192,14 +205,14 @@ class WebView(QWebView):
Args:
e: The QMouseEvent.
"""
- if e.button() == Qt.XButton1:
+ if e.button() in (Qt.XButton1, Qt.LeftButton):
# Back button on mice which have it.
if self.page().history().canGoBack():
self.back()
else:
message.error(self._win_id, "At beginning of history.",
immediately=True)
- elif e.button() == Qt.XButton2:
+ elif e.button() in (Qt.XButton2, Qt.RightButton):
# Forward button on mice which have it.
if self.page().history().canGoForward():
self.forward()
@@ -497,7 +510,15 @@ class WebView(QWebView):
Return:
The superclass return value.
"""
- if e.button() in (Qt.XButton1, Qt.XButton2):
+ if e.button() == Qt.LeftButton:
+ self.left_pressed = True
+ elif e.button() == Qt.RightButton:
+ self.right_pressed = True
+
+ if e.button() in (Qt.XButton1, Qt.XButton2) or (
+ e.button() in (Qt.LeftButton, Qt.RightButton)
+ and config.get('input', 'rocker-gestures')
+ and self.right_pressed and self.left_pressed):
self._mousepress_backforward(e)
super().mousePressEvent(e)
return
@@ -507,6 +528,10 @@ class WebView(QWebView):
def mouseReleaseEvent(self, e):
"""Extend mouseReleaseEvent to enter insert mode if needed."""
+ if e.button() == Qt.LeftButton:
+ self.left_pressed = False
+ elif e.button() == Qt.RightButton:
+ self.right_pressed = False
super().mouseReleaseEvent(e)
# We want to make sure we check the focus element after the WebView is
# updated completely.
diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py
index 75703f8..05a0b56 100644
--- a/qutebrowser/config/configdata.py
+++ b/qutebrowser/config/configdata.py
@@ -370,6 +370,10 @@ DATA = collections.OrderedDict([
('links-included-in-focus-chain',
SettingValue(typ.Bool(), 'true'),
"Whether hyperlinks should be included in the keyboard focus chain."),
+
+ ('rocker-gestures',
+ SettingValue(typ.Bool(), 'false'),
+ "Whether to enable Opera-like mouse rocker gestures. This disables the context menu."),
)),
('tabs', sect.KeyValue(