The source code moved from the SPIN with license changed to Flora 1.1
[apps/native/home/homescreen-efl.git] / src / livebox / livebox_widget.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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 #include <Elementary.h>
18 #include <widget_viewer_evas.h>
19 #include <widget_errno.h>
20 #include <shortcut.h>
21
22 #include "homescreen-efl.h"
23 #include "livebox/livebox_widget.h"
24 #include "livebox/livebox_panel.h"
25 #include "livebox/livebox_utils.h"
26 #include "util.h"
27 #include "data_model.h"
28 #include "page_scroller.h"
29 #include "popup.h"
30
31
32 static int __livebox_widget_get_pkg_list_cb(const char *pkg_id, const char *widget_id, int is_prime, void *data);
33
34 static int request_cb(const char *appid,
35                 const char *name,
36                 int type,
37                 const char *content_info,
38                 const char *icon,
39                 int pid,
40                 double period,
41                 int allow_duplicate,
42                 void *data);
43
44 static void update_content_info(Evas_Object *widget, const char *content_info);
45
46 static struct {
47         Eina_List *widget_list;
48 } s_info = {
49         .widget_list = NULL,
50 };
51
52 void livebox_widget_init(void)
53 {
54         int ret = -1;
55
56         ret = widget_service_get_widget_list(__livebox_widget_get_pkg_list_cb, NULL);
57
58         if (ret == WIDGET_ERROR_INVALID_PARAMETER ||
59                 ret == WIDGET_ERROR_IO_ERROR ||
60                 ret == WIDGET_ERROR_PERMISSION_DENIED) {
61                 LOGE("FAILED TO GET PKGLIST. ERROR CODE: %d", ret);
62                 return;
63         } else {
64                 LOGI("SUCCESS TO GET PKGLIST. COUNT: %d", ret);
65         }
66
67         widget_viewer_evas_init(home_screen_get_win());
68
69         ret = shortcut_set_request_cb(request_cb, NULL);
70         if (ret < 0)
71                 LOGE("Failed to add shortcut event listener: 0x%X\n", ret);
72 }
73
74 Eina_List *livebox_widget_get_list(void)
75 {
76         if (!s_info.widget_list) {
77                 LOGE("s_info.widget_list == NULL");
78                 return NULL;
79         }
80
81         return s_info.widget_list;
82 }
83
84 static void widget_content_info_updated_cb(void *data, Evas_Object *obj, void *event_info)
85 {
86         widget_evas_event_info_s *info = event_info;
87         const char *content_info;
88
89         if (info->error != WIDGET_ERROR_NONE || !info->widget_app_id)
90                 return;
91
92         content_info = widget_viewer_evas_get_content_info(obj);
93         LOGD("Content inf is updated [%s] - [%s]\n", info->widget_app_id, content_info);
94
95         update_content_info(obj, content_info);
96
97 }
98
99 Evas_Object *livebox_widget_add(const char *pkg_name, Evas_Object *parent, char *content_info)
100 {
101         Evas_Object *livebox = widget_viewer_evas_add_widget(parent, pkg_name, content_info, WIDGET_VIEWER_EVAS_DEFAULT_PERIOD);
102         if (!livebox) {
103                 LOGE("livebox == NULL");
104                 return NULL;
105         }
106
107         evas_object_smart_callback_add(livebox, WIDGET_SMART_SIGNAL_EXTRA_INFO_UPDATED, widget_content_info_updated_cb, NULL);
108
109         return livebox;
110 }
111
112 void livebox_widget_del(Evas_Object *widget)
113 {
114         if (!widget) {
115                 LOGE("widget == NULL");
116                 return;
117         }
118
119         LOGI("DELETING WIDGET: %s", widget_viewer_evas_get_widget_id(widget));
120         widget_viewer_evas_set_permanent_delete(widget, 1);
121 }
122
123 void livebox_widget_fini(void)
124 {
125         Eina_List *l;
126         widget_info_t *widget = NULL;
127
128         if (!s_info.widget_list) {
129                 LOGE("s_info.widget_list == NULL");
130                 return;
131         }
132
133         EINA_LIST_FOREACH(s_info.widget_list, l, widget) {
134                 if (!widget) {
135                         LOGE("widget == NULL");
136                         continue;
137                 }
138
139                 free(widget->pkg_id);
140                 free(widget->widget_id);
141         }
142
143         eina_list_free(s_info.widget_list);
144 }
145
146 void livebox_widget_viewer_paused(void)
147 {
148         int ret;
149         ret = widget_viewer_evas_notify_paused_status_of_viewer();
150         LOGD("Viewer is paused: %d\n", ret);
151 }
152
153 void livebox_widget_viewer_resumed(void)
154 {
155         Evas_Object *page = NULL;
156         Eina_List *lb_layouts = NULL;
157         Eina_List *l = NULL;
158         Eina_List *l2 = NULL;
159         Eina_List *pages = NULL;
160         Evas_Object *widget = NULL;
161         Evas_Object *lb_layout = NULL;
162         const char *content_info = NULL;
163         int ret;
164         static Eina_Bool app_created = EINA_TRUE;
165
166         ret = widget_viewer_evas_notify_resumed_status_of_viewer();
167         LOGD("Viewer is resumed: %d\n", ret);
168
169         if (app_created) {
170                 app_created = EINA_FALSE;
171                 return;
172         }
173
174         pages = page_scroller_get_all_pages(livebox_panel_get());
175
176         if (!pages) {
177                 LOGE("pages == NULL");
178                 return;
179         }
180
181         EINA_LIST_FOREACH(pages, l, page) {
182                 if (!page) {
183                         LOGE("page == NULL");
184                         return;
185                 }
186
187                 lb_layouts = livebox_utils_get_liveboxes_on_page_list(page);
188                 if (!lb_layouts) {
189                         LOGE("lb_layouts == NULL");
190                         continue;
191                 }
192
193                 EINA_LIST_FOREACH(lb_layouts, l2, lb_layout) {
194                         if (!lb_layout) {
195                                 LOGE("lb_layout == NULL");
196                                 continue;
197                         }
198
199                         widget = elm_layout_content_get(lb_layout, PART_LIVEBOX);
200                         if (!widget) {
201                                 LOGE("widget == NULL");
202                                 return;
203                         }
204
205                         content_info = widget_viewer_evas_get_content_info(widget);
206                         update_content_info(widget, content_info);
207
208                         LOGD("Content inf is updated [%s] - [%s]\n",
209                                         widget_viewer_evas_get_widget_id(widget),
210                                         content_info);
211                 }
212         }
213 }
214
215 void livebox_widget_get_dimensions(int size, int *x, int *y)
216 {
217         if (!x || !y) {
218                 LOGE("Wrong arguments provided: %p %p", x, y);
219                 return;
220         }
221
222         switch (size) {
223         case WIDGET_SIZE_TYPE_1x1:
224                 *x = 1;
225                 *y = 1;
226                 break;
227         case WIDGET_SIZE_TYPE_2x1:
228                 *x = 2;
229                 *y = 1;
230                 break;
231         case WIDGET_SIZE_TYPE_2x2:
232                 *x = 2;
233                 *y = 2;
234                 break;
235         case WIDGET_SIZE_TYPE_4x1:
236                 *x = 4;
237                 *y = 1;
238                 break;
239         case WIDGET_SIZE_TYPE_4x2:
240                 *x = 4;
241                 *y = 2;
242                 break;
243         case WIDGET_SIZE_TYPE_4x3:
244                 *x = 4;
245                 *y = 3;
246                 break;
247         case WIDGET_SIZE_TYPE_4x4:
248                 *x = 4;
249                 *y = 4;
250                 break;
251         case WIDGET_SIZE_TYPE_4x5:
252                 *x = 4;
253                 *y = 5;
254                 break;
255         case WIDGET_SIZE_TYPE_4x6:
256                 *x = 4;
257                 *y = 6;
258                 break;
259         case WIDGET_SIZE_TYPE_EASY_1x1:
260                 *x = 1;
261                 *y = 1;
262                 break;
263         case WIDGET_SIZE_TYPE_EASY_3x1:
264                 *x = 3;
265                 *y = 1;
266                 break;
267         case WIDGET_SIZE_TYPE_EASY_3x3:
268                 *x = 3;
269                 *y = 3;
270                 break;
271         case WIDGET_SIZE_TYPE_FULL:
272                 *x = 4;
273                 *y = 4;
274                 break;
275         case WIDGET_SIZE_TYPE_UNKNOWN:
276                 *x = -1;
277                 *y = -1;
278                 break;
279         default:
280                 *x = -1;
281                 *y = -1;
282         }
283 }
284
285 void livebox_widget_get_size_available(Evas_Object *widget, int *cnt, int **size_list)
286 {
287         int ret = -1;
288         const char *widget_id = NULL;
289         *cnt = 0;
290
291         if (!widget) {
292                 LOGE("widget == NULL");
293                 return;
294         }
295
296         if (!size_list) {
297                 LOGE("size_list == NULL");
298                 return;
299         }
300
301         if (*size_list) {
302                 free(*size_list);
303                 *size_list = NULL;
304         }
305
306         widget_id = widget_viewer_evas_get_widget_id(widget);
307         if (!widget_id) {
308                 LOGE("widget_id == NULL");
309                 free(*size_list);
310                 *size_list = NULL;
311                 return;
312         }
313
314         ret = widget_service_get_supported_size_types(widget_id, cnt, size_list);
315
316         if (ret != 0 || *cnt == 0) {
317                 LOGE("RESIZE COULD NOT GET SUPPORTED SIZES");
318                 *size_list = calloc(WIDGET_NR_OF_SIZE_LIST, sizeof(widget_size_type_e));
319                 *cnt = 2;
320                 (*size_list)[0] = WIDGET_SIZE_TYPE_4x2;
321                 (*size_list)[1] = WIDGET_SIZE_TYPE_4x4;
322         }
323
324         LOGD("RESIZE AVAILABLE SIZE COUNT: %d", *cnt);
325 }
326
327 void livebox_widget_set_event_blocking(Evas_Object *widget)
328 {
329         if (!widget) {
330                 LOGE("widget == NULL");
331                 return;
332         }
333
334         widget_viewer_evas_cancel_click_event(widget);
335         LOGI("BLOCKING: %s", widget_viewer_evas_get_widget_id(widget));
336 }
337
338 static int __livebox_widget_get_pkg_list_cb(const char *pkg_id, const char *widget_id, int is_prime, void *data)
339 {
340         widget_info_t *widget = NULL;
341         int cnt = WIDGET_NR_OF_SIZE_LIST;;
342         int *size_list = NULL;
343         int ret = -1;
344
345         LOGI("WIDGET: %s; %s; %d", pkg_id, widget_id, is_prime);
346
347         widget = calloc(1, sizeof(widget_info_t));
348         if (!widget) {
349                 LOGE("widget == NULL");
350                 return 0;
351         }
352
353         widget->widget_id = strdup(widget_id);
354         widget->pkg_id    = strdup(pkg_id);
355         widget->is_prime  = is_prime;
356
357         ret = widget_service_get_supported_size_types(widget_id, &cnt, &size_list);
358
359         if(ret == 0 && cnt > 0) {
360                 livebox_widget_get_dimensions(size_list[0], &widget->width, &widget->height);
361                 LOGI("SIZE SET [%d, %d] ret == %d; cnt == %d", widget->width, widget->height, ret, cnt);
362         } else {
363                 LOGE("COULD NOT GET AVAILABLE SiZES ret == %d; cnt == %d; size_list[0] == %d", ret, cnt, size_list[0]);
364                 widget->width  = LIVEBOX_ON_CREATE_SIZE;
365                 widget->height = LIVEBOX_ON_CREATE_SIZE;
366         }
367
368         s_info.widget_list = eina_list_append(s_info.widget_list, widget);
369         return 0;
370 }
371
372 static void livebox_widget_new(int widget_width, int widget_height, const char *content_info)
373 {
374         int page_index = -1;
375         int pos_x = 0;
376         int pos_y = 0;
377         Tree_node_t *page_node = NULL;
378         Tree_node_t *item_node = NULL;
379         Evas_Object *page = NULL;
380
381         page_index = livebox_panel_find_empty_space(widget_width, widget_height, &pos_x, &pos_y);
382
383         if (page_index > -1)
384                 page = page_scroller_get_page(livebox_panel_get(), page_index);
385
386         if (!page) {
387                 pos_x = 0;
388                 pos_y = 0;
389
390                 if (!livebox_panel_can_add_page()) {
391                         LOGI("Cannot add new page");
392                         return;
393                 }
394
395                 page_node = data_model_add_widget_page();
396                 if (!page_node) {
397                         livebox_panel_destroy();
398                         LOGE("page_node == NULL");
399                         return;
400                 }
401
402                 page = livebox_panel_add_page(page_node, livebox_panel_get());
403                 if (!page) {
404                         LOGE("page == NULL");
405                         livebox_panel_destroy();
406                         data_model_del_item(page_node);
407                         return;
408                 }
409
410                 page_index = page_scroller_get_page_count(livebox_panel_get()) - 1;
411         } else {
412                 page_node = evas_object_data_get(page, KEY_ICON_DATA);
413                 if (!page_node) {
414                         LOGE("obj_node == NULL");
415                         livebox_panel_destroy();
416                         return;
417                 }
418         }
419
420         item_node = data_model_add_widget(page_node, content_info, pos_x, pos_y, widget_width, widget_height, NULL);
421         if (!item_node) {
422                 LOGE("item == NULL");
423                 return;
424         }
425
426         elm_scroller_page_bring_in(livebox_panel_get(), page_index, 0);
427         livebox_panel_add_livebox(item_node, page, content_info, pos_x, pos_y, widget_width, widget_height, NULL);
428         livebox_panel_update_dynamic_index();
429 }
430
431 static void _cannot_add_widget_popup_show(void)
432 {
433         popup_data_t *data = popup_create_data();
434         if (!data) {
435                 LOGE("data == NULL");
436                 return;
437         }
438
439         data->orientation        = ELM_POPUP_ORIENT_CENTER;
440         data->popup_cancel_text  = NULL;
441         data->popup_confirm_text = NULL;
442         data->popup_content_text = strdup(_("IDS_HS_HEADER_UNABLE_TO_ADD_WIDGET_ABB"));
443         data->popup_title_text   = NULL;
444         data->type               = POPUP_INFO;
445         data->visible_time       = 5.0;
446
447         popup_show(data, NULL, NULL, NULL);
448 }
449
450 static int request_cb(const char *appid, const char *name, int type,
451         const char *content_info, const char *icon, int pid, double period,
452         int allow_duplicate, void *data)
453 {
454         int widget_width;
455         int widget_height;
456
457         LOGI("====== WIDGET REQUEST ======");
458         LOGI("Package name: %s\n",    appid);
459         LOGI("Name: %s\n",            name);
460         LOGI("Type: %d\n",            type);
461         LOGI("Content: %s\n",         content_info);
462         LOGI("Icon: %s\n",            icon);
463         LOGI("Requested from: %d\n",  pid);
464         LOGI("Period: %lf\n",         period);
465         LOGI("Allow duplicate: %d\n", allow_duplicate);
466         LOGI("CBDATA: %p\n",          data);
467         LOGI("============================");
468
469         switch (type) {
470         case WIDGET_SIZE_4x2:
471                 widget_width =  4;
472                 widget_height = 2;
473                 break;
474         case WIDGET_SIZE_4x4:
475                 widget_width =  4;
476                 widget_height = 4;
477                 break;
478         default:
479                 /* Unsupported */
480                 LOGE("Unsupported type: %x\n", type);
481                 _cannot_add_widget_popup_show();
482                 return 0;
483         }
484
485         LOGI("Widget will be added: %dx%d\n", widget_width, widget_height);
486
487         livebox_widget_new(widget_width, widget_height, content_info);
488         home_screen_print_tree();
489
490         return 0; /*returns success. */
491 }
492
493 static void update_content_info(Evas_Object *widget, const char *content_info)
494 {
495         Evas_Object *parent = NULL;
496         Tree_node_t *node = NULL;
497
498         if (!widget) {
499                 LOGE("widget == NULL");
500                 return;
501         }
502
503         parent = elm_object_parent_widget_get(widget);
504         if (!parent) {
505                 LOGE("parent == NULL");
506                 return;
507         }
508
509         node = evas_object_data_get(parent, KEY_ICON_DATA);
510         if (!node) {
511                 LOGE("node == NULL");
512                 return;
513         }
514
515         data_model_update_content_info(node, content_info);
516 }