From d04fc291632a50058e7bbfabe33390175176dac6 Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Mon, 12 Feb 2018 18:10:22 -0500 Subject: [PATCH 01/13] save input_mode when entering/leaving mode instead of when changing tab --- qutebrowser/keyinput/modeman.py | 10 ++++++++++ qutebrowser/mainwindow/tabbedbrowser.py | 15 ++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py index e32830f50..5204c8068 100644 --- a/qutebrowser/keyinput/modeman.py +++ b/qutebrowser/keyinput/modeman.py @@ -267,6 +267,11 @@ class ModeManager(QObject): raise cmdexc.CommandError( "Mode {} can't be entered manually!".format(mode)) + if (config.val.tabs.mode_on_change == 'restore' and + m.name in ['insert', 'passthrough']): + window = objreg.get('main-window', scope='window', + window=self._win_id) + window.tabbed_browser.currentWidget().data.input_mode = m self.enter(m, 'command') @pyqtSlot(usertypes.KeyMode, str, bool) @@ -301,6 +306,11 @@ class ModeManager(QObject): """Leave the mode we're currently in.""" if self.mode == usertypes.KeyMode.normal: raise ValueError("Can't leave normal mode!") + if config.val.tabs.mode_on_change == 'restore': + window = objreg.get('main-window', scope='window', + window=self._win_id) + tab = window.tabbed_browser.currentWidget() + tab.data.input_mode = usertypes.KeyMode.normal self.leave(self.mode, 'leave current') def eventFilter(self, event): diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index 8cee35524..94fd05b83 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -647,8 +647,6 @@ class TabbedBrowser(tabwidget.TabWidget): def on_current_changed(self, idx): """Set last-focused-tab and leave hinting mode when focus changed.""" mode_on_change = config.val.tabs.mode_on_change - modes_to_save = [usertypes.KeyMode.insert, - usertypes.KeyMode.passthrough] if idx == -1 or self.shutting_down: # closing the last tab (before quitting) or shutting down return @@ -657,23 +655,18 @@ class TabbedBrowser(tabwidget.TabWidget): log.webview.debug("on_current_changed got called with invalid " "index {}".format(idx)) return - if self._now_focused is not None and mode_on_change == 'restore': - current_mode = modeman.instance(self._win_id).mode - if current_mode not in modes_to_save: - current_mode = usertypes.KeyMode.normal - self._now_focused.data.input_mode = current_mode log.modes.debug("Current tab changed, focusing {!r}".format(tab)) tab.setFocus() modes_to_leave = [usertypes.KeyMode.hint, usertypes.KeyMode.caret] - if mode_on_change != 'persist': - modes_to_leave += modes_to_save + if mode_on_change == 'normal': + modes_to_leave += [usertypes.KeyMode.insert, + usertypes.KeyMode.passthrough] for mode in modes_to_leave: modeman.leave(self._win_id, mode, 'tab changed', maybe=True) if mode_on_change == 'restore': - modeman.enter(self._win_id, tab.data.input_mode, - 'restore input mode for tab') + modeman.enter(self._win_id, tab.data.input_mode, 'restore') if self._now_focused is not None: objreg.register('last-focused-tab', self._now_focused, update=True, scope='window', window=self._win_id) From 6214c38d7eaf1061018e2cec8d784c905c3d1544 Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Mon, 12 Feb 2018 18:11:32 -0500 Subject: [PATCH 02/13] add input_mode tests for tabs.mode_on_change --- tests/end2end/features/keyinput.feature | 45 +++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/end2end/features/keyinput.feature b/tests/end2end/features/keyinput.feature index ee5b667e8..08d368a71 100644 --- a/tests/end2end/features/keyinput.feature +++ b/tests/end2end/features/keyinput.feature @@ -162,3 +162,48 @@ Feature: Keyboard input And I press the key "c" Then the message "foo 3" should be shown And the message "foo 3" should be shown + + Scenario: tabs.mode_on_change_restore + Given I clean up open tabs + And I set tabs.mode_on_change to restore + When I open about:blank + And I run :enter-mode insert + And I open about:blank in a new tab + And I run :enter-mode passthrough + And I run :tab-focus 1 + Then "Entering mode KeyMode.insert (reason: command)" should be logged + And "Leaving mode KeyMode.insert (reason: tab changed)" should not be logged + And "Entering mode KeyMode.normal (reason: restore)" should be logged + And "Entering mode KeyMode.passthrough (reason: command)" should be logged + And "Leaving mode KeyMode.passthrough (reason: tab changed)" should not be logged + And "Entering mode KeyMode.insert (reason: restore)" should be logged + + Scenario: tabs.mode_on_change_persist + Given I clean up open tabs + And I set tabs.mode_on_change to persist + When I open about:blank + And I run :enter-mode insert + And I open about:blank in a new tab + And I run :enter-mode passthrough + And I run :tab-focus 1 + Then "Entering mode KeyMode.insert (reason: command)" should be logged + And "Leaving mode KeyMode.insert (reason: tab changed)" should not be logged + And "Entering mode KeyMode.normal (reason: restore)" should not be logged + And "Entering mode KeyMode.passthrough (reason: command)" should be logged + And "Leaving mode KeyMode.passthrough (reason: tab changed)" should not be logged + And "Entering mode KeyMode.insert (reason: restore)" should not be logged + + Scenario: tabs.mode_on_change_normal + Given I clean up open tabs + And I set tabs.mode_on_change to normal + When I open about:blank + And I run :enter-mode insert + And I open about:blank in a new tab + And I run :enter-mode passthrough + And I run :tab-focus 1 + Then "Entering mode KeyMode.insert (reason: command)" should be logged + And "Leaving mode KeyMode.insert (reason: tab changed)" should be logged + And "Entering mode KeyMode.normal (reason: restore)" should not be logged + And "Entering mode KeyMode.passthrough (reason: command)" should be logged + And "Leaving mode KeyMode.passthrough (reason: tab changed)" should be logged + And "Entering mode KeyMode.insert (reason: restore)" should not be logged From fbb78f11330655dd0a68295cee8680cd2d71a18b Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Mon, 12 Feb 2018 21:57:53 -0500 Subject: [PATCH 03/13] hook into modeman's entered and left signals - save previous mode when a prompt is shown - restore previous mode when finished prompting --- qutebrowser/keyinput/modeman.py | 21 ++++++++++----------- qutebrowser/mainwindow/mainwindow.py | 1 + qutebrowser/mainwindow/tabbedbrowser.py | 10 ++++++++++ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py index 5204c8068..585742d36 100644 --- a/qutebrowser/keyinput/modeman.py +++ b/qutebrowser/keyinput/modeman.py @@ -115,6 +115,7 @@ class ModeManager(QObject): Attributes: mode: The mode we're currently in. _win_id: The window ID of this ModeManager + _prev_mode: mode before a prompt poped up _parsers: A dictionary of modes and their keyparsers. _forward_unbound_keys: If we should forward unbound keys. _releaseevents_to_pass: A set of KeyEvents where the keyPressEvent was @@ -138,6 +139,7 @@ class ModeManager(QObject): super().__init__(parent) self._win_id = win_id self._parsers = {} + self._prev_mode = usertypes.KeyMode.normal self.mode = usertypes.KeyMode.normal self._releaseevents_to_pass = set() @@ -247,6 +249,11 @@ class ModeManager(QObject): return log.modes.debug("Overriding mode {}.".format(self.mode)) self.left.emit(self.mode, mode, self._win_id) + if mode in prompt_modes: + # save previous mode when being prompted + self._prev_mode = self.mode + else: + self._prev_mode = usertypes.KeyMode.normal self.mode = mode self.entered.emit(mode, self._win_id) @@ -266,12 +273,6 @@ class ModeManager(QObject): usertypes.KeyMode.yesno, usertypes.KeyMode.prompt]: raise cmdexc.CommandError( "Mode {} can't be entered manually!".format(mode)) - - if (config.val.tabs.mode_on_change == 'restore' and - m.name in ['insert', 'passthrough']): - window = objreg.get('main-window', scope='window', - window=self._win_id) - window.tabbed_browser.currentWidget().data.input_mode = m self.enter(m, 'command') @pyqtSlot(usertypes.KeyMode, str, bool) @@ -299,6 +300,9 @@ class ModeManager(QObject): self.clear_keychain() self.mode = usertypes.KeyMode.normal self.left.emit(mode, self.mode, self._win_id) + if mode in [usertypes.KeyMode.prompt, usertypes.KeyMode.yesno]: + self.enter(self._prev_mode, + reason='restore mode before {}'.format(mode.name)) @cmdutils.register(instance='mode-manager', name='leave-mode', not_modes=[usertypes.KeyMode.normal], scope='window') @@ -306,11 +310,6 @@ class ModeManager(QObject): """Leave the mode we're currently in.""" if self.mode == usertypes.KeyMode.normal: raise ValueError("Can't leave normal mode!") - if config.val.tabs.mode_on_change == 'restore': - window = objreg.get('main-window', scope='window', - window=self._win_id) - tab = window.tabbed_browser.currentWidget() - tab.data.input_mode = usertypes.KeyMode.normal self.leave(self.mode, 'leave current') def eventFilter(self, event): diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 05482a1d5..18b349d5d 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -484,6 +484,7 @@ class MainWindow(QWidget): self.tabbed_browser.cur_fullscreen_requested.connect(status.maybe_hide) # command input / completion + mode_manager.entered.connect(self.tabbed_browser.on_mode_entered) mode_manager.left.connect(self.tabbed_browser.on_mode_left) cmd.clear_completion_selection.connect( completion_obj.on_clear_completion_selection) diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index 94fd05b83..7d60369d3 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -631,6 +631,14 @@ class TabbedBrowser(tabwidget.TabWidget): if config.val.tabs.tabs_are_windows: self.window().setWindowIcon(icon) + @pyqtSlot(usertypes.KeyMode) + def on_mode_entered(self, mode): + """Save input mode when tabs.mode_on_change = restore.""" + input_modes = [usertypes.KeyMode.insert, usertypes.KeyMode.passthrough] + if (mode in input_modes and + config.val.tabs.mode_on_change == 'restore'): + self.currentWidget().data.input_mode = mode + @pyqtSlot(usertypes.KeyMode) def on_mode_left(self, mode): """Give focus to current tab if command mode was left.""" @@ -642,6 +650,8 @@ class TabbedBrowser(tabwidget.TabWidget): if widget is None: return widget.setFocus() + elif config.val.tabs.mode_on_change == 'restore': + self.currentWidget().data.input_mode = usertypes.KeyMode.normal @pyqtSlot(int) def on_current_changed(self, idx): From e38df261cb38d389598a26b6f6c61476ddfa52d8 Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Tue, 13 Feb 2018 13:00:44 -0500 Subject: [PATCH 04/13] skip this test for qt>=5.10 until the log problem gets resolved --- tests/end2end/features/keyinput.feature | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/end2end/features/keyinput.feature b/tests/end2end/features/keyinput.feature index 08d368a71..29e9f94fa 100644 --- a/tests/end2end/features/keyinput.feature +++ b/tests/end2end/features/keyinput.feature @@ -178,6 +178,8 @@ Feature: Keyboard input And "Leaving mode KeyMode.passthrough (reason: tab changed)" should not be logged And "Entering mode KeyMode.insert (reason: restore)" should be logged + # we skip this for now because the logs are still present from the previous test with qt>=5.10 + @qt<5.10 Scenario: tabs.mode_on_change_persist Given I clean up open tabs And I set tabs.mode_on_change to persist From f94e12008a084cf0a44c330cd877edb6979445f3 Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Tue, 13 Feb 2018 16:23:56 -0500 Subject: [PATCH 05/13] fix the tests by clearing history --- tests/end2end/features/keyinput.feature | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/end2end/features/keyinput.feature b/tests/end2end/features/keyinput.feature index 29e9f94fa..9c709ae09 100644 --- a/tests/end2end/features/keyinput.feature +++ b/tests/end2end/features/keyinput.feature @@ -163,25 +163,25 @@ Feature: Keyboard input Then the message "foo 3" should be shown And the message "foo 3" should be shown - Scenario: tabs.mode_on_change_restore - Given I clean up open tabs - And I set tabs.mode_on_change to restore + # :test all tabs.mode_on_change modes + + Scenario: mode on change normal + Given I run :history-clear --force + And I set tabs.mode_on_change to normal When I open about:blank And I run :enter-mode insert And I open about:blank in a new tab And I run :enter-mode passthrough And I run :tab-focus 1 Then "Entering mode KeyMode.insert (reason: command)" should be logged - And "Leaving mode KeyMode.insert (reason: tab changed)" should not be logged - And "Entering mode KeyMode.normal (reason: restore)" should be logged + And "Leaving mode KeyMode.insert (reason: tab changed)" should be logged + And "Entering mode KeyMode.normal (reason: restore)" should not be logged And "Entering mode KeyMode.passthrough (reason: command)" should be logged - And "Leaving mode KeyMode.passthrough (reason: tab changed)" should not be logged - And "Entering mode KeyMode.insert (reason: restore)" should be logged + And "Leaving mode KeyMode.passthrough (reason: tab changed)" should be logged + And "Entering mode KeyMode.insert (reason: restore)" should not be logged - # we skip this for now because the logs are still present from the previous test with qt>=5.10 - @qt<5.10 - Scenario: tabs.mode_on_change_persist - Given I clean up open tabs + Scenario: mode on change persist + Given I run :history-clear --force And I set tabs.mode_on_change to persist When I open about:blank And I run :enter-mode insert @@ -195,17 +195,17 @@ Feature: Keyboard input And "Leaving mode KeyMode.passthrough (reason: tab changed)" should not be logged And "Entering mode KeyMode.insert (reason: restore)" should not be logged - Scenario: tabs.mode_on_change_normal - Given I clean up open tabs - And I set tabs.mode_on_change to normal + Scenario: mode on change restore + Given I run :history-clear --force + And I set tabs.mode_on_change to restore When I open about:blank And I run :enter-mode insert And I open about:blank in a new tab And I run :enter-mode passthrough And I run :tab-focus 1 Then "Entering mode KeyMode.insert (reason: command)" should be logged - And "Leaving mode KeyMode.insert (reason: tab changed)" should be logged - And "Entering mode KeyMode.normal (reason: restore)" should not be logged + And "Leaving mode KeyMode.insert (reason: tab changed)" should not be logged + And "Entering mode KeyMode.normal (reason: restore)" should be logged And "Entering mode KeyMode.passthrough (reason: command)" should be logged - And "Leaving mode KeyMode.passthrough (reason: tab changed)" should be logged - And "Entering mode KeyMode.insert (reason: restore)" should not be logged + And "Leaving mode KeyMode.passthrough (reason: tab changed)" should not be logged + And "Entering mode KeyMode.insert (reason: restore)" should be logged From 9b8a182a78a2ced11063ca3b44faa1ff1f5696bb Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Tue, 13 Feb 2018 17:03:01 -0500 Subject: [PATCH 06/13] history-clear does nothing to help here --- tests/end2end/features/keyinput.feature | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/end2end/features/keyinput.feature b/tests/end2end/features/keyinput.feature index 9c709ae09..fb2e546b7 100644 --- a/tests/end2end/features/keyinput.feature +++ b/tests/end2end/features/keyinput.feature @@ -166,8 +166,7 @@ Feature: Keyboard input # :test all tabs.mode_on_change modes Scenario: mode on change normal - Given I run :history-clear --force - And I set tabs.mode_on_change to normal + Given I set tabs.mode_on_change to normal When I open about:blank And I run :enter-mode insert And I open about:blank in a new tab @@ -181,8 +180,7 @@ Feature: Keyboard input And "Entering mode KeyMode.insert (reason: restore)" should not be logged Scenario: mode on change persist - Given I run :history-clear --force - And I set tabs.mode_on_change to persist + Given I set tabs.mode_on_change to persist When I open about:blank And I run :enter-mode insert And I open about:blank in a new tab @@ -196,8 +194,7 @@ Feature: Keyboard input And "Entering mode KeyMode.insert (reason: restore)" should not be logged Scenario: mode on change restore - Given I run :history-clear --force - And I set tabs.mode_on_change to restore + Given I set tabs.mode_on_change to restore When I open about:blank And I run :enter-mode insert And I open about:blank in a new tab From 8a3049f09bad2cecb5be6eb3e0d39b649faa439e Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Wed, 14 Feb 2018 08:33:32 -0500 Subject: [PATCH 07/13] make sure there IS a current widget before using it --- qutebrowser/mainwindow/tabbedbrowser.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index 7d60369d3..a5cf7958e 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -637,7 +637,9 @@ class TabbedBrowser(tabwidget.TabWidget): input_modes = [usertypes.KeyMode.insert, usertypes.KeyMode.passthrough] if (mode in input_modes and config.val.tabs.mode_on_change == 'restore'): - self.currentWidget().data.input_mode = mode + tab = self.currentWidget() + if tab != 0: + tab.data.input_mode = mode @pyqtSlot(usertypes.KeyMode) def on_mode_left(self, mode): @@ -651,7 +653,9 @@ class TabbedBrowser(tabwidget.TabWidget): return widget.setFocus() elif config.val.tabs.mode_on_change == 'restore': - self.currentWidget().data.input_mode = usertypes.KeyMode.normal + tab = self.currentWidget() + if tab != 0: + tab.data.input_mode = usertypes.KeyMode.normal @pyqtSlot(int) def on_current_changed(self, idx): From b791dd3eb4966a41e6cebae76b9613b558eaaa20 Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Wed, 14 Feb 2018 09:44:40 -0500 Subject: [PATCH 08/13] no restore while in prompt modes on tab change --- qutebrowser/mainwindow/tabbedbrowser.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index a5cf7958e..64fdfed10 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -673,13 +673,18 @@ class TabbedBrowser(tabwidget.TabWidget): log.modes.debug("Current tab changed, focusing {!r}".format(tab)) tab.setFocus() + prompt_modes = [usertypes.KeyMode.prompt, usertypes.KeyMode.yesno] modes_to_leave = [usertypes.KeyMode.hint, usertypes.KeyMode.caret] + + mm_instance = modeman.instance(self._win_id) + current_mode = mm_instance.mode + if mode_on_change == 'normal': modes_to_leave += [usertypes.KeyMode.insert, usertypes.KeyMode.passthrough] for mode in modes_to_leave: modeman.leave(self._win_id, mode, 'tab changed', maybe=True) - if mode_on_change == 'restore': + if mode_on_change == 'restore' and current_mode not in prompt_modes: modeman.enter(self._win_id, tab.data.input_mode, 'restore') if self._now_focused is not None: objreg.register('last-focused-tab', self._now_focused, update=True, From 620a966d1e9d5e96382eeaf62e1368588bf7c0a3 Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Wed, 14 Feb 2018 09:58:23 -0500 Subject: [PATCH 09/13] add debug logs and adjust tests to use them --- qutebrowser/mainwindow/tabbedbrowser.py | 5 ++++- tests/end2end/features/keyinput.feature | 27 +++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index 64fdfed10..00da9ea86 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -678,7 +678,8 @@ class TabbedBrowser(tabwidget.TabWidget): mm_instance = modeman.instance(self._win_id) current_mode = mm_instance.mode - + log.modes.debug("{}: mode before tab change: {}." + .format(mode_on_change, current_mode.name)) if mode_on_change == 'normal': modes_to_leave += [usertypes.KeyMode.insert, usertypes.KeyMode.passthrough] @@ -689,6 +690,8 @@ class TabbedBrowser(tabwidget.TabWidget): if self._now_focused is not None: objreg.register('last-focused-tab', self._now_focused, update=True, scope='window', window=self._win_id) + log.modes.debug("{}: mode after tab change: {}." + .format(mode_on_change, mm_instance.mode.name)) self._now_focused = tab self.current_tab_changed.emit(tab) QTimer.singleShot(0, self._update_window_title) diff --git a/tests/end2end/features/keyinput.feature b/tests/end2end/features/keyinput.feature index fb2e546b7..db21831b6 100644 --- a/tests/end2end/features/keyinput.feature +++ b/tests/end2end/features/keyinput.feature @@ -167,42 +167,39 @@ Feature: Keyboard input Scenario: mode on change normal Given I set tabs.mode_on_change to normal + And I clean up open tabs When I open about:blank And I run :enter-mode insert And I open about:blank in a new tab - And I run :enter-mode passthrough - And I run :tab-focus 1 Then "Entering mode KeyMode.insert (reason: command)" should be logged And "Leaving mode KeyMode.insert (reason: tab changed)" should be logged - And "Entering mode KeyMode.normal (reason: restore)" should not be logged - And "Entering mode KeyMode.passthrough (reason: command)" should be logged - And "Leaving mode KeyMode.passthrough (reason: tab changed)" should be logged - And "Entering mode KeyMode.insert (reason: restore)" should not be logged + And "normal: mode before tab change: insert." should be logged + And "normal: mode after tab change: normal." should be logged Scenario: mode on change persist Given I set tabs.mode_on_change to persist + And I clean up open tabs When I open about:blank And I run :enter-mode insert And I open about:blank in a new tab - And I run :enter-mode passthrough - And I run :tab-focus 1 Then "Entering mode KeyMode.insert (reason: command)" should be logged - And "Leaving mode KeyMode.insert (reason: tab changed)" should not be logged - And "Entering mode KeyMode.normal (reason: restore)" should not be logged - And "Entering mode KeyMode.passthrough (reason: command)" should be logged - And "Leaving mode KeyMode.passthrough (reason: tab changed)" should not be logged - And "Entering mode KeyMode.insert (reason: restore)" should not be logged + And "persist: mode before tab change: insert." should be logged + And "persist: mode after tab change: insert." should be logged Scenario: mode on change restore Given I set tabs.mode_on_change to restore + And I clean up open tabs When I open about:blank And I run :enter-mode insert And I open about:blank in a new tab And I run :enter-mode passthrough And I run :tab-focus 1 Then "Entering mode KeyMode.insert (reason: command)" should be logged - And "Leaving mode KeyMode.insert (reason: tab changed)" should not be logged + And "restore: mode before tab change: insert." should be logged And "Entering mode KeyMode.normal (reason: restore)" should be logged + And "restore: mode after tab change: normal." should be logged And "Entering mode KeyMode.passthrough (reason: command)" should be logged - And "Leaving mode KeyMode.passthrough (reason: tab changed)" should not be logged + And "restore: mode before tab change: passthrough." should be logged And "Entering mode KeyMode.insert (reason: restore)" should be logged + And "restore: mode after tab change: insert." should be logged + From 872cff2ae18b908a4c4c2f6f6ffa1a5911b98729 Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Fri, 16 Feb 2018 14:03:11 -0500 Subject: [PATCH 10/13] make sure tab is not None either, had a crash because of this --- qutebrowser/mainwindow/tabbedbrowser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index 00da9ea86..389cc1dc4 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -638,7 +638,7 @@ class TabbedBrowser(tabwidget.TabWidget): if (mode in input_modes and config.val.tabs.mode_on_change == 'restore'): tab = self.currentWidget() - if tab != 0: + if tab and tab is not None: tab.data.input_mode = mode @pyqtSlot(usertypes.KeyMode) @@ -654,7 +654,7 @@ class TabbedBrowser(tabwidget.TabWidget): widget.setFocus() elif config.val.tabs.mode_on_change == 'restore': tab = self.currentWidget() - if tab != 0: + if tab and tab is not None: tab.data.input_mode = usertypes.KeyMode.normal @pyqtSlot(int) From 5992688926d6a9bccaa10d5ab4080e549d4cbf0c Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Wed, 7 Mar 2018 11:43:17 -0500 Subject: [PATCH 11/13] Save input modes when mode_on_change=='restore' --- qutebrowser/keyinput/modeman.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py index 585742d36..3f706d43c 100644 --- a/qutebrowser/keyinput/modeman.py +++ b/qutebrowser/keyinput/modeman.py @@ -236,6 +236,7 @@ class ModeManager(QObject): if mode not in self._parsers: raise ValueError("No keyparser for mode {}".format(mode)) prompt_modes = (usertypes.KeyMode.prompt, usertypes.KeyMode.yesno) + input_modes = [usertypes.KeyMode.insert, usertypes.KeyMode.passthrough] if self.mode == mode or (self.mode in prompt_modes and mode in prompt_modes): log.modes.debug("Ignoring request as we're in mode {} " @@ -249,7 +250,8 @@ class ModeManager(QObject): return log.modes.debug("Overriding mode {}.".format(self.mode)) self.left.emit(self.mode, mode, self._win_id) - if mode in prompt_modes: + if (mode in prompt_modes and self.mode in input_modes and + config.val.tabs.mode_on_change == 'restore'): # save previous mode when being prompted self._prev_mode = self.mode else: @@ -273,6 +275,7 @@ class ModeManager(QObject): usertypes.KeyMode.yesno, usertypes.KeyMode.prompt]: raise cmdexc.CommandError( "Mode {} can't be entered manually!".format(mode)) + self.enter(m, 'command') @pyqtSlot(usertypes.KeyMode, str, bool) From 7c2802e84312904f83e24e2ef336d3731e863bde Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Wed, 7 Mar 2018 11:46:14 -0500 Subject: [PATCH 12/13] beautify code as requested --- qutebrowser/mainwindow/tabbedbrowser.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index 389cc1dc4..7914aca63 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -635,10 +635,9 @@ class TabbedBrowser(tabwidget.TabWidget): def on_mode_entered(self, mode): """Save input mode when tabs.mode_on_change = restore.""" input_modes = [usertypes.KeyMode.insert, usertypes.KeyMode.passthrough] - if (mode in input_modes and - config.val.tabs.mode_on_change == 'restore'): + if mode in input_modes and config.val.tabs.mode_on_change == 'restore': tab = self.currentWidget() - if tab and tab is not None: + if tab is not None: tab.data.input_mode = mode @pyqtSlot(usertypes.KeyMode) @@ -654,7 +653,7 @@ class TabbedBrowser(tabwidget.TabWidget): widget.setFocus() elif config.val.tabs.mode_on_change == 'restore': tab = self.currentWidget() - if tab and tab is not None: + if tab is not None: tab.data.input_mode = usertypes.KeyMode.normal @pyqtSlot(int) From c9f6cd507b55dabe4d4d8f7841955837a634ff20 Mon Sep 17 00:00:00 2001 From: Marc Jauvin Date: Tue, 13 Mar 2018 23:31:48 -0400 Subject: [PATCH 13/13] address requested changes - add INPUT_MODES & PROMPT_MODES constants in modeman - use those in tabbedbrowser and modeman - fix debug logs format to be more human readable - fix associated tests for new debug logs --- qutebrowser/keyinput/modeman.py | 16 ++++++------ qutebrowser/mainwindow/tabbedbrowser.py | 34 +++++++++++-------------- tests/end2end/features/keyinput.feature | 19 +++++++------- 3 files changed, 33 insertions(+), 36 deletions(-) diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py index 3f706d43c..4e9d78fb0 100644 --- a/qutebrowser/keyinput/modeman.py +++ b/qutebrowser/keyinput/modeman.py @@ -30,6 +30,9 @@ from qutebrowser.config import config from qutebrowser.commands import cmdexc, cmdutils from qutebrowser.utils import usertypes, log, objreg, utils +INPUT_MODES = [usertypes.KeyMode.insert, usertypes.KeyMode.passthrough] +PROMPT_MODES = [usertypes.KeyMode.prompt, usertypes.KeyMode.yesno] + @attr.s(frozen=True) class KeyEvent: @@ -115,7 +118,7 @@ class ModeManager(QObject): Attributes: mode: The mode we're currently in. _win_id: The window ID of this ModeManager - _prev_mode: mode before a prompt poped up + _prev_mode: Mode before a prompt popped up _parsers: A dictionary of modes and their keyparsers. _forward_unbound_keys: If we should forward unbound keys. _releaseevents_to_pass: A set of KeyEvents where the keyPressEvent was @@ -235,10 +238,8 @@ class ModeManager(QObject): mode, '' if reason is None else ' (reason: {})'.format(reason))) if mode not in self._parsers: raise ValueError("No keyparser for mode {}".format(mode)) - prompt_modes = (usertypes.KeyMode.prompt, usertypes.KeyMode.yesno) - input_modes = [usertypes.KeyMode.insert, usertypes.KeyMode.passthrough] - if self.mode == mode or (self.mode in prompt_modes and - mode in prompt_modes): + if self.mode == mode or (self.mode in PROMPT_MODES and + mode in PROMPT_MODES): log.modes.debug("Ignoring request as we're in mode {} " "already.".format(self.mode)) return @@ -250,9 +251,8 @@ class ModeManager(QObject): return log.modes.debug("Overriding mode {}.".format(self.mode)) self.left.emit(self.mode, mode, self._win_id) - if (mode in prompt_modes and self.mode in input_modes and + if (mode in PROMPT_MODES and self.mode in INPUT_MODES and config.val.tabs.mode_on_change == 'restore'): - # save previous mode when being prompted self._prev_mode = self.mode else: self._prev_mode = usertypes.KeyMode.normal @@ -303,7 +303,7 @@ class ModeManager(QObject): self.clear_keychain() self.mode = usertypes.KeyMode.normal self.left.emit(mode, self.mode, self._win_id) - if mode in [usertypes.KeyMode.prompt, usertypes.KeyMode.yesno]: + if mode in PROMPT_MODES: self.enter(self._prev_mode, reason='restore mode before {}'.format(mode.name)) diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index 7914aca63..df5ab5584 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -634,8 +634,8 @@ class TabbedBrowser(tabwidget.TabWidget): @pyqtSlot(usertypes.KeyMode) def on_mode_entered(self, mode): """Save input mode when tabs.mode_on_change = restore.""" - input_modes = [usertypes.KeyMode.insert, usertypes.KeyMode.passthrough] - if mode in input_modes and config.val.tabs.mode_on_change == 'restore': + if (config.val.tabs.mode_on_change == 'restore' and + mode in modeman.INPUT_MODES): tab = self.currentWidget() if tab is not None: tab.data.input_mode = mode @@ -643,18 +643,15 @@ class TabbedBrowser(tabwidget.TabWidget): @pyqtSlot(usertypes.KeyMode) def on_mode_left(self, mode): """Give focus to current tab if command mode was left.""" - if mode in [usertypes.KeyMode.command, usertypes.KeyMode.prompt, - usertypes.KeyMode.yesno]: - widget = self.currentWidget() + widget = self.currentWidget() + if widget is None: + return + if mode in [usertypes.KeyMode.command] + modeman.PROMPT_MODES: log.modes.debug("Left status-input mode, focusing {!r}".format( widget)) - if widget is None: - return widget.setFocus() - elif config.val.tabs.mode_on_change == 'restore': - tab = self.currentWidget() - if tab is not None: - tab.data.input_mode = usertypes.KeyMode.normal + if config.val.tabs.mode_on_change == 'restore': + widget.data.input_mode = usertypes.KeyMode.normal @pyqtSlot(int) def on_current_changed(self, idx): @@ -672,25 +669,24 @@ class TabbedBrowser(tabwidget.TabWidget): log.modes.debug("Current tab changed, focusing {!r}".format(tab)) tab.setFocus() - prompt_modes = [usertypes.KeyMode.prompt, usertypes.KeyMode.yesno] modes_to_leave = [usertypes.KeyMode.hint, usertypes.KeyMode.caret] mm_instance = modeman.instance(self._win_id) current_mode = mm_instance.mode - log.modes.debug("{}: mode before tab change: {}." - .format(mode_on_change, current_mode.name)) + log.modes.debug("Mode before tab change: {} (mode_on_change = {})" + .format(current_mode.name, mode_on_change)) if mode_on_change == 'normal': - modes_to_leave += [usertypes.KeyMode.insert, - usertypes.KeyMode.passthrough] + modes_to_leave += modeman.INPUT_MODES for mode in modes_to_leave: modeman.leave(self._win_id, mode, 'tab changed', maybe=True) - if mode_on_change == 'restore' and current_mode not in prompt_modes: + if (mode_on_change == 'restore' and + current_mode not in modeman.PROMPT_MODES): modeman.enter(self._win_id, tab.data.input_mode, 'restore') if self._now_focused is not None: objreg.register('last-focused-tab', self._now_focused, update=True, scope='window', window=self._win_id) - log.modes.debug("{}: mode after tab change: {}." - .format(mode_on_change, mm_instance.mode.name)) + log.modes.debug("Mode after tab change: {} (mode_on_change = {})" + .format(current_mode.name, mode_on_change)) self._now_focused = tab self.current_tab_changed.emit(tab) QTimer.singleShot(0, self._update_window_title) diff --git a/tests/end2end/features/keyinput.feature b/tests/end2end/features/keyinput.feature index db21831b6..5a857002a 100644 --- a/tests/end2end/features/keyinput.feature +++ b/tests/end2end/features/keyinput.feature @@ -163,7 +163,7 @@ Feature: Keyboard input Then the message "foo 3" should be shown And the message "foo 3" should be shown - # :test all tabs.mode_on_change modes + # test all tabs.mode_on_change modes Scenario: mode on change normal Given I set tabs.mode_on_change to normal @@ -173,8 +173,8 @@ Feature: Keyboard input And I open about:blank in a new tab Then "Entering mode KeyMode.insert (reason: command)" should be logged And "Leaving mode KeyMode.insert (reason: tab changed)" should be logged - And "normal: mode before tab change: insert." should be logged - And "normal: mode after tab change: normal." should be logged + And "Mode before tab change: insert (mode_on_change = normal)" should be logged + And "Mode after tab change: normal (mode_on_change = normal)" should be logged Scenario: mode on change persist Given I set tabs.mode_on_change to persist @@ -183,8 +183,9 @@ Feature: Keyboard input And I run :enter-mode insert And I open about:blank in a new tab Then "Entering mode KeyMode.insert (reason: command)" should be logged - And "persist: mode before tab change: insert." should be logged - And "persist: mode after tab change: insert." should be logged + And "Leaving mode KeyMode.insert (reason: tab changed)" should not be logged + And "Mode before tab change: insert (mode_on_change = persist)" should be logged + And "Mode after tab change: insert (mode_on_change = persist)" should be logged Scenario: mode on change restore Given I set tabs.mode_on_change to restore @@ -195,11 +196,11 @@ Feature: Keyboard input And I run :enter-mode passthrough And I run :tab-focus 1 Then "Entering mode KeyMode.insert (reason: command)" should be logged - And "restore: mode before tab change: insert." should be logged + And "Mode before tab change: insert (mode_on_change = restore)" should be logged And "Entering mode KeyMode.normal (reason: restore)" should be logged - And "restore: mode after tab change: normal." should be logged + And "Mode after tab change: normal (mode_on_change = restore)" should be logged And "Entering mode KeyMode.passthrough (reason: command)" should be logged - And "restore: mode before tab change: passthrough." should be logged + And "Mode before tab change: passthrough (mode_on_change = restore)" should be logged And "Entering mode KeyMode.insert (reason: restore)" should be logged - And "restore: mode after tab change: insert." should be logged + And "Mode after tab change: insert (mode_on_change = restore)" should be logged