898d7e4b9e8040ae0c30eee1f76aca8dc5d6cb80
[apps/core/preloaded/quickpanel.git] / daemon / notifications / status_msg.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 #include <Elementary.h>
17 #include <Ecore_X.h>
18 #include <vconf.h>
19 #include <notification.h>
20
21 #include "quickpanel-ui.h"
22 #include "common.h"
23 #include "noti_win.h"
24
25 #define QP_STATUS_DURATION      3
26 #define QP_STATUS_DETAIL_DURATION 6
27
28 #define STATUS_MSG_LEN                          1024
29 #define DEFAULT_ICON ICONDIR            "/quickpanel_icon_default.png"
30
31 #define E_DATA_STATUS_DETAIL "detail"
32
33 static Evas_Object *g_status_win;
34 static Ecore_Timer *g_status_timer;
35 static int g_noti_height;
36
37 static int quickpanel_status_init(void *data);
38 static int quickpanel_status_fini(void *data);
39 static void quickpanel_status_reflesh(void *data);
40
41 QP_Module ticker_status = {
42         .name = "ticker_status",
43         .init = quickpanel_status_init,
44         .fini = quickpanel_status_fini,
45         .hib_enter = NULL,
46         .hib_leave = NULL,
47         .lang_changed = NULL,
48         .refresh = quickpanel_status_reflesh
49 };
50
51 /*****************************************************************************
52  *
53  * (Static) Util functions
54  *
55  *****************************************************************************/
56 static void _quickpanel_status_hide(void *data)
57 {
58         if (g_status_win) {
59                 evas_object_hide(g_status_win);
60                 evas_object_del(g_status_win);
61                 g_status_win = NULL;
62         }
63 }
64
65 static void _quickpanel_status_set_text(Evas_Object *detail, const char *message) {
66         retif(detail == NULL, , "Invalid parameter!");
67         retif(message == NULL, , "Invalid parameter!");
68
69         elm_object_part_text_set(detail, "elm.text", message);
70 }
71
72 static Eina_Bool _quickpanel_status_timeout_cb(void *data)
73 {
74         DBG("");
75
76         g_status_timer = NULL;
77
78         _quickpanel_status_hide(data);
79
80         return ECORE_CALLBACK_CANCEL;
81 }
82
83 static void _quickpanel_status_detail_hide_cb(void *data, Evas *e,
84                                         Evas_Object *obj,
85                                         void *event_info)
86 {
87         if (g_status_timer) {
88                 ecore_timer_del(g_status_timer);
89                 g_status_timer = NULL;
90         }
91 }
92
93 static void _quickpanel_status_detail_show_cb(void *data, Evas *e,
94                                         Evas_Object *obj,
95                                         void *event_info)
96 {
97         DBG("");
98 }
99
100 static void _quickpanel_status_clicked_cb(void *data, Evas_Object *obj,
101                                         void *event_info)
102 {
103         _quickpanel_status_hide(data);
104 }
105
106 static void _noti_hide_cb(void *data, Evas_Object *obj,
107                         const char *emission, const char *source)
108 {
109         DBG("");
110
111         if (g_status_timer) {
112                 ecore_timer_del(g_status_timer);
113                 g_status_timer = NULL;
114         }
115 }
116
117 static Evas_Object *_quickpanel_status_create_status_noti(const char *message, void *data)
118 {
119         Evas_Object *status_noti = NULL;
120         Evas_Object *detail = NULL;
121         const char *data_win_height = NULL;
122         int noti_height = 0;
123
124         retif(message == NULL, NULL, "Invalid parameter!");
125
126         status_noti = noti_win_add(NULL);
127         retif(status_noti == NULL, NULL, "Failed to add elm status_noti.");
128
129         detail = elm_layout_add(status_noti);
130         if (!detail) {
131                 ERR("Failed to get detailview.");
132                 evas_object_del(status_noti);
133                 return NULL;
134         }
135         elm_layout_theme_set(detail, "tickernoti", "base", "textonly");
136         elm_object_signal_callback_add(detail, "request,hide", "",
137                                 _noti_hide_cb, NULL);
138
139         data_win_height = (char *)elm_layout_data_get(detail, "height");
140         if (data_win_height != NULL && elm_config_scale_get() > 0.0)
141                 noti_height = (int)(elm_config_scale_get()
142                                         * atoi(data_win_height));
143         evas_object_size_hint_min_set(detail, 1, noti_height);
144         g_noti_height = noti_height;
145         DBG("height:%d", g_noti_height);
146
147         noti_win_content_set(status_noti, detail);
148
149         _quickpanel_status_set_text(detail, message);
150         /* Use style "default" for detailview mode and
151          * "info" for text only mode
152          */
153         elm_object_style_set(status_noti, "textonly");
154         evas_object_data_set(status_noti, E_DATA_STATUS_DETAIL, detail);
155
156         return status_noti;
157 }
158
159 static int _quickpanel_status_get_angle(void *data)
160 {
161         struct appdata *ad = (struct appdata *)data;
162         Ecore_X_Window xwin, root;
163         int ret = 0, angle = 0, count = 0;
164         unsigned char *prop_data = NULL;
165
166         xwin = elm_win_xwindow_get(ad->win);
167         root = ecore_x_window_root_get(xwin);
168
169         ret = ecore_x_window_prop_property_get(root,
170                                 ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE,
171                                 ECORE_X_ATOM_CARDINAL, 32,
172                                 &prop_data, &count);
173
174         if (ret && prop_data) {
175                 memcpy(&angle, prop_data, sizeof(int));
176
177                 if (prop_data)
178                         free(prop_data);
179
180                 return angle;
181         } else {
182                 ERR("Fail to get angle");
183                 if (prop_data)
184                         free(prop_data);
185
186                 return -1;
187         }
188 }
189
190 static void _quickpanel_status_update_geometry_on_rotation(void *data, int *x, int *y, int *w, int *h) {
191         int angle = 0;
192
193         if (!data)
194                 return;
195
196         angle = _quickpanel_status_get_angle(data);
197         Evas_Coord root_w, root_h;
198
199         /*
200          * manually calculate win_status_noti_indi window position & size
201          *  - win_indi is not full size window
202          */
203         ecore_x_window_size_get(ecore_x_window_root_first_get(), &root_w, &root_h);
204
205         // rotate win
206         switch(angle)
207         {
208                 case 90:
209                         *w = g_noti_height;
210                         *h = root_h;
211                         break;
212                 case 270:
213                         *w = g_noti_height;
214                         *h = root_h;
215                         *x = root_w - g_noti_height;
216                         break;
217                 case 180:
218                         *w = root_w;
219                         *h = g_noti_height;
220                         *y = root_h - g_noti_height;
221                         break;
222                 case 0:
223                 default:
224                         *w = root_w;
225                         *h = g_noti_height;
226                         break;
227         }
228         elm_win_rotation_set(g_status_win, angle);
229 }
230
231 static void _quickpanel_status_win_rotated(void *data) {
232         retif(data == NULL, ,"data is NULL");
233
234         struct appdata *ad = data;
235         int x = 0, y = 0, w = 0, h = 0;
236
237         _quickpanel_status_update_geometry_on_rotation(ad, &x, &y, &w, &h);
238
239         if (g_status_win != NULL) {
240                 evas_object_move(g_status_win, x, y);
241                 evas_object_resize(g_status_win, w, h);
242         }
243 }
244
245 static void _quickpanel_status_cb(const char *message, void *data)
246 {
247         DBG("");
248         retif(message == NULL, ,"message is NULL");
249         retif(data == NULL, ,"data is NULL");
250
251         if (g_status_timer)
252                 ecore_timer_del(g_status_timer);
253
254         /* Skip if previous status is still shown */
255         if (g_status_win != NULL) {
256                 Evas_Object *detail = evas_object_data_get(g_status_win, E_DATA_STATUS_DETAIL);
257                 _quickpanel_status_set_text(detail, message);
258                 elm_win_activate(g_status_win);
259         } else {
260                 g_status_win = _quickpanel_status_create_status_noti(message, data);
261                 if (g_status_win == NULL) {
262                         ERR("Fail to create status_noti");
263                         return;
264                 }
265
266                 _quickpanel_status_win_rotated(data);
267                 evas_object_show(g_status_win);
268
269                 evas_object_event_callback_add(g_status_win, EVAS_CALLBACK_SHOW,
270                                         _quickpanel_status_detail_show_cb,
271                                         g_status_win);
272                 evas_object_event_callback_add(g_status_win, EVAS_CALLBACK_HIDE,
273                                         _quickpanel_status_detail_hide_cb,
274                                         g_status_win);
275                 evas_object_smart_callback_add(g_status_win, "clicked",
276                                         _quickpanel_status_clicked_cb,
277                                         g_status_win);
278         }
279
280         g_status_timer = ecore_timer_add(QP_STATUS_DURATION,
281                         _quickpanel_status_timeout_cb, NULL);
282 }
283
284 /*****************************************************************************
285  *
286  * Util functions
287  *
288  *****************************************************************************/
289 static int quickpanel_status_init(void *data)
290 {
291         int ret = QP_OK;
292
293         ret = notification_status_monitor_message_cb_set(_quickpanel_status_cb, data);
294
295         return ret;
296 }
297
298 static int quickpanel_status_fini(void *data)
299 {
300         int ret = 0;
301         _quickpanel_status_hide(NULL);
302
303         ret = notification_status_monitor_message_cb_unset();
304
305         return ret;
306 }
307
308 static void quickpanel_status_reflesh(void *data)
309 {
310         retif(data == NULL, , "Invalid parameter!");
311
312         if (g_status_win != NULL) {
313                 _quickpanel_status_win_rotated(data);
314         }
315 }