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>
31 #include <widget_errno.h> /* widget_service */
32 #include <widget_provider.h> /* widget_provider */
33 #include <widget_script.h> /* widget_service - widget_event_info */
34 #include <widget_conf.h>
35 #include <widget/widget_internal.h> /* widget - WIDGET_SYS_EVENT_XXX */
36 #include <widget/widget.h> /* widget - WIDGET_SYS_EVENT_XXX */
38 #include "critical_log.h"
41 #include "so_handler.h"
47 struct pre_callback_item {
48 widget_pre_callback_t cb;
53 Ecore_Timer *ping_timer;
54 Eina_List *widget_pre_callback_list[WIDGET_PRE_CALLBACK_COUNT];
57 .widget_pre_callback_list = { NULL, },
60 static void invoke_pre_callback(widget_pre_callback_e type, const char *id)
64 struct pre_callback_item *item;
66 EINA_LIST_FOREACH_SAFE(s_info.widget_pre_callback_list[type], l, n, item) {
67 item->cb(id, item->data);
71 int widget_provider_app_add_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
73 struct pre_callback_item *item;
76 if (!cb || type == WIDGET_PRE_CALLBACK_COUNT) {
77 return WIDGET_ERROR_INVALID_PARAMETER;
80 EINA_LIST_FOREACH(s_info.widget_pre_callback_list[type], l, item) {
81 if (item->cb == cb && item->data == data) {
82 return WIDGET_ERROR_ALREADY_EXIST;
86 item = malloc(sizeof(*item));
88 ErrPrint("malloc: %d\n", errno);
89 return WIDGET_ERROR_OUT_OF_MEMORY;
95 s_info.widget_pre_callback_list[type] = eina_list_append(s_info.widget_pre_callback_list[type], item);
99 int widget_provider_app_del_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
103 struct pre_callback_item *item;
105 if (!cb || type == WIDGET_PRE_CALLBACK_COUNT) {
106 ErrPrint("Invalid parameter\n");
107 return WIDGET_ERROR_INVALID_PARAMETER;
110 EINA_LIST_FOREACH_SAFE(s_info.widget_pre_callback_list[type], l, n, item) {
111 if (item->cb == cb && item->data == data) {
112 s_info.widget_pre_callback_list[type] = eina_list_remove_list(s_info.widget_pre_callback_list[type], l);
114 return WIDGET_ERROR_NONE;
118 return WIDGET_ERROR_NOT_EXIST;
121 static int method_new(struct widget_event_arg *arg, int *width, int *height, double *priority, void *data)
124 struct widget_create_arg _arg;
125 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",
128 arg->info.widget_create.content,
129 arg->info.widget_create.timeout,
130 arg->info.widget_create.has_script,
131 arg->info.widget_create.period,
132 arg->info.widget_create.cluster, arg->info.widget_create.category,
133 arg->info.widget_create.skip_need_to_create,
134 arg->info.widget_create.abi,
135 arg->info.widget_create.width,
136 arg->info.widget_create.height);
138 if (!arg->info.widget_create.content || !strlen(arg->info.widget_create.content)) {
139 DbgPrint("Use default content: \"%s\"\n", WIDGET_CONF_DEFAULT_CONTENT);
140 arg->info.widget_create.content = WIDGET_CONF_DEFAULT_CONTENT;
143 _arg.content = arg->info.widget_create.content;
144 _arg.timeout = arg->info.widget_create.timeout;
145 _arg.has_widget_script = arg->info.widget_create.has_script;
146 _arg.period = arg->info.widget_create.period;
147 _arg.cluster = arg->info.widget_create.cluster;
148 _arg.category = arg->info.widget_create.category;
149 _arg.abi = arg->info.widget_create.abi;
150 _arg.skip_need_to_create = arg->info.widget_create.skip_need_to_create;
151 _arg.direct_addr = arg->info.widget_create.direct_addr;
153 invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
155 ret = widget_create(arg->pkgname, arg->id,
157 width, height, priority,
158 &arg->info.widget_create.out_content,
159 &arg->info.widget_create.out_title);
162 if (arg->info.widget_create.width > 0 && arg->info.widget_create.height > 0) {
163 DbgPrint("Create size: %dx%d (created: %dx%d)\n", arg->info.widget_create.width, arg->info.widget_create.height, *width, *height);
164 if (*width != arg->info.widget_create.width || *height != arg->info.widget_create.height) {
166 tmp = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.widget_create.width, arg->info.widget_create.height);
167 DbgPrint("widget_resize returns: %d\n", tmp);
168 if (tmp == (int)WIDGET_ERROR_NONE) {
171 * Just returns resized canvas size.
172 * Even if it is not ready to render contents.
173 * Provider will allocate render buffer using this size.
175 *width = arg->info.widget_create.width;
176 *height = arg->info.widget_create.height;
181 arg->info.widget_create.out_is_pinned_up = (widget_viewer_is_pinned_up(arg->pkgname, arg->id) == 1);
183 ErrPrint("widget_create returns %d\n", ret);
186 if (widget_is_all_paused()) {
187 DbgPrint("Box is paused\n");
188 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_PAUSED);
194 static int method_renew(struct widget_event_arg *arg, void *data)
200 struct widget_create_arg _arg;
202 DbgPrint("Re-create: pkgname[%s], id[%s], content[%s], timeout[%d], has_script[%d], period[%lf], cluster[%s], category[%s], abi[%s]\n",
203 arg->pkgname, arg->id,
204 arg->info.widget_recreate.content,
205 arg->info.widget_recreate.timeout,
206 arg->info.widget_recreate.has_script,
207 arg->info.widget_recreate.period,
208 arg->info.widget_recreate.cluster,
209 arg->info.widget_recreate.category,
210 arg->info.widget_recreate.abi);
212 if (!arg->info.widget_recreate.content || !strlen(arg->info.widget_recreate.content)) {
213 DbgPrint("Use default content: \"%s\"\n", WIDGET_CONF_DEFAULT_CONTENT);
214 arg->info.widget_recreate.content = WIDGET_CONF_DEFAULT_CONTENT;
217 _arg.content = arg->info.widget_recreate.content;
218 _arg.timeout = arg->info.widget_recreate.timeout;
219 _arg.has_widget_script = arg->info.widget_recreate.has_script;
220 _arg.period = arg->info.widget_recreate.period;
221 _arg.cluster = arg->info.widget_recreate.cluster;
222 _arg.category = arg->info.widget_recreate.category;
223 _arg.abi = arg->info.widget_recreate.abi;
224 _arg.skip_need_to_create = 1;
225 _arg.direct_addr = arg->info.widget_recreate.direct_addr;
227 invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
229 ret = widget_create(arg->pkgname, arg->id,
232 &arg->info.widget_recreate.out_content,
233 &arg->info.widget_recreate.out_title);
235 if (w != arg->info.widget_recreate.width || h != arg->info.widget_recreate.height) {
237 tmp = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.widget_recreate.width, arg->info.widget_recreate.height);
239 DbgPrint("Resize[%dx%d] returns: %d\n", arg->info.widget_recreate.width, arg->info.widget_recreate.height, tmp);
242 DbgPrint("No need to change the size: %dx%d\n", w, h);
245 arg->info.widget_recreate.out_is_pinned_up = (widget_viewer_is_pinned_up(arg->pkgname, arg->id) == 1);
247 ErrPrint("widget_create returns %d\n", ret);
250 if (widget_is_all_paused()) {
251 DbgPrint("Box is paused\n");
252 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_PAUSED);
258 static int method_delete(struct widget_event_arg *arg, void *data)
262 DbgPrint("pkgname[%s] id[%s]\n", arg->pkgname, arg->id);
264 if (arg->info.widget_destroy.type == WIDGET_DESTROY_TYPE_DEFAULT || arg->info.widget_destroy.type == WIDGET_DESTROY_TYPE_UNINSTALL) {
265 DbgPrint("Box is deleted from the viewer\n");
266 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_DELETED);
269 invoke_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, arg->id);
270 ret = widget_destroy(arg->pkgname, arg->id, 0);
274 static int method_content_event(struct widget_event_arg *arg, void *data)
277 struct widget_event_info info;
279 info = arg->info.content_event.info;
281 ret = widget_script_event(arg->pkgname, arg->id,
282 arg->info.content_event.signal_name, arg->info.content_event.source,
287 static int method_clicked(struct widget_event_arg *arg, void *data)
291 DbgPrint("pkgname[%s] id[%s] event[%s] timestamp[%lf] x[%lf] y[%lf]\n",
292 arg->pkgname, arg->id,
293 arg->info.clicked.event, arg->info.clicked.timestamp,
294 arg->info.clicked.x, arg->info.clicked.y);
295 ret = widget_clicked(arg->pkgname, arg->id,
296 arg->info.clicked.event,
297 arg->info.clicked.timestamp, arg->info.clicked.x, arg->info.clicked.y);
302 static int method_text_signal(struct widget_event_arg *arg, void *data)
305 struct widget_event_info info;
307 info = arg->info.text_signal.info;
309 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);
310 ret = widget_script_event(arg->pkgname, arg->id,
311 arg->info.text_signal.signal_name, arg->info.text_signal.source,
317 static int method_resize(struct widget_event_arg *arg, void *data)
321 invoke_pre_callback(WIDGET_PRE_RESIZE_CALLBACK, arg->id);
323 DbgPrint("pkgname[%s] id[%s] w[%d] h[%d]\n", arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
324 ret = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
329 static int method_set_period(struct widget_event_arg *arg, void *data)
332 DbgPrint("pkgname[%s] id[%s] period[%lf]\n", arg->pkgname, arg->id, arg->info.set_period.period);
333 ret = widget_viewer_set_period(arg->pkgname, arg->id, arg->info.set_period.period);
337 static int method_change_group(struct widget_event_arg *arg, void *data)
340 DbgPrint("pkgname[%s] id[%s] cluster[%s] category[%s]\n", arg->pkgname, arg->id, arg->info.change_group.cluster, arg->info.change_group.category);
341 ret = widget_change_group(arg->pkgname, arg->id, arg->info.change_group.cluster, arg->info.change_group.category);
345 static int method_pinup(struct widget_event_arg *arg, void *data)
347 DbgPrint("pkgname[%s] id[%s] state[%d]\n", arg->pkgname, arg->id, arg->info.pinup.state);
348 arg->info.pinup.content_info = widget_pinup(arg->pkgname, arg->id, arg->info.pinup.state);
349 return arg->info.pinup.content_info ? WIDGET_ERROR_NONE : WIDGET_ERROR_NOT_SUPPORTED;
352 static int method_update_content(struct widget_event_arg *arg, void *data)
356 if (!arg->id || !strlen(arg->id)) {
357 if (arg->info.update_content.content && strlen(arg->info.update_content.content)) {
358 DbgPrint("pkgname[%s] content[%s]\n", arg->pkgname, arg->info.update_content.content);
359 ret = widget_set_content_info_all(arg->pkgname, arg->info.update_content.content);
361 DbgPrint("pkgname[%s] cluster[%s] category[%s]\n", arg->pkgname, arg->info.update_content.cluster, arg->info.update_content.category);
362 ret = widget_update_all(arg->pkgname, arg->info.update_content.cluster, arg->info.update_content.category, arg->info.update_content.force);
365 if (arg->info.update_content.content && strlen(arg->info.update_content.content)) {
366 DbgPrint("id[%s] content[%s]\n", arg->id, arg->info.update_content.content);
367 ret = widget_set_content_info(arg->pkgname, arg->id, arg->info.update_content.content);
369 DbgPrint("Update [%s]\n", arg->id);
370 ret = widget_update(arg->pkgname, arg->id, arg->info.update_content.force);
377 static int method_pause(struct widget_event_arg *arg, void *data)
381 if (s_info.ping_timer) {
382 ecore_timer_freeze(s_info.ping_timer);
385 if (WIDGET_CONF_SLAVE_AUTO_CACHE_FLUSH) {
386 elm_cache_all_flush();
387 sqlite3_release_memory(WIDGET_CONF_SQLITE_FLUSH_MAX);
391 return WIDGET_ERROR_NONE;
394 static int method_resume(struct widget_event_arg *arg, void *data)
398 if (s_info.ping_timer) {
399 ecore_timer_thaw(s_info.ping_timer);
402 return WIDGET_ERROR_NONE;
405 static Eina_Bool send_ping_cb(void *data)
407 widget_provider_send_ping();
408 return ECORE_CALLBACK_RENEW;
411 static int method_disconnected(struct widget_event_arg *arg, void *data)
413 if (s_info.ping_timer) {
414 ecore_timer_del(s_info.ping_timer);
415 s_info.ping_timer = NULL;
419 return WIDGET_ERROR_NONE;
422 static int method_connected(struct widget_event_arg *arg, void *data)
425 ret = widget_provider_send_hello();
427 double ping_interval;
429 ping_interval = WIDGET_CONF_DEFAULT_PING_TIME / 2.0f;
430 DbgPrint("Ping Timer: %lf\n", ping_interval);
432 s_info.ping_timer = ecore_timer_add(ping_interval, send_ping_cb, NULL);
433 if (!s_info.ping_timer) {
434 ErrPrint("Failed to add a ping timer\n");
438 return WIDGET_ERROR_NONE;
441 static int method_gbar_created(struct widget_event_arg *arg, void *data)
445 ret = widget_open_gbar(arg->pkgname, arg->id);
447 DbgPrint("%s Open PD: %d\n", arg->id, ret);
450 return WIDGET_ERROR_NONE;
453 static int method_gbar_destroyed(struct widget_event_arg *arg, void *data)
457 ret = widget_close_gbar(arg->pkgname, arg->id);
459 DbgPrint("%s Close PD: %d\n", arg->id, ret);
462 return WIDGET_ERROR_NONE;
465 static int method_gbar_moved(struct widget_event_arg *arg, void *data)
468 struct widget_event_info info;
470 memset(&info, 0, sizeof(info));
471 info.pointer.x = arg->info.gbar_move.x;
472 info.pointer.y = arg->info.gbar_move.y;
473 info.pointer.down = 0;
475 ret = widget_script_event(arg->pkgname, arg->id,
476 "gbar,move", util_uri_to_path(arg->id), &info);
480 static int method_widget_pause(struct widget_event_arg *arg, void *data)
484 ret = widget_pause(arg->pkgname, arg->id);
486 if (WIDGET_CONF_SLAVE_AUTO_CACHE_FLUSH) {
487 elm_cache_all_flush();
488 sqlite3_release_memory(WIDGET_CONF_SQLITE_FLUSH_MAX);
495 static int method_widget_resume(struct widget_event_arg *arg, void *data)
497 return widget_resume(arg->pkgname, arg->id);
500 static int method_viewer_connected(struct widget_event_arg *arg, void *data)
502 return widget_viewer_connected(arg->pkgname, arg->id, arg->info.viewer_connected.direct_addr);
505 static int method_viewer_disconnected(struct widget_event_arg *arg, void *data)
507 return widget_viewer_disconnected(arg->pkgname, arg->id, arg->info.viewer_disconnected.direct_addr);
510 static int method_orientation(struct widget_event_arg *arg, void *data)
512 invoke_pre_callback(WIDGET_PRE_ORIENTATION_CALLBACK, arg->id);
513 return widget_set_orientation(arg->pkgname, arg->id, arg->info.orientation.degree);
516 HAPI int client_init(const char *name, const char *abi, const char *accel, int secured)
518 struct widget_event_table table = {
519 .widget_create = method_new,
520 .widget_recreate = method_renew,
521 .widget_destroy = method_delete,
522 .content_event = method_content_event,
523 .clicked = method_clicked,
524 .text_signal = method_text_signal,
525 .resize = method_resize,
526 .set_period = method_set_period,
527 .change_group = method_change_group,
528 .pinup = method_pinup,
529 .update_content = method_update_content,
530 .pause = method_pause,
531 .resume = method_resume,
532 .disconnected = method_disconnected,
533 .connected = method_connected,
534 .gbar_create = method_gbar_created,
535 .gbar_destroy = method_gbar_destroyed,
536 .gbar_move = method_gbar_moved,
537 .widget_pause = method_widget_pause,
538 .widget_resume = method_widget_resume,
539 .viewer_connected = method_viewer_connected,
540 .viewer_disconnected = method_viewer_disconnected,
541 .orientation = method_orientation,
544 widget_provider_prepare_init(abi, accel, secured);
545 return widget_provider_init(util_screen_get(), name, &table, NULL, 1, 1);
548 HAPI int client_fini(void)
550 (void)widget_provider_fini();
551 return WIDGET_ERROR_NONE;