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;
57 private Logger logger =
58 SkinLogger.getSkinLogger(EmulatorFingers.class).getLogger();
60 private int multiTouchEnable;
61 private int maxTouchPoint;
62 protected int fingerCnt;
63 private int fingerCntMax;
64 protected int fingerPointSize;
65 protected int fingerPointSizeHalf;
66 private Color fingerPointColor;
67 private Color fingerPointOutlineColor;
68 private int grabFingerID = 0;
69 protected Image fingerSlotimage;
70 protected ImageData imageData;
71 protected FingerPoint fingerSlot;
72 protected SocketCommunicator communicator;
73 protected EmulatorSkin emulatorSkin;
74 ArrayList<FingerPoint> FingerPointList;
76 EmulatorSkinState currentState;
78 EmulatorFingers(EmulatorSkinState currentState) {
79 this.currentState = currentState;
80 initMultiTouchState();
83 protected void setCommunicator(SocketCommunicator communicator) {
84 this.communicator = communicator;
87 //private fingerPointSurface;
88 protected class FingerPoint {
95 FingerPoint(int originX, int originY, int x, int y) {
96 this.originX = originX;
97 this.originY = -originY;
102 FingerPoint(int id, int originX, int originY, int x, int y) {
104 this.originX = originX;
105 this.originY = -originY;
111 public FingerPoint getFingerPointFromSlot(int index) {
112 if (index < 0 || index > this.fingerCntMax) {
116 return FingerPointList.get(index);
119 public FingerPoint getFingerPointSearch(int x, int y) {
121 FingerPoint fingerPoint = null;
122 int fingerRegion = (this.fingerPointSize) + 2;
123 //logger.info("x: "+x+ "y: "+ y + " fingerRegion: " + fingerRegion);
125 for (i = this.fingerCnt - 1; i >= 0; i--) {
126 fingerPoint = getFingerPointFromSlot(i);
128 if (fingerPoint != null) {
129 if (x >= (fingerPoint.x - fingerRegion) &&
130 x < (fingerPoint.x + fingerRegion) &&
131 y >= (fingerPoint.y - fingerRegion) &&
132 y < (fingerPoint.y + fingerRegion)) {
133 //logger.info("return finger point:" + fingerPoint);
142 protected void setEmulatorSkin(EmulatorSkin emulatorSkin) {
143 this.emulatorSkin = emulatorSkin;
146 public void initMultiTouchState() {
147 this.multiTouchEnable = 0;
148 this.fingerCntMax = this.currentState.getMaxTouchPoint();
150 if (this.fingerCntMax > MAX_FINGER_CNT) {
151 this.fingerCntMax = MAX_FINGER_CNT;
152 setMaxTouchPoint(this.fingerCntMax);
155 logger.info("maxTouchPoint="+ this.fingerCntMax);
158 if (this.fingerSlot != null) {
159 this.fingerSlot = null;
162 FingerPointList = new ArrayList<FingerPoint>();
164 for (i = 0; i <= fingerCntMax; i++) {
165 FingerPointList.add(new FingerPoint(-1, -1, -1, -1));
167 this.fingerPointSize = 32;
168 this.fingerPointSizeHalf = this.fingerPointSize / 2;
170 this.fingerPointOutlineColor = new Color(Display.getCurrent(), 0xDD, 0xDD, 0xDD);
171 this.fingerPointColor = new Color(Display.getCurrent(), 0x0F, 0x0F, 0x0F);
172 PaletteData palette = new PaletteData(RED_MASK, GREEN_MASK, BLUE_MASK);
174 this.imageData = new ImageData(
175 fingerPointSize + 4, fingerPointSize + 4, COLOR_DEPTH, palette);
176 this.imageData.transparentPixel = 0;
177 this.fingerSlotimage = new Image(Display.getCurrent(), imageData);
179 GC gc = new GC(this.fingerSlotimage);
181 gc.setForeground(this.fingerPointOutlineColor);
182 gc.drawOval(0, 0, this.fingerPointSize + 2, this.fingerPointSize + 2);
184 gc.setBackground(this.fingerPointColor);
185 gc.fillOval(2, 2, this.fingerPointSize, this.fingerPointSize);
190 public void setMultiTouchEnable(int multiTouchEnable) {
191 this.multiTouchEnable = multiTouchEnable;
194 public int getMultiTouchEnable() {
195 return this.multiTouchEnable;
198 protected int addFingerPoint(int originX, int originY, int x, int y) {
199 if (this.fingerCnt == this.fingerCntMax) {
200 logger.info("support multi-touch up to "
201 + this.fingerCntMax + " fingers");
206 FingerPointList.get(fingerCnt -1).id = this.fingerCnt;
207 FingerPointList.get(fingerCnt -1).originX = originX;
208 FingerPointList.get(fingerCnt -1).originY = originY;
209 FingerPointList.get(fingerCnt -1).x = x;
210 FingerPointList.get(fingerCnt -1).y = y;
211 logger.info(this.fingerCnt + " finger touching");
213 return this.fingerCnt;
216 protected void drawImage(PaintEvent e, int currentAngle) {
218 for (int i = 0; i < this.fingerCnt; i++) {
219 this.fingerSlot = this.getFingerPointFromSlot(i);
221 // logger.info("OriginX: "+ this.fingerSlot.originX + ",OriginY: " + (this.fingerSlot.originY));
222 // logger.info("x: "+ this.fingerSlot.x + ",y: " + (this.fingerSlot.y));
224 e.gc.drawImage(this.fingerSlotimage,
225 this.fingerSlot.originX - fingerPointSizeHalf - 2,
226 this.fingerSlot.originY - fingerPointSizeHalf - 2);
231 public void maruFingerProcessing1(
232 int touchType, int originX, int originY, int x, int y) {
233 FingerPoint finger = null;
234 MouseEventData mouseEventData;
236 if (touchType == MouseEventType.PRESS.value() ||
237 touchType == MouseEventType.DRAG.value()) { /* pressed */
238 if (grabFingerID > 0) {
239 finger = getFingerPointFromSlot(grabFingerID - 1);
240 if (finger != null) {
241 finger.originX = originX;
242 finger.originY = originY;
246 if (finger.id != 0) {
247 logger.info(String.format(
248 "id %d finger multi-touch dragging = (%d, %d)",
249 this.grabFingerID, x, y));
251 mouseEventData = new MouseEventData(
252 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
253 originX, originY, x, y, grabFingerID - 1);
254 communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData);
261 if (this.fingerCnt == 0)
262 { /* first finger touch input */
263 if (addFingerPoint(originX, originY, x, y) == -1) {
267 mouseEventData = new MouseEventData(
268 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
269 originX, originY, x, y, 0);
270 communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData);
272 else if ((finger = getFingerPointSearch(x, y)) != null)
273 { /* check the position of previous touch event */
274 /* finger point is selected */
275 this.grabFingerID = finger.id;
276 logger.info(String.format("id %d finger is grabbed\n", this.grabFingerID));
278 else if (this.fingerCnt == this.fingerCntMax)
279 { /* Let's assume that this event is last finger touch input */
280 finger = getFingerPointFromSlot(this.fingerCntMax - 1);
281 if (finger != null) {
282 mouseEventData = new MouseEventData(
283 MouseButtonType.LEFT.value(), MouseEventType.RELEASE.value(),
284 originX, originY, finger.x, finger.y, this.fingerCntMax - 1);
285 communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData);
287 finger.originX = originX;
288 finger.originY = originY;
292 if (finger.id != 0) {
293 mouseEventData = new MouseEventData(
294 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
295 originX, originY, x, y, this.fingerCntMax - 1);
296 communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData);
301 { /* one more finger */
302 addFingerPoint(originX, originY, x, y);
303 mouseEventData = new MouseEventData(
304 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
305 originX, originY, x, y, this.fingerCnt - 1);
306 communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData);
308 } else if (touchType == MouseEventType.RELEASE.value()) { /* released */
309 logger.info("mouse up for multi touch");
310 this.grabFingerID = 0;
314 public void maruFingerProcessing2(
315 int touchType, int originX, int originY, int x, int y) {
316 FingerPoint finger = null;
317 MouseEventData mouseEventData;
319 if (touchType == MouseEventType.PRESS.value() ||
320 touchType == MouseEventType.DRAG.value()) { /* pressed */
321 if (this.grabFingerID > 0) {
322 finger = getFingerPointFromSlot(grabFingerID - 1);
323 if (finger != null) {
324 int originDistanceX = originX - finger.originX;
325 int originDistanceY = originY - finger.originY;
326 int distanceX = x - finger.x;
327 int distanceY = y - finger.y;
329 int currrntScreenW = currentState.getCurrentResolutionWidth();
330 int currrntScreenH = currentState.getCurrentResolutionHeight();
331 int tempFingerX, tempFingerY;
334 /* bounds checking */
335 for (i = 0; i < this.fingerCnt; i++) {
336 finger = getFingerPointFromSlot(i);
337 if (finger != null) {
338 tempFingerX = finger.x + distanceX;
339 tempFingerY = finger.y + distanceY;
341 if (tempFingerX > currrntScreenW || tempFingerX < 0 ||
342 tempFingerY > currrntScreenH || tempFingerY < 0) {
343 logger.info(String.format(
344 "id %d finger is out of bounds (%d, %d)\n",
345 i + 1, tempFingerX, tempFingerY));
351 for (i = 0; i < this.fingerCnt; i++) {
352 finger = getFingerPointFromSlot(i);
353 if (finger != null) {
354 finger.originX += originDistanceX;
355 finger.originY += originDistanceY;
356 finger.x += distanceX;
357 finger.y += distanceY;
359 if (finger.id != 0) {
360 mouseEventData = new MouseEventData(
361 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
362 originX, originY, finger.x, finger.y, i);
363 communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData);
365 /* logger.info(String.format(
366 "id %d finger multi-touch dragging = (%d, %d)",
367 i + 1, finger.x, finger.y));*/
372 } catch (InterruptedException e) {
382 if (this.fingerCnt == 0)
383 { /* first finger touch input */
384 if (this.addFingerPoint(originX, originY, x, y) == -1) {
388 mouseEventData = new MouseEventData(
389 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
390 originX, originY, x, y, 0);
391 communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData);
393 else if ((finger = this.getFingerPointSearch(x, y)) != null)
394 { /* check the position of previous touch event */
395 /* finger point is selected */
396 this.grabFingerID = finger.id;
397 logger.info(String.format("id %d finger is grabbed\n", this.grabFingerID));
399 else if (this.fingerCnt == this.fingerCntMax)
400 { /* Let's assume that this event is last finger touch input */
403 else /* one more finger */
405 addFingerPoint(originX, originY, x, y);
406 mouseEventData = new MouseEventData(
407 MouseButtonType.LEFT.value(), MouseEventType.PRESS.value(),
408 originX, originY, x, y, this.fingerCnt - 1);
409 communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData);
411 } else if (touchType == MouseEventType.RELEASE.value()) { /* released */
412 logger.info("mouse up for multi touch");
413 this.grabFingerID = 0;
417 private Boolean CalculateOriginCoordinates(
418 int ScaledLcdWitdh, int ScaledLcdHeight,
419 double scaleFactor, int rotationType, FingerPoint finger) {
421 int pointX, pointY, rotatedPointX, rotatedPointY, flag;
424 /* logger.info("ScaledLcdWitdh:" + ScaledLcdWitdh +
425 " ScaledLcdHeight:" + ScaledLcdHeight +
426 " scaleFactor:" + scaleFactor + " rotationType:" + rotationType); */
428 rotatedPointX = pointX = (int)(finger.x * scaleFactor);
429 rotatedPointY = pointY = (int)(finger.y * scaleFactor);
431 /* logger.info("rotatedPointX:" + rotatedPointX +
432 " rotatedPointY:" + rotatedPointY); */
434 if (rotationType == RotationInfo.LANDSCAPE.id()) {
435 rotatedPointX = pointY;
436 rotatedPointY = ScaledLcdWitdh - pointX;
437 } else if (rotationType == RotationInfo.REVERSE_PORTRAIT.id()) {
438 rotatedPointX = ScaledLcdWitdh - pointX;
439 rotatedPointY = ScaledLcdHeight - pointY;
440 } else if (rotationType == RotationInfo.REVERSE_LANDSCAPE.id()) {
441 rotatedPointX = ScaledLcdHeight - pointY;
442 rotatedPointY = pointX;
444 /* PORTRAIT: do nothing */
447 if (finger.originX != rotatedPointX) {
448 logger.info("finger.originX: " +finger.originX);
449 finger.originX = rotatedPointX;
452 if (finger.originY != rotatedPointY) {
453 logger.info("finger.originY: " +finger.originY);
454 finger.originY = rotatedPointY;
465 public int rearrangeFingerPoints(
466 int lcdWidth, int lcdHeight, double scaleFactor, int rotationType) {
469 FingerPoint finger = null;
471 if (this.multiTouchEnable == 0) {
475 scaleFactor = scaleFactor / 100;
476 lcdWidth *= scaleFactor;
477 lcdHeight *= scaleFactor;
479 for (i = 0; i < this.fingerCnt; i++) {
480 finger = getFingerPointFromSlot(i);
481 if (finger != null && finger.id != 0) {
482 if (CalculateOriginCoordinates(
483 lcdWidth, lcdHeight, scaleFactor, rotationType, finger) == true) {
490 this.grabFingerID = 0;
496 public void clearFingerSlot() {
498 FingerPoint finger = null;
500 for (i = 0; i < this.fingerCnt; i++) {
501 finger = getFingerPointFromSlot(i);
502 if (finger != null && finger.id != 0) {
503 logger.info(String.format(
504 "clear %d, %d, %d", finger.x, finger.y, finger.id - 1));
506 MouseEventData mouseEventData = new MouseEventData(
507 MouseButtonType.LEFT.value(), MouseEventType.RELEASE.value(),
508 0, 0, finger.x, finger.y, finger.id - 1);
509 communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData);
513 finger.originX = finger.originY = finger.x = finger.y = -1;
516 this.grabFingerID = 0;
518 logger.info("clear multi touch");
521 public void cleanup_multiTouchState() {
522 this.multiTouchEnable = 0;
524 fingerSlotimage.dispose();
527 public int getMaxTouchPoint() {
528 if (this.maxTouchPoint <= 0) {
532 return this.maxTouchPoint;
535 public void setMaxTouchPoint(int cnt) {
540 this.maxTouchPoint = cnt;