touch: added maru_finger_processing_3 function on maru_shm
authorGiWoong Kim <giwoong.kim@samsung.com>
Thu, 1 Jan 2015 09:06:16 +0000 (18:06 +0900)
committerGiWoong Kim <giwoong.kim@samsung.com>
Thu, 1 Jan 2015 09:11:40 +0000 (18:11 +0900)
support symmetric multi-touch (Ctrl + Alt + Click)module: title

Change-Id: Id2a0a47fb220a43ae9efac5d2eac911a0ea6745c
Signed-off-by: GiWoong Kim <giwoong.kim@samsung.com>
tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorFingers.java
tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorShmSkin.java

index 8b2c43bf9a3edd1bf8ebe1c9694722bd92be6194..0ad8b1fd085bcb963aa3d6590ae12562d17aa2c3 100644 (file)
@@ -80,7 +80,7 @@ public class EmulatorFingers {
                initMultiTouchState(maximum, palette);
        }
 
-       /* one finger */
+       /* a finger */
        static class FingerPoint {
                private int id;
                private int originX;
@@ -102,6 +102,30 @@ public class EmulatorFingers {
                        this.x = x;
                        this.y = y;
                }
+       };
+
+       public int removeFingerPointFromSlot(int index) {
+               grabFingerID = 0;
+
+               FingerPoint finger = getFingerPointFromSlot(index);
+               if (finger != null) {
+                       logger.info("id " + finger.id + " finger releasing");
+
+                       if (finger.id > 0) {
+                               MouseEventData mouseEventData = new MouseEventData(
+                                               MouseButtonType.LEFT.value(), MouseEventType.RELEASE.value(),
+                                               0, 0, finger.x, finger.y, finger.id - 1);
+                               communicator.sendToQEMU(
+                                               SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
+                       }
+
+                       finger.id = 0;
+                       finger.originX = finger.originY = finger.x = finger.y = -1;
+
+                       fingerCnt--;
+               }
+
+               return fingerCnt;
        }
 
        public FingerPoint getFingerPointFromSlot(int index) {
@@ -113,20 +137,19 @@ public class EmulatorFingers {
        }
 
        public FingerPoint getFingerPointSearch(int x, int y) {
-               FingerPoint fingerPoint = null;
+               FingerPoint finger = null;
                int fingerRegion = fingerPointSize + 2;
                //logger.info("x: "+x+ "y: "+ y + " fingerRegion: " + fingerRegion);
 
                for (int i = fingerCnt - 1; i >= 0; i--) {
-                       fingerPoint = getFingerPointFromSlot(i);
-
-                       if (fingerPoint != null) {
-                               if (x >= (fingerPoint.x - fingerRegion) &&
-                                               x < (fingerPoint.x + fingerRegion) &&
-                                               y >= (fingerPoint.y - fingerRegion) &&
-                                               y < (fingerPoint.y + fingerRegion)) {
-                                       //logger.info("return finger point:" + fingerPoint);
-                                       return fingerPoint;
+                       finger = getFingerPointFromSlot(i);
+
+                       if (finger != null) {
+                               if (x >= (finger.x - fingerRegion) &&
+                                               x < (finger.x + fingerRegion) &&
+                                               y >= (finger.y - fingerRegion) &&
+                                               y < (finger.y + fingerRegion)) {
+                                       return finger;
                                }
                        }
                }
@@ -175,14 +198,18 @@ public class EmulatorFingers {
                pointColor.dispose();
        }
 
-       public void setMultiTouchEnable(int value) {
-               multiTouchEnable = value;
+       public void setMultiTouchEnable(int mode) {
+               multiTouchEnable = mode;
        }
 
        public int getMultiTouchEnable() {
                return multiTouchEnable;
        }
 
+       public int getFingerCnt() {
+               return fingerCnt;
+       }
+
        protected int addFingerPoint(int originX, int originY, int x, int y) {
                if (fingerCnt == getMaxTouchPoint()) {
                        logger.warning("support multi-touch up to "
@@ -198,7 +225,7 @@ public class EmulatorFingers {
                FingerPointList.get(fingerCnt - 1).x = x;
                FingerPointList.get(fingerCnt - 1).y = y;
 
-               logger.info(fingerCnt + " finger touching");
+               logger.info("id " + fingerCnt + " finger touching");
 
                return fingerCnt;
        }
@@ -237,8 +264,8 @@ public class EmulatorFingers {
                                        finger.y = y;
 
                                        if (finger.id != 0) {
-                                               logger.info("id " + grabFingerID + " finger multi-touch dragging : ("
-                                                               + x + ", " + y + ")");
+                                               /* logger.info("id " + grabFingerID +
+                                                               " finger multi-touch dragging : (" + x + ", " + y + ")"); */
 
                                                mouseEventData = new MouseEventData(
                                                                MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
@@ -253,6 +280,8 @@ public class EmulatorFingers {
 
                        if (fingerCnt == 0)
                        { /* first finger touch input */
+                               logger.info("multi-touch mode 1 processing");
+
                                if (addFingerPoint(originX, originY, x, y) == -1) {
                                        return;
                                }
@@ -271,39 +300,46 @@ public class EmulatorFingers {
                        }
                        else if (fingerCnt == getMaxTouchPoint())
                        { /* Let's assume that this event is last finger touch input */
-                               finger = getFingerPointFromSlot(getMaxTouchPoint() - 1);
+                               finger = getFingerPointFromSlot(fingerCnt - 1);
                                if (finger != null) {
+                                       /* send release event */
                                mouseEventData = new MouseEventData(
                                                        MouseButtonType.LEFT.value(), MouseEventType.RELEASE.value(),
-                                                       originX, originY, finger.x, finger.y, getMaxTouchPoint() - 1);
+                                                       originX, originY, finger.x, finger.y, fingerCnt - 1);
                                        communicator.sendToQEMU(
                                                        SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
 
+                                       /* update position */
                                        finger.originX = originX;
                                        finger.originY = originY;
                                        finger.x = x;
                                        finger.y = y;
 
                                        if (finger.id != 0) {
+                                               logger.info("id " + finger.id + " finger touching");
                                                mouseEventData = new MouseEventData(
                                                                MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
-                                                               originX, originY, x, y, getMaxTouchPoint() - 1);
+                                                               originX, originY, x, y, fingerCnt - 1);
                                                communicator.sendToQEMU(
                                                                SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
                                        }
                                }
                        }
-                       else
-                       { /* one more finger */
-                               addFingerPoint(originX, originY, x, y);
+                       else /* one more finger */
+                       {
+                               if (addFingerPoint(originX, originY, x, y) == -1) {
+                                       return;
+                               }
+
                                mouseEventData = new MouseEventData(
                                                MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
                                                originX, originY, x, y, fingerCnt - 1);
                                communicator.sendToQEMU(
                                                SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
                        }
+
                } else if (touchType == MouseEventType.RELEASE.value()) { /* released */
-                       logger.info("mouse up for multi touch");
+                       //logger.info("mouse up for multi touch");
                        grabFingerID = 0;
                }
        }
@@ -318,26 +354,26 @@ public class EmulatorFingers {
                        if (grabFingerID > 0) {
                                finger = getFingerPointFromSlot(grabFingerID - 1);
                                if (finger != null) {
-                                       int originDistanceX = originX - finger.originX;
-                                       int originDistanceY = originY - finger.originY;
-                                       int distanceX = x - finger.x;
-                                       int distanceY = y - finger.y;
-
-                                       int currrntScreenW = currentState.getCurrentResolutionWidth();
-                                       int currrntScreenH = currentState.getCurrentResolutionHeight();
-                                       int tempFingerX = 0, tempFingerY = 0;
+                                       final int originDistanceX = originX - finger.originX;
+                                       final int originDistanceY = originY - finger.originY;
+                                       final int distanceX = x - finger.x;
+                                       final int distanceY = y - finger.y;
 
                                        int i = 0;
 
-                                       /* bounds checking */                                             
+                                       /* bounds checking */
+                                       final int currrntScreenW = currentState.getCurrentResolutionWidth();
+                                       final int currrntScreenH = currentState.getCurrentResolutionHeight();
+                                       int tempFingerX = 0, tempFingerY = 0;
+
                                        for (i = 0; i < fingerCnt; i++) {
                                                finger = getFingerPointFromSlot(i);
                                                if (finger != null) {
                                                        tempFingerX = finger.x + distanceX;
                                                        tempFingerY = finger.y + distanceY;
 
-                                                       if (tempFingerX > currrntScreenW || tempFingerX < 0 ||
-                                                                       tempFingerY > currrntScreenH || tempFingerY < 0) {
+                                                       if (tempFingerX >= currrntScreenW || tempFingerX < 0 ||
+                                                                       tempFingerY >= currrntScreenH || tempFingerY < 0) {
                                                                logger.info("id " + (i + 1) + " finger is out of bounds : ("
                                                                        + tempFingerX + ", " + tempFingerY + ")");
 
@@ -346,6 +382,7 @@ public class EmulatorFingers {
                                                }
                                        }
 
+                                       /* move */
                                        for (i = 0; i < fingerCnt; i++) {
                                                finger = getFingerPointFromSlot(i);
                                                if (finger != null) {
@@ -357,17 +394,17 @@ public class EmulatorFingers {
                                                        if (finger.id != 0) {
                                                                mouseEventData = new MouseEventData(
                                                                                MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
-                                                                               originX, originY, finger.x, finger.y, i);
+                                                                               finger.originX, finger.originY, finger.x, finger.y, i);
                                                                communicator.sendToQEMU(
                                                                                SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
 
                                                                /* logger.info(String.format(
                                                                                "id %d finger multi-touch dragging = (%d, %d)",
-                                                                               i + 1, finger.x, finger.y));*/
+                                                                               i + 1, finger.x, finger.y)); */
                                                        }
 
                                                        try {
-                                                               Thread.sleep(2);
+                                                               Thread.sleep(1);
                                                        } catch (InterruptedException e) {
                                                                e.printStackTrace();
                                                        }
@@ -380,6 +417,8 @@ public class EmulatorFingers {
 
                        if (fingerCnt == 0)
                        { /* first finger touch input */
+                               logger.info("multi-touch mode 2 processing");
+
                                if (addFingerPoint(originX, originY, x, y) == -1) {
                                        return;
                                }
@@ -397,20 +436,162 @@ public class EmulatorFingers {
                                logger.info("id " + grabFingerID + " finger is grabbed");
                        }
                        else if (fingerCnt == getMaxTouchPoint())
-                       {  /* Let's assume that this event is last finger touch input */
+                       {
                                /* do nothing */
+                               return;
+                       }
+                       else /* one more finger */
+                       {
+                               if (addFingerPoint(originX, originY, x, y) == -1) {
+                                       return;
+                               }
+
+                               mouseEventData = new MouseEventData(
+                                               MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
+                                               originX, originY, x, y, fingerCnt - 1);
+                               communicator.sendToQEMU(
+                                               SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
+                       }
+
+               } else if (touchType == MouseEventType.RELEASE.value()) { /* released */
+                       //logger.info("mouse up for multi touch");
+                       grabFingerID = 0;
+               }
+       }
+
+       public void maruFingerProcessing3(
+                       int touchType, int originX, int originY, int x, int y) {
+               FingerPoint finger = null;
+               MouseEventData mouseEventData = null;
+
+               if (touchType == MouseEventType.PRESS.value() ||
+                               touchType == MouseEventType.DRAG.value()) { /* pressed */
+                       if (grabFingerID > 0) {
+                               finger = getFingerPointFromSlot(grabFingerID - 1);
+                               if (finger != null) {
+                                       final int originDistanceX = originX - finger.originX;
+                                       final int originDistanceY = originY - finger.originY;
+                                       final int distanceX = x - finger.x;
+                                       final int distanceY = y - finger.y;
+
+                                       /* move */
+                                       finger.originX += originDistanceX;
+                                       finger.originY += originDistanceY;
+                                       finger.x += distanceX;
+                                       finger.y += distanceY;
+                                       if (finger.id != 0) {
+                                               mouseEventData = new MouseEventData(
+                                                               MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
+                                                               finger.originX, finger.originY, finger.x, finger.y, finger.id - 1);
+                                               communicator.sendToQEMU(
+                                                               SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
+
+                                               /* logger.info(String.format(
+                                                               "id %d finger multi-touch dragging = (%d, %d)",
+                                                               i + 1, finger.x, finger.y)); */
+                                       }
+
+                                       if (fingerCnt > 1) {
+                                               FingerPoint coFinger = getFingerPointFromSlot(
+                                                               (grabFingerID == 2) ? 0 : 1);
+                                               if (coFinger != null) {
+                                                       /* bounds checking */
+                                                       final int currrntScreenW = currentState.getCurrentResolutionWidth();
+                                                       final int currrntScreenH = currentState.getCurrentResolutionHeight();
+
+                                                       if (coFinger.x - distanceX >= currrntScreenW ||
+                                                                       coFinger.x - distanceX < 0 ||
+                                                                       coFinger.y - distanceY >= currrntScreenH ||
+                                                                       coFinger.y - distanceY < 0) {
+                                                               logger.info("id " + coFinger.id + " finger is out of bounds : ("
+                                                                       + (coFinger.x - distanceX) + ", " + (coFinger.y - distanceY) + ")");
+                                                               return;
+                                                       }
+
+                                                       /* move */
+                                                       coFinger.originX -= originDistanceX;
+                                                       coFinger.originY -= originDistanceY;
+                                                       coFinger.x -= distanceX;
+                                                       coFinger.y -= distanceY;
+                                                       if (coFinger.id != 0) {
+                                                               mouseEventData = new MouseEventData(
+                                                                               MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
+                                                                               coFinger.originX, coFinger.originY,
+                                                                               coFinger.x, coFinger.y, coFinger.id - 1);
+                                                               communicator.sendToQEMU(
+                                                                               SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               return;
+                       }
+
+                       if (fingerCnt == 0)
+                       { /* first finger touch input */
+                               logger.info("multi-touch mode 3 processing");
+
+                               if (addFingerPoint(originX, originY, x, y) == -1) {
+                                       return;
+                               }
+
+                               mouseEventData = new MouseEventData(
+                                               MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
+                                               originX, originY, x, y, 0);
+                               communicator.sendToQEMU(
+                                               SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
+                       }
+                       else if ((finger = getFingerPointSearch(x, y)) != null)
+                       { /* check the position of previous touch event */
+                               /* finger point is selected */
+                               grabFingerID = finger.id;
+                               logger.info("id " + grabFingerID + " finger is grabbed");
+                       }
+                       else if (fingerCnt >= 2) /* supports up to 2 fingers */
+                       { /* Let's assume that this event is last finger touch input */
+                               finger = getFingerPointFromSlot(1);
+                               if (finger != null) {
+                                       /* send release event */
+                                       mouseEventData = new MouseEventData(
+                                                       MouseButtonType.LEFT.value(), MouseEventType.RELEASE.value(),
+                                                       originX, originY, finger.x, finger.y, 1);
+                                       communicator.sendToQEMU(
+                                                       SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
+
+                                       /* update position */
+                                       finger.originX = originX;
+                                       finger.originY = originY;
+                                       finger.x = x;
+                                       finger.y = y;
+
+                                       if (finger.id != 0) {
+                                               logger.info("id " + finger.id + " finger touching");
+                                               mouseEventData = new MouseEventData(
+                                                               MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
+                                                               originX, originY, x, y, 1);
+                                               communicator.sendToQEMU(
+                                                               SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
+                                       }
+                               }
                        }
                        else /* one more finger */
                        {
-                               addFingerPoint(originX, originY, x, y);
+                               if (addFingerPoint(originX, originY, x, y) == -1) {
+                                       return;
+                               }
+
                                mouseEventData = new MouseEventData(
                                                MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
                                                originX, originY, x, y, fingerCnt - 1);
                                communicator.sendToQEMU(
                                                SendCommand.SEND_MOUSE_EVENT, mouseEventData, false);
                        }
+
                } else if (touchType == MouseEventType.RELEASE.value()) { /* released */
-                       logger.info("mouse up for multi touch");
+                       if (grabFingerID != 0) {
+                               logger.info("id " + grabFingerID + " finger releasing");
+                       }
                        grabFingerID = 0;
                }
        }
index 88b29e2b4927af579f6758310dd5263c8ab0e15f..b43ae81975a13553b3c7a52addf5c5ca500b4815 100644 (file)
@@ -102,9 +102,10 @@ public class EmulatorShmSkin extends EmulatorSkin {
        private Image imageCover;
 
        private int maxTouchPoint;
-       private EmulatorFingers finger;
+       private EmulatorFingers fingers;
        private int multiTouchKey;
-       private int multiTouchKeySub;
+       private int multiTouchKeySub1;
+       private int multiTouchKeySub2;
 
        class BufferPainter extends Thread {
                private Display display;
@@ -235,7 +236,7 @@ public class EmulatorShmSkin extends EmulatorSkin {
                bufferPainter.stopRequest();
 
                /* remove multi-touch finger points */
-               finger.cleanupMultiTouchState();
+               fingers.cleanupMultiTouchState();
 
                super.skinFinalize();
        }
@@ -244,15 +245,17 @@ public class EmulatorShmSkin extends EmulatorSkin {
        public StartData initSkin() {
                initLayout();
 
-               finger = new EmulatorFingers(maxTouchPoint,
+               fingers = new EmulatorFingers(maxTouchPoint,
                                currentState, communicator, palette);
 
+               /* multi-touch toggle key */
                if (SwtUtil.isMacPlatform() == true) {
                        multiTouchKey = SWT.COMMAND;
                } else {
                        multiTouchKey = SWT.CTRL;
                }
-               multiTouchKeySub = SWT.SHIFT;
+               multiTouchKeySub1 = SWT.SHIFT;
+               multiTouchKeySub2 = SWT.ALT;
 
                initDisplay();
 
@@ -374,9 +377,9 @@ public class EmulatorShmSkin extends EmulatorSkin {
                                        break;
                                }
 
-                               if (finger != null && finger.getMultiTouchEnable() != 0) {
+                               if (fingers != null && fingers.getMultiTouchEnable() != 0) {
                                        /* draw points for multi-touch */
-                                       finger.drawFingerPoints(e.gc);
+                                       fingers.drawFingerPoints(e.gc);
                                }
                        }
                });
@@ -397,8 +400,8 @@ public class EmulatorShmSkin extends EmulatorSkin {
        public void setSuitableTransform() {
                super.setSuitableTransform();
 
-               if (finger != null) {
-                       finger.rearrangeFingerPoints(
+               if (fingers != null) {
+                       fingers.rearrangeFingerPoints(
                                        currentState.getCurrentResolutionWidth(),
                                        currentState.getCurrentResolutionHeight(),
                                        currentState.getCurrentScale(),
@@ -469,15 +472,24 @@ public class EmulatorShmSkin extends EmulatorSkin {
                                currentState.getCurrentScale(),
                                currentState.getCurrentRotationId());
 
-               //eventType = MouseEventType.DRAG.value();
-               if (finger.getMultiTouchEnable() == 1) {
-                       finger.maruFingerProcessing1(eventType,
+               /* multi-touch */
+               if (fingers.getMultiTouchEnable() == 1) {
+                       /* Ctrl or Shift */
+                       fingers.maruFingerProcessing1(eventType,
                                        e.x, e.y, geometry[0], geometry[1]);
 
                        displayCanvas.redraw();
                        return;
-               } else if (finger.getMultiTouchEnable() == 2) {
-                       finger.maruFingerProcessing2(eventType,
+               } else if (fingers.getMultiTouchEnable() == 2) {
+                       /* Ctrl + Shift */
+                       fingers.maruFingerProcessing2(eventType,
+                                       e.x, e.y, geometry[0], geometry[1]);
+
+                       displayCanvas.redraw();
+                       return;
+               } else if (fingers.getMultiTouchEnable() == 3) {
+                       /* Ctrl + Alt */
+                       fingers.maruFingerProcessing3(eventType,
                                        e.x, e.y, geometry[0], geometry[1]);
 
                        displayCanvas.redraw();
@@ -505,16 +517,20 @@ public class EmulatorShmSkin extends EmulatorSkin {
                pressingX = pressingY = -1;
                pressingOriginX = pressingOriginY = -1;
 
-               if (finger.getMultiTouchEnable() == 1) {
-                       logger.info("maruFingerProcessing 1");
-                       finger.maruFingerProcessing1(MouseEventType.RELEASE.value(),
+               if (fingers.getMultiTouchEnable() == 1) {
+                       fingers.maruFingerProcessing1(MouseEventType.RELEASE.value(),
+                                       e.x, e.y, geometry[0], geometry[1]);
+
+                       displayCanvas.redraw();
+                       return;
+               } else if (fingers.getMultiTouchEnable() == 2) {
+                       fingers.maruFingerProcessing2(MouseEventType.RELEASE.value(),
                                        e.x, e.y, geometry[0], geometry[1]);
 
                        displayCanvas.redraw();
                        return;
-               } else if (finger.getMultiTouchEnable() == 2) {
-                       logger.info("maruFingerProcessing 2");
-                       finger.maruFingerProcessing2(MouseEventType.RELEASE.value(),
+               } else if (fingers.getMultiTouchEnable() == 3) {
+                       fingers.maruFingerProcessing3(MouseEventType.RELEASE.value(),
                                        e.x, e.y, geometry[0], geometry[1]);
 
                        displayCanvas.redraw();
@@ -544,16 +560,20 @@ public class EmulatorShmSkin extends EmulatorSkin {
                pressingOriginX = e.x;
                pressingOriginY = e.y;
 
-               if (finger.getMultiTouchEnable() == 1) {
-                       logger.info("maruFingerProcessing 1");
-                       finger.maruFingerProcessing1(MouseEventType.PRESS.value(),
+               if (fingers.getMultiTouchEnable() == 1) {
+                       fingers.maruFingerProcessing1(MouseEventType.PRESS.value(),
                                        e.x, e.y, geometry[0], geometry[1]);
 
                        displayCanvas.redraw();
                        return;
-               } else if (finger.getMultiTouchEnable() == 2) {
-                       logger.info("maruFingerProcessing 2");
-                       finger.maruFingerProcessing2(MouseEventType.PRESS.value(),
+               } else if (fingers.getMultiTouchEnable() == 2) {
+                       fingers.maruFingerProcessing2(MouseEventType.PRESS.value(),
+                                       e.x, e.y, geometry[0], geometry[1]);
+
+                       displayCanvas.redraw();
+                       return;
+               } else if (fingers.getMultiTouchEnable() == 3) {
+                       fingers.maruFingerProcessing3(MouseEventType.PRESS.value(),
                                        e.x, e.y, geometry[0], geometry[1]);
 
                        displayCanvas.redraw();
@@ -572,21 +592,30 @@ public class EmulatorShmSkin extends EmulatorSkin {
        @Override
        protected void keyReleasedDelivery(int keyCode,
                        int stateMask, int keyLocation, boolean remove) {
-               if (finger.getMaxTouchPoint() > 1) {
-                       /* check multi-touch */
-                       if (keyCode == multiTouchKeySub || keyCode == multiTouchKey) {
-                               int tempStateMask = stateMask & ~SWT.BUTTON1;
-
-                               if (tempStateMask == (multiTouchKeySub | multiTouchKey)) {
-                                       finger.setMultiTouchEnable(1);
-
-                                       logger.info("enable multi-touch = mode 1");
+               if (fingers.getMaxTouchPoint() > 1) {
+                       final int tempStateMask = stateMask & ~SWT.BUTTON1;
+
+                       /* multi-touch checking */
+                       if (keyCode == multiTouchKey || keyCode == multiTouchKeySub1) {
+                               if (tempStateMask == (multiTouchKeySub1 | multiTouchKey)) {
+                                       fingers.setMultiTouchEnable(1);
+                                       logger.info("enable multi-touch mode 2->1");
                                } else {
-                                       finger.clearFingerSlot(false);
-                                       updateDisplay();
+                                       fingers.clearFingerSlot(false);
+                                       logger.info("disable multi-touch");
+                               }
 
+                               updateDisplay();
+                       } else if (keyCode == multiTouchKeySub2) {
+                               if (tempStateMask == (multiTouchKey | multiTouchKeySub2)) {
+                                       fingers.setMultiTouchEnable(1);
+                                       logger.info("enable multi-touch mode 3->1");
+                               } else {
+                                       fingers.clearFingerSlot(false);
                                        logger.info("disable multi-touch");
                                }
+
+                               updateDisplay();
                        }
                }
 
@@ -603,42 +632,69 @@ public class EmulatorShmSkin extends EmulatorSkin {
        @Override
        protected void keyPressedDelivery(int keyCode,
                        int stateMask, int keyLocation, boolean add) {
-               if (finger.getMaxTouchPoint() > 1) {
+               if (fingers.getMaxTouchPoint() > 1) {
                    /* multi-touch checking */
-                       int tempStateMask = stateMask & ~SWT.BUTTON1;
+                       final int tempStateMask = stateMask & ~SWT.BUTTON1;
+
+                       if ((keyCode == multiTouchKey && tempStateMask == multiTouchKeySub2) ||
+                                       (keyCode == multiTouchKeySub2 && tempStateMask == multiTouchKey))
+                       {
+                               /* multi-touch mode 3 supports up to 2 fingers */
+                               int i = fingers.getFingerCnt();
+                               for ( ; i > 2; i--) {
+                                       fingers.removeFingerPointFromSlot(i - 1);
+                               }
+                               updateDisplay();
 
-                       if ((keyCode == multiTouchKeySub && (tempStateMask & multiTouchKey) != 0) ||
-                                       (keyCode == multiTouchKey && (tempStateMask & multiTouchKeySub) != 0))
+                               fingers.setMultiTouchEnable(3);
+
+                               logger.info("enable multi-touch mode 3");
+                       }
+                       else if ((keyCode == multiTouchKey && tempStateMask == multiTouchKeySub1) ||
+                                       (keyCode == multiTouchKeySub1 && tempStateMask == multiTouchKey))
                        {
-                               finger.setMultiTouchEnable(2);
+                               fingers.setMultiTouchEnable(2);
 
-                               /* add a finger before start the multi-touch processing
-                               if already exist the pressed touch in display */
-                               if (pressingX != -1 && pressingY != -1 &&
+                               /* Before the Emulator starts multi-touch processing,
+                                * add a first finger if user just switches on to the multi-touch mode
+                                * while display dragging. */
+                               if (fingers.getFingerCnt() == 0 && pressingX != -1 && pressingY != -1 &&
                                                pressingOriginX != -1 && pressingOriginY != -1) {
-                                       finger.addFingerPoint(
+                                       fingers.addFingerPoint(
                                                        pressingOriginX, pressingOriginY,
                                                        pressingX, pressingY);
                                        pressingX = pressingY = -1;
                                        pressingOriginX = pressingOriginY = -1;
+
+                                       updateDisplay();
                                }
 
-                               logger.info("enable multi-touch mode 2");
-                       } else if (keyCode == multiTouchKeySub || keyCode == multiTouchKey) {
-                               finger.setMultiTouchEnable(1);
+                               logger.info("enable multi-touch mode 2");
+                       } else if (keyCode == multiTouchKeySub1 || keyCode == multiTouchKey) {
+                               fingers.setMultiTouchEnable(1);
 
-                               /* add a finger before start the multi-touch processing
-                               if already exist the pressed touch in display */
-                               if (pressingX != -1 && pressingY != -1 &&
+                               /* Before the Emulator starts multi-touch processing,
+                                * add a first finger if user just switches on to the multi-touch mode
+                                * while display dragging. */
+                               if (fingers.getFingerCnt() == 0 && pressingX != -1 && pressingY != -1 &&
                                                pressingOriginX != -1 && pressingOriginY != -1) {
-                                       finger.addFingerPoint(
+                                       fingers.addFingerPoint(
                                                        pressingOriginX, pressingOriginY,
                                                        pressingX, pressingY);
                                        pressingX = pressingY = -1;
                                        pressingOriginX = pressingOriginY = -1;
+
+                                       updateDisplay();
                                }
 
-                               logger.info("enable multi-touch = mode 1");
+                               logger.info("enable multi-touch mode 1");
+                       } else {
+                               if (fingers.getMultiTouchEnable() != 0) {
+                                       fingers.clearFingerSlot(false);
+                                       logger.info("disable multi-touch");
+
+                                       updateDisplay();
+                               }
                        }
                }