forked from enlightenment/enlightenment
288 lines
8.2 KiB
C
288 lines
8.2 KiB
C
#define E_COMP_X
|
|
|
|
#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__, E_Client *ec);
|
|
static void _cb_hook_post_assign(void *data __UNUSED__, E_Client *ec);
|
|
static void _cb_hook_layout(E_Comp *comp);
|
|
|
|
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 *clients = NULL;
|
|
static E_Client *ec_active = NULL;
|
|
|
|
#define LADD(l, f) l = eina_list_append(l, f)
|
|
|
|
void
|
|
e_policy_init(void)
|
|
{
|
|
LADD(hooks, e_client_hook_add(E_CLIENT_HOOK_EVAL_POST_FETCH,
|
|
_cb_hook_post_fetch, NULL));
|
|
LADD(hooks, e_client_hook_add(E_CLIENT_HOOK_EVAL_POST_FRAME_ASSIGN,
|
|
_cb_hook_post_assign, NULL));
|
|
LADD(handlers, ecore_event_handler_add(E_EVENT_CLIENT_ADD,
|
|
_cb_event_add, NULL));
|
|
LADD(handlers, ecore_event_handler_add(E_EVENT_CLIENT_REMOVE,
|
|
_cb_event_del, NULL));
|
|
LADD(handlers, ecore_event_handler_add(E_EVENT_CLIENT_FOCUS_IN,
|
|
_cb_event_focus_in, NULL));
|
|
LADD(handlers, ecore_event_handler_add(E_EVENT_CLIENT_FOCUS_OUT,
|
|
_cb_event_focus_out, NULL));
|
|
e_client_layout_cb_set((E_Client_Layout_Cb)_cb_hook_layout);
|
|
}
|
|
|
|
void
|
|
e_policy_shutdown(void)
|
|
{
|
|
E_Client_Hook *bh;
|
|
Ecore_Event_Handler *eh;
|
|
|
|
EINA_LIST_FREE(hooks, bh) e_client_hook_del(bh);
|
|
EINA_LIST_FREE(handlers, eh) ecore_event_handler_del(eh);
|
|
e_client_layout_cb_set(NULL);
|
|
}
|
|
|
|
void
|
|
e_policy_kbd_override_set(Eina_Bool override)
|
|
{
|
|
const Eina_List *l, *ll;
|
|
E_Client *ec, *kbd = NULL;;
|
|
E_Comp *comp;
|
|
|
|
if (kbd_override == override) return;
|
|
kbd_override = override;
|
|
EINA_LIST_FOREACH(e_comp_list(), l, comp)
|
|
EINA_LIST_FOREACH(comp->clients, ll, ec)
|
|
{
|
|
if (ec->vkbd.vkbd)
|
|
{
|
|
kbd = ec;
|
|
}
|
|
}
|
|
if (kbd)
|
|
{
|
|
ec = kbd;
|
|
e_client_uniconify(ec);
|
|
evas_object_raise(ec->frame);
|
|
evas_object_show(ec->frame);
|
|
}
|
|
}
|
|
|
|
const Eina_List *
|
|
e_policy_clients_get(void)
|
|
{
|
|
return clients;
|
|
}
|
|
|
|
const E_Client *
|
|
e_policy_client_active_get(void)
|
|
{
|
|
return ec_active;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_event_add(void *data __UNUSED__, int type __UNUSED__, void *event)
|
|
{
|
|
E_Event_Client *ev = event;
|
|
E_Client *ec = ev->ec;
|
|
|
|
if (ec_active) clients = eina_list_append_relative(clients, ec, ec_active);
|
|
else clients = eina_list_prepend(clients, ec);
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_event_del(void *data __UNUSED__, int type __UNUSED__, void *event)
|
|
{
|
|
E_Event_Client *ev = event;
|
|
E_Client *ec = ev->ec;
|
|
|
|
clients = eina_list_remove(clients, ec);
|
|
if (ec_active == ec) ec_active = NULL;
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_event_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event)
|
|
{
|
|
E_Event_Client *ev = event;
|
|
E_Client *ec = ev->ec;
|
|
|
|
ec_active = ec;
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_event_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event)
|
|
{
|
|
E_Event_Client *ev = event;
|
|
E_Client *ec = ev->ec;
|
|
|
|
if (ec_active == ec) ec_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__, E_Client *ec)
|
|
{
|
|
/* NB: for this policy we disable all remembers set on a client */
|
|
if (ec->remember) e_remember_del(ec->remember);
|
|
ec->remember = NULL;
|
|
|
|
/* set this client to borderless */
|
|
ec->borderless = 1;
|
|
EC_CHANGED(ec);
|
|
}
|
|
|
|
static void
|
|
_cb_hook_post_assign(void *data __UNUSED__, E_Client *ec)
|
|
{
|
|
ec->internal_no_remember = 1;
|
|
|
|
/* do not allow client to change these properties */
|
|
ec->lock_client_size = 1;
|
|
ec->lock_client_shade = 1;
|
|
ec->lock_client_maximize = 1;
|
|
ec->lock_client_location = 1;
|
|
ec->lock_client_stacking = 1;
|
|
|
|
/* do not allow the user to change these properties */
|
|
ec->lock_user_location = 1;
|
|
ec->lock_user_size = 1;
|
|
ec->lock_user_shade = 1;
|
|
|
|
/* clear any centered states */
|
|
/* NB: this is mainly needed for E's main config dialog */
|
|
ec->e.state.centered = 0;
|
|
|
|
/* lock the border type so user/client cannot change */
|
|
ec->lock_border = 1;
|
|
}
|
|
|
|
static void
|
|
_cb_hook_layout(E_Comp *comp)
|
|
{
|
|
Eina_List *l;
|
|
E_Client *ec, *kbd = NULL;;
|
|
Eina_Bool want_kbd = EINA_FALSE;
|
|
Eina_Bool have_focused = EINA_FALSE;
|
|
int kx = 0, ky = 0, kw = 0, kh = 0;
|
|
|
|
EINA_LIST_FOREACH(comp->clients, l, ec)
|
|
{
|
|
if (e_client_util_ignored_get(ec)) continue;
|
|
if (ec->focused) have_focused = EINA_TRUE;
|
|
#ifndef HAVE_WAYLAND_ONLY
|
|
if ((ec->focused) &&
|
|
(ec->vkbd.state > ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF))
|
|
want_kbd = EINA_TRUE;
|
|
if (ec->vkbd.vkbd) kbd = ec;
|
|
#endif
|
|
}
|
|
|
|
if ((have_focused) && (kbd_override)) want_kbd = EINA_TRUE;
|
|
|
|
if (kbd)
|
|
{
|
|
kw = kbd->zone->w;
|
|
kh = kbd->icccm.min_h;
|
|
kx = kbd->zone->x;
|
|
ky = kbd->zone->y + kbd->zone->h - kh;
|
|
}
|
|
EINA_LIST_FOREACH(comp->clients, l, ec)
|
|
{
|
|
int x, y, w, h;
|
|
|
|
if (!ec->zone) continue;
|
|
if (e_client_util_ignored_get(ec)) continue;
|
|
|
|
w = ec->zone->w;
|
|
h = ec->zone->h;
|
|
x = ec->zone->x;
|
|
y = ec->zone->y;
|
|
|
|
if (ec->vkbd.vkbd)
|
|
{
|
|
x = kx; y = ky; w = kw; h = kh;
|
|
if (want_kbd)
|
|
{
|
|
e_client_uniconify(ec);
|
|
evas_object_raise(ec->frame);
|
|
evas_object_show(ec->frame);
|
|
}
|
|
else
|
|
{
|
|
e_client_iconify(ec);
|
|
}
|
|
}
|
|
else if (((ec->netwm.type == E_WINDOW_TYPE_DIALOG) ||
|
|
(ec->icccm.transient_for != 0)) &&
|
|
((ec->icccm.min_w == ec->icccm.max_w) &&
|
|
(ec->icccm.min_h == ec->icccm.max_h)))
|
|
{
|
|
// center dialog at min size
|
|
w = ec->icccm.min_w;
|
|
h = ec->icccm.min_h;
|
|
if (w > (ec->zone->w)) w = ec->zone->w;
|
|
if (h > (ec->zone->h - kh)) h = (ec->zone->h - kh);
|
|
x = ec->zone->x + ((ec->zone->w - w) / 2);
|
|
y = ec->zone->y + ((ec->zone->h - kh - h) / 2);
|
|
}
|
|
else
|
|
{
|
|
#warning X ONLY! SPANK! SPANK! SPANK!!!
|
|
if (ec->comp_data->illume.conformant.conformant)
|
|
{
|
|
if (kbd_on != want_kbd)
|
|
{
|
|
if (want_kbd)
|
|
ecore_x_e_illume_keyboard_geometry_set(e_client_util_win_get(ec),
|
|
kx, ky, kw, kh);
|
|
else
|
|
ecore_x_e_illume_keyboard_geometry_set(e_client_util_win_get(ec),
|
|
0, 0, 0, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// just make all windows fill the zone...
|
|
if (want_kbd)
|
|
{
|
|
w = ec->zone->w;
|
|
h = ec->zone->h - kh;
|
|
x = ec->zone->x;
|
|
y = ec->zone->y;
|
|
}
|
|
}
|
|
}
|
|
|
|
// implement the positioning/sizing
|
|
if ((ec->x != x) || (ec->y != y))
|
|
{
|
|
ec->placed = 1;
|
|
ec->x = x;
|
|
ec->y = y;
|
|
ec->changes.pos = 1;
|
|
EC_CHANGED(ec);
|
|
}
|
|
if ((ec->w != w) || (ec->h != h))
|
|
{
|
|
ec->w = w;
|
|
ec->h = h;
|
|
e_comp_object_frame_wh_unadjust(ec->frame, ec->w, ec->h, &ec->client.w, &ec->client.h);
|
|
ec->changes.size = 1;
|
|
EC_CHANGED(ec);
|
|
}
|
|
}
|
|
|
|
kbd_on = want_kbd;
|
|
}
|