sync with private git. updated the license and the boilerplates
[apps/home/quickpanel.git] / daemon / notifications / noti_win.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
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
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
17 #include <Elementary.h>
18 #include <utilX.h>
19
20 #define NOTI_HEIGHT 50
21 #ifndef __UNUSED__
22 #define __UNUSED__ __attribute__((unused))
23 #endif
24 /* Using this macro to emphasize that some portion like stacking and
25 rotation handling are implemented for X based platform
26 */
27
28 #ifdef HAVE_X
29 #include <Ecore_X.h>
30 #endif
31 #include "common.h"
32 #include "noti_win.h"
33
34 struct Internal_Data {
35         Evas_Object *content;
36         Ecore_Event_Handler *rotation_event_handler;
37         Evas_Coord w;
38         Evas_Coord h;
39         int angle;
40         enum Noti_Orient orient;
41 };
42
43 static const char *data_key = "_data";
44
45 static void _set_win_type_notification_level(Evas_Object *win)
46 {
47         retif(win == NULL, , "invalid parameter");
48
49         Ecore_X_Window w = elm_win_xwindow_get(win);
50
51         if (w > 0) {
52                 ecore_x_icccm_hints_set(w, 0, ECORE_X_WINDOW_STATE_HINT_NONE, 0, 0,
53                         0, 0, 0);
54                 ecore_x_netwm_opacity_set(w, 0);
55
56                 ecore_x_netwm_window_type_set(w,
57                                 ECORE_X_WINDOW_TYPE_NOTIFICATION);
58                 utilx_set_system_notification_level(ecore_x_display_get(), w,
59                                 UTILX_NOTIFICATION_LEVEL_HIGH);
60         }
61 }
62
63 static void _show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
64         void *event_info __UNUSED__)
65 {
66         struct Internal_Data *wd = evas_object_data_get(obj, data_key);
67
68         if (!wd)
69                 return;
70         if (wd->content)
71                 evas_object_show(wd->content);
72 }
73
74 static void _content_hide(void *data, Evas *e __UNUSED__,
75         Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
76 {
77         evas_object_hide(data);
78 }
79
80 static void _content_changed_size_hints(void *data, Evas *e __UNUSED__,
81         Evas_Object *obj, void *event_info __UNUSED__)
82 {
83         Evas_Coord h;
84         struct Internal_Data *wd = evas_object_data_get(data, data_key);
85
86         if (!wd)
87                 return;
88
89         evas_object_size_hint_min_get(obj, NULL, &h);
90         if ((h > 0)) {
91                 wd->h = h;
92                 evas_object_size_hint_min_set(obj, wd->w, wd->h);
93                 evas_object_size_hint_min_set(data, wd->w, wd->h);
94                 evas_object_resize(data, wd->w, wd->h);
95         }
96 }
97
98 static void _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
99 {
100         struct Internal_Data *wd = evas_object_data_get(obj, data_key);
101         Evas_Object *sub = event_info;
102
103         if (!wd)
104                 return;
105         if (sub == wd->content) {
106                 evas_object_event_callback_del(wd->content, EVAS_CALLBACK_HIDE,
107                         _content_hide);
108                 evas_object_event_callback_del(wd->content,
109                         EVAS_CALLBACK_CHANGED_SIZE_HINTS,
110                         _content_changed_size_hints);
111                 wd->content = NULL;
112         }
113 }
114
115 static void _del(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
116         void *event_info __UNUSED__)
117 {
118         struct Internal_Data *wd = evas_object_data_get(obj, data_key);
119
120         if (!wd)
121                 return;
122         if (wd->rotation_event_handler)
123                 ecore_event_handler_del(wd->rotation_event_handler);
124         evas_object_data_set(data, data_key, NULL);
125         free(wd);
126 }
127
128 #ifdef HAVE_X
129 static void _update_geometry_on_rotation(Evas_Object *obj, int angle,
130                 int *x, int *y, int *w)
131 {
132         Evas_Coord root_w, root_h;
133         struct Internal_Data *wd = evas_object_data_get(obj, data_key);
134
135         if (!wd)
136                 return;
137
138         ecore_x_window_size_get(ecore_x_window_root_first_get(), &root_w,
139                 &root_h);
140
141         /* rotate window */
142         switch (angle) {
143         case 90:
144                 *w = root_h;
145                 if (wd->orient == NOTI_ORIENT_BOTTOM)
146                         *x = root_w - wd->h;
147                 break;
148         case 270:
149                 *w = root_h;
150                 if (!(wd->orient == NOTI_ORIENT_BOTTOM))
151                         *x = root_w - wd->h;
152                 break;
153         case 180:
154                 *w = root_w;
155                 if (!wd->orient == NOTI_ORIENT_BOTTOM)
156                         *y = root_h - wd->h;
157                 break;
158         case 0:
159         default:
160                 *w = root_w;
161                 if (wd->orient == NOTI_ORIENT_BOTTOM)
162                         *y = root_h - wd->h;
163                 break;
164         }
165 }
166
167 static void _win_rotated(Evas_Object *obj)
168 {
169         int x = 0;
170         int y = 0;
171         int w = 0;
172         int angle = 0;
173         struct Internal_Data *wd =  evas_object_data_get(obj, data_key);
174
175         if (!wd)
176                 return;
177         angle = elm_win_rotation_get(obj);
178         if (angle % 90)
179                 return;
180         angle %= 360;
181         if (angle < 0)
182                 angle += 360;
183         wd->angle = angle;
184
185         _update_geometry_on_rotation(obj, wd->angle, &x, &y, &w);
186
187         evas_object_move(obj, x, y);
188         wd->w = w;
189         evas_object_resize(obj, wd->w, wd->h);
190 }
191
192 static Eina_Bool _prop_change(void *data, int type __UNUSED__, void *event)
193 {
194         Ecore_X_Event_Window_Property *ev;
195         struct Internal_Data *wd = evas_object_data_get(data, data_key);
196
197         if (!wd)
198                 return ECORE_CALLBACK_PASS_ON;
199         ev = event;
200         if (ev->atom == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE)
201                 if (ev->win == elm_win_xwindow_get(data))
202                         _win_rotated(data);
203         return ECORE_CALLBACK_PASS_ON;
204 }
205 #endif
206
207 HAPI Evas_Object *noti_win_add(Evas_Object *parent)
208 {
209         Evas_Object *win;
210         Evas_Object *bg;
211         struct Internal_Data *wd;
212         Evas_Coord w = 0;
213
214         win = elm_win_add(parent, "noti_win", ELM_WIN_NOTIFICATION);
215         elm_win_alpha_set(win, EINA_TRUE);
216
217         if (!win)
218                 return NULL;
219         elm_win_title_set(win, "noti_win");
220         elm_win_borderless_set(win, EINA_TRUE);
221         elm_win_autodel_set(win, EINA_TRUE);
222         evas_object_size_hint_weight_set(win, EVAS_HINT_EXPAND,
223                 EVAS_HINT_EXPAND);
224         evas_object_size_hint_align_set(win, EVAS_HINT_FILL, EVAS_HINT_FILL);
225         bg = elm_bg_add(win);
226         evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND,
227                 EVAS_HINT_EXPAND);
228         elm_win_resize_object_add(win, bg);
229
230         _set_win_type_notification_level(win);
231
232         wd = (struct Internal_Data *) calloc(1, sizeof(struct Internal_Data));
233         if (!wd)
234                 return NULL;
235         evas_object_data_set(win, data_key, wd);
236         wd->angle = 0;
237         wd->orient = NOTI_ORIENT_TOP;
238         evas_object_move(win, 0, 0);
239 #ifdef HAVE_X
240         ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, NULL);
241         evas_object_resize(win, w, NOTI_HEIGHT);
242         wd->rotation_event_handler = ecore_event_handler_add(
243                 ECORE_X_EVENT_WINDOW_PROPERTY, _prop_change, win);
244 #endif
245         wd->w = w;
246         wd->h = NOTI_HEIGHT;
247         evas_object_smart_callback_add(win, "sub-object-del", _sub_del, NULL);
248         evas_object_event_callback_add(win, EVAS_CALLBACK_SHOW, _show, NULL);
249         evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _del, NULL);
250         return win;
251 }
252
253 HAPI void noti_win_content_set(Evas_Object *obj, Evas_Object *content)
254 {
255         Evas_Coord h;
256         struct Internal_Data *wd;
257
258         if (!obj)
259                 return;
260         wd = evas_object_data_get(obj, data_key);
261         if (!wd)
262                 return;
263         if (wd->content)
264                 evas_object_del(content);
265         wd->content = content;
266         if (content) {
267                 evas_object_size_hint_weight_set(wd->content, EVAS_HINT_EXPAND,
268                         EVAS_HINT_EXPAND);
269                 elm_win_resize_object_add(obj, wd->content);
270                 evas_object_size_hint_min_get(wd->content, NULL, &h);
271                 if (h)
272                         wd->h = h;
273                 evas_object_size_hint_min_set(wd->content, wd->w, wd->h);
274                 evas_object_resize(obj, wd->w, wd->h);
275                 evas_object_event_callback_add(wd->content, EVAS_CALLBACK_HIDE,
276                                 _content_hide, obj);
277                 evas_object_event_callback_add(wd->content,
278                                 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
279                                 _content_changed_size_hints, obj);
280         }
281 }
282
283 HAPI void noti_win_orient_set(Evas_Object *obj, enum Noti_Orient orient)
284 {
285 #ifdef HAVE_X
286         Evas_Coord root_w, root_h;
287 #endif
288         struct Internal_Data *wd = evas_object_data_get(obj, data_key);
289
290         if (!wd)
291                 return;
292         if (orient >= NOTI_ORIENT_LAST)
293                 return;
294 #ifdef HAVE_X
295         ecore_x_window_size_get(ecore_x_window_root_first_get(), &root_w,
296                 &root_h);
297 #endif
298         switch (orient) {
299         case NOTI_ORIENT_BOTTOM:
300 #ifdef HAVE_X
301                 evas_object_move(obj, 0, root_h - wd->h);
302 #endif
303                 wd->orient = NOTI_ORIENT_BOTTOM;
304                 break;
305         case NOTI_ORIENT_TOP:
306         default:
307 #ifdef HAVE_X
308                 evas_object_move(obj, 0, 0);
309 #endif
310                 wd->orient = NOTI_ORIENT_TOP;
311                 break;
312         }
313 }