remove timer when back key selected
[apps/home/ug-image-viewer-efl.git] / common / src / ivug-mouse-event.c
1 /*\r
2  * Copyright 2012  Samsung Electronics Co., Ltd\r
3  *\r
4  * Licensed under the Flora License, Version 1.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *        http://www.tizenopensource.org/license\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16
17 #include <Elementary.h>
18 #include <stdbool.h>
19 #include "ivug-debug.h"
20 #include "ivug-mouse-event.h"
21
22
23 // Click condition.
24 // Down Up duration under 300ms & Down pos, Up pos under 3 pixel
25
26
27 // Long pressed condition
28 // Down Up duration upper 1s & Down pos, Up pos under 5 pixel
29
30 typedef enum {
31         MOUSE_DOWN_UNKNWON,
32         MOUSE_DOWN_NONE,
33         MOUSE_DOWN_1,
34         MOUSE_DOWN_2,
35         MOUSE_DOWN_3,
36         MOUSE_DOWN_4,           // Invalid state.
37 } MouseState;
38
39
40
41 #define INVALID_DEVICE_ID (-1)
42 #define MULTI_INDEX (9)
43 #define NUM_MAX_BUTTON (3)
44
45 typedef struct _mouse_data_t{
46         void *pClientData;
47         Evas_Object *obj;
48
49         mouse_callback_t cb;
50
51         MouseState m_state;
52
53         bool bDown[NUM_MAX_BUTTON];             // For Mose down check before mouse move
54         bool bHold[NUM_MAX_BUTTON];
55
56         MouseEvent event[NUM_MAX_BUTTON];
57         MouseEvent down[NUM_MAX_BUTTON];
58         MouseEvent prve_up[NUM_MAX_BUTTON];
59
60         unsigned int prev_dist;
61
62         int multi_min_idx;                      // multi min index is different in each target. Temp solution
63
64         bool bSendPinchStart;
65
66         MouseEvent center;
67         int pinch_dist;
68 // For debugging purpose, later will be removed.
69         char alias[100];                //
70 } mouse_data_t;
71
72
73 #ifndef __UNUSED__
74 #define __UNUSED__ __attribute__((unused))
75 #endif
76
77 static unsigned int _get_distance(int prevX, int prevY, int X, int Y)
78 {
79 #include <math.h>
80         int dx = prevX - X;
81         int dy = prevY - Y;
82
83         return sqrt(dx*dx + dy*dy);
84 }
85
86 static void _on_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
87 {
88         if ( data == NULL )
89         {
90                 MSG_MOUSE_ERROR("Debug me!!!!");
91                 return;
92         }
93
94         mouse_data_t *pData = (mouse_data_t *)data;
95         MouseEvent *ev = event_info;
96
97         if ( ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
98         {
99                 MSG_MOUSE_HIGH("[%s] %s On Hold. Dev=%d", pData->alias, __func__, ev->device);
100         }
101
102         int pressed = ev->device;
103
104         if(pressed >= NUM_MAX_BUTTON)
105         {
106                 MSG_MOUSE_FATAL("Invalid Pressed(%d)", pressed);
107                 return;
108         }
109
110         if ( pData->m_state == MOUSE_DOWN_UNKNWON )
111         {
112                 MSG_MOUSE_ERROR("[%s] Something wrong", pData->alias);
113         }
114
115         if \r( pData->bDown[pressed] == true )
116         {
117                 MSG_MOUSE_WARN("Mouse down is detected. but already pressed button. ignore");
118                 return;
119         }
120
121         pData->m_state++;
122         pData->bDown[pressed] = true;           // TODO : probably, can make memory overwritten issues.
123
124         if ( pData->m_state == MOUSE_DOWN_1 )
125         {
126                 MSG_MOUSE_HIGH("[%s] Callback Mouse Down : Dev=%d (%d,%d)", pData->alias, ev->device, ev->x, ev->y);
127
128                 if ( pData->cb.onMouseDown )
129                 {
130                         (pData->cb.onMouseDown)(pData->obj, ev, pData->pClientData);
131                 }
132
133                 MSG_MOUSE_MED("Func:%s Device=%d XY(%d,%d)", "_on_mouse_down", pressed, ev->x , ev->y );
134         }
135         else if ( pData->m_state == MOUSE_DOWN_2 )
136         {
137                 MouseEvent *other = NULL;
138
139                 if ( pData->bDown[ (pressed + 1) % NUM_MAX_BUTTON] == true )
140                 {
141                         other = &pData->event[(pressed + 1) % NUM_MAX_BUTTON];
142                 }
143
144                 if ( pData->bDown[(pressed + 2) % NUM_MAX_BUTTON] == true )
145                 {
146                         if ( other != NULL )
147                         {
148                                 MSG_MOUSE_ERROR("Error!!!");
149                         }
150                         other = &pData->event[(pressed + 2) % NUM_MAX_BUTTON];
151                 }
152
153                 if ( other == NULL )
154                 {
155                         MSG_MOUSE_ERROR("[%s] Error! Pressed(%d,%d,%d)",  pData->alias,
156                                 pData->bDown[0],
157                                 pData->bDown[1],
158                                 pData->bDown[2]);
159
160                         return ;                // Fix for B/S
161                 }
162
163                 int centerX = ( other->x + ev->x ) / 2;
164                 int centerY = ( other->y + ev->y ) / 2;
165
166                 int dist = _get_distance(other->x, other->y, ev->x, ev->y);
167
168                 MSG_MOUSE_HIGH("[%s] Callback PinchStart : Dev=%d OtherDev=%d Center(%d,%d) Dist=%d", pData->alias, ev->device, other->device, centerX, centerY, dist);
169
170                 if ( pData->cb.onPinchStart )
171                 {
172                         pData->center.x = centerX;
173                         pData->center.y = centerY;
174                         pData->center.timestamp = ev->timestamp;
175                         pData->pinch_dist = dist;
176
177                         (pData->cb.onPinchStart)(pData->obj, &pData->center, dist, pData->pClientData);
178                 }
179
180                 pData->prev_dist = dist;
181
182                 MSG_MOUSE_HIGH("[%s] Two fingure is clicked. Distance=%d", pData->alias, pData->prev_dist);
183         }
184         else
185         {
186                 MSG_MOUSE_WARN("[%s] Ignore third finger! State=%d Dev=%d bPressed(%d,%d,%d)", pData->alias, pData->m_state, ev->device,
187                         pData->bDown[0],
188                         pData->bDown[1],
189                         pData->bDown[2]);
190
191                 return ;
192         }
193
194         pData->event[pressed] = *ev;
195         pData->down[pressed] = *ev;
196
197         return ;
198 }
199
200
201 static void _on_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
202 {
203
204         if ( data == NULL )
205         {
206                 MSG_MOUSE_ERROR("Debug me!!!!");
207                 return;
208         }
209
210         mouse_data_t *pData = (mouse_data_t *)data;
211         MouseEvent *ev = event_info;
212
213         int pressed = ev->device;
214
215         if(pressed >= NUM_MAX_BUTTON)
216         {
217                 MSG_MOUSE_FATAL("Invalid Pressed(%d)", pressed);
218                 return;
219         }
220
221         if ( pData->m_state == MOUSE_DOWN_UNKNWON )
222         {
223                 MSG_MOUSE_ERROR("[%s] Something wrong. Dev=%d",  pData->alias, ev->device);
224                 MSG_MOUSE_ERROR("[%s] Error! State=%d Dev=%d bPressed(%d,%d,%d)", pData->alias, pData->m_state, ev->device,
225                         pData->bDown[0],
226                         pData->bDown[1],
227                         pData->bDown[2]);
228
229         }
230
231         if ( pData->m_state == MOUSE_DOWN_NONE )
232         {
233                 MSG_MOUSE_WARN("[%s] Mouse up is detected. but state is NONE.", pData->alias);
234                 pData->bDown[0] = pData->bDown[1] = pData->bDown[2] = 0;
235                 return;
236         }
237
238         pData->m_state--;
239
240         if \r( pData->bDown[pressed] == false )
241         {
242                 MSG_MOUSE_ERROR("[%s] Something wrong", pData->alias);
243                 MSG_MOUSE_ERROR("[%s] Error! State=%d Dev=%d bPressed(%d,%d,%d)", pData->alias, pData->m_state, ev->device,
244                         pData->bDown[0],
245                         pData->bDown[1],
246                         pData->bDown[2]);
247         }
248
249         if ( ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
250         {
251                 MSG_MOUSE_HIGH("[%s] %s On Hold. Dev=%d", pData->alias, __func__, ev->device);
252                 pData->bHold[pressed] = true;
253         }
254
255         pData->bDown[pressed] = false;
256
257         if ( pData->m_state == MOUSE_DOWN_1 )
258         {
259                 MSG_MOUSE_HIGH("[%s] Callback Pinch End", pData->alias);
260
261                 if ( pData->cb.onPinchEnd )
262                 {
263                         pData->bSendPinchStart = false;
264                         (pData->cb.onPinchEnd)(pData->obj, ev, pData->pClientData);
265                 }
266         }
267         else if ( pData->m_state == MOUSE_DOWN_NONE )
268         {
269                 MSG_MOUSE_HIGH("[%s] Callback Mouse Up : Dev=%d (%d,%d)", pData->alias, ev->device, ev->x, ev->y);
270
271                 if ( ev->button_flags & EVAS_BUTTON_DOUBLE_CLICK)
272                 {
273                         if ( pData->cb.onMouseDlbClick )
274                         {
275                                 (pData->cb.onMouseDlbClick)(pData->obj, ev, pData->pClientData);
276                         }
277                         MSG_MOUSE_HIGH("[%s] %s Double click detected. Dev=%d (%d,%d)", pData->alias, __func__, ev->device, ev->x, ev->y);
278                 }
279                 if ( pData->cb.onMouseUp )
280                 {
281                         (pData->cb.onMouseUp)(pData->obj, ev, pData->pClientData);
282                 }
283
284                 pData->prve_up[pressed] = *ev;
285
286                 MSG_MOUSE_MED("Func:%s State=%d Device=%d XY(%d,%d)", "_on_mouse_up", pData->m_state, pressed, ev->x , ev->y);
287         }
288
289         return ;
290
291 }
292
293 static void _on_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
294 {
295         if ( data == NULL )
296         {
297                 MSG_MOUSE_ERROR("Debug me!!!!");
298                 return;
299         }
300
301         mouse_data_t *pData = (mouse_data_t *)data;
302         MouseEvent *ev = event_info;
303
304         int pressed = ev->device;
305
306         if ( ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
307         {
308                 MSG_MOUSE_HIGH("[%s] %s On Hold. Dev=%d", pData->alias, __func__, ev->device);
309         }
310
311         if(pressed >= NUM_MAX_BUTTON)
312         {
313                 MSG_MOUSE_FATAL("Invalid Pressed(%d)", pressed);
314                 return;
315         }
316
317         if ( pData->bDown[pressed] == false)
318         {
319                 // Move event prior down should be ignored
320                 MSG_MOUSE_MED("Ignore move event before click");
321                 return ;
322         }
323
324         switch ( pData->m_state )
325         {
326         case MOUSE_DOWN_3:
327                 // Ignore Mouse Event when all 3 buttons is pressed.
328                 return ;
329         case MOUSE_DOWN_2:
330         {
331                 MouseEvent *other = NULL;
332
333                 if ( pData->bDown[ (pressed + 1) % NUM_MAX_BUTTON] == true )
334                 {
335                         other = &pData->event[(pressed + 1) % NUM_MAX_BUTTON];
336                 }
337
338                 if ( pData->bDown[(pressed + 2) % NUM_MAX_BUTTON] == true )
339                 {
340                         if ( other != NULL )
341                         {
342                                 MSG_MOUSE_ERROR("Debug me!!!");
343                         }
344                         other = &pData->event[(pressed + 2) % NUM_MAX_BUTTON];
345                 }
346
347                 if ( other == NULL )
348                 {
349                         MSG_MOUSE_ERROR("[%s] Error! Pressed(%d,%d,%d)", pData->alias,
350                                 pData->bDown[0],
351                                 pData->bDown[1],
352                                 pData->bDown[2]);
353
354                         // TODO : Recover.
355                         return;
356                 }
357
358                 int centerX = ( other->x + ev->x ) / 2;
359                 int centerY = ( other->y + ev->y ) / 2;
360
361                 int dist = _get_distance(other->x, other->y, ev->x, ev->y);
362
363                 if ( pData->cb.onPinchMove )
364                 {
365                         MSG_MOUSE_MED("Callback Pinch : (%d,%d) dDistance=%d", centerX, centerY, dist - pData->prev_dist);
366
367                         pData->center.x = centerX;
368                         pData->center.y = centerY;
369                         pData->center.timestamp = ev->timestamp;
370                         pData->pinch_dist = dist;
371
372                         (pData->cb.onPinchMove)(pData->obj, &pData->center, pData->pinch_dist , pData->pClientData);
373                 }
374
375                 pData->prev_dist = dist;
376
377                 MSG_MOUSE_LOW("Pinch zoom. Pos1(%d,%d) Pos2(%d,%d) Delta=%d", other->x, other->y, ev->x, ev->y, pData->prev_dist);
378
379                 pData->event[pressed] = *ev;
380
381                 return ;
382         }
383         break;
384         case MOUSE_DOWN_1:
385         {
386                 MSG_MOUSE_MED("Func:%s. Device=%d Old(%d,%d) Cur(%d,%d)", __FUNCTION__, pressed,
387                                 pData->event[pressed].x, pData->event[pressed].y,
388                                 ev->x , ev->y);
389
390                 if ( pData->cb.onMouseMove )
391                 {
392                         MSG_MOUSE_MED("[%s] Callback Mouse Move : (%d,%d)",  pData->alias, ev->x, ev->y);
393                         (pData->cb.onMouseMove)(pData->obj, &pData->event[pressed], ev, pData->pClientData);
394                 }
395
396                 pData->event[pressed] = *ev;
397
398                 break;
399         }
400         default:
401                 MSG_MOUSE_ERROR("[%s] Something wrong. state=%d", pData->alias, pData->m_state);
402                 break;
403
404         }
405
406         return ;
407 }
408
409
410
411 static void _proxy_on_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
412 {
413         Evas_Event_Mouse_Down *ev = event_info;
414
415         MouseEvent event;
416
417         event.device = 0;
418         event.timestamp = ev->timestamp;
419         event.x = ev->canvas.x;
420         event.y = ev->canvas.y;
421         event.button_flags = ev->flags;
422         event.event_flags = ev->event_flags;
423
424         MSG_MOUSE_MED("%s Dev=%d Button=%d Flags=%d Event=%d", __func__, (int)ev->dev, ev->button, ev->flags, ev->event_flags);
425
426         _on_mouse_down(data, NULL, obj, (void *)&event);
427 }
428
429 static void _proxy_on_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
430 {
431         Evas_Event_Mouse_Up *ev = event_info;
432
433         MouseEvent event;
434
435         event.device = 0;
436         event.timestamp = ev->timestamp;
437         event.x = ev->canvas.x;
438         event.y = ev->canvas.y;
439         event.button_flags = ev->flags;
440         event.event_flags = ev->event_flags;
441
442
443         MSG_MOUSE_MED("%s Dev=%d Button=%d Flags=%d Event=%d", __func__, (int)ev->dev, ev->button, ev->flags, ev->event_flags);
444
445
446         _on_mouse_up(data, NULL, obj, (void *)&event);
447 }
448
449 static void _proxy_on_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
450 {
451         Evas_Event_Mouse_Move *ev = event_info;
452
453         MouseEvent event;
454
455         event.device = 0;
456         event.timestamp = ev->timestamp;
457         event.x = ev->cur.canvas.x;
458         event.y = ev->cur.canvas.y;
459         event.button_flags = 0;
460         event.event_flags = ev->event_flags;
461
462         MSG_MOUSE_MED("%s Dev=%d Button=%d Event=%d Prev(%d,%d) Cur(%d,%d)", __func__, (int)ev->dev, ev->buttons, ev->event_flags,
463                                 ev->prev.canvas.x, ev->prev.canvas.y, ev->cur.canvas.x, ev->cur.canvas.y);
464
465         _on_mouse_move(data, NULL, obj, (void *)&event);
466
467 }
468
469 static void _proxy_on_mouse_multi_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
470 {
471         Evas_Event_Multi_Down *ev = event_info;
472         mouse_data_t *pData = data;
473
474         MouseEvent event;
475
476         if ( pData->multi_min_idx == INVALID_DEVICE_ID)
477         {
478                 MSG_MOUSE_HIGH("[%s] Min Device Index=%d", pData->alias, ev->device);
479                 pData->multi_min_idx = ev->device -1;           // Index start from 0. so -1 is needed
480         }
481
482         event.device = ev->device - pData->multi_min_idx;       // ev->device is 10(for second), 11(3rd), 12(4th) finger
483         event.timestamp = ev->timestamp;
484         event.x = ev->canvas.x;
485         event.y = ev->canvas.y;
486         event.button_flags = 0;
487         event.event_flags = ev->event_flags;
488
489
490         if(event.device >= NUM_MAX_BUTTON)
491         {
492                 MSG_MOUSE_FATAL("[%s] Invalid Device. Dev=%d Min=%d", pData->alias, event.device, pData->multi_min_idx);
493                 return;
494         }
495
496         MSG_MOUSE_MED("%s Dev=%d", __func__, ev->device);
497
498         _on_mouse_down(data, NULL, obj, (void *)&event);
499 }
500
501 static void _proxy_on_mouse_multi_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
502 {
503         Evas_Event_Multi_Up *ev = event_info;
504         mouse_data_t *pData = data;
505
506         MouseEvent event;
507
508         if ( pData->multi_min_idx == INVALID_DEVICE_ID)
509         {
510                 // Sometimes Multi up came ealry
511                 MSG_MOUSE_HIGH("[%s] Min Device Index=%d", pData->alias, ev->device);
512                 pData->multi_min_idx = ev->device -1;           // Index start from 0. so -1 is needed
513         }
514
515         event.device = ev->device - pData->multi_min_idx;
516         event.timestamp = ev->timestamp;
517         event.x = ev->canvas.x;
518         event.y = ev->canvas.y;
519         event.button_flags = 0;
520         event.event_flags = ev->event_flags;
521
522         if(event.device >= NUM_MAX_BUTTON)
523         {
524                 MSG_MOUSE_FATAL("[%s] Invalid Device. Dev=%d Min=%d", pData->alias, event.device, pData->multi_min_idx);
525                 return;
526         }
527
528         MSG_MOUSE_MED("%s Dev=%d", __func__, ev->device);
529
530         _on_mouse_up(data, NULL, obj, (void *)&event);
531
532 }
533
534 static void _proxy_on_mouse_multi_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
535 {
536         Evas_Event_Multi_Move *ev = event_info;
537         mouse_data_t *pData = data;
538
539         MouseEvent event;
540
541         if ( pData->multi_min_idx == INVALID_DEVICE_ID)
542         {
543                 // Mouse Move come faster than Mouse down
544                 MSG_MOUSE_HIGH("[%s] Min Device Index=%d", pData->alias, ev->device);
545                 pData->multi_min_idx = ev->device -1;
546         }
547
548         event.device = ev->device - pData->multi_min_idx;
549         event.timestamp = ev->timestamp;
550         event.x = ev->cur.canvas.x;
551         event.y = ev->cur.canvas.y;
552         event.button_flags = 0;
553         event.event_flags = ev->event_flags;
554
555         if(event.device >= NUM_MAX_BUTTON)
556         {
557                 MSG_MOUSE_FATAL("[%s] Invalid Device. Dev=%d Min=%d", pData->alias, event.device, pData->multi_min_idx);
558                 return;
559         }
560
561         MSG_MOUSE_MED("%s Dev=%d", __func__, ev->device);
562
563         _on_mouse_move(data, NULL, obj, (void *)&event);
564 }
565
566 Ivug_Event_Handle
567 ivug_mouse_event_add(Evas_Object *obj, mouse_callback_t *pCallback, void *client_data, const char *alias)
568 {
569         mouse_data_t *pData = NULL;
570 //TODO : Should check parameters
571
572         pData = calloc(1, sizeof(mouse_data_t));
573
574         pData->obj = obj;
575         pData->pClientData = client_data;
576         pData->m_state = MOUSE_DOWN_NONE;
577         pData->multi_min_idx = INVALID_DEVICE_ID;
578         strncpy(pData->alias, alias, sizeof(pData->alias));
579
580         memcpy(&pData->cb, pCallback, sizeof(mouse_callback_t));
581
582         evas_object_event_callback_add(pData->obj, EVAS_CALLBACK_MOUSE_DOWN, _proxy_on_mouse_down, pData);
583         evas_object_event_callback_add(pData->obj, EVAS_CALLBACK_MOUSE_UP, _proxy_on_mouse_up,  pData);
584         evas_object_event_callback_add(pData->obj, EVAS_CALLBACK_MOUSE_MOVE, _proxy_on_mouse_move, pData);
585         evas_object_event_callback_add(pData->obj, EVAS_CALLBACK_MULTI_DOWN, _proxy_on_mouse_multi_down, pData);
586         evas_object_event_callback_add(pData->obj, EVAS_CALLBACK_MULTI_UP, _proxy_on_mouse_multi_up, pData);
587         evas_object_event_callback_add(pData->obj, EVAS_CALLBACK_MULTI_MOVE, _proxy_on_mouse_multi_move, pData);
588
589         MSG_MOUSE_HIGH("Mouse Event Handler Add : Alias(%s) 0x%08x for Object(0x%08x)", alias, pData, obj);
590
591         return (Ivug_Event_Handle *)pData;
592 }
593
594
595 void ivug_mouse_event_del(Ivug_Event_Handle handle)
596 {
597         mouse_data_t *pData = handle;
598
599         evas_object_event_callback_del(pData->obj, EVAS_CALLBACK_MOUSE_DOWN, _proxy_on_mouse_down);
600         evas_object_event_callback_del(pData->obj, EVAS_CALLBACK_MOUSE_UP, _proxy_on_mouse_up);
601         evas_object_event_callback_del(pData->obj, EVAS_CALLBACK_MOUSE_MOVE, _proxy_on_mouse_move);
602         evas_object_event_callback_del(pData->obj, EVAS_CALLBACK_MULTI_DOWN, _proxy_on_mouse_multi_down);
603         evas_object_event_callback_del(pData->obj, EVAS_CALLBACK_MULTI_UP, _proxy_on_mouse_multi_up);
604         evas_object_event_callback_del(pData->obj, EVAS_CALLBACK_MULTI_MOVE, _proxy_on_mouse_multi_move);
605
606         MSG_MOUSE_HIGH("Mouse Event Handler Remove : 0x%08x", pData);
607
608         free(handle);
609 }
610
611
612