From 1b3e9613eaa6fc511bc23fed29e4944c8d484620 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 28 Oct 2016 07:34:45 +0200 Subject: [PATCH] Fix mode handling with multi-window questions When the prompt mode is left in any window, we need to take care of: - Cancelling the question if needed (exactly once) - Leaving the prompt mode in all other windows too --- qutebrowser/mainwindow/mainwindow.py | 8 ++++---- qutebrowser/mainwindow/prompt.py | 21 ++++++++++++++++++--- qutebrowser/utils/message.py | 2 ++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 490529180..48763a2f7 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -175,6 +175,9 @@ class MainWindow(QWidget): self._init_completion() + log.init.debug("Initializing modes...") + modeman.init(self.win_id, self) + self._commandrunner = runners.CommandRunner(self.win_id, partial_match=True) @@ -191,9 +194,6 @@ class MainWindow(QWidget): scope='window', window=self.win_id) self._prompt_container.hide() - log.init.debug("Initializing modes...") - modeman.init(self.win_id, self) - if geometry is not None: self._load_geometry(geometry) elif self.win_id == 0: @@ -397,7 +397,7 @@ class MainWindow(QWidget): mode_manager.entered.connect(status.on_mode_entered) mode_manager.left.connect(status.on_mode_left) mode_manager.left.connect(cmd.on_mode_left) - mode_manager.left.connect(prompt.prompt_queue.on_mode_left) + mode_manager.left.connect(message.global_bridge.mode_left) # commands keyparsers[usertypes.KeyMode.normal].keystring_updated.connect( diff --git a/qutebrowser/mainwindow/prompt.py b/qutebrowser/mainwindow/prompt.py index ccf2c3d4d..b4b1c5813 100644 --- a/qutebrowser/mainwindow/prompt.py +++ b/qutebrowser/mainwindow/prompt.py @@ -93,6 +93,7 @@ class PromptQueue(QObject): self._shutting_down = False self._loops = [] self._queue = collections.deque() + message.global_bridge.mode_left.connect(self._on_mode_left) def __repr__(self): return utils.get_repr(self, loops=len(self._loops), @@ -198,14 +199,15 @@ class PromptQueue(QObject): question.completed.connect(self._pop_later) @pyqtSlot(usertypes.KeyMode) - def on_mode_left(self, mode): - """Clear and reset input when the mode was left.""" + def _on_mode_left(self, mode): + """Abort question when a mode was left.""" if self._question is not None: log.prompt.debug("Left mode {}, hiding {}".format( mode, self._question)) self.show_prompts.emit(None) - # FIXME move this somewhere else? if self._question.answer is None and not self._question.is_aborted: + log.prompt.debug("Cancelling {} because {} was left".format( + self._question, mode)) self._question.cancel() self._question = None @@ -257,6 +259,7 @@ class PromptContainer(QWidget): message.global_bridge.prompt_done.connect(self._on_prompt_done) prompt_queue.show_prompts.connect(self._on_show_prompts) + message.global_bridge.mode_left.connect(self._on_global_mode_left) def __repr__(self): return utils.get_repr(self, win_id=self._win_id) @@ -308,6 +311,18 @@ class PromptContainer(QWidget): """Leave the prompt mode in this window if a question was answered.""" modeman.maybe_leave(self._win_id, key_mode, ':prompt-accept') + @pyqtSlot(usertypes.KeyMode) + def _on_global_mode_left(self, mode): + """Leave prompt/yesno mode in this window if it was left elsewhere. + + PromptQueue takes care of getting rid of the question if a mode was + left, but if that happens in a different window, this window will still + be stuck in prompt mode. Here we make sure to leave that if it was left + anywhere else. + """ + if mode in [usertypes.KeyMode.prompt, usertypes.KeyMode.yesno]: + modeman.maybe_leave(self._win_id, mode, 'left in other window') + @cmdutils.register(instance='prompt-container', hide=True, scope='window', modes=[usertypes.KeyMode.prompt, usertypes.KeyMode.yesno]) diff --git a/qutebrowser/utils/message.py b/qutebrowser/utils/message.py index 642ec55b0..4e1250e77 100644 --- a/qutebrowser/utils/message.py +++ b/qutebrowser/utils/message.py @@ -170,11 +170,13 @@ class GlobalMessageBridge(QObject): IMPORTANT: Slots need to be connected to this signal via a Qt.DirectConnection! + mode_left: Emitted when a keymode was left in any window. """ show_message = pyqtSignal(usertypes.MessageLevel, str) prompt_done = pyqtSignal(usertypes.KeyMode) ask_question = pyqtSignal(usertypes.Question, bool) + mode_left = pyqtSignal(usertypes.KeyMode) def ask(self, question, blocking, *, log_stack=False): """Ask a question to the user.