touch: implement multi-touch tracking
authorGiWoong Kim <giwoong.kim@samsung.com>
Tue, 28 Apr 2015 12:38:43 +0000 (21:38 +0900)
committerGiWoong Kim <giwoong.kim@samsung.com>
Wed, 29 Apr 2015 12:33:53 +0000 (21:33 +0900)
supports separated moving mode only

Change-Id: If3193d7f961118fca4305744ce2114ff4d10a259
Signed-off-by: GiWoong Kim <giwoong.kim@samsung.com>
12 files changed:
tizen/src/ui/displaybase.cpp
tizen/src/ui/displaybase.h
tizen/src/ui/input/Makefile.objs
tizen/src/ui/input/keyboardhelper.cpp
tizen/src/ui/input/keyboardhelper.h
tizen/src/ui/input/multitouchtracker.cpp [new file with mode: 0644]
tizen/src/ui/input/multitouchtracker.h [new file with mode: 0644]
tizen/src/ui/input/touchscreenhelper.cpp
tizen/src/ui/input/touchscreenhelper.h
tizen/src/ui/mainwindow.cpp
tizen/src/ui/mainwindow.h
tizen/src/ui/skinview.cpp

index 7b0ccb9..54fbec7 100644 (file)
@@ -127,6 +127,11 @@ QPoint DisplayBase::getGuestPos(QPoint hostPos)
     return guestPos;
 }
 
+TouchScreenHelper *DisplayBase::getTouchScreenHelper()
+{
+    return tsHelper;
+}
+
 void DisplayBase::handleMousePress(QMouseEvent *event)
 {
     if (event->button() == Qt::LeftButton) {
index 8728bd5..495a44d 100644 (file)
@@ -46,7 +46,9 @@ public:
     void scale(qreal scaleFactor);
     void update();
     void updateGeometry();
+
     QPoint getGuestPos(QPoint hostPos);
+    TouchScreenHelper *getTouchScreenHelper();
 
 protected:
     DisplayBase(QRect rect, int angle, qreal scaleFactor, QWidget *w);
index 71484d4..2b953a4 100644 (file)
@@ -1,4 +1,5 @@
 obj-$(CONFIG_QT) += touchscreenhelper.o
+obj-$(CONFIG_QT) += multitouchtracker.o
 obj-$(CONFIG_QT) += keyboardhelper.o
 obj-$(CONFIG_QT) += keyboardshortcut.o moc_keyboardshortcut.o
 
index 5c3e21f..5000f18 100644 (file)
@@ -30,6 +30,7 @@
 #include <QtWidgets>
 
 #include "keyboardhelper.h"
+#include "mainwindow.h"
 
 extern "C" {
 #include "emul_state.h"
@@ -38,13 +39,14 @@ extern "C" {
 void virtio_keyboard_event(int keycode);
 }
 
-KeyboardHelper::KeyboardHelper()
+KeyboardHelper::KeyboardHelper(QWidget *parent)
 {
-    createKeyMap();
-    createKeypadMap();
-
+    this->parent = parent;
     this->numLockState = false;
     this->capsLockState = false;
+
+    createKeyMap();
+    createKeypadMap();
 }
 
 void KeyboardHelper::createKeypadMap()
@@ -205,6 +207,14 @@ void KeyboardHelper::createKeyMap()
     keyMap.insert(Qt::Key_F12, 88); /* f12 */
 }
 
+void KeyboardHelper::finishMtTracking()
+{
+    DisplayBase *display = ((MainWindow *)parent->parentWidget())->getDisplay();
+    if (display != NULL) {
+        display->getTouchScreenHelper()->finishMtTracking();
+    }
+}
+
 void KeyboardHelper::autoKeyRelease(void)
 {
     while (!keyCodeList.isEmpty()) {
@@ -216,9 +226,10 @@ void KeyboardHelper::autoKeyRelease(void)
 
     /* disable multi-touch mode */
     if (get_multi_touch_enable() != 0) {
-        set_multi_touch_enable(0);
-
         qDebug() << "disable multi-touch";
+
+        set_multi_touch_enable(0);
+        finishMtTracking();
     }
 }
 
@@ -275,39 +286,42 @@ bool KeyboardHelper::isSpecialKey(int keyCode)
     return false;
 }
 
-static void pressFilterMtChecking(QKeyEvent *event) {
+void KeyboardHelper::pressFilterMtChecking(QKeyEvent *event)
+{
     switch(event->key()) {
     case Qt::Key_Alt:
         if (event->modifiers() == (Qt::ControlModifier | Qt::AltModifier)) {
-            set_multi_touch_enable(3);
             qDebug() << "enable multi-touch mode : 3";
+            set_multi_touch_enable(3);
         }
 
         break;
     case Qt::Key_Shift:
         if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) {
-            set_multi_touch_enable(2);
             qDebug() << "enable multi-touch mode : 2";
+            set_multi_touch_enable(2);
         } else if (event->modifiers() == Qt::ShiftModifier) {
-            set_multi_touch_enable(1);
             qDebug() << "enable multi-touch mode : 1";
+            set_multi_touch_enable(1);
         }
 
         break;
     case Qt::Key_Control:
         if (event->modifiers() == Qt::ControlModifier) {
-            set_multi_touch_enable(1);
             qDebug() << "enable multi-touch mode : 1";
+            set_multi_touch_enable(1);
         } else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) {
-            set_multi_touch_enable(2);
             qDebug() << "enable multi-touch mode : 2";
+            set_multi_touch_enable(2);
         }
 
         break;
     default:
         if (get_multi_touch_enable() != 0) {
-            set_multi_touch_enable(0);
             qDebug() << "disable multi-touch";
+
+            set_multi_touch_enable(0);
+            finishMtTracking();
         }
 
         break;
@@ -417,35 +431,42 @@ void KeyboardHelper::keyPressed(QKeyEvent *event)
     }
 }
 
-static void releaseFilterMtChecking(QKeyEvent *event) {
+void KeyboardHelper::releaseFilterMtChecking(QKeyEvent *event)
+{
     switch(event->key()) {
     case Qt::Key_Alt:
         if (event->modifiers() == Qt::ControlModifier) {
-            set_multi_touch_enable(1);
             qDebug() << "enabled multi-touch mode : 3 -> 1";
+            set_multi_touch_enable(1);
         } else {
-            set_multi_touch_enable(0);
             qDebug() << "disable multi-touch";
+
+            set_multi_touch_enable(0);
+            finishMtTracking();
         }
 
         break;
     case Qt::Key_Shift:
         if (event->modifiers() == Qt::ControlModifier) {
-            set_multi_touch_enable(1);
             qDebug() << "enabled multi-touch mode : 2 -> 1";
+            set_multi_touch_enable(1);
         } else {
-            set_multi_touch_enable(0);
             qDebug() << "disable multi-touch";
+
+            set_multi_touch_enable(0);
+            finishMtTracking();
         }
 
         break;
     case Qt::Key_Control:
         if (event->modifiers() == Qt::ShiftModifier) {
-            set_multi_touch_enable(1);
             qDebug() << "enabled multi-touch mode : 2 -> 1";
+            set_multi_touch_enable(1);
         } else {
-            set_multi_touch_enable(0);
             qDebug() << "disable multi-touch";
+
+            set_multi_touch_enable(0);
+            finishMtTracking();
         }
 
         break;
index 7eef329..c4afca6 100644 (file)
@@ -40,7 +40,7 @@ enum KbdLedState {
 class KeyboardHelper
 {
 public:
-    KeyboardHelper();
+    KeyboardHelper(QWidget *parent);
     ~KeyboardHelper();
 
     void keyPressed(QKeyEvent *event);
@@ -50,6 +50,7 @@ public:
     int keyCodeOperation(QKeyEvent *event, int keyCode);
 
 protected:
+    QWidget *parent;
     QList<int> keyCodeList;
     QMap<int, int> keyMap;
     QMap<int, int> keypadMap;
@@ -59,6 +60,10 @@ protected:
 private:
     void createKeyMap();
     void createKeypadMap();
+
+    void finishMtTracking();
+    void pressFilterMtChecking(QKeyEvent *event);
+    void releaseFilterMtChecking(QKeyEvent *event);
 };
 
 #endif // KEYBOARDHELPER_H
diff --git a/tizen/src/ui/input/multitouchtracker.cpp b/tizen/src/ui/input/multitouchtracker.cpp
new file mode 100644 (file)
index 0000000..1663fe5
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#include <QWidget>
+#include <QDebug>
+
+#include "multitouchtracker.h"
+
+extern "C" {
+void virtio_touchscreen_event(int x, int y, int z, int buttons_state);
+}
+
+TouchPoint::TouchPoint()
+{
+    this->id = 0;
+    this->hostPos = QPoint(0, 0);
+    this->guestPos = QPoint(0, 0);
+}
+
+TouchPoint::TouchPoint(int id, QPoint hostPos, QPoint guestPos)
+{
+    this->id = id;
+    this->hostPos = hostPos;
+    this->guestPos = guestPos;
+}
+
+int TouchPoint::getID()
+{
+    return id;
+}
+
+QPoint TouchPoint::getHostPos()
+{
+    return hostPos;
+}
+
+QPoint TouchPoint::getGuestPos()
+{
+    return guestPos;
+}
+
+void TouchPoint::updatePos(QPoint hostPos, QPoint guestPos)
+{
+    this->hostPos = hostPos;
+    this->guestPos = guestPos;
+}
+
+MultiTouchTracker::MultiTouchTracker(int maxTouchPoint)
+{
+    this->maxTouchPoint = maxTouchPoint;
+    this->pointRadius = 16; // TODO:
+    this->grabTouchPoint = NULL;
+}
+
+int MultiTouchTracker::getMaxTouchPoint()
+{
+    return maxTouchPoint;
+}
+
+int MultiTouchTracker::addTouchPoint(QPoint hostPos, QPoint guestPos)
+{
+    const int touchCnt = touchPointList.count();
+
+    if (touchCnt >= getMaxTouchPoint()) {
+        qWarning() << "support multi-touch up to" << getMaxTouchPoint();
+        return -1;
+    }
+
+    TouchPoint *point = new TouchPoint(touchCnt + 1, hostPos, guestPos);
+    touchPointList.append(point);
+    qDebug() << "ID" << point->getID() << "point touching";
+
+    return touchPointList.count();
+}
+
+TouchPoint *MultiTouchTracker::searchTouchPoint(QPoint targetPos)
+{
+    TouchPoint *point = NULL;
+
+    for (int i = 0; i < touchPointList.count(); i++) {
+        point = touchPointList.at(i);
+        if (point != NULL) {
+            if (targetPos.x() >= point->getHostPos().x() - pointRadius &&
+                targetPos.x() < point->getHostPos().x() + pointRadius &&
+                targetPos.y() >= point->getHostPos().y() - pointRadius &&
+                targetPos.y() < point->getHostPos().y() + pointRadius) {
+                return point;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+TouchPoint *MultiTouchTracker::searchTouchPoint(int targetID)
+{
+    TouchPoint *point = NULL;
+
+    for (int i = 0; i < touchPointList.count(); i++) {
+        point = touchPointList.at(i);
+        if (point != NULL) {
+            if (targetID == point->getID()) {
+                return point;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+/* separated moving mode */
+void MultiTouchTracker::touchProcessingSepa(QPoint hostPos, QPoint guestPos)
+{
+    TouchPoint *point = NULL;
+    const int touchCnt = touchPointList.count();
+
+    if (grabTouchPoint != NULL) {
+        grabTouchPoint->updatePos(hostPos, guestPos);
+
+        virtio_touchscreen_event(guestPos.x(), guestPos.y(),
+            grabTouchPoint->getID() - 1, 1);
+        return;
+    }
+
+    if (touchCnt == 0) { /* first touch input */
+        qDebug("mt sepa mode processing");
+
+        if (addTouchPoint(hostPos, guestPos) == -1) {
+            return;
+        }
+
+        virtio_touchscreen_event(guestPos.x(), guestPos.y(), 0, 1);
+    } else if ((point = searchTouchPoint(hostPos)) != NULL) { /* grab a touch */
+        qDebug() << "ID" << point->getID() << "point is taken";
+        grabTouchPoint = point;
+    } else if (touchCnt == getMaxTouchPoint()) { /* last touch */
+        point = touchPointList.last();
+        if (point != NULL) {
+            /* re-input */
+            qDebug() << "ID" << point->getID() << "point re-touching";
+
+            virtio_touchscreen_event(
+                point->getGuestPos().x(), point->getGuestPos().y(),
+                point->getID() - 1, 0);
+
+            point->updatePos(hostPos, guestPos);
+            virtio_touchscreen_event(
+                point->getGuestPos().x(), point->getGuestPos().y(),
+                point->getID() - 1, 1);
+        }
+    } else { /* additional touch */
+        if (addTouchPoint(hostPos, guestPos) == -1) {
+            return;
+        }
+
+        point = touchPointList.last();
+        virtio_touchscreen_event(guestPos.x(), guestPos.y(),
+            point->getID() - 1, 1);
+    }
+}
+
+/* parallel moving mode */
+void MultiTouchTracker::touchProcessingPara(QPoint hostPos, QPoint guestPos)
+{
+    //TODO:
+}
+
+/* symmetrical moving mode */
+void MultiTouchTracker::touchProcessingSymm(QPoint hostPos, QPoint guestPos)
+{
+   //TODO:
+}
+
+void MultiTouchTracker::touchReleasing()
+{
+    if (grabTouchPoint != NULL) {
+        qDebug() << "ID" << grabTouchPoint->getID() << "point let go";
+        grabTouchPoint = NULL;
+    }
+}
+
+void MultiTouchTracker::finishTracking()
+{
+    touchReleasing();
+
+    TouchPoint *point = NULL;
+    for (int i = 0; i < touchPointList.count(); i++) {
+        point = touchPointList.at(i);
+        if (point != NULL) {
+            virtio_touchscreen_event(
+                point->getGuestPos().x(), point->getGuestPos().y(),
+                point->getID() - 1, 0);
+
+            delete point;
+        }
+    }
+    touchPointList.clear();
+}
+
+MultiTouchTracker::~MultiTouchTracker()
+{
+    qDebug("destroy multi-touch tracker");
+
+    finishTracking();
+}
diff --git a/tizen/src/ui/input/multitouchtracker.h b/tizen/src/ui/input/multitouchtracker.h
new file mode 100644 (file)
index 0000000..1032dac
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#ifndef MULTITOUCHTRACKER_H
+#define MULTITOUCHTRACKER_H
+
+class TouchPoint
+{
+public:
+    TouchPoint();
+    TouchPoint(int id, QPoint hostPos, QPoint guestPos);
+
+    int getID();
+    QPoint getHostPos();
+    QPoint getGuestPos();
+    void updatePos(QPoint hostPos, QPoint guestPos);
+
+private:
+    int id; /* 1 ~ */
+    QPoint hostPos;
+    QPoint guestPos;
+};
+
+class MultiTouchTracker
+{
+public:
+    MultiTouchTracker(int maxTouchPoint);
+    ~MultiTouchTracker();
+
+    int getMaxTouchPoint();
+    int addTouchPoint(QPoint hostPos, QPoint guestPos);
+    TouchPoint *searchTouchPoint(QPoint targetPos);
+    TouchPoint *searchTouchPoint(int targetID);
+    void touchProcessingSepa(QPoint hostPos, QPoint guestPos);
+    void touchProcessingPara(QPoint hostPos, QPoint guestPos);
+    void touchProcessingSymm(QPoint hostPos, QPoint guestPos);
+    void touchReleasing();
+    void finishTracking();
+
+private:
+    int maxTouchPoint;
+    int pointRadius;
+    TouchPoint *grabTouchPoint;
+    QList<TouchPoint *> touchPointList;
+};
+
+#endif // MULTITOUCHTRACKER_H
index cd11e1f..3649eaf 100644 (file)
  */
 
 #include <QWidget>
+#include <QMouseEvent>
 
 #include "touchscreenhelper.h"
 
 extern "C" {
 #include "emul_state.h"
-#include "skin/maruskin_operation.h"
 
 void virtio_touchscreen_event(int x, int y, int z, int buttons_state);
 }
 
 TouchScreenHelper::TouchScreenHelper()
 {
-    /* do nothing */
+    this->mtTracker = new MultiTouchTracker(get_emul_max_touch_point());
 }
 
 void TouchScreenHelper::mousePressed(QMouseEvent *event, QPoint guestPos)
 {
-    // TODO: multi-touch
+    /* multi-touch processing */
+    if (get_multi_touch_enable() == 1) {
+        mtTracker->touchProcessingSepa(QPoint(event->x(), event->y()), guestPos);
+        return;
+    } else if (get_multi_touch_enable() == 2) {
+        mtTracker->touchProcessingPara(QPoint(event->x(), event->y()), guestPos);
+        return;
+    } else if (get_multi_touch_enable() == 3) {
+        mtTracker->touchProcessingSymm(QPoint(event->x(), event->y()), guestPos);
+        return;
+    }
 
     virtio_touchscreen_event(guestPos.x(), guestPos.y(), 0, 1);
 }
 
 void TouchScreenHelper::mouseReleased(QMouseEvent *event, QPoint guestPos)
 {
-    // TODO: multi-touch
+    if (get_multi_touch_enable() != 0) {
+        mtTracker->touchReleasing();
+        return;
+    }
 
     virtio_touchscreen_event(guestPos.x(), guestPos.y(), 0, 0);
 }
 
 void TouchScreenHelper::mouseMoved(QMouseEvent *event, QPoint guestPos)
 {
-    // TODO: multi-touch
+    /* multi-touch processing */
+    if (get_multi_touch_enable() == 1) {
+        mtTracker->touchProcessingSepa(QPoint(event->x(), event->y()), guestPos);
+        return;
+    } else if (get_multi_touch_enable() == 2) {
+        mtTracker->touchProcessingPara(QPoint(event->x(), event->y()), guestPos);
+        return;
+    } else if (get_multi_touch_enable() == 3) {
+        mtTracker->touchProcessingSymm(QPoint(event->x(), event->y()), guestPos);
+        return;
+    }
 
     virtio_touchscreen_event(guestPos.x(), guestPos.y(), 0, 1);
 }
 
+void TouchScreenHelper::finishMtTracking()
+{
+    mtTracker->finishTracking();
+}
+
 TouchScreenHelper::~TouchScreenHelper()
 {
     qDebug("destroy touch screen helper");
+
+    if (mtTracker != NULL) {
+        delete mtTracker;
+        mtTracker = NULL;
+    }
 }
index 90745a2..ff62907 100644 (file)
@@ -30,6 +30,8 @@
 #ifndef TOUCHSCREENHELPER_H
 #define TOUCHSCREENHELPER_H
 
+#include "multitouchtracker.h"
+
 class TouchScreenHelper
 {
 public:
@@ -40,7 +42,10 @@ public:
     void mouseReleased(QMouseEvent *event, QPoint guestPos);
     void mouseMoved(QMouseEvent *event, QPoint guestPos);
 
+    void finishMtTracking();
+
 private:
+    MultiTouchTracker *mtTracker;
 };
 
 #endif // TOUCHSCREENHELPER_H
index c7d55fa..3b6b612 100644 (file)
@@ -217,6 +217,11 @@ ContextMenu *MainWindow::getPopupMenu()
     return popupMenu;
 }
 
+DisplayBase *MainWindow::getDisplay()
+{
+    return display;
+}
+
 DockingController *MainWindow::getDockingCon()
 {
     return getUIState()->conState.dockingCon;
index 8661f59..7c982d2 100644 (file)
@@ -76,8 +76,10 @@ public:
 
     UIState *getUIState(void);
     ContextMenu *getPopupMenu();
+    DisplayBase *getDisplay();
     KeyboardShortcut *getKeyboardShortcut();
     QLabel *getScreenWidget();
+
     void switchForm(int angle);
     void scaleForm(int scale);
     void capture(void);
index 7b6806f..872ac66 100644 (file)
@@ -48,7 +48,7 @@ SkinView::SkinView(QGraphicsScene *scene, QWidget *parent) :
 
     update();
 
-    kbd = new KeyboardHelper();
+    kbd = new KeyboardHelper(this);
 }
 
 void SkinView::createItems(MainForm *form)