b7ebb4106caa73fe1671e30bcdf11bf7fd99fc32
[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         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;
72         
73         EmulatorSkinState currentState;
74         
75         EmulatorFingers(EmulatorSkinState currentState) {
76                 this.currentState = currentState;
77                 initMultiTouchState();
78         }
79         
80          protected void setCommunicator(SocketCommunicator communicator) {
81                  this.communicator = communicator;
82          }
83         
84         //private fingerPointSurface;
85         protected class FingerPoint {
86                 int id;
87                 int originX;
88                 int originY;
89                 int x;
90                 int y;
91                 
92                 FingerPoint(int originX, int originY, int x, int y) {
93                         this.originX = originX;
94                         this.originY = -originY;
95                         this.x = x;
96                         this.y = y;
97                 }
98                 
99                 FingerPoint(int id, int originX, int originY, int x, int y) {
100                         this.id = id;
101                         this.originX = originX;
102                         this.originY = -originY;
103                         this.x = x;
104                         this.y = y;
105                 }
106         }
107         
108         public FingerPoint getFingerPointFromSlot(int index) {
109                 if(index < 0 || index > this.fingerCntMax) {
110                         return null;
111                 }
112                 return FingerPointList.get(index);
113         }
114         
115         public FingerPoint getFingerPointSearch(int x, int y) {
116                 int i;
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);
122                         
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);
129                                         return fingerPoint;
130                                 }
131                         }
132                 }
133                 return null;
134         }
135         
136         protected void setEmulatorSkin(EmulatorSkin emulatorSkin) {
137                 this.emulatorSkin = emulatorSkin;
138         }
139         
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);
146                 }
147                 logger.info("maxTouchPoint="+ this.fingerCntMax);
148                 this.fingerCnt = 0;
149                 
150                 if (this.fingerSlot != null) {
151                         this.fingerSlot = null;
152                 }
153                 
154                 FingerPointList = new ArrayList<FingerPoint>();
155                 int i;
156                 for(i = 0; i <= fingerCntMax; i++) {
157                         FingerPointList.add(new FingerPoint(-1, -1, -1, -1));
158                 } 
159                 this.fingerPointSize = 32;
160                 this.fingerPointSizeHalf = this.fingerPointSize / 2 ;
161                 
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);
165                 
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);
169
170                 GC gc = new GC(this.fingerSlotimage);
171                 
172                 gc.setForeground(this.fingerPointOutlineColor);
173                 gc.drawOval(0, 0, this.fingerPointSize+2 , this.fingerPointSize+2);
174                 
175                 gc.setBackground(this.fingerPointColor);
176                 gc.fillOval(2, 2 , this.fingerPointSize, this.fingerPointSize);
177                 
178                 gc.dispose();
179         }
180         
181         public void setMultiTouchEnable(int multiTouchEnable) {
182                 this.multiTouchEnable = multiTouchEnable;
183         }
184         
185         public int getMultiTouchEnable() {
186                 return this.multiTouchEnable;
187         }
188         
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");
192                         return -1;
193                 }
194                 this.fingerCnt += 1;
195                 
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");
202                 
203                 return this.fingerCnt;
204                 
205         }
206         
207         protected void drawImage(PaintEvent e, int currentAngle) {
208                 //by mq
209                 for(int i=0; i < this.fingerCnt; i++) {
210                         this.fingerSlot = this.getFingerPointFromSlot(i);       
211                         e.gc.setAlpha(0x7E);
212                 //      logger.info("OriginX: "+ this.fingerSlot.originX + ",OriginY: " + (this.fingerSlot.originY));
213                 //      logger.info("x: "+ this.fingerSlot.x + ",y: " + (this.fingerSlot.y));
214                         
215                         e.gc.drawImage(this.fingerSlotimage, 
216                                         this.fingerSlot.originX - fingerPointSizeHalf - 2,
217                                         this.fingerSlot.originY - fingerPointSizeHalf - 2);
218                         e.gc.setAlpha(0xFF);
219                 }
220         }
221         
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;
231                         finger.x = x;
232                         finger.y = y;
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 );                                
239                         }   
240                     }   
241                     return;
242                 }
243                 
244                 if(this.fingerCnt == 0) {
245                         //first finger touch input
246                         if(addFingerPoint(originX, originY, x, y) == -1) {
247                                 return;
248                         }
249            
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 );
254                 }
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));
260                 }
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);
264                         if(finger != null) {
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 );
269                                 
270                                         finger.originX = originX;
271                                         finger.originY = originY;
272                                         finger.x = x;
273                                         finger.y = y;
274                                         if(finger.id != 0) {
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 );
279                                         
280                                         }
281                         }
282                 }
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 );
289                                 
290                 }   
291                 }
292                 else if (touchType == MouseEventType.RELEASE.value()) { /* released */
293                         logger.info("mouse up for multi touch");
294                         this.grabFingerID = 0;
295                 }
296
297         }
298         
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);
305                                 if(finger != null) {
306                                         int originDistanceX = originX - finger.originX;
307                                         int originDistanceY = originY - finger.originY;
308                                         int distanceX = x - finger.x;
309                                         int distanceY = y - finger.y;
310                                         
311                                         int currrntScreenW = currentState.getCurrentResolutionWidth();
312                                         int currrntScreenH = currentState.getCurrentResolutionHeight();
313                                         int tempFingerX, tempFingerY;
314                                         
315                                         int i;
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));
325                                         return;                                               
326                                 } 
327                             }
328                         }
329
330                         for(i = 0; i < this.fingerCnt; i++) {   
331                             finger = getFingerPointFromSlot(i);
332
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));
344                                 }
345                                 try {
346                                                                 Thread.sleep(2);
347                                                         } catch (InterruptedException e) {
348                                                                 e.printStackTrace();
349                                                 
350                                                         }
351                             }
352                         }
353                     }
354                     return;
355                 }
356                         
357                         if (this.fingerCnt == 0)
358                         { //first finger touch input                                              
359                                 if (this.addFingerPoint(originX, originY, x, y) == -1) {
360                                 return;
361                         }
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 );                        
366                     }
367                     else if((finger = this.getFingerPointSearch(x, y)) != null) //check the position of previous touch event
368                     {
369                         //finger point is selected                                            
370                         this.grabFingerID = finger.id;          
371                         logger.info(String.format("id %d finger is grabbed\n", this.grabFingerID));
372                    
373                 }       
374                 else if(this.fingerCnt == this.fingerCntMax) //Let's assume that this event is last finger touch input
375                 {       
376                     //do nothing
377                 }       
378                 else //one more finger                                                    
379                 {   
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 );                                            
385                         }       
386                 }else if (touchType == MouseEventType.RELEASE.value()) { /* released */
387                         logger.info("mouse up for multi touch");
388                         this.grabFingerID = 0;
389                 }       
390
391         }
392         
393         private Boolean CalculateOriginCoordinates(int ScaledLcdWitdh, int ScaledLcdHeight, double scaleFactor, int rotationType, FingerPoint finger) {
394             
395                 int pointX, pointY, rotatedPointX, rotatedPointY, flag;
396             flag = 0;
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;
410             } else {
411               //PORTRAIT: do nothing    
412             }
413                 
414
415             if (finger.originX != rotatedPointX) {
416                 logger.info("finger.originX: " +finger.originX);
417                 finger.originX = rotatedPointX;
418                 flag = 1;
419             }
420             if (finger.originY != rotatedPointY) {
421                 logger.info("finger.originY: " +finger.originY);
422                 finger.originY = rotatedPointY;
423                 flag = 1;
424             }
425
426             if (flag != 0) {
427                 return true;
428             }
429
430             return false;
431         }
432         
433         public int rearrangeFingerPoints(int lcdWidth, int lcdHeight, double scaleFactor, int rotationType) {
434                 int i = 0;                                                                    
435             int count = 0;                                                                
436             FingerPoint finger = null;                                                   
437                                                                                           
438             if (this.multiTouchEnable == 0) {                                            
439                 return 0;                                                                 
440             }                                                                             
441             scaleFactor = scaleFactor/100;                                                                              
442             lcdWidth *= scaleFactor;                                                        
443             lcdHeight *= scaleFactor;                                                        
444                                                                                           
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) {                    
450                         count++;                                                          
451                     }                                                                     
452                 }                                                                         
453             }                                                                             
454                                                                                           
455             if (count != 0) {                                                             
456                 this.grabFingerID = 0;                                                      
457             }                                                                             
458                                                                                           
459             return count;           
460         }
461         
462         public void clearFingerSlot() {
463                 int i = 0;
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 );
473                         }
474                         finger.id = 0;
475                         finger.originX = finger.originY = finger.x = finger.y = -1;
476                 }
477                 this.grabFingerID = 0;
478                 this.fingerCnt = 0;
479                 logger.info("clear multi touch");
480         }
481         
482         public void cleanup_multiTouchState() {
483                 this.multiTouchEnable = 0;
484                 clearFingerSlot();
485                 fingerSlotimage.dispose();
486         }
487         
488         public int getMaxTouchPoint() {
489                 if(this.maxTouchPoint <= 0 ) {
490                         setMaxTouchPoint(1);
491                 }
492                 return this.maxTouchPoint;
493         }
494         
495         public void setMaxTouchPoint(int cnt) {
496                 if(cnt <=0) {
497                         cnt =1;
498                 }
499                 this.maxTouchPoint = cnt;                       
500         }
501 }