2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
22 #include <Elementary.h>
32 #include <widget_provider.h> /* widget_provider */
33 #include <widget_errno.h> /* widget_service */
34 #include <widget_script.h> /* widget_service - widget_event_info */
35 #include <widget_conf.h>
36 #include <widget/widget_internal.h> /* widget - WIDGET_SYS_EVENT_XXX */
37 #include <widget/widget.h> /* widget - WIDGET_SYS_EVENT_XXX */
39 #include "critical_log.h"
42 #include "so_handler.h"
48 struct pre_callback_item {
49 widget_pre_callback_t cb;
54 Ecore_Timer *ping_timer;
55 Eina_List *widget_pre_callback_list[WIDGET_PRE_CALLBACK_COUNT];
58 .widget_pre_callback_list = { NULL, },
61 static void invoke_pre_callback(widget_pre_callback_e type, const char *id)
65 struct pre_callback_item *item;
67 EINA_LIST_FOREACH_SAFE(s_info.widget_pre_callback_list[type], l, n, item) {
68 item->cb(id, item->data);
72 int widget_provider_app_add_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
74 struct pre_callback_item *item;
77 if (!cb || type == WIDGET_PRE_CALLBACK_COUNT) {
78 return WIDGET_ERROR_INVALID_PARAMETER;
81 EINA_LIST_FOREACH(s_info.widget_pre_callback_list[type], l, item) {
82 if (item->cb == cb && item->data == data) {
83 return WIDGET_ERROR_ALREADY_EXIST;
87 item = malloc(sizeof(*item));
89 ErrPrint("malloc: %d\n", errno);
90 return WIDGET_ERROR_OUT_OF_MEMORY;
96 s_info.widget_pre_callback_list[type] = eina_list_append(s_info.widget_pre_callback_list[type], item);
100 int widget_provider_app_del_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
104 struct pre_callback_item *item;
106 if (!cb || type == WIDGET_PRE_CALLBACK_COUNT) {
107 ErrPrint("Invalid parameter\n");
108 return WIDGET_ERROR_INVALID_PARAMETER;
111 EINA_LIST_FOREACH_SAFE(s_info.widget_pre_callback_list[type], l, n, item) {
112 if (item->cb == cb && item->data == data) {
113 s_info.widget_pre_callback_list[type] = eina_list_remove_list(s_info.widget_pre_callback_list[type], l);
115 return WIDGET_ERROR_NONE;
119 return WIDGET_ERROR_NOT_EXIST;
122 static int method_new(struct widget_event_arg *arg, int *width, int *height, double *priority, void *data)
125 struct widget_create_arg _arg;
126 DbgPrint("Create: pkgname[%s], id[%s], content[%s], timeout[%d], has_script[%d], period[%lf], cluster[%s], category[%s], skip[%d], abi[%s], size: %dx%d\n",
129 arg->info.widget_create.content,
130 arg->info.widget_create.timeout,
131 arg->info.widget_create.has_script,
132 arg->info.widget_create.period,
133 arg->info.widget_create.cluster, arg->info.widget_create.category,
134 arg->info.widget_create.skip_need_to_create,
135 arg->info.widget_create.abi,
136 arg->info.widget_create.width,
137 arg->info.widget_create.height);
139 if (!arg->info.widget_create.content || !strlen(arg->info.widget_create.content)) {
140 DbgPrint("Use default content: \"%s\"\n", WIDGET_CONF_DEFAULT_CONTENT);
141 arg->info.widget_create.content = WIDGET_CONF_DEFAULT_CONTENT;
144 _arg.content = arg->info.widget_create.content;
145 _arg.timeout = arg->info.widget_create.timeout;
146 _arg.has_widget_script = arg->info.widget_create.has_script;
147 _arg.period = arg->info.widget_create.period;
148 _arg.cluster = arg->info.widget_create.cluster;
149 _arg.category = arg->info.widget_create.category;
150 _arg.abi = arg->info.widget_create.abi;
151 _arg.skip_need_to_create = arg->info.widget_create.skip_need_to_create;
152 _arg.direct_addr = arg->info.widget_create.direct_addr;
154 invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
156 ret = widget_create(arg->pkgname, arg->id,
158 width, height, priority,
159 &arg->info.widget_create.out_content,
160 &arg->info.widget_create.out_title);
163 if (arg->info.widget_create.width > 0 && arg->info.widget_create.height > 0) {
164 DbgPrint("Create size: %dx%d (created: %dx%d)\n", arg->info.widget_create.width, arg->info.widget_create.height, *width, *height);
165 if (*width != arg->info.widget_create.width || *height != arg->info.widget_create.height) {
167 tmp = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.widget_create.width, arg->info.widget_create.height);
168 DbgPrint("widget_resize returns: %d\n", tmp);
169 if (tmp == (int)WIDGET_ERROR_NONE) {
172 * Just returns resized canvas size.
173 * Even if it is not ready to render contents.
174 * Provider will allocate render buffer using this size.
176 *width = arg->info.widget_create.width;
177 *height = arg->info.widget_create.height;
182 arg->info.widget_create.out_is_pinned_up = (widget_viewer_is_pinned_up(arg->pkgname, arg->id) == 1);
184 ErrPrint("widget_create returns %d\n", ret);
187 if (widget_is_all_paused()) {
188 DbgPrint("Box is paused\n");
189 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_PAUSED);
195 static int method_renew(struct widget_event_arg *arg, void *data)
201 struct widget_create_arg _arg;
203 DbgPrint("Re-create: pkgname[%s], id[%s], content[%s], timeout[%d], has_script[%d], period[%lf], cluster[%s], category[%s], abi[%s]\n",
204 arg->pkgname, arg->id,
205 arg->info.widget_recreate.content,
206 arg->info.widget_recreate.timeout,
207 arg->info.widget_recreate.has_script,
208 arg->info.widget_recreate.period,
209 arg->info.widget_recreate.cluster,
210 arg->info.widget_recreate.category,
211 arg->info.widget_recreate.abi);
213 if (!arg->info.widget_recreate.content || !strlen(arg->info.widget_recreate.content)) {
214 DbgPrint("Use default content: \"%s\"\n", WIDGET_CONF_DEFAULT_CONTENT);
215 arg->info.widget_recreate.content = WIDGET_CONF_DEFAULT_CONTENT;
218 _arg.content = arg->info.widget_recreate.content;
219 _arg.timeout = arg->info.widget_recreate.timeout;
220 _arg.has_widget_script = arg->info.widget_recreate.has_script;
221 _arg.period = arg->info.widget_recreate.period;
222 _arg.cluster = arg->info.widget_recreate.cluster;
223 _arg.category = arg->info.widget_recreate.category;
224 _arg.abi = arg->info.widget_recreate.abi;
225 _arg.skip_need_to_create = 1;
226 _arg.direct_addr = arg->info.widget_recreate.direct_addr;
228 invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
230 ret = widget_create(arg->pkgname, arg->id,
233 &arg->info.widget_recreate.out_content,
234 &arg->info.widget_recreate.out_title);
236 if (w != arg->info.widget_recreate.width || h != arg->info.widget_recreate.height) {
238 tmp = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.widget_recreate.width, arg->info.widget_recreate.height);
240 DbgPrint("Resize[%dx%d] returns: %d\n", arg->info.widget_recreate.width, arg->info.widget_recreate.height, tmp);
243 DbgPrint("No need to change the size: %dx%d\n", w, h);
246 arg->info.widget_recreate.out_is_pinned_up = (widget_viewer_is_pinned_up(arg->pkgname, arg->id) == 1);
248 ErrPrint("widget_create returns %d\n", ret);
251 if (widget_is_all_paused()) {
252 DbgPrint("Box is paused\n");
253 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_PAUSED);
259 static int method_delete(struct widget_event_arg *arg, void *data)
263 DbgPrint("pkgname[%s] id[%s]\n", arg->pkgname, arg->id);
265 if (arg->info.widget_destroy.type == WIDGET_DESTROY_TYPE_DEFAULT || arg->info.widget_destroy.type == WIDGET_DESTROY_TYPE_UNINSTALL) {
266 DbgPrint("Box is deleted from the viewer\n");
267 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_DELETED);
270 invoke_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, arg->id);
271 ret = widget_destroy(arg->pkgname, arg->id, 0);
275 static int method_content_event(struct widget_event_arg *arg, void *data)
278 struct widget_event_info info;
280 info = arg->info.content_event.info;
282 ret = widget_script_event(arg->pkgname, arg->id,
283 arg->info.content_event.signal_name, arg->info.content_event.source,
288 static int method_clicked(struct widget_event_arg *arg, void *data)
292 DbgPrint("pkgname[%s] id[%s] event[%s] timestamp[%lf] x[%lf] y[%lf]\n",
293 arg->pkgname, arg->id,
294 arg->info.clicked.event, arg->info.clicked.timestamp,
295 arg->info.clicked.x, arg->info.clicked.y);
296 ret = widget_clicked(arg->pkgname, arg->id,
297 arg->info.clicked.event,
298 arg->info.clicked.timestamp, arg->info.clicked.x, arg->info.clicked.y);
303 static int method_text_signal(struct widget_event_arg *arg, void *data)
306 struct widget_event_info info;
308 info = arg->info.text_signal.info;
310 DbgPrint("pkgname[%s] id[%s] signal_name[%s] source[%s]\n", arg->pkgname, arg->id, arg->info.text_signal.signal_name, arg->info.text_signal.source);
311 ret = widget_script_event(arg->pkgname, arg->id,
312 arg->info.text_signal.signal_name, arg->info.text_signal.source,
318 static int method_resize(struct widget_event_arg *arg, void *data)
322 invoke_pre_callback(WIDGET_PRE_RESIZE_CALLBACK, arg->id);
324 DbgPrint("pkgname[%s] id[%s] w[%d] h[%d]\n", arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
325 ret = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
330 static int method_set_period(struct widget_event_arg *arg, void *data)
333 DbgPrint("pkgname[%s] id[%s] period[%lf]\n", arg->pkgname, arg->id, arg->info.set_period.period);
334 ret = widget_viewer_set_period(arg->pkgname, arg->id, arg->info.set_period.period);
338 static int method_change_group(struct widget_event_arg *arg, void *data)
341 DbgPrint("pkgname[%s] id[%s] cluster[%s] category[%s]\n", arg->pkgname, arg->id, arg->info.change_group.cluster, arg->info.change_group.category);
342 ret = widget_change_group(arg->pkgname, arg->id, arg->info.change_group.cluster, arg->info.change_group.category);
346 static int method_pinup(struct widget_event_arg *arg, void *data)
348 DbgPrint("pkgname[%s] id[%s] state[%d]\n", arg->pkgname, arg->id, arg->info.pinup.state);
349 arg->info.pinup.content_info = widget_pinup(arg->pkgname, arg->id, arg->info.pinup.state);
350 return arg->info.pinup.content_info ? WIDGET_ERROR_NONE : WIDGET_ERROR_NOT_SUPPORTED;
353 static int method_update_content(struct widget_event_arg *arg, void *data)
357 if (!arg->id || !strlen(arg->id)) {
358 if (arg->info.update_content.content && strlen(arg->info.update_content.content)) {
359 DbgPrint("pkgname[%s] content[%s]\n", arg->pkgname, arg->info.update_content.content);
360 ret = widget_set_content_info_all(arg->pkgname, arg->info.update_content.content);
362 DbgPrint("pkgname[%s] cluster[%s] category[%s]\n", arg->pkgname, arg->info.update_content.cluster, arg->info.update_content.category);
363 ret = widget_update_all(arg->pkgname, arg->info.update_content.cluster, arg->info.update_content.category, arg->info.update_content.force);
366 if (arg->info.update_content.content && strlen(arg->info.update_content.content)) {
367 DbgPrint("id[%s] content[%s]\n", arg->id, arg->info.update_content.content);
368 ret = widget_set_content_info(arg->pkgname, arg->id, arg->info.update_content.content);
370 DbgPrint("Update [%s]\n", arg->id);
371 ret = widget_update(arg->pkgname, arg->id, arg->info.update_content.force);
378 static int method_pause(struct widget_event_arg *arg, void *data)
382 if (s_info.ping_timer) {
383 ecore_timer_freeze(s_info.ping_timer);
386 if (WIDGET_CONF_SLAVE_AUTO_CACHE_FLUSH) {
387 elm_cache_all_flush();
388 sqlite3_release_memory(WIDGET_CONF_SQLITE_FLUSH_MAX);
392 return WIDGET_ERROR_NONE;
395 static int method_resume(struct widget_event_arg *arg, void *data)
399 if (s_info.ping_timer) {
400 ecore_timer_thaw(s_info.ping_timer);
403 return WIDGET_ERROR_NONE;
406 static Eina_Bool send_ping_cb(void *data)
408 widget_provider_send_ping();
409 return ECORE_CALLBACK_RENEW;
412 static int method_disconnected(struct widget_event_arg *arg, void *data)
414 if (s_info.ping_timer) {
415 ecore_timer_del(s_info.ping_timer);
416 s_info.ping_timer = NULL;
420 return WIDGET_ERROR_NONE;
423 static int method_connected(struct widget_event_arg *arg, void *data)
426 ret = widget_provider_send_hello();
428 double ping_interval;
430 ping_interval = WIDGET_CONF_DEFAULT_PING_TIME / 2.0f;
431 DbgPrint("Ping Timer: %lf\n", ping_interval);
433 s_info.ping_timer = ecore_timer_add(ping_interval, send_ping_cb, NULL);
434 if (!s_info.ping_timer) {
435 ErrPrint("Failed to add a ping timer\n");
439 return WIDGET_ERROR_NONE;
442 static int method_gbar_created(struct widget_event_arg *arg, void *data)
446 ret = widget_open_gbar(arg->pkgname, arg->id);
448 DbgPrint("%s Open PD: %d\n", arg->id, ret);
451 return WIDGET_ERROR_NONE;
454 static int method_gbar_destroyed(struct widget_event_arg *arg, void *data)
458 ret = widget_close_gbar(arg->pkgname, arg->id);
460 DbgPrint("%s Close PD: %d\n", arg->id, ret);
463 return WIDGET_ERROR_NONE;
466 static int method_gbar_moved(struct widget_event_arg *arg, void *data)
469 struct widget_event_info info;
471 memset(&info, 0, sizeof(info));
472 info.pointer.x = arg->info.gbar_move.x;
473 info.pointer.y = arg->info.gbar_move.y;
474 info.pointer.down = 0;
476 ret = widget_script_event(arg->pkgname, arg->id,
477 "gbar,move", util_uri_to_path(arg->id), &info);
481 static int method_widget_pause(struct widget_event_arg *arg, void *data)
485 ret = widget_pause(arg->pkgname, arg->id);
487 if (WIDGET_CONF_SLAVE_AUTO_CACHE_FLUSH) {
488 elm_cache_all_flush();
489 sqlite3_release_memory(WIDGET_CONF_SQLITE_FLUSH_MAX);
496 static int method_widget_resume(struct widget_event_arg *arg, void *data)
498 return widget_resume(arg->pkgname, arg->id);
501 static int method_viewer_connected(struct widget_event_arg *arg, void *data)
503 return widget_viewer_connected(arg->pkgname, arg->id, arg->info.viewer_connected.direct_addr);
506 static int method_viewer_disconnected(struct widget_event_arg *arg, void *data)
508 return widget_viewer_disconnected(arg->pkgname, arg->id, arg->info.viewer_disconnected.direct_addr);
511 static int method_orientation(struct widget_event_arg *arg, void *data)
513 int ret = widget_set_orientation(arg->pkgname, arg->id, arg->info.orientation.degree);
514 invoke_pre_callback(WIDGET_PRE_ORIENTATION_CALLBACK, arg->id);
518 HAPI int client_init(const char *name, const char *abi, const char *accel, int secured)
520 struct widget_event_table table = {
521 .widget_create = method_new,
522 .widget_recreate = method_renew,
523 .widget_destroy = method_delete,
524 .content_event = method_content_event,
525 .clicked = method_clicked,
526 .text_signal = method_text_signal,
527 .resize = method_resize,
528 .set_period = method_set_period,
529 .change_group = method_change_group,
530 .pinup = method_pinup,
531 .update_content = method_update_content,
532 .pause = method_pause,
533 .resume = method_resume,
534 .disconnected = method_disconnected,
535 .connected = method_connected,
536 .gbar_create = method_gbar_created,
537 .gbar_destroy = method_gbar_destroyed,
538 .gbar_move = method_gbar_moved,
539 .widget_pause = method_widget_pause,
540 .widget_resume = method_widget_resume,
541 .viewer_connected = method_viewer_connected,
542 .viewer_disconnected = method_viewer_disconnected,
543 .orientation = method_orientation,
546 widget_provider_prepare_init(abi, accel, secured);
547 return widget_provider_init(util_screen_get(), name, &table, NULL, 1, 1);
550 HAPI int client_fini(void)
552 (void)widget_provider_fini();
553 return WIDGET_ERROR_NONE;