1 #include "e_illume_private.h"
2 #include "e_mod_policy.h"
4 /* local function prototypes */
5 static char *_e_mod_policy_find(void);
6 static int _e_mod_policy_load(char *file);
7 static void _e_mod_policy_handlers_add(void);
8 static void _e_mod_policy_hooks_add(void);
9 static void _e_mod_policy_cb_free(E_Illume_Policy *p);
10 static Eina_Bool _e_mod_policy_cb_border_add(void *data __UNUSED__, int type __UNUSED__, void *event);
11 static Eina_Bool _e_mod_policy_cb_border_del(void *data __UNUSED__, int type __UNUSED__, void *event);
12 static Eina_Bool _e_mod_policy_cb_border_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event);
13 static Eina_Bool _e_mod_policy_cb_border_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event);
14 static Eina_Bool _e_mod_policy_cb_border_show(void *data __UNUSED__, int type __UNUSED__, void *event);
15 static Eina_Bool _e_mod_policy_cb_zone_move_resize(void *data __UNUSED__, int type __UNUSED__, void *event);
16 static Eina_Bool _e_mod_policy_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event);
17 static Eina_Bool _e_mod_policy_cb_window_property(void *data __UNUSED__, int type __UNUSED__, void *event);
18 static Eina_Bool _e_mod_policy_cb_policy_change(void *data __UNUSED__, int type, void *event __UNUSED__);
19 static void _e_mod_policy_cb_hook_post_fetch(void *data __UNUSED__, void *data2);
20 static void _e_mod_policy_cb_hook_post_assign(void *data __UNUSED__, void *data2);
21 static void _e_mod_policy_cb_hook_layout(void *data __UNUSED__, void *data2 __UNUSED__);
24 static E_Illume_Policy *_policy = NULL;
25 static Eina_List *_policy_hdls = NULL, *_policy_hooks = NULL;
27 /* external variables */
28 int E_ILLUME_POLICY_EVENT_CHANGE = 0;
31 e_mod_policy_init(void)
37 /* try to find the policy specified in config */
38 if (!(file = _e_mod_policy_find()))
40 printf("Cannot find policy\n");
44 /* attempt to load policy */
45 if (!_e_mod_policy_load(file))
47 /* loading policy failed, bail out */
48 printf("Cannot load policy: %s\n", file);
53 /* create new event for policy changes */
54 E_ILLUME_POLICY_EVENT_CHANGE = ecore_event_type_new();
56 /* add our event handlers */
57 _e_mod_policy_handlers_add();
59 /* add our border hooks */
60 _e_mod_policy_hooks_add();
62 /* loop the root windows */
63 EINA_LIST_FOREACH(e_manager_list(), ml, man)
68 /* loop the containers */
69 EINA_LIST_FOREACH(man->containers, cl, con)
75 EINA_LIST_FOREACH(con->zones, zl, zone)
77 E_Illume_Config_Zone *cz;
78 Ecore_X_Illume_Mode mode = ECORE_X_ILLUME_MODE_SINGLE;
80 /* check for zone config */
81 if (!(cz = e_illume_zone_config_get(zone->num)))
84 /* set mode on this zone */
85 if (cz->mode.dual == 0)
86 mode = ECORE_X_ILLUME_MODE_SINGLE;
89 if ((cz->mode.dual == 1) && (cz->mode.side == 0))
90 mode = ECORE_X_ILLUME_MODE_DUAL_TOP;
91 else if ((cz->mode.dual == 1) && (cz->mode.side == 1))
92 mode = ECORE_X_ILLUME_MODE_DUAL_LEFT;
94 ecore_x_e_illume_mode_set(zone->black_win, mode);
103 e_mod_policy_shutdown(void)
105 Ecore_Event_Handler *hdl;
108 /* remove the ecore event handlers */
109 EINA_LIST_FREE(_policy_hdls, hdl)
110 ecore_event_handler_del(hdl);
112 /* remove the border hooks */
113 EINA_LIST_FREE(_policy_hooks, hook)
114 e_border_hook_del(hook);
116 /* destroy the policy if it exists */
117 if (_policy) e_object_del(E_OBJECT(_policy));
119 /* reset event type */
120 E_ILLUME_POLICY_EVENT_CHANGE = 0;
125 /* local functions */
127 _e_mod_policy_find(void)
130 char buff[PATH_MAX], dir[PATH_MAX], *file;
132 snprintf(buff, sizeof(buff), "%s.so", _e_illume_cfg->policy.name);
133 snprintf(dir, sizeof(dir), "%s/policies", _e_illume_mod_dir);
135 /* try to list all files in this directory */
136 if (!(files = ecore_file_ls(dir))) return NULL;
138 /* loop the returned files */
139 EINA_LIST_FREE(files, file)
141 /* compare file with needed .so */
142 if (!strcmp(file, buff))
144 snprintf(dir, sizeof(dir), "%s/policies/%s",
145 _e_illume_mod_dir, file);
150 if (file) free(file);
153 /* if we did not find the requested policy, use a fallback */
154 snprintf(dir, sizeof(dir), "%s/policies/illume.so", _e_illume_mod_dir);
161 _e_mod_policy_load(char *file)
166 /* delete existing policy first */
167 if (_policy) e_object_del(E_OBJECT(_policy));
169 /* try to create our new policy object */
171 E_OBJECT_ALLOC(E_Illume_Policy, E_ILLUME_POLICY_TYPE,
172 _e_mod_policy_cb_free);
175 printf("Failed to allocate new policy object\n");
179 /* attempt to open the .so */
180 if (!(_policy->handle = dlopen(file, (RTLD_NOW | RTLD_GLOBAL))))
182 /* cannot open the .so file, bail out */
183 printf("Cannot open policy: %s\n", ecore_file_file_get(file));
184 printf("\tError: %s\n", dlerror());
185 e_object_del(E_OBJECT(_policy));
189 /* clear any existing errors in dynamic loader */
192 /* try to link to the needed policy api functions */
193 _policy->api = dlsym(_policy->handle, "e_illume_policy_api");
194 _policy->funcs.init = dlsym(_policy->handle, "e_illume_policy_init");
195 _policy->funcs.shutdown = dlsym(_policy->handle, "e_illume_policy_shutdown");
197 /* check that policy supports needed functions */
198 if ((!_policy->api) || (!_policy->funcs.init) || (!_policy->funcs.shutdown))
200 /* policy doesn't support needed functions, bail out */
201 printf("Policy does not support needed functions: %s\n",
202 ecore_file_file_get(file));
203 printf("\tError: %s\n", dlerror());
204 e_object_del(E_OBJECT(_policy));
208 /* check policy api version */
209 if (_policy->api->version < E_ILLUME_POLICY_API_VERSION)
211 /* policy is too old, bail out */
212 printf("Policy is too old: %s\n", ecore_file_file_get(file));
213 e_object_del(E_OBJECT(_policy));
217 /* try to initialize the policy */
218 if (!_policy->funcs.init(_policy))
220 /* init failed, bail out */
221 printf("Policy failed to initialize: %s\n", ecore_file_file_get(file));
222 e_object_del(E_OBJECT(_policy));
230 _e_mod_policy_handlers_add(void)
233 eina_list_append(_policy_hdls,
234 ecore_event_handler_add(E_EVENT_BORDER_ADD,
235 _e_mod_policy_cb_border_add, NULL));
237 eina_list_append(_policy_hdls,
238 ecore_event_handler_add(E_EVENT_BORDER_REMOVE,
239 _e_mod_policy_cb_border_del, NULL));
241 eina_list_append(_policy_hdls,
242 ecore_event_handler_add(E_EVENT_BORDER_FOCUS_IN,
243 _e_mod_policy_cb_border_focus_in,
246 eina_list_append(_policy_hdls,
247 ecore_event_handler_add(E_EVENT_BORDER_FOCUS_OUT,
248 _e_mod_policy_cb_border_focus_out,
251 eina_list_append(_policy_hdls,
252 ecore_event_handler_add(E_EVENT_BORDER_SHOW,
253 _e_mod_policy_cb_border_show,
256 eina_list_append(_policy_hdls,
257 ecore_event_handler_add(E_EVENT_ZONE_MOVE_RESIZE,
258 _e_mod_policy_cb_zone_move_resize,
261 eina_list_append(_policy_hdls,
262 ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
263 _e_mod_policy_cb_client_message,
266 eina_list_append(_policy_hdls,
267 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY,
268 _e_mod_policy_cb_window_property,
271 eina_list_append(_policy_hdls,
272 ecore_event_handler_add(E_ILLUME_POLICY_EVENT_CHANGE,
273 _e_mod_policy_cb_policy_change,
278 _e_mod_policy_hooks_add(void)
281 eina_list_append(_policy_hooks,
282 e_border_hook_add(E_BORDER_HOOK_EVAL_POST_FETCH,
283 _e_mod_policy_cb_hook_post_fetch, NULL));
285 eina_list_append(_policy_hooks,
286 e_border_hook_add(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN,
287 _e_mod_policy_cb_hook_post_assign, NULL));
289 eina_list_append(_policy_hooks,
290 e_border_hook_add(E_BORDER_HOOK_CONTAINER_LAYOUT,
291 _e_mod_policy_cb_hook_layout, NULL));
295 _e_mod_policy_cb_free(E_Illume_Policy *p)
297 /* tell the policy to shutdown */
298 if (p->funcs.shutdown) p->funcs.shutdown(p);
299 p->funcs.shutdown = NULL;
301 p->funcs.init = NULL;
304 /* close the linked .so */
305 if (p->handle) dlclose(p->handle);
312 _e_mod_policy_cb_border_add(void *data __UNUSED__, int type __UNUSED__, void *event)
314 E_Event_Border_Add *ev;
317 if ((_policy) && (_policy->funcs.border_add))
318 _policy->funcs.border_add(ev->border);
320 return ECORE_CALLBACK_PASS_ON;
324 _e_mod_policy_cb_border_del(void *data __UNUSED__, int type __UNUSED__, void *event)
326 E_Event_Border_Remove *ev;
329 if ((_policy) && (_policy->funcs.border_del))
330 _policy->funcs.border_del(ev->border);
332 return ECORE_CALLBACK_PASS_ON;
336 _e_mod_policy_cb_border_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event)
338 E_Event_Border_Focus_In *ev;
341 if ((_policy) && (_policy->funcs.border_focus_in))
342 _policy->funcs.border_focus_in(ev->border);
344 return ECORE_CALLBACK_PASS_ON;
348 _e_mod_policy_cb_border_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event)
350 E_Event_Border_Focus_Out *ev;
353 if ((_policy) && (_policy->funcs.border_focus_out))
354 _policy->funcs.border_focus_out(ev->border);
356 return ECORE_CALLBACK_PASS_ON;
360 _e_mod_policy_cb_border_show(void *data __UNUSED__, int type __UNUSED__, void *event)
362 E_Event_Border_Show *ev;
365 if ((_policy) && (_policy->funcs.border_show))
366 _policy->funcs.border_show(ev->border);
368 return ECORE_CALLBACK_PASS_ON;
372 _e_mod_policy_cb_zone_move_resize(void *data __UNUSED__, int type __UNUSED__, void *event)
374 E_Event_Zone_Move_Resize *ev;
377 if ((_policy) && (_policy->funcs.zone_move_resize))
378 _policy->funcs.zone_move_resize(ev->zone);
380 return ECORE_CALLBACK_PASS_ON;
384 _e_mod_zone_win_get(Ecore_X_Window win)
389 if (!(bd = e_border_find_by_client_window(win)))
391 if (!(zone = e_util_zone_window_find(win))) return NULL;
393 else if (bd->zone) zone = bd->zone;
398 _e_mod_policy_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event)
400 Ecore_X_Event_Client_Message *ev;
403 if (ev->message_type == ECORE_X_ATOM_NET_ACTIVE_WINDOW)
407 if (!(bd = e_border_find_by_client_window(ev->win))) return ECORE_CALLBACK_PASS_ON;
408 if ((_policy) && (_policy->funcs.border_activate))
409 _policy->funcs.border_activate(bd);
411 else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_MODE)
415 if (!(zone = _e_mod_zone_win_get(ev->win))) return ECORE_CALLBACK_PASS_ON;
416 if ((_policy) && (_policy->funcs.zone_mode_change))
417 _policy->funcs.zone_mode_change(zone, ev->data.l[0]);
419 else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_CLOSE)
423 if (!(zone = _e_mod_zone_win_get(ev->win))) return ECORE_CALLBACK_PASS_ON;
424 if ((_policy) && (_policy->funcs.zone_close))
425 _policy->funcs.zone_close(zone);
427 else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_FOCUS_BACK)
431 if (!(zone = _e_mod_zone_win_get(ev->win))) return ECORE_CALLBACK_PASS_ON;
432 if ((_policy) && (_policy->funcs.focus_back))
433 _policy->funcs.focus_back(zone);
435 else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD)
439 if (!(zone = _e_mod_zone_win_get(ev->win))) return ECORE_CALLBACK_PASS_ON;
440 if ((_policy) && (_policy->funcs.focus_forward))
441 _policy->funcs.focus_forward(zone);
443 else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_FOCUS_HOME)
447 if (!(zone = _e_mod_zone_win_get(ev->win))) return ECORE_CALLBACK_PASS_ON;
448 if ((_policy) && (_policy->funcs.focus_home))
449 _policy->funcs.focus_home(zone);
451 else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_DRAG_START)
455 if (!(bd = e_border_find_by_client_window(ev->win))) return ECORE_CALLBACK_PASS_ON;
456 if ((_policy) && (_policy->funcs.drag_start))
457 _policy->funcs.drag_start(bd);
459 else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_DRAG_END)
463 if (!(bd = e_border_find_by_client_window(ev->win))) return ECORE_CALLBACK_PASS_ON;
464 if ((_policy) && (_policy->funcs.drag_end))
465 _policy->funcs.drag_end(bd);
468 return ECORE_CALLBACK_PASS_ON;
472 _e_mod_policy_cb_window_property(void *data __UNUSED__, int type __UNUSED__, void *event)
474 Ecore_X_Event_Window_Property *ev;
477 if ((_policy) && (_policy->funcs.property_change))
478 _policy->funcs.property_change(ev);
480 return ECORE_CALLBACK_PASS_ON;
484 _e_mod_policy_cb_policy_change(void *data __UNUSED__, int type, void *event __UNUSED__)
488 if (type != E_ILLUME_POLICY_EVENT_CHANGE) return ECORE_CALLBACK_PASS_ON;
490 /* find policy specified in config */
491 if (!(file = _e_mod_policy_find())) return ECORE_CALLBACK_PASS_ON;
493 /* try to load the policy */
494 _e_mod_policy_load(file);
496 if (file) free(file);
498 return ECORE_CALLBACK_PASS_ON;
502 _e_mod_policy_cb_hook_post_fetch(void *data __UNUSED__, void *data2)
506 if (!(bd = data2)) return;
507 if ((_policy) && (_policy->funcs.border_post_fetch))
508 _policy->funcs.border_post_fetch(bd);
512 _e_mod_policy_cb_hook_post_assign(void *data __UNUSED__, void *data2)
516 if (!(bd = data2)) return;
517 if ((_policy) && (_policy->funcs.border_post_assign))
518 _policy->funcs.border_post_assign(bd);
522 _e_mod_policy_cb_hook_layout(void *data __UNUSED__, void *data2 __UNUSED__)
526 Eina_List *zl = NULL, *l;
528 /* loop through border list and find what changed */
529 EINA_LIST_FOREACH(e_border_client_list(), l, bd)
531 if ((bd->new_client) || (bd->pending_move_resize) ||
532 (bd->changes.pos) || (bd->changes.size) || (bd->changes.visible) ||
533 (bd->need_shape_export) || (bd->need_shape_merge))
535 /* NB: this border changed. add it's zone to list of what needs
536 * updating. This is done so we do not waste cpu cycles
537 * updating zones where nothing changed */
538 if (!eina_list_data_find(zl, bd->zone))
539 zl = eina_list_append(zl, bd->zone);
543 /* loop the zones that need updating and call the policy update function */
544 EINA_LIST_FREE(zl, zone)
546 if ((_policy) && (_policy->funcs.zone_layout))
547 _policy->funcs.zone_layout(zone);