Commit 24479fd3 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Workaround Krita canvas cursor update when application has no input focus

When we have no input focus, we cannot track keyboard key press/release
events (for security reasons). But at the same time, the user can easily
hover Krita canvas, and we should show him somewhat correct cursor.

So here we just try to fetch at least basic modifiers state from mouse/
tablet events. It is perfectly allowed by OS.

Yes, this workaround will not fetch custom modifiers like V-key switch
for straight lines. But I don't think anyone will worry about it.

BUG:369305
parent fb089519
......@@ -31,6 +31,7 @@
#include "kis_touch_shortcut.h"
#include "kis_native_gesture_shortcut.h"
#include "kis_input_profile_manager.h"
#include "kis_extended_modifiers_mapper.h"
/**
* This hungry class EventEater encapsulates event masking logic.
......@@ -337,7 +338,6 @@ bool KisInputManager::Private::CanvasSwitcher::eventFilter(QObject* object, QEve
break;
case QEvent::MouseMove:
case QEvent::TabletMove: {
QWidget *widget = static_cast<QWidget*>(object);
if (!widget->hasFocus()) {
......@@ -621,6 +621,29 @@ bool KisInputManager::Private::handleCompressedTabletEvent(QEvent *event)
{
bool retval = false;
/**
* When Krita (as an application) has no input focus, we cannot
* handle key events. But at the same time, when the user hovers
* Krita canvas, we should still show him the correct cursor.
*
* So here we just add a simple workaround to resync shortcut
* matcher's state at least against the basic modifiers, like
* Shift, Control and Alt.
*/
QWidget *recievingWidget = dynamic_cast<QWidget*>(eventsReceiver);
if (recievingWidget && !recievingWidget->hasFocus()) {
QVector<Qt::Key> guessedKeys;
KisExtendedModifiersMapper mapper;
Qt::KeyboardModifiers modifiers = mapper.queryStandardModifiers();
Q_FOREACH (Qt::Key key, mapper.queryExtendedModifiers()) {
QKeyEvent kevent(QEvent::ShortcutOverride, key, modifiers);
guessedKeys << KisExtendedModifiersMapper::workaroundShiftAltMetaHell(&kevent);
}
matcher.recoveryModifiersWithoutFocus(guessedKeys);
}
if (!matcher.pointerMoved(event) && toolProxy) {
toolProxy->forwardHoverEvent(event);
}
......
......@@ -371,6 +371,32 @@ void KisShortcutMatcher::reinitialize()
}
}
void KisShortcutMatcher::recoveryModifiersWithoutFocus(const QVector<Qt::Key> &keys)
{
QVector<Qt::Key> pressedKeys;
QVector<Qt::Key> releasedKeys;
splitStates(m_d->keys, keys, &pressedKeys, &releasedKeys);
Q_FOREACH (Qt::Key key, m_d->keys) {
if (!keys.contains(key)) {
keyReleased(key);
}
}
Q_FOREACH (Qt::Key key, keys) {
if (!m_d->keys.contains(key)) {
keyPressed(key);
}
}
if (!m_d->runningShortcut) {
prepareReadyShortcuts();
tryActivateReadyShortcut();
}
DEBUG_ACTION("recoverySyncModifiers");
}
void KisShortcutMatcher::lostFocusEvent(const QPointF &localPos)
{
if (m_d->runningShortcut) {
......
......@@ -202,6 +202,16 @@ public:
*/
void reinitialize();
/**
* Resets the internal state of the matcher, tries to resync it to the state
* passed via argument and activates the prepared action if possible.
*
* This synchronization should happen when the user hovers Krita windows,
* **without** having keyboard focus set to it (therefore matcher cannot
* get key press and release events).
*/
void recoveryModifiersWithoutFocus(const QVector<Qt::Key> &keys);
/**
* Kirta lost focus, it means that all the running actions should be ended
* forcefully.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment