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 (widget_set_orientation(arg->pkgname, arg->id, arg->info.widget_create.degree) < 0) {
164 ErrPrint("Failed to set orientation %s - %d\n", arg->id, arg->info.widget_create.degree);
166 if (arg->info.widget_create.width > 0 && arg->info.widget_create.height > 0) {
167 DbgPrint("Create size: %dx%d (created: %dx%d)\n", arg->info.widget_create.width, arg->info.widget_create.height, *width, *height);
168 if (*width != arg->info.widget_create.width || *height != arg->info.widget_create.height) {
170 tmp = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.widget_create.width, arg->info.widget_create.height);
171 DbgPrint("widget_resize returns: %d\n", tmp);
172 if (tmp == (int)WIDGET_ERROR_NONE) {
175 * Just returns resized canvas size.
176 * Even if it is not ready to render contents.
177 * Provider will allocate render buffer using this size.
179 *width = arg->info.widget_create.width;
180 *height = arg->info.widget_create.height;
185 arg->info.widget_create.out_is_pinned_up = (widget_viewer_is_pinned_up(arg->pkgname, arg->id) == 1);
187 ErrPrint("widget_create returns %d\n", ret);
190 if (widget_is_all_paused()) {
191 DbgPrint("Box is paused\n");
192 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_PAUSED);
198 static int method_renew(struct widget_event_arg *arg, void *data)
204 struct widget_create_arg _arg;
206 DbgPrint("Re-create: pkgname[%s], id[%s], content[%s], timeout[%d], has_script[%d], period[%lf], cluster[%s], category[%s], abi[%s]\n",
207 arg->pkgname, arg->id,
208 arg->info.widget_recreate.content,
209 arg->info.widget_recreate.timeout,
210 arg->info.widget_recreate.has_script,
211 arg->info.widget_recreate.period,
212 arg->info.widget_recreate.cluster,
213 arg->info.widget_recreate.category,
214 arg->info.widget_recreate.abi);
216 if (!arg->info.widget_recreate.content || !strlen(arg->info.widget_recreate.content)) {
217 DbgPrint("Use default content: \"%s\"\n", WIDGET_CONF_DEFAULT_CONTENT);
218 arg->info.widget_recreate.content = WIDGET_CONF_DEFAULT_CONTENT;
221 _arg.content = arg->info.widget_recreate.content;
222 _arg.timeout = arg->info.widget_recreate.timeout;
223 _arg.has_widget_script = arg->info.widget_recreate.has_script;
224 _arg.period = arg->info.widget_recreate.period;
225 _arg.cluster = arg->info.widget_recreate.cluster;
226 _arg.category = arg->info.widget_recreate.category;
227 _arg.abi = arg->info.widget_recreate.abi;
228 _arg.skip_need_to_create = 1;
229 _arg.direct_addr = arg->info.widget_recreate.direct_addr;
231 invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
233 ret = widget_create(arg->pkgname, arg->id,
236 &arg->info.widget_recreate.out_content,
237 &arg->info.widget_recreate.out_title);
239 if (widget_set_orientation(arg->pkgname, arg->id, arg->info.widget_create.degree) < 0) {
240 ErrPrint("Failed to set orientation %s - %d\n", arg->id, arg->info.widget_create.degree);
243 if (w != arg->info.widget_recreate.width || h != arg->info.widget_recreate.height) {
245 tmp = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.widget_recreate.width, arg->info.widget_recreate.height);
247 DbgPrint("Resize[%dx%d] returns: %d\n", arg->info.widget_recreate.width, arg->info.widget_recreate.height, tmp);
250 DbgPrint("No need to change the size: %dx%d\n", w, h);
253 arg->info.widget_recreate.out_is_pinned_up = (widget_viewer_is_pinned_up(arg->pkgname, arg->id) == 1);
255 ErrPrint("widget_create returns %d\n", ret);
258 if (widget_is_all_paused()) {
259 DbgPrint("Box is paused\n");
260 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_PAUSED);
266 static int method_delete(struct widget_event_arg *arg, void *data)
270 DbgPrint("pkgname[%s] id[%s]\n", arg->pkgname, arg->id);
272 if (arg->info.widget_destroy.type == WIDGET_DESTROY_TYPE_DEFAULT || arg->info.widget_destroy.type == WIDGET_DESTROY_TYPE_UNINSTALL) {
273 DbgPrint("Box is deleted from the viewer\n");
274 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_DELETED);
277 invoke_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, arg->id);
278 ret = widget_destroy(arg->pkgname, arg->id, 0);
282 static int method_content_event(struct widget_event_arg *arg, void *data)
285 struct widget_event_info info;
287 info = arg->info.content_event.info;
289 ret = widget_script_event(arg->pkgname, arg->id,
290 arg->info.content_event.signal_name, arg->info.content_event.source,
295 static int method_clicked(struct widget_event_arg *arg, void *data)
299 DbgPrint("pkgname[%s] id[%s] event[%s] timestamp[%lf] x[%lf] y[%lf]\n",
300 arg->pkgname, arg->id,
301 arg->info.clicked.event, arg->info.clicked.timestamp,
302 arg->info.clicked.x, arg->info.clicked.y);
303 ret = widget_clicked(arg->pkgname, arg->id,
304 arg->info.clicked.event,
305 arg->info.clicked.timestamp, arg->info.clicked.x, arg->info.clicked.y);
310 static int method_text_signal(struct widget_event_arg *arg, void *data)
313 struct widget_event_info info;
315 info = arg->info.text_signal.info;
317 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);
318 ret = widget_script_event(arg->pkgname, arg->id,
319 arg->info.text_signal.signal_name, arg->info.text_signal.source,
325 static int method_resize(struct widget_event_arg *arg, void *data)
329 invoke_pre_callback(WIDGET_PRE_RESIZE_CALLBACK, arg->id);
331 DbgPrint("pkgname[%s] id[%s] w[%d] h[%d]\n", arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
332 ret = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
337 static int method_set_period(struct widget_event_arg *arg, void *data)
340 DbgPrint("pkgname[%s] id[%s] period[%lf]\n", arg->pkgname, arg->id, arg->info.set_period.period);
341 ret = widget_viewer_set_period(arg->pkgname, arg->id, arg->info.set_period.period);
345 static int method_change_group(struct widget_event_arg *arg, void *data)
348 DbgPrint("pkgname[%s] id[%s] cluster[%s] category[%s]\n", arg->pkgname, arg->id, arg->info.change_group.cluster, arg->info.change_group.category);
349 ret = widget_change_group(arg->pkgname, arg->id, arg->info.change_group.cluster, arg->info.change_group.category);
353 static int method_pinup(struct widget_event_arg *arg, void *data)
355 DbgPrint("pkgname[%s] id[%s] state[%d]\n", arg->pkgname, arg->id, arg->info.pinup.state);
356 arg->info.pinup.content_info = widget_pinup(arg->pkgname, arg->id, arg->info.pinup.state);
357 return arg->info.pinup.content_info ? WIDGET_ERROR_NONE : WIDGET_ERROR_NOT_SUPPORTED;
360 static int method_update_content(struct widget_event_arg *arg, void *data)
364 if (!arg->id || !strlen(arg->id)) {
365 if (arg->info.update_content.content && strlen(arg->info.update_content.content)) {
366 DbgPrint("pkgname[%s] content[%s]\n", arg->pkgname, arg->info.update_content.content);
367 ret = widget_set_content_info_all(arg->pkgname, arg->info.update_content.content);
369 DbgPrint("pkgname[%s] cluster[%s] category[%s]\n", arg->pkgname, arg->info.update_content.cluster, arg->info.update_content.category);
370 ret = widget_update_all(arg->pkgname, arg->info.update_content.cluster, arg->info.update_content.category, arg->info.update_content.force);
373 if (arg->info.update_content.content && strlen(arg->info.update_content.content)) {
374 DbgPrint("id[%s] content[%s]\n", arg->id, arg->info.update_content.content);
375 ret = widget_set_content_info(arg->pkgname, arg->id, arg->info.update_content.content);
377 DbgPrint("Update [%s]\n", arg->id);
378 ret = widget_update(arg->pkgname, arg->id, arg->info.update_content.force);
385 static int method_pause(struct widget_event_arg *arg, void *data)
389 if (s_info.ping_timer) {
390 ecore_timer_freeze(s_info.ping_timer);
393 if (WIDGET_CONF_SLAVE_AUTO_CACHE_FLUSH) {
394 elm_cache_all_flush();
395 sqlite3_release_memory(WIDGET_CONF_SQLITE_FLUSH_MAX);
399 return WIDGET_ERROR_NONE;
402 static int method_resume(struct widget_event_arg *arg, void *data)
406 if (s_info.ping_timer) {
407 ecore_timer_thaw(s_info.ping_timer);
410 return WIDGET_ERROR_NONE;
413 static Eina_Bool send_ping_cb(void *data)
415 widget_provider_send_ping();
416 return ECORE_CALLBACK_RENEW;
419 static int method_disconnected(struct widget_event_arg *arg, void *data)
421 if (s_info.ping_timer) {
422 ecore_timer_del(s_info.ping_timer);
423 s_info.ping_timer = NULL;
427 return WIDGET_ERROR_NONE;
430 static int method_connected(struct widget_event_arg *arg, void *data)
433 ret = widget_provider_send_hello();
435 double ping_interval;
437 ping_interval = WIDGET_CONF_DEFAULT_PING_TIME / 2.0f;
438 DbgPrint("Ping Timer: %lf\n", ping_interval);
440 s_info.ping_timer = ecore_timer_add(ping_interval, send_ping_cb, NULL);
441 if (!s_info.ping_timer) {
442 ErrPrint("Failed to add a ping timer\n");
446 return WIDGET_ERROR_NONE;
449 static int method_gbar_created(struct widget_event_arg *arg, void *data)
453 ret = widget_open_gbar(arg->pkgname, arg->id);
455 DbgPrint("%s Open PD: %d\n", arg->id, ret);
458 return WIDGET_ERROR_NONE;
461 static int method_gbar_destroyed(struct widget_event_arg *arg, void *data)
465 ret = widget_close_gbar(arg->pkgname, arg->id);
467 DbgPrint("%s Close PD: %d\n", arg->id, ret);
470 return WIDGET_ERROR_NONE;
473 static int method_gbar_moved(struct widget_event_arg *arg, void *data)
476 struct widget_event_info info;
478 memset(&info, 0, sizeof(info));
479 info.pointer.x = arg->info.gbar_move.x;
480 info.pointer.y = arg->info.gbar_move.y;
481 info.pointer.down = 0;
483 ret = widget_script_event(arg->pkgname, arg->id,
484 "gbar,move", util_uri_to_path(arg->id), &info);
488 static int method_widget_pause(struct widget_event_arg *arg, void *data)
492 ret = widget_pause(arg->pkgname, arg->id);
494 if (WIDGET_CONF_SLAVE_AUTO_CACHE_FLUSH) {
495 elm_cache_all_flush();
496 sqlite3_release_memory(WIDGET_CONF_SQLITE_FLUSH_MAX);
503 static int method_widget_resume(struct widget_event_arg *arg, void *data)
505 return widget_resume(arg->pkgname, arg->id);
508 static int method_viewer_connected(struct widget_event_arg *arg, void *data)
510 return widget_viewer_connected(arg->pkgname, arg->id, arg->info.viewer_connected.direct_addr);
513 static int method_viewer_disconnected(struct widget_event_arg *arg, void *data)
515 return widget_viewer_disconnected(arg->pkgname, arg->id, arg->info.viewer_disconnected.direct_addr);
518 static int method_orientation(struct widget_event_arg *arg, void *data)
522 ret = widget_set_orientation(arg->pkgname, arg->id, arg->info.orientation.degree);
523 invoke_pre_callback(WIDGET_PRE_ORIENTATION_CALLBACK, arg->id);
528 HAPI int client_init(const char *name, const char *abi, const char *accel, int secured)
530 struct widget_event_table table = {
531 .widget_create = method_new,
532 .widget_recreate = method_renew,
533 .widget_destroy = method_delete,
534 .content_event = method_content_event,
535 .clicked = method_clicked,
536 .text_signal = method_text_signal,
537 .resize = method_resize,
538 .set_period = method_set_period,
539 .change_group = method_change_group,
540 .pinup = method_pinup,
541 .update_content = method_update_content,
542 .pause = method_pause,
543 .resume = method_resume,
544 .disconnected = method_disconnected,
545 .connected = method_connected,
546 .gbar_create = method_gbar_created,
547 .gbar_destroy = method_gbar_destroyed,
548 .gbar_move = method_gbar_moved,
549 .widget_pause = method_widget_pause,
550 .widget_resume = method_widget_resume,
551 .viewer_connected = method_viewer_connected,
552 .viewer_disconnected = method_viewer_disconnected,
553 .orientation = method_orientation,
556 widget_provider_prepare_init(abi, accel, secured);
557 return widget_provider_init(util_screen_get(), name, &table, NULL, 1, 1);
560 HAPI int client_fini(void)
562 (void)widget_provider_fini();
563 return WIDGET_ERROR_NONE;