2 #include "e_mod_main.h"
3 #include "e_mod_config.h"
4 #include "e_busycover.h"
6 #define IL_HOME_WIN_TYPE 0xE0b0102f
9 typedef struct _Il_Home_Win Il_Home_Win;
10 typedef struct _Il_Home_Exec Il_Home_Exec;
14 E_Object e_obj_inherit;
17 Evas_Object *o_bg, *o_sf, *o_fm, *o_cover;
25 Efreet_Desktop *desktop;
35 /* local function prototypes */
36 static void _il_home_apps_populate(void);
37 static void _il_home_apps_unpopulate(void);
38 static void _il_home_desks_populate(void);
39 static void _il_home_desktop_run(Il_Home_Win *hwin, Efreet_Desktop *desktop);
40 static E_Border *_il_home_desktop_find_border(E_Zone *zone, Efreet_Desktop *desktop);
41 static void _il_home_win_new(E_Zone *zone);
42 static void _il_home_win_cb_free(Il_Home_Win *hwin);
43 static void _il_home_win_cb_resize(E_Win *win);
44 static void _il_home_fmc_set(Evas_Object *obj);
45 static Eina_Bool _il_home_update_deferred(void *data __UNUSED__);
46 static void _il_home_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
47 static void _il_home_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
48 static void _il_home_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
49 static void _il_home_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
50 static void _il_home_cb_selected(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__);
51 static Eina_Bool _il_home_desktop_cache_update(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__);
52 static Eina_Bool _il_home_cb_border_add(void *data __UNUSED__, int type __UNUSED__, void *event);
53 static Eina_Bool _il_home_cb_border_del(void *data __UNUSED__, int type __UNUSED__, void *event);
54 static Eina_Bool _il_home_cb_exe_del(void *data __UNUSED__, int type __UNUSED__, void *event);
55 static Eina_Bool _il_home_cb_exe_timeout(void *data);
56 static Eina_Bool _il_home_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event);
57 static Eina_Bool _il_home_cb_prop_change(void *data __UNUSED__, int type __UNUSED__, void *event);
58 static Eina_Bool _il_home_cb_bg_change(void *data __UNUSED__, int type __UNUSED__, void *event);
61 static Eina_List *hwins = NULL;
62 static Eina_List *hdls = NULL;
63 static Eina_List *desks = NULL;
64 static Eina_List *exes = NULL;
65 static Ecore_Timer *defer = NULL;
67 /* public functions */
68 EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Illume Home" };
71 e_modapi_init(E_Module *m)
76 if (!il_home_config_init(m)) return NULL;
78 _il_home_apps_unpopulate();
79 _il_home_apps_populate();
82 eina_list_append(hdls,
83 ecore_event_handler_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE,
84 _il_home_desktop_cache_update,
88 eina_list_append(hdls,
89 ecore_event_handler_add(E_EVENT_BORDER_ADD,
90 _il_home_cb_border_add, NULL));
92 eina_list_append(hdls,
93 ecore_event_handler_add(E_EVENT_BORDER_REMOVE,
94 _il_home_cb_border_del, NULL));
96 eina_list_append(hdls,
97 ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
98 _il_home_cb_exe_del, NULL));
100 eina_list_append(hdls,
101 ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
102 _il_home_cb_client_message,
105 eina_list_append(hdls,
106 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY,
107 _il_home_cb_prop_change,
110 eina_list_append(hdls,
111 ecore_event_handler_add(E_EVENT_BG_UPDATE,
112 _il_home_cb_bg_change, NULL));
114 EINA_LIST_FOREACH(e_manager_list(), ml, man)
119 EINA_LIST_FOREACH(man->containers, cl, con)
124 EINA_LIST_FOREACH(con->zones, zl, zone)
126 Ecore_X_Illume_Mode mode;
128 mode = ecore_x_e_illume_mode_get(zone->black_win);
129 _il_home_win_new(zone);
130 if (mode > ECORE_X_ILLUME_MODE_SINGLE)
131 _il_home_win_new(zone);
140 e_modapi_shutdown(E_Module *m __UNUSED__)
142 Ecore_Event_Handler *hdl;
146 EINA_LIST_FREE(hwins, hwin)
147 e_object_del(E_OBJECT(hwin));
149 EINA_LIST_FREE(exes, exe)
153 ecore_exe_terminate(exe->exec);
154 ecore_exe_free(exe->exec);
156 if (exe->handle) e_busycover_pop(exe->cover, exe->handle);
157 if (exe->timeout) ecore_timer_del(exe->timeout);
158 if (exe->desktop) efreet_desktop_free(exe->desktop);
162 EINA_LIST_FREE(hdls, hdl)
163 ecore_event_handler_del(hdl);
165 _il_home_apps_unpopulate();
167 il_home_config_shutdown();
172 e_modapi_save(E_Module *m __UNUSED__)
174 return il_home_config_save();
178 il_home_win_cfg_update(void)
180 _il_home_apps_unpopulate();
181 _il_home_apps_populate();
184 /* local function prototypes */
186 _il_home_apps_populate(void)
192 e_user_dir_concat_static(buff, "appshadow");
193 ecore_file_mkpath(buff);
195 _il_home_desks_populate();
197 EINA_LIST_FOREACH(hwins, l, hwin)
199 _il_home_fmc_set(hwin->o_fm);
200 e_fm2_path_set(hwin->o_fm, NULL, buff);
205 _il_home_apps_unpopulate(void)
207 Efreet_Desktop *desktop;
209 char buff[PATH_MAX], *file;
212 EINA_LIST_FREE(desks, desktop)
213 efreet_desktop_free(desktop);
215 len = e_user_dir_concat_static(buff, "appshadow");
216 if ((len + 2) >= sizeof(buff)) return;
218 files = ecore_file_ls(buff);
222 EINA_LIST_FREE(files, file)
224 if (eina_strlcpy(buff + len, file, sizeof(buff) - len) >= sizeof(buff) - len)
226 ecore_file_unlink(buff);
232 _il_home_desks_populate(void)
234 Efreet_Menu *menu, *entry;
235 Eina_List *ml, *settings, *sys, *kbd;
236 Efreet_Desktop *desktop;
239 if (!(menu = efreet_menu_get())) return;
241 settings = efreet_util_desktop_category_list("Settings");
242 sys = efreet_util_desktop_category_list("System");
243 kbd = efreet_util_desktop_category_list("Keyboard");
245 EINA_LIST_FOREACH(menu->entries, ml, entry)
250 if (entry->type != EFREET_MENU_ENTRY_MENU) continue;
251 EINA_LIST_FOREACH(entry->entries, sl, sm)
255 if (sm->type != EFREET_MENU_ENTRY_DESKTOP) continue;
256 if (!(desktop = sm->desktop)) continue;
257 if ((settings) && (sys) &&
258 (eina_list_data_find(settings, desktop)) &&
259 (eina_list_data_find(sys, desktop))) continue;
260 if ((kbd) && (eina_list_data_find(kbd, desktop)))
262 efreet_desktop_ref(desktop);
263 desks = eina_list_append(desks, desktop);
264 e_user_dir_snprintf(buff, sizeof(buff),
265 "appshadow/%04x.desktop", num);
266 ecore_file_symlink(desktop->orig_path, buff);
271 efreet_menu_free(menu);
273 EINA_LIST_FREE(settings, desktop)
274 efreet_desktop_free(desktop);
275 EINA_LIST_FREE(sys, desktop)
276 efreet_desktop_free(desktop);
277 EINA_LIST_FREE(kbd, desktop)
278 efreet_desktop_free(desktop);
282 _il_home_desktop_run(Il_Home_Win *hwin, Efreet_Desktop *desktop)
284 E_Exec_Instance *eins;
290 if ((!hwin) || (!desktop) || (!desktop->exec)) return;
291 EINA_LIST_FOREACH(exes, l, exec)
293 if (exec->desktop != desktop) continue;
294 if ((exec->border) && (exec->border->zone == hwin->zone))
296 e_border_uniconify(exec->border);
297 e_border_raise(exec->border);
298 e_border_focus_set(exec->border, 1, 1);
302 if ((bd = _il_home_desktop_find_border(hwin->zone, desktop)))
304 e_border_uniconify(bd);
306 e_border_focus_set(bd, 1, 1);
310 exec = E_NEW(Il_Home_Exec, 1);
312 exec->cover = hwin->cover;
313 eins = e_exec(hwin->zone, desktop, NULL, NULL, "illume-home");
314 exec->desktop = desktop;
315 exec->zone = hwin->zone;
318 exec->exec = eins->exe;
319 exec->startup_id = eins->startup_id;
321 exec->pid = ecore_exe_pid_get(eins->exe);
323 exec->timeout = ecore_timer_add(2.0, _il_home_cb_exe_timeout, exec);
324 snprintf(buff, sizeof(buff), "Starting %s", desktop->name);
325 exec->handle = e_busycover_push(hwin->cover, buff, NULL);
326 exes = eina_list_append(exes, exec);
330 _il_home_desktop_find_border(E_Zone *zone, Efreet_Desktop *desktop)
334 char *exe = NULL, *p;
336 if (!desktop) return NULL;
337 if (!desktop->exec) return NULL;
338 p = strchr(desktop->exec, ' ');
340 exe = strdup(desktop->exec);
343 size_t s = p - desktop->exec + 1;
345 if (exe) eina_strlcpy(exe, desktop->exec, s);
349 p = strrchr(exe, '/');
350 if (p) strcpy(exe, p + 1);
353 EINA_LIST_FOREACH(e_border_client_list(), l, bd)
355 if (bd->zone != zone) continue;
356 if (e_exec_startup_id_pid_find(bd->client.netwm.pid,
357 bd->client.netwm.startup_id) == desktop)
364 if (bd->client.icccm.command.argv)
368 pp = strrchr(bd->client.icccm.command.argv[0], '/');
369 if (!pp) pp = bd->client.icccm.command.argv[0];
370 if (!strcmp(exe, pp))
376 if ((bd->client.icccm.name) &&
377 (!strcasecmp(bd->client.icccm.name, exe)))
389 _il_home_win_new(E_Zone *zone)
397 hwin = E_OBJECT_ALLOC(Il_Home_Win, IL_HOME_WIN_TYPE, _il_home_win_cb_free);
401 hwin->win = e_win_new(zone->container);
404 e_object_del(E_OBJECT(hwin));
407 hwin->win->data = hwin;
408 e_win_title_set(hwin->win, _("Illume Home"));
409 e_win_name_class_set(hwin->win, "Illume-Home", "Illume-Home");
410 e_win_resize_callback_set(hwin->win, _il_home_win_cb_resize);
411 e_win_no_remember_set(hwin->win, EINA_TRUE);
413 snprintf(buff, sizeof(buff), "%s/e-module-illume-home.edj",
414 il_home_cfg->mod_dir);
416 evas = e_win_evas_get(hwin->win);
418 desk = e_desk_current_get(zone);
420 bgfile = e_bg_file_get(zone->container->num, zone->num, desk->x, desk->y);
422 bgfile = e_bg_file_get(zone->container->num, zone->num, -1, -1);
424 hwin->o_bg = edje_object_add(evas);
425 edje_object_file_set(hwin->o_bg, bgfile, "e/desktop/background");
426 evas_object_move(hwin->o_bg, 0, 0);
427 evas_object_show(hwin->o_bg);
429 hwin->o_sf = e_scrollframe_add(evas);
430 e_scrollframe_single_dir_set(hwin->o_sf, EINA_TRUE);
431 e_scrollframe_custom_edje_file_set(hwin->o_sf, buff,
432 "modules/illume-home/launcher/scrollview");
433 evas_object_move(hwin->o_sf, 0, 0);
434 evas_object_show(hwin->o_sf);
436 hwin->o_fm = e_fm2_add(evas);
437 _il_home_fmc_set(hwin->o_fm);
438 evas_object_show(hwin->o_fm);
439 e_user_dir_concat_static(buff, "appshadow");
440 e_fm2_path_set(hwin->o_fm, NULL, buff);
441 e_fm2_window_object_set(hwin->o_fm, E_OBJECT(hwin->win));
442 e_scrollframe_extern_pan_set(hwin->o_sf, hwin->o_fm,
445 _il_home_pan_max_get,
446 _il_home_pan_child_size_get);
447 evas_object_propagate_events_set(hwin->o_fm, 0);
448 evas_object_smart_callback_add(hwin->o_fm, "selected",
449 _il_home_cb_selected, hwin);
451 hwin->cover = e_busycover_new(hwin->win);
453 e_win_move_resize(hwin->win, zone->x, zone->y, zone->w, (zone->h / 2));
454 e_win_show(hwin->win);
455 e_border_zone_set(hwin->win->border, zone);
456 if (hwin->win->evas_win)
457 e_drop_xdnd_register_set(hwin->win->evas_win, EINA_TRUE);
459 hwins = eina_list_append(hwins, hwin);
463 _il_home_win_cb_free(Il_Home_Win *hwin)
465 if (hwin->win->evas_win) e_drop_xdnd_register_set(hwin->win->evas_win, 0);
466 if (hwin->cover) e_object_del(E_OBJECT(hwin->cover));
467 if (hwin->o_bg) evas_object_del(hwin->o_bg);
468 if (hwin->o_sf) evas_object_del(hwin->o_sf);
469 if (hwin->o_fm) evas_object_del(hwin->o_fm);
470 if (hwin->win) e_object_del(E_OBJECT(hwin->win));
475 _il_home_win_cb_resize(E_Win *win)
479 if (!(hwin = win->data)) return;
480 if (hwin->o_bg) evas_object_resize(hwin->o_bg, win->w, win->h);
481 if (hwin->o_sf) evas_object_resize(hwin->o_sf, win->w, win->h);
482 if (hwin->cover) e_busycover_resize(hwin->cover, win->w, win->h);
486 _il_home_fmc_set(Evas_Object *obj)
491 memset(&fmc, 0, sizeof(E_Fm2_Config));
492 fmc.view.mode = E_FM2_VIEW_MODE_GRID_ICONS;
493 fmc.view.open_dirs_in_place = 1;
494 fmc.view.selector = 0;
495 fmc.view.single_click = il_home_cfg->single_click;
496 fmc.view.single_click_delay = il_home_cfg->single_click_delay;
497 fmc.view.no_subdir_jump = 1;
498 fmc.icon.extension.show = 0;
499 fmc.icon.icon.w = il_home_cfg->icon_size * e_scale / 2.0;
500 fmc.icon.icon.h = il_home_cfg->icon_size * e_scale / 2.0;
501 fmc.icon.fixed.w = il_home_cfg->icon_size * e_scale / 2.0;
502 fmc.icon.fixed.h = il_home_cfg->icon_size * e_scale / 2.0;
503 fmc.list.sort.no_case = 0;
504 fmc.list.sort.dirs.first = 1;
505 fmc.list.sort.dirs.last = 0;
506 fmc.selection.single = 1;
507 fmc.selection.windows_modifiers = 0;
508 e_fm2_config_set(obj, &fmc);
512 _il_home_update_deferred(void *data __UNUSED__)
514 _il_home_apps_unpopulate();
515 _il_home_apps_populate();
517 return ECORE_CALLBACK_CANCEL;
521 _il_home_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
523 e_fm2_pan_set(obj, x, y);
527 _il_home_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
529 e_fm2_pan_get(obj, x, y);
533 _il_home_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
535 e_fm2_pan_max_get(obj, x, y);
539 _il_home_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
541 e_fm2_pan_child_size_get(obj, w, h);
545 _il_home_cb_selected(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
549 E_Fm2_Icon_Info *ici;
551 if (!(hwin = data)) return;
552 if (!(selected = e_fm2_selected_list_get(hwin->o_fm))) return;
553 EINA_LIST_FREE(selected, ici)
555 Efreet_Desktop *desktop;
557 if ((!ici) || (!ici->real_link)) continue;
558 if (!(desktop = efreet_desktop_get(ici->real_link))) continue;
559 _il_home_desktop_run(hwin, desktop);
564 _il_home_desktop_cache_update(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
566 if (defer) ecore_timer_del(defer);
567 defer = ecore_timer_add(0.5, _il_home_update_deferred, NULL);
568 return ECORE_CALLBACK_PASS_ON;
572 _il_home_cb_border_add(void *data __UNUSED__, int type __UNUSED__, void *event)
574 E_Event_Border_Add *ev;
579 EINA_LIST_FOREACH(exes, l, exe)
583 if ((exe->startup_id == ev->border->client.netwm.startup_id) ||
584 (exe->pid == ev->border->client.netwm.pid))
586 exe->border = ev->border;
589 if (!exe->border) continue;
590 if (exe->border->zone != exe->zone)
592 exe->border->zone = exe->zone;
593 exe->border->x = exe->zone->x;
594 exe->border->y = exe->zone->y;
595 exe->border->changes.pos = 1;
596 exe->border->changed = 1;
600 e_busycover_pop(exe->cover, exe->handle);
603 if (exe->timeout) ecore_timer_del(exe->timeout);
606 return ECORE_CALLBACK_PASS_ON;
610 _il_home_cb_border_del(void *data __UNUSED__, int type __UNUSED__, void *event)
612 E_Event_Border_Remove *ev;
617 EINA_LIST_FOREACH(exes, l, exe)
619 if (exe->border == ev->border)
621 if (exe->exec) ecore_exe_free(exe->exec);
623 if (exe->handle) e_busycover_pop(exe->cover, exe->handle);
626 exes = eina_list_remove(exes, exe);
631 return ECORE_CALLBACK_PASS_ON;
635 _il_home_cb_exe_del(void *data __UNUSED__, int type __UNUSED__, void *event)
638 Ecore_Exe_Event_Del *ev;
642 EINA_LIST_FOREACH(exes, l, exe)
644 if (exe->pid == ev->pid)
648 e_busycover_pop(exe->cover, exe->handle);
651 exes = eina_list_remove_list(exes, l);
652 if (exe->timeout) ecore_timer_del(exe->timeout);
653 if (exe->desktop) efreet_desktop_free(exe->desktop);
658 return ECORE_CALLBACK_PASS_ON;
662 _il_home_cb_exe_timeout(void *data)
666 if (!(exe = data)) return ECORE_CALLBACK_CANCEL;
667 if (exe->handle) e_busycover_pop(exe->cover, exe->handle);
671 exes = eina_list_remove(exes, exe);
672 if (exe->desktop) efreet_desktop_free(exe->desktop);
674 return ECORE_CALLBACK_CANCEL;
677 return ECORE_CALLBACK_CANCEL;
681 _il_home_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event)
683 Ecore_X_Event_Client_Message *ev;
686 if (ev->message_type == ECORE_X_ATOM_E_ILLUME_HOME_NEW)
690 zone = e_util_zone_window_find(ev->win);
691 if (zone->black_win != ev->win) return ECORE_CALLBACK_PASS_ON;
692 _il_home_win_new(zone);
694 else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_HOME_DEL)
700 if (!(bd = e_border_find_by_client_window(ev->win))) return ECORE_CALLBACK_PASS_ON;
701 EINA_LIST_FOREACH(hwins, l, hwin)
703 if (hwin->win->border == bd)
705 hwins = eina_list_remove_list(hwins, hwins);
706 e_object_del(E_OBJECT(hwin));
711 return ECORE_CALLBACK_PASS_ON;
715 _il_home_cb_prop_change(void *data __UNUSED__, int type __UNUSED__, void *event)
717 Ecore_X_Event_Window_Property *ev;
722 if (ev->atom != ATM_ENLIGHTENMENT_SCALE) return ECORE_CALLBACK_PASS_ON;
723 EINA_LIST_FOREACH(hwins, l, hwin)
726 _il_home_fmc_set(hwin->o_fm);
727 e_fm2_refresh(hwin->o_fm);
730 return ECORE_CALLBACK_PASS_ON;
734 _il_home_cb_bg_change(void *data __UNUSED__, int type, void *event __UNUSED__)
739 if (type != E_EVENT_BG_UPDATE) return ECORE_CALLBACK_PASS_ON;
741 EINA_LIST_FOREACH(hwins, l, hwin)
748 desk = e_desk_current_get(zone);
750 bgfile = e_bg_file_get(zone->container->num, zone->num, desk->x, desk->y);
752 bgfile = e_bg_file_get(zone->container->num, zone->num, -1, -1);
753 edje_object_file_set(hwin->o_bg, bgfile, "e/desktop/background");
756 return ECORE_CALLBACK_PASS_ON;