ccc6c90837656b668b701778447c9fa4be192ea7
[sdk/emulator/qemu.git] / tizen / src / skin / client / src / org / tizen / emulator / skin / EmulatorFingers.java
1 /**
2  *
3  *
4  * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * Munkyu Im <munkyu.im@samsung.com>
8  * GiWoong Kim <giwoong.kim@samsung.com>
9  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
10  *
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.
15  *
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.
20  *
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.
24  *
25  * Contributors:
26  * - S-Core Co., Ltd
27  *
28  */
29
30 package org.tizen.emulator.skin;
31
32 import java.util.ArrayList;
33 import java.util.logging.Logger;
34
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;
49
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
57         private Logger logger =
58                         SkinLogger.getSkinLogger(EmulatorFingers.class).getLogger();
59
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;
75
76         EmulatorSkinState currentState;
77
78         EmulatorFingers(EmulatorSkinState currentState) {
79                 this.currentState = currentState;
80                 initMultiTouchState();
81         }
82
83         protected void setCommunicator(SocketCommunicator communicator) {
84                  this.communicator = communicator;
85          }
86
87         //private fingerPointSurface;
88         protected class FingerPoint {
89                 int id;
90                 int originX;
91                 int originY;
92                 int x;
93                 int y;
94
95                 FingerPoint(int originX, int originY, int x, int y) {
96                         this.originX = originX;
97                         this.originY = -originY;
98                         this.x = x;
99                         this.y = y;
100                 }
101
102                 FingerPoint(int id, int originX, int originY, int x, int y) {
103                         this.id = id;
104                         this.originX = originX;
105                         this.originY = -originY;
106                         this.x = x;
107                         this.y = y;
108                 }
109         }
110
111         public FingerPoint getFingerPointFromSlot(int index) {
112                 if (index < 0 || index > this.fingerCntMax) {
113                         return null;
114                 }
115
116                 return FingerPointList.get(index);
117         }
118
119         public FingerPoint getFingerPointSearch(int x, int y) {
120                 int i;
121                 FingerPoint fingerPoint = null;
122                 int fingerRegion = (this.fingerPointSize) + 2;
123                 //logger.info("x: "+x+ "y: "+ y + " fingerRegion: " + fingerRegion);
124
125                 for (i = this.fingerCnt - 1; i >= 0; i--) {
126                         fingerPoint = getFingerPointFromSlot(i);
127
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);
134                                         return fingerPoint;
135                                 }
136                         }
137                 }
138
139                 return null;
140         }
141
142         protected void setEmulatorSkin(EmulatorSkin emulatorSkin) {
143                 this.emulatorSkin = emulatorSkin;
144         }
145
146         public void initMultiTouchState() {
147                 this.multiTouchEnable = 0;
148                 this.fingerCntMax = this.currentState.getMaxTouchPoint();
149
150                 if (this.fingerCntMax > MAX_FINGER_CNT) {
151                         this.fingerCntMax = MAX_FINGER_CNT;
152                         setMaxTouchPoint(this.fingerCntMax);
153                 }
154
155                 logger.info("maxTouchPoint="+ this.fingerCntMax);
156                 this.fingerCnt = 0;
157
158                 if (this.fingerSlot != null) {
159                         this.fingerSlot = null;
160                 }
161
162                 FingerPointList = new ArrayList<FingerPoint>();
163                 int i;
164                 for (i = 0; i <= fingerCntMax; i++) {
165                         FingerPointList.add(new FingerPoint(-1, -1, -1, -1));
166                 } 
167                 this.fingerPointSize = 32;
168                 this.fingerPointSizeHalf = this.fingerPointSize / 2;
169
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);
173
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);
178
179                 GC gc = new GC(this.fingerSlotimage);
180
181                 gc.setForeground(this.fingerPointOutlineColor);
182                 gc.drawOval(0, 0, this.fingerPointSize + 2, this.fingerPointSize + 2);
183
184                 gc.setBackground(this.fingerPointColor);
185                 gc.fillOval(2, 2, this.fingerPointSize, this.fingerPointSize);
186
187                 gc.dispose();
188         }
189
190         public void setMultiTouchEnable(int multiTouchEnable) {
191                 this.multiTouchEnable = multiTouchEnable;
192         }
193
194         public int getMultiTouchEnable() {
195                 return this.multiTouchEnable;
196         }
197
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");
202                         return -1;
203                 }
204                 this.fingerCnt += 1;
205
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");
212
213                 return this.fingerCnt;
214         }
215
216         protected void drawImage(PaintEvent e, int currentAngle) {
217                 //by mq
218                 for (int i = 0; i < this.fingerCnt; i++) {
219                         this.fingerSlot = this.getFingerPointFromSlot(i);       
220                         e.gc.setAlpha(0x7E);
221                 //      logger.info("OriginX: "+ this.fingerSlot.originX + ",OriginY: " + (this.fingerSlot.originY));
222                 //      logger.info("x: "+ this.fingerSlot.x + ",y: " + (this.fingerSlot.y));
223
224                         e.gc.drawImage(this.fingerSlotimage, 
225                                         this.fingerSlot.originX - fingerPointSizeHalf - 2,
226                                         this.fingerSlot.originY - fingerPointSizeHalf - 2);
227                         e.gc.setAlpha(0xFF);
228                 }
229         }
230
231         public void maruFingerProcessing1(
232                         int touchType, int originX, int originY, int x, int y) {
233                 FingerPoint finger = null;
234                 MouseEventData mouseEventData;
235
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;
243                                         finger.x = x;
244                                         finger.y = y;
245
246                                         if (finger.id != 0) {
247                                                 logger.info(String.format(
248                                                                 "id %d finger multi-touch dragging = (%d, %d)",
249                                                                 this.grabFingerID, x, y));
250
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);
255                                         } 
256                                 }
257
258                                 return;
259                         }
260
261                         if (this.fingerCnt == 0)
262                         { /* first finger touch input */
263                                 if (addFingerPoint(originX, originY, x, y) == -1) {
264                                         return;
265                                 }
266
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);
271                         }
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));
277                         }
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);
286
287                                         finger.originX = originX;
288                                         finger.originY = originY;
289                                         finger.x = x;
290                                         finger.y = y;
291
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);
297                                         }
298                                 }
299                         }
300                         else
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);
307                         }
308                 } else if (touchType == MouseEventType.RELEASE.value()) { /* released */
309                         logger.info("mouse up for multi touch");
310                         this.grabFingerID = 0;
311                 }
312         }
313
314         public void maruFingerProcessing2(
315                         int touchType, int originX, int originY, int x, int y) {
316                 FingerPoint finger = null;
317                 MouseEventData mouseEventData;
318
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;
328
329                                         int currrntScreenW = currentState.getCurrentResolutionWidth();
330                                         int currrntScreenH = currentState.getCurrentResolutionHeight();
331                                         int tempFingerX, tempFingerY;
332
333                                         int i;
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;
340
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));
346                                                                 return;
347                                                         }
348                                                 }
349                                         }
350
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;
358
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);
364
365                                                                 /* logger.info(String.format(
366                                                                                 "id %d finger multi-touch dragging = (%d, %d)",
367                                                                                 i + 1, finger.x, finger.y));*/
368                                                         }
369
370                                                         try {
371                                                                 Thread.sleep(2);
372                                                         } catch (InterruptedException e) {
373                                                                 e.printStackTrace();
374                                                         }
375                                                 }
376                                         }
377                                 }
378
379                                 return;
380                         }
381
382                         if (this.fingerCnt == 0)
383                         { /* first finger touch input */
384                                 if (this.addFingerPoint(originX, originY, x, y) == -1) {
385                                         return;
386                                 }
387
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);
392                         }
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));
398                         }
399                         else if (this.fingerCnt == this.fingerCntMax)
400                         {  /* Let's assume that this event is last finger touch input */
401                                 /* do nothing */
402                         }
403                         else /* one more finger */
404                         {
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);
410                         }
411                 } else if (touchType == MouseEventType.RELEASE.value()) { /* released */
412                         logger.info("mouse up for multi touch");
413                         this.grabFingerID = 0;
414                 }
415         }
416
417         private Boolean CalculateOriginCoordinates(
418                         int ScaledLcdWitdh, int ScaledLcdHeight,
419                         double scaleFactor, int rotationType, FingerPoint finger) {
420
421                 int pointX, pointY, rotatedPointX, rotatedPointY, flag;
422                 flag = 0;
423
424                 /* logger.info("ScaledLcdWitdh:" + ScaledLcdWitdh +
425                                 " ScaledLcdHeight:" + ScaledLcdHeight +
426                                 " scaleFactor:" + scaleFactor + " rotationType:" + rotationType); */
427
428                 rotatedPointX = pointX = (int)(finger.x * scaleFactor);
429                 rotatedPointY = pointY = (int)(finger.y * scaleFactor);
430
431                 /* logger.info("rotatedPointX:" + rotatedPointX +
432                                 " rotatedPointY:" + rotatedPointY); */
433
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;
443                 } else {
444                         /* PORTRAIT: do nothing */
445                 }
446
447                 if (finger.originX != rotatedPointX) {
448                         logger.info("finger.originX: " +finger.originX);
449                         finger.originX = rotatedPointX;
450                         flag = 1;
451                 }
452                 if (finger.originY != rotatedPointY) {
453                         logger.info("finger.originY: " +finger.originY);
454                         finger.originY = rotatedPointY;
455                         flag = 1;
456                 }
457
458                 if (flag != 0) {
459                         return true;
460                 }
461
462                 return false;
463         }
464
465         public int rearrangeFingerPoints(
466                         int lcdWidth, int lcdHeight, double scaleFactor, int rotationType) {
467                 int i = 0;
468                 int count = 0;
469                 FingerPoint finger = null;
470
471                 if (this.multiTouchEnable == 0) {
472                         return 0;
473                 }
474
475                 scaleFactor = scaleFactor / 100;
476                 lcdWidth *= scaleFactor;
477                 lcdHeight *= scaleFactor;
478
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) {
484                                         count++;
485                                 }
486                         }
487                 }
488
489                 if (count != 0) {
490                         this.grabFingerID = 0;
491                 }
492
493                 return count;
494         }
495
496         public void clearFingerSlot() {
497                 int i = 0;
498                 FingerPoint finger = null;
499
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));
505
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);
510                         }
511
512                         finger.id = 0;
513                         finger.originX = finger.originY = finger.x = finger.y = -1;
514                 }
515
516                 this.grabFingerID = 0;
517                 this.fingerCnt = 0;
518                 logger.info("clear multi touch");
519         }
520
521         public void cleanup_multiTouchState() {
522                 this.multiTouchEnable = 0;
523                 clearFingerSlot();
524                 fingerSlotimage.dispose();
525         }
526
527         public int getMaxTouchPoint() {
528                 if (this.maxTouchPoint <= 0) {
529                         setMaxTouchPoint(1);
530                 }
531
532                 return this.maxTouchPoint;
533         }
534
535         public void setMaxTouchPoint(int cnt) {
536                 if (cnt <=0) {
537                         cnt = 1;
538                 }
539
540                 this.maxTouchPoint = cnt;                       
541         }
542 }