Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_input_manager.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 *
3 * SPDX-FileCopyrightText: 2012 Arjen Hiemstra <ahiemstra@heimr.nl>
4 * SPDX-FileCopyrightText: 2015 Michael Abrahams <miabraha@gmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "kis_input_manager.h"
10
11#include <kis_debug.h>
12#include <QQueue>
13#include <klocalizedstring.h>
14#include <QApplication>
15#include <QTouchEvent>
16#include <QWidget>
17
18#include <KoToolManager.h>
19#include <KoPointerEvent.h>
20
21#include "kis_tool_proxy.h"
22
23#include <kis_config.h>
24#include <kis_config_notifier.h>
25#include <kis_canvas2.h>
26#include <KisViewManager.h>
27#include <kis_image.h>
30
34
36#include "kis_stroke_shortcut.h"
38#include "kis_touch_shortcut.h"
39
40#include "kis_input_profile.h"
43
46
48#include "kis_input_manager_p.h"
49#include "kis_algebra_2d.h"
50#include "config-qt-patches-present.h"
51
52
53template <typename T>
55 return reinterpret_cast<quintptr>(value.data());
56}
57
59 : QObject(parent), d(new Private(this))
60{
61 d->setupActions();
62
63 connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
65
66 connect(KoToolManager::instance(), SIGNAL(aboutToChangeTool(KoCanvasController*)), SLOT(slotAboutToChangeTool()));
67 connect(KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*)), SLOT(slotToolChanged()));
68 connect(KoToolManager::instance(), SIGNAL(textModeChanged(bool)), SLOT(slotTextModeChanged()));
69 connect(&d->moveEventCompressor, SIGNAL(timeout()), SLOT(slotCompressedMoveEvent()));
70
71
72 QApplication::instance()->
73 installEventFilter(new Private::ProximityNotifier(d, this));
74
75 // on macos global Monitor listen to keypresses when krita is not in focus
76 // and local monitor listen presses when krita is in focus.
77#ifdef Q_OS_MACOS
78 KisExtendedModifiersMapper::setLocalMonitor(true, &d->matcher);
79#endif
80}
81
83{
84#ifdef Q_OS_MACOS
85 KisExtendedModifiersMapper::setLocalMonitor(false);
86#endif
87 delete d;
88}
89
94
99
101{
102 d->popupWidget = popupWidget;
103
104 // FUNKY!
105 auto popupObject = dynamic_cast<QObject*>(d->popupWidget);
106 KIS_ASSERT(popupObject);
107 connect(popupObject, SIGNAL(finished()), this, SLOT(deregisterPopupWidget()));
108}
109
111{
112 if (d->popupWidget->onScreen()) {
114 }
115
116 // FUNKY!
117 auto popupObject = dynamic_cast<QObject*>(d->popupWidget);
118 KIS_ASSERT(popupObject);
119 disconnect(popupObject, nullptr, this, nullptr); // Disconnect all.
120
121 d->popupWidget = nullptr;
122}
123
125{
126#ifdef Q_OS_WIN
127 d->ignoreHighFunctionKeys = KisConfig(true).ignoreHighFunctionKeys();
129#endif
130}
131
136
137void KisInputManager::attachPriorityEventFilter(QObject *filter, int priority)
138{
139 Private::PriorityList::iterator begin = d->priorityEventFilter.begin();
140 Private::PriorityList::iterator it = begin;
141 Private::PriorityList::iterator end = d->priorityEventFilter.end();
142
143 it = std::find_if(begin, end,
144 kismpl::mem_equal_to(&Private::PriorityPair::second, filter));
145
146 if (it != end) return;
147
148 it = std::find_if(begin, end,
149 kismpl::mem_greater(&Private::PriorityPair::first, priority));
150
151 d->priorityEventFilter.insert(it, qMakePair(priority, filter));
153}
154
156{
157 Private::PriorityList::iterator it = d->priorityEventFilter.begin();
158 Private::PriorityList::iterator end = d->priorityEventFilter.end();
159
160 it = std::find_if(it, end,
161 kismpl::mem_equal_to(&Private::PriorityPair::second, filter));
162
163 if (it != end) {
164 d->priorityEventFilter.erase(it);
165 }
166}
167
169{
170 if (d->eventsReceiver) {
171 d->eventsReceiver->removeEventFilter(this);
172 }
173
174 d->eventsReceiver = receiver;
175
176 if (d->eventsReceiver) {
177 d->eventsReceiver->installEventFilter(this);
178 }
179}
180
181#if defined (__clang__)
182#pragma GCC diagnostic ignored "-Wswitch"
183#endif
184
185bool KisInputManager::eventFilter(QObject* object, QEvent* event)
186{
187 if (object != d->eventsReceiver) return false;
188
189 if (d->eventEater.eventFilter(object, event)) return false;
190
191 if (!d->matcher.hasRunningShortcut()) {
192
193 int savedPriorityEventFilterSeqNo = d->priorityEventFilterSeqNo;
194
195 for (auto it = d->priorityEventFilter.begin(); it != d->priorityEventFilter.end(); /*noop*/) {
196 const QPointer<QObject> &filter = it->second;
197
198 if (filter.isNull()) {
199 it = d->priorityEventFilter.erase(it);
200
202 savedPriorityEventFilterSeqNo++;
203 continue;
204 }
205
206 if (filter->eventFilter(object, event)) return true;
207
212 if (d->priorityEventFilterSeqNo != savedPriorityEventFilterSeqNo) {
213 return true;
214 }
215
216 ++it;
217 }
218
219 // KoToolProxy needs to pre-process some events to ensure the
220 // global shortcuts (not the input manager's ones) are not
221 // executed, in particular, this line will accept events when the
222 // tool is in text editing, preventing shortcut triggering
223 if (d->toolProxy) {
224 d->toolProxy->processEvent(event);
225 }
226 }
227
228 // Continue with the actual switch statement...
229 return eventFilterImpl(event);
230}
231
232template <class Event>
234{
239 static_assert(std::is_same<Event, QMouseEvent>::value ||
240 std::is_same<Event, QTabletEvent>::value,
241 "event should be a mouse or a tablet event");
242
243
244 bool retval = false;
245
249 if ((event->type() == QEvent::MouseMove ||
250 event->type() == QEvent::TabletMove) &&
253#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
254 KoPointerEvent::copyQtPointerEvent(event, d->compressedMoveEvent);
255#else
256 d->compressedMoveEvent.reset(event->clone());
257#endif
259
267 event->setAccepted(true);
268 }
269
270 retval = true;
271 } else {
273 retval = d->handleCompressedTabletEvent(event);
274 }
275
276 return retval;
277}
278
279bool shouldResetWheelDelta(QEvent * event)
280{
281 return
282 event->type() == QEvent::FocusIn ||
283 event->type() == QEvent::FocusOut ||
284 event->type() == QEvent::MouseButtonPress ||
285 event->type() == QEvent::MouseButtonRelease ||
286 event->type() == QEvent::MouseButtonDblClick ||
287 event->type() == QEvent::TabletPress ||
288 event->type() == QEvent::TabletRelease ||
289 event->type() == QEvent::Enter ||
290 event->type() == QEvent::Leave ||
291 event->type() == QEvent::TouchBegin ||
292 event->type() == QEvent::TouchEnd ||
293 event->type() == QEvent::TouchCancel ||
294 event->type() == QEvent::NativeGesture;
295
296}
297
299{
300 bool retval = false;
301
302 // Try closing any open popup widget and
303 // consume input if possible.
304 if (d->popupWidget) {
305 QEvent::Type type = event->type();
306
307 if (type == QEvent::MouseButtonPress
308 || type == QEvent::MouseButtonDblClick
309 || type == QEvent::TabletPress
310 || type == QEvent::TouchBegin
311 || type == QEvent::NativeGesture) {
312 bool wasVisible = d->popupWidget->onScreen();
314
315 if (wasVisible) {
316 d->popupWasActive = true;
317 event->setAccepted(true);
318 return true; // Event consumed.
319 }
320 }
321 }
322
323 if (shouldResetWheelDelta(event)) {
325 }
326
327 if (event->type() == QEvent::MouseMove ||
328 event->type() == QEvent::MouseButtonPress ||
329 event->type() == QEvent::MouseButtonRelease ||
330 event->type() == QEvent::TabletMove ||
331 event->type() == QEvent::TabletPress ||
332 event->type() == QEvent::TabletRelease ||
333 event->type() == QEvent::Wheel) {
334
344 QWidget *receivingWidget = dynamic_cast<QWidget*>(d->eventsReceiver);
345 if (receivingWidget && !receivingWidget->hasFocus()) {
347 } else {
355 QInputEvent *inputEvent = static_cast<QInputEvent*>(event);
356 if (event->type() != QEvent::ShortcutOverride &&
357 !d->matcher.sanityCheckModifiersCorrectness(inputEvent->modifiers())) {
358
360 } else if (d->matcher.hasPolledKeys()) {
369 }
370 }
371 }
372
373 switch (event->type()) {
374 case QEvent::MouseButtonPress:
375 case QEvent::MouseButtonDblClick: {
376 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
377
378 if (d->popupWidget) {
379 retval = true;
380 } else {
381 //Make sure the input actions know we are active.
383 retval = d->matcher.buttonPressed(mouseEvent->button(), mouseEvent);
384 }
385 //Reset signal compressor to prevent processing events before press late
387 event->setAccepted(retval);
388 break;
389 }
390 case QEvent::MouseButtonRelease: {
391 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
392 retval = d->matcher.buttonReleased(mouseEvent->button(), mouseEvent);
393 event->setAccepted(retval);
394 break;
395 }
396 case QEvent::ShortcutOverride: {
397 KisInputEventsEater::debugEvent<QKeyEvent>(event);
398 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
399
401
410 QVector<Qt::Key> guessedKeys;
412 Qt::KeyboardModifiers modifiers = mapper.queryStandardModifiers();
413 Q_FOREACH (Qt::Key key, mapper.queryExtendedModifiers()) {
414 QKeyEvent kevent(QEvent::ShortcutOverride, key, modifiers);
416 }
417
418 if (!d->matcher.debugPressedKeys().contains(key)) {
419 guessedKeys.removeOne(key);
420 }
421
422 d->fixShortcutMatcherModifiersState(guessedKeys, modifiers);
424 }
425
426 if (!keyEvent->isAutoRepeat()) {
427 retval = d->matcher.keyPressed(key);
428 } else {
429 retval = d->matcher.autoRepeatedKeyPressed(key);
430 }
431
432 // In case we matched a shortcut we should accept the event to
433 // notify Qt that it shouldn't try to trigger its partially matched
434 // shortcuts.
435 if (retval) {
436 keyEvent->setAccepted(true);
437 }
438
439 break;
440 }
441 case QEvent::KeyRelease: {
442 KisInputEventsEater::debugEvent<QKeyEvent>(event);
443 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
444
445 if (!keyEvent->isAutoRepeat()) {
447 retval = d->matcher.keyReleased(key);
448
476 !d->matcher.debugPressedKeys().isEmpty() &&
477 (key == Qt::Key_Shift || key == Qt::Key_Alt ||
478 key == Qt::Key_Control || key == Qt::Key_Meta)) {
479
481 }
482 }
483 break;
484 }
485 case QEvent::MouseMove: {
486 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
487 retval = compressMoveEventCommon(mouseEvent);
488
489 break;
490 }
491 case QEvent::Wheel: {
492 KisInputEventsEater::debugEvent<QWheelEvent>(event);
493 QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
494
495 if (wheelEvent->phase() != Qt::NoScrollPhase && d->matcher.hasTouchpadScrollShortcuts()) {
503 if (wheelEvent->phase() == Qt::ScrollBegin) {
505 } else if (wheelEvent->phase() == Qt::ScrollEnd) {
506 d->matcher.touchpadScrollEndEvent(wheelEvent);
507 } else {
508 d->matcher.touchpadScrollEvent(wheelEvent);
509 }
510
511 break;
512 }
513
514 d->accumulatedScrollDelta += wheelEvent->angleDelta();
515
520 if (wheelEvent->angleDelta().isNull()) {
521 retval = true;
522 break;
523 }
524
525 bool wasScrolled = false;
526
527 {
529
530 if (wheelEvent->angleDelta().y() < 0) {
532 } else if (wheelEvent->angleDelta().y() > 0) {
534 }
535
536 while (qAbs(d->accumulatedScrollDelta.y()) >= QWheelEvent::DefaultDeltasPerStep) {
537 // Make sure the input actions know we are active.
539 retval = d->matcher.wheelEvent(yAction, wheelEvent);
541 KisAlgebra2D::signPZ(d->accumulatedScrollDelta.y()) * QWheelEvent::DefaultDeltasPerStep;
542 wasScrolled = true;
543 }
544 }
545
546 {
548
549 if (wheelEvent->angleDelta().x() < 0) {
551 } else if (wheelEvent->angleDelta().x() > 0) {
553 }
554
555 while (qAbs(d->accumulatedScrollDelta.x()) >= QWheelEvent::DefaultDeltasPerStep) {
556 // Make sure the input actions know we are active.
558 retval = d->matcher.wheelEvent(xAction, wheelEvent);
560 KisAlgebra2D::signPZ(d->accumulatedScrollDelta.x()) * QWheelEvent::DefaultDeltasPerStep;
561 wasScrolled = true;
562 }
563 }
564
565 retval = !wasScrolled;
566 break;
567 }
568#ifndef Q_OS_ANDROID
569 case QEvent::Enter:
570 KisInputEventsEater::debugEvent<QEvent>(event);
571 //Make sure the input actions know we are active.
574 break;
575 case QEvent::Leave:
576 KisInputEventsEater::debugEvent<QEvent>(event);
578 break;
579#endif
580 case QEvent::FocusIn:
581 KisInputEventsEater::debugEvent<QEvent>(event);
583
586 break;
587
588 case QEvent::FocusOut: {
589 KisInputEventsEater::debugEvent<QEvent>(event);
591
592 QPointF currentLocalPos =
593 canvas()->canvasWidget()->mapFromGlobal(QCursor::pos());
594
595 d->matcher.lostFocusEvent(currentLocalPos);
596
597 break;
598 }
599 case QEvent::TabletPress: {
600 QTabletEvent *tabletEvent = static_cast<QTabletEvent*>(event);
601
602 {
603 //Make sure the input actions know we are active.
605 retval = d->matcher.buttonPressed(tabletEvent->button(), tabletEvent);
606 }
607
608 event->setAccepted(true);
609 retval = true;
610
611 //Reset signal compressor to prevent processing events before press late
613
614#if defined Q_OS_LINUX && !KRITA_QT_HAS_ENTER_LEAVE_PATCH
615 // remove this hack when this patch is integrated:
616 // https://codereview.qt-project.org/#/c/255384/
617 event->setAccepted(false);
619#elif defined Q_OS_WIN32
625#endif
626
627 break;
628 }
629 case QEvent::TabletMove: {
630 QTabletEvent *tabletEvent = static_cast<QTabletEvent*>(event);
631 retval = compressMoveEventCommon(tabletEvent);
632
633 if (d->tabletLatencyTracker) {
634 d->tabletLatencyTracker->push(tabletEvent->timestamp());
635 }
636
637#if defined Q_OS_LINUX && !KRITA_QT_HAS_ENTER_LEAVE_PATCH
638 // remove this hack when this patch is integrated:
639 // https://codereview.qt-project.org/#/c/255384/
640 event->setAccepted(false);
641#endif
642
643 break;
644 }
645 case QEvent::TabletRelease: {
646 QTabletEvent *tabletEvent = static_cast<QTabletEvent*>(event);
647 retval = d->matcher.buttonReleased(tabletEvent->button(), tabletEvent);
648 retval = true;
649 event->setAccepted(true);
650
651#if defined Q_OS_LINUX && !KRITA_QT_HAS_ENTER_LEAVE_PATCH
652 // remove this hack when this patch is integrated:
653 // https://codereview.qt-project.org/#/c/255384/
654 event->setAccepted(false);
655#endif
656
657 break;
658 }
659
660 case QEvent::TouchBegin:
661 {
662 // The popup was dismissed in previous TouchBegin->TouchEnd sequence. We now have a new TouchBegin.
663 d->popupWasActive = false;
664 QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
666
667 retval = d->matcher.touchBeginEvent(touchEvent);
668
670 // we accept touch events unconditionally to disable
671 // system-wide gesture on the canvas
672 event->accept();
673 break;
674 }
675
676 case QEvent::TouchUpdate:
677 {
678 if (d->popupWasActive) {
679 event->setAccepted(true);
680 return true;
681 }
682 QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
683
684#ifdef Q_OS_MAC
686 const int totalPointCount = KisTouchShortcut::countTouchPoints(touchEvent, KisTouchShortcut::allTouchStates());
687
688 if (pressedCount < 2 && totalPointCount > pressedCount) {
689 d->matcher.touchEndEvent(touchEvent);
690 retval = true;
691 } else {
692#endif
694 d->matcher.touchUpdateEvent(touchEvent);
716 retval = true;
717
718#ifdef Q_OS_MACOS
719 }
720#endif
721
722 // we accept touch events unconditionally to disable
723 // system-wide gesture on the canvas
724 event->accept();
725 break;
726 }
727
728 case QEvent::TouchEnd:
729 {
730 if (d->popupWasActive) {
731 event->setAccepted(true);
732 return true;
733 }
734 QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
735
736 retval = d->matcher.touchEndEvent(touchEvent);
737
738 // we accept touch events unconditionally to disable
739 // system-wide gesture on the canvas
740 event->accept();
741 break;
742 }
743 case QEvent::TouchCancel:
744 {
745 if (d->popupWasActive) {
746 event->setAccepted(true);
747 return true;
748 }
749 QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
750 d->matcher.touchCancelEvent(touchEvent);
751
752 retval = true;
753
754 // we accept tablet events unconditionally to disable
755 // system-wide gesture on the canvas
756 event->accept();
757 break;
758 }
759
760 case QEvent::NativeGesture:
761 {
762 QNativeGestureEvent *gevent = static_cast<QNativeGestureEvent*>(event);
763 switch (gevent->gestureType()) {
764 case Qt::BeginNativeGesture:
765 {
767 retval = d->matcher.nativeGestureBeginEvent(gevent);
768 event->accept();
769 break;
770 }
771 case Qt::EndNativeGesture:
772 {
773 retval = d->matcher.nativeGestureEndEvent(gevent);
774 event->accept();
775 break;
776 }
777 default:
778 {
780 retval = d->matcher.nativeGestureEvent(gevent);
781 event->accept();
782 break;
783 }
784 }
785 retval = true;
786 event->accept();
787 break;
788 }
789
790 default:
791 break;
792 }
793
794 return !retval ? d->processUnhandledEvent(event) : true;
795}
796
804
806{
807 return d->canvas;
808}
809
814
819
821{
822 QPointF currentLocalPos;
823 if (canvas() && canvas()->canvasWidget()) {
824 currentLocalPos = canvas()->canvasWidget()->mapFromGlobal(QCursor::pos());
825 }
826 // once more, don't forget the global state whenever matcher may trigger a KisAbstractInputAction
828
829 d->matcher.lostFocusEvent(currentLocalPos);
830}
831
833{
834 if (!d->canvas) return;
835 KoToolManager *toolManager = KoToolManager::instance();
836 KoToolBase *tool = toolManager->toolById(canvas(), toolManager->activeToolId());
837 if (tool) {
838 // once more, don't forget the global state whenever matcher may trigger a KisAbstractInputAction
840
842 if (tool->isInTextMode()) {
845 } else {
846 d->forwardAllEventsToTool = false;
848 }
849
850 d->matcher.suppressConflictingKeyActions(toolProxy()->toolPriorityShortcuts());
852 }
853}
854
856{
857 if (!d->canvas) return;
858 KoToolManager *toolManager = KoToolManager::instance();
859 KoToolBase *tool = toolManager->toolById(canvas(), toolManager->activeToolId());
860 if (tool) {
861 if (tool->isInTextMode()) {
864 } else {
865 d->forwardAllEventsToTool = false;
867 }
868 }
869}
870
872{
874
876 if (profile) {
877 const QList<KisShortcutConfiguration*> shortcuts = profile->allShortcuts();
878
879 for (KisShortcutConfiguration * const shortcut : shortcuts) {
880 dbgUI << "Adding shortcut" << shortcut->keys() << "for action" << shortcut->action()->name();
881 switch(shortcut->type()) {
883 d->addKeyShortcut(shortcut->action(), shortcut->mode(), shortcut->keys());
884 break;
886 d->addStrokeShortcut(shortcut->action(), shortcut->mode(), shortcut->keys(), shortcut->buttons());
887 break;
889 d->addWheelShortcut(shortcut->action(), shortcut->mode(), shortcut->keys(), shortcut->wheel());
890 break;
892 d->addTouchShortcut(shortcut->action(), shortcut->mode(), shortcut->touchGesture());
893 break;
895 d->addNativeGestureShortcut(shortcut->action(), shortcut->mode(), shortcut->nativeGesture());
896 break;
897 default:
898 break;
899 }
900 }
901
902 {
903 KisAbstractInputAction *action = profile->actionForId("Tool Invocation");
904 if (action) {
905 // Touch painting shortcuts
908 }
909 }
910 }
911 else {
912 warnUI << "No Input Profile Found: canvas interaction will be impossible";
913 }
914}
float value(const T *src, size_t ch)
unsigned int uint
Abstract base class for input actions.
static void setInputManager(KisInputManager *manager)
KisAbstractCanvasWidget * canvasWidget
static KisConfigNotifier * instance()
bool ignoreHighFunctionKeys(bool defaultValue=false) const
static Qt::Key workaroundShiftAltMetaHell(const QKeyEvent *keyEvent)
bool eventFilter(QObject *target, QEvent *event)
void addTouchShortcut(KisAbstractInputAction *action, int index, KisShortcutConfiguration::TouchGestureAction gesture, bool isTouchPainting=false)
void setMaskSyntheticEvents(bool value)
KisInputEventsEater eventEater
bool handleCompressedTabletEvent(QEvent *event)
bool addNativeGestureShortcut(KisAbstractInputAction *action, int index, KisShortcutConfiguration::NativeGestureAction gesture)
void addKeyShortcut(KisAbstractInputAction *action, int index, const QList< Qt::Key > &keys)
void addWheelShortcut(KisAbstractInputAction *action, int index, const QList< Qt::Key > &modifiers, KisShortcutConfiguration::MouseWheelMovement wheelAction)
KisToolInvocationAction * defaultInputAction
QPointer< KisToolProxy > toolProxy
KisSignalCompressor moveEventCompressor
void addStrokeShortcut(KisAbstractInputAction *action, int index, const QList< Qt::Key > &modifiers, Qt::MouseButtons buttons)
QScopedPointer< QEvent > compressedMoveEvent
QPointer< KisCanvas2 > canvas
bool processUnhandledEvent(QEvent *event)
KisSharedPtr< TabletLatencyTracker > tabletLatencyTracker
KisPopupWidgetInterface * popupWidget
KisCanvas2 * canvas() const
bool compressMoveEventCommon(Event *event)
~KisInputManager() override
void detachPriorityEventFilter(QObject *filter)
detachPriorityEventFilter
void setupAsEventFilter(QObject *receiver)
QPointer< KisToolProxy > toolProxy() const
void removeTrackedCanvas(KisCanvas2 *canvas)
void addTrackedCanvas(KisCanvas2 *canvas)
KisInputManager(QObject *parent)
void attachPriorityEventFilter(QObject *filter, int priority=0)
attachPriorityEventFilter
KisToolInvocationAction * defaultInputAction() const
bool eventFilter(QObject *object, QEvent *event) override
void registerPopupWidget(KisPopupWidgetInterface *popupWidget)
bool eventFilterImpl(QEvent *event)
static KisInputProfileManager * instance()
A container class for sets of shortcuts associated with an action.
QList< KisShortcutConfiguration * > allShortcuts() const
KisAbstractInputAction * actionForId(const QString &id) const
The PopupWidgetInterface abstract class defines the basic interface that will be used by all popup wi...
virtual void dismiss()=0
Called when you want to dismiss a popup widget.
virtual bool onScreen()=0
Returns whether the widget is active (on screen) or not.
A class encapsulating all settings for a single shortcut.
@ MouseButtonType
A mouse button, possibly with key modifiers.
@ MouseWheelType
Mouse wheel movement, possibly with key modifiers.
@ KeyCombinationType
A list of keys that should be pressed.
void lostFocusEvent(const QPointF &localPos)
bool autoRepeatedKeyPressed(Qt::Key key)
bool buttonReleased(Qt::MouseButton button, QEvent *event)
bool touchpadScrollEndEvent(QWheelEvent *event)
bool hasTouchpadScrollShortcuts() const
bool nativeGestureEndEvent(QNativeGestureEvent *event)
bool keyPressed(Qt::Key key)
bool touchBeginEvent(QTouchEvent *event)
bool touchpadScrollBeginEvent(QWheelEvent *event)
bool touchpadScrollEvent(QWheelEvent *event)
void touchCancelEvent(QTouchEvent *event)
QVector< Qt::Key > debugPressedKeys() const
bool touchEndEvent(QTouchEvent *event)
bool touchUpdateEvent(QTouchEvent *event)
bool nativeGestureEvent(QNativeGestureEvent *event)
bool buttonPressed(Qt::MouseButton button, QEvent *event)
bool sanityCheckModifiersCorrectness(Qt::KeyboardModifiers modifiers) const
bool nativeGestureBeginEvent(QNativeGestureEvent *event)
void suppressConflictingKeyActions(const QVector< QKeySequence > &shortcuts)
bool keyReleased(Qt::Key key)
bool wheelEvent(KisSingleActionShortcut::WheelAction wheelAction, QWheelEvent *event)
@ WheelDown
Mouse wheel moves down.
@ WheelRight
Mouse wheel moves right.
@ WheelLeft
Mouse wheel moves left.
static KisTabletDebugger * instance()
Tool Invocation action of KisAbstractInputAction.
static Qt::TouchPointStates pressedOnlyTouchStates()
static int countTouchPoints(const QTouchEvent *event, Qt::TouchPointStates allowedStates)
static Qt::TouchPointStates allTouchStates()
bool maskSyntheticEvents() const
bool isInTextMode() const
KoToolBase * toolById(KoCanvasBase *canvas, const QString &id) const
QString activeToolId() const
Returns the toolId of the currently active tool.
static KoToolManager * instance()
Return the toolmanager singleton.
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
#define dbgUI
Definition kis_debug.h:56
#define warnUI
Definition kis_debug.h:101
bool shouldResetWheelDelta(QEvent *event)
uint qHash(QPointer< T > value)
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
auto mem_equal_to(MemTypeNoRef Class::*ptr, MemType &&value)
mem_equal_to is an unary functor that compares a member of the object to a given value
Definition KisMpl.h:233
auto mem_greater(MemTypeNoRef Class::*ptr, MemType &&value)
mem_greater is an unary functor that compares a member of the object to a given value
Definition KisMpl.h:341