9215e24dd371958ec80a36c48e9fad52b4706730
[platform/core/appfw/ui-gadget-1.git] / client / ug-client.c
1 /*
2  *  UI Gadget
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <appcore-efl.h>
24 #include <ui-gadget.h>
25
26 #include <dlog.h>
27 #include <aul.h>
28 #include <app.h>
29 #include <vconf.h>
30
31 #include "ug-client.h"
32
33 #include <tzplatform_config.h>
34
35 #ifdef LOG_TAG
36 #undef LOG_TAG
37 #endif
38
39 #define PATH_UG_LAUNCHER tzplatform_mkpath(TZ_SYS_BIN,"ug-launcher")
40
41 #define LOG_TAG "UI_GADGET_CLIENT"
42
43 static void prt_usage(const char *cmd)
44 {
45         fprintf(stderr, "Usage: %s [-f] [-F] -n <UG NAME> [-d <Arguments>]\n",
46                 cmd);
47         fprintf(stderr, "   Options:\n");
48         fprintf(stderr, "            -d argument\n");
49         fprintf(stderr, "            -F Fullview mode (Default)\n");
50         fprintf(stderr, "            -f Frameview mode\n");
51         fprintf(stderr, "   Example:\n");
52         fprintf(stderr,
53                 "            %s -F -n helloUG-efl -d \"name,John Doe\" -d \"age,30\"\n",
54                 cmd);
55
56 }
57
58 static void win_del(void *data, Evas_Object *obj, void *event)
59 {
60         elm_exit();
61 }
62
63 static void main_quit_cb(void *data, Evas_Object *obj,
64                          const char *emission, const char *source)
65 {
66         elm_exit();
67 }
68
69 static int ug_send_rotate_event(int angle)
70 {
71         int ret = -1;
72         LOGD("ug_send_rotate_event angle : %d", angle);
73         switch(angle) {
74                 case 0 :
75                         ret = ug_send_event(UG_EVENT_ROTATE_PORTRAIT);
76                         break;
77                 case 90 :
78                         ret = ug_send_event(UG_EVENT_ROTATE_LANDSCAPE_UPSIDEDOWN);
79                         break;
80                 case 180 :
81                         ret = ug_send_event(UG_EVENT_ROTATE_PORTRAIT_UPSIDEDOWN);
82                         break;
83                 case 270 :
84                         ret = ug_send_event(UG_EVENT_ROTATE_LANDSCAPE);
85                         break;
86                 default :
87                         LOGW("wrong angle(%d) for send rotate event",angle);
88                         break;
89         }
90
91         return ret;
92 }
93
94 static void rotate(void *data, Evas_Object *obj, void *event)
95 {
96         int changed_angle = 0;
97         struct appdata *ad = data;
98
99         changed_angle = elm_win_rotation_get((const Evas_Object *)obj);
100         if(changed_angle == -1) {
101                 LOGE("elm_win_rotation_get error");
102                 return;
103         }
104
105         LOGD("rotate call back : changed angle(%d) / current angle(%d)",
106                 changed_angle, ad->rotate);
107
108         if(ad->rotate != changed_angle) {
109                 ug_send_rotate_event(changed_angle);
110         }
111
112         ad->rotate = changed_angle;
113
114         return;
115 }
116
117 void _ug_client_layout_cb(ui_gadget_h ug, enum ug_mode mode, void *priv)
118 {
119         struct appdata *ad;
120         Evas_Object *base;
121
122         if (!ug || !priv)
123                 return;
124
125         ad = priv;
126
127         base = ug_get_layout(ug);
128         if (!base) {
129                 LOGE("base layout is null");
130                 return;
131         }
132
133         switch (mode) {
134         case UG_MODE_FULLVIEW:
135                 evas_object_size_hint_weight_set(base, EVAS_HINT_EXPAND,
136                                                  EVAS_HINT_EXPAND);
137                 ug_disable_effect(ug);
138                 elm_object_content_set(ad->ly_main, base);
139                 evas_object_show(base);
140                 break;
141         case UG_MODE_FRAMEVIEW:
142                 elm_object_part_content_set(ad->ly_main, "content", base);
143                 break;
144         default:
145                 break;
146         }
147 }
148
149 void _ug_client_result_cb(ui_gadget_h ug, service_h reply, void *priv)
150 {
151         struct appdata *ad = NULL;
152         int ret;
153         char* value = NULL;
154         int result;
155
156         if (!ug || !priv)
157                 return;
158
159         ret = service_get_extra_data (reply, UG_SERVICE_DATA_RESULT, &value);
160         if((ret == SERVICE_ERROR_NONE) && (value)) {
161                 result = atoi(value);
162                 LOGD("reply result is %d", result);
163         } else {
164                 LOGW("get reply result error(%d) . result will be SERVICE_RESULT_SUCCEEDED", ret);
165                 result = SERVICE_RESULT_SUCCEEDED;
166         }
167
168         ad = priv;
169         if (!ad) {
170                 LOGE("appdata is null");
171                 return;
172         }
173
174         ret = service_reply_to_launch_request(reply, ad->request, (service_result_e)result);
175         if (ret != SERVICE_ERROR_NONE)
176                 LOGE("service_reply_to_launch_request failed, %d", ret);
177 }
178
179 void _ug_client_destroy_cb(ui_gadget_h ug, void *priv)
180 {
181         struct appdata *ad = NULL;
182
183         if (!ug)
184                 return;
185
186         ad = priv;
187         if (!ad) {
188                 LOGE("appdata is null. win lower is fail");
189         } else {
190                 LOGD("window lower");
191                 elm_win_lower(ad->win);
192         }
193
194         elm_exit();
195 }
196
197 void _ug_client_end_cb(ui_gadget_h ug, void *priv)
198 {
199         if (!ug)
200                 return;
201
202         LOGD("_ug_client_end_cb invoked");
203
204         elm_exit();
205 }
206
207 static void profile_changed_cb(void *data, Evas_Object * obj, void *event)
208 {
209         const char *profile = elm_config_profile_get();
210
211         LOGE("!!! profile_changed_cb(%s) !!!", profile);
212
213         if (strcmp(profile, "desktop") == 0)
214                 elm_win_indicator_mode_set(obj, ELM_WIN_INDICATOR_HIDE);
215 }
216
217 static Evas_Object *create_win(const char *name)
218 {
219         Ecore_Evas *ee;
220         Evas_Object *eo;
221         int w, h;
222
223         eo = elm_win_add(NULL, name, ELM_WIN_BASIC);
224         if (eo) {
225                 elm_win_title_set(eo, name);
226                 elm_win_conformant_set(eo, EINA_TRUE);
227                 evas_object_smart_callback_add(eo, "delete,request",
228                                                win_del, NULL);
229                 /* disable destktop mode
230                 evas_object_smart_callback_add(eo, "profile,changed", profile_changed_cb, NULL); */
231                 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(eo));
232                 evas_output_size_get(ee, &w, &h);
233                 evas_object_resize(eo, w, h);
234
235                 elm_win_indicator_mode_set(eo,ELM_WIN_INDICATOR_SHOW);
236         }
237
238         return eo;
239 }
240
241 static Evas_Object *_ug_client_load_edj(Evas_Object *parent, const char *file,
242                              const char *group)
243 {
244         Evas_Object *eo;
245         int r;
246         eo = elm_layout_add(parent);
247         if (eo) {
248                 r = elm_layout_file_set(eo, file, group);
249                 if (!r) {
250                         evas_object_del(eo);
251                         return NULL;
252                 }
253                 evas_object_size_hint_weight_set(eo,
254                                                  EVAS_HINT_EXPAND,
255                                                  EVAS_HINT_EXPAND);
256         }
257         return eo;
258 }
259
260 static int low_memory(void *data)
261 {
262         return ug_send_event(UG_EVENT_LOW_MEMORY);
263 }
264
265 static int low_battery(void *data)
266 {
267         return ug_send_event(UG_EVENT_LOW_BATTERY);
268 }
269
270 static int lang_changed(void *data)
271 {
272         char* lang = NULL;
273
274         lang = vconf_get_str(VCONFKEY_LANGSET);
275         if(lang) {
276                 LOGD("lang : %s", lang);
277                 elm_language_set((const char*)lang);
278                 free(lang);
279         } else {
280                 LOGW("language get error");
281         }
282
283         return ug_send_event(UG_EVENT_LANG_CHANGE);
284 }
285
286 static int region_changed(void *data)
287 {
288         return ug_send_event(UG_EVENT_REGION_CHANGE);
289 }
290
291 static void _home_screen_top_cb(keynode_t* node, void *data)
292 {
293         struct appdata *ad = data;
294
295         if (!node) {
296                 LOGE("home screen top cb node value is null");
297                 return;
298         }
299
300         if ((vconf_keynode_get_int(node) == VCONFKEY_IDLE_SCREEN_TOP_TRUE) && (!ad->is_transient)) {
301                 LOGW("home key pressed. window is not transient. ug client will be terminated");
302                 elm_exit();
303         }
304 }
305
306 static int app_create(void *data)
307 {
308         struct appdata *ad = data;
309         Evas_Object *win;
310         Evas_Object *ly;
311         Evas_Object *conform;
312         Evas_Object *bg;
313
314         /* create window */
315         win = create_win(PACKAGE);
316         if (win == NULL)
317                 return -1;
318         ad->win = win;
319
320         UG_INIT_EFL(ad->win, UG_OPT_INDICATOR_ENABLE);
321
322         bg = elm_bg_add(win);
323         evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
324         elm_win_resize_object_add(win, bg);
325         evas_object_show(bg);
326
327         conform = elm_conformant_add(win);
328         evas_object_size_hint_weight_set(conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
329         ad->conform = conform;
330
331         /* load edje */
332         ly = _ug_client_load_edj(conform, EDJ_FILE, GRP_MAIN);
333         if (ly == NULL)
334                 return -1;
335         elm_win_resize_object_add(win, conform);
336
337         evas_object_show(conform);
338         elm_object_content_set(conform, ly);
339         edje_object_signal_callback_add(elm_layout_edje_get(ly),
340                                         "EXIT", "*", main_quit_cb, NULL);
341         ad->ly_main = ly;
342         lang_changed(ad);
343
344         /* rotate notice */
345         int angle = -1;
346         angle = elm_win_rotation_get((const Evas_Object *)win);
347         LOGE("rotate : %d", angle);
348         if(angle != -1) {
349                 ug_send_rotate_event(angle);
350                 ad->rotate = angle;
351         } else {
352                 LOGE("elm win rotation get error");
353         }
354     /*
355         if(elm_win_wm_rotation_supported_get(win)) {
356                 int rots[4] = { 0, 90, 180, 270 };
357                 elm_win_wm_rotation_available_rotations_set(win, (const int*)&rots, 4);
358         } else {
359                 LOGW("wm rotation supported get error");
360         }
361     */
362         evas_object_smart_callback_add(win, "wm,rotation,changed", rotate, data);
363
364         appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, low_memory, ad);
365         appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, low_battery, ad);
366         appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, lang_changed, ad);
367         appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, region_changed, ad);
368
369         return 0;
370 }
371
372 static int app_terminate(void *data)
373 {
374         struct appdata *ad = data;
375
376         LOGD("app_terminate called");
377
378         evas_object_smart_callback_del(ad->win, "wm,rotation,changed", rotate);
379
380         ug_destroy_all();
381
382         if (ad->ly_main) {
383                 evas_object_del(ad->ly_main);
384                 ad->ly_main = NULL;
385         }
386
387         if (ad->win) {
388                 evas_object_del(ad->win);
389                 ad->win = NULL;
390         }
391
392         service_destroy(ad->request);
393
394         if (ad->name) {
395                 free(ad->name);
396         }
397
398         LOGD("app_terminate end");
399
400         return 0;
401 }
402
403 static int app_pause(void *data)
404 {
405         struct appdata *ad = data;
406
407         LOGD("app_pause called");
408
409         ug_pause();
410
411 #if ENABLE_TRANSIENT_SUB_MODE
412         if (!ad->is_transient) {
413                 LOGD("app_pause received. close ug service");
414                 elm_exit();
415         }
416 #endif
417
418         return 0;
419 }
420
421 static int app_resume(void *data)
422 {
423         ug_resume();
424         return 0;
425 }
426
427 static int svc_cb(void *data)
428 {
429         LOGD("svc_cb called");
430         return 0;
431 }
432
433 static int app_reset(bundle *b, void *data)
434 {
435         struct appdata *ad = data;
436         struct ug_cbs cbs = { 0, };
437         service_h service;
438         enum ug_mode mode = UG_MODE_FULLVIEW;
439         int ret;
440         Ecore_X_Window id2 = elm_win_xwindow_get(ad->win);
441
442         ret = appsvc_request_transient_app(b, id2, svc_cb, "svc test");
443
444         if (ret) {
445                 LOGD("fail to request transient app: return value(%d)", ret);
446                 if(vconf_notify_key_changed(VCONFKEY_IDLE_SCREEN_TOP, _home_screen_top_cb, ad) != 0) {
447                         LOGW("home screen vconf key changed cb error");
448                 }
449         } else {
450                 /* check home screen raise */
451                 ad->is_transient = 1;
452         }
453
454         if (ad->win) {
455                 elm_win_activate(ad->win);
456                 evas_object_show(ad->win);
457         }
458
459         if (ad->data)   /* ug-launcher */
460                 service_create_event(ad->data, &service);
461         else
462                 service_create_event(b, &service);
463
464         if(service) {
465                 service_clone(&ad->request, service);
466                 service_destroy(service);
467         }
468
469         cbs.layout_cb = _ug_client_layout_cb;
470         cbs.destroy_cb = _ug_client_destroy_cb;
471         cbs.result_cb = _ug_client_result_cb;
472         cbs.end_cb = _ug_client_end_cb;
473         cbs.priv = ad;
474
475         mode = ad->is_frameview ? UG_MODE_FRAMEVIEW : UG_MODE_FULLVIEW;
476
477         ad->ug = ug_create(NULL, ad->name, mode, ad->request, &cbs);
478         if (ad->ug == NULL) {
479                 LOGE("ug_create fail: %s", ad->name);
480                 elm_exit();
481         }
482
483         return 0;
484 }
485
486 static int update_argument(const char *optarg, struct appdata *ad)
487 {
488         const char *key;
489         const char *val;
490         key = strtok((char *)optarg, ",");
491         if (!key)
492                 return -1;
493
494         val = optarg + strlen(key) + 1;
495
496         if (!ad->data)
497                 ad->data = bundle_create();
498         if (!ad->data)
499                 return -1;
500         bundle_add(ad->data, key, val);
501         return 0;
502 }
503
504 int main(int argc, char *argv[])
505 {
506         int opt;
507         struct appdata ad;
508         struct appcore_ops ops = {
509                 .create = app_create,
510                 .terminate = app_terminate,
511                 .pause = app_pause,
512                 .resume = app_resume,
513                 .reset = app_reset,
514         };
515         int cmdlen = 0;
516
517         memset(&ad, 0x0, sizeof(struct appdata));
518         ops.data = &ad;
519
520         cmdlen = strlen(argv[0]);
521         if (strncmp(argv[0], "ug-launcher", cmdlen) == 0
522                 || strncmp(argv[0], PATH_UG_LAUNCHER , cmdlen) == 0) {
523                 while ((opt = getopt(argc, argv, "n:d:")) != -1) {
524                         switch (opt) {
525                         case 'n':
526                                 if (optarg)
527                                         ad.name = strdup(optarg);
528                                 break;
529                         case 'f':
530                                 ad.is_frameview = 1;
531                                 break;
532                         case 'F':
533                                 ad.is_frameview = 0;
534                                 break;
535                         case 'd':
536                                 if (update_argument(optarg, &ad)) {
537                                         if (ad.data)
538                                                 bundle_free(ad.data);
539                                         prt_usage(argv[0]);
540                                         return -1;
541                                 }
542                                 break;
543                         default:
544                                 prt_usage(argv[0]);
545                                 return -1;
546                         }
547                 }
548
549                 if (!ad.name) {
550                         prt_usage(argv[0]);
551                         return -1;
552                 }
553                 argc = 1; // remove appsvc bundle
554         } else {        /* ug-client */
555                 char *name = NULL;
556                 name = strrchr(argv[0], '/');
557                 if (name == NULL)
558                         return -1;
559                 /* .../bin/{name} */
560                 ad.name = strdup(&name[1]);
561         }
562         return appcore_efl_main(PACKAGE, &argc, &argv, &ops);
563 }