Commit 97a2fe4d authored by Sharaf Zaman's avatar Sharaf Zaman

Add touch support to android

Maniphest: T10784
parent b56fb1c8
......@@ -33,6 +33,7 @@ public:
Private()
: tabletEvent(0)
, mouseEvent(0)
, touchEvent(0)
, deviceEvent(0)
, tabletButton(Qt::NoButton)
, globalPos(0, 0)
......@@ -45,6 +46,7 @@ public:
QTabletEvent *tabletEvent;
QMouseEvent *mouseEvent;
QTouchEvent *touchEvent;
KoInputDeviceHandlerEvent *deviceEvent;
Qt::MouseButton tabletButton;
QPoint globalPos, pos;
......@@ -70,6 +72,16 @@ KoPointerEvent::KoPointerEvent(QTabletEvent *ev, const QPointF &pnt)
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)
: m_event(ev)
, d(new Private())
......
......@@ -68,6 +68,8 @@ public:
*/
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(KoPointerEvent *event, const QPointF& point);
......
......@@ -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)
{
controller = c;
......
......@@ -142,6 +142,8 @@ public:
/// Set the new active tool.
virtual void setActiveTool(KoToolBase *tool);
void touchEvent(QTouchEvent* event, const QPointF& point);
/// \internal
KoToolProxyPrivate *priv();
......
......@@ -73,6 +73,14 @@ KoPointerEvent KisToolProxy::convertEventToPointerEvent(QEvent *event, const QPo
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
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:
;
}
......@@ -115,6 +123,7 @@ bool KisToolProxy::forwardEvent(ActionState state, KisTool::ToolAction action, Q
QTabletEvent *tabletEvent = dynamic_cast<QTabletEvent*>(event);
QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
QTouchEvent *touchEvent = dynamic_cast<QTouchEvent *> (event);
if (tabletEvent) {
QPointF docPoint = widgetToDocument(tabletEvent->posF());
......@@ -138,6 +147,13 @@ bool KisToolProxy::forwardEvent(ActionState state, KisTool::ToolAction action, Q
forwardToTool(state, action, originalEvent, docPoint);
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) {
QKeyEvent* kevent = static_cast<QKeyEvent*>(event);
keyPressEvent(kevent);
......
......@@ -231,6 +231,15 @@ template<> void copyEventHack(QTabletEvent *src, QScopedPointer<QEvent> &dst) {
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>
......@@ -241,7 +250,8 @@ bool KisInputManager::compressMoveEventCommon(Event *event)
* has a correct type.
*/
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");
bool retval = false;
......@@ -250,7 +260,8 @@ bool KisInputManager::compressMoveEventCommon(Event *event)
* Compress the events if the tool doesn't need high resolution input
*/
if ((event->type() == QEvent::MouseMove ||
event->type() == QEvent::TabletMove) &&
event->type() == QEvent::TabletMove ||
event->type() == QEvent::TouchUpdate) &&
(!d->matcher.supportsHiResInputEvents() ||
d->testingCompressBrushEvents)) {
......@@ -303,6 +314,7 @@ bool KisInputManager::eventFilterImpl(QEvent * event)
d->accumulatedScrollDelta = 0;
}
switch (event->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonDblClick: {
......@@ -576,16 +588,32 @@ bool KisInputManager::eventFilterImpl(QEvent * event)
case QEvent::TouchBegin:
{
if (startTouch(retval)) {
QTouchEvent *tevent = static_cast<QTouchEvent*>(event);
QTouchEvent *touchEvent = static_cast<QTouchEvent *> (event);
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();
}
// if the event isn't handled, Qt starts to send MouseEvents
if (!KisConfig(true).disableTouchOnCanvas())
retval = true;
break;
}
case QEvent::TouchUpdate:
{
QTouchEvent *tevent = static_cast<QTouchEvent*>(event);
QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
#ifdef Q_OS_MAC
int count = 0;
Q_FOREACH (const QTouchEvent::TouchPoint &point, tevent->touchPoints()) {
......@@ -599,20 +627,47 @@ bool KisInputManager::eventFilterImpl(QEvent * event)
retval = d->matcher.touchEndEvent(tevent);
} else {
#endif
d->touchHasBlockedPressEvents = KisConfig(true).disableTouchOnCanvas();
KisAbstractInputAction::setInputManager(this);
retval = d->matcher.touchUpdateEvent(tevent);
if (!KisConfig(true).disableTouchOnCanvas()
&& !d->touchHasBlockedPressEvents
&& 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
}
#endif
// if the event isn't handled, Qt starts to send MouseEvents
if (!KisConfig(true).disableTouchOnCanvas())
retval = true;
event->accept();
break;
}
case QEvent::TouchEnd:
{
endTouch();
QTouchEvent *tevent = static_cast<QTouchEvent*>(event);
retval = d->matcher.touchEndEvent(tevent);
QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
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();
break;
}
......@@ -657,7 +712,6 @@ bool KisInputManager::eventFilterImpl(QEvent * event)
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
if (KisConfig(true).disableTouchOnCanvas()) {
d->eatOneMousePress();
......
......@@ -79,6 +79,8 @@ public:
PriorityList priorityEventFilter;
int priorityEventFilterSeqNo;
bool touchStrokeShortcut = false;
void blockMouseEvents();
void allowMouseEvents();
void eatOneMousePress();
......
......@@ -27,6 +27,7 @@
#include "kis_stroke_shortcut.h"
#include "kis_touch_shortcut.h"
#include "kis_native_gesture_shortcut.h"
#include "kis_config.h"
#ifdef DEBUG_MATCHER
......@@ -89,13 +90,15 @@ public:
bool usingNativeGesture;
inline bool actionsSuppressed() const {
return suppressAllActions || !cursorEntered;
return (suppressAllActions || !cursorEntered)
&& KisConfig(true).disableTouchOnCanvas();
}
inline bool actionsSuppressedIgnoreFocus() const {
return suppressAllActions;
}
// only for touch events with touchPoints count >= 2
inline bool isUsingTouch() const {
return usingTouch || usingNativeGesture;
}
......@@ -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->runningShortcut) {
if (!hasRunningShortcut()) {
prepareReadyShortcuts();
retval = tryRunReadyShortcut(button, event);
}
m_d->buttons.insert(button);
if (!m_d->runningShortcut) {
if (!hasRunningShortcut()) {
prepareReadyShortcuts();
tryActivateReadyShortcut();
}
......@@ -609,12 +612,12 @@ bool KisShortcutMatcher::tryRunTouchShortcut( QTouchEvent* event )
if( goodCandidate ) {
if( m_d->runningShortcut ) {
QMouseEvent mouseEvent(QEvent::MouseButtonRelease,
event->touchPoints().at(0).pos().toPoint(),
Qt::LeftButton,
Qt::LeftButton,
event->modifiers());
tryEndRunningShortcut(Qt::LeftButton, &mouseEvent);
QTouchEvent touchEvent(QEvent::TouchEnd,
event->device(),
event->modifiers(),
Qt::TouchPointReleased,
event->touchPoints());
tryEndRunningShortcut(Qt::LeftButton, &touchEvent);
}
goodCandidate->action()->activate(goodCandidate->shortcutIndex());
goodCandidate->action()->begin(goodCandidate->shortcutIndex(), event);
......
......@@ -24,6 +24,11 @@
#include "kis_abstract_shortcut.h"
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
{
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