10#include <QApplication>
11#include <QScopedPointer>
15#include <boost/preprocessor/repeat_from_to.hpp>
29#include "config-qt-patches-present.h"
65 return (t == QEvent::MouseMove ||
66 t == QEvent::MouseButtonPress ||
67 t == QEvent::MouseButtonRelease ||
68 t == QEvent::MouseButtonDblClick);
83 QString pre = QString(
"[BLOCKED %1:]").arg(i);
84 QMouseEvent *ev =
static_cast<QMouseEvent*
>(event);
89 auto debugTabletEvent = [&](
int i) {
91 QString pre = QString(
"[BLOCKED %1:]").arg(i);
92 QTabletEvent *ev =
static_cast<QTabletEvent*
>(event);
97 auto debugTouchEvent = [&](
int i) {
99 QString pre = QString(
"[BLOCKED %1:]").arg(i);
100 QTouchEvent *ev =
static_cast<QTouchEvent*
>(event);
105 if (peckish && event->type() == QEvent::MouseButtonPress
107 && (
static_cast<QMouseEvent*
>(event)->button() == Qt::LeftButton)) {
113 if (activateSecondaryButtonsWorkaround) {
114 if (event->type() == QEvent::TabletPress ||
115 event->type() == QEvent::TabletRelease) {
117 QTabletEvent *te =
static_cast<QTabletEvent*
>(event);
118 if (te->button() != Qt::LeftButton) {
122 }
else if (event->type() == QEvent::MouseButtonPress ||
123 event->type() == QEvent::MouseButtonRelease ||
124 event->type() == QEvent::MouseButtonDblClick) {
126 QMouseEvent *me =
static_cast<QMouseEvent*
>(event);
127 if (me->button() != Qt::LeftButton) {
138 || (eatSyntheticEvents &&
static_cast<QMouseEvent*
>(event)->
source() != Qt::MouseEventNotSynthesized)
146 if (eatTouchEvents && event->type() == QEvent::TouchBegin) {
161 dbgTablet <<
"Start blocking mouse events";
169 dbgTablet <<
"Stop blocking mouse events";
182 eatTouchEvents =
true;
187 eatTouchEvents =
false;
238#if defined Q_OS_LINUX && !KRITA_QT_HAS_UNBALANCED_KEY_PRESS_RELEASE_PATCH
242 if (qEnvironmentVariableIsSet(
"KRITA_FIX_UNBALANCED_KEY_EVENTS")) {
258 eatOneMouseStroke(false),
265 QWidget *widget = qobject_cast<QWidget*>(
object);
268 thresholdConnections.clear();
269 thresholdConnections.addConnection(&focusSwitchThreshold, SIGNAL(timeout()), widget, SLOT(setFocus()));
276 QObject *canvasWidget =
canvas->canvasWidget();
278 if (!canvasResolver.contains(canvasWidget)) {
279 canvasResolver.insert(canvasWidget,
canvas);
288 canvasWidget->installEventFilter(
this);
290 setupFocusThreshold(canvasWidget);
291 focusSwitchThreshold.setEnabled(
false);
300 QObject *widget =
canvas->canvasWidget();
302 canvasResolver.remove(widget);
308 widget->removeEventFilter(
this);
318 if (!w)
return false;
322 types << QLatin1String(
"QAbstractSlider");
323 types << QLatin1String(
"QAbstractSpinBox");
324 types << QLatin1String(
"QLineEdit");
325 types << QLatin1String(
"QTextEdit");
326 types << QLatin1String(
"QPlainTextEdit");
327 types << QLatin1String(
"QComboBox");
328 types << QLatin1String(
"QKeySequenceEdit");
330 Q_FOREACH (
const QLatin1String &type, types) {
331 if (w->inherits(type.data())) {
341 if (canvasResolver.contains(
object)) {
342 switch (event->type()) {
343 case QEvent::FocusIn: {
344 QFocusEvent *fevent =
static_cast<QFocusEvent*
>(event);
352 eatOneMouseStroke = 2 * (fevent->reason() == Qt::MouseFocusReason);
360 object->removeEventFilter(
this);
361 object->installEventFilter(
this);
363 setupFocusThreshold(
object);
364 focusSwitchThreshold.setEnabled(
false);
366 const QPoint globalPos = QCursor::pos();
367 const QPoint localPos =
d->
canvas->canvasWidget()->mapFromGlobal(globalPos);
368 QWidget *canvasWindow =
d->
canvas->canvasWidget()->window();
369 const QPoint windowsPos = canvasWindow ? canvasWindow->mapFromGlobal(globalPos) : localPos;
371 QEnterEvent event(localPos, windowsPos, globalPos);
375 case QEvent::FocusOut: {
376 focusSwitchThreshold.setEnabled(
true);
379 case QEvent::Enter: {
382 case QEvent::Leave: {
383 focusSwitchThreshold.stop();
386 case QEvent::Wheel: {
387 QWidget *widget =
static_cast<QWidget*
>(object);
391 case QEvent::MouseButtonPress:
392 case QEvent::MouseButtonRelease:
393 case QEvent::TabletPress:
394 case QEvent::TabletRelease:
395 focusSwitchThreshold.forceDone();
397 if (eatOneMouseStroke) {
402 case QEvent::MouseButtonDblClick:
403 focusSwitchThreshold.forceDone();
404 if (eatOneMouseStroke) {
408 case QEvent::MouseMove:
409 case QEvent::TabletMove: {
410 QWidget *widget =
static_cast<QWidget*
>(object);
412 if (!widget->hasFocus()) {
417 focusSwitchThreshold.setDelayThreshold(delay);
418 focusSwitchThreshold.start();
426 return QObject::eventFilter(
object, event);
435 switch (event->type()) {
436 case QEvent::TabletEnterProximity:
449 case QEvent::TabletLeaveProximity:
454 case QEvent::KeyPress:
455 case QEvent::KeyRelease:
456 case QEvent::ShortcutOverride:
457 if (
d->ignoreHighFunctionKeys) {
458 QKeyEvent *keyEvent =
static_cast<QKeyEvent *
>(event);
459 int key = keyEvent->key();
461 if (key >= Qt::Key_F13 && key <= Qt::Key_F35) {
463 const QString pre =
"[BLOCKED HIGH F-KEY]";
474 return QObject::eventFilter(
object, event);
477#define EXTRA_BUTTON(z, n, _) \
478 if(buttons & Qt::ExtraButton##n) { \
479 buttonSet << Qt::ExtraButton##n; \
489 QSet<Qt::MouseButton> buttonSet;
491 buttonSet << Qt::LeftButton;
493 if(
buttons & Qt::RightButton) {
494 buttonSet << Qt::RightButton;
496 if(
buttons & Qt::MiddleButton) {
497 buttonSet << Qt::MiddleButton;
502 if (!buttonSet.empty()) {
503 strokeShortcut->
setButtons(QSet<Qt::Key>(modifiers.cbegin(), modifiers.cend()), buttonSet);
507 delete strokeShortcut;
514 if (keys.size() == 0)
return;
524 Qt::Key key = allKeys.takeLast();
525 QSet<Qt::Key> modifiers = QSet<Qt::Key>(allKeys.begin(), allKeys.end());
526 keyShortcut->
setKey(modifiers, key);
534 std::unique_ptr<KisSingleActionShortcut> keyShortcut(
538 switch(wheelAction) {
557 keyShortcut->setWheel(QSet<Qt::Key>(modifiers.begin(), modifiers.end()), a);
608 Qt::NativeGestureType type;
611 case KisShortcutConfiguration::PinchGesture:
612 type = Qt::ZoomNativeGesture;
614 case KisShortcutConfiguration::PanGesture:
615 type = Qt::PanNativeGesture;
617 case KisShortcutConfiguration::RotateGesture:
618 type = Qt::RotateNativeGesture;
620 case KisShortcutConfiguration::SmartZoomGesture:
621 type = Qt::SmartZoomNativeGesture;
656 event->type() == QEvent::KeyPress ||
657 event->type() == QEvent::KeyRelease) {
667inline QPointF dividePoints(
const QPointF &pt1,
const QPointF &pt2) {
668 return QPointF(pt1.x() / pt2.x(), pt1.y() / pt2.y());
671inline QPointF multiplyPoints(
const QPointF &pt1,
const QPointF &pt2) {
672 return QPointF(pt1.x() * pt2.x(), pt1.y() * pt2.y());
745 qreal distanceSquared = (
d.x() *
d.x()) + (
d.y() *
d.y());
751#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
752 QScopedPointer<QEvent> dst;
753 KoPointerEvent::copyQtPointerEvent(touchEvent, dst);
763 switch (touchEvent->type()) {
764 case QEvent::TouchBegin:
767 case QEvent::TouchUpdate:
771 qWarning(
"Unhandled buffered touch event type %d",
int(touchEvent->type()));
797 event->setAccepted(
true);
809 QKeyEvent kevent(QEvent::ShortcutOverride, key, modifiers);
822 for (
auto it = danglingKeys.begin(); it != danglingKeys.end();) {
823 if (newKeys.contains(*it)) {
824 newKeys.removeOne(*it);
825 it = danglingKeys.erase(it);
831 Q_FOREACH (Qt::Key key, danglingKeys) {
832 QKeyEvent kevent(QEvent::KeyRelease, key, modifiers);
836 Q_FOREACH (Qt::Key key, newKeys) {
839 QKeyEvent kevent(QEvent::ShortcutOverride, key, modifiers);
843 QKeyEvent kevent(QEvent::KeyPress, key, modifiers);
855 QElapsedTimer elapsed;
857 return elapsed.msecsSinceReference();
float value(const T *src, size_t ch)
KisMagneticGraph::vertex_descriptor target(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
static bool debugEnabled()
Linethickness.
bool testingAcceptCompressedTabletEvents(bool defaultValue=false) const
int tabletEventsDelay(bool defaultValue=false) const
bool trackTabletEventLatency(bool defaultValue=false) const
bool useRightMiddleTabletButtonWorkaround(bool defaultValue=false) const
bool testingCompressBrushEvents(bool defaultValue=false) const
static Qt::Key workaroundShiftAltMetaHell(const QKeyEvent *keyEvent)
Qt::KeyboardModifiers queryStandardModifiers()
ExtendedModifiers queryExtendedModifiers()
@ WheelTrackpad
A pan movement on a trackpad.
@ WheelDown
Downwards movement, toward the user.
@ WheelUp
Upwards movement, away from the user.
@ WheelLeft
Left movement.
@ WheelRight
Right movement.
bool hasRunningShortcut() const
void addShortcut(KisSingleActionShortcut *shortcut)
void setInputActionGroupsMaskCallback(std::function< KisInputActionGroupsMask()> func)
QVector< Qt::Key > debugPressedKeys() const
bool touchUpdateEvent(QTouchEvent *event)
static constexpr int TOUCH_SLOP_SQUARED
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.
@ WheelTrackpad
A pan movement on a trackpad.
@ 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 setMaximumTouchPoints(int max)
void setDisableOnTouchPainting(bool disableOnTouchPainting)
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)