[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [ktexteditor] src: Annoyingly, in Qt 5.5 we can no longer trigger shortcuts by replaying
From: Simon St James <kdedevel () etotheipiplusone ! com>
Date: 2016-06-18 8:35:36
Message-ID: E1bEBj6-0002HX-6I () code ! kde ! org
[Download RAW message or body]
Git commit 025edb11ca9b0fa3685802e6c9cb608a4daa7911 by Simon St James.
Committed on 18/06/2016 at 08:35.
Pushed by sstjames into branch 'master'.
Annoyingly, in Qt 5.5 we can no longer trigger shortcuts by replaying QKeyEvents \
(something that the Vi Mode - which stores and swallows all key events by default in \
case they are part of a Mapping and replays them if it turns out they weren't - \
depends on), so if we are stealing shortcuts, they will no longer be triggered e.g. \
pressing Ctrl+S will not save! This patch reworks the whole mechanism, moving from \
"swallow all QKeyEvents and maybe replay later" to "decide whether to swallow \
shortcuts, but if not, let Qt's shortcut handling system despatch the \
QShortcutOverride itself". This mostly fixes things, though we can't e.g. create a \
mapping that, when triggered, saves the document or triggers any of Kate's shortcuts, \
plus some other small edge cases :(
BUG:35333
REVIEW:D1894
M +1 -1 src/inputmode/kateabstractinputmode.h
M +1 -1 src/inputmode/katenormalinputmode.cpp
M +1 -1 src/inputmode/katenormalinputmode.h
M +25 -22 src/inputmode/kateviinputmode.cpp
M +3 -1 src/inputmode/kateviinputmode.h
M +4 -2 src/vimode/emulatedcommandbar/emulatedcommandbar.cpp
M +2 -1 src/vimode/emulatedcommandbar/emulatedcommandbar.h
M +1 -1 src/vimode/inputmodemanager.cpp
M +28 -2 src/vimode/keymapper.cpp
M +7 -2 src/vimode/modes/normalvimode.cpp
http://commits.kde.org/ktexteditor/025edb11ca9b0fa3685802e6c9cb608a4daa7911
diff --git a/src/inputmode/kateabstractinputmode.h \
b/src/inputmode/kateabstractinputmode.h index 70d9512..c34f3ba 100644
--- a/src/inputmode/kateabstractinputmode.h
+++ b/src/inputmode/kateabstractinputmode.h
@@ -53,7 +53,7 @@ public:
virtual bool overwrite() const = 0;
virtual void overwrittenChar(const QChar &) = 0;
virtual void clearSelection() = 0;
- virtual bool stealKey(const QKeyEvent *) const = 0;
+ virtual bool stealKey(QKeyEvent* k) = 0;
virtual void gotFocus() = 0;
virtual void lostFocus() = 0;
diff --git a/src/inputmode/katenormalinputmode.cpp \
b/src/inputmode/katenormalinputmode.cpp index 4990892..bc18f65 100644
--- a/src/inputmode/katenormalinputmode.cpp
+++ b/src/inputmode/katenormalinputmode.cpp
@@ -67,7 +67,7 @@ void KateNormalInputMode::clearSelection()
view()->clearSelection();
}
-bool KateNormalInputMode::stealKey(const QKeyEvent *) const
+bool KateNormalInputMode::stealKey( QKeyEvent *)
{
return false;
}
diff --git a/src/inputmode/katenormalinputmode.h \
b/src/inputmode/katenormalinputmode.h index fcb4e7f..7baaad0 100644
--- a/src/inputmode/katenormalinputmode.h
+++ b/src/inputmode/katenormalinputmode.h
@@ -46,7 +46,7 @@ public:
void overwrittenChar(const QChar &) Q_DECL_OVERRIDE;
void clearSelection() Q_DECL_OVERRIDE;
- bool stealKey(const QKeyEvent *) const Q_DECL_OVERRIDE;
+ bool stealKey(QKeyEvent *) Q_DECL_OVERRIDE;
void gotFocus() Q_DECL_OVERRIDE;
void lostFocus() Q_DECL_OVERRIDE;
diff --git a/src/inputmode/kateviinputmode.cpp b/src/inputmode/kateviinputmode.cpp
index 557cec1..a7609cd 100644
--- a/src/inputmode/kateviinputmode.cpp
+++ b/src/inputmode/kateviinputmode.cpp
@@ -65,6 +65,7 @@ KateViInputMode::KateViInputMode(KateViewInternal *viewInternal, \
KateVi::GlobalS , m_viModeEmulatedCommandBar(0)
, m_viGlobal(global)
, m_caret(KateRenderer::Block)
+ , m_nextKeypressIsOverriddenShortCut(false)
, m_activated(false)
{
m_relLineNumbers = KateViewConfig::global()->viRelativeLineNumbers();
@@ -131,11 +132,22 @@ void KateViInputMode::clearSelection()
// do nothing, handled elsewhere
}
-bool KateViInputMode::stealKey(const QKeyEvent *k) const
+bool KateViInputMode::stealKey(QKeyEvent *k)
{
- const bool steal = KateViewConfig::global()->viInputModeStealKeys();
- return steal && (m_viModeManager->getCurrentViMode() != \
KateVi::ViMode::InsertMode ||
- k->modifiers() == Qt::ControlModifier || k->key() == \
Qt::Key_Insert); + if (!KateViewConfig::global()->viInputModeStealKeys())
+ {
+ return false;
+ }
+
+ // Actually see if we can make use of this key - if so, we've stolen it; if not,
+ // let Qt's shortcut handling system deal with it.
+ const bool stolen = keyPress(k);
+ if (stolen)
+ {
+ // Qt will replay this QKeyEvent, next time as an ordinary KeyPress.
+ m_nextKeypressIsOverriddenShortCut = true;
+ }
+ return stolen;
}
KTextEditor::View::InputMode KateViInputMode::viewInputMode() const
@@ -255,7 +267,7 @@ void KateViInputMode::showViModeEmulatedCommandBar()
KateVi::EmulatedCommandBar *KateViInputMode::viModeEmulatedCommandBar()
{
if (!m_viModeEmulatedCommandBar) {
- m_viModeEmulatedCommandBar = new KateVi::EmulatedCommandBar(m_viModeManager, \
view()); + m_viModeEmulatedCommandBar = new KateVi::EmulatedCommandBar(this, \
m_viModeManager, view()); m_viModeEmulatedCommandBar->hide();
}
@@ -269,24 +281,15 @@ void KateViInputMode::updateRendererConfig()
bool KateViInputMode::keyPress(QKeyEvent *e)
{
- if (m_viModeManager->getCurrentViMode() == KateVi::InsertMode ||
- m_viModeManager->getCurrentViMode() == KateVi::ReplaceMode) {
+ if (m_nextKeypressIsOverriddenShortCut)
+ {
+ // This is just the replay of a shortcut that we stole, this time as a \
QKeyEvent. + // Ignore it, as we'll have already handled it via stealKey()!
+ m_nextKeypressIsOverriddenShortCut = false;
+ return true;
+ }
- if (m_viModeManager->handleKeypress(e)) {
- return true;
- } else if (e->modifiers() != Qt::NoModifier && e->modifiers() != \
Qt::ShiftModifier) {
- // re-post key events not handled if they have a modifier other than \
shift
- QEvent *copy = new QKeyEvent(e->type(), e->key(), e->modifiers(), \
e->text(),
- e->isAutoRepeat(), e->count());
- QCoreApplication::postEvent(viewInternal()->parent(), copy);
- }
- } else { // !InsertMode
- if (!m_viModeManager->handleKeypress(e)) {
- // we didn't need that keypress, un-steal it :-)
- QEvent *copy = new QKeyEvent(e->type(), e->key(), e->modifiers(), \
e->text(),
- e->isAutoRepeat(), e->count());
- QCoreApplication::postEvent(viewInternal()->parent(), copy);
- }
+ if (m_viModeManager->handleKeypress(e)) {
emit view()->viewModeChanged(view(), viewMode());
return true;
}
diff --git a/src/inputmode/kateviinputmode.h b/src/inputmode/kateviinputmode.h
index 21f95cb..330148f 100644
--- a/src/inputmode/kateviinputmode.h
+++ b/src/inputmode/kateviinputmode.h
@@ -49,7 +49,7 @@ public:
void overwrittenChar(const QChar &) Q_DECL_OVERRIDE;
void clearSelection() Q_DECL_OVERRIDE;
- bool stealKey(const QKeyEvent *) const Q_DECL_OVERRIDE;
+ bool stealKey(QKeyEvent *) Q_DECL_OVERRIDE;
void gotFocus() Q_DECL_OVERRIDE;
void lostFocus() Q_DECL_OVERRIDE;
@@ -92,6 +92,8 @@ private:
KateVi::GlobalState *m_viGlobal;
KateRenderer::caretStyles m_caret;
+ bool m_nextKeypressIsOverriddenShortCut;
+
// configs
bool m_relLineNumbers;
bool m_activated;
diff --git a/src/vimode/emulatedcommandbar/emulatedcommandbar.cpp \
b/src/vimode/emulatedcommandbar/emulatedcommandbar.cpp index 818ec95..3197981 100644
--- a/src/vimode/emulatedcommandbar/emulatedcommandbar.cpp
+++ b/src/vimode/emulatedcommandbar/emulatedcommandbar.cpp
@@ -27,6 +27,7 @@
#include "../globalstate.h"
#include <vimode/keyparser.h>
#include <vimode/inputmodemanager.h>
+#include <inputmode/kateviinputmode.h>
#include <vimode/modes/normalvimode.h>
#include "matchhighlighter.h"
#include "interactivesedreplacemode.h"
@@ -69,8 +70,9 @@ QString escapedForSearchingAsLiteral(const QString \
&originalQtRegex) }
}
-EmulatedCommandBar::EmulatedCommandBar(InputModeManager *viInputModeManager, QWidget \
*parent) +EmulatedCommandBar::EmulatedCommandBar(KateViInputMode* viInputMode, \
InputModeManager *viInputModeManager, QWidget *parent) : KateViewBarWidget(false, \
parent), + m_viInputMode(viInputMode),
m_viInputModeManager(viInputModeManager),
m_view(viInputModeManager->view())
{
@@ -230,7 +232,7 @@ bool EmulatedCommandBar::eventFilter(QObject *object, QEvent \
*event) if (event->type() == QEvent::KeyPress) {
// Re-route this keypress through Vim's central keypress handling area, so \
that we can use the keypress in e.g. // mappings and macros.
- return m_viInputModeManager->handleKeypress(static_cast<QKeyEvent \
*>(event)); + return m_viInputMode->keyPress(static_cast<QKeyEvent *>(event));
}
return false;
}
diff --git a/src/vimode/emulatedcommandbar/emulatedcommandbar.h \
b/src/vimode/emulatedcommandbar/emulatedcommandbar.h index 2751cae..3704662 100644
--- a/src/vimode/emulatedcommandbar/emulatedcommandbar.h
+++ b/src/vimode/emulatedcommandbar/emulatedcommandbar.h
@@ -56,7 +56,7 @@ class KTEXTEDITOR_EXPORT EmulatedCommandBar : public \
KateViewBarWidget
public:
enum Mode { NoMode, SearchForward, SearchBackward, Command };
- explicit EmulatedCommandBar(InputModeManager *viInputModeManager, QWidget \
*parent = 0); + explicit EmulatedCommandBar(KateViInputMode* viInputMode, \
InputModeManager *viInputModeManager, QWidget *parent = 0); virtual \
~EmulatedCommandBar(); void init(Mode mode, const QString &initialText = QString());
bool isActive();
@@ -71,6 +71,7 @@ public:
private:
+ KateViInputMode *m_viInputMode;
InputModeManager *m_viInputModeManager;
bool m_isActive = false;
bool m_wasAborted = true;
diff --git a/src/vimode/inputmodemanager.cpp b/src/vimode/inputmodemanager.cpp
index db06acf..650c09e 100644
--- a/src/vimode/inputmodemanager.cpp
+++ b/src/vimode/inputmodemanager.cpp
@@ -118,7 +118,7 @@ bool InputModeManager::handleKeypress(const QKeyEvent *e)
// of a mapping, we don't want to record them when they are played back by \
m_keyMapper, hence
// the "!isPlayingBackRejectedKeys()". And obviously, since we're recording keys \
before they are mapped, we don't
// want to also record the executed mapping, as when we replayed the macro, we'd \
get duplication!
- if (m_macroRecorder->isRecording() && !m_macroRecorder->isReplaying() && \
!isSyntheticSearchCompletedKeyPress && !keyMapper()->isExecutingMapping() && \
!keyMapper()->isPlayingBackRejectedKeys()) { + if (m_macroRecorder->isRecording() \
&& !m_macroRecorder->isReplaying() && !isSyntheticSearchCompletedKeyPress && \
!keyMapper()->isExecutingMapping() && !keyMapper()->isPlayingBackRejectedKeys() && \
!lastChangeRecorder()->isReplaying()) { m_macroRecorder->record(*e);
}
diff --git a/src/vimode/keymapper.cpp b/src/vimode/keymapper.cpp
index 10091de..887b3f6 100644
--- a/src/vimode/keymapper.cpp
+++ b/src/vimode/keymapper.cpp
@@ -26,6 +26,7 @@
#include <vimode/keymapper.h>
#include <vimode/keyparser.h>
#include <vimode/inputmodemanager.h>
+#include "macrorecorder.h"
#include <QTimer>
@@ -119,8 +120,33 @@ bool KeyMapper::handleKeypress(QChar key)
// We've been swallowing all the keypresses meant for m_keys for our mapping \
keys; now that we know // this cannot be a mapping, restore them.
Q_ASSERT(!isPartialMapping && !isFullMapping);
- playBackRejectedKeys();
- return true;
+ const bool isUserKeypress = \
!m_viInputModeManager->macroRecorder()->isReplaying() && !isExecutingMapping(); + \
if (isUserKeypress && m_mappingKeys.size() == 1) + {
+ // Ugh - unpleasant complication starting with Qt 5.5-ish - it is no
+ // longer possible to replay QKeyEvents in such a way that shortcuts
+ // are triggered, so if we want to correctly handle a shortcut (e.g.
+ // ctrl+s for e.g. Save), we can no longer pop it into m_mappingKeys
+ // then immediately playBackRejectedKeys() (as this will not trigger
+ // the e.g. Save shortcut) - the best we can do is, if e.g. ctrl+s is
+ // not part of any mapping, immediately return false, *not* calling
+ // playBackRejectedKeys() and clearing m_mappingKeys ourselves.
+ // If e.g. ctrl+s *is* part of a mapping, then if the mapping is
+ // rejected, the played back e.g. ctrl+s does not trigger the e.g.
+ // Save shortcut. Likewise, we can no longer have e.g. ctrl+s inside
+ // mappings or macros - the e.g. Save shortcut will not be triggered!
+ // Altogether, a pretty disastrous change from Qt's old behaviour -
+ // either they "fix" it (although it could be argued that being able
+ // to trigger shortcuts from QKeyEvents was never the desired behaviour)
+ // or we try to emulate Shortcut-handling ourselves :(
+ m_mappingKeys.clear();
+ return false;
+ }
+ else
+ {
+ playBackRejectedKeys();
+ return true;
+ }
}
m_doNotMapNextKeypress = false;
return false;
diff --git a/src/vimode/modes/normalvimode.cpp b/src/vimode/modes/normalvimode.cpp
index b306376..e8dbb4f 100644
--- a/src/vimode/modes/normalvimode.cpp
+++ b/src/vimode/modes/normalvimode.cpp
@@ -426,11 +426,16 @@ bool NormalViMode::handleKeypress(const QKeyEvent *e)
}
} else if (m_matchingCommands.size() == 0 && m_matchingMotions.size() == 0) {
resetParser();
- return false;
+ // A bit ugly: we haven't made use of the key event,
+ // but don't want "typeable" keypresses (e.g. a, b, 3, etc) to be marked
+ // as unused as they will then be added to the document, but we don't
+ // want to swallow all keys in case this was a shortcut.
+ // So say we made use of it if and only if it was *not* a shortcut.
+ return e->type() != QEvent::ShortcutOverride;
}
m_matchingMotions.clear();
- return false;
+ return true; // TODO - need to check this - it's currently required for making \
tests pass, but seems odd. }
/**
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic