10#include <QApplication>
11#include <QScopedPointer>
15#include <boost/preprocessor/repeat_from_to.hpp>
29#include "config-qt-patches-present.h"
63 return (t == QEvent::MouseMove ||
64 t == QEvent::MouseButtonPress ||
65 t == QEvent::MouseButtonRelease ||
66 t == QEvent::MouseButtonDblClick);
81 QString pre = QString(
"[BLOCKED %1:]").arg(i);
82 QMouseEvent *ev =
static_cast<QMouseEvent*
>(event);
87 auto debugTabletEvent = [&](
int i) {
89 QString pre = QString(
"[BLOCKED %1:]").arg(i);
90 QTabletEvent *ev =
static_cast<QTabletEvent*
>(event);
95 auto debugTouchEvent = [&](
int i) {
97 QString pre = QString(
"[BLOCKED %1:]").arg(i);
98 QTouchEvent *ev =
static_cast<QTouchEvent*
>(event);
103 if (peckish && event->type() == QEvent::MouseButtonPress
105 && (
static_cast<QMouseEvent*
>(event)->button() == Qt::LeftButton)) {
111 if (activateSecondaryButtonsWorkaround) {
112 if (event->type() == QEvent::TabletPress ||
113 event->type() == QEvent::TabletRelease) {
115 QTabletEvent *te =
static_cast<QTabletEvent*
>(event);
116 if (te->button() != Qt::LeftButton) {
120 }
else if (event->type() == QEvent::MouseButtonPress ||
121 event->type() == QEvent::MouseButtonRelease ||
122 event->type() == QEvent::MouseButtonDblClick) {
124 QMouseEvent *me =
static_cast<QMouseEvent*
>(event);
125 if (me->button() != Qt::LeftButton) {
136 || (eatSyntheticEvents &&
static_cast<QMouseEvent*
>(event)->
source() != Qt::MouseEventNotSynthesized)
144 if (eatTouchEvents && event->type() == QEvent::TouchBegin) {
159 dbgTablet <<
"Start blocking mouse events";
167 dbgTablet <<
"Stop blocking mouse events";
180 eatTouchEvents =
true;
185 eatTouchEvents =
false;
236#if defined Q_OS_LINUX && !KRITA_QT_HAS_UNBALANCED_KEY_PRESS_RELEASE_PATCH
240 if (qEnvironmentVariableIsSet(
"KRITA_FIX_UNBALANCED_KEY_EVENTS")) {
256 eatOneMouseStroke(false),
263 QWidget *widget = qobject_cast<QWidget*>(
object);
266 thresholdConnections.clear();
267 thresholdConnections.addConnection(&focusSwitchThreshold, SIGNAL(timeout()), widget, SLOT(setFocus()));
274 QObject *canvasWidget =
canvas->canvasWidget();
276 if (!canvasResolver.contains(canvasWidget)) {
277 canvasResolver.insert(canvasWidget,
canvas);
286 canvasWidget->installEventFilter(
this);
288 setupFocusThreshold(canvasWidget);
289 focusSwitchThreshold.setEnabled(
false);
298 QObject *widget =
canvas->canvasWidget();
300 canvasResolver.remove(widget);
306 widget->removeEventFilter(
this);
316 if (!w)
return false;
320 types << QLatin1String(
"QAbstractSlider");
321 types << QLatin1String(
"QAbstractSpinBox");
322 types << QLatin1String(
"QLineEdit");
323 types << QLatin1String(
"QTextEdit");
324 types << QLatin1String(
"QPlainTextEdit");
325 types << QLatin1String(
"QComboBox");
326 types << QLatin1String(
"QKeySequenceEdit");
328 Q_FOREACH (
const QLatin1String &type, types) {
329 if (w->inherits(type.data())) {
339 if (canvasResolver.contains(
object)) {
340 switch (event->type()) {
341 case QEvent::FocusIn: {
342 QFocusEvent *fevent =
static_cast<QFocusEvent*
>(event);
350 eatOneMouseStroke = 2 * (fevent->reason() == Qt::MouseFocusReason);
358 object->removeEventFilter(
this);
359 object->installEventFilter(
this);
361 setupFocusThreshold(
object);
362 focusSwitchThreshold.setEnabled(
false);
364 const QPoint globalPos = QCursor::pos();
365 const QPoint localPos =
d->
canvas->canvasWidget()->mapFromGlobal(globalPos);
366 QWidget *canvasWindow =
d->
canvas->canvasWidget()->window();
367 const QPoint windowsPos = canvasWindow ? canvasWindow->mapFromGlobal(globalPos) : localPos;
369 QEnterEvent event(localPos, windowsPos, globalPos);
373 case QEvent::FocusOut: {
374 focusSwitchThreshold.setEnabled(
true);
377 case QEvent::Enter: {
380 case QEvent::Leave: {
381 focusSwitchThreshold.stop();
384 case QEvent::Wheel: {
385 QWidget *widget =
static_cast<QWidget*
>(object);
389 case QEvent::MouseButtonPress:
390 case QEvent::MouseButtonRelease:
391 case QEvent::TabletPress:
392 case QEvent::TabletRelease:
393 focusSwitchThreshold.forceDone();
395 if (eatOneMouseStroke) {
400 case QEvent::MouseButtonDblClick:
401 focusSwitchThreshold.forceDone();
402 if (eatOneMouseStroke) {
406 case QEvent::MouseMove:
407 case QEvent::TabletMove: {
408 QWidget *widget =
static_cast<QWidget*
>(object);
410 if (!widget->hasFocus()) {
415 focusSwitchThreshold.setDelayThreshold(delay);
416 focusSwitchThreshold.start();
424 return QObject::eventFilter(
object, event);
433 switch (event->type()) {
434 case QEvent::TabletEnterProximity:
447 case QEvent::TabletLeaveProximity:
452 case QEvent::KeyPress:
453 case QEvent::KeyRelease:
454 case QEvent::ShortcutOverride:
455 if (
d->ignoreHighFunctionKeys) {
456 QKeyEvent *keyEvent =
static_cast<QKeyEvent *
>(event);
457 int key = keyEvent->key();
459 if (key >= Qt::Key_F13 && key <= Qt::Key_F35) {
461 const QString pre =
"[BLOCKED HIGH F-KEY]";
472 return QObject::eventFilter(
object, event);
475#define EXTRA_BUTTON(z, n, _) \
476 if(buttons & Qt::ExtraButton##n) { \
477 buttonSet << Qt::ExtraButton##n; \
487 QSet<Qt::MouseButton> buttonSet;
489 buttonSet << Qt::LeftButton;
491 if(
buttons & Qt::RightButton) {
492 buttonSet << Qt::RightButton;
494 if(
buttons & Qt::MiddleButton) {
495 buttonSet << Qt::MiddleButton;
500 if (!buttonSet.empty()) {
501 strokeShortcut->
setButtons(QSet<Qt::Key>(modifiers.cbegin(), modifiers.cend()), buttonSet);
505 delete strokeShortcut;
512 if (keys.size() == 0)
return;
522 Qt::Key key = allKeys.takeLast();
523 QSet<Qt::Key> modifiers = QSet<Qt::Key>(allKeys.begin(), allKeys.end());
524 keyShortcut->
setKey(modifiers, key);
532 QScopedPointer<KisSingleActionShortcut> keyShortcut(
536 switch(wheelAction) {
555 keyShortcut->setWheel(QSet<Qt::Key>(modifiers.begin(), modifiers.end()), a);
606 Qt::NativeGestureType type;
609 case KisShortcutConfiguration::PinchGesture:
610 type = Qt::ZoomNativeGesture;
612 case KisShortcutConfiguration::PanGesture:
613 type = Qt::PanNativeGesture;
615 case KisShortcutConfiguration::RotateGesture:
616 type = Qt::RotateNativeGesture;
618 case KisShortcutConfiguration::SmartZoomGesture:
619 type = Qt::SmartZoomNativeGesture;
654 event->type() == QEvent::KeyPress ||
655 event->type() == QEvent::KeyRelease) {
665inline QPointF dividePoints(
const QPointF &pt1,
const QPointF &pt2) {
666 return QPointF(pt1.x() / pt2.x(), pt1.y() / pt2.y());
669inline QPointF multiplyPoints(
const QPointF &pt1,
const QPointF &pt2) {
670 return QPointF(pt1.x() * pt2.x(), pt1.y() * pt2.y());
743 qreal distanceSquared = (
d.x() *
d.x()) + (
d.y() *
d.y());
749#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
750 QScopedPointer<QEvent> dst;
751 KoPointerEvent::copyQtPointerEvent(touchEvent, dst);
761 switch (touchEvent->type()) {
762 case QEvent::TouchBegin:
765 case QEvent::TouchUpdate:
769 qWarning(
"Unhandled buffered touch event type %d",
int(touchEvent->type()));
795 event->setAccepted(
true);
807 QKeyEvent kevent(QEvent::ShortcutOverride, key, modifiers);
820 for (
auto it = danglingKeys.begin(); it != danglingKeys.end();) {
821 if (newKeys.contains(*it)) {
822 newKeys.removeOne(*it);
823 it = danglingKeys.erase(it);
829 Q_FOREACH (Qt::Key key, danglingKeys) {
830 QKeyEvent kevent(QEvent::KeyRelease, key, modifiers);
834 Q_FOREACH (Qt::Key key, newKeys) {
837 QKeyEvent kevent(QEvent::ShortcutOverride, key, modifiers);
841 QKeyEvent kevent(QEvent::KeyPress, key, modifiers);
853 QElapsedTimer elapsed;
855 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)