enlightenment/src/bin/e_resist.c

351 lines
11 KiB
C

#include "e.h"
typedef struct _E_Resist_Rect E_Resist_Rect;
struct _E_Resist_Rect
{
int x, y, w, h;
int v1;
int resist_out;
};
static void _e_resist_rects(Eina_List *rects, int px, int py, int pw, int ph, int x, int y, int w, int h, int *rx, int *ry, int *rw, int *rh);
E_API int
e_resist_client_position(Eina_List *skiplist,
int px, int py, int pw, int ph,
int x, int y, int w, int h,
int *rx, int *ry, int *rw, int *rh)
{
Eina_List *l, *rects = NULL;
E_Resist_Rect *r;
E_Client *ec;
E_Desk *desk;
E_Zone *zone;
if (!e_config->use_resist)
{
*rx = x;
*ry = y;
*rw = w;
*rh = h;
return 0;
}
/* edges of screen */
#define OBSTACLE(_x, _y, _w, _h, _resist) \
{ \
r = E_NEW(E_Resist_Rect, 1); \
r->x = _x; r->y = _y; r->w = _w; r->h = _h; r->v1 = _resist; \
r->resist_out = 0; \
rects = eina_list_append(rects, r); \
}
#define HOLDER(_x, _y, _w, _h, _resist) \
{ \
r = E_NEW(E_Resist_Rect, 1); \
r->x = _x; r->y = _y; r->w = _w; r->h = _h; r->v1 = _resist; \
r->resist_out = 1; \
rects = eina_list_append(rects, r); \
}
EINA_LIST_FOREACH(e_comp->zones, l, zone)
{
HOLDER(zone->x, zone->y, zone->w, zone->h, e_config->desk_resist);
}
/* FIXME: need to add resist or complete BLOCKS for things like ibar */
/* can add code here to add more fake obstacles with custom resist values */
/* here if need be - ie xinerama middle between screens and panels etc. */
E_CLIENT_FOREACH(ec)
{
if (e_client_util_ignored_get(ec) || (!evas_object_visible_get(ec->frame))) continue;
if (ec->offer_resistance && (!eina_list_data_find(skiplist, ec)))
{
OBSTACLE(ec->x, ec->y, ec->w, ec->h, e_config->window_resist);
}
}
desk = e_desk_current_get(e_zone_current_get());
{
E_Zone_Obstacle *obs;
EINA_INLIST_FOREACH(desk->obstacles, obs)
OBSTACLE(obs->x, obs->y, obs->w, obs->h, e_config->gadget_resist);
EINA_INLIST_FOREACH(desk->zone->obstacles, obs)
OBSTACLE(obs->x, obs->y, obs->w, obs->h, e_config->gadget_resist);
}
if (rects)
{
_e_resist_rects(rects,
px, py, pw, ph,
x, y, w, h,
rx, ry, rw, rh);
E_FREE_LIST(rects, E_FREE);
}
return 1;
}
E_API int
e_resist_gadman_position(Eina_List *skiplist EINA_UNUSED,
int px, int py, int pw, int ph,
int x, int y, int w, int h,
int *rx, int *ry)
{
Eina_List *l, *rects = NULL;
E_Resist_Rect *r;
E_Shelf *es;
if (!e_config->use_resist)
{
*rx = x;
*ry = y;
return 0;
}
l = e_shelf_list_all();
EINA_LIST_FREE(l, es)
{
if (e_shelf_desk_visible(es, e_desk_current_get(es->zone)))
{
OBSTACLE(es->x + es->zone->x, es->y + es->zone->y, es->w, es->h,
e_config->gadget_resist);
}
}
if (rects)
{
_e_resist_rects(rects,
px, py, pw, ph,
x, y, w, h,
rx, ry, NULL, NULL);
E_FREE_LIST(rects, E_FREE);
}
return 1;
}
static void
_e_resist_rects(Eina_List *rects,
int px, int py, int pw, int ph,
int x, int y, int w, int h,
int *rx, int *ry, int *rw, int *rh)
{
int dx, dy, dw, dh, d, pd;
int resist_x = 0, resist_y = 0;
int resist_w = 0, resist_h = 0;
Eina_List *l;
E_Resist_Rect *r;
dx = x - px;
dy = y - py;
dw = w - pw;
dh = h - ph;
EINA_LIST_FOREACH(rects, l, r)
{
if (E_SPANS_COMMON(r->y, r->h, y, h))
{
if (dx > 0)
{
/* moving right */
if (r->resist_out)
{
/* check right edge of windows against left */
d = x + w - (r->x + r->w);
pd = px + pw - (r->x + r->w);
if ((d > 0) && (pd <= 0) && (d <= r->v1))
{
if (-resist_x < d)
resist_x = -d;
}
}
else
{
/* check left edge of windows against right */
d = r->x - (x + w);
pd = r->x - (px + pw);
if ((d < 0) && (pd >= 0) && (d >= -r->v1))
{
if (resist_x > d)
resist_x = d;
}
}
}
else if (dx < 0)
{
/* moving left */
if (r->resist_out)
{
/* check left edge of windows against right */
d = r->x - x;
pd = r->x - px;
if ((d > 0) && (pd <= 0) && (d <= r->v1))
{
if (resist_x < d)
{
resist_x = d;
resist_w = -d;
}
}
}
else
{
/* check right edge of windows against left */
d = x - (r->x + r->w);
pd = px - (r->x + r->w);
if ((d < 0) && (pd >= 0) && (d >= -r->v1))
{
if (-resist_x > d)
{
resist_x = -d;
resist_w = d;
}
}
}
}
if ((dw > 0) && (dx == 0))
{
/* enlarging window by moving lower corner */
if (r->resist_out)
{
/* check right edge of windows against left */
d = x + w - (r->x + r->w);
pd = px + pw - (r->x + r->w);
if ((d > 0) && (pd <= 0) && (d <= r->v1))
{
if (-resist_w < d)
resist_w = -d;
}
}
else
{
/* check left edge of windows against right */
d = r->x - (x + w);
pd = r->x - (px + pw);
if ((d < 0) && (pd >= 0) && (d >= -r->v1))
{
if (resist_w > d)
resist_w = d;
}
}
}
}
if (E_SPANS_COMMON(r->x, r->w, x, w))
{
if (dy > 0)
{
/* moving down */
if (r->resist_out)
{
/* check bottom edge of windows against top */
d = y + h - (r->y + r->h);
pd = py + ph - (r->y + r->h);
if ((d > 0) && (pd <= 0) && (d <= r->v1))
{
if (-resist_y < d)
resist_y = -d;
}
}
else
{
/* check top edge of windows against bottom */
d = r->y - (y + h);
pd = r->y - (py + ph);
if ((d < 0) && (pd >= 0) && (d >= -r->v1))
{
if (resist_y > d)
resist_y = d;
}
}
}
else if (dy < 0)
{
/* moving up */
if (r->resist_out)
{
/* check top edge of windows against bottom */
d = r->y - y;
pd = r->y - py;
if ((d > 0) && (pd <= 0) && (d <= r->v1))
{
if (resist_y < d)
{
resist_y = d;
resist_h = -d;
}
}
}
else
{
/* moving up - check bottom edge of windows against top */
d = y - (r->y + r->h);
pd = py - (r->y + r->h);
if ((d < 0) && (pd >= 0) && (d >= -r->v1))
{
if (-resist_y > d)
{
resist_y = -d;
resist_h = d;
}
}
}
}
if ((dh > 0) && (dy == 0))
{
/* enlarging window by moving lower corner */
if (r->resist_out)
{
/* check bottom edge of windows against top */
d = y + h - (r->y + r->h);
pd = py + ph - (r->y + r->h);
if ((d > 0) && (pd <= 0) && (d <= r->v1))
{
if (-resist_h < d)
resist_h = -d;
}
}
else
{
/* check top edge of windows against bottom */
d = r->y - (y + h);
pd = r->y - (py + ph);
if ((d < 0) && (pd >= 0) && (d >= -r->v1))
{
if (resist_h > d)
resist_h = d;
}
}
}
}
}
if (rx)
{
if (dx != 0)
*rx = x + resist_x;
else
*rx = x;
}
if (ry)
{
if (dy != 0)
*ry = y + resist_y;
else
*ry = y;
}
if (rw)
{
if (dw != 0)
*rw = w + resist_w;
else
*rw = w;
}
if (rh)
{
if (dh != 0)
*rh = h + resist_h;
else
*rh = h;
}
}