1516 lines
38 KiB
C
1516 lines
38 KiB
C
#include "e_illume.h"
|
|
#include "policy.h"
|
|
#include "e.h"
|
|
|
|
/* local function prototypes */
|
|
static void _policy_border_set_focus(E_Client *ec);
|
|
static void _policy_border_move(E_Client *ec, int x, int y);
|
|
static void _policy_border_resize(E_Client *ec, int w, int h);
|
|
static void _policy_border_hide_below(E_Client *ec);
|
|
static void _policy_zone_layout_update(E_Zone *zone);
|
|
static void _policy_zone_layout_indicator(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_quickpanel(E_Client *ec);
|
|
static void _policy_zone_layout_softkey(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_keyboard(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_home_single(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_fullscreen(E_Client *ec);
|
|
static void _policy_zone_layout_app_single(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_app_dual_top(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_app_dual_custom(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_app_dual_left(E_Client *ec, E_Illume_Config_Zone *cz, Eina_Bool force);
|
|
static void _policy_zone_layout_dialog(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_splash(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_conformant_single(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
#if 0
|
|
static void _policy_zone_layout_conformant_dual_top(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_conformant_dual_custom(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
static void _policy_zone_layout_conformant_dual_left(E_Client *ec, E_Illume_Config_Zone *cz);
|
|
#endif
|
|
|
|
static Eina_List *_pol_focus_stack;
|
|
|
|
/* local functions */
|
|
static void
|
|
_policy_border_set_focus(E_Client *ec)
|
|
{
|
|
if (!ec) return;
|
|
/* printf("_policy_border_set_focus %s\n", e_client_util_name_get(ec)); */
|
|
|
|
/* if focus is locked out then get out */
|
|
if (ec->lock_focus_out) return;
|
|
|
|
if ((ec->icccm.accepts_focus) || (ec->icccm.take_focus))
|
|
{
|
|
/* check E's focus settings */
|
|
if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
|
|
((ec->parent) &&
|
|
((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
|
|
((ec->parent->focused) &&
|
|
(e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))))
|
|
{
|
|
/* if the border was hidden due to layout, we need to unhide */
|
|
if (!ec->visible) e_illume_client_show(ec);
|
|
|
|
if ((ec->iconic) && (!ec->lock_user_iconify))
|
|
e_client_uniconify(ec);
|
|
|
|
if (!ec->lock_user_stacking) evas_object_raise(ec->frame);
|
|
|
|
/* focus the border */
|
|
evas_object_focus_set(ec->frame, 1);
|
|
/* evas_object_raise(ec->frame); */
|
|
/* hide the border below this one */
|
|
_policy_border_hide_below(ec);
|
|
|
|
/* NB: since we skip needless border evals when container layout
|
|
* is called (to save cpu cycles), we need to
|
|
* signal this border that it's focused so that the edj gets
|
|
* updated.
|
|
*
|
|
* This is potentially useless as THIS policy
|
|
* makes all windows borderless anyway, but it's in here for
|
|
* completeness
|
|
e_client_focus_latest_set(ec);
|
|
if (ec->bg_object)
|
|
edje_object_signal_emit(ec->bg_object, "e,state,focused", "e");
|
|
if (ec->icon_object)
|
|
edje_object_signal_emit(ec->icon_object, "e,state,focused", "e");
|
|
e_focus_event_focus_in(ec);
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_policy_border_move(E_Client *ec, int x, int y)
|
|
{
|
|
if (!ec) return;
|
|
|
|
ec->x = x;
|
|
ec->y = y;
|
|
ec->changes.pos = 1;
|
|
EC_CHANGED(ec);
|
|
}
|
|
|
|
static void
|
|
_policy_border_resize(E_Client *ec, int w, int h)
|
|
{
|
|
if (!ec) return;
|
|
|
|
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);
|
|
}
|
|
|
|
static void
|
|
_policy_border_hide_below(E_Client *ec)
|
|
{
|
|
E_Client *b;
|
|
|
|
return;
|
|
|
|
// printf("Hide Borders Below: %s %d %d\n",
|
|
// ec->icccm.name, ec->x, ec->y);
|
|
|
|
if (!ec) return;
|
|
|
|
/* Find the windows below this one */
|
|
E_CLIENT_FOREACH(ec->comp, b)
|
|
{
|
|
if (e_client_util_ignored_get(b)) continue;
|
|
if (b->layer < E_LAYER_CLIENT_BELOW) continue;
|
|
/* skip if it's the same border */
|
|
if (b == ec) break;
|
|
|
|
/* skip if it's not on this zone */
|
|
if (b->zone != ec->zone) continue;
|
|
|
|
/* skip special borders */
|
|
if (e_illume_client_is_indicator(b)) continue;
|
|
if (e_illume_client_is_softkey(b)) continue;
|
|
if (e_illume_client_is_keyboard(b)) continue;
|
|
if (e_illume_client_is_quickpanel(b)) continue;
|
|
if (e_illume_client_is_home(b)) continue;
|
|
|
|
if ((ec->fullscreen) || (ec->need_fullscreen))
|
|
{
|
|
if (b->visible) e_illume_client_hide(b);
|
|
}
|
|
else
|
|
{
|
|
/* we need to check x/y position */
|
|
if (E_CONTAINS(ec->x, ec->y, ec->w, ec->h,
|
|
b->x, b->y, b->w, b->h))
|
|
{
|
|
if (b->visible) e_illume_client_hide(b);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
static void
|
|
_policy_border_show_below(E_Client *ec)
|
|
{
|
|
Eina_List *l;
|
|
E_Client *prev, *b;
|
|
|
|
// printf("Show Borders Below: %s %d %d\n",
|
|
// ec->icccm.class, ec->x, ec->y);
|
|
|
|
if (!ec) return;
|
|
/* printf("_policy_border_show_below %s\n", e_client_util_name_get(ec)); */
|
|
if (ec->icccm.transient_for)
|
|
{
|
|
if ((prev = e_pixmap_find_client(E_PIXMAP_TYPE_X, ec->icccm.transient_for)))
|
|
{
|
|
_policy_border_set_focus(prev);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Find the windows below this one */
|
|
E_CLIENT_FOREACH(ec->comp, b)
|
|
{
|
|
if (e_client_util_ignored_get(b)) continue;
|
|
if (b->layer < E_LAYER_CLIENT_BELOW) continue;
|
|
if (b == ec) break;
|
|
|
|
/* skip if it's not on this zone */
|
|
if (b->zone != ec->zone) continue;
|
|
|
|
/* skip special borders */
|
|
if (e_illume_client_is_indicator(b)) continue;
|
|
if (e_illume_client_is_softkey(b)) continue;
|
|
if (e_illume_client_is_keyboard(b)) continue;
|
|
if (e_illume_client_is_quickpanel(b)) continue;
|
|
if (e_illume_client_is_home(b)) continue;
|
|
|
|
if ((ec->fullscreen) || (ec->need_fullscreen))
|
|
{
|
|
_policy_border_set_focus(b);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
/* need to check x/y position */
|
|
if (E_CONTAINS(ec->x, ec->y, ec->w, ec->h,
|
|
b->x, b->y, b->w, b->h))
|
|
{
|
|
_policy_border_set_focus(b);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* if we reach here, then there is a problem with showing a window below
|
|
* this one, so show previous window in stack */
|
|
EINA_LIST_REVERSE_FOREACH(_pol_focus_stack, l, prev)
|
|
{
|
|
if (prev->zone != ec->zone) continue;
|
|
_policy_border_set_focus(prev);
|
|
return;
|
|
}
|
|
|
|
/* Fallback to focusing home if all above fails */
|
|
_policy_focus_home(ec->zone);
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
_policy_zone_layout_update(E_Zone *zone)
|
|
{
|
|
Eina_List *l;
|
|
E_Client *ec;
|
|
|
|
if (!zone) return;
|
|
|
|
EINA_LIST_FOREACH(zone->comp->clients, l, ec)
|
|
{
|
|
if (e_client_util_ignored_get(ec)) continue;
|
|
/* skip borders not on this zone */
|
|
if (ec->zone != zone) continue;
|
|
|
|
/* skip special windows */
|
|
if (e_object_is_del(E_OBJECT(ec))) continue;
|
|
if (e_illume_client_is_keyboard(ec)) continue;
|
|
if (e_illume_client_is_quickpanel(ec)) continue;
|
|
|
|
/* signal a changed pos here so layout gets updated */
|
|
ec->changes.pos = 1;
|
|
EC_CHANGED(ec);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_indicator(E_Client *ec, E_Illume_Config_Zone *cz)
|
|
{
|
|
if ((!ec) || (!cz)) return;
|
|
|
|
/* grab minimum indicator size */
|
|
e_illume_client_min_get(ec, NULL, &cz->indicator.size);
|
|
|
|
/* no point in doing anything here if indicator is hidden */
|
|
if ((!ec->new_client) && (!ec->visible))
|
|
{
|
|
ecore_x_e_illume_indicator_geometry_set(ec->zone->black_win,
|
|
0, 0, 0, 0);
|
|
return;
|
|
}
|
|
|
|
/* if we are dragging, then skip it for now */
|
|
if (ec->illume.drag.drag)
|
|
{
|
|
/* when dragging indicator, we need to trigger a layout update */
|
|
ecore_x_e_illume_indicator_geometry_set(ec->zone->black_win,
|
|
0, 0, 0, 0);
|
|
_policy_zone_layout_update(ec->zone);
|
|
return;
|
|
}
|
|
|
|
// printf("\tLayout Indicator: %d\n", ec->zone->num);
|
|
|
|
/* lock indicator window from dragging if we need to */
|
|
if ((cz->mode.dual == 1) && (cz->mode.side == 0))
|
|
ecore_x_e_illume_drag_locked_set(e_client_util_win_get(ec), 0);
|
|
else
|
|
ecore_x_e_illume_drag_locked_set(e_client_util_win_get(ec), 1);
|
|
|
|
if ((ec->w != ec->zone->w) || (ec->h != cz->indicator.size))
|
|
_policy_border_resize(ec, ec->zone->w, cz->indicator.size);
|
|
|
|
if (!cz->mode.dual)
|
|
{
|
|
/* move to 0, 0 (relative to zone) if needed */
|
|
if ((ec->x != ec->zone->x) || (ec->y != ec->zone->y))
|
|
{
|
|
_policy_border_move(ec, ec->zone->x, ec->zone->y);
|
|
ecore_x_e_illume_quickpanel_position_update_send(e_client_util_win_get(ec));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (cz->mode.side == 0)
|
|
{
|
|
/* top mode...indicator is draggable so just set X.
|
|
* in this case, the indicator itself should be responsible for
|
|
* sending the quickpanel position update message when it is
|
|
* finished dragging */
|
|
if (ec->x != ec->zone->x)
|
|
_policy_border_move(ec, ec->zone->x, ec->y);
|
|
}
|
|
else
|
|
{
|
|
/* move to 0, 0 (relative to zone) if needed */
|
|
if ((ec->x != ec->zone->x) || (ec->y != ec->zone->y))
|
|
{
|
|
_policy_border_move(ec, ec->zone->x, ec->zone->y);
|
|
ecore_x_e_illume_quickpanel_position_update_send(e_client_util_win_get(ec));
|
|
}
|
|
}
|
|
}
|
|
ecore_x_e_illume_indicator_geometry_set(ec->zone->black_win,
|
|
ec->x, ec->y,
|
|
ec->w, ec->h);
|
|
|
|
if (ec->layer != POL_INDICATOR_LAYER)
|
|
evas_object_layer_set(ec->frame, POL_INDICATOR_LAYER);
|
|
}
|
|
|
|
#define ZONE_GEOMETRY \
|
|
int x, y, w, h; \
|
|
e_zone_useful_geometry_get(ec->zone, &x, &y, &w, &h); \
|
|
x += ec->zone->x; \
|
|
y += ec->zone->y; \
|
|
|
|
static void
|
|
_border_geometry_set(E_Client *ec, int x, int y, int w, int h, int layer)
|
|
{
|
|
if ((ec->w != w) || (ec->h != h))
|
|
_policy_border_resize(ec, w, h);
|
|
|
|
if ((ec->x != x) || (ec->y != y))
|
|
_policy_border_move(ec, x, y);
|
|
|
|
if ((int)ec->layer != layer) evas_object_layer_set(ec->frame, layer);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_quickpanel(E_Client *ec)
|
|
{
|
|
int mh;
|
|
|
|
if (!ec) return;
|
|
|
|
e_illume_client_min_get(ec, NULL, &mh);
|
|
|
|
if ((ec->w != ec->zone->w) || (ec->h != mh))
|
|
_policy_border_resize(ec, ec->zone->w, mh);
|
|
|
|
if (ec->layer != POL_QUICKPANEL_LAYER)
|
|
evas_object_layer_set(ec->frame, POL_QUICKPANEL_LAYER);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_softkey(E_Client *ec, E_Illume_Config_Zone *cz)
|
|
{
|
|
int ny;
|
|
|
|
if ((!ec) || (!cz)) return;
|
|
if (!ec->visible)
|
|
{
|
|
ecore_x_e_illume_softkey_geometry_set(ec->zone->black_win, 0, 0, 0, 0);
|
|
return;
|
|
}
|
|
|
|
ZONE_GEOMETRY;
|
|
|
|
e_illume_client_min_get(ec, NULL, &cz->softkey.size);
|
|
|
|
/* if we are dragging, then skip it for now */
|
|
/* NB: Disabled currently until we confirm that softkey should be draggable */
|
|
// if (ec->illume.drag.drag) return;
|
|
|
|
if ((ec->w != w) || (ec->h != cz->softkey.size))
|
|
_policy_border_resize(ec, w, cz->softkey.size);
|
|
|
|
ny = ((ec->zone->y + ec->zone->h) - cz->softkey.size);
|
|
|
|
/* NB: not sure why yet, but on startup the border->y is reporting
|
|
* that it is already in this position...but it's actually not.
|
|
* So for now, just disable the ny check until this gets sorted out */
|
|
|
|
if ((ec->x != x) || (ec->y != ny))
|
|
_policy_border_move(ec, x, ny);
|
|
|
|
/* _border_geometry_set(ec, x, ny, nw, nh, ec, POL_CONFORMANT_LAYER); */
|
|
|
|
ecore_x_e_illume_softkey_geometry_set(ec->zone->black_win,
|
|
ec->x, ec->y,
|
|
ec->w, ec->h);
|
|
|
|
if (ec->layer != POL_SOFTKEY_LAYER) evas_object_layer_set(ec->frame, POL_SOFTKEY_LAYER);
|
|
}
|
|
|
|
|
|
|
|
#define MIN_HEIGHT 100
|
|
|
|
static Eina_Bool
|
|
_policy_layout_app_check(E_Client *ec)
|
|
{
|
|
if (!ec)
|
|
return EINA_FALSE;
|
|
|
|
if (!ec->visible)
|
|
return EINA_FALSE;
|
|
|
|
if ((ec->desk != e_desk_current_get(ec->zone)) && (!ec->sticky))
|
|
return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
|
|
static void
|
|
_policy_keyboard_restrict(E_Client *ec, int *h)
|
|
{
|
|
int kh;
|
|
|
|
if (ec->vkbd.state > ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
|
|
{
|
|
e_illume_keyboard_safe_app_region_get(ec->zone, NULL, NULL, NULL, &kh);
|
|
kh -= ec->zone->h - *h;
|
|
if ((kh < *h) && (kh > MIN_HEIGHT))
|
|
*h = kh;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_policy_indicator_restrict(E_Illume_Config_Zone *cz, int *y, int *h)
|
|
{
|
|
if ((cz->indicator.size) && (*y < cz->indicator.size))
|
|
{
|
|
*h -= cz->indicator.size;
|
|
*y = cz->indicator.size;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_policy_softkey_restrict(E_Illume_Config_Zone *cz, int *y, int *h)
|
|
{
|
|
if ((cz->softkey.size) && ((*y + *h) > cz->softkey.size))
|
|
*h -= (*y + *h) - cz->softkey.size;
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_keyboard(E_Client *ec, E_Illume_Config_Zone *cz)
|
|
{
|
|
int ny, layer;
|
|
|
|
if ((!ec) || (!cz) || (!ec->visible)) return;
|
|
|
|
ZONE_GEOMETRY;
|
|
|
|
e_illume_client_min_get(ec, NULL, &cz->vkbd.size);
|
|
|
|
ny = ((ec->zone->y + ec->zone->h) - cz->vkbd.size);
|
|
|
|
/* if ((ec->fullscreen) || (ec->need_fullscreen))
|
|
* layer = POL_FULLSCREEN_LAYER;
|
|
* else */
|
|
layer = POL_KEYBOARD_LAYER;
|
|
|
|
_border_geometry_set(ec, x, ny, w, cz->vkbd.size, layer);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_home_single(E_Client *ec, E_Illume_Config_Zone *cz)
|
|
{
|
|
if ((!ec) || (!cz) || (!ec->visible)) return;
|
|
|
|
ZONE_GEOMETRY;
|
|
_policy_indicator_restrict(cz, &y, &h);
|
|
_border_geometry_set(ec, x, y, w, h, POL_HOME_LAYER);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_fullscreen(E_Client *ec)
|
|
{
|
|
if (!_policy_layout_app_check(ec)) return;
|
|
|
|
ZONE_GEOMETRY;
|
|
|
|
_policy_keyboard_restrict(ec, &h);
|
|
|
|
_border_geometry_set(ec, x, y, w, h, POL_FULLSCREEN_LAYER);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_app_single(E_Client *ec, E_Illume_Config_Zone *cz)
|
|
{
|
|
if (!_policy_layout_app_check(ec)) return;
|
|
|
|
ZONE_GEOMETRY;
|
|
|
|
_policy_keyboard_restrict(ec, &h);
|
|
_policy_indicator_restrict(cz, &y, &h);
|
|
_policy_softkey_restrict(cz, &y, &h);
|
|
|
|
_border_geometry_set(ec, x, y, w, h, POL_APP_LAYER);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_app_dual_top(E_Client *ec, E_Illume_Config_Zone *cz)
|
|
{
|
|
E_Client *ec2;
|
|
|
|
if (!_policy_layout_app_check(ec)) return;
|
|
|
|
ZONE_GEOMETRY;
|
|
|
|
_policy_keyboard_restrict(ec, &h);
|
|
_policy_indicator_restrict(cz, &y, &h);
|
|
_policy_softkey_restrict(cz, &y, &h);
|
|
|
|
ec2 = e_illume_client_at_xy_get(ec->zone, x, y);
|
|
if ((ec2) && (ec2 != ec))
|
|
{
|
|
if ((ec->focused) && (ec->vkbd.state > ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF))
|
|
_border_geometry_set(ec2, x, h/2 + y, w, h/2, POL_APP_LAYER);
|
|
else
|
|
y += h/2;
|
|
}
|
|
|
|
_border_geometry_set(ec, x, y, w, h/2, POL_APP_LAYER);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_app_dual_custom(E_Client *ec, E_Illume_Config_Zone *cz)
|
|
{
|
|
E_Client *app;
|
|
int iy, ny, nh;
|
|
|
|
if (!_policy_layout_app_check(ec)) return;
|
|
|
|
ZONE_GEOMETRY;
|
|
|
|
e_illume_client_indicator_pos_get(ec->zone, NULL, &iy);
|
|
|
|
ny = ec->zone->y;
|
|
nh = iy;
|
|
|
|
app = e_illume_client_at_xy_get(ec->zone, ec->zone->x, ec->zone->y);
|
|
if ((app) && (ec != app))
|
|
{
|
|
ny = (iy + cz->indicator.size);
|
|
nh = ((ec->zone->y + ec->zone->h) - ny - cz->softkey.size);
|
|
}
|
|
|
|
_border_geometry_set(ec, x, ny, w, nh, POL_APP_LAYER);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_app_dual_left(E_Client *ec, E_Illume_Config_Zone *cz, Eina_Bool force)
|
|
{
|
|
E_Client *ec2;
|
|
int ky, kh, nx, nw;
|
|
|
|
if (!_policy_layout_app_check(ec)) return;
|
|
|
|
ZONE_GEOMETRY;
|
|
|
|
e_illume_keyboard_safe_app_region_get(ec->zone, NULL, &ky, NULL, &kh);
|
|
|
|
if (kh >= ec->zone->h)
|
|
kh = (kh - cz->indicator.size - cz->softkey.size);
|
|
else
|
|
kh = (kh - cz->indicator.size);
|
|
|
|
nx = x;
|
|
nw = w / 2;
|
|
|
|
if (!force)
|
|
{
|
|
/* see if there is a border already there. if so, place at right */
|
|
ec2 = e_illume_client_at_xy_get(ec->zone, nx, y);
|
|
if ((ec2) && (ec != ec2)) nx = x + nw;
|
|
}
|
|
|
|
_border_geometry_set(ec, nx, y, nw, kh, POL_APP_LAYER);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_dialog(E_Client *ec, E_Illume_Config_Zone *cz)
|
|
{
|
|
E_Client *parent;
|
|
int mw, mh, nx, ny;
|
|
|
|
/* if (!_policy_layout_app_check(ec)) return; */
|
|
if ((!ec) || (!cz)) return;
|
|
printf("place dialog %d - %dx%d\n", ec->placed, ec->w, ec->h);
|
|
|
|
if (ec->placed)
|
|
return;
|
|
|
|
ZONE_GEOMETRY;
|
|
|
|
mw = ec->w;
|
|
mh = ec->h;
|
|
|
|
if (e_illume_client_is_fixed_size(ec))
|
|
{
|
|
if (mw > w) mw = w;
|
|
if (mh > h) mh = h;
|
|
}
|
|
else
|
|
{
|
|
if (w * 2/3 > ec->w)
|
|
mw = w * 2/3;
|
|
|
|
if (h * 2/3 > ec->h)
|
|
mh = h * 2/3;
|
|
}
|
|
|
|
parent = e_illume_client_parent_get(ec);
|
|
|
|
if ((!parent) || (cz->mode.dual == 1))
|
|
{
|
|
nx = (x + ((w - mw) / 2));
|
|
ny = (y + ((h - mh) / 2));
|
|
}
|
|
else
|
|
{
|
|
if (mw > parent->w) mw = parent->w;
|
|
if (mh > parent->h) mh = parent->h;
|
|
|
|
nx = (parent->x + ((parent->w - mw) / 2));
|
|
ny = (parent->y + ((parent->h - mh) / 2));
|
|
}
|
|
|
|
ec->placed = 1;
|
|
|
|
_border_geometry_set(ec, nx, ny, mw, mh, POL_DIALOG_LAYER);
|
|
printf("set geom %d %d\n", mw, mh);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_splash(E_Client *ec, E_Illume_Config_Zone *cz)
|
|
{
|
|
_policy_zone_layout_dialog(ec, cz);
|
|
|
|
if (ec->layer != POL_SPLASH_LAYER) evas_object_layer_set(ec->frame, POL_SPLASH_LAYER);
|
|
}
|
|
|
|
static void
|
|
_policy_zone_layout_conformant_single(E_Client *ec, E_Illume_Config_Zone *cz __UNUSED__)
|
|
{
|
|
if (!_policy_layout_app_check(ec)) return;
|
|
|
|
_border_geometry_set(ec, ec->zone->x, ec->zone->y,
|
|
ec->zone->w, ec->zone->h,
|
|
POL_CONFORMANT_LAYER);
|
|
}
|
|
|
|
#if 0
|
|
typedef struct _App_Desk App_Desk;
|
|
|
|
struct _App_Desk
|
|
{
|
|
E_Desk *desk;
|
|
const char *class;
|
|
Eina_List *borders;
|
|
};
|
|
|
|
static Eina_List *desks = NULL;
|
|
|
|
#define EINA_LIST_FIND(_list, _item, _match) \
|
|
{ \
|
|
Eina_List *_l; \
|
|
EINA_LIST_FOREACH(_list, _l, _item) \
|
|
if (_match) break; \
|
|
}
|
|
#endif
|
|
|
|
|
|
/* policy functions */
|
|
void
|
|
_policy_border_add(E_Client *ec)
|
|
{
|
|
// printf("Border added: %s\n", ec->icccm.class);
|
|
|
|
if (!ec) return;
|
|
|
|
/* NB: this call sets an atom on the window that specifices the zone.
|
|
* the logic here is that any new windows created can access the zone
|
|
* window by a 'get' call. This is useful for elementary apps as they
|
|
* normally would not have access to the zone window. Typical use case
|
|
* is for indicator & softkey windows so that they can send messages
|
|
* that apply to their respective zone only. Example: softkey sends close
|
|
* messages (or back messages to cycle focus) that should pertain just
|
|
* to it's current zone */
|
|
ecore_x_e_illume_zone_set(e_client_util_win_get(ec), ec->zone->black_win);
|
|
|
|
if (e_illume_client_is_keyboard(ec))
|
|
{
|
|
ec->sticky = 1;
|
|
e_hints_window_sticky_set(ec, 1);
|
|
}
|
|
|
|
if (e_illume_client_is_home(ec))
|
|
{
|
|
ec->sticky = 1;
|
|
e_hints_window_sticky_set(ec, 1);
|
|
}
|
|
|
|
if (e_illume_client_is_indicator(ec))
|
|
{
|
|
ec->sticky = 1;
|
|
e_hints_window_sticky_set(ec, 1);
|
|
}
|
|
|
|
if (e_illume_client_is_softkey(ec))
|
|
{
|
|
ec->sticky = 1;
|
|
e_hints_window_sticky_set(ec, 1);
|
|
}
|
|
|
|
/* ignore stolen borders. These are typically quickpanel or keyboards */
|
|
if (ec->stolen) return;
|
|
|
|
/* if this is a fullscreen window, than we need to hide indicator window */
|
|
/* NB: we could use the e_illume_client_is_fullscreen function here
|
|
* but we save ourselves a function call this way */
|
|
if ((ec->fullscreen) || (ec->need_fullscreen))
|
|
{
|
|
E_Client *ind, *sft;
|
|
|
|
if ((ind = e_illume_client_indicator_get(ec->zone)))
|
|
{
|
|
if (ind->visible) e_illume_client_hide(ind);
|
|
}
|
|
if ((sft = e_illume_client_softkey_get(ec->zone)))
|
|
{
|
|
if (e_illume_client_is_conformant(ec))
|
|
{
|
|
if (sft->visible)
|
|
e_illume_client_hide(sft);
|
|
else if (!sft->visible)
|
|
e_illume_client_show(sft);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#if 0
|
|
if (ec->icccm.class)
|
|
{
|
|
Eina_List *l;
|
|
App_Desk *d;
|
|
|
|
EINA_LIST_FIND(desks, d, (d->class == ec->icccm.class));
|
|
|
|
if (!d)
|
|
{
|
|
d = E_NEW(App_Desk, 1);
|
|
d->desk
|
|
}
|
|
|
|
d->borders = eina_list_append(d->borders, ec);
|
|
e_client_desk_set(ec, d->desk);
|
|
}
|
|
#endif
|
|
|
|
/* Add this border to our focus stack if it can accept or take focus */
|
|
if ((ec->icccm.accepts_focus) || (ec->icccm.take_focus))
|
|
_pol_focus_stack = eina_list_append(_pol_focus_stack, ec);
|
|
|
|
if ((e_illume_client_is_softkey(ec)) || (e_illume_client_is_indicator(ec)))
|
|
_policy_zone_layout_update(ec->zone);
|
|
else
|
|
{
|
|
/* set focus on new border if we can */
|
|
_policy_border_set_focus(ec);
|
|
}
|
|
}
|
|
|
|
void
|
|
_policy_border_del(E_Client *ec)
|
|
{
|
|
// printf("Policy Border deleted: %s\n", ec->icccm.class);
|
|
|
|
if (!ec) return;
|
|
|
|
/* if this is a fullscreen window, than we need to show indicator window */
|
|
/* NB: we could use the e_illume_client_is_fullscreen function here
|
|
* but we save ourselves a function call this way */
|
|
if ((ec->fullscreen) || (ec->need_fullscreen))
|
|
{
|
|
E_Client *ind;
|
|
|
|
/* try to get the Indicator on this zone */
|
|
if ((ind = e_illume_client_indicator_get(ec->zone)))
|
|
{
|
|
if (!ind->visible) e_illume_client_show(ind);
|
|
}
|
|
_policy_zone_layout_update(ec->zone);
|
|
}
|
|
|
|
/* remove from focus stack */
|
|
if ((ec->icccm.accepts_focus) || (ec->icccm.take_focus))
|
|
_pol_focus_stack = eina_list_remove(_pol_focus_stack, ec);
|
|
|
|
if (e_illume_client_is_softkey(ec))
|
|
{
|
|
E_Illume_Config_Zone *cz;
|
|
|
|
cz = e_illume_zone_config_get(ec->zone->num);
|
|
cz->softkey.size = 0;
|
|
_policy_zone_layout_update(ec->zone);
|
|
}
|
|
else if (e_illume_client_is_indicator(ec))
|
|
{
|
|
E_Illume_Config_Zone *cz;
|
|
|
|
cz = e_illume_zone_config_get(ec->zone->num);
|
|
cz->indicator.size = 0;
|
|
_policy_zone_layout_update(ec->zone);
|
|
}
|
|
/* else
|
|
* {
|
|
* _policy_border_show_below(ec);
|
|
* } */
|
|
}
|
|
|
|
void
|
|
_policy_border_focus_in(E_Client *ec __UNUSED__)
|
|
{
|
|
E_Client *ind;
|
|
|
|
// printf("Border focus in: %s\n", ec->icccm.name);
|
|
if ((ec->fullscreen) || (ec->need_fullscreen))
|
|
{
|
|
/* try to get the Indicator on this zone */
|
|
if ((ind = e_illume_client_indicator_get(ec->zone)))
|
|
{
|
|
/* we have the indicator, show it if needed */
|
|
if (ind->visible) e_illume_client_hide(ind);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* try to get the Indicator on this zone */
|
|
if ((ind = e_illume_client_indicator_get(ec->zone)))
|
|
{
|
|
/* we have the indicator, show it if needed */
|
|
if (!ind->visible) e_illume_client_show(ind);
|
|
}
|
|
}
|
|
_policy_zone_layout_update(ec->zone);
|
|
}
|
|
|
|
void
|
|
_policy_border_focus_out(E_Client *ec)
|
|
{
|
|
// printf("Border focus out: %s\n", ec->icccm.name);
|
|
|
|
if (!ec) return;
|
|
|
|
/* NB: if we got this focus_out event on a deleted border, we check if
|
|
* it is a transient (child) of another window. If it is, then we
|
|
* transfer focus back to the parent window */
|
|
if (e_object_is_del(E_OBJECT(ec)))
|
|
{
|
|
if (e_illume_client_is_dialog(ec))
|
|
{
|
|
E_Client *parent;
|
|
|
|
if ((parent = e_illume_client_parent_get(ec)))
|
|
_policy_border_set_focus(parent);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
_policy_border_activate(E_Client *ec)
|
|
{
|
|
E_Client *sft;
|
|
|
|
// printf("Border Activate: %s\n", ec->icccm.name);
|
|
|
|
if (!ec) return;
|
|
|
|
/* NB: stolen borders may or may not need focus call...have to test */
|
|
if (ec->stolen) return;
|
|
|
|
/* conformant windows hide the softkey */
|
|
if ((sft = e_illume_client_softkey_get(ec->zone)))
|
|
{
|
|
if (e_illume_client_is_conformant(ec))
|
|
{
|
|
if (sft->visible) e_illume_client_hide(sft);
|
|
}
|
|
else
|
|
{
|
|
if (!sft->visible) e_illume_client_show(sft);
|
|
}
|
|
}
|
|
|
|
/* NB: We cannot use our set_focus function here because it does,
|
|
* occasionally fall through wrt E's focus policy, so cherry pick the good
|
|
* parts and use here :) */
|
|
if (ec->desk != e_desk_current_get(ec->zone))
|
|
e_desk_show(ec->desk);
|
|
|
|
/* if the border is iconified then uniconify if allowed */
|
|
if ((ec->iconic) && (!ec->lock_user_iconify))
|
|
e_client_uniconify(ec);
|
|
|
|
/* set very high layer for this window as it needs attention and thus
|
|
* should show above everything */
|
|
evas_object_layer_set(ec->frame, POL_ACTIVATE_LAYER);
|
|
|
|
/* if we can raise the border do it */
|
|
if (!ec->lock_user_stacking) evas_object_raise(ec->frame);
|
|
|
|
/* focus the border */
|
|
evas_object_focus_set(ec->frame, 1);
|
|
|
|
/* NB: since we skip needless border evals when container layout
|
|
* is called (to save cpu cycles), we need to
|
|
* signal this border that it's focused so that the edj gets
|
|
* updated.
|
|
*
|
|
* This is potentially useless as THIS policy
|
|
* makes all windows borderless anyway, but it's in here for
|
|
* completeness
|
|
e_client_focus_latest_set(ec);
|
|
if (ec->bg_object)
|
|
edje_object_signal_emit(ec->bg_object, "e,state,focused", "e");
|
|
if (ec->icon_object)
|
|
edje_object_signal_emit(ec->icon_object, "e,state,focused", "e");
|
|
e_focus_event_focus_in(ec);
|
|
*/
|
|
}
|
|
static Eina_Bool
|
|
_policy_border_is_dialog(E_Client *ec)
|
|
{
|
|
if (e_illume_client_is_dialog(ec))
|
|
return EINA_TRUE;
|
|
|
|
if (ec->e.state.centered)
|
|
return EINA_TRUE;
|
|
|
|
if (ec->internal)
|
|
{
|
|
if (ec->icccm.class)
|
|
{
|
|
if (!strncmp(ec->icccm.class, "Illume", 6))
|
|
return EINA_FALSE;
|
|
if (!strncmp(ec->icccm.class, "e_fwin", 6))
|
|
return EINA_FALSE;
|
|
if (!strncmp(ec->icccm.class, "every", 5))
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
void
|
|
_policy_border_post_fetch(E_Client *ec)
|
|
{
|
|
if (!ec) return;
|
|
|
|
/* NB: for this policy we disable all remembers set on a border */
|
|
if (ec->remember) e_remember_del(ec->remember);
|
|
ec->remember = NULL;
|
|
|
|
if (_policy_border_is_dialog(ec))
|
|
{
|
|
return;
|
|
}
|
|
else if (e_illume_client_is_fixed_size(ec))
|
|
{
|
|
return;
|
|
}
|
|
else if (!ec->borderless)
|
|
{
|
|
ec->borderless = 1;
|
|
ec->border.changed = 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
_policy_border_post_assign(E_Client *ec)
|
|
{
|
|
if (!ec) return;
|
|
|
|
ec->internal_no_remember = 1;
|
|
|
|
if (_policy_border_is_dialog(ec) ||
|
|
e_illume_client_is_fixed_size(ec))
|
|
return;
|
|
|
|
/* 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;
|
|
|
|
/* disable e's placement (and honoring of icccm.request_pos) */
|
|
ec->placed = 1;
|
|
}
|
|
|
|
void
|
|
_policy_border_show(E_Client *ec)
|
|
{
|
|
if (!ec) return;
|
|
|
|
/* printf("_policy_border_show %s\n", e_client_util_name_get(ec)); */
|
|
|
|
if (!ec->icccm.name) return;
|
|
|
|
// printf("Border Show: %s\n", ec->icccm.class);
|
|
|
|
/* trap for special windows so we can ignore hides below them */
|
|
if (e_illume_client_is_indicator(ec)) return;
|
|
if (e_illume_client_is_softkey(ec)) return;
|
|
if (e_illume_client_is_quickpanel(ec)) return;
|
|
if (e_illume_client_is_keyboard(ec)) return;
|
|
|
|
_policy_border_hide_below(ec);
|
|
}
|
|
|
|
/* called on E_CLIENT_HOOK_CONTAINER_LAYOUT (after e_border/eval0) */
|
|
void
|
|
_policy_zone_layout(E_Zone *zone)
|
|
{
|
|
E_Illume_Config_Zone *cz;
|
|
Eina_List *l;
|
|
E_Client *ec;
|
|
|
|
if (!zone) return;
|
|
|
|
cz = e_illume_zone_config_get(zone->num);
|
|
|
|
EINA_LIST_FOREACH(zone->comp->clients, l, ec)
|
|
{
|
|
if (e_client_util_ignored_get(ec)) continue;
|
|
if (e_object_is_del(E_OBJECT(ec))) continue;
|
|
|
|
if (ec->zone != zone) continue;
|
|
|
|
if ((!ec->new_client) && (!ec->changes.pos) && (!ec->changes.size) &&
|
|
(!ec->changes.visible) &&
|
|
(!ec->need_shape_export) && (!ec->need_shape_merge)) continue;
|
|
|
|
if (e_illume_client_is_indicator(ec))
|
|
_policy_zone_layout_indicator(ec, cz);
|
|
|
|
else if (e_illume_client_is_quickpanel(ec))
|
|
_policy_zone_layout_quickpanel(ec);
|
|
|
|
else if (e_illume_client_is_softkey(ec))
|
|
_policy_zone_layout_softkey(ec, cz);
|
|
|
|
else if (e_illume_client_is_keyboard(ec))
|
|
_policy_zone_layout_keyboard(ec, cz);
|
|
|
|
else if (e_illume_client_is_home(ec))
|
|
_policy_zone_layout_home_single(ec, cz);
|
|
|
|
else if ((ec->fullscreen) || (ec->need_fullscreen))
|
|
_policy_zone_layout_fullscreen(ec);
|
|
|
|
else if (e_illume_client_is_splash(ec))
|
|
_policy_zone_layout_splash(ec, cz);
|
|
|
|
else if (_policy_border_is_dialog(ec))
|
|
_policy_zone_layout_dialog(ec, cz);
|
|
|
|
else if (e_illume_client_is_conformant(ec))
|
|
_policy_zone_layout_conformant_single(ec, cz);
|
|
|
|
else if (e_illume_client_is_fixed_size(ec))
|
|
_policy_zone_layout_dialog(ec, cz);
|
|
|
|
else if (ec->internal && ec->icccm.class &&
|
|
(!strcmp(ec->icccm.class, "everything-window")))
|
|
{
|
|
if (ec->vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON)
|
|
_policy_zone_layout_app_single(ec, cz);
|
|
/* else
|
|
* _policy_zone_layout_app_dual_left(ec, cz, EINA_TRUE); */
|
|
if (ec->layer != POL_ACTIVATE_LAYER)
|
|
evas_object_layer_set(ec->frame, POL_ACTIVATE_LAYER);
|
|
|
|
/* if (ec->layer != POL_SPLASH_LAYER)
|
|
* evas_object_layer_set(ec->frame, POL_SPLASH_LAYER); */
|
|
}
|
|
else if (ec->e.state.centered)
|
|
_policy_zone_layout_dialog(ec, cz);
|
|
else if (!cz->mode.dual)
|
|
_policy_zone_layout_app_single(ec, cz);
|
|
else
|
|
{
|
|
if (cz->mode.side == 0)
|
|
{
|
|
int ty;
|
|
|
|
/* grab the indicator position so we can tell if it
|
|
* is in a custom position or not (user dragged it) */
|
|
e_illume_client_indicator_pos_get(ec->zone, NULL, &ty);
|
|
if (ty <= ec->zone->y)
|
|
_policy_zone_layout_app_dual_top(ec, cz);
|
|
else
|
|
_policy_zone_layout_app_dual_custom(ec, cz);
|
|
}
|
|
else
|
|
_policy_zone_layout_app_dual_left(ec, cz, EINA_FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
_policy_zone_move_resize(E_Zone *zone)
|
|
{
|
|
Eina_List *l;
|
|
E_Client *ec;
|
|
|
|
if (!zone) return;
|
|
|
|
EINA_LIST_FOREACH(zone->comp->clients, l, ec)
|
|
{
|
|
if (e_client_util_ignored_get(ec)) continue;
|
|
if (ec->zone != zone) continue;
|
|
|
|
ec->changes.pos = 1;
|
|
EC_CHANGED(ec);
|
|
}
|
|
}
|
|
|
|
void
|
|
_policy_zone_mode_change(E_Zone *zone, Ecore_X_Atom mode)
|
|
{
|
|
E_Illume_Config_Zone *cz;
|
|
/* Eina_List *homes = NULL; */
|
|
E_Client *ec;
|
|
/* int count; */
|
|
|
|
if (!zone) return;
|
|
|
|
cz = e_illume_zone_config_get(zone->num);
|
|
|
|
if (mode == ECORE_X_ATOM_E_ILLUME_MODE_SINGLE)
|
|
cz->mode.dual = 0;
|
|
else
|
|
{
|
|
cz->mode.dual = 1;
|
|
if (mode == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP)
|
|
cz->mode.side = 0;
|
|
else if (mode == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT)
|
|
cz->mode.side = 1;
|
|
}
|
|
e_config_save_queue();
|
|
|
|
/* lock indicator window from dragging if we need to */
|
|
ec = e_illume_client_indicator_get(zone);
|
|
if (ec)
|
|
{
|
|
/* only dual-top mode can drag */
|
|
if ((cz->mode.dual == 1) && (cz->mode.side == 0))
|
|
{
|
|
/* only set locked if we need to */
|
|
if (ec->illume.drag.locked != 0)
|
|
ecore_x_e_illume_drag_locked_set(e_client_util_win_get(ec), 0);
|
|
}
|
|
else
|
|
{
|
|
/* only set locked if we need to */
|
|
if (ec->illume.drag.locked != 1)
|
|
ecore_x_e_illume_drag_locked_set(e_client_util_win_get(ec), 1);
|
|
}
|
|
}
|
|
#if 0 /* split home window? wtf?! go home! */
|
|
if (!(homes = e_illume_client_home_borders_get(zone))) return;
|
|
|
|
count = eina_list_count(homes);
|
|
|
|
/* create a new home window (if needed) for dual mode */
|
|
if (cz->mode.dual == 1)
|
|
{
|
|
if (count < 2)
|
|
ecore_x_e_illume_home_new_send(zone->black_win);
|
|
}
|
|
else if (cz->mode.dual == 0)
|
|
{
|
|
/* if we went to single mode, delete any extra home windows */
|
|
if (count >= 2)
|
|
{
|
|
E_Client *home;
|
|
|
|
/* try to get a home window on this zone and remove it */
|
|
if ((home = e_illume_client_home_get(zone)))
|
|
ecore_x_e_illume_home_del_send(e_client_util_win_get(home));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
_policy_zone_layout_update(zone);
|
|
}
|
|
|
|
void
|
|
_policy_zone_close(E_Zone *zone)
|
|
{
|
|
E_Client *ec;
|
|
|
|
if (!zone) return;
|
|
|
|
if (!(ec = e_client_focused_get())) return;
|
|
|
|
if (ec->zone != zone) return;
|
|
|
|
/* close this border */
|
|
e_client_act_close_begin(ec);
|
|
}
|
|
|
|
void
|
|
_policy_drag_start(E_Client *ec)
|
|
{
|
|
if (!ec) return;
|
|
|
|
if (ec->stolen) return;
|
|
|
|
ecore_x_e_illume_drag_set(e_client_util_win_get(ec), 1);
|
|
ecore_x_e_illume_drag_set(ec->zone->black_win, 1);
|
|
}
|
|
|
|
void
|
|
_policy_drag_end(E_Client *ec)
|
|
{
|
|
// printf("Drag end\n");
|
|
|
|
if (!ec) return;
|
|
|
|
if (ec->stolen) return;
|
|
|
|
/* set property on this border to say we are done dragging */
|
|
ecore_x_e_illume_drag_set(e_client_util_win_get(ec), 0);
|
|
|
|
/* set property on zone window that a drag is finished */
|
|
ecore_x_e_illume_drag_set(ec->zone->black_win, 0);
|
|
}
|
|
|
|
void
|
|
_policy_focus_back(E_Zone *zone)
|
|
{
|
|
Eina_List *l, *fl = NULL;
|
|
E_Client *ec, *fbd;
|
|
|
|
if (!zone) return;
|
|
if (eina_list_count(_pol_focus_stack) < 1) return;
|
|
|
|
// printf("Focus back\n");
|
|
|
|
EINA_LIST_REVERSE_FOREACH(_pol_focus_stack, l, ec)
|
|
{
|
|
if (ec->zone != zone) continue;
|
|
fl = eina_list_append(fl, ec);
|
|
}
|
|
|
|
if (!(fbd = e_client_focused_get())) return;
|
|
if (fbd->parent) return;
|
|
|
|
EINA_LIST_REVERSE_FOREACH(fl, l, ec)
|
|
{
|
|
if ((fbd) && (ec == fbd))
|
|
{
|
|
E_Client *b;
|
|
|
|
if ((l->next) && (b = l->next->data))
|
|
{
|
|
_policy_border_set_focus(b);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* we've reached the end of the list. Set focus to first */
|
|
if ((b = eina_list_nth(fl, 0)))
|
|
{
|
|
_policy_border_set_focus(b);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
eina_list_free(fl);
|
|
}
|
|
|
|
void
|
|
_policy_focus_forward(E_Zone *zone)
|
|
{
|
|
Eina_List *l, *fl = NULL;
|
|
E_Client *ec, *fbd;
|
|
|
|
if (!zone) return;
|
|
if (eina_list_count(_pol_focus_stack) < 1) return;
|
|
|
|
// printf("Focus forward\n");
|
|
|
|
EINA_LIST_FOREACH(_pol_focus_stack, l, ec)
|
|
{
|
|
if (ec->zone != zone) continue;
|
|
fl = eina_list_append(fl, ec);
|
|
}
|
|
|
|
if (!(fbd = e_client_focused_get())) return;
|
|
if (fbd->parent) return;
|
|
|
|
EINA_LIST_FOREACH(fl, l, ec)
|
|
{
|
|
if ((fbd) && (ec == fbd))
|
|
{
|
|
E_Client *b;
|
|
|
|
if ((l->next) && (b = l->next->data))
|
|
{
|
|
_policy_border_set_focus(b);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* we've reached the end of the list. Set focus to first */
|
|
if ((b = eina_list_nth(fl, 0)))
|
|
{
|
|
_policy_border_set_focus(b);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
eina_list_free(fl);
|
|
}
|
|
|
|
void
|
|
_policy_focus_home(E_Zone *zone)
|
|
{
|
|
E_Client *ec;
|
|
|
|
if (!zone) return;
|
|
if (!(ec = e_illume_client_home_get(zone))) return;
|
|
_policy_border_set_focus(ec);
|
|
}
|
|
|
|
void
|
|
_policy_property_change(Ecore_X_Event_Window_Property *event)
|
|
{
|
|
if (event->atom == ECORE_X_ATOM_NET_WM_STATE)
|
|
{
|
|
E_Client *ec, *ind;
|
|
|
|
if (!(ec = e_pixmap_find_client(E_PIXMAP_TYPE_X, event->win))) return;
|
|
|
|
/* not interested in stolen or invisible borders */
|
|
if ((ec->stolen) || (!ec->visible)) return;
|
|
|
|
/* make sure the border has a name or class */
|
|
/* NB: this check is here because some E borders get State Changes
|
|
* but do not have a name/class associated with them. Not entirely sure
|
|
* which ones they are, but I would guess Managers, Containers, or Zones.
|
|
* At any rate, we're not interested in those types of borders */
|
|
if ((!ec->icccm.name) || (!ec->icccm.class)) return;
|
|
|
|
/* NB: If we have reached this point, then it should be a fullscreen
|
|
* border that has toggled fullscreen on/off */
|
|
|
|
/* try to get the Indicator on this zone */
|
|
if (!(ind = e_illume_client_indicator_get(ec->zone))) return;
|
|
|
|
/* if we are fullscreen, hide the indicator...else we show it */
|
|
/* NB: we could use the e_illume_client_is_fullscreen function here
|
|
* but we save ourselves a function call this way */
|
|
if ((ec->fullscreen) || (ec->need_fullscreen))
|
|
{
|
|
if (ind->visible)
|
|
{
|
|
e_illume_client_hide(ind);
|
|
_policy_zone_layout_update(ec->zone);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!ind->visible)
|
|
{
|
|
e_illume_client_show(ind);
|
|
_policy_zone_layout_update(ec->zone);
|
|
}
|
|
}
|
|
}
|
|
else if (event->atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY)
|
|
{
|
|
Eina_List *l;
|
|
E_Zone *zone;
|
|
E_Client *ec;
|
|
int x, y, w, h;
|
|
|
|
if (!(zone = e_util_zone_window_find(event->win))) return;
|
|
|
|
if (!(ec = e_illume_client_indicator_get(zone))) return;
|
|
x = ec->x;
|
|
y = ec->y;
|
|
w = ec->w;
|
|
h = ec->h;
|
|
|
|
EINA_LIST_FOREACH(zone->comp->clients, l, ec)
|
|
{
|
|
if (e_client_util_ignored_get(ec)) continue;
|
|
if (ec->zone != zone) continue;
|
|
if (!e_illume_client_is_conformant(ec)) continue;
|
|
/* set indicator geometry on conformant window */
|
|
/* NB: This is needed so that conformant apps get told about
|
|
* the indicator size/position...else they have no way of
|
|
* knowing that the geometry has been updated */
|
|
ecore_x_e_illume_indicator_geometry_set(e_client_util_win_get(ec), x, y, w, h);
|
|
}
|
|
}
|
|
else if (event->atom == ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY)
|
|
{
|
|
Eina_List *l;
|
|
E_Zone *zone;
|
|
E_Client *ec;
|
|
int x, y, w, h;
|
|
|
|
if (!(zone = e_util_zone_window_find(event->win))) return;
|
|
|
|
if (!(ec = e_illume_client_softkey_get(zone))) return;
|
|
x = ec->x;
|
|
y = ec->y;
|
|
w = ec->w;
|
|
h = ec->h;
|
|
|
|
EINA_LIST_FOREACH(zone->comp->clients, l, ec)
|
|
{
|
|
if (e_client_util_ignored_get(ec)) continue;
|
|
if (ec->zone != zone) continue;
|
|
if (!e_illume_client_is_conformant(ec)) continue;
|
|
/* set softkey geometry on conformant window */
|
|
/* NB: This is needed so that conformant apps get told about
|
|
* the softkey size/position...else they have no way of
|
|
* knowing that the geometry has been updated */
|
|
ecore_x_e_illume_softkey_geometry_set(e_client_util_win_get(ec), x, y, w, h);
|
|
}
|
|
}
|
|
else if (event->atom == ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY)
|
|
{
|
|
Eina_List *l;
|
|
E_Zone *zone;
|
|
E_Illume_Keyboard *kbd;
|
|
E_Client *ec;
|
|
int x, y, w, h;
|
|
|
|
if (!(zone = e_util_zone_window_find(event->win))) return;
|
|
|
|
if (!(kbd = e_illume_keyboard_get())) return;
|
|
if (!kbd->client) return;
|
|
|
|
x = kbd->client->x;
|
|
w = kbd->client->w;
|
|
h = kbd->client->h;
|
|
|
|
/* adjust Y for keyboard visibility because keyboard uses fx_offset */
|
|
y = 0;
|
|
#warning this is totally broken on so many levels
|
|
//if (kbd->client->frame &&
|
|
//(!e_util_strcmp(edje_object_part_state_get(kbd->client->cw->effect_obj, "mover", NULL), "custom")))
|
|
//y = kbd->client->y;
|
|
|
|
/* look for conformant borders */
|
|
EINA_LIST_FOREACH(zone->comp->clients, l, ec)
|
|
{
|
|
if (e_client_util_ignored_get(ec)) continue;
|
|
if (ec->zone != zone) continue;
|
|
if (!e_illume_client_is_conformant(ec)) continue;
|
|
/* set keyboard geometry on conformant window */
|
|
/* NB: This is needed so that conformant apps get told about
|
|
* the keyboard size/position...else they have no way of
|
|
* knowing that the geometry has been updated */
|
|
ecore_x_e_illume_keyboard_geometry_set(e_client_util_win_get(ec), x, y, w, h);
|
|
}
|
|
}
|
|
else if (event->atom == ATM_ENLIGHTENMENT_SCALE)
|
|
{
|
|
const Eina_List *l;
|
|
E_Comp *comp;
|
|
|
|
|
|
EINA_LIST_FOREACH(e_comp_list(), l, comp)
|
|
{
|
|
Eina_List *zl;
|
|
E_Zone *zone;
|
|
|
|
if (event->win != comp->man->root) continue;
|
|
|
|
EINA_LIST_FOREACH(comp->zones, zl, zone)
|
|
_policy_zone_layout_update(zone);
|
|
}
|
|
}
|
|
}
|