4 * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
7 * Munkyu Im <munkyu.im@samsung.com>
8 * GiWoong Kim <giwoong.kim@samsung.com>
9 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 package org.tizen.emulator.skin;
32 import java.util.ArrayList;
33 import java.util.logging.Logger;
35 import org.eclipse.swt.events.PaintEvent;
36 import org.eclipse.swt.graphics.Color;
37 import org.eclipse.swt.graphics.GC;
38 import org.eclipse.swt.graphics.Image;
39 import org.eclipse.swt.graphics.ImageData;
40 import org.eclipse.swt.graphics.PaletteData;
41 import org.eclipse.swt.widgets.Display;
42 import org.tizen.emulator.skin.comm.ICommunicator.MouseButtonType;
43 import org.tizen.emulator.skin.comm.ICommunicator.MouseEventType;
44 import org.tizen.emulator.skin.comm.ICommunicator.RotationInfo;
45 import org.tizen.emulator.skin.comm.ICommunicator.SendCommand;
46 import org.tizen.emulator.skin.comm.sock.SocketCommunicator;
47 import org.tizen.emulator.skin.comm.sock.data.MouseEventData;
48 import org.tizen.emulator.skin.log.SkinLogger;
50 public class EmulatorFingers {
51 private static final int MAX_FINGER_CNT = 10;
52 private static final int RED_MASK = 0x0000FF00;
53 private static final int GREEN_MASK = 0x00FF0000;
54 private static final int BLUE_MASK = 0xFF000000;
55 private static final int COLOR_DEPTH = 32;
56 private Logger logger = SkinLogger.getSkinLogger( EmulatorFingers.class ).getLogger();
57 private int multiTouchEnable;
58 private int maxTouchPoint;
59 protected int fingerCnt;
60 private int fingerCntMax;
61 protected int fingerPointSize;
62 protected int fingerPointSizeHalf;
63 private Color fingerPointColor;
64 private Color fingerPointOutlineColor;
65 private int grabFingerID = 0;
66 protected Image fingerSlotimage;
67 protected ImageData imageData;
68 protected FingerPoint fingerSlot;
69 protected SocketCommunicator communicator;
70 protected EmulatorSkin emulatorSkin;
71 ArrayList<FingerPoint> FingerPointList;
73 EmulatorSkinState currentState;
75 EmulatorFingers(EmulatorSkinState currentState) {
76 this.currentState = currentState;
77 initMultiTouchState();
80 protected void setCommunicator(SocketCommunicator communicator) {
81 this.communicator = communicator;
84 //private fingerPointSurface;
85 protected class FingerPoint {
92 FingerPoint(int originX, int originY, int x, int y) {
93 this.originX = originX;
94 this.originY = -originY;
99 FingerPoint(int id, int originX, int originY, int x, int y) {
101 this.originX = originX;
102 this.originY = -originY;
108 public FingerPoint getFingerPointFromSlot(int index) {
109 if(index < 0 || index > this.fingerCntMax) {
112 return FingerPointList.get(index);
115 public FingerPoint getFingerPointSearch(int x, int y) {
117 FingerPoint fingerPoint = null;
118 int fingerRegion = (this.fingerPointSize ) + 2;
119 //logger.info("x: "+x+ "y: "+ y + " fingerRegion: " + fingerRegion);
120 for(i = this.fingerCnt -1; i >= 0; i--) {
121 fingerPoint = getFingerPointFromSlot(i);
123 if(fingerPoint != null) {
124 if(x >= (fingerPoint.x - fingerRegion) &&
125 x < (fingerPoint.x + fingerRegion) &&
126 y >= (fingerPoint.y - fingerRegion) &&
127 y < (fingerPoint.y + fingerRegion)) {
128 //logger.info("return finger point:" + fingerPoint);
136 protected void setEmulatorSkin(EmulatorSkin emulatorSkin) {
137 this.emulatorSkin = emulatorSkin;
140 public void initMultiTouchState() {
141 this.multiTouchEnable = 0;
142 this.fingerCntMax = this.currentState.getMaxTouchPoint();
143 if(this.fingerCntMax > MAX_FINGER_CNT) {
144 this.fingerCntMax = MAX_FINGER_CNT;
145 setMaxTouchPoint(this.fingerCntMax);
147 logger.info("maxTouchPoint="+ this.fingerCntMax);
150 if (this.fingerSlot != null) {
151 this.fingerSlot = null;
154 FingerPointList = new ArrayList<FingerPoint>();
156 for(i = 0; i <= fingerCntMax; i++) {
157 FingerPointList.add(new FingerPoint(-1, -1, -1, -1));
159 this.fingerPointSize = 32;
160 this.fingerPointSizeHalf = this.fingerPointSize / 2 ;
162 this.fingerPointOutlineColor = new Color(Display.getCurrent(), 0xDD, 0xDD, 0xDD);
163 this.fingerPointColor = new Color(Display.getCurrent(), 0x0F, 0x0F, 0x0F);
164 PaletteData palette = new PaletteData(RED_MASK, GREEN_MASK, BLUE_MASK);
166 this.imageData = new ImageData(fingerPointSize + 4, fingerPointSize + 4, COLOR_DEPTH, palette);
167 this.imageData.transparentPixel = 0;
168 this.fingerSlotimage = new Image(Display.getCurrent(), imageData);
170 GC gc = new GC(this.fingerSlotimage);
172 gc.setForeground(this.fingerPointOutlineColor);
173 gc.drawOval(0, 0, this.fingerPointSize+2 , this.fingerPointSize+2);
175 gc.setBackground(this.fingerPointColor);
176 gc.fillOval(2, 2 , this.fingerPointSize, this.fingerPointSize);
181 public void setMultiTouchEnable(int multiTouchEnable) {
182 this.multiTouchEnable = multiTouchEnable;
185 public int getMultiTouchEnable() {
186 return this.multiTouchEnable;
189 protected int addFingerPoint(int originX, int originY, int x, int y) {
190 if (this.fingerCnt == this.fingerCntMax) {
191 logger.info("support multi-touch up to " + this.fingerCntMax +" fingers");
196 FingerPointList.get(fingerCnt -1).id = this.fingerCnt;
197 FingerPointList.get(fingerCnt -1).originX = originX;
198 FingerPointList.get(fingerCnt -1).originY = originY;
199 FingerPointList.get(fingerCnt -1).x = x;
200 FingerPointList.get(fingerCnt -1).y = y;
201 logger.info(this.fingerCnt + " finger touching");
203 return this.fingerCnt;
207 protected void drawImage(PaintEvent e, int currentAngle) {
209 for(int i=0; i < this.fingerCnt; i++) {
210 this.fingerSlot = this.getFingerPointFromSlot(i);
212 // logger.info("OriginX: "+ this.fingerSlot.originX + ",OriginY: " + (this.fingerSlot.originY));
213 // logger.info("x: "+ this.fingerSlot.x + ",y: " + (this.fingerSlot.y));
215 e.gc.drawImage(this.fingerSlotimage,
216 this.fingerSlot.originX - fingerPointSizeHalf - 2,
217 this.fingerSlot.originY - fingerPointSizeHalf - 2);
222 public void maruFingerProcessing1(int touchType, int originX, int originY, int x, int y) {
223 FingerPoint finger = null;
224 MouseEventData mouseEventData;
225 if (touchType == MouseEventType.PRESS.value() || touchType == MouseEventType.DRAG.value()) { /* pressed */
226 if (grabFingerID > 0) {
227 finger = getFingerPointFromSlot(grabFingerID - 1);
228 if (finger != null) {
229 finger.originX = originX;
230 finger.originY = originY;
233 if (finger.id != 0) {
234 logger.info(String.format("id %d finger multi-touch dragging = (%d, %d)", this.grabFingerID, x, y));
235 mouseEventData = new MouseEventData(
236 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
237 originX, originY, x, y, grabFingerID -1);
238 communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData );
244 if(this.fingerCnt == 0) {
245 //first finger touch input
246 if(addFingerPoint(originX, originY, x, y) == -1) {
250 mouseEventData = new MouseEventData(
251 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
252 originX, originY, x, y, 0);
253 communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData );
255 //check the position of previous touch event
256 else if ((finger = getFingerPointSearch(x, y)) != null) {
257 //finger point is selected
258 this.grabFingerID = finger.id;
259 logger.info(String.format("id %d finger is grabbed\n", this.grabFingerID));
261 //Let's assume that this event is last finger touch input
262 else if (this.fingerCnt == this.fingerCntMax) {
263 finger = getFingerPointFromSlot(this.fingerCntMax -1);
265 mouseEventData = new MouseEventData(
266 MouseButtonType.LEFT.value(), MouseEventType.RELEASE.value(),
267 originX, originY, finger.x, finger.y, this.fingerCntMax -1);
268 communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData );
270 finger.originX = originX;
271 finger.originY = originY;
275 mouseEventData = new MouseEventData(
276 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
277 originX, originY, x, y, this.fingerCntMax -1);
278 communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData );
283 else { //one more finger
284 addFingerPoint(originX, originY, x, y);
285 mouseEventData = new MouseEventData(
286 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
287 originX, originY, x, y, this.fingerCnt -1);
288 communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData );
292 else if (touchType == MouseEventType.RELEASE.value()) { /* released */
293 logger.info("mouse up for multi touch");
294 this.grabFingerID = 0;
299 public void maruFingerProcessing2(int touchType, int originX, int originY, int x, int y) {
300 FingerPoint finger = null;
301 MouseEventData mouseEventData;
302 if (touchType == MouseEventType.PRESS.value() || touchType == MouseEventType.DRAG.value()) { /* pressed */
303 if(this.grabFingerID > 0) {
304 finger = getFingerPointFromSlot(grabFingerID - 1);
306 int originDistanceX = originX - finger.originX;
307 int originDistanceY = originY - finger.originY;
308 int distanceX = x - finger.x;
309 int distanceY = y - finger.y;
311 int currrntScreenW = currentState.getCurrentResolutionWidth();
312 int currrntScreenH = currentState.getCurrentResolutionHeight();
313 int tempFingerX, tempFingerY;
316 /* bounds checking */
317 for(i = 0; i < this.fingerCnt; i++) {
318 finger = getFingerPointFromSlot(i);
319 if (finger != null) {
320 tempFingerX = finger.x + distanceX;
321 tempFingerY = finger.y + distanceY;
322 if (tempFingerX > currrntScreenW || tempFingerX < 0
323 || tempFingerY > currrntScreenH || tempFingerY < 0) {
324 logger.info(String.format("id %d finger is out of bounds (%d, %d)\n", i + 1, tempFingerX, tempFingerY));
330 for(i = 0; i < this.fingerCnt; i++) {
331 finger = getFingerPointFromSlot(i);
333 if (finger != null) {
334 finger.originX += originDistanceX;
335 finger.originY += originDistanceY;
336 finger.x += distanceX;
337 finger.y += distanceY;
338 if (finger.id != 0) {
339 mouseEventData = new MouseEventData(
340 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
341 originX, originY, finger.x, finger.y, i);
342 communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData );
343 //logger.info(String.format("id %d finger multi-touch dragging = (%d, %d)", i + 1, finger.x, finger.y));
347 } catch (InterruptedException e) {
357 if (this.fingerCnt == 0)
358 { //first finger touch input
359 if (this.addFingerPoint(originX, originY, x, y) == -1) {
362 mouseEventData = new MouseEventData(
363 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
364 originX, originY, x, y, 0);
365 communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData );
367 else if((finger = this.getFingerPointSearch(x, y)) != null) //check the position of previous touch event
369 //finger point is selected
370 this.grabFingerID = finger.id;
371 logger.info(String.format("id %d finger is grabbed\n", this.grabFingerID));
374 else if(this.fingerCnt == this.fingerCntMax) //Let's assume that this event is last finger touch input
378 else //one more finger
380 addFingerPoint(originX, originY, x, y);
381 mouseEventData = new MouseEventData(
382 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
383 originX, originY, x, y, this.fingerCnt -1);
384 communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData );
386 }else if (touchType == MouseEventType.RELEASE.value()) { /* released */
387 logger.info("mouse up for multi touch");
388 this.grabFingerID = 0;
393 private Boolean CalculateOriginCoordinates(int ScaledLcdWitdh, int ScaledLcdHeight, double scaleFactor, int rotationType, FingerPoint finger) {
395 int pointX, pointY, rotatedPointX, rotatedPointY, flag;
397 // logger.info("ScaledLcdWitdh:"+ScaledLcdWitdh+" ScaledLcdHeight:"+ScaledLcdHeight+ " scaleFactor:"+ scaleFactor+" rotationType:"+rotationType);
398 rotatedPointX = pointX = (int)(finger.x * scaleFactor);
399 rotatedPointY = pointY = (int)(finger.y * scaleFactor);
400 // logger.info("rotatedPointX:"+rotatedPointX+" rotatedPointY:"+rotatedPointY);
401 if (rotationType == RotationInfo.LANDSCAPE.id()) {
402 rotatedPointX = pointY;
403 rotatedPointY = ScaledLcdWitdh - pointX;
404 } else if (rotationType == RotationInfo.REVERSE_PORTRAIT.id()) {
405 rotatedPointX = ScaledLcdWitdh - pointX;
406 rotatedPointY = ScaledLcdHeight - pointY;
407 } else if (rotationType == RotationInfo.REVERSE_LANDSCAPE.id()) {
408 rotatedPointX = ScaledLcdHeight - pointY;
409 rotatedPointY = pointX;
411 //PORTRAIT: do nothing
415 if (finger.originX != rotatedPointX) {
416 logger.info("finger.originX: " +finger.originX);
417 finger.originX = rotatedPointX;
420 if (finger.originY != rotatedPointY) {
421 logger.info("finger.originY: " +finger.originY);
422 finger.originY = rotatedPointY;
433 public int rearrangeFingerPoints(int lcdWidth, int lcdHeight, double scaleFactor, int rotationType) {
436 FingerPoint finger = null;
438 if (this.multiTouchEnable == 0) {
441 scaleFactor = scaleFactor/100;
442 lcdWidth *= scaleFactor;
443 lcdHeight *= scaleFactor;
445 for (i = 0; i < this.fingerCnt; i++) {
446 finger = getFingerPointFromSlot(i);
447 if (finger != null && finger.id != 0) {
448 if (CalculateOriginCoordinates(lcdWidth, lcdHeight,
449 scaleFactor, rotationType, finger) == true) {
456 this.grabFingerID = 0;
462 public void clearFingerSlot() {
464 FingerPoint finger = null;
465 for(i = 0; i < this.fingerCnt; i++) {
466 finger = getFingerPointFromSlot(i);
467 if(finger != null && finger.id != 0) {
468 logger.info(String.format("clear %d, %d, %d", finger.x, finger.y, finger.id -1));
469 MouseEventData mouseEventData = new MouseEventData(
470 MouseButtonType.LEFT.value(), MouseEventType.RELEASE.value(),
471 0, 0, finger.x, finger.y, finger.id -1);
472 communicator.sendToQEMU( SendCommand.SEND_MOUSE_EVENT, mouseEventData );
475 finger.originX = finger.originY = finger.x = finger.y = -1;
477 this.grabFingerID = 0;
479 logger.info("clear multi touch");
482 public void cleanup_multiTouchState() {
483 this.multiTouchEnable = 0;
485 fingerSlotimage.dispose();
488 public int getMaxTouchPoint() {
489 if(this.maxTouchPoint <= 0 ) {
492 return this.maxTouchPoint;
495 public void setMaxTouchPoint(int cnt) {
499 this.maxTouchPoint = cnt;