[Tizen 3.0] 2.4 source code merge
[apps/core/preloaded/quickpanel.git] / daemon / minictrl / minictrl.c
1 /*
2  * Copyright (c) 2009-2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18
19 #include <Elementary.h>
20 #include <glib.h>
21 #include <string.h>
22 #include <stdbool.h>
23
24 #include <minicontrol-viewer.h>
25 #include <minicontrol-internal.h>
26 #include <bundle.h>
27 #include <tzsh.h>
28 #include <tzsh_quickpanel_service.h>
29 #include <E_DBus.h>
30
31 #include "common.h"
32 #include "common_uic.h"
33 #include "quickpanel-ui.h"
34 #include "quickpanel_def.h"
35 #include "list_util.h"
36 #include "quickpanel_debug_util.h"
37 #include "minictrl.h"
38 #include "vi_manager.h"
39
40 #ifdef QP_SCREENREADER_ENABLE
41 #include "accessibility.h"
42 #endif
43
44 #define MINICONTROL_TYPE_STR_VIEWER "::[viewer="
45 #define MINICONTROL_TYPE_STR_QUICKPANEL "QUICKPANEL"
46 #define MINICONTROL_TYPE_STR_LOCKSCREEN "LOCKSCREEN"
47 #define MINICONTROL_TYPE_STR_ONGOING "_ongoing]"
48 #define MINICONTROL_VIEW_DATA "MINICONTROL_VIEW_DATA"
49
50 #define THRESHOLD_DELETE_START 30
51 #define THRESHOLD_DELETE_START_Y_LIMIT 60
52 #define THRESHOLD_DISTANCE (200)
53 #define THRESHOLD_DISTANCE_LOCK (500)
54
55 #define MINICONTROL_BUNDLE_KEY_WIDTH "width"
56 #define MINICONTROL_BUNDLE_KEY_HEIGHT "height"
57
58 #define BUNDLE_BUFFER_LENGTH 100
59
60 typedef enum _gesture_state_type {
61         STATE_NORMAL = 0,
62         STATE_GESTURE_WAIT,
63         STATE_GESTURE_CANCELED,
64         STATE_DELETED,
65 } gesture_state_type;
66
67 struct _viewer_item {
68         char *name;
69         unsigned int width;
70         unsigned int height;
71         Evas_Object *viewer;
72         void *data;
73
74         //for flick gesture
75         QP_VI *vi;
76         int obj_w;
77         int obj_h;
78         int press_x;
79         int press_y;
80         int distance;
81         int need_to_cancel_press;
82         gesture_state_type state;
83         int deletable;
84 };
85
86 static struct _info {
87         GHashTable *prov_table;
88 } s_info = {
89         .prov_table = NULL,
90 };
91
92 void _minictrl_sendview_rotation_event(const char* name, int angle);
93
94 static int _viewer_check(const char *name)
95 {
96         char *pos_start = NULL;
97
98         if (!name) {
99                 ERR("Name is NULL");
100                 return 0;
101         }
102
103         if ((pos_start = strstr(name, MINICONTROL_TYPE_STR_VIEWER)) != NULL) {
104                 if (strstr(pos_start, MINICONTROL_TYPE_STR_QUICKPANEL) != NULL) {
105                         return 1;
106                 } else {
107                         return 0;
108                 }
109         } else if (strstr(name, MINICONTROL_TYPE_STR_LOCKSCREEN) != NULL) {
110                 return 0;
111         }
112
113         return 1;
114 }
115
116 static void _viewer_unfreeze(Evas_Object *viewer)
117 {
118         int i = 0, freezed_count = 0;
119
120         if (!viewer) {
121                 ERR("Invalid parameter");
122                 return;
123         }
124
125         freezed_count = elm_object_scroll_freeze_get(viewer);
126
127         for (i = 0 ; i < freezed_count; i++) {
128                 elm_object_scroll_freeze_pop(viewer);
129         }
130 }
131
132 static Evas_Object *_get_minictrl_obj(Evas_Object *layout)
133 {
134         if (!layout) {
135                 ERR("Invalid parameter");
136                 return NULL;
137         }
138
139         return elm_object_part_content_get(layout, "elm.icon");
140 }
141
142 static void _viewer_set_size(Evas_Object *layout, void *data, int width, int height)
143 {
144         Evas_Object *viewer;
145         struct appdata *ad;
146         int max_width;
147         int resized_width;
148         int is_landscape;
149
150         if (!layout || !data || width < 0 || height < 0) {
151                 ERR("Invalid parameters (%p, %p, %d, %d)", layout, data, width, height);
152                 return;
153         }
154
155         viewer = _get_minictrl_obj(layout);
156         if (!viewer) {
157                 ERR("Unable to get the 'viewer'");
158                 return;
159         }
160
161         ad = data;
162
163         if (ad->angle == 0 || ad->angle == 180) {
164                 is_landscape = 0;
165         } else {
166                 is_landscape = 1;
167         }
168
169         if (width > ad->win_width) {
170                 ERR("MC Size is not valid. it is larger than window size: %dx%d (%dx%d) %d", width, height, ad->win_width, ad->win_height, ad->angle);
171         }
172
173         max_width  = is_landscape ? ad->win_height : ad->win_width;
174         resized_width = (width > max_width) ? max_width : width;
175
176         SERR("minicontroller view is resized to w:%d/%d(%d) h:%d Landscape[%d]", resized_width, max_width, width, height, is_landscape);
177
178         evas_object_size_hint_min_set(viewer, resized_width, height);
179         evas_object_size_hint_max_set(viewer, resized_width, height);
180 }
181
182 static void _viewer_item_free(struct _viewer_item *item)
183 {
184         struct appdata *ad;
185
186         ad = quickpanel_get_app_data();
187         if (!ad || !ad->list || !item) {
188                 ERR("Invalid paramter %p, %p, %p", ad, ad ? ad->list : NULL, item);
189                 return;
190         }
191
192         free(item->name);
193
194         if (item->viewer) {
195                 quickpanel_list_util_item_unpack_by_object(ad->list, item->viewer, 0, 0);
196                 quickpanel_list_util_item_del_tag(item->viewer);
197                 evas_object_del(item->viewer);
198         }
199
200         free(item);
201 }
202
203 static bool _check_deletable(Evas_Object *obj)
204 {
205         struct _viewer_item *vit;
206
207         vit = evas_object_data_get(obj, MINICONTROL_VIEW_DATA);
208         if (vit) {
209                 return vit->deletable;
210         }
211
212         return TRUE;
213 }
214
215 static void _mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
216 {
217         Evas_Event_Mouse_Down *ev;
218         struct _viewer_item *vit;
219
220         vit = evas_object_data_get(obj, MINICONTROL_VIEW_DATA);
221         ev = (Evas_Event_Mouse_Down *)event_info;
222
223         if (!ev || !vit) {
224                 ERR("ev %p, vit %p");
225                 return;
226         }
227
228         evas_object_geometry_get(obj, NULL, NULL, &vit->obj_w, &vit->obj_h);
229
230         vit->press_x = ev->canvas.x;
231         vit->press_y = ev->canvas.y;
232         vit->state = STATE_NORMAL;
233
234         SDBG("mouse down:%d %d %d", vit->obj_w, vit->obj_h, vit->state);
235
236         if (vit->vi != NULL) {
237                 quickpanel_vi_user_event_del(vit->vi);
238                 vit->vi = NULL;
239         }
240
241         vit->need_to_cancel_press = 0;
242 }
243
244 static void _mouse_move_cb(void* data, Evas* e, Evas_Object* obj, void* event_info)
245 {
246         static int vi_start_x = 0;
247         static int delta_prev = -1;
248         int delta_x;
249         int x;
250         int y;
251         int w;
252         int h;
253         Evas_Event_Mouse_Move* ev;
254         struct _viewer_item *vit;
255         struct appdata *ad;
256
257         ad = data;
258         ev = event_info;
259         vit = evas_object_data_get(obj, MINICONTROL_VIEW_DATA);
260         if (!ev || !vit || !ad) {
261                 ERR("ev: %p, vit: %p, ad: %p", ev, vit, ad);
262                 return;
263         }
264
265         if (vit->state == STATE_GESTURE_CANCELED) {
266                 DBG("deletion has been canceled");
267                 return;
268         }
269
270         if (!_check_deletable(obj)) {
271                 DBG("vit->deletable is false");
272                 return;
273         }
274
275         evas_object_geometry_get(obj, &x, &y, &w, &h);
276         delta_x = (ev->cur.output.x - vit->press_x) / 2;
277
278         switch (vit->state) {
279         case STATE_NORMAL:
280                 if (abs(delta_x) >= THRESHOLD_DELETE_START) {
281                         QP_VI *vi;
282
283                         DBG("start a deletion");
284                         vit->state = STATE_GESTURE_WAIT;
285
286                         vi_start_x = delta_x;
287
288                         vi = quickpanel_vi_new_with_data(
289                                         VI_OP_DELETE,
290                                         QP_ITEM_TYPE_NOTI,
291                                         NULL,
292                                         obj,
293                                         NULL,
294                                         NULL,
295                                         NULL,
296                                         NULL, /* _drag_cancel_cb, */
297                                         NULL, /* vi == null */
298                                         NULL,
299                                         0,
300                                         0);
301
302                         if (vi) {
303                                 vit->vi = vi;
304                                 quickpanel_vi_user_event_add(vi);
305                         } else {
306                                 ERR("Unable to create a 'vi'");
307                         }
308
309                         vit->need_to_cancel_press = 1;
310                 }
311                 break;
312         case STATE_GESTURE_WAIT:
313                 if (delta_prev != delta_x) {
314                         Evas_Map *map;
315
316                         map = evas_map_new(4);
317                         if (map != NULL) {
318                                 evas_map_util_points_populate_from_object(map, obj);
319                                 evas_map_util_points_populate_from_geometry(map, x + delta_x - vi_start_x, y, w, h, 0);
320                                 evas_object_map_enable_set(obj, EINA_TRUE);
321                                 evas_object_map_set(obj, map);
322                                 evas_map_free(map);
323                                 _viewer_unfreeze(ad->scroller);
324                         }
325                         delta_prev = delta_x;
326                 }
327                 break;
328         default:
329                 break;
330         }
331
332         vit->distance = delta_x;
333 }
334
335 static void _minictrl_remove(const char *name, void *data)
336 {
337         DBG("_minictrl_remove [%s]", name);
338
339         minicontrol_viewer_send_event(name, MINICONTROL_EVENT_REQUEST_HIDE, NULL);
340
341         if (s_info.prov_table) {
342                 if (g_hash_table_remove(s_info.prov_table, name)) {
343                         DBG("success to remove %s", name);
344                         if (!data) {
345                                 ERR("data is NULL");
346                                 /**
347                                  * @todo
348                                  * Oh, this function doesn't handles "data".
349                                  * Why does this has to check its existence??
350                                  */
351                                 return;
352                         }
353                 } else {
354                         WARN("unknown provider name : %s", name);
355                 }
356         }
357 }
358
359 static void _mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
360 {
361         struct _viewer_item *vit;
362         struct appdata *ad;
363         int swipe_distance;
364
365         ad = data;
366         vit = evas_object_data_get(obj, MINICONTROL_VIEW_DATA);
367         if (!vit || !ad) {
368                 ERR("vit: %p, ad: %p", vit, ad);
369                 return;
370         }
371
372         _viewer_unfreeze(ad->scroller);
373
374         if (!_check_deletable(obj)) {
375                 swipe_distance = THRESHOLD_DISTANCE_LOCK;
376         } else {
377                 swipe_distance = THRESHOLD_DISTANCE;
378         }
379
380         switch (vit->state) {
381         case STATE_GESTURE_WAIT:
382                 if (abs(vit->distance) >= (swipe_distance - 10)) {
383                         Elm_Transit *transit_flick;
384                         int x;
385
386                         x = abs(vit->distance) - THRESHOLD_DELETE_START;
387
388                         if (vit->distance > 0) {
389                                 evas_object_map_set(obj, NULL);
390                                 transit_flick = elm_transit_add();
391                                 if (transit_flick != NULL) {
392                                         elm_transit_effect_translation_add(transit_flick, x, 0, 480, 0);
393                                         elm_transit_object_add(transit_flick, obj);
394                                         elm_transit_duration_set(transit_flick, 0.25 * (480 - x ) / 480);
395                                         elm_transit_tween_mode_set(transit_flick, ELM_TRANSIT_TWEEN_MODE_LINEAR);
396                                         elm_transit_objects_final_state_keep_set(transit_flick, EINA_TRUE);
397                                         elm_transit_go(transit_flick);
398                                         _minictrl_remove(vit->name, vit->data);
399                                 }
400                         } else if (vit->distance < 0) {
401                                 evas_object_map_set(obj, NULL);
402                                 transit_flick = elm_transit_add();
403                                 if (transit_flick != NULL) {
404                                         elm_transit_effect_translation_add(transit_flick, -x, 0, -480, 0);
405                                         elm_transit_object_add(transit_flick, obj);
406                                         elm_transit_duration_set(transit_flick, 0.25 * ( 480 - x ) / 480);
407                                         elm_transit_tween_mode_set(transit_flick, ELM_TRANSIT_TWEEN_MODE_LINEAR);
408                                         elm_transit_objects_final_state_keep_set(transit_flick, EINA_TRUE);
409                                         elm_transit_go(transit_flick);
410                                         _minictrl_remove(vit->name, vit->data);
411                                 }
412                         }
413                 } else {
414                         evas_object_map_enable_set(obj, EINA_FALSE);
415                 }
416
417                 if (vit->vi != NULL) {
418                         quickpanel_vi_user_event_del(vit->vi);
419                         vit->vi = NULL;
420                 }
421                 break;
422         case STATE_GESTURE_CANCELED:
423                 evas_object_map_enable_set(obj, EINA_FALSE);
424
425                 if (vit->vi != NULL) {
426                         quickpanel_vi_user_event_del(vit->vi);
427                         vit->vi = NULL;
428                 }
429                 break;
430         default:
431                 break;
432         }
433
434         vit->state = STATE_NORMAL;
435 }
436
437 static Evas_Object *_minictrl_create_view(struct appdata *ad, const char *name)
438 {
439         Evas_Object *layout;
440         Evas_Object *viewer;
441         Evas_Object *focus;
442
443         if (!ad || !ad->list || !name) {
444                 ERR("Invalid parameters: %p %p %p", ad, ad ? ad->list : NULL, name);
445                 return NULL;
446         }
447
448         layout = elm_layout_add(ad->list);
449         if (!layout) {
450                 ERR("Unable to create a layout");
451                 return NULL;
452         }
453
454         elm_layout_file_set(layout, DEFAULT_EDJ, "quickpanel/minictrl/default");
455         evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
456         evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
457         evas_object_show(layout);
458
459         viewer = minicontrol_viewer_add(layout, name);
460         if (!viewer) {
461                 ERR("fail to add viewer - %s", name);
462                 evas_object_del(layout);
463                 return NULL;
464         }
465         elm_object_focus_allow_set(viewer, EINA_TRUE);
466         elm_object_part_content_set(layout, "elm.icon", viewer);
467
468         evas_object_event_callback_add(viewer, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, ad);
469         evas_object_event_callback_add(viewer, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, ad);
470         evas_object_event_callback_add(viewer, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, ad);
471
472         focus = quickpanel_accessibility_ui_get_focus_object(layout);
473         elm_object_part_content_set(layout, "focus", focus);
474 #ifdef QP_SCREENREADER_ENABLE
475         Evas_Object *ao;
476         ao = quickpanel_accessibility_screen_reader_object_get(layout, SCREEN_READER_OBJ_TYPE_ELM_OBJECT, "focus", layout);
477         if (ao != NULL) {
478                 elm_access_info_cb_set(ao, ELM_ACCESS_TYPE, quickpanel_accessibility_info_cb, _NOT_LOCALIZED("Mini controller"));
479         }
480 #endif
481
482         return layout;
483 }
484
485 static int _minictrl_is_ongoing(const char *str)
486 {
487         if (str == NULL) {
488                 return 0;
489         }
490
491         if (strstr(str, MINICONTROL_TYPE_STR_ONGOING) != NULL) {
492                 return 1;
493         } else {
494                 return 0;
495         }
496 }
497
498 static void _minictrl_add(const char *name, unsigned int width, unsigned int height, void *data)
499 {
500         qp_item_data *qid = NULL;
501         struct _viewer_item *vit = NULL;
502         qp_item_type_e type;
503         struct appdata *ad;
504         Evas_Object *viewer = NULL;
505
506         if (!name || !data) {
507                 ERR("name: %p, data: %p", name, data);
508                 return;
509         }
510
511         ad = data;
512         if (!ad->list) {
513                 ERR("List is null");
514                 return;
515         }
516
517         if (s_info.prov_table) {
518                 struct _viewer_item *found;
519
520                 found = g_hash_table_lookup(s_info.prov_table, name);
521                 if (found) {
522                         ERR("already have it : %s", name);
523                         return;
524                 }
525         } else {
526                 ERR("s_info.prov_table is NULL");
527                 return;
528         }
529
530         /* elm_plug receives 'server_del' event,
531          * if it repeats connect and disconnect frequently.
532          *
533          */
534         viewer = _minictrl_create_view(ad, name);
535         if (!viewer) {
536                 ERR("Failed to create view[%s]", name);
537                 return;
538         }
539
540         _viewer_set_size(viewer, ad, width, height);
541         quickpanel_uic_initial_resize(viewer,
542                         (height > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
543                         ? height : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
544
545         vit = malloc(sizeof(*vit));
546         if (!vit) {
547                 ERR("fail to alloc vit");
548                 evas_object_del(viewer);
549                 return;
550         }
551
552         if (_minictrl_is_ongoing(name) == 1) {
553                 type = QP_ITEM_TYPE_MINICTRL_ONGOING;
554         } else {
555                 type = QP_ITEM_TYPE_MINICTRL_MIDDLE;
556         }
557
558         qid = quickpanel_list_util_item_new(type, vit);
559         if (!qid) {
560                 ERR("fail to alloc vit");
561                 evas_object_del(viewer);
562                 free(vit);
563                 return;
564         }
565
566         vit->name = strdup(name);
567         if (!vit->name) {
568                 ERR("strdup: %d", errno);
569                 quickpanel_list_util_item_del(qid);
570                 evas_object_del(viewer);
571                 free(vit);
572                 return;
573         }
574         vit->width = width;
575         vit->height = height;
576         vit->viewer = viewer;
577         vit->data = data;
578         vit->deletable = 1;
579         quickpanel_list_util_item_set_tag(vit->viewer, qid);
580         quickpanel_list_util_sort_insert(ad->list, vit->viewer);
581         evas_object_data_set(_get_minictrl_obj(viewer), MINICONTROL_VIEW_DATA, vit);
582
583         g_hash_table_insert(s_info.prov_table, g_strdup(name), vit);
584
585         DBG("success to add minicontrol %s", name);
586         _minictrl_sendview_rotation_event(vit->name, ad->angle);
587 }
588
589 static void _anim_init_resize(void *data)
590 {
591         QP_VI *vi;
592         Evas_Object *item;
593
594         vi = data;
595         if (!vi) {
596                 ERR("Invalid parameter");
597                 return;
598         }
599
600         item = vi->target;
601         if (!item) {
602                 ERR("Invalid target");
603                 return;
604         }
605
606         evas_object_color_set(item, 0, 0, 0, 0);
607 }
608
609 static Eina_Bool _anim_init_cb(void *data)
610 {
611         QP_VI *vi;
612         int i;
613         static qp_vi_op_table anim_init_table[] = {
614                 {
615                         .op_type = VI_OP_RESIZE,
616                         .handler = _anim_init_resize,
617                 },
618                 {
619                         .op_type = VI_OP_NONE,
620                         .handler = NULL,
621                 },
622         };
623         
624         vi = data;
625         if (!vi) {
626                 ERR("Invalid parameter");
627                 return EINA_FALSE;
628         }
629
630         for (i = 0; anim_init_table[i].op_type != VI_OP_NONE; i++) {
631                 if (anim_init_table[i].op_type != vi->op_type) {
632                         continue;
633                 }
634
635                 anim_init_table[i].handler(vi);
636                 break;
637         }
638
639         return EINA_TRUE;
640 }
641
642 static void _reorder_transit_del_cb(void *data, Elm_Transit *transit)
643 {
644         QP_VI *vi;
645         Evas_Object *item;
646         struct appdata *ad;
647
648         vi = data;
649         if (!vi) {
650                 ERR("vi is null");
651                 return;
652         }
653
654         item = vi->target;
655         if (!item) {
656                 ERR("Target is null");
657                 return;
658         }
659
660         ad = quickpanel_get_app_data();
661         if (!ad) {
662                 ERR("ad is null");
663                 return;
664         }
665
666         _viewer_set_size(item, ad, vi->extra_flag_1, vi->extra_flag_2);
667         quickpanel_uic_initial_resize(item,
668                         (vi->extra_flag_2 > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
669                         ? vi->extra_flag_2 : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
670 }
671
672 static void _anim_job_resize(void *data)
673 {
674         Elm_Transit *transit_layout_parent;
675         struct _viewer_item *viewer_item;
676         Elm_Transit *transit_fadein;
677         struct appdata *ad;
678         Evas_Object *item;
679         int to_w, to_h;
680         QP_VI *vi;
681
682         vi = data;
683         ad = quickpanel_get_app_data();
684         if (!ad || !vi || !vi->target || !vi->extra_data_2) {
685                 ERR("Invalid parameters: %p %p %p %p", ad, vi, vi ? vi->target : NULL, vi ? vi->extra_data_2 : NULL);
686                 return;
687         }
688
689         item = vi->target;
690         to_w = vi->extra_flag_1;
691         to_h = vi->extra_flag_2;
692         viewer_item = vi->extra_data_2;
693
694         transit_layout_parent = quickpanel_list_util_get_reorder_transit(viewer_item->viewer, NULL, to_h - viewer_item->height);
695         if (transit_layout_parent != NULL) {
696                 elm_transit_del_cb_set(transit_layout_parent, _reorder_transit_del_cb, vi);
697         } else {
698                 _viewer_set_size(item, ad, to_w, to_h);
699                 quickpanel_uic_initial_resize(item,
700                                 (to_h > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
701                                 ? to_h : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
702         }
703
704         transit_fadein = elm_transit_add();
705         if (transit_fadein != NULL) {
706                 elm_transit_object_add(transit_fadein, item);
707                 elm_transit_effect_color_add(transit_fadein, 0, 0, 0, 0, 255, 255, 255, 255);
708                 elm_transit_duration_set(transit_fadein, 0.35);
709                 elm_transit_tween_mode_set(transit_fadein, quickpanel_vim_get_tweenmode(VI_OP_INSERT));
710                 elm_transit_del_cb_set(transit_fadein, quickpanel_vi_done_cb_for_transit, vi);
711                 elm_transit_objects_final_state_keep_set(transit_fadein, EINA_TRUE);
712
713                 if (transit_layout_parent != NULL) {
714                         elm_transit_chain_transit_add(transit_layout_parent, transit_fadein);
715                         elm_transit_go(transit_layout_parent);
716                 } else {
717                         elm_transit_go(transit_fadein);
718                 }
719         } else {
720                 ERR("Failed to create all the transit");
721                 quickpanel_vi_done(vi);
722         }
723 }
724
725 static Eina_Bool _anim_job_cb(void *data)
726 {
727         QP_VI *vi;
728         int i;
729         static qp_vi_op_table anim_job_table[] = {
730                 {
731                         .op_type = VI_OP_RESIZE,
732                         .handler = _anim_job_resize,
733                 },
734                 {
735                         .op_type = VI_OP_NONE,
736                         .handler = NULL,
737                 },
738         };
739
740         vi = data;
741         if (!vi) {
742                 ERR("Invalid parameter");
743                 return EINA_FALSE;
744         }
745
746         for (i = 0; anim_job_table[i].op_type != VI_OP_NONE; i++) {
747                 if (anim_job_table[i].op_type != vi->op_type) {
748                         continue;
749                 }
750
751                 anim_job_table[i].handler(vi);
752                 break;
753         }
754
755         return EINA_TRUE;
756 }
757
758 static void _anim_done_resize(void *data)
759 {
760         QP_VI *vi;
761         struct _viewer_item *viewer_item;
762         struct appdata *ad;
763         Evas_Object *item;
764
765         vi = data;
766         if (!vi) {
767                 ERR("Invalid parameter");
768                 return;
769         }
770
771         ad = quickpanel_get_app_data();
772         if (!ad) {
773                 ERR("Invalid ad");
774                 return;
775         }
776
777         item = vi->target;
778         if (!item) {
779                 ERR("Invalid target");
780                 return;
781         }
782
783         viewer_item = vi->extra_data_2;
784         if (!viewer_item) {
785                 ERR("viewer_item is null");
786                 return;
787         }
788
789         viewer_item->width = vi->extra_flag_1;
790         viewer_item->height = vi->extra_flag_2;
791
792         _viewer_set_size(item, ad, viewer_item->width, viewer_item->height);
793         quickpanel_uic_initial_resize(item,
794                         (viewer_item->height > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
795                         ? viewer_item->height : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
796         evas_object_color_set(item, 255, 255, 255, 255);
797 }
798
799 static Eina_Bool _anim_done_cb(void *data)
800 {
801         QP_VI *vi;
802         int i;
803         static qp_vi_op_table anim_done_table[] = {
804                 {
805                         .op_type = VI_OP_RESIZE,
806                         .handler = _anim_done_resize,
807                 },
808                 {
809                         .op_type = VI_OP_NONE,
810                         .handler = NULL,
811                 },
812         };
813
814         vi = data;
815         if (!vi) {
816                 ERR("Invalid parameter");
817                 return EINA_FALSE;
818         }
819
820         for (i = 0; anim_done_table[i].op_type != VI_OP_NONE; i++) {
821                 if (anim_done_table[i].op_type != vi->op_type) {
822                         continue;
823                 }
824
825                 anim_done_table[i].handler(vi);
826                 break;
827         }
828
829         return EINA_TRUE;
830 }
831
832 static void _minictrl_resize_vi(Evas_Object *list, struct _viewer_item *item, int to_w, int to_h)
833 {
834         QP_VI *vi;
835
836         if (!list || !item) {
837                 ERR("Invalid parameter: list: %p, item: %p", list, item);
838                 return;
839         }
840
841         vi = quickpanel_vi_new_with_data(
842                         VI_OP_RESIZE,
843                         QP_ITEM_TYPE_MINICTRL_MIDDLE,
844                         list,
845                         item->viewer,
846                         _anim_init_cb,
847                         _anim_job_cb,
848                         _anim_done_cb,
849                         _anim_done_cb,
850                         NULL, /* vi == NULL */
851                         item,
852                         to_w,
853                         to_h);
854
855         if (vi) {
856                 quickpanel_vi_start(vi);
857         } else {
858                 ERR("Unable to create 'vi'");
859         }
860 }
861
862 static void _minictrl_update(const char *name, unsigned int width, unsigned int height, void *data)
863 {
864         struct appdata *ad = data;
865         struct _viewer_item *found = NULL;
866
867         if (!s_info.prov_table || !ad) {
868                 ERR("name: %s, table: %p, ad: %p", name, s_info.prov_table, ad);
869                 return;
870         }
871
872         found = g_hash_table_lookup(s_info.prov_table, name);
873         if (!found) {
874                 WARN("unknown provider name : %s", name);
875                 return;
876         }
877
878         if (found->viewer) {
879                 if (found->height != height || found->width != width) {
880                         _minictrl_resize_vi(ad->list, found, width, height);
881                 } else {
882                         _viewer_set_size(found->viewer, ad, width, height);
883                         quickpanel_uic_initial_resize(found->viewer,
884                                         (height > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
885                                         ? height : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
886                 }
887         }
888 }
889
890 #if defined(WINSYS_X11)
891 static void _minictrl_lock(const char *name)
892 {
893         struct _viewer_item *found;
894
895         if (!s_info.prov_table) {
896                 ERR("table is empty: %s", name);
897                 return;
898         }
899
900         DBG("minictrl_lock %s", name);
901         found = g_hash_table_lookup(s_info.prov_table, name);
902         if (!found) {
903                 WARN("unknown provider name : %s", name);
904                 return;
905         }
906
907         if (found->viewer) {
908                 struct _viewer_item *vit;
909
910                 vit = evas_object_data_del(_get_minictrl_obj(found->viewer), MINICONTROL_VIEW_DATA);
911                 if (vit) {
912                         vit->deletable = 0;
913                         evas_object_data_set(_get_minictrl_obj(found->viewer), MINICONTROL_VIEW_DATA, vit);
914                 } else {
915                         WARN("vit is NULL");
916                 }
917         }
918 }
919 #endif
920
921 static void _mctrl_viewer_event_cb(minicontrol_event_e event, const char *name, bundle *event_arg, void *data)
922 {
923         struct appdata *ad;
924         int ret;
925         int *width;
926         int *height;
927         int _width;
928         int _height;
929         size_t bundle_size;
930
931         if (!data || !name) {
932                 ERR("Invalid parameter");
933                 return;
934         }
935
936         ad = data;
937
938         if (_viewer_check(name) == 0) {
939                 ERR("%s: ignored", name);
940                 return;
941         }
942
943 #if defined(WINSYS_X11)
944
945         if ((int)event == MINICONTROL_EVENT_REQUEST_LOCK) {
946                 /**
947                  * This event type is extra one. not in the enumeration list.
948                  */
949                 _minictrl_lock(name);
950         } else {
951 #endif  
952                 switch (event) {
953                 case MINICONTROL_EVENT_START:
954                         ret = bundle_get_byte(event_arg, MINICONTROL_BUNDLE_KEY_WIDTH, (void **)&width, &bundle_size);
955                         if (ret != BUNDLE_ERROR_NONE || bundle_size != sizeof(int)) {
956                                 ERR("Failed to get bundle value(width) %d : %d", ret, bundle_size);
957                                 _width = 0;
958                                 width = &_width;
959                         }
960
961                         ret = bundle_get_byte(event_arg, MINICONTROL_BUNDLE_KEY_HEIGHT, (void **)&height, &bundle_size);
962                         if (ret != BUNDLE_ERROR_NONE || bundle_size != sizeof(int)) {
963                                 ERR("Failed to get bundle value(height) : %d", ret);
964                                 _height = 0;
965                                 height = &_height;
966                         }
967
968                         DBG("Name: %s, Size: %dx%d", name, *width, *height);
969                         _minictrl_add(name, *width, *height, data);
970                         break;
971                 case MINICONTROL_EVENT_RESIZE:
972                         ret = bundle_get_byte(event_arg, MINICONTROL_BUNDLE_KEY_WIDTH, (void **)&width, &bundle_size);
973                         if (ret != BUNDLE_ERROR_NONE || bundle_size != sizeof(int)) {
974                                 ERR("Failed to get bundle value(width) %d : %d", ret, bundle_size);
975                                 _width = 0;
976                                 width = &_width;
977                         }
978
979                         ret = bundle_get_byte(event_arg, MINICONTROL_BUNDLE_KEY_HEIGHT, (void **)&height, &bundle_size);
980                         if (ret != BUNDLE_ERROR_NONE || bundle_size != sizeof(int)) {
981                                 ERR("Failed to get bundle value(height) : %d", ret);
982                                 _height = 0;
983                                 height = &_height;
984                         }
985
986                         DBG("Name: %s, Size: %dx%d", name, *width, *height);
987                         _minictrl_update(name, *width, *height, data);
988                         break;
989                 case MINICONTROL_EVENT_STOP:
990                         _minictrl_remove(name, data);
991                         break;
992                 case MINICONTROL_EVENT_REQUEST_HIDE:
993                         quickpanel_uic_close_quickpanel(true, 0);
994                         break;
995                 case MINICONTROL_EVENT_REQUEST_ANGLE:
996                         if (ad->list != NULL) {
997                                 SERR("need to broadcasting angle by %s ", name, event);
998                                 _minictrl_sendview_rotation_event(name, ad->angle);
999                         }
1000                         break;
1001                 default:
1002                         break;
1003                 }
1004 #if defined(WINSYS_X11)
1005         }
1006 #endif  
1007 }
1008
1009 static int _init(void *data)
1010 {
1011         minicontrol_error_e ret;
1012
1013         if (!data) {
1014                 ERR("Invalid parameter");
1015                 return QP_FAIL;
1016         }
1017
1018         s_info.prov_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1019                         (GDestroyNotify)g_free,
1020                         (GDestroyNotify)_viewer_item_free);
1021
1022         ret = minicontrol_viewer_set_event_cb(_mctrl_viewer_event_cb, data);
1023         if (ret != MINICONTROL_ERROR_NONE) {
1024                 ERR("fail to minicontrol_viewer_set_event_cb()- %d", ret);
1025                 return QP_FAIL;
1026         }
1027
1028         return QP_OK;
1029 }
1030
1031 static int _fini(void *data)
1032 {
1033         minicontrol_error_e ret;
1034
1035         ret = minicontrol_viewer_unset_event_cb();
1036
1037         if (ret != MINICONTROL_ERROR_NONE) {
1038                 ERR("fail to minicontrol_viewer_unset_event_cb()- %d", ret);
1039         }
1040
1041         if (s_info.prov_table) {
1042                 g_hash_table_destroy(s_info.prov_table);
1043                 s_info.prov_table = NULL;
1044         }
1045
1046         return QP_OK;
1047 }
1048
1049 static int _suspend(void *data)
1050 {
1051         struct appdata *ad;
1052
1053         ad = data;
1054         if (!ad) {
1055                 ERR("Invalid parameter");
1056                 return QP_FAIL;
1057         }
1058
1059         if (ad->list != NULL) {
1060                 _viewer_unfreeze(ad->scroller);
1061         }
1062
1063         return QP_OK;
1064 }
1065
1066 static int _resume(void *data)
1067 {
1068         struct appdata *ad;
1069
1070         ad = data;
1071         if (!ad) {
1072                 ERR("Invalid parameter");
1073                 return QP_FAIL;
1074         }
1075
1076         if (ad->list != NULL) {
1077                 _viewer_unfreeze(ad->scroller);
1078         }
1079
1080         return QP_OK;
1081 }
1082
1083 HAPI void quickpanel_minictrl_rotation_report(int angle)
1084 {
1085         bundle *event_arg_bundle;
1086
1087         if (s_info.prov_table == NULL) {
1088                 return;
1089         }
1090
1091         if (g_hash_table_size(s_info.prov_table) <= 0) {
1092                 return;
1093         }
1094
1095         GHashTableIter iter;
1096         gpointer key, value;
1097
1098         g_hash_table_iter_init (&iter, s_info.prov_table);
1099         while (g_hash_table_iter_next (&iter, &key, &value))
1100         {
1101                 SINFO("minicontrol name:%s rotation:%d", key, angle);
1102                 event_arg_bundle = bundle_create();
1103                 if (event_arg_bundle) {
1104                         char bundle_value_buffer[BUNDLE_BUFFER_LENGTH] = { 0, };
1105                         snprintf(bundle_value_buffer, sizeof(bundle_value_buffer) - 1, "%d", angle);
1106                         bundle_add_str(event_arg_bundle, "angle", bundle_value_buffer);
1107                         minicontrol_viewer_send_event(key, MINICONTROL_EVENT_REPORT_ANGLE, event_arg_bundle);
1108                         bundle_free(event_arg_bundle);
1109                 }
1110         }
1111 }
1112
1113 void _minictrl_sendview_rotation_event(const char* name, int angle)
1114 {
1115         bundle *event_arg_bundle;
1116
1117         if (!name) {
1118                 ERR("Invalid parameter");
1119                 return;
1120         }
1121
1122         if (s_info.prov_table == NULL) {
1123                 return;
1124         }
1125
1126         if (g_hash_table_size(s_info.prov_table) <= 0) {
1127                 return;
1128         }
1129
1130         SINFO("minicontrol name:%s rotation:%d", name, angle);
1131         event_arg_bundle = bundle_create();
1132         if (event_arg_bundle) {
1133                 char bundle_value_buffer[BUNDLE_BUFFER_LENGTH] = { 0, };
1134
1135                 snprintf(bundle_value_buffer, sizeof(bundle_value_buffer) - 1, "%d", angle);
1136                 bundle_add_str(event_arg_bundle, "angle", bundle_value_buffer);
1137                 minicontrol_viewer_send_event(name, MINICONTROL_EVENT_REPORT_ANGLE, event_arg_bundle);
1138                 bundle_free(event_arg_bundle);
1139         }
1140 }
1141
1142 #if defined(WINSYS_X11)
1143 static void _minictrl_send_view_event_cb(gpointer key, gpointer value, gpointer user_data)
1144 {
1145         if (!key) {
1146                 ERR("Key is null");
1147                 return;
1148         }
1149
1150         bundle *event_arg_bundle;
1151
1152         event_arg_bundle = bundle_create();
1153         if (event_arg_bundle) {
1154                 minicontrol_viewer_event_e event;
1155
1156                 event = (minicontrol_viewer_event_e)user_data;
1157                 minicontrol_viewer_send_event(key, event, event_arg_bundle);
1158                 bundle_free(event_arg_bundle);
1159         }
1160 }
1161 #endif
1162
1163 static void _minictrl_opened(void *data)
1164 {
1165         DBG("");
1166 #if defined(WINSYS_X11)
1167         g_hash_table_foreach(s_info.prov_table, _minictrl_send_view_event_cb, (gpointer)MINICONTROL_VIEWER_EVENT_SHOW);
1168 #endif
1169 }
1170
1171 static void _minictrl_closed(void *data)
1172 {
1173         DBG("");
1174 #if defined(WINSYS_X11)
1175         g_hash_table_foreach(s_info.prov_table, _minictrl_send_view_event_cb, (gpointer)MINICONTROL_VIEWER_EVENT_HIDE);
1176 #endif
1177 }
1178
1179 QP_Module minictrl = {
1180         .name = "minictrl",
1181         .init = _init,
1182         .fini = _fini,
1183         .suspend = _suspend,
1184         .resume = _resume,
1185         .hib_enter = NULL,
1186         .hib_leave = NULL,
1187         .lang_changed = NULL,
1188         .refresh = NULL,
1189         .get_height = NULL,
1190         .qp_opened = _minictrl_opened,
1191         .qp_closed = _minictrl_closed,
1192 };
1193
1194 /* End of a file */