The problem that e17 couldn't move/resize window when the window fetch the rotation...
[platform/core/uifw/e17.git] / src / bin / e_popup.c
1 #include "e.h"
2
3 /* local subsystem functions */
4 static void      _e_popup_free(E_Popup *pop);
5 static Eina_Bool _e_popup_idle_enterer(void *data);
6 static Eina_Bool _e_popup_cb_window_shape(void *data, int ev_type, void *ev);
7
8 /* local subsystem globals */
9 static Ecore_Event_Handler *_e_popup_window_shape_handler = NULL;
10 static Eina_List *_e_popup_list = NULL;
11 static Eina_Hash *_e_popup_hash = NULL;
12
13 /* externally accessible functions */
14
15 EINTERN int
16 e_popup_init(void)
17 {
18    _e_popup_window_shape_handler =
19      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHAPE,
20                              _e_popup_cb_window_shape, NULL);
21    if (!_e_popup_hash) _e_popup_hash = eina_hash_string_superfast_new(NULL);
22    return 1;
23 }
24
25 EINTERN int
26 e_popup_shutdown(void)
27 {
28    if (_e_popup_hash)
29      {
30         eina_hash_free(_e_popup_hash);
31         _e_popup_hash = NULL;
32      }
33    E_FN_DEL(ecore_event_handler_del, _e_popup_window_shape_handler);
34    return 1;
35 }
36
37 EAPI E_Popup *
38 e_popup_new(E_Zone *zone, int x, int y, int w, int h)
39 {
40    E_Popup *pop;
41
42    pop = E_OBJECT_ALLOC(E_Popup, E_POPUP_TYPE, _e_popup_free);
43    if (!pop) return NULL;
44    pop->zone = zone;
45    pop->zx = pop->zone->x;
46    pop->zy = pop->zone->y;
47    pop->x = x;
48    pop->y = y;
49    pop->w = w;
50    pop->h = h;
51    pop->layer = e_desklock_state_get() ? 200 : 250;
52    pop->ecore_evas = e_canvas_new(pop->zone->container->win,
53                                   pop->zone->x + pop->x, pop->zone->y + pop->y, pop->w, pop->h, 1, 1,
54                                   &(pop->evas_win));
55    if (!pop->ecore_evas)
56      {
57         free(pop);
58         return NULL;
59      }
60    /* avoid excess exposes when shaped - set damage avoid to 1 */
61 //   ecore_evas_avoid_damage_set(pop->ecore_evas, 1);
62
63    e_canvas_add(pop->ecore_evas);
64    pop->shape = e_container_shape_add(pop->zone->container);
65    e_container_shape_move(pop->shape, pop->zone->x + pop->x, pop->zone->y + pop->y);
66    e_container_shape_resize(pop->shape, pop->w, pop->h);
67    pop->evas = ecore_evas_get(pop->ecore_evas);
68    e_container_window_raise(pop->zone->container, pop->evas_win, pop->layer);
69    ecore_x_window_shape_events_select(pop->evas_win, 1);
70    ecore_evas_name_class_set(pop->ecore_evas, "E", "_e_popup_window");
71    ecore_evas_title_set(pop->ecore_evas, "E Popup");
72    e_object_ref(E_OBJECT(pop->zone));
73    pop->zone->popups = eina_list_append(pop->zone->popups, pop);
74    _e_popup_list = eina_list_append(_e_popup_list, pop);
75    eina_hash_add(_e_popup_hash, e_util_winid_str_get(pop->evas_win), pop);
76    return pop;
77 }
78
79 EAPI void
80 e_popup_name_set(E_Popup *pop, const char *name)
81 {
82    if (eina_stringshare_replace(&pop->name, name))
83      ecore_evas_name_class_set(pop->ecore_evas, "E", pop->name);
84 }
85
86 EAPI void
87 e_popup_show(E_Popup *pop)
88 {
89    E_OBJECT_CHECK(pop);
90    E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE);
91    if (pop->visible) return;
92    pop->visible = 1;
93    if ((pop->shaped) && (!e_config->use_composite))
94      {
95         ecore_evas_move(pop->ecore_evas,
96                         pop->zone->container->manager->w,
97                         pop->zone->container->manager->h);
98         ecore_evas_show(pop->ecore_evas);
99         if (pop->idle_enterer) ecore_idle_enterer_del(pop->idle_enterer);
100         pop->idle_enterer = ecore_idle_enterer_add(_e_popup_idle_enterer, pop);
101      }
102    else
103      {
104         ecore_evas_show(pop->ecore_evas);
105         if (!(pop->shaped && e_config->use_composite))
106           e_container_shape_show(pop->shape);
107      }
108 }
109
110 EAPI void
111 e_popup_hide(E_Popup *pop)
112 {
113    E_OBJECT_CHECK(pop);
114    E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE);
115    if (!pop->visible) return;
116    if (pop->idle_enterer) ecore_idle_enterer_del(pop->idle_enterer);
117    pop->idle_enterer = NULL;
118    pop->visible = 0;
119    ecore_evas_hide(pop->ecore_evas);
120    e_container_shape_hide(pop->shape);
121 }
122
123 EAPI void
124 e_popup_move(E_Popup *pop, int x, int y)
125 {
126    E_OBJECT_CHECK(pop);
127    E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE);
128    if ((pop->x == x) && (pop->y == y) &&
129        (pop->zone->x == pop->zx) && (pop->zone->y == pop->zy)) return;
130    pop->zx = pop->zone->x;
131    pop->zy = pop->zone->y;
132    pop->x = x;
133    pop->y = y;
134    ecore_evas_move(pop->ecore_evas,
135                    pop->zone->x + pop->x,
136                    pop->zone->y + pop->y);
137    e_container_shape_move(pop->shape,
138                           pop->zone->x + pop->x,
139                           pop->zone->y + pop->y);
140 }
141
142 EAPI void
143 e_popup_resize(E_Popup *pop, int w, int h)
144 {
145    E_OBJECT_CHECK(pop);
146    E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE);
147    if ((pop->w == w) && (pop->h == h)) return;
148    pop->w = w;
149    pop->h = h;
150    ecore_evas_resize(pop->ecore_evas, pop->w, pop->h);
151    e_container_shape_resize(pop->shape, pop->w, pop->h);
152 }
153
154 EAPI void
155 e_popup_move_resize(E_Popup *pop, int x, int y, int w, int h)
156 {
157    E_OBJECT_CHECK(pop);
158    E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE);
159    if ((pop->x == x) && (pop->y == y) &&
160        (pop->w == w) && (pop->h == h) &&
161        (pop->zone->x == pop->zx) && (pop->zone->y == pop->zy)) return;
162    pop->zx = pop->zone->x;
163    pop->zy = pop->zone->y;
164    pop->x = x;
165    pop->y = y;
166    pop->w = w;
167    pop->h = h;
168    ecore_evas_move_resize(pop->ecore_evas,
169                           pop->zone->x + pop->x,
170                           pop->zone->y + pop->y,
171                           pop->w, pop->h);
172    e_container_shape_move(pop->shape,
173                           pop->zone->x + pop->x,
174                           pop->zone->y + pop->y);
175    e_container_shape_resize(pop->shape, pop->w, pop->h);
176 }
177
178 EAPI void
179 e_popup_ignore_events_set(E_Popup *pop, int ignore)
180 {
181    ecore_evas_ignore_events_set(pop->ecore_evas, ignore);
182 }
183
184 EAPI void
185 e_popup_edje_bg_object_set(E_Popup *pop, Evas_Object *o)
186 {
187    const char *shape_option;
188
189    E_OBJECT_CHECK(pop);
190    E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE);
191    shape_option = edje_object_data_get(o, "shaped");
192    if (shape_option)
193      {
194         if (!strcmp(shape_option, "1"))
195           pop->shaped = 1;
196         else
197           pop->shaped = 0;
198         if (e_config->use_composite)
199           {
200              ecore_evas_alpha_set(pop->ecore_evas, pop->shaped);
201              eina_hash_del(_e_popup_hash, e_util_winid_str_get(pop->evas_win), pop);
202              pop->evas_win = ecore_evas_software_x11_window_get(pop->ecore_evas);
203              eina_hash_add(_e_popup_hash, e_util_winid_str_get(pop->evas_win), pop);
204              e_container_window_raise(pop->zone->container, pop->evas_win, pop->layer);
205           }
206         else
207           ecore_evas_shaped_set(pop->ecore_evas, pop->shaped);
208      }
209    else
210      {
211         pop->shaped = 0;
212         ecore_evas_alpha_set(pop->ecore_evas, pop->shaped);
213         eina_hash_del(_e_popup_hash, e_util_winid_str_get(pop->evas_win), pop);
214         pop->evas_win = ecore_evas_software_x11_window_get(pop->ecore_evas);
215         eina_hash_add(_e_popup_hash, e_util_winid_str_get(pop->evas_win), pop);
216         e_container_window_raise(pop->zone->container, pop->evas_win, pop->layer);
217         ecore_evas_shaped_set(pop->ecore_evas, pop->shaped);
218      }
219 }
220
221 EAPI void
222 e_popup_layer_set(E_Popup *pop, int layer)
223 {
224    E_OBJECT_CHECK(pop);
225    E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE);
226    pop->layer = layer;
227    e_container_window_raise(pop->zone->container, pop->evas_win, pop->layer);
228 }
229
230 EAPI void
231 e_popup_idler_before(void)
232 {
233    Eina_List *l;
234    E_Popup *pop;
235
236    EINA_LIST_FOREACH(_e_popup_list, l, pop)
237      {
238         if (pop->need_shape_export)
239           {
240              Ecore_X_Rectangle *rects, *orects;
241              int num;
242
243              rects = ecore_x_window_shape_rectangles_get(pop->evas_win, &num);
244              if (rects)
245                {
246                   int changed;
247
248                   changed = 1;
249                   if ((num == pop->shape_rects_num) && (pop->shape_rects))
250                     {
251                        int i;
252
253                        orects = pop->shape_rects;
254                        changed = 0;
255                        for (i = 0; i < num; i++)
256                          {
257                             if (rects[i].x < 0)
258                               {
259                                  rects[i].width -= rects[i].x;
260                                  rects[i].x = 0;
261                               }
262                             if ((rects[i].x + (int)rects[i].width) > pop->w)
263                               rects[i].width = rects[i].width - rects[i].x;
264                             if (rects[i].y < 0)
265                               {
266                                  rects[i].height -= rects[i].y;
267                                  rects[i].y = 0;
268                               }
269                             if ((rects[i].y + (int)rects[i].height) > pop->h)
270                               rects[i].height = rects[i].height - rects[i].y;
271
272                             if ((orects[i].x != rects[i].x) ||
273                                 (orects[i].y != rects[i].y) ||
274                                 (orects[i].width != rects[i].width) ||
275                                 (orects[i].height != rects[i].height))
276                               {
277                                  changed = 1;
278                                  break;
279                               }
280                          }
281                     }
282                   if (changed)
283                     {
284                        E_FREE(pop->shape_rects);
285                        pop->shape_rects = rects;
286                        pop->shape_rects_num = num;
287                        e_container_shape_rects_set(pop->shape, rects, num);
288                     }
289                   else
290                     free(rects);
291                }
292              else
293                {
294                   E_FREE(pop->shape_rects);
295                   pop->shape_rects = NULL;
296                   pop->shape_rects_num = 0;
297                   e_container_shape_rects_set(pop->shape, NULL, 0);
298                }
299              pop->need_shape_export = 0;
300           }
301         if ((pop->visible) && (!pop->idle_enterer) &&
302             (!pop->shaped && e_config->use_composite))
303           e_container_shape_show(pop->shape);
304      }
305 }
306
307 EAPI E_Popup *
308 e_popup_find_by_window(Ecore_X_Window win)
309 {
310    E_Popup *pop;
311
312    pop = eina_hash_find(_e_popup_hash, e_util_winid_str_get(win));
313    if ((pop) && (pop->evas_win != win))
314      return NULL;
315    return pop;
316 }
317
318 /* local subsystem functions */
319
320 static void
321 _e_popup_free(E_Popup *pop)
322 {
323    if (pop->idle_enterer) ecore_idle_enterer_del(pop->idle_enterer);
324    pop->idle_enterer = NULL;
325    E_FREE(pop->shape_rects);
326    pop->shape_rects_num = 0;
327    e_container_shape_hide(pop->shape);
328    e_object_del(E_OBJECT(pop->shape));
329    e_canvas_del(pop->ecore_evas);
330    ecore_evas_free(pop->ecore_evas);
331    e_object_unref(E_OBJECT(pop->zone));
332    pop->zone->popups = eina_list_remove(pop->zone->popups, pop);
333    _e_popup_list = eina_list_remove(_e_popup_list, pop);
334    eina_hash_del(_e_popup_hash, e_util_winid_str_get(pop->evas_win), pop);
335    if (pop->name) eina_stringshare_del(pop->name);
336    free(pop);
337 }
338
339 static Eina_Bool
340 _e_popup_idle_enterer(void *data)
341 {
342    E_Popup *pop;
343
344    if (!(pop = data)) return ECORE_CALLBACK_CANCEL;
345    ecore_evas_move(pop->ecore_evas,
346                    pop->zone->x + pop->x,
347                    pop->zone->y + pop->y);
348    e_container_shape_show(pop->shape);
349    pop->idle_enterer = NULL;
350    return ECORE_CALLBACK_CANCEL;
351 }
352
353 static Eina_Bool
354 _e_popup_cb_window_shape(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
355 {
356    E_Popup *pop;
357    Ecore_X_Event_Window_Shape *e;
358
359    e = ev;
360    pop = e_popup_find_by_window(e->win);
361    if (pop) pop->need_shape_export = 1;
362    return ECORE_CALLBACK_PASS_ON;
363 }
364