sync with tizen 2.0
[apps/core/preloaded/tickernoti.git] / src / tickernoti-syspopup.c
1 /*
2  * tickernoti
3  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an AS IS BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18
19
20 #include <stdio.h>
21 #include <appcore-efl.h>
22 #include <Ecore_X.h>
23 #include <syspopup.h>
24
25 #include <time.h>
26 #include "tickernoti-syspopup.h"
27
28 #define HAVE_ELEMENTARY_X 1
29 #define SYSPOPUP_PARAM_LEN 3
30 syspopup_handler handler = {
31         .def_term_fn = NULL,
32         .def_timeout_fn = NULL
33 };
34
35 static void __win_del(void *data, Evas_Object * obj, void *event)
36 {
37         elm_exit();
38 }
39
40 static Evas_Object *__create_win(const char *name)
41 {
42         if(!name) return NULL;
43         Evas_Object *eo;
44         int w;
45         int h;
46
47         eo = elm_win_add(NULL, name, ELM_WIN_DIALOG_BASIC);
48         if (eo) {
49                 elm_win_title_set(eo, name);
50                 elm_win_borderless_set(eo, EINA_TRUE);
51                 elm_win_alpha_set(eo, EINA_TRUE);
52                 elm_win_raise(eo);
53                 evas_object_smart_callback_add(eo, "delete,request",
54                                                    __win_del, NULL);
55                 ecore_x_window_size_get(ecore_x_window_root_first_get(),
56                                         &w, &h);
57                 evas_object_resize(eo, w, h);
58         }
59
60
61         return eo;
62 }
63
64 static int __app_create(void *data)
65 {
66         if(!data) return -1;
67         struct appdata *ad = data;
68
69         int r;
70         int ret = -1;
71
72         /* init internationalization */
73         r = appcore_set_i18n(PACKAGE, LOCALEDIR);
74         if (r != 0)
75         {
76                 return -1;
77         }
78
79         return 0;
80 }
81
82 static void unload_popup(void *data)
83 {
84         if(!data) return ;
85         struct appdata *ad = data;
86
87         if (ad->rotation_event_handler)
88         {
89                 ecore_event_handler_del(ad->rotation_event_handler);
90         }
91
92         if (ad->layout)
93         {
94                 evas_object_del(ad->layout);
95                 ad->layout = NULL;
96         }
97 }
98
99 static int __app_terminate(void *data)
100 {
101
102         if(!data) return -1;
103         struct appdata *ad = data;
104         int ret = -1;
105
106         unload_popup(ad);
107
108         if (ad->win)
109         {
110                 evas_object_del(ad->win);
111                 ad->win = NULL;
112         }
113         if (ad->b)
114         {
115                 ret = bundle_free(ad->b);
116                 if (ret != 0 )
117                 {
118                 }
119                 ad->b = NULL;
120         }
121
122         return 0;
123 }
124
125 static int __app_pause(void *data)
126 {
127         return 0;
128 }
129
130 static int __app_resume(void *data)
131 {
132         return 0;
133 }
134
135 static void __prt_recvd_bundle(const char *key, const char *value, void *d)
136 {
137 }
138
139 static Eina_Bool timeout_cb(void *data)
140 {
141
142         elm_exit();
143
144         return ECORE_CALLBACK_CANCEL;
145 }
146
147 #ifdef HAVE_ELEMENTARY_X
148 static void
149 _update_window_hints(Evas_Object *obj)
150 {
151    Ecore_X_Window xwin;
152    Ecore_X_Atom _notification_level_atom;
153    int level;
154    // elm_win_xwindow_get() must call after elm_win_alpha_set()
155    xwin = elm_win_xwindow_get(obj);
156
157    ecore_x_icccm_hints_set(xwin, 0, ECORE_X_WINDOW_STATE_HINT_NONE, 0, 0, 0, 0, 0);
158    ecore_x_netwm_window_type_set(xwin, ECORE_X_WINDOW_TYPE_NOTIFICATION);
159    ecore_x_netwm_opacity_set(xwin, 0);
160    // Create atom for notification level
161    _notification_level_atom = ecore_x_atom_get("_E_ILLUME_NOTIFICATION_LEVEL");
162
163    // HIGH:150, NORMAL:100, LOW:50
164    level = 100;
165
166    // Set notification level of the window
167    ecore_x_window_prop_property_set(xwin, _notification_level_atom, ECORE_X_ATOM_CARDINAL, 32, &level, 1);
168 }
169
170 #endif
171 static Evas_Object
172 *_create_window(Evas_Object *parent, const char *name)
173 {
174    Evas_Object *win;
175
176    win = elm_win_add(parent, name, ELM_WIN_BASIC);
177    elm_win_title_set(win, name);
178    elm_win_borderless_set(win, EINA_TRUE);
179    elm_win_autodel_set(win, EINA_TRUE);
180    elm_win_alpha_set(win, EINA_TRUE);
181    evas_object_size_hint_weight_set(win, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
182    evas_object_size_hint_align_set(win, EVAS_HINT_FILL, EVAS_HINT_FILL);
183
184 #ifdef HAVE_ELEMENTARY_X
185    // set top window
186    _update_window_hints(win);
187 #endif
188    return win;
189 }
190
191 static void
192 _update_geometry_on_rotation(void *data, int *x, int *y, int *w)
193 {
194    int angle;
195
196    if(!data) return ;
197    struct appdata *ad = data;
198
199    angle = ad->angle;
200 #ifdef HAVE_ELEMENTARY_X
201    Evas_Coord root_w, root_h;
202
203    /*
204    * manually calculate win_tickernoti_indi window position & size
205    *  - win_indi is not full size window
206    */
207    ecore_x_window_size_get(ecore_x_window_root_first_get(), &root_w, &root_h);
208    // rotate win
209    switch(angle)
210      {
211       case 90:
212          *w = root_h;
213          if (ad->orient == _ELM_TICKERNOTI_ORIENT_BOTTOM)
214            *x = root_w - ad->noti_height;
215          break;
216       case 270:
217          *w = root_h;
218          if (!(ad->orient == _ELM_TICKERNOTI_ORIENT_BOTTOM))
219            *x = root_w - ad->noti_height;
220          break;
221       case 180:
222          *w = root_w;
223          if (!ad->orient == _ELM_TICKERNOTI_ORIENT_BOTTOM)
224            *y = root_h - ad->noti_height;
225          break;
226        case 0:
227       default:
228          *w = root_w;
229          if (ad->orient == _ELM_TICKERNOTI_ORIENT_BOTTOM)
230            *y = root_h - ad->noti_height;
231          break;
232      }
233 #endif
234 }
235
236 static void
237 _win_rotated(void *data)
238 {
239    struct appdata *ad = data;
240    int x = 0, y = 0, w = 0, angle = 0;
241
242    if (!ad) return;
243    angle = elm_win_rotation_get(ad->win);
244    if (angle % 90) return;
245    angle %= 360;
246    if (angle < 0) angle += 360;
247    ad->angle = angle;
248    _update_geometry_on_rotation(ad, &x, &y, &w);
249    evas_object_move(ad->win, x, y);
250    evas_object_resize(ad->win, w, ad->noti_height);
251 #ifdef HAVE_ELEMENTARY_X
252    _update_window_hints(ad->win);
253 #endif
254 }
255
256 static Eina_Bool
257 _prop_change(void *data, int type, void *event)
258 {
259 #ifdef HAVE_ELEMENTARY_X
260    Ecore_X_Event_Window_Property *ev;
261    struct appdata *ad = data;
262
263    if (!ad) return ECORE_CALLBACK_PASS_ON;
264    ev = event;
265    if (ev->atom == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE)
266      {
267         if (ev->win == elm_win_xwindow_get(ad->win))
268           {
269              _win_rotated(data);
270           }
271      }
272    return ECORE_CALLBACK_PASS_ON;
273 #endif
274 }
275 static void _hide_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
276 {
277    struct appdata *ad = data;
278
279    if (!ad) return;
280    evas_object_hide(ad->win);
281 }
282
283 static void
284 _create_tickernoti(void *data)
285 {
286    Evas_Coord w;
287    char *data_win_height = NULL;
288
289    if(!data) return ;
290    struct appdata *ad = data;
291
292    evas_object_move(ad->win, 0, 0);
293
294    ad->layout = elm_layout_add(ad->win);
295    elm_layout_file_set(ad->layout, TICKERNOTI_EDJ, ad->style);
296
297    elm_win_resize_object_add(ad->win, ad->layout);
298    evas_object_size_hint_weight_set(ad->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
299
300    // tickernoti height setting
301    if ((ad->style) && (!strcmp(ad->style, "info")))
302       data_win_height = TICKERNOTI_INFO_BG_MIN_HEIGHT;
303    else
304       data_win_height = TICKERNOTI_DEFAULT_BG_MIN_HEIGHT;
305
306    if (data_win_height != NULL && elm_config_scale_get() > 0.0)
307      ad->noti_height = (int)(elm_config_scale_get() * atoi(data_win_height));
308
309    ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, NULL);
310    evas_object_size_hint_min_set(ad->layout, w, ad->noti_height);
311    evas_object_resize(ad->win, w, ad->noti_height);
312
313    ad->rotation_event_handler = ecore_event_handler_add(
314             ECORE_X_EVENT_WINDOW_PROPERTY, _prop_change, ad);
315
316    edje_object_signal_callback_add(elm_layout_edje_get(ad->layout), "request,hide", "", _hide_cb, ad);
317    evas_object_show(ad->layout);
318 }
319
320 static void
321 _show_tickernoti(void *data)
322 {
323    if(!data) return ;
324    struct appdata *ad = data;
325
326    _update_window_hints(ad->win);
327    evas_object_show(ad->win);
328    edje_object_signal_emit(elm_layout_edje_get(ad->layout), "effect,show", "elm");
329    edje_object_message_signal_process(elm_layout_edje_get(ad->layout));
330 }
331
332 static void
333 _hide(void *data, Evas *e, Evas_Object *obj, void *event_info)
334 {
335    if(!data) return ;
336    struct appdata *ad = data;
337    evas_object_hide(ad->win);
338 }
339
340 EAPI Evas_Object *
341 _elm_tickernoti_add(void *data)
342 {
343    Evas_Object *obj;
344
345    if(!data) return NULL;
346    struct appdata *ad = data;
347
348    ad->win = _create_window(NULL, "noti-window");
349
350    _create_tickernoti(ad);
351
352    evas_object_event_callback_add(ad->layout, EVAS_CALLBACK_HIDE, _hide, ad);
353    return ad->layout;
354 }
355
356 static void
357 _sizing_eval(void *data)
358 {
359    if(!data) return ;
360    struct appdata *ad = data;
361    Evas_Coord minw = -1, minh = -1;
362
363    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
364    edje_object_size_min_restricted_calc(elm_layout_edje_get(ad->layout), &minw, &minh, minw, minh);
365 }
366
367 static void
368 _elm_tickernoti_label_set(void *data)
369 {
370    if(!data) return ;
371    struct appdata *ad = data;
372    edje_object_part_text_set(elm_layout_edje_get(ad->layout), "elm.text", ad->text);
373    _sizing_eval(ad);
374 }
375
376 EAPI void
377 _elm_tickernoti_orient_set(void *data, _Elm_Tickernoti_Orient orient)
378 {
379    Evas_Coord root_w, root_h;
380    if(!data) return ;
381    struct appdata *ad = data;
382
383    if (orient >= _ELM_TICKERNOTI_ORIENT_LAST) return;
384
385    ecore_x_window_size_get(ecore_x_window_root_first_get(), &root_w, &root_h);
386
387    switch(orient) {
388       case _ELM_TICKERNOTI_ORIENT_BOTTOM:
389          evas_object_move(ad->win, 0, root_h - ad->noti_height);
390          ad->orient = _ELM_TICKERNOTI_ORIENT_BOTTOM;
391          break;
392       case _ELM_TICKERNOTI_ORIENT_TOP:
393       default:
394          evas_object_move(ad->win, 0, 0);
395          ad->orient = _ELM_TICKERNOTI_ORIENT_TOP;
396          break;
397    }
398    _update_window_hints(ad->win);
399 }
400
401 static void load_small_popup(void *data)
402 {
403         if(!data) return ;
404         struct appdata *ad = data;
405         int ret = -1;
406
407         if (ad->win)
408         {
409                 evas_object_del(ad->win);
410                 ad->win = NULL;
411         }
412
413         _elm_tickernoti_add(ad);
414
415         ret = syspopup_create(ad->b, &handler, ad->win, ad);
416         if(ret != 0) return;
417
418         _elm_tickernoti_label_set(ad);
419         _elm_tickernoti_orient_set(ad, ad->orient);
420         evas_object_show(ad->layout);
421         _show_tickernoti(ad);
422
423         if (ad->timeout <= 0) return;
424         ad->e_timer = ecore_timer_add(ad->timeout, timeout_cb, NULL);
425 }
426
427 static int __app_reset(bundle *b, void *data)
428 {
429
430         if(!data) return -1;
431         struct appdata *ad = data;
432         char key[SYSPOPUP_PARAM_LEN];
433         int ret = 0;
434
435         ad->b = bundle_dup(b);
436
437         /* When syspopup is already loaded, remove the popup and load new popup */
438         if (syspopup_has_popup(b))
439         {
440                 if (ad->e_timer)
441                 {
442                         ecore_timer_del(ad->e_timer);
443                         ad->e_timer = NULL;
444                 }
445                 if (ad->layout)
446                 {
447                         evas_object_del(ad->layout);
448                         ad->layout = NULL;
449                 }
450                 if (ad->win)
451                 {
452                         evas_object_del(ad->win);
453                         ad->win = NULL;
454                 }
455                 /* Resetting all proporties of syspopup */
456                 syspopup_reset(b);
457         }
458
459         /* get text */
460         snprintf(key, SYSPOPUP_PARAM_LEN, "%d", SYSPOPUP_TEXT);
461         ad->text = bundle_get_val(b, (const char *)key);
462         if (!ad->text)
463         {
464                 elm_exit();
465         }
466
467         /* get tickernoti style */
468         snprintf(key, SYSPOPUP_PARAM_LEN, "%d", SYSPOPUP_STYLE);
469         ad->style = bundle_get_val(b, (const char *)key);
470         if (!ad->style) ad->style = "default";
471
472         /* get orient */
473         snprintf(key, SYSPOPUP_PARAM_LEN, "%d", SYSPOPUP_ORIENT);
474         const char *orient = bundle_get_val(b, (const char *)key);
475         if (!orient)
476         {
477                 /* default orient */
478                 ad->orient = _ELM_TICKERNOTI_ORIENT_TOP;
479         }
480         else
481         {
482                 ad->orient = atoi(orient);
483         }
484
485         /* get timeout */
486         snprintf(key, SYSPOPUP_PARAM_LEN, "%d", SYSPOPUP_TIMEOUT);
487         const char *timeout = bundle_get_val(b, (const char *)key);
488         if (!timeout)
489         {
490                 /* default timeout */
491                 ad->timeout = -1;
492         }
493         else
494         {
495                 ad->timeout = atoi(timeout);
496         }
497
498    load_small_popup(ad);
499
500         return 0;
501 }
502
503 int main(int argc, char *argv[])
504 {
505
506         struct appdata ad;
507         struct appcore_ops ops = {
508                 .create = __app_create,
509                 .terminate = __app_terminate,
510                 .pause = __app_pause,
511                 .resume = __app_resume,
512                 .reset = __app_reset,
513         };
514
515         memset(&ad, 0x0, sizeof(struct appdata));
516         ops.data = &ad;
517
518         return appcore_efl_main(PACKAGE, &argc, &argv, &ops);
519 }
520