From f49dba6e38a5ed4fbd6a2d8e9920310c2c22ed74 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 15 May 2015 18:59:46 +0200 Subject: [PATCH] Use fake key events for scrolling. Closes #669. Fixes #218. See #246, #534. --- qutebrowser/browser/commands.py | 75 +++++++++++++++++++++++++++++--- qutebrowser/config/configdata.py | 18 ++++++-- tests/config/test_config.py | 13 ++++++ 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 94afb0dc2..55a0c5d22 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -27,8 +27,8 @@ import posixpath import functools from PyQt5.QtWidgets import QApplication, QTabBar -from PyQt5.QtCore import Qt, QUrl -from PyQt5.QtGui import QClipboard +from PyQt5.QtCore import Qt, QUrl, QEvent +from PyQt5.QtGui import QClipboard, QKeyEvent from PyQt5.QtPrintSupport import QPrintDialog, QPrintPreviewDialog from PyQt5.QtWebKitWidgets import QWebPage import pygments @@ -555,8 +555,8 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', hide=True, scope='window', count='count') - def scroll(self, dx: {'type': float}, dy: {'type': float}, count=1): - """Scroll the current tab by 'count * dx/dy'. + def scroll_px(self, dx: {'type': float}, dy: {'type': float}, count=1): + """Scroll the current tab by 'count * dx/dy' pixels. Args: dx: How much to scroll in x-direction. @@ -569,6 +569,57 @@ class CommandDispatcher: cmdutils.check_overflow(dy, 'int') self._current_widget().page().currentFrame().scroll(dx, dy) + @cmdutils.register(instance='command-dispatcher', hide=True, + scope='window', count='count') + def scroll(self, + direction: {'type': (str, float)}, + dy: {'type': float, 'hide': True}=None, + count=1): + """Scroll the current tab in the given direction. + + Args: + direction: In which direction to scroll + (up/down/left/right/top/bottom). + dy: Deprecated argument to support the old dx/dy form. + count: multiplier + """ + try: + # Check for deprecated dx/dy form (like with scroll-px). + dx = float(direction) + dy = float(dy) + except (ValueError, TypeError): + # Invalid values will get handled later. + pass + else: + message.warning(self._win_id, ":scroll with dx/dy arguments is " + "deprecated - use :scroll-px instead!") + self.scroll_px(dx, dy, count=count) + return + + fake_keys = { + 'up': Qt.Key_Up, + 'down': Qt.Key_Down, + 'left': Qt.Key_Left, + 'right': Qt.Key_Right, + 'top': Qt.Key_Home, + 'bottom': Qt.Key_End, + 'page-up': Qt.Key_PageUp, + 'page-down': Qt.Key_PageDown, + } + try: + key = fake_keys[direction] + except KeyError: + raise cmdexc.CommandError("Invalid value {!r} for direction - " + "expected one of: {}".format( + direction, ', '.join(fake_keys))) + widget = self._current_widget() + press_evt = QKeyEvent(QEvent.KeyPress, key, Qt.NoModifier, 0, 0, 0) + release_evt = QKeyEvent(QEvent.KeyRelease, key, Qt.NoModifier, 0, 0, 0) + + for _ in range(count): + widget.keyPressEvent(press_evt) + widget.keyReleaseEvent(release_evt) + @cmdutils.register(instance='command-dispatcher', hide=True, scope='window', count='count') def scroll_perc(self, perc: {'type': float}=None, @@ -596,10 +647,22 @@ class CommandDispatcher: y: How many pages to scroll down. count: multiplier """ + mult_x = count * x + mult_y = count * y + if mult_y.is_integer(): + if mult_y == 0: + pass + elif mult_y < 0: + self.scroll('page-up', count=-mult_y) + elif mult_y > 0: + self.scroll('page-down', count=mult_y) + mult_y = 0 + if mult_x == 0 and mult_y == 0: + return frame = self._current_widget().page().currentFrame() size = frame.geometry() - dx = count * x * size.width() - dy = count * y * size.height() + dx = mult_x * size.width() + dy = mult_y * size.height() cmdutils.check_overflow(dx, 'int') cmdutils.check_overflow(dy, 'int') frame.scroll(dx, dy) diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index c67944eb0..7df7ed9df 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -1143,10 +1143,10 @@ KEY_DATA = collections.OrderedDict([ ('hint --rapid links tab-bg', [';r']), ('hint --rapid links window', [';R']), ('hint links download', [';d']), - ('scroll -50 0', ['h']), - ('scroll 0 50', ['j']), - ('scroll 0 -50', ['k']), - ('scroll 50 0', ['l']), + ('scroll left', ['h']), + ('scroll down', ['j']), + ('scroll up', ['k']), + ('scroll right', ['l']), ('undo', ['u', '']), ('scroll-perc 0', ['gg']), ('scroll-perc', ['G']), @@ -1260,12 +1260,22 @@ KEY_DATA = collections.OrderedDict([ CHANGED_KEY_COMMANDS = [ (re.compile(r'^open -([twb]) about:blank$'), r'open -\1'), + (re.compile(r'^download-page$'), r'download'), (re.compile(r'^cancel-download$'), r'download-cancel'), + (re.compile(r'^search ""$'), r'search'), (re.compile(r"^search ''$"), r'search'), + (re.compile(r"""^set-cmd-text ['"](.*) ['"]$"""), r'set-cmd-text -s \1'), (re.compile(r"""^set-cmd-text ['"](.*)['"]$"""), r'set-cmd-text \1'), + (re.compile(r"^hint links rapid$"), r'hint --rapid links tab-bg'), (re.compile(r"^hint links rapid-win$"), r'hint --rapid links window'), + + (re.compile(r'^scroll -50 0$'), r'scroll left'), + (re.compile(r'^scroll 0 50$'), r'scroll down'), + (re.compile(r'^scroll 0 -50$'), r'scroll up'), + (re.compile(r'^scroll 50 0$'), r'scroll right'), + (re.compile(r'^scroll ([-\d]+ [-\d]+)$'), r'scroll-px \1'), ] diff --git a/tests/config/test_config.py b/tests/config/test_config.py index 6c78990e4..636d89c9b 100644 --- a/tests/config/test_config.py +++ b/tests/config/test_config.py @@ -198,18 +198,31 @@ class TestKeyConfigParser: ('open -b about:blank', 'open -b'), ('open about:blank', None), ('open -t example.com', None), + ('download-page', 'download'), ('cancel-download', 'download-cancel'), + ('search ""', 'search'), ("search ''", 'search'), ('search "foo"', None), + ('set-cmd-text "foo bar"', 'set-cmd-text foo bar'), ("set-cmd-text 'foo bar'", 'set-cmd-text foo bar'), ('set-cmd-text foo bar', None), ('set-cmd-text "foo bar "', 'set-cmd-text -s foo bar'), ("set-cmd-text 'foo bar '", 'set-cmd-text -s foo bar'), + ('hint links rapid', 'hint --rapid links tab-bg'), ('hint links rapid-win', 'hint --rapid links window'), + + ('scroll -50 0', 'scroll left'), + ('scroll 0 50', 'scroll down'), + ('scroll 0 -50', 'scroll up'), + ('scroll 50 0', 'scroll right'), + ('scroll -50 10', 'scroll-px -50 10'), + ('scroll 50 50', 'scroll-px 50 50'), + ('scroll 0 0', 'scroll-px 0 0'), + ('scroll 23 42', 'scroll-px 23 42'), ] ) def test_migrations(self, old, new_expected):