Commit 2c299f5b authored by Sharaf Zaman's avatar Sharaf Zaman Committed by Boudewijn Rempt

Add touch support to android

Maniphest: T10784
parent b1bf4fe7
...@@ -33,6 +33,7 @@ public: ...@@ -33,6 +33,7 @@ public:
Private() Private()
: tabletEvent(0) : tabletEvent(0)
, mouseEvent(0) , mouseEvent(0)
, touchEvent(0)
, deviceEvent(0) , deviceEvent(0)
, tabletButton(Qt::NoButton) , tabletButton(Qt::NoButton)
, globalPos(0, 0) , globalPos(0, 0)
...@@ -45,6 +46,7 @@ public: ...@@ -45,6 +46,7 @@ public:
QTabletEvent *tabletEvent; QTabletEvent *tabletEvent;
QMouseEvent *mouseEvent; QMouseEvent *mouseEvent;
QTouchEvent *touchEvent;
KoInputDeviceHandlerEvent *deviceEvent; KoInputDeviceHandlerEvent *deviceEvent;
Qt::MouseButton tabletButton; Qt::MouseButton tabletButton;
QPoint globalPos, pos; QPoint globalPos, pos;
...@@ -70,6 +72,16 @@ KoPointerEvent::KoPointerEvent(QTabletEvent *ev, const QPointF &pnt) ...@@ -70,6 +72,16 @@ KoPointerEvent::KoPointerEvent(QTabletEvent *ev, const QPointF &pnt)
d->tabletEvent = ev; d->tabletEvent = ev;
} }
KoPointerEvent::KoPointerEvent(QTouchEvent* ev, const QPointF &pnt)
: point(pnt)
, m_event(ev)
, d(new Private)
{
Q_ASSERT(m_event);
d->touchEvent = ev;
d->pos = ev->touchPoints().at(0).pos().toPoint();
}
KoPointerEvent::KoPointerEvent(KoInputDeviceHandlerEvent * ev, int x, int y, int z, int rx, int ry, int rz) KoPointerEvent::KoPointerEvent(KoInputDeviceHandlerEvent * ev, int x, int y, int z, int rx, int ry, int rz)
: m_event(ev) : m_event(ev)
, d(new Private()) , d(new Private())
......
...@@ -68,6 +68,8 @@ public: ...@@ -68,6 +68,8 @@ public:
*/ */
KoPointerEvent(QTabletEvent *event, const QPointF &point); KoPointerEvent(QTabletEvent *event, const QPointF &point);
KoPointerEvent(QTouchEvent* ev, const QPointF& pnt);
KoPointerEvent(KoInputDeviceHandlerEvent *event, int x, int y, int z = 0, int rx = 0, int ry = 0, int rz = 0); KoPointerEvent(KoInputDeviceHandlerEvent *event, int x, int y, int z = 0, int rx = 0, int ry = 0, int rz = 0);
KoPointerEvent(KoPointerEvent *event, const QPointF& point); KoPointerEvent(KoPointerEvent *event, const QPointF& point);
......
...@@ -375,6 +375,29 @@ void KoToolProxy::setActiveTool(KoToolBase *tool) ...@@ -375,6 +375,29 @@ void KoToolProxy::setActiveTool(KoToolBase *tool)
} }
} }
void KoToolProxy::touchEvent(QTouchEvent* event, const QPointF& point)
{
// only one "touchpoint" events should be here
KoPointerEvent ev(event, point);
if (!d->activeTool) return;
switch (event->touchPointStates())
{
case Qt::TouchPointPressed:
d->activeTool->mousePressEvent(&ev);
break;
case Qt::TouchPointMoved:
d->activeTool->mouseMoveEvent(&ev);
break;
case Qt::TouchPointReleased:
d->activeTool->mouseReleaseEvent(&ev);
break;
default: // don't care
;
}
}
void KoToolProxyPrivate::setCanvasController(KoCanvasController *c) void KoToolProxyPrivate::setCanvasController(KoCanvasController *c)
{ {
controller = c; controller = c;
......
...@@ -142,6 +142,8 @@ public: ...@@ -142,6 +142,8 @@ public:
/// Set the new active tool. /// Set the new active tool.
virtual void setActiveTool(KoToolBase *tool); virtual void setActiveTool(KoToolBase *tool);
void touchEvent(QTouchEvent* event, const QPointF& point);
/// \internal /// \internal
KoToolProxyPrivate *priv(); KoToolProxyPrivate *priv();
......
...@@ -73,6 +73,14 @@ KoPointerEvent KisToolProxy::convertEventToPointerEvent(QEvent *event, const QPo ...@@ -73,6 +73,14 @@ KoPointerEvent KisToolProxy::convertEventToPointerEvent(QEvent *event, const QPo
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
return KoPointerEvent(mouseEvent, docPoint); return KoPointerEvent(mouseEvent, docPoint);
} }
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
{
*result = true;
QTouchEvent *touchEvent = static_cast<QTouchEvent *> (event);
return KoPointerEvent(touchEvent, docPoint);
}
default: default:
; ;
} }
...@@ -115,6 +123,7 @@ bool KisToolProxy::forwardEvent(ActionState state, KisTool::ToolAction action, Q ...@@ -115,6 +123,7 @@ bool KisToolProxy::forwardEvent(ActionState state, KisTool::ToolAction action, Q
QTabletEvent *tabletEvent = dynamic_cast<QTabletEvent*>(event); QTabletEvent *tabletEvent = dynamic_cast<QTabletEvent*>(event);
QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event); QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
QTouchEvent *touchEvent = dynamic_cast<QTouchEvent *> (event);
if (tabletEvent) { if (tabletEvent) {
QPointF docPoint = widgetToDocument(tabletEvent->posF()); QPointF docPoint = widgetToDocument(tabletEvent->posF());
...@@ -138,6 +147,13 @@ bool KisToolProxy::forwardEvent(ActionState state, KisTool::ToolAction action, Q ...@@ -138,6 +147,13 @@ bool KisToolProxy::forwardEvent(ActionState state, KisTool::ToolAction action, Q
forwardToTool(state, action, originalEvent, docPoint); forwardToTool(state, action, originalEvent, docPoint);
retval = mouseEvent->isAccepted(); retval = mouseEvent->isAccepted();
} }
else if (touchEvent) {
QPointF docPoint = widgetToDocument(touchEvent->touchPoints().at(0).pos());
touchEvent->accept();
this->touchEvent(touchEvent, docPoint);
forwardToTool(state, action, touchEvent, docPoint);
retval = touchEvent->isAccepted();
}
else if (event && event->type() == QEvent::KeyPress) { else if (event && event->type() == QEvent::KeyPress) {
QKeyEvent* kevent = static_cast<QKeyEvent*>(event); QKeyEvent* kevent = static_cast<QKeyEvent*>(event);
keyPressEvent(kevent); keyPressEvent(kevent);
......
...@@ -231,6 +231,15 @@ template<> void copyEventHack(QTabletEvent *src, QScopedPointer<QEvent> &dst) { ...@@ -231,6 +231,15 @@ template<> void copyEventHack(QTabletEvent *src, QScopedPointer<QEvent> &dst) {
dst.reset(tmp); dst.reset(tmp);
} }
template<> void copyEventHack(QTouchEvent *src, QScopedPointer<QEvent> &dst) {
QTouchEvent *tmp = new QTouchEvent(src->type(),
src->device(),
src->modifiers(),
src->touchPointStates(),
src->touchPoints());
tmp->setTimestamp(src->timestamp());
dst.reset(tmp);
}
template <class Event> template <class Event>
...@@ -241,7 +250,8 @@ bool KisInputManager::compressMoveEventCommon(Event *event) ...@@ -241,7 +250,8 @@ bool KisInputManager::compressMoveEventCommon(Event *event)
* has a correct type. * has a correct type.
*/ */
static_assert(std::is_same<Event, QMouseEvent>::value || static_assert(std::is_same<Event, QMouseEvent>::value ||
std::is_same<Event, QTabletEvent>::value, std::is_same<Event, QTabletEvent>::value ||
std::is_same<Event, QTouchEvent>::value,
"event should be a mouse or a tablet event"); "event should be a mouse or a tablet event");
bool retval = false; bool retval = false;
...@@ -250,7 +260,8 @@ bool KisInputManager::compressMoveEventCommon(Event *event) ...@@ -250,7 +260,8 @@ bool KisInputManager::compressMoveEventCommon(Event *event)
* Compress the events if the tool doesn't need high resolution input * Compress the events if the tool doesn't need high resolution input
*/ */
if ((event->type() == QEvent::MouseMove || if ((event->type() == QEvent::MouseMove ||
event->type() == QEvent::TabletMove) && event->type() == QEvent::TabletMove ||
event->type() == QEvent::TouchUpdate) &&
(!d->matcher.supportsHiResInputEvents() || (!d->matcher.supportsHiResInputEvents() ||
d->testingCompressBrushEvents)) { d->testingCompressBrushEvents)) {
...@@ -303,6 +314,7 @@ bool KisInputManager::eventFilterImpl(QEvent * event) ...@@ -303,6 +314,7 @@ bool KisInputManager::eventFilterImpl(QEvent * event)
d->accumulatedScrollDelta = 0; d->accumulatedScrollDelta = 0;
} }
switch (event->type()) { switch (event->type()) {
case QEvent::MouseButtonPress: case QEvent::MouseButtonPress:
case QEvent::MouseButtonDblClick: { case QEvent::MouseButtonDblClick: {
...@@ -576,16 +588,32 @@ bool KisInputManager::eventFilterImpl(QEvent * event) ...@@ -576,16 +588,32 @@ bool KisInputManager::eventFilterImpl(QEvent * event)
case QEvent::TouchBegin: case QEvent::TouchBegin:
{ {
if (startTouch(retval)) { if (startTouch(retval)) {
QTouchEvent *tevent = static_cast<QTouchEvent*>(event); QTouchEvent *touchEvent = static_cast<QTouchEvent *> (event);
KisAbstractInputAction::setInputManager(this); KisAbstractInputAction::setInputManager(this);
retval = d->matcher.touchBeginEvent(tevent);
if (!KisConfig(true).disableTouchOnCanvas()
&& touchEvent->touchPoints().count() == 1
&& touchEvent->touchPointStates() != Qt::TouchPointStationary)
{
retval = d->matcher.buttonPressed(Qt::LeftButton, touchEvent);
d->touchStrokeShortcut = true;
}
else {
retval = d->matcher.touchBeginEvent(touchEvent);
}
event->accept(); event->accept();
} }
// if the event isn't handled, Qt starts to send MouseEvents
if (!KisConfig(true).disableTouchOnCanvas())
retval = true;
break; break;
} }
case QEvent::TouchUpdate: case QEvent::TouchUpdate:
{ {
QTouchEvent *tevent = static_cast<QTouchEvent*>(event); QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
int count = 0; int count = 0;
Q_FOREACH (const QTouchEvent::TouchPoint &point, tevent->touchPoints()) { Q_FOREACH (const QTouchEvent::TouchPoint &point, tevent->touchPoints()) {
...@@ -599,20 +627,47 @@ bool KisInputManager::eventFilterImpl(QEvent * event) ...@@ -599,20 +627,47 @@ bool KisInputManager::eventFilterImpl(QEvent * event)
retval = d->matcher.touchEndEvent(tevent); retval = d->matcher.touchEndEvent(tevent);
} else { } else {
#endif #endif
d->touchHasBlockedPressEvents = KisConfig(true).disableTouchOnCanvas(); if (!KisConfig(true).disableTouchOnCanvas()
KisAbstractInputAction::setInputManager(this); && !d->touchHasBlockedPressEvents
retval = d->matcher.touchUpdateEvent(tevent); && touchEvent->touchPoints().count() == 1
&& touchEvent->touchPointStates() != Qt::TouchPointStationary)
{
retval = compressMoveEventCommon(touchEvent);
d->blockMouseEvents();
d->resetCompressor();
}
else {
KisAbstractInputAction::setInputManager(this);
d->touchHasBlockedPressEvents = true;
retval = d->matcher.touchUpdateEvent(touchEvent);
}
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
} }
#endif #endif
// if the event isn't handled, Qt starts to send MouseEvents
if (!KisConfig(true).disableTouchOnCanvas())
retval = true;
event->accept(); event->accept();
break; break;
} }
case QEvent::TouchEnd: case QEvent::TouchEnd:
{ {
endTouch(); endTouch();
QTouchEvent *tevent = static_cast<QTouchEvent*>(event); QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
retval = d->matcher.touchEndEvent(tevent); retval = d->matcher.touchEndEvent(touchEvent);
if (d->touchStrokeShortcut)
{
retval = d->matcher.buttonReleased(Qt::LeftButton, touchEvent);
d->touchStrokeShortcut = false;
}
// if the event isn't handled, Qt starts to send MouseEvents
if (!KisConfig(true).disableTouchOnCanvas())
retval = true;
event->accept(); event->accept();
break; break;
} }
...@@ -657,7 +712,6 @@ bool KisInputManager::eventFilterImpl(QEvent * event) ...@@ -657,7 +712,6 @@ bool KisInputManager::eventFilterImpl(QEvent * event)
bool KisInputManager::startTouch(bool &retval) bool KisInputManager::startTouch(bool &retval)
{ {
d->touchHasBlockedPressEvents = KisConfig(true).disableTouchOnCanvas();
// Touch rejection: if touch is disabled on canvas, no need to block mouse press events // Touch rejection: if touch is disabled on canvas, no need to block mouse press events
if (KisConfig(true).disableTouchOnCanvas()) { if (KisConfig(true).disableTouchOnCanvas()) {
d->eatOneMousePress(); d->eatOneMousePress();
......
...@@ -79,6 +79,8 @@ public: ...@@ -79,6 +79,8 @@ public:
PriorityList priorityEventFilter; PriorityList priorityEventFilter;
int priorityEventFilterSeqNo; int priorityEventFilterSeqNo;
bool touchStrokeShortcut = false;
void blockMouseEvents(); void blockMouseEvents();
void allowMouseEvents(); void allowMouseEvents();
void eatOneMousePress(); void eatOneMousePress();
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "kis_stroke_shortcut.h" #include "kis_stroke_shortcut.h"
#include "kis_touch_shortcut.h" #include "kis_touch_shortcut.h"
#include "kis_native_gesture_shortcut.h" #include "kis_native_gesture_shortcut.h"
#include "kis_config.h"
#ifdef DEBUG_MATCHER #ifdef DEBUG_MATCHER
...@@ -89,13 +90,15 @@ public: ...@@ -89,13 +90,15 @@ public:
bool usingNativeGesture; bool usingNativeGesture;
inline bool actionsSuppressed() const { inline bool actionsSuppressed() const {
return suppressAllActions || !cursorEntered; return (suppressAllActions || !cursorEntered)
&& KisConfig(true).disableTouchOnCanvas();
} }
inline bool actionsSuppressedIgnoreFocus() const { inline bool actionsSuppressedIgnoreFocus() const {
return suppressAllActions; return suppressAllActions;
} }
// only for touch events with touchPoints count >= 2
inline bool isUsingTouch() const { inline bool isUsingTouch() const {
return usingTouch || usingNativeGesture; return usingTouch || usingNativeGesture;
} }
...@@ -204,14 +207,14 @@ bool KisShortcutMatcher::buttonPressed(Qt::MouseButton button, QEvent *event) ...@@ -204,14 +207,14 @@ bool KisShortcutMatcher::buttonPressed(Qt::MouseButton button, QEvent *event)
if (m_d->buttons.contains(button)) { DEBUG_ACTION("Peculiar, button was already pressed."); } if (m_d->buttons.contains(button)) { DEBUG_ACTION("Peculiar, button was already pressed."); }
if (!m_d->runningShortcut) { if (!hasRunningShortcut()) {
prepareReadyShortcuts(); prepareReadyShortcuts();
retval = tryRunReadyShortcut(button, event); retval = tryRunReadyShortcut(button, event);
} }
m_d->buttons.insert(button); m_d->buttons.insert(button);
if (!m_d->runningShortcut) { if (!hasRunningShortcut()) {
prepareReadyShortcuts(); prepareReadyShortcuts();
tryActivateReadyShortcut(); tryActivateReadyShortcut();
} }
...@@ -609,12 +612,12 @@ bool KisShortcutMatcher::tryRunTouchShortcut( QTouchEvent* event ) ...@@ -609,12 +612,12 @@ bool KisShortcutMatcher::tryRunTouchShortcut( QTouchEvent* event )
if( goodCandidate ) { if( goodCandidate ) {
if( m_d->runningShortcut ) { if( m_d->runningShortcut ) {
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, QTouchEvent touchEvent(QEvent::TouchEnd,
event->touchPoints().at(0).pos().toPoint(), event->device(),
Qt::LeftButton, event->modifiers(),
Qt::LeftButton, Qt::TouchPointReleased,
event->modifiers()); event->touchPoints());
tryEndRunningShortcut(Qt::LeftButton, &mouseEvent); tryEndRunningShortcut(Qt::LeftButton, &touchEvent);
} }
goodCandidate->action()->activate(goodCandidate->shortcutIndex()); goodCandidate->action()->activate(goodCandidate->shortcutIndex());
goodCandidate->action()->begin(goodCandidate->shortcutIndex(), event); goodCandidate->action()->begin(goodCandidate->shortcutIndex(), event);
......
...@@ -24,6 +24,11 @@ ...@@ -24,6 +24,11 @@
#include "kis_abstract_shortcut.h" #include "kis_abstract_shortcut.h"
class QTouchEvent; class QTouchEvent;
/**
* @brief The KisTouchShortcut class only handles touch gestures
* it _does not_ handle tool invocation i.e painting (which is being
* handled in KisShortcutMatcher).
*/
class KisTouchShortcut : public KisAbstractShortcut class KisTouchShortcut : public KisAbstractShortcut
{ {
public: public:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment