1 #include "e_illume_private.h"
2 #include "e_mod_floating_window.h"
4 /* global event callback function */
5 static Eina_Bool _e_mod_floating_cb_idle_enterer(void *data __UNUSED__);
6 static Eina_Bool _e_mod_floating_cb_border_add(void *data __UNUSED__,
9 static Eina_Bool _e_mod_floating_cb_border_del(void *data __UNUSED__,
13 static Eina_Bool _e_mod_floating_cb_client_message(void *data,
16 static Eina_Bool _e_mod_floating_cb_window_property(void *data,
20 /* general function */
21 static int _e_mod_floating_atom_init(void);
22 static void _e_mod_floating_border_list_add(E_Border *bd);
23 static void _e_mod_floating_border_list_del(E_Border *bd);
24 static void _e_mod_hints_floating_list_set(void);
25 static E_Illume_Floating_Border* _e_mod_floating_get_floating_border(Ecore_X_Window win);
26 static void _e_mod_floating_window_state_change(Ecore_X_Event_Window_Property *ev);
28 /* for close the floating windows */
29 static void _e_mod_floating_close_all(void);
31 /* for iconify the floating windows */
32 static void _e_mod_floating_iconify(E_Illume_Floating_Border *ft_bd,
34 static void _e_mod_floating_iconify_all(Eina_Bool iconify);
36 /* for automatically align the floating windows */
37 static void _e_mod_floating_smart_cleanup(Ecore_X_Event_Client_Message *event);
39 /* for controlling app-in-app window */
40 static Ecore_X_Atom E_ILLUME_ATOM_FLOATING_WINDOW_ALIGN;
41 static Ecore_X_Atom E_ILLUME_ATOM_FLOATING_WINDOW_CHANGE_VISIBLE;
42 static Ecore_X_Atom E_ILLUME_ATOM_FLOATING_WINDOW_CLOSE_ALL;
43 static Ecore_X_Atom E_ILLUME_ATOM_FLOATING_WINDOW_LIST;
45 static Eina_List *_fw_hdls;
46 static Eina_List *_fw_hooks;
47 static Ecore_Idle_Enterer *_idle_enterer;
49 static Eina_Hash *floating_wins_hash;
50 static Eina_List *floating_wins;
53 e_mod_floating_init(void)
55 Eina_Bool ret = EINA_FALSE;
58 eina_list_append(_fw_hdls,
59 ecore_event_handler_add(E_EVENT_BORDER_ADD,
60 _e_mod_floating_cb_border_add,
63 eina_list_append(_fw_hdls,
64 ecore_event_handler_add(E_EVENT_BORDER_REMOVE,
65 _e_mod_floating_cb_border_del,
68 eina_list_append(_fw_hdls,
69 ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
70 _e_mod_floating_cb_client_message,
73 eina_list_append(_fw_hdls,
74 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY,
75 _e_mod_floating_cb_window_property,
78 _idle_enterer = ecore_idle_enterer_add(_e_mod_floating_cb_idle_enterer, NULL);
80 ret = _e_mod_floating_atom_init();
82 L(LT_FLOATING, "%s(%d) Failed initializing atoms\n", __func__, __LINE__);
84 if (!floating_wins_hash)
85 floating_wins_hash = eina_hash_string_superfast_new(NULL);
91 e_mod_floating_shutdown(void)
93 E_FREE_LIST(_fw_hdls, ecore_event_handler_del);
94 E_FREE_LIST(_fw_hooks, e_border_hook_del);
96 if (_idle_enterer) ecore_idle_enterer_del(_idle_enterer);
99 if (floating_wins_hash) eina_hash_free(floating_wins_hash);
100 floating_wins_hash = NULL;
102 if (floating_wins) eina_list_free(floating_wins);
103 floating_wins = NULL;
109 e_mod_floating_border_is_floating(E_Border *bd)
111 unsigned int state = bd->client.illume.win_state.state;
112 Eina_Bool ret = EINA_FALSE;
114 if (state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)
121 e_mod_floating_get_window_list(void)
123 return floating_wins;
127 _e_mod_floating_atom_init(void)
129 E_ILLUME_ATOM_FLOATING_WINDOW_ALIGN =
130 ecore_x_atom_get("_E_ILLUME_ATOM_FLOATING_WINDOW_ALIGN");
131 if (!E_ILLUME_ATOM_FLOATING_WINDOW_ALIGN)
133 fprintf (stderr, "[ILLUME2] Critical Error!!!"
134 "Cannot create _E_ILLUME_ATOM_FLOATING_WINDOW_ALIGN Atom...\n");
138 E_ILLUME_ATOM_FLOATING_WINDOW_CHANGE_VISIBLE =
139 ecore_x_atom_get("_E_ILLUME_ATOM_FLOATING_WINDOW_CHANGE_VISIBLE");
140 if (!E_ILLUME_ATOM_FLOATING_WINDOW_CHANGE_VISIBLE)
142 fprintf (stderr, "[ILLUME2] Critical Error!!!"
143 "Cannot create _E_ILLUME_ATOM_FLOATING_WINDOW_CHANGE_VISIBLE Atom...\n");
147 E_ILLUME_ATOM_FLOATING_WINDOW_CLOSE_ALL =
148 ecore_x_atom_get("_E_ILLUME_ATOM_FLOATING_WINDOW_CLOSE_ALL");
149 if (!E_ILLUME_ATOM_FLOATING_WINDOW_CLOSE_ALL)
151 fprintf (stderr, "[ILLUME2] Critical Error!!!"
152 "Cannot create _E_ILLUME_ATOM_FLOATING_WINDOW_CLOSE_ALL Atom...\n");
156 E_ILLUME_ATOM_FLOATING_WINDOW_LIST =
157 ecore_x_atom_get("_E_ILLUME_ATOM_FLOATING_WINDOW_LIST");
158 if (!E_ILLUME_ATOM_FLOATING_WINDOW_LIST)
160 fprintf (stderr, "[ILLUME2] Critical Error!!!"
161 "Cannot create _E_ILLUME_ATOM_FLOATING_WINDOW_LIST Atom...\n");
169 _e_mod_floating_window_state_change(Ecore_X_Event_Window_Property *ev)
172 unsigned int state = 0;
174 if (!(bd = e_border_find_by_client_window(ev->win))) return;
176 state = ecore_x_e_illume_window_state_get(ev->win);
179 case ECORE_X_ILLUME_WINDOW_STATE_FLOATING:
180 L(LT_FLOATING, "%s(%d) State of window is changed to floating, win: 0x%08x\n",
181 __func__, __LINE__, ev->win);
182 _e_mod_floating_border_list_add(bd);
184 case ECORE_X_ILLUME_WINDOW_STATE_NORMAL:
185 L(LT_FLOATING, "%s(%d) State of window is changed to normal, win: 0x%08x\n",
186 __func__, __LINE__, ev->win);
187 _e_mod_floating_border_list_del(bd);
192 static E_Illume_Floating_Border*
193 _e_mod_floating_get_floating_border(Ecore_X_Window win)
195 return eina_hash_find(floating_wins_hash, e_util_winid_str_get(win));
199 _e_mod_floating_border_list_add(E_Border *bd)
201 E_Illume_Floating_Border *ft_bd = NULL, *tmp_ft_bd = NULL;
203 EINA_SAFETY_ON_NULL_RETURN(bd);
204 if (!e_mod_floating_border_is_floating(bd)) return;
206 L(LT_FLOATING, "%s(%d) Foating window is added in list, win: 0x%08x\n",
207 __func__, __LINE__, bd->client.win);
209 ft_bd = E_NEW(E_Illume_Floating_Border, 1);
210 EINA_SAFETY_ON_NULL_RETURN(ft_bd);
212 memset(ft_bd, 0, sizeof(E_Illume_Floating_Border));
215 floating_wins = eina_list_append(floating_wins, ft_bd);
216 tmp_ft_bd = eina_hash_find(floating_wins_hash, e_util_winid_str_get(bd->client.win));
219 E_Border *bd2 = tmp_ft_bd->bd;
221 L(LT_FLOATING, "%s(%d) Something worng!!\n", __func__, __LINE__);
222 eina_hash_del(floating_wins_hash,
223 e_util_winid_str_get(bd2->client.win), tmp_ft_bd);
224 eina_hash_del(floating_wins_hash,
225 e_util_winid_str_get(bd2->bg_win), tmp_ft_bd);
226 eina_hash_del(floating_wins_hash,
227 e_util_winid_str_get(bd2->win), tmp_ft_bd);
229 eina_hash_add(floating_wins_hash, e_util_winid_str_get(bd->client.win), ft_bd);
230 eina_hash_add(floating_wins_hash, e_util_winid_str_get(bd->bg_win), ft_bd);
231 eina_hash_add(floating_wins_hash, e_util_winid_str_get(bd->win), ft_bd);
233 _e_mod_hints_floating_list_set();
237 _e_mod_floating_border_list_del(E_Border *bd)
239 E_Illume_Floating_Border *ft_bd = NULL;
241 ft_bd = _e_mod_floating_get_floating_border(bd->win);
244 L(LT_FLOATING, "%s(%d) There is no border in list", __func__, __LINE__);
248 L(LT_FLOATING, "%s(%d) Floating window is removed in list, win:0x%08x\n",
249 __func__, __LINE__, bd->win);
251 floating_wins = eina_list_remove(floating_wins, ft_bd);
252 eina_hash_del(floating_wins_hash, e_util_winid_str_get(bd->client.win), ft_bd);
253 eina_hash_del(floating_wins_hash, e_util_winid_str_get(bd->bg_win), ft_bd);
254 eina_hash_del(floating_wins_hash, e_util_winid_str_get(bd->win), ft_bd);
256 memset(ft_bd, 0, sizeof(E_Illume_Floating_Border));
259 _e_mod_hints_floating_list_set();
263 _e_mod_hints_floating_list_set(void)
265 Eina_List *ml = NULL, *cl = NULL;
270 E_Illume_Floating_Border *ft_bd = NULL;
271 Ecore_X_Window *clients = NULL;
274 num = floating_wins ? floating_wins->accounting->count : 0;
276 L(LT_FLOATING, "%s(%d) Floating window list has being updated\n",
281 clients = calloc(num, sizeof(Ecore_X_Window));
282 EINA_SAFETY_ON_NULL_RETURN(clients);
284 EINA_LIST_FOREACH(e_manager_list(), ml, m)
286 EINA_LIST_FOREACH(m->containers, cl, c)
288 bl = e_container_border_list_first(c);
289 while ((b = e_container_border_list_next(bl)))
291 ft_bd = _e_mod_floating_get_floating_border(b->client.win);
292 if (!ft_bd) continue;
294 clients[i++] = b->client.win;
296 e_container_border_list_free(bl);
299 ecore_x_window_prop_window_set(m->root,
300 E_ILLUME_ATOM_FLOATING_WINDOW_LIST,
303 ecore_x_window_prop_window_set(m->root,
304 E_ILLUME_ATOM_FLOATING_WINDOW_LIST,
311 EINA_LIST_FOREACH(e_manager_list(), ml, m)
313 L(LT_FLOATING, "%s(%d) There is no floating window\n",
315 ecore_x_window_prop_window_set(m->root,
316 E_ILLUME_ATOM_FLOATING_WINDOW_LIST,
323 _e_mod_floating_cb_border_add(void *data __UNUSED__,
327 E_Event_Border_Add *ev = event;
331 EINA_SAFETY_ON_NULL_GOTO(bd, end);
332 if (!e_mod_floating_border_is_floating(bd)) goto end;
334 _e_mod_floating_border_list_add(bd);
337 return ECORE_CALLBACK_PASS_ON;
341 _e_mod_floating_cb_border_del(void *data __UNUSED__,
345 E_Event_Border_Remove *ev = event;
349 EINA_SAFETY_ON_NULL_GOTO(bd, end);
351 _e_mod_floating_border_list_del(bd);
354 return ECORE_CALLBACK_PASS_ON;
358 _e_mod_floating_cb_client_message(void *data __UNUSED__,
362 Ecore_X_Event_Client_Message *ev = event;
363 Eina_Bool iconify = EINA_FALSE;
365 if (ev->message_type == E_ILLUME_ATOM_FLOATING_WINDOW_CLOSE_ALL)
368 "%s(%d) Received message, E_ILLUME_ATOM_FLOATING_WINDOW_CLOSE_ALL\n",
371 _e_mod_floating_close_all();
373 else if (ev->message_type == E_ILLUME_ATOM_FLOATING_WINDOW_CHANGE_VISIBLE)
376 "%s(%d) Received message, E_ILLUME_ATOM_FLOATING_WINDOW_CHANGE_VISIBLE\n",
379 iconify = ev->data.b[0];
380 _e_mod_floating_iconify_all(iconify);
382 else if (ev->message_type == E_ILLUME_ATOM_FLOATING_WINDOW_ALIGN)
385 "%s(%d) Received message, E_ILLUME_ATOM_FLOATING_WINDOW_ALIGN\n",
388 _e_mod_floating_smart_cleanup(ev);
391 return ECORE_CALLBACK_PASS_ON;
395 _e_mod_floating_cb_window_property(void *data __UNUSED__,
399 Ecore_X_Event_Window_Property *ev = event;
401 if (ev->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
403 _e_mod_floating_window_state_change(ev);
406 return ECORE_CALLBACK_PASS_ON;
410 _e_mod_floating_cb_idle_enterer(void *data __UNUSED__)
412 E_Illume_Floating_Border *ft_bd = NULL;
416 if (!floating_wins) return ECORE_CALLBACK_RENEW;
418 EINA_LIST_FOREACH(floating_wins, l, ft_bd)
420 if (!ft_bd) continue;
421 if (!ft_bd->changed) continue;
427 L(LT_FLOATING, "%s(%d) idle state, win: 0x%08x\n",
428 __func__, __LINE__, bd->client.win);
430 if (ft_bd->defer.close)
432 e_border_act_close_begin(ft_bd->bd);
433 ft_bd->defer.close = 0;
437 return ECORE_CALLBACK_RENEW;
441 _e_mod_floating_close_all(void)
443 E_Illume_Floating_Border *ft_bd = NULL;
446 EINA_LIST_FOREACH(floating_wins, l, ft_bd)
448 _e_mod_floating_iconify(ft_bd, 1);
450 ft_bd->defer.close = 1;
456 _e_mod_floating_iconify(E_Illume_Floating_Border *ft_bd,
461 EINA_SAFETY_ON_NULL_RETURN(ft_bd);
463 EINA_SAFETY_ON_NULL_RETURN(bd);
468 e_border_iconify(bd);
473 e_border_uniconify(bd);
478 _e_mod_floating_iconify_all(Eina_Bool iconify)
481 E_Illume_Floating_Border *ft_bd = NULL;
483 EINA_LIST_FOREACH(floating_wins, l, ft_bd)
485 _e_mod_floating_iconify(ft_bd, iconify);
490 _e_mod_floating_smart_cleanup(Ecore_X_Event_Client_Message *event __UNUSED__)
492 Eina_List *borders = NULL, *l;
493 E_Illume_Floating_Border *ft_bd = NULL;
494 E_Border *border = NULL;
496 EINA_LIST_FOREACH(floating_wins, l, ft_bd)
499 if (!border) continue;
500 /* Build a list of windows not iconified. */
501 if ((!border->iconic) && (!border->lock_user_location))
507 /* Ordering windows largest to smallest gives better results */
508 area = border->w * border->h;
509 EINA_LIST_FOREACH(borders, ll, bd)
513 testarea = bd->w * bd->h;
514 /* Insert the border if larger than the current border */
515 if (area >= testarea)
517 borders = eina_list_prepend_relative(borders, border, bd);
521 /* Looped over all borders without placing, so place at end */
522 if (!ll) borders = eina_list_append(borders, border);
526 /* Loop over the borders moving each one using the smart placement */
527 EINA_LIST_FREE(borders, border)
531 e_place_zone_region_smart(border->zone, borders, border->x, border->y,
532 border->w, border->h, &new_x, &new_y);
533 e_border_move(border, new_x, new_y);