#include "e_mod_main.h" static Eina_Bool _cb_event_add(void *data __UNUSED__, int type __UNUSED__, void *event); static Eina_Bool _cb_event_del(void *data __UNUSED__, int type __UNUSED__, void *event); static Eina_Bool _cb_event_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event); static Eina_Bool _cb_event_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event); static void _cb_hook_post_fetch(void *data __UNUSED__, void *data2); static void _cb_hook_post_assign(void *data __UNUSED__, void *data2); static void _cb_hook_layout(void *data __UNUSED__, void *data2); static Eina_List *hooks = NULL; static Eina_List *handlers = NULL; static Eina_Bool kbd_on = EINA_FALSE; static Eina_Bool kbd_override = EINA_FALSE; static Eina_List *borders = NULL; static E_Border *bd_active = NULL; #define LADD(l, f) l = eina_list_append(l, f) void e_policy_init(void) { LADD(hooks, e_border_hook_add(E_BORDER_HOOK_EVAL_POST_FETCH, _cb_hook_post_fetch, NULL)); LADD(hooks, e_border_hook_add(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, _cb_hook_post_assign, NULL)); LADD(hooks, e_border_hook_add(E_BORDER_HOOK_CONTAINER_LAYOUT, _cb_hook_layout, NULL)); LADD(handlers, ecore_event_handler_add(E_EVENT_BORDER_ADD, _cb_event_add, NULL)); LADD(handlers, ecore_event_handler_add(E_EVENT_BORDER_REMOVE, _cb_event_del, NULL)); LADD(handlers, ecore_event_handler_add(E_EVENT_BORDER_FOCUS_IN, _cb_event_focus_in, NULL)); LADD(handlers, ecore_event_handler_add(E_EVENT_BORDER_FOCUS_OUT, _cb_event_focus_out, NULL)); } void e_policy_shutdown(void) { E_Border_Hook *bh; Ecore_Event_Handler *eh; EINA_LIST_FREE(hooks, bh) e_border_hook_del(bh); EINA_LIST_FREE(handlers, eh) ecore_event_handler_del(eh); } void e_policy_kbd_override_set(Eina_Bool override) { Eina_List *l; E_Border *bd, *kbd = NULL;; if (kbd_override == override) return; kbd_override = override; EINA_LIST_FOREACH(e_border_client_list(), l, bd) { if (bd->client.vkbd.vkbd) { kbd = bd; } } if (kbd) { bd = kbd; e_border_uniconify(bd); e_border_raise(bd); e_border_show(bd); } } const Eina_List * e_policy_borders_get(void) { return borders; } const E_Border * e_polict_border_active_get(void) { return bd_active; } static Eina_Bool _cb_event_add(void *data __UNUSED__, int type __UNUSED__, void *event) { E_Event_Border_Add *ev = event; E_Border *bd = ev->border; if (bd_active) borders = eina_list_append_relative(borders, bd, bd_active); else borders = eina_list_prepend(borders, bd); return ECORE_CALLBACK_PASS_ON; } static Eina_Bool _cb_event_del(void *data __UNUSED__, int type __UNUSED__, void *event) { E_Event_Border_Remove *ev = event; E_Border *bd = ev->border; borders = eina_list_remove(borders, bd); if (bd_active == bd) bd_active = NULL; return ECORE_CALLBACK_PASS_ON; } static Eina_Bool _cb_event_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event) { E_Event_Border_Focus_In *ev = event; E_Border *bd = ev->border; bd_active = bd; return ECORE_CALLBACK_PASS_ON; } static Eina_Bool _cb_event_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event) { E_Event_Border_Focus_Out *ev = event; E_Border *bd = ev->border; if (bd_active == bd) bd_active = NULL; if (kbd_on) e_policy_kbd_override_set(EINA_FALSE); return ECORE_CALLBACK_PASS_ON; } static void _cb_hook_post_fetch(void *data __UNUSED__, void *data2) { E_Border *bd = data2; if (!bd) return; /* NB: for this policy we disable all remembers set on a border */ if (bd->remember) e_remember_del(bd->remember); bd->remember = NULL; /* set this border to borderless */ bd->borderless = 1; bd->client.border.changed = 1; } static void _cb_hook_post_assign(void *data __UNUSED__, void *data2) { E_Border *bd = data2; if (!bd) return; bd->internal_no_remember = 1; /* do not allow client to change these properties */ bd->lock_client_size = 1; bd->lock_client_shade = 1; bd->lock_client_maximize = 1; bd->lock_client_location = 1; bd->lock_client_stacking = 1; /* do not allow the user to change these properties */ bd->lock_user_location = 1; bd->lock_user_size = 1; bd->lock_user_shade = 1; /* clear any centered states */ /* NB: this is mainly needed for E's main config dialog */ bd->client.e.state.centered = 0; /* lock the border type so user/client cannot change */ bd->lock_border = 1; } static void _cb_hook_layout(void *data __UNUSED__, void *data2) { E_Container *con = data2; Eina_List *l; E_Border *bd, *kbd = NULL;; Eina_Bool want_kbd = EINA_FALSE; Eina_Bool have_focused = EINA_FALSE; int kx = 0, ky = 0, kw = 0, kh = 0; if (!con) return; EINA_LIST_FOREACH(e_border_client_list(), l, bd) { if (bd->focused) have_focused = EINA_TRUE; if ((bd->focused) && (bd->client.vkbd.state > ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)) want_kbd = EINA_TRUE; if (bd->client.vkbd.vkbd) kbd = bd; } if ((have_focused) && (kbd_override)) want_kbd = EINA_TRUE; if (kbd) { kw = kbd->zone->w; kh = kbd->client.icccm.min_h; kx = kbd->zone->x; ky = kbd->zone->y + kbd->zone->h - kh; } EINA_LIST_FOREACH(e_border_client_list(), l, bd) { int x, y, w, h; if (!bd->zone) continue; w = bd->zone->w; h = bd->zone->h; x = bd->zone->x; y = bd->zone->y; if (bd->client.vkbd.vkbd) { x = kx; y = ky; w = kw; h = kh; if (want_kbd) { e_border_uniconify(bd); e_border_raise(bd); e_border_show(bd); } else { e_border_iconify(bd); } } else if (((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG) || (bd->client.icccm.transient_for != 0)) && ((bd->client.icccm.min_w == bd->client.icccm.max_w) && (bd->client.icccm.min_h == bd->client.icccm.max_h))) { // center dialog at min size w = bd->client.icccm.min_w; h = bd->client.icccm.min_h; if (w > (bd->zone->w)) w = bd->zone->w; if (h > (bd->zone->h - kh)) h = (bd->zone->h - kh); x = bd->zone->x + ((bd->zone->w - w) / 2); y = bd->zone->y + ((bd->zone->h - kh - h) / 2); } else { if (bd->client.illume.conformant.conformant) { if (kbd_on != want_kbd) { if (want_kbd) ecore_x_e_illume_keyboard_geometry_set(bd->client.win, kx, ky, kw, kh); else ecore_x_e_illume_keyboard_geometry_set(bd->client.win, 0, 0, 0, 0); } } else { // just make all windows fill the zone... if (want_kbd) { w = bd->zone->w; h = bd->zone->h - kh; x = bd->zone->x; y = bd->zone->y; } } } // implement the positioning/sizing if ((bd->x != x) || (bd->y != y)) { bd->placed = 1; bd->x = x; bd->y = y; bd->changes.pos = 1; bd->changed = 1; } if ((bd->w != w) || (bd->h != h)) { bd->w = w; bd->h = h; bd->client.w = (bd->w - (bd->client_inset.l + bd->client_inset.r)); bd->client.h = (bd->h - (bd->client_inset.t + bd->client_inset.b)); bd->changes.size = 1; bd->changed = 1; } } kbd_on = want_kbd; }