Create widget base API set
[platform/core/appfw/appcore-widget.git] / src / efl_base / widget_app.c
1 /*
2  * Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
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
18 #include <stdlib.h>
19 #include <glib.h>
20
21 #include <bundle.h>
22 #include <aul.h>
23 #include <dlog.h>
24 #include <Elementary.h>
25 #include <widget_errno.h>
26 #include <widget_instance.h>
27
28 #include "widget_base.h"
29 #include "widget_app.h"
30 #include "widget-log.h"
31 #include "widget-private.h"
32 #include "widget_app_internal.h"
33
34 #ifdef LOG_TAG
35 #undef LOG_TAG
36 #endif
37
38 #define LOG_TAG "CAPI_WIDGET_APPLICATION"
39
40 struct instance_data {
41         Evas_Object *win;
42 };
43
44 struct app_cb_info {
45         widget_app_lifecycle_callback_s *callback;
46         void *user_data;
47 };
48
49 struct app_class_cb_info {
50         widget_instance_lifecycle_callback_s callback;
51         void *user_data;
52 };
53
54 static int __class_resize(widget_base_instance_h instance_h, int w, int h,
55                 void *class_data)
56 {
57         int ret = 0;
58         struct instance_data *data;
59         struct app_class_cb_info *callback_data =
60                         (struct app_class_cb_info *)class_data;
61
62         widget_base_class_on_resize(instance_h, w, h);
63         data = (struct instance_data *)
64                         widget_base_context_get_user_data(instance_h);
65         if (data->win)
66                 evas_object_resize(data->win, w, h);
67         else
68                 _E("unable to find window");
69
70         if (callback_data && callback_data->callback.resize) {
71                 ret = callback_data->callback.resize(
72                                 (widget_context_h)instance_h,
73                                 w, h, callback_data->user_data);
74         }
75
76         return ret;
77 }
78
79 static int __class_update(widget_base_instance_h instance_h, bundle *content,
80                 int force, void *class_data)
81 {
82         int ret = 0;
83         struct app_class_cb_info *callback_data =
84                         (struct app_class_cb_info *)class_data;
85
86         widget_base_class_on_update(instance_h, content, force);
87         if (callback_data && callback_data->callback.update) {
88                 ret = callback_data->callback.update(
89                                 (widget_context_h)instance_h,
90                                 content, force, callback_data->user_data);
91         }
92
93         return ret;
94 }
95
96 static int __class_create(widget_base_instance_h instance_h, bundle *content,
97                 int w, int h, void *class_data)
98 {
99         int ret = -1;
100         struct app_class_cb_info *callback_data =
101                         (struct app_class_cb_info *)class_data;
102
103         widget_base_class_on_create(instance_h, content, w, h);
104         if (callback_data && callback_data->callback.create) {
105                 ret = callback_data->callback.create(
106                                 (widget_context_h)instance_h,
107                                 content, w, h, callback_data->user_data);
108         }
109         return ret;
110 }
111
112 static int __class_destroy(widget_base_instance_h instance_h,
113                 widget_base_destroy_type_e reason, bundle *content,
114                 void *class_data)
115 {
116         int ret = 0;
117         struct instance_data *data;
118         struct app_class_cb_info *callback_data =
119                         (struct app_class_cb_info *)class_data;
120
121         if (callback_data && callback_data->callback.destroy) {
122                 ret = callback_data->callback.destroy(
123                                 (widget_context_h)instance_h,
124                                 reason, content, callback_data->user_data);
125         }
126
127         data = (struct instance_data *)widget_base_context_get_user_data(instance_h);
128         if (data != NULL) {
129                 widget_base_context_set_user_data(instance_h, NULL);
130                 free(data);
131         }
132
133         widget_base_class_on_destroy(instance_h, reason, content);
134
135         return ret;
136 }
137
138 static int __class_pause(widget_base_instance_h instance_h, void *class_data)
139 {
140         int ret = 0;
141         struct app_class_cb_info *callback_data =
142                         (struct app_class_cb_info *)class_data;
143
144         widget_base_class_on_pause(instance_h);
145         if (callback_data && callback_data->callback.pause) {
146                 ret = callback_data->callback.pause(
147                                 (widget_context_h)instance_h,
148                                 callback_data->user_data);
149         }
150
151         return ret;
152 }
153
154 static int __class_resume(widget_base_instance_h instance_h, void *class_data)
155 {
156         int ret = 0;
157         struct app_class_cb_info *callback_data =
158                         (struct app_class_cb_info *)class_data;
159
160         widget_base_class_on_resume(instance_h);
161         if (callback_data && callback_data->callback.resume) {
162                 ret = callback_data->callback.resume(
163                                 (widget_context_h)instance_h,
164                                 callback_data->user_data);
165         }
166
167         return ret;
168 }
169
170 static int __widget_app_create(void *data)
171 {
172         struct app_cb_info *cb_info = (struct app_cb_info *)data;
173         widget_app_lifecycle_callback_s *callback;
174
175         widget_base_on_create();
176         if (cb_info && cb_info->callback && cb_info->callback->create) {
177                 callback = cb_info->callback;
178                 if (callback->create(cb_info->user_data) == NULL) {
179                         _D("fail to create widget");
180                         return -1;
181                 }
182                 _D("widget app is created");
183                 return 0;
184         }
185
186         return -1;
187 }
188
189 static int __widget_app_terminate(void *data)
190 {
191         struct app_cb_info *cb_info = (struct app_cb_info *)data;
192         widget_app_lifecycle_callback_s *callback;
193
194         if (cb_info && cb_info->callback && cb_info->callback->terminate) {
195                 callback = cb_info->callback;
196                 callback->terminate(cb_info->user_data);
197                 widget_base_on_terminate();
198                 _D("widget app is terminated");
199
200                 return 0;
201         }
202
203         widget_base_on_terminate();
204
205         return -1;
206 }
207
208 static void __widget_app_init(int argc, char **argv, void *data)
209 {
210         elm_init(argc, argv);
211 }
212
213 static void __widget_app_finish(void)
214 {
215         elm_shutdown();
216 }
217
218 static void __widget_app_run(void *data)
219 {
220         elm_run();
221 }
222
223 static void __widget_app_exit(void *data)
224 {
225         elm_exit();
226 }
227
228 EXPORT_API int widget_app_main(int argc, char **argv,
229                 widget_app_lifecycle_callback_s *callback, void *user_data)
230 {
231         widget_base_ops ops;
232         struct app_cb_info cb_info;
233         int r;
234
235         if (argc <= 0 || argv == NULL || callback == NULL)
236                 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
237                                 __FUNCTION__, NULL);
238
239         if (callback->create == NULL)
240                 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
241                                 __FUNCTION__,
242                                 "widget_app_create_cb() callback must be "
243                                 "registered");
244
245         ops.create = __widget_app_create;
246         ops.terminate = __widget_app_terminate;
247         ops.init = __widget_app_init;
248         ops.finish = __widget_app_finish;
249         ops.run = __widget_app_run;
250         ops.exit = __widget_app_exit;
251
252         cb_info.callback = callback;
253         cb_info.user_data = user_data;
254
255         r = widget_base_init(ops, argc, argv, &cb_info);
256         widget_base_fini();
257
258         return r;
259 }
260
261 EXPORT_API int widget_app_exit(void)
262 {
263         return widget_base_exit();
264 }
265
266 EXPORT_API int widget_app_terminate_context(widget_context_h context)
267 {
268         return widget_base_terminate_context((widget_base_instance_h)context);
269 }
270
271 EXPORT_API int widget_app_foreach_context(widget_context_cb cb, void *data)
272 {
273         return widget_base_foreach_context((widget_base_instance_cb)cb, data);
274 }
275
276 EXPORT_API int widget_app_add_event_handler(app_event_handler_h *event_handler,
277                                         app_event_type_e event_type,
278                                         app_event_cb callback,
279                                         void *user_data)
280 {
281         return widget_base_add_event_handler(event_handler, event_type,
282                                         callback, user_data);
283 }
284
285 EXPORT_API int widget_app_remove_event_handler(app_event_handler_h
286                                                 event_handler)
287 {
288         return widget_base_remove_event_handler(event_handler);
289 }
290
291 EXPORT_API const char *widget_app_get_id(widget_context_h context)
292 {
293         int ret;
294         char *id;
295
296         if (!context) {
297                 set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
298                 return NULL;
299         }
300
301         ret = widget_base_context_get_id((widget_base_instance_h)context, &id);
302         if (ret != WIDGET_BASE_ERROR_NONE) {
303                 _E("failed to get context id"); /* LCOV_EXCL_LINE */
304                 set_last_result(ret); /* LCOV_EXCL_LINE */
305                 return NULL; /* LCOV_EXCL_LINE */
306         }
307
308         set_last_result(WIDGET_ERROR_NONE);
309         return id;
310 }
311
312 static void __win_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
313 {
314         char *plug_id;
315         plug_id = evas_object_data_del(obj, "___PLUGID");
316         free(plug_id);
317 }
318
319 EXPORT_API int widget_app_get_elm_win(widget_context_h context,
320                                         Evas_Object **win)
321 {
322         Evas_Object *ret_win = NULL;
323         Ecore_Wl_Window *wl_win;
324         struct instance_data *data;
325         char buffer[256];
326         int rots[3] = {0};
327         int win_id;
328         char *id;
329         int ret;
330
331         if (context == NULL || win == NULL)
332                 return widget_app_error(WIDGET_ERROR_INVALID_PARAMETER,
333                                 __FUNCTION__, NULL);
334
335         ret = widget_base_context_get_id((widget_base_instance_h)context, &id);
336         if (ret != WIDGET_BASE_ERROR_NONE) {
337                 _E("failed to get context id"); /* LCOV_EXCL_LINE */
338                 goto fault; /* LCOV_EXCL_LINE */
339         }
340
341         ret_win = elm_win_add(NULL, id, ELM_WIN_BASIC);
342         if (ret_win == NULL) {
343                 _E("failed to create window"); /* LCOV_EXCL_LINE */
344                 goto fault; /* LCOV_EXCL_LINE */
345         }
346
347         elm_win_wm_rotation_preferred_rotation_set(ret_win, -1);
348         elm_win_wm_rotation_available_rotations_set(ret_win, rots, 1);
349
350         wl_win = elm_win_wl_window_get(ret_win);
351         if (wl_win == NULL) {
352                 _E("failed to get wayland window"); /* LCOV_EXCL_LINE */
353                 goto fault;
354         }
355
356         ecore_wl_window_class_name_set(wl_win, id);
357         elm_win_aux_hint_add(ret_win, "wm.policy.win.user.geometry", "1");
358         widget_base_context_window_bind((widget_base_instance_h)context,        id, wl_win);
359
360         /* Set data to use in accessibility */
361         snprintf(buffer, sizeof(buffer), "%s:%d", id, getpid());
362         evas_object_data_set(ret_win, "___PLUGID", strdup(buffer));
363         evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL, __win_del_cb, NULL);
364
365         win_id = ecore_wl_window_id_get(wl_win);
366         _D("window created: %d", win_id);
367
368         data = (struct instance_data *)widget_base_context_get_user_data(
369                         (widget_base_instance_h)context);
370         if (data == NULL) {
371                 data = calloc(1, sizeof(struct instance_data));
372                 if (data == NULL) {
373                         _E("failed to alloc instance_data"); /* LCOV_EXCL_LINE */
374                         goto fault; /* LCOV_EXCL_LINE */
375                 }
376
377                 ret = widget_base_context_set_user_data((widget_base_instance_h)context, data);
378                 if (ret != WIDGET_BASE_ERROR_NONE) {
379                         _E("fail to set extra data"); /* LCOV_EXCL_LINE */
380                         goto fault; /* LCOV_EXCL_LINE */
381                 }
382         }
383
384         data->win = ret_win;
385         *win = ret_win;
386
387         return WIDGET_ERROR_NONE;
388
389 fault:
390         if (ret_win)    /* LCOV_EXCL_LINE */
391                 evas_object_del(ret_win); /* LCOV_EXCL_LINE */
392
393         return WIDGET_ERROR_FAULT; /* LCOV_EXCL_LINE */
394 }
395
396 EXPORT_API widget_class_h widget_app_class_add(widget_class_h widget_class,
397                 const char *class_id,
398                 widget_instance_lifecycle_callback_s callback, void *user_data)
399 {
400         widget_base_class cls;
401         struct app_class_cb_info *callback_data;
402         widget_class_h wc;
403
404         cls = widget_base_class_get_default();
405
406         /* override methods */
407         cls.ops.create = __class_create;
408         cls.ops.destroy = __class_destroy;
409         cls.ops.pause = __class_pause;
410         cls.ops.resume = __class_resume;
411         cls.ops.resize = __class_resize;
412         cls.ops.update = __class_update;
413
414         callback_data = calloc(1, sizeof(struct app_class_cb_info));
415         if (!callback_data) {
416                 _E("failed to calloc : %s", __FUNCTION__);
417                 set_last_result(WIDGET_ERROR_OUT_OF_MEMORY);
418                 return NULL;
419         }
420         callback_data->callback = callback;
421         callback_data->user_data = user_data;
422
423         wc = (widget_class_h)widget_base_class_add(cls, class_id,
424                         callback_data);
425
426         if (!wc) {
427                 free(callback_data);
428                 return NULL;
429         }
430
431         set_last_result(WIDGET_ERROR_NONE);
432
433         return wc;
434 }
435
436 EXPORT_API widget_class_h widget_app_class_create(
437                 widget_instance_lifecycle_callback_s callback, void *user_data)
438 {
439         char *appid;
440         widget_class_h wc;
441
442         app_get_id(&appid);
443         if (!appid) {
444                 LOGE("appid is NULL");
445                 return NULL;
446         }
447
448         wc = (widget_class_h)widget_app_class_add(NULL, appid, callback,
449                         user_data);
450         free(appid);
451
452         return wc;
453 }
454
455 EXPORT_API int widget_app_context_set_tag(widget_context_h context, void *tag)
456 {
457         int ret = 0;
458
459         ret = widget_base_context_set_tag((widget_base_instance_h)context, tag);
460         if (ret != WIDGET_BASE_ERROR_NONE)
461                 return widget_app_error(ret, __FUNCTION__, NULL);
462
463         return WIDGET_ERROR_NONE;
464 }
465
466 EXPORT_API int widget_app_context_get_tag(widget_context_h context, void **tag)
467 {
468         int ret = 0;
469
470         ret = widget_base_context_get_tag((widget_base_instance_h)context, tag);
471         if (ret != WIDGET_BASE_ERROR_NONE)
472                 return widget_app_error(ret, __FUNCTION__, NULL);
473
474         return WIDGET_ERROR_NONE;
475 }
476
477 EXPORT_API int widget_app_context_set_content_info(widget_context_h context,
478                 bundle *content_info)
479 {
480         int ret = 0;
481
482         ret = widget_base_context_set_content_info(
483                         (widget_base_instance_h)context, content_info);
484         if (ret != WIDGET_BASE_ERROR_NONE)
485                 return widget_app_error(ret, __FUNCTION__, NULL);
486
487         return WIDGET_ERROR_NONE;
488 }
489
490 EXPORT_API int widget_app_context_set_title(widget_context_h context,
491                 const char *title)
492 {
493         struct instance_data *data = NULL;
494         int ret;
495
496         if (!context || !title) {
497                 _E("Invalid parameter %p %p", context, title);
498                 return WIDGET_ERROR_INVALID_PARAMETER;
499         }
500
501         data = (struct instance_data *)widget_base_context_get_user_data(
502                         (widget_base_instance_h)context);
503         if (data == NULL) {
504                 data = calloc(1, sizeof(struct instance_data));
505                 if (data == NULL) {
506                         return widget_app_error(WIDGET_ERROR_FAULT,
507                                         __FUNCTION__, NULL);
508                 }
509                 ret = widget_base_context_set_user_data(context, data);
510                 if (ret != WIDGET_BASE_ERROR_NONE)
511                         widget_app_error(ret, __FUNCTION__, NULL);
512         }
513
514         if (data->win)
515                 elm_win_title_set(data->win, title);
516
517         return WIDGET_ERROR_NONE;
518 }