[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [calligra/krita-testing-kazakov] krita/ui: Added global Tablet Move Event throttling
From:       Dmitry Kazakov <dimula73 () gmail ! com>
Date:       2013-11-22 13:46:50
Message-ID: E1Vjr4M-0002n0-1L () scm ! kde ! org
[Download RAW message or body]

Git commit 6d9b809bf98502bae5ef003a2011342a52329fce by Dmitry Kazakov.
Committed on 22/11/2013 at 13:46.
Pushed by dkazakov into branch 'krita-testing-kazakov'.

Added global Tablet Move Event throttling

Now the tablet move events are compressed with the period of 10 ms
to avoid choking of receivers. Only KisToolFreehand is capable of handling
so many events simultaneously.

BUG:327581,327570,327383

M  +6    -0    krita/ui/canvas/kis_tool_proxy.cpp
M  +1    -0    krita/ui/canvas/kis_tool_proxy.h
M  +5    -5    krita/ui/input/kis_abstract_input_action.h
M  +43   -18   krita/ui/input/kis_input_manager.cpp
M  +1    -0    krita/ui/input/kis_input_manager.h
M  +8    -19   krita/ui/input/kis_shortcut_matcher.cpp
M  +9    -11   krita/ui/input/kis_shortcut_matcher.h
M  +1    -1    krita/ui/input/kis_tool_invocation_action.cpp
M  +0    -22   krita/ui/tests/kis_input_manager_test.cpp
M  +5    -0    krita/ui/tool/kis_tool.cc
M  +1    -0    krita/ui/tool/kis_tool.h
M  +5    -0    krita/ui/tool/kis_tool_freehand.cc
M  +2    -0    krita/ui/tool/kis_tool_freehand.h

http://commits.kde.org/calligra/6d9b809bf98502bae5ef003a2011342a52329fce

diff --git a/krita/ui/canvas/kis_tool_proxy.cpp b/krita/ui/canvas/kis_tool_proxy.cpp
index b64b300..f25dd72 100644
--- a/krita/ui/canvas/kis_tool_proxy.cpp
+++ b/krita/ui/canvas/kis_tool_proxy.cpp
@@ -160,3 +160,9 @@ void KisToolProxy::forwardToTool(ActionState state, \
KisTool::ToolAction action,  break;
     }
 }
+
+bool KisToolProxy::primaryActionSupportsHiResEvents() const
+{
+    KisTool *activeTool = \
dynamic_cast<KisTool*>(const_cast<KisToolProxy*>(this)->priv()->activeTool); +    \
return activeTool && activeTool->primaryActionSupportsHiResEvents(); +}
diff --git a/krita/ui/canvas/kis_tool_proxy.h b/krita/ui/canvas/kis_tool_proxy.h
index 5b92cb3..f49bcb8 100644
--- a/krita/ui/canvas/kis_tool_proxy.h
+++ b/krita/ui/canvas/kis_tool_proxy.h
@@ -36,6 +36,7 @@ public:
     KisToolProxy(KoCanvasBase *canvas, QObject *parent = 0);
 
     void forwardEvent(ActionState state, KisTool::ToolAction action, QEvent *event, \
QEvent *originalEvent, QTabletEvent *lastTabletEvent, const QPoint \
&canvasOriginWorkaround); +    bool primaryActionSupportsHiResEvents() const;
 
 private:
     KoPointerEvent convertEventToPointerEvent(QEvent *event, const QPointF \
                &docPoint, bool *result);
diff --git a/krita/ui/input/kis_abstract_input_action.h \
b/krita/ui/input/kis_abstract_input_action.h index b5e80de..bf42cba 100644
--- a/krita/ui/input/kis_abstract_input_action.h
+++ b/krita/ui/input/kis_abstract_input_action.h
@@ -108,11 +108,11 @@ public:
     virtual void inputEvent(QEvent* event);
 
     /**
-     * On some platforms (Windows in particular), tablet and mouse
-     * events generate different flows of messages. The amount of
-     * tablet events may be hard to process for some actions, so it is
-     * false by default. On Linux platform the flows are exactly the
-     * same so there is no difference between tablet and mouse events.
+     * Returns true if the action can handle HiRes flow of move events
+     * which is generated by the tablet. If the function returns
+     * false, some of the events will be dropped or postponed. For
+     * most of the actions in Krita (except of real painting) it is
+     * perfectly acceptable, so 'false' is the default value.
      */
     virtual bool supportsHiResInputEvents() const;
 
diff --git a/krita/ui/input/kis_input_manager.cpp \
b/krita/ui/input/kis_input_manager.cpp index 04e559d..55da31a 100644
--- a/krita/ui/input/kis_input_manager.cpp
+++ b/krita/ui/input/kis_input_manager.cpp
@@ -54,6 +54,7 @@
 #include "kis_shortcut_configuration.h"
 
 #include <input/kis_tablet_event.h>
+#include <kis_signal_compressor.h>
 
 
 class KisInputManager::Private
@@ -70,6 +71,7 @@ public:
     #endif
         , lastTabletEvent(0)
         , lastTouchEvent(0)
+        , moveEventCompressor(10 /* ms */, KisSignalCompressor::FIRST_ACTIVE)
         , logTabletEvents(false)
     {
     }
@@ -86,6 +88,7 @@ public:
     Qt::Key workaroundShiftAltMetaHell(const QKeyEvent *keyEvent);
     void setupActions();
     void saveTouchEvent( QTouchEvent* event );
+    bool handleKisTabletEvent(QObject *object, KisTabletEvent *tevent);
 
     KisInputManager *q;
 
@@ -105,6 +108,9 @@ public:
 
     KisAbstractInputAction *defaultInputAction;
 
+    KisSignalCompressor moveEventCompressor;
+    QScopedPointer<KisTabletEvent> compressedMoveEvent;
+
     bool logTabletEvents;
     void debugMouseEvent(QEvent *event);
     void debugTabletEvent(QEvent *event);
@@ -477,6 +483,8 @@ KisInputManager::KisInputManager(KisCanvas2 *canvas, KisToolProxy \
*proxy)  
     connect(KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*,int)),
             SLOT(slotToolChanged()));
+    connect(&d->moveEventCompressor, SIGNAL(timeout()), \
SLOT(slotCompressedMoveEvent())); +
 
     QApplication::instance()->
         installEventFilter(new Private::ProximityNotifier(d, this));
@@ -643,16 +651,7 @@ bool KisInputManager::eventFilter(QObject* object, QEvent* \
event)  //event.
         QTabletEvent* tabletEvent = static_cast<QTabletEvent*>(event);
         d->saveTabletEvent(tabletEvent);
-
-#ifdef Q_OS_WIN
-        if (event->type() == QEvent::TabletMove) {
-            retval = d->matcher.tabletMoved(static_cast<QTabletEvent*>(event));
-            event->setAccepted(retval);
-        }
-#else
         event->ignore();
-#endif
-
 
         break;
     }
@@ -664,16 +663,15 @@ bool KisInputManager::eventFilter(QObject* object, QEvent* \
event)  
         KisTabletEvent *tevent = static_cast<KisTabletEvent*>(event);
 
-        QTabletEvent qte = tevent->toQTabletEvent();
-        qte.ignore();
-        retval = eventFilter(object, &qte);
-        tevent->setAccepted(qte.isAccepted());
+        if (tevent->type() == KisTabletEvent::TabletMoveEx &&
+            !d->matcher.supportsHiResInputEvents()) {
 
-        if (!retval && !qte.isAccepted()) {
-            QMouseEvent qme = tevent->toQMouseEvent();
-            qme.ignore();
-            retval = eventFilter(object, &qme);
-            tevent->setAccepted(qme.isAccepted());
+            d->compressedMoveEvent.reset(new KisTabletEvent(*tevent));
+            d->moveEventCompressor.start();
+            retval = true;
+        } else {
+            slotCompressedMoveEvent();
+            retval = d->handleKisTabletEvent(object, tevent);
         }
 
         /**
@@ -717,6 +715,33 @@ bool KisInputManager::eventFilter(QObject* object, QEvent* \
event)  return !retval ? d->processUnhandledEvent(event) : true;
 }
 
+bool KisInputManager::Private::handleKisTabletEvent(QObject *object, KisTabletEvent \
*tevent) +{
+    bool retval = false;
+
+    QTabletEvent qte = tevent->toQTabletEvent();
+    qte.ignore();
+    retval = q->eventFilter(object, &qte);
+    tevent->setAccepted(qte.isAccepted());
+
+    if (!retval && !qte.isAccepted()) {
+        QMouseEvent qme = tevent->toQMouseEvent();
+        qme.ignore();
+        retval = q->eventFilter(object, &qme);
+        tevent->setAccepted(qme.isAccepted());
+    }
+
+    return retval;
+}
+
+void KisInputManager::slotCompressedMoveEvent()
+{
+    if (d->compressedMoveEvent) {
+        (void) d->handleKisTabletEvent(this, d->compressedMoveEvent.data());
+        d->compressedMoveEvent.reset();
+    }
+}
+
 KisCanvas2* KisInputManager::canvas() const
 {
     return d->canvas;
diff --git a/krita/ui/input/kis_input_manager.h b/krita/ui/input/kis_input_manager.h
index d9a793d..2a6d311 100644
--- a/krita/ui/input/kis_input_manager.h
+++ b/krita/ui/input/kis_input_manager.h
@@ -104,6 +104,7 @@ public Q_SLOTS:
 private Q_SLOTS:
     void slotToolChanged();
     void profileChanged();
+    void slotCompressedMoveEvent();
 
 private:
     class Private;
diff --git a/krita/ui/input/kis_shortcut_matcher.cpp \
b/krita/ui/input/kis_shortcut_matcher.cpp index a17d75d..881248d 100644
--- a/krita/ui/input/kis_shortcut_matcher.cpp
+++ b/krita/ui/input/kis_shortcut_matcher.cpp
@@ -99,6 +99,14 @@ void KisShortcutMatcher::addAction(KisAbstractInputAction *action)
     m_d->actions.append(action);
 }
 
+bool KisShortcutMatcher::supportsHiResInputEvents()
+{
+    return
+        m_d->runningShortcut &&
+        m_d->runningShortcut->action() &&
+        m_d->runningShortcut->action()->supportsHiResInputEvents();
+}
+
 bool KisShortcutMatcher::keyPressed(Qt::Key key)
 {
     bool retval = false;
@@ -259,25 +267,6 @@ Qt::MouseButtons listToFlags(const QList<Qt::MouseButton> &list) \
{  return flags;
 }
 
-bool KisShortcutMatcher::tabletMoved(QTabletEvent *event)
-{
-    if (!m_d->runningShortcut) return false;
-    bool retval = false;
-
-    KisAbstractInputAction *action = m_d->runningShortcut->action();
-    if (action->supportsHiResInputEvents()) {
-        QMouseEvent mouseEvent(QEvent::MouseMove,
-                               event->pos(),
-                               Qt::NoButton,
-                               listToFlags(m_d->buttons),
-                               event->modifiers());
-        action->inputEvent(&mouseEvent);
-        retval = true;
-    }
-
-    return retval;
-}
-
 void KisShortcutMatcher::reset()
 {
     m_d->keys.clear();
diff --git a/krita/ui/input/kis_shortcut_matcher.h \
b/krita/ui/input/kis_shortcut_matcher.h index 3f7eb74..801242c 100644
--- a/krita/ui/input/kis_shortcut_matcher.h
+++ b/krita/ui/input/kis_shortcut_matcher.h
@@ -92,6 +92,15 @@ public:
     void addAction(KisAbstractInputAction *action);
 
     /**
+     * Returns true if the currently running shortcut supports
+     * processing hi resolution flow of events from the tablet
+     * device. In most of the cases (except of the painting itself)
+     * too many events make the execution of the action too slow, so
+     * the action can decide whether it needs it.
+     */
+    bool supportsHiResInputEvents();
+
+    /**
      * Handles a key press event.
      * No autorepeat events should be passed to this method.
      *
@@ -163,17 +172,6 @@ public:
     bool touchEndEvent(QTouchEvent *event);
 
     /**
-     * Handles the High Resolution tablet events
-     * (used on Windows only)
-     *
-     * \param event the event that caused this call
-     *
-     * \return whether the event has been handled successfully and
-     * should be eaten by the events filter
-     */
-    bool tabletMoved(QTabletEvent *event);
-
-    /**
      * Resets the internal state of the matcher
      *
      * This should be done when the window has lost the focus for
diff --git a/krita/ui/input/kis_tool_invocation_action.cpp \
b/krita/ui/input/kis_tool_invocation_action.cpp index 685bbda..20ae352 100644
--- a/krita/ui/input/kis_tool_invocation_action.cpp
+++ b/krita/ui/input/kis_tool_invocation_action.cpp
@@ -117,5 +117,5 @@ void KisToolInvocationAction::inputEvent(QEvent* event)
 
 bool KisToolInvocationAction::supportsHiResInputEvents() const
 {
-    return true;
+    return inputManager()->toolProxy()->primaryActionSupportsHiResEvents();
 }
diff --git a/krita/ui/tests/kis_input_manager_test.cpp \
b/krita/ui/tests/kis_input_manager_test.cpp index 51bfcc8..a7244aa 100644
--- a/krita/ui/tests/kis_input_manager_test.cpp
+++ b/krita/ui/tests/kis_input_manager_test.cpp
@@ -353,28 +353,6 @@ void KisInputManagerTest::testMouseMoves()
     QCOMPARE(a->m_gotInput, true);
     a->reset();
 
-    // Check High Resolution events for usual action
-    QTabletEvent tabletEvent(QEvent::TabletMove, QPoint(), QPoint(), QPointF(),
-                             0, 0, 0.0, 0, 0, 0.0, 0.0, 0, Qt::NoModifier, 0);
-    QVERIFY(!m.tabletMoved(&tabletEvent));
-    QCOMPARE(a->m_gotInput, false);
-    a->reset();
-
-    // Check usual events for High Resolution actions
-    a->setHighResInputEvents(true);
-    QVERIFY(m.mouseMoved(&mouseEvent));
-    QCOMPARE(a->m_gotInput, true);
-    a->reset();
-    a->setHighResInputEvents(false);
-
-    // Check High Resolution for High Resolution actions
-    a->setHighResInputEvents(true);
-    QVERIFY(m.tabletMoved(&tabletEvent));
-    QCOMPARE(a->m_gotInput, true);
-    a->reset();
-    a->setHighResInputEvents(false);
-
-
     // Release Ctrl
     QVERIFY(!m.keyReleased(Qt::Key_Control));
     QCOMPARE(a->m_beginIndex, -1);
diff --git a/krita/ui/tool/kis_tool.cc b/krita/ui/tool/kis_tool.cc
index 77842a0..9a32306 100644
--- a/krita/ui/tool/kis_tool.cc
+++ b/krita/ui/tool/kis_tool.cc
@@ -450,6 +450,11 @@ void KisTool::endPrimaryAction(KoPointerEvent *event)
     Q_UNUSED(event);
 }
 
+bool KisTool::primaryActionSupportsHiResEvents() const
+{
+    return false;
+}
+
 void KisTool::beginAlternateAction(KoPointerEvent *event, AlternateAction action)
 {
     Q_UNUSED(event);
diff --git a/krita/ui/tool/kis_tool.h b/krita/ui/tool/kis_tool.h
index 5089fed..1bbce7a 100644
--- a/krita/ui/tool/kis_tool.h
+++ b/krita/ui/tool/kis_tool.h
@@ -98,6 +98,7 @@ public:
     virtual void continuePrimaryAction(KoPointerEvent *event);
     virtual void endPrimaryAction(KoPointerEvent *event);
     virtual void beginPrimaryDoubleClickAction(KoPointerEvent *event);
+    virtual bool primaryActionSupportsHiResEvents() const;
 
     enum ToolAction {
         Primary,
diff --git a/krita/ui/tool/kis_tool_freehand.cc b/krita/ui/tool/kis_tool_freehand.cc
index fbf0782..699efe4 100644
--- a/krita/ui/tool/kis_tool_freehand.cc
+++ b/krita/ui/tool/kis_tool_freehand.cc
@@ -165,6 +165,11 @@ void KisToolFreehand::endStroke()
     setCurrentNodeLocked(false);
 }
 
+bool KisToolFreehand::primaryActionSupportsHiResEvents() const
+{
+    return true;
+}
+
 void KisToolFreehand::beginPrimaryAction(KoPointerEvent *event)
 {
     // FIXME: workaround for the Duplicate Op
diff --git a/krita/ui/tool/kis_tool_freehand.h b/krita/ui/tool/kis_tool_freehand.h
index 3e750be..1963e46 100644
--- a/krita/ui/tool/kis_tool_freehand.h
+++ b/krita/ui/tool/kis_tool_freehand.h
@@ -56,6 +56,8 @@ public:
 
 protected:
     bool tryPickByPaintOp(KoPointerEvent *event, AlternateAction action);
+
+    bool primaryActionSupportsHiResEvents() const;
     void beginPrimaryAction(KoPointerEvent *event);
     void continuePrimaryAction(KoPointerEvent *event);
     void endPrimaryAction(KoPointerEvent *event);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic