2 * Copyright (c) 2009-2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <minicontrol-viewer.h>
22 #include <minicontrol-monitor.h>
25 #include "quickpanel-ui.h"
26 #include "quickpanel_def.h"
27 #include "list_util.h"
28 #include "quickpanel_debug_util.h"
29 #ifdef QP_SCREENREADER_ENABLE
30 #include "accessibility.h"
33 #include "vi_manager.h"
35 #define MINICONTROL_TYPE_STR_VIEWER "::[viewer="
36 #define MINICONTROL_TYPE_STR_QUICKPANEL "QUICKPANEL"
37 #define MINICONTROL_TYPE_STR_LOCKSCREEN "LOCKSCREEN"
38 #define MINICONTROL_TYPE_STR_ONGOING "_ongoing]"
40 static Eina_Bool _anim_init_cb(void *data);
41 static Eina_Bool _anim_job_cb(void *data);
42 static Eina_Bool _anim_done_cb(void *data);
43 static int quickpanel_minictrl_init(void *data);
44 static int quickpanel_minictrl_fini(void *data);
45 static int quickpanel_minictrl_suspend(void *data);
46 static int quickpanel_minictrl_resume(void *data);
48 QP_Module minictrl = {
50 .init = quickpanel_minictrl_init,
51 .fini = quickpanel_minictrl_fini,
52 .suspend = quickpanel_minictrl_suspend,
53 .resume = quickpanel_minictrl_resume,
65 minicontrol_priority_e priority;
70 static void _minictrl_resize_vi(Evas_Object *list,
71 struct _viewer_item *item, int to_w, int to_h);
73 GHashTable *g_prov_table;
75 static int _viewer_check(const char *name)
77 char *pos_start = NULL;
78 retif(!name, 0, "name is NULL");
80 if ((pos_start = strstr(name, MINICONTROL_TYPE_STR_VIEWER)) != NULL) {
81 if (strstr(pos_start, MINICONTROL_TYPE_STR_QUICKPANEL) != NULL) {
86 } else if (strstr(name, MINICONTROL_TYPE_STR_LOCKSCREEN) != NULL) {
93 static void _viewer_freeze(Evas_Object *viewer)
95 int freezed_count = 0;
96 retif(viewer == NULL, , "Invalid parameter!");
98 freezed_count = elm_object_scroll_freeze_get(viewer);
100 if (freezed_count <= 0) {
101 elm_object_scroll_freeze_push(viewer);
105 static void _viewer_unfreeze(Evas_Object *viewer)
107 int i = 0, freezed_count = 0;
108 retif(viewer == NULL, , "Invalid parameter!");
110 freezed_count = elm_object_scroll_freeze_get(viewer);
112 for (i = 0 ; i < freezed_count; i++) {
113 elm_object_scroll_freeze_pop(viewer);
117 static Evas_Object *_get_minictrl_obj(Evas_Object *layout) {
118 retif(layout == NULL, NULL, "Invalid parameter!");
120 return elm_object_part_content_get(layout, "elm.icon");
123 static void _viewer_set_size(Evas_Object *layout, void *data, int width, int height)
125 Evas_Object *viewer = NULL;
126 retif(layout == NULL, , "Invalid parameter!");
127 retif(data == NULL, , "Invalid parameter!");
128 retif(width < 0, , "Invalid parameter!");
129 retif(height < 0, , "Invalid parameter!");
130 struct appdata *ad = data;
132 int resized_width = 0;
133 int is_landscape = 0;
135 viewer = _get_minictrl_obj(layout);
136 retif(viewer == NULL, , "Invalid parameter!");
138 is_landscape = (width > ad->win_width) ? 1 : 0;
141 max_width = (ad->scale * ad->win_height);
143 max_width = (ad->scale * ad->win_width);
145 resized_width = (width > max_width) ? max_width : width;
147 SERR("minicontroller view is resized to w:%d(%d) h:%d Landscape[%d]", resized_width, width, height, is_landscape);
149 evas_object_size_hint_min_set(viewer, resized_width, height);
150 evas_object_size_hint_max_set(viewer, resized_width, height);
153 static void _viewer_item_free(struct _viewer_item *item)
155 struct appdata *ad = quickpanel_get_app_data();
156 retif(ad == NULL, , "Invalid parameter!");
157 retif(ad->list == NULL, , "Invalid parameter!");
158 retif(item == NULL, , "Invalid parameter!");
164 quickpanel_list_util_item_unpack_by_object(ad->list, item->viewer, 0, 0);
165 quickpanel_list_util_item_del_tag(item->viewer);
166 if (item->viewer != NULL) {
167 evas_object_del(item->viewer);
175 static Evas_Object *_minictrl_create_view(struct appdata *ad, const char *name)
177 retif(ad == NULL, NULL, "Invalid parameter!");
178 retif(ad->list == NULL, NULL, "Invalid parameter!");
179 retif(name == NULL, NULL, "Invalid parameter!");
181 Evas_Object *layout = NULL;
183 layout = elm_layout_add(ad->list);
185 elm_layout_file_set(layout, DEFAULT_EDJ,
186 "quickpanel/minictrl/default");
188 evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
189 evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
190 evas_object_show(layout);
192 Evas_Object *viewer = minicontrol_viewer_add(layout, name);
195 ERR("fail to add viewer - %s", name);
198 evas_object_del(layout);
202 elm_object_focus_allow_set(viewer, EINA_TRUE);
203 elm_object_part_content_set(layout, "elm.icon", viewer);
205 Evas_Object *focus = quickpanel_ui_get_focus_object(layout);
206 elm_object_part_content_set(layout, "focus", focus);
208 #ifdef QP_SCREENREADER_ENABLE
209 Evas_Object *ao = quickpanel_screen_reader_object_get(layout,
210 SCREEN_READER_OBJ_TYPE_ELM_OBJECT, "focus", layout);
213 elm_access_info_cb_set(ao, ELM_ACCESS_TYPE, quickpanel_access_info_cb,
214 _NOT_LOCALIZED("Mini controller"));
221 static int _minictrl_is_ongoing(const char *str)
223 if (str == NULL) return 0;
225 if (strstr(str, MINICONTROL_TYPE_STR_ONGOING) != NULL) {
232 static qp_item_type_e _minictrl_priority_to_type(minicontrol_priority_e priority)
237 case MINICONTROL_PRIORITY_TOP:
238 type = QP_ITEM_TYPE_MINICTRL_TOP;
240 case MINICONTROL_PRIORITY_MIDDLE:
241 type = QP_ITEM_TYPE_MINICTRL_MIDDLE;
243 case MINICONTROL_PRIORITY_LOW:
245 type = QP_ITEM_TYPE_MINICTRL_LOW;
252 static void _minictrl_release_cb(void *data, Evas *e,
253 Evas_Object *obj, void *event_info) {
255 retif(!data, , "data is NULL");
258 _viewer_unfreeze(ad->scroller);
261 static void _minictrl_add(const char *name, unsigned int width,
263 minicontrol_priority_e priority,
266 qp_item_data *qid = NULL;
267 struct _viewer_item *vit = NULL;
270 Evas_Object *viewer = NULL;
272 retif(!name, , "name is NULL");
273 retif(!data, , "data is NULL");
276 retif(!ad->list, , "list is NULL");
279 struct _viewer_item *found = NULL;
280 found = g_hash_table_lookup(g_prov_table, name);
283 ERR("already have it : %s", name);
287 ERR("g_prov_table is NULL");
291 /* elm_plug receives 'server_del' event,
292 * if it repeats connect and disconnect frequently.
295 viewer = _minictrl_create_view(ad, name);
298 ERR("Failed to create view[%s]", name);
301 _viewer_set_size(viewer, ad, width, height);
302 quickpanel_initial_resize(viewer,
303 (height > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
304 ? height : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
306 evas_object_event_callback_add(_get_minictrl_obj(viewer), EVAS_CALLBACK_MOUSE_UP,
307 _minictrl_release_cb, ad);
309 vit = malloc(sizeof(struct _viewer_item));
311 ERR("fail to alloc vit");
312 if (viewer != NULL) {
313 evas_object_del(viewer);
319 if (_minictrl_is_ongoing(name) == 1) {
320 type = QP_ITEM_TYPE_MINICTRL_ONGOING;
322 type = _minictrl_priority_to_type(priority);
324 qid = quickpanel_list_util_item_new(type, vit);
326 ERR("fail to alloc vit");
327 if (viewer != NULL) {
328 evas_object_del(viewer);
334 vit->name = strdup(name);
336 vit->height = height;
337 vit->priority = priority;
338 vit->viewer = viewer;
340 quickpanel_list_util_item_set_tag(vit->viewer, qid);
341 quickpanel_list_util_sort_insert(ad->list, vit->viewer);
343 g_hash_table_insert(g_prov_table, g_strdup(name), vit);
345 DBG("success to add minicontrol %s", name);
346 quickpanel_minictrl_rotation_report(ad->angle);
349 static void _minictrl_remove(const char *name, void *data)
352 if (g_hash_table_remove(g_prov_table, name))
354 DBG("success to remove %s", name);
356 retif(data == NULL, , "data is NULL");
359 WARN("unknown provider name : %s", name);
363 static void _minictrl_update(const char *name, unsigned int width,
364 unsigned int height, void *data)
367 struct appdata *ad = data;
368 struct _viewer_item *found = NULL;
370 retif(!g_prov_table, , "data is NULL");
371 retif(!ad, , "data is NULL");
373 found = g_hash_table_lookup(g_prov_table, name);
376 WARN("unknown provider name : %s", name);
380 old_h = found->height;
383 if (old_h != height) {
384 _minictrl_resize_vi(ad->list,
385 found, width, height);
387 _viewer_set_size(found->viewer, ad, width, height);
388 quickpanel_initial_resize(found->viewer,
389 (height > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
390 ? height : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
395 static void _minictrl_request(const char *name, int action, int value, void *data)
397 struct appdata *ad = data;
398 retif(!name, , "name is NULL");
399 retif(!ad, , "data is NULL");
401 SDBG("%s %d %d", name, action, value);
403 if (action == MINICONTROL_REQ_HIDE_VIEWER) {
404 quickpanel_close_quickpanel(true, 0);
405 } else if (action == MINICONTROL_REQ_FREEZE_SCROLL_VIEWER) {
406 if (ad->list != NULL) {
407 ERR("freezed by %s", name);
408 _viewer_freeze(ad->scroller);
410 } else if (action == MINICONTROL_REQ_UNFREEZE_SCROLL_VIEWER) {
411 if (ad->list != NULL) {
412 ERR("unfreezed by %s", name);
413 _viewer_unfreeze(ad->scroller);
415 } else if (action == MINICONTROL_REQ_REPORT_VIEWER_ANGLE) {
416 if (ad->list != NULL) {
417 SERR("need to broadcasting angle by %s %d", name, action);
418 quickpanel_minictrl_rotation_report(ad->angle);
423 static void _mctrl_monitor_cb(minicontrol_action_e action,
424 const char *name, unsigned int width,
426 minicontrol_priority_e priority,
429 retif(!data, , "data is NULL");
430 retif(!name, , "name is NULL");
432 if (_viewer_check(name) == 0) {
433 ERR("%s: ignored", name);
438 case MINICONTROL_ACTION_START:
439 _minictrl_add(name, width, height, priority, data);
441 case MINICONTROL_ACTION_RESIZE:
442 _minictrl_update(name, width, height, data);
444 case MINICONTROL_ACTION_STOP:
445 _minictrl_remove(name, data);
447 case MINICONTROL_ACTION_REQUEST:
448 _minictrl_request(name, width, height, data);
455 static void _minictrl_resize_vi(Evas_Object *list,
456 struct _viewer_item *item, int to_w, int to_h)
459 retif(list == NULL, , "invalid parameter");
460 retif(item == NULL, , "invalid parameter");
462 vi = quickpanel_vi_new_with_data(
464 QP_ITEM_TYPE_MINICTRL_MIDDLE,
475 quickpanel_vi_start(vi);
478 static void _anim_init_resize(void *data) {
480 retif(vi == NULL, , "invalid parameter");
481 retif(vi->target == NULL, , "invalid parameter");
483 Evas_Object *item = vi->target;
484 evas_object_color_set(item, 0, 0, 0, 0);
487 void _reorder_transit_del_cb(void *data, Elm_Transit *transit) {
489 int to_w = 0, to_h = 0;
490 Evas_Object *item = NULL;
491 retif(vi == NULL, , "data is NULL");
492 retif(vi->target == NULL, , "invalid parameter");
495 to_w = vi->extra_flag_1;
496 to_h = vi->extra_flag_2;
498 struct appdata *ad = quickpanel_get_app_data();
499 retif(ad == NULL, , "Invalid parameter!");
501 _viewer_set_size(item, ad, to_w, to_h);
502 quickpanel_initial_resize(item,
503 (to_h > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
504 ? to_h : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
507 static void _anim_job_resize(void *data) {
509 int to_w = 0, to_h = 0;
510 Elm_Transit *transit_layout_parent = NULL;
511 Elm_Transit *transit_fadein = NULL;
512 Evas_Object *item = NULL;
513 struct _viewer_item *viewer_item = NULL;
515 struct appdata *ad = quickpanel_get_app_data();
516 retif(ad == NULL, , "Invalid parameter!");
517 retif(vi == NULL, , "invalid parameter");
518 retif(vi->target == NULL, , "invalid parameter");
519 retif(vi->extra_data_2 == NULL, , "invalid parameter");
522 to_w = vi->extra_flag_1;
523 to_h = vi->extra_flag_2;
524 viewer_item = vi->extra_data_2;
526 transit_layout_parent = quickpanel_list_get_reorder_transit(viewer_item->viewer, NULL, to_h - viewer_item->height);
527 if (transit_layout_parent != NULL) {
528 elm_transit_del_cb_set(transit_layout_parent, _reorder_transit_del_cb, vi);
530 _viewer_set_size(item, ad, to_w, to_h);
531 quickpanel_initial_resize(item,
532 (to_h > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
533 ? to_h : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
536 transit_fadein = elm_transit_add();
537 if (transit_fadein != NULL) {
538 elm_transit_object_add(transit_fadein, item);
539 elm_transit_effect_color_add(transit_fadein, 0, 0, 0, 0, 255, 255, 255, 255);
540 elm_transit_duration_set(transit_fadein, 0.35);
541 elm_transit_tween_mode_set(transit_fadein,
542 quickpanel_vim_get_tweenmode(VI_OP_INSERT));
543 elm_transit_del_cb_set(transit_fadein, quickpanel_vi_done_cb_for_transit, vi);
544 elm_transit_objects_final_state_keep_set(transit_fadein, EINA_TRUE);
546 if (transit_layout_parent != NULL) {
547 elm_transit_chain_transit_add(transit_layout_parent, transit_fadein);
548 elm_transit_go(transit_layout_parent);
550 elm_transit_go(transit_fadein);
553 ERR("Failed to create all the transit");
554 quickpanel_vi_done(vi);
558 static void _anim_done_resize(void *data) {
560 struct _viewer_item *viewer_item = NULL;
561 struct appdata *ad = quickpanel_get_app_data();
562 retif(ad == NULL, , "Invalid parameter!");
563 retif(vi == NULL, , "invalid parameter");
564 retif(vi->target == NULL, , "invalid parameter");
566 Evas_Object *item = vi->target;
567 viewer_item = vi->extra_data_2;
569 viewer_item->width = vi->extra_flag_1;
570 viewer_item->height = vi->extra_flag_2;
572 _viewer_set_size(item, ad, viewer_item->width, viewer_item->height);
573 quickpanel_initial_resize(item,
574 (viewer_item->height > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
575 ? viewer_item->height : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
576 evas_object_color_set(item, 255, 255, 255, 255);
579 static Eina_Bool _anim_init_cb(void *data) {
581 retif(vi == NULL, EINA_FALSE, "invalid parameter");
583 static qp_vi_op_table anim_init_table[] = {
585 .op_type = VI_OP_RESIZE,
586 .handler = _anim_init_resize,
589 .op_type = VI_OP_NONE,
595 for (i = 0; anim_init_table[i].op_type != VI_OP_NONE; i++) {
596 if (anim_init_table[i].op_type != vi->op_type)
599 anim_init_table[i].handler(vi);
606 static Eina_Bool _anim_job_cb(void *data) {
608 retif(vi == NULL, EINA_FALSE, "invalid parameter");
610 static qp_vi_op_table anim_job_table[] = {
612 .op_type = VI_OP_RESIZE,
613 .handler = _anim_job_resize,
616 .op_type = VI_OP_NONE,
622 for (i = 0; anim_job_table[i].op_type != VI_OP_NONE; i++) {
623 if (anim_job_table[i].op_type != vi->op_type)
626 anim_job_table[i].handler(vi);
633 static Eina_Bool _anim_done_cb(void *data) {
635 retif(vi == NULL, EINA_FALSE, "invalid parameter");
637 static qp_vi_op_table anim_done_table[] = {
639 .op_type = VI_OP_RESIZE,
640 .handler = _anim_done_resize,
643 .op_type = VI_OP_NONE,
649 for (i = 0; anim_done_table[i].op_type != VI_OP_NONE; i++) {
650 if (anim_done_table[i].op_type != vi->op_type)
653 anim_done_table[i].handler(vi);
660 static int quickpanel_minictrl_init(void *data)
662 minicontrol_error_e ret;
664 retif(!data, QP_FAIL, "Invalid parameter!");
666 g_prov_table = g_hash_table_new_full(g_str_hash, g_str_equal,
667 (GDestroyNotify)g_free,
668 (GDestroyNotify)_viewer_item_free);
670 ret = minicontrol_monitor_start(_mctrl_monitor_cb, data);
671 if (ret != MINICONTROL_ERROR_NONE) {
672 ERR("fail to minicontrol_monitor_start()- %d", ret);
679 static int quickpanel_minictrl_fini(void *data)
681 minicontrol_error_e ret;
682 ret = minicontrol_monitor_stop();
683 if (ret != MINICONTROL_ERROR_NONE)
684 ERR("fail to minicontrol_monitor_stop()- %d", ret);
687 g_hash_table_remove_all(g_prov_table);
694 static int quickpanel_minictrl_suspend(void *data)
696 struct appdata *ad = data;
697 retif(ad == NULL, QP_FAIL, "Invalid parameter!");
699 if (ad->list != NULL) {
700 _viewer_unfreeze(ad->scroller);
706 static int quickpanel_minictrl_resume(void *data)
708 struct appdata *ad = data;
709 retif(ad == NULL, QP_FAIL, "Invalid parameter!");
711 if (ad->list != NULL) {
712 _viewer_unfreeze(ad->scroller);
718 void quickpanel_minictrl_rotation_report(int angle)
720 if (g_prov_table != NULL) {
721 if (g_hash_table_size(g_prov_table) > 0) {
722 SINFO("minicontrol rotation:%d", angle);
723 minicontrol_viewer_request(QP_PKG_QUICKPANEL,
724 MINICONTROL_REQ_ROTATE_PROVIDER, angle);