10#include <QApplication>
11#include <QScopedPointer>
15#include <boost/preprocessor/repeat_from_to.hpp>
28#include "config-qt-patches-present.h"
40 , moveEventCompressor(10 ,
43 , priorityEventFilterSeqNo(0)
44 , popupWidget(nullptr)
45 , canvasSwitcher(this, qq)
80#if defined Q_OS_LINUX && !KRITA_QT_HAS_UNBALANCED_KEY_PRESS_RELEASE_PATCH
84 if (qEnvironmentVariableIsSet(
"KRITA_FIX_UNBALANCED_KEY_EVENTS")) {
95 eatOneMouseStroke(false),
102 QWidget *widget = qobject_cast<QWidget*>(
object);
105 thresholdConnections.clear();
106 thresholdConnections.addConnection(&focusSwitchThreshold, SIGNAL(timeout()), widget, SLOT(setFocus()));
113 QObject *canvasWidget =
canvas->canvasWidget();
115 if (!canvasResolver.contains(canvasWidget)) {
116 canvasResolver.insert(canvasWidget,
canvas);
125 canvasWidget->installEventFilter(
this);
127 setupFocusThreshold(canvasWidget);
128 focusSwitchThreshold.setEnabled(
false);
137 QObject *widget =
canvas->canvasWidget();
139 canvasResolver.remove(widget);
145 widget->removeEventFilter(
this);
155 if (!w)
return false;
159 types << QLatin1String(
"QAbstractSlider");
160 types << QLatin1String(
"QAbstractSpinBox");
161 types << QLatin1String(
"QLineEdit");
162 types << QLatin1String(
"QTextEdit");
163 types << QLatin1String(
"QPlainTextEdit");
164 types << QLatin1String(
"QComboBox");
165 types << QLatin1String(
"QKeySequenceEdit");
167 Q_FOREACH (
const QLatin1String &type, types) {
168 if (w->inherits(type.data())) {
178 if (canvasResolver.contains(
object)) {
179 switch (event->type()) {
180 case QEvent::FocusIn: {
181 QFocusEvent *fevent =
static_cast<QFocusEvent*
>(event);
189 eatOneMouseStroke = 2 * (fevent->reason() == Qt::MouseFocusReason);
197 object->removeEventFilter(
this);
198 object->installEventFilter(
this);
200 setupFocusThreshold(
object);
201 focusSwitchThreshold.setEnabled(
false);
203 const QPoint globalPos = QCursor::pos();
204 const QPoint localPos =
d->
canvas->canvasWidget()->mapFromGlobal(globalPos);
205 QWidget *canvasWindow =
d->
canvas->canvasWidget()->window();
206 const QPoint windowsPos = canvasWindow ? canvasWindow->mapFromGlobal(globalPos) : localPos;
208 QEnterEvent event(localPos, windowsPos, globalPos);
212 case QEvent::FocusOut: {
213 focusSwitchThreshold.setEnabled(
true);
216 case QEvent::Enter: {
219 case QEvent::Leave: {
220 focusSwitchThreshold.stop();
223 case QEvent::Wheel: {
224 QWidget *widget =
static_cast<QWidget*
>(object);
228 case QEvent::MouseButtonPress:
229 case QEvent::MouseButtonRelease:
230 case QEvent::TabletPress:
231 case QEvent::TabletRelease:
232 focusSwitchThreshold.forceDone();
234 if (eatOneMouseStroke) {
239 case QEvent::MouseButtonDblClick:
240 focusSwitchThreshold.forceDone();
241 if (eatOneMouseStroke) {
245 case QEvent::MouseMove:
246 case QEvent::TabletMove: {
247 QWidget *widget =
static_cast<QWidget*
>(object);
249 if (!widget->hasFocus()) {
254 focusSwitchThreshold.setDelayThreshold(delay);
255 focusSwitchThreshold.start();
263 return QObject::eventFilter(
object, event);
272 switch (event->type()) {
273 case QEvent::TabletEnterProximity:
274 KisInputEventsEater::debugEvent<QEvent>(event);
277 case QEvent::TabletLeaveProximity:
278 KisInputEventsEater::debugEvent<QEvent>(event);
282 case QEvent::KeyPress:
283 case QEvent::KeyRelease:
284 case QEvent::ShortcutOverride:
285 if (
d->ignoreHighFunctionKeys) {
286 QKeyEvent *keyEvent =
static_cast<QKeyEvent *
>(event);
287 int key = keyEvent->key();
289 if (key >= Qt::Key_F13 && key <= Qt::Key_F35) {
291 const QString pre =
"[BLOCKED HIGH F-KEY]";
302 return QObject::eventFilter(
object, event);
305#define EXTRA_BUTTON(z, n, _) \
306 if(buttons & Qt::ExtraButton##n) { \
307 buttonSet << Qt::ExtraButton##n; \
317 QSet<Qt::MouseButton> buttonSet;
319 buttonSet << Qt::LeftButton;
321 if(
buttons & Qt::RightButton) {
322 buttonSet << Qt::RightButton;
324 if(
buttons & Qt::MiddleButton) {
325 buttonSet << Qt::MiddleButton;
330 if (!buttonSet.empty()) {
331 strokeShortcut->
setButtons(QSet<Qt::Key>(modifiers.cbegin(), modifiers.cend()), buttonSet);
335 delete strokeShortcut;
342 if (keys.size() == 0)
return;
352 Qt::Key key = allKeys.takeLast();
353 QSet<Qt::Key> modifiers = QSet<Qt::Key>(allKeys.begin(), allKeys.end());
354 keyShortcut->
setKey(modifiers, key);
365 std::unique_ptr<KisSingleActionShortcut> keyShortcut(
367 keyShortcut->setWheel(QSet<Qt::Key>(modifiers.begin(), modifiers.end()), a);
371 switch(wheelAction) {
393 if (isTouchPainting) {
397 dbgKrita <<
"TouchAction:" << action->
name() << (isTouchPainting ?
"touch-painting" :
"");
485 event->type() == QEvent::KeyPress ||
486 event->type() == QEvent::KeyRelease) {
508 event->setAccepted(
true);
520 QKeyEvent kevent(QEvent::ShortcutOverride, key, modifiers);
533 for (
auto it = danglingKeys.begin(); it != danglingKeys.end();) {
534 if (newKeys.contains(*it)) {
535 newKeys.removeOne(*it);
536 it = danglingKeys.erase(it);
550 Q_FOREACH (Qt::Key key, danglingKeys) {
551 QKeyEvent kevent(QEvent::KeyRelease, key, modifiers);
555 Q_FOREACH (Qt::Key key, newKeys) {
558 QKeyEvent kevent(QEvent::ShortcutOverride, key, modifiers);
562 QKeyEvent kevent(QEvent::KeyPress, key, modifiers);
574 QElapsedTimer elapsed;
576 return elapsed.msecsSinceReference();
float value(const T *src, size_t ch)
bool testingAcceptCompressedTabletEvents(bool defaultValue=false) const
int tabletEventsDelay(bool defaultValue=false) const
bool trackTabletEventLatency(bool defaultValue=false) const
bool testingCompressBrushEvents(bool defaultValue=false) const
static Qt::Key workaroundShiftAltMetaHell(const QKeyEvent *keyEvent)
Qt::KeyboardModifiers queryStandardModifiers()
ExtendedModifiers queryExtendedModifiers()
@ TouchpadScroll
Two-dimensional pixel scrolling on a touchpad, supported on MacOS and Wayland only.
@ SmartZoomGesture
Smart zoom gesture, typically a double tap that is a boolean zoom/unzoom.
@ PinchGesture
Pinch gesture, a two finger gesture used for navigating the canvas.
@ WheelDown
Downwards movement, toward the user.
@ WheelUp
Upwards movement, away from the user.
@ WheelLeft
Left movement.
@ WheelRight
Right movement.
@ WheelReserved_0
Do not use! Previously was used for TouchpadScroll shortcut.
void addShortcut(KisSingleActionShortcut *shortcut)
void setInputActionGroupsMaskCallback(std::function< KisInputActionGroupsMask()> func)
void setIgnoreMultiFingerCancelWorkaroundEnalbed(bool value)
QVector< Qt::Key > debugPressedKeys() const
void handlePolledKeys(const QVector< Qt::Key > &keys)
bool pointerMoved(QEvent *event)
void setDelay(std::function< bool()> idleCallback, int idleDelay, int timeout)
@ WheelDown
Mouse wheel moves down.
@ WheelUp
Mouse wheel moves up.
@ WheelRight
Mouse wheel moves right.
@ WheelLeft
Mouse wheel moves left.
void setKey(const QSet< Qt::Key > &modifiers, Qt::Key key)
void setButtons(const QSet< Qt::Key > &modifiers, const QSet< Qt::MouseButton > &buttons)
QString eventToString(const QMouseEvent &ev, const QString &prefix)
static KisTabletDebugger * instance()
bool debugEnabled() const
The KisTouchShortcut class only handles touch gestures it does not handle tool invocation i....
void setIsTouchPainting(bool value)
void setMinDragThreshold(qreal value)
void setMaximumTouchPoints(int max)
void setMinimumTouchPoints(int min)
#define KIS_SAFE_ASSERT_RECOVER_BREAK(cond)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
QString buttons(const T &ev)