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.
20 #include <minicontrol-viewer.h>
21 #include <minicontrol-monitor.h>
24 #include "quickpanel-ui.h"
25 #include "quickpanel_def.h"
26 #include "list_util.h"
27 #include "quickpanel_debug_util.h"
28 #ifdef QP_SCREENREADER_ENABLE
29 #include "accessibility.h"
32 #include "vi_manager.h"
34 #define MINICONTROL_TYPE_STR_VIEWER "::[viewer="
35 #define MINICONTROL_TYPE_STR_QUICKPANEL "QUICKPANEL"
36 #define MINICONTROL_TYPE_STR_LOCKSCREEN "LOCKSCREEN"
37 #define MINICONTROL_TYPE_STR_ONGOING "_ongoing]"
39 static Eina_Bool _anim_init_cb(void *data);
40 static Eina_Bool _anim_job_cb(void *data);
41 static Eina_Bool _anim_done_cb(void *data);
42 static int _init(void *data);
43 static int _fini(void *data);
44 static int _suspend(void *data);
45 static int _resume(void *data);
47 QP_Module minictrl = {
64 minicontrol_priority_e priority;
69 static void _minictrl_resize_vi(Evas_Object *list,
70 struct _viewer_item *item, int to_w, int to_h);
72 GHashTable *g_prov_table;
74 static int _viewer_check(const char *name)
76 char *pos_start = NULL;
77 retif(!name, 0, "name is NULL");
79 if ((pos_start = strstr(name, MINICONTROL_TYPE_STR_VIEWER)) != NULL) {
80 if (strstr(pos_start, MINICONTROL_TYPE_STR_QUICKPANEL) != NULL) {
85 } else if (strstr(name, MINICONTROL_TYPE_STR_LOCKSCREEN) != NULL) {
92 static void _viewer_freeze(Evas_Object *viewer)
94 int freezed_count = 0;
95 retif(viewer == NULL, , "Invalid parameter!");
97 freezed_count = elm_object_scroll_freeze_get(viewer);
99 if (freezed_count <= 0) {
100 elm_object_scroll_freeze_push(viewer);
104 static void _viewer_unfreeze(Evas_Object *viewer)
106 int i = 0, freezed_count = 0;
107 retif(viewer == NULL, , "Invalid parameter!");
109 freezed_count = elm_object_scroll_freeze_get(viewer);
111 for (i = 0 ; i < freezed_count; i++) {
112 elm_object_scroll_freeze_pop(viewer);
116 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!");
165 quickpanel_list_util_item_unpack_by_object(ad->list, item->viewer, 0, 0);
166 quickpanel_list_util_item_del_tag(item->viewer);
167 if (item->viewer != NULL) {
168 evas_object_del(item->viewer);
176 static Evas_Object *_minictrl_create_view(struct appdata *ad, const char *name)
178 retif(ad == NULL, NULL, "Invalid parameter!");
179 retif(ad->list == NULL, NULL, "Invalid parameter!");
180 retif(name == NULL, NULL, "Invalid parameter!");
182 Evas_Object *layout = NULL;
184 layout = elm_layout_add(ad->list);
186 elm_layout_file_set(layout, DEFAULT_EDJ,
187 "quickpanel/minictrl/default");
189 evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
190 evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
191 evas_object_show(layout);
193 Evas_Object *viewer = minicontrol_viewer_add(layout, name);
195 ERR("fail to add viewer - %s", name);
197 evas_object_del(layout);
201 elm_object_focus_allow_set(viewer, EINA_TRUE);
202 elm_object_part_content_set(layout, "elm.icon", viewer);
204 Evas_Object *focus = quickpanel_accessibility_ui_get_focus_object(layout);
205 elm_object_part_content_set(layout, "focus", focus);
207 #ifdef QP_SCREENREADER_ENABLE
208 Evas_Object *ao = quickpanel_accessibility_screen_reader_object_get(layout,
209 SCREEN_READER_OBJ_TYPE_ELM_OBJECT, "focus", layout);
212 elm_access_info_cb_set(ao, ELM_ACCESS_TYPE, quickpanel_accessibility_info_cb,
213 _NOT_LOCALIZED("Mini controller"));
220 static int _minictrl_is_ongoing(const char *str)
226 if (strstr(str, MINICONTROL_TYPE_STR_ONGOING) != NULL) {
233 static qp_item_type_e _minictrl_priority_to_type(minicontrol_priority_e priority)
238 case MINICONTROL_PRIORITY_TOP:
239 type = QP_ITEM_TYPE_MINICTRL_TOP;
241 case MINICONTROL_PRIORITY_MIDDLE:
242 type = QP_ITEM_TYPE_MINICTRL_MIDDLE;
244 case MINICONTROL_PRIORITY_LOW:
246 type = QP_ITEM_TYPE_MINICTRL_LOW;
253 static void _minictrl_release_cb(void *data, Evas *e,
254 Evas_Object *obj, void *event_info)
257 retif(!data, , "data is NULL");
260 _viewer_unfreeze(ad->scroller);
263 static void _minictrl_add(const char *name, unsigned int width,
265 minicontrol_priority_e priority,
268 qp_item_data *qid = NULL;
269 struct _viewer_item *vit = NULL;
272 Evas_Object *viewer = NULL;
274 retif(!name, , "name is NULL");
275 retif(!data, , "data is NULL");
278 retif(!ad->list, , "list is NULL");
281 struct _viewer_item *found = NULL;
282 found = g_hash_table_lookup(g_prov_table, name);
285 ERR("already have it : %s", name);
289 ERR("g_prov_table is NULL");
293 /* elm_plug receives 'server_del' event,
294 * if it repeats connect and disconnect frequently.
297 viewer = _minictrl_create_view(ad, name);
299 ERR("Failed to create view[%s]", name);
302 _viewer_set_size(viewer, ad, width, height);
303 quickpanel_uic_initial_resize(viewer,
304 (height > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
305 ? height : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
307 evas_object_event_callback_add(_get_minictrl_obj(viewer), EVAS_CALLBACK_MOUSE_UP,
308 _minictrl_release_cb, ad);
310 vit = malloc(sizeof(struct _viewer_item));
312 ERR("fail to alloc vit");
313 if (viewer != NULL) {
314 evas_object_del(viewer);
320 if (_minictrl_is_ongoing(name) == 1) {
321 type = QP_ITEM_TYPE_MINICTRL_ONGOING;
323 type = _minictrl_priority_to_type(priority);
325 qid = quickpanel_list_util_item_new(type, vit);
327 ERR("fail to alloc vit");
328 if (viewer != NULL) {
329 evas_object_del(viewer);
335 vit->name = strdup(name);
337 vit->height = height;
338 vit->priority = priority;
339 vit->viewer = viewer;
341 quickpanel_list_util_item_set_tag(vit->viewer, qid);
342 quickpanel_list_util_sort_insert(ad->list, vit->viewer);
344 g_hash_table_insert(g_prov_table, g_strdup(name), vit);
346 DBG("success to add minicontrol %s", name);
347 quickpanel_minictrl_rotation_report(ad->angle);
350 static void _minictrl_remove(const char *name, void *data)
353 if (g_hash_table_remove(g_prov_table, name)) {
354 DBG("success to remove %s", name);
356 retif(data == NULL, , "data is NULL");
358 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_uic_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_uic_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);
417 else if (action == MINICONTROL_REQ_REPORT_VIEWER_ANGLE) {
418 if (ad->list != NULL) {
419 SERR("need to broadcasting angle by %s %d", name, action);
420 quickpanel_minictrl_rotation_report(ad->angle);
426 static void _mctrl_monitor_cb(minicontrol_action_e action,
427 const char *name, unsigned int width,
429 minicontrol_priority_e priority,
432 retif(!data, , "data is NULL");
433 retif(!name, , "name is NULL");
435 if (_viewer_check(name) == 0) {
436 ERR("%s: ignored", name);
441 case MINICONTROL_ACTION_START:
442 _minictrl_add(name, width, height, priority, data);
444 case MINICONTROL_ACTION_RESIZE:
445 _minictrl_update(name, width, height, data);
447 case MINICONTROL_ACTION_STOP:
448 _minictrl_remove(name, data);
450 case MINICONTROL_ACTION_REQUEST:
451 _minictrl_request(name, width, height, data);
458 static void _minictrl_resize_vi(Evas_Object *list,
459 struct _viewer_item *item, int to_w, int to_h)
462 retif(list == NULL, , "invalid parameter");
463 retif(item == NULL, , "invalid parameter");
465 vi = quickpanel_vi_new_with_data(
467 QP_ITEM_TYPE_MINICTRL_MIDDLE,
478 quickpanel_vi_start(vi);
481 static void _anim_init_resize(void *data)
484 retif(vi == NULL, , "invalid parameter");
485 retif(vi->target == NULL, , "invalid parameter");
487 Evas_Object *item = vi->target;
488 evas_object_color_set(item, 0, 0, 0, 0);
491 static void _reorder_transit_del_cb(void *data, Elm_Transit *transit)
494 int to_w = 0, to_h = 0;
495 Evas_Object *item = NULL;
496 retif(vi == NULL, , "data is NULL");
497 retif(vi->target == NULL, , "invalid parameter");
500 to_w = vi->extra_flag_1;
501 to_h = vi->extra_flag_2;
503 struct appdata *ad = quickpanel_get_app_data();
504 retif(ad == NULL, , "Invalid parameter!");
506 _viewer_set_size(item, ad, to_w, to_h);
507 quickpanel_uic_initial_resize(item,
508 (to_h > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
509 ? to_h : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
512 static void _anim_job_resize(void *data)
515 int to_w = 0, to_h = 0;
516 Elm_Transit *transit_layout_parent = NULL;
517 Elm_Transit *transit_fadein = NULL;
518 Evas_Object *item = NULL;
519 struct _viewer_item *viewer_item = NULL;
521 struct appdata *ad = quickpanel_get_app_data();
522 retif(ad == NULL, , "Invalid parameter!");
523 retif(vi == NULL, , "invalid parameter");
524 retif(vi->target == NULL, , "invalid parameter");
525 retif(vi->extra_data_2 == NULL, , "invalid parameter");
528 to_w = vi->extra_flag_1;
529 to_h = vi->extra_flag_2;
530 viewer_item = vi->extra_data_2;
532 transit_layout_parent = quickpanel_list_util_get_reorder_transit(viewer_item->viewer, NULL, to_h - viewer_item->height);
533 if (transit_layout_parent != NULL) {
534 elm_transit_del_cb_set(transit_layout_parent, _reorder_transit_del_cb, vi);
536 _viewer_set_size(item, ad, to_w, to_h);
537 quickpanel_uic_initial_resize(item,
538 (to_h > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
539 ? to_h : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
542 transit_fadein = elm_transit_add();
543 if (transit_fadein != NULL) {
544 elm_transit_object_add(transit_fadein, item);
545 elm_transit_effect_color_add(transit_fadein, 0, 0, 0, 0, 255, 255, 255, 255);
546 elm_transit_duration_set(transit_fadein, 0.35);
547 elm_transit_tween_mode_set(transit_fadein,
548 quickpanel_vim_get_tweenmode(VI_OP_INSERT));
549 elm_transit_del_cb_set(transit_fadein, quickpanel_vi_done_cb_for_transit, vi);
550 elm_transit_objects_final_state_keep_set(transit_fadein, EINA_TRUE);
552 if (transit_layout_parent != NULL) {
553 elm_transit_chain_transit_add(transit_layout_parent, transit_fadein);
554 elm_transit_go(transit_layout_parent);
556 elm_transit_go(transit_fadein);
559 ERR("Failed to create all the transit");
560 quickpanel_vi_done(vi);
564 static void _anim_done_resize(void *data)
567 struct _viewer_item *viewer_item = NULL;
568 struct appdata *ad = quickpanel_get_app_data();
569 retif(ad == NULL, , "Invalid parameter!");
570 retif(vi == NULL, , "invalid parameter");
571 retif(vi->target == NULL, , "invalid parameter");
573 Evas_Object *item = vi->target;
574 viewer_item = vi->extra_data_2;
576 viewer_item->width = vi->extra_flag_1;
577 viewer_item->height = vi->extra_flag_2;
579 _viewer_set_size(item, ad, viewer_item->width, viewer_item->height);
580 quickpanel_uic_initial_resize(item,
581 (viewer_item->height > QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT)
582 ? viewer_item->height : QP_THEME_LIST_ITEM_MINICONTRL_HEIGHT + QP_THEME_LIST_ITEM_SEPERATOR_HEIGHT);
583 evas_object_color_set(item, 255, 255, 255, 255);
586 static Eina_Bool _anim_init_cb(void *data)
589 retif(vi == NULL, EINA_FALSE, "invalid parameter");
591 static qp_vi_op_table anim_init_table[] = {
593 .op_type = VI_OP_RESIZE,
594 .handler = _anim_init_resize,
597 .op_type = VI_OP_NONE,
603 for (i = 0; anim_init_table[i].op_type != VI_OP_NONE; i++) {
604 if (anim_init_table[i].op_type != vi->op_type) {
608 anim_init_table[i].handler(vi);
615 static Eina_Bool _anim_job_cb(void *data)
618 retif(vi == NULL, EINA_FALSE, "invalid parameter");
620 static qp_vi_op_table anim_job_table[] = {
622 .op_type = VI_OP_RESIZE,
623 .handler = _anim_job_resize,
626 .op_type = VI_OP_NONE,
632 for (i = 0; anim_job_table[i].op_type != VI_OP_NONE; i++) {
633 if (anim_job_table[i].op_type != vi->op_type) {
637 anim_job_table[i].handler(vi);
644 static Eina_Bool _anim_done_cb(void *data)
647 retif(vi == NULL, EINA_FALSE, "invalid parameter");
649 static qp_vi_op_table anim_done_table[] = {
651 .op_type = VI_OP_RESIZE,
652 .handler = _anim_done_resize,
655 .op_type = VI_OP_NONE,
661 for (i = 0; anim_done_table[i].op_type != VI_OP_NONE; i++) {
662 if (anim_done_table[i].op_type != vi->op_type) {
666 anim_done_table[i].handler(vi);
673 static int _init(void *data)
675 minicontrol_error_e ret;
677 retif(!data, QP_FAIL, "Invalid parameter!");
679 g_prov_table = g_hash_table_new_full(g_str_hash, g_str_equal,
680 (GDestroyNotify)g_free,
681 (GDestroyNotify)_viewer_item_free);
683 ret = minicontrol_monitor_start(_mctrl_monitor_cb, data);
684 if (ret != MINICONTROL_ERROR_NONE) {
685 ERR("fail to minicontrol_monitor_start()- %d", ret);
692 static int _fini(void *data)
694 minicontrol_error_e ret;
695 ret = minicontrol_monitor_stop();
696 if (ret != MINICONTROL_ERROR_NONE) {
697 ERR("fail to minicontrol_monitor_stop()- %d", ret);
701 g_hash_table_remove_all(g_prov_table);
708 static int _suspend(void *data)
710 struct appdata *ad = data;
711 retif(ad == NULL, QP_FAIL, "Invalid parameter!");
713 if (ad->list != NULL) {
714 _viewer_unfreeze(ad->scroller);
720 static int _resume(void *data)
722 struct appdata *ad = data;
723 retif(ad == NULL, QP_FAIL, "Invalid parameter!");
725 if (ad->list != NULL) {
726 _viewer_unfreeze(ad->scroller);
732 HAPI void quickpanel_minictrl_rotation_report(int angle)
734 if (g_prov_table != NULL) {
735 if (g_hash_table_size(g_prov_table) > 0) {
736 SINFO("minicontrol rotation:%d", angle);
738 minicontrol_viewer_request(QP_PKG_QUICKPANEL,
739 MINICONTROL_REQ_ROTATE_PROVIDER, angle);