EINA_SAFETY_ON_NULL_RETURN(zone);
}
+EINTERN Eina_Bool
+e_zone_obstacle_add(E_Zone *zone, E_Client *ec, Eina_Rectangle *geom, Eina_Bool vertical)
+{
+ E_Zone_Obstacle *obs;
+ Eina_List *l;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(geom, EINA_FALSE);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(zone == ec->zone, EINA_FALSE);
+
+ // check in the list...
+ EINA_LIST_FOREACH(zone->obstacles, l, obs)
+ {
+ if (obs->ec == ec)
+ {
+ ELOGF("E_ZONE", "Already ADDED in the obstacle list", ec);
+ return EINA_TRUE;
+ }
+ }
+
+ obs = E_NEW(E_Zone_Obstacle, 1);
+ if (!obs) return EINA_FALSE;
+ obs->ec = ec;
+ obs->x = geom->x;
+ obs->y = geom->y;
+ obs->w = geom->w;
+ obs->h = geom->h;
+ obs->vertical = !!vertical;
+
+ ELOGF("E_ZONE", "ADD obstacle... geo(%d,%d,%dx%d), vertical:%d", ec, obs->x, obs->y, obs->w, obs->h, obs->vertical);
+
+ zone->obstacles = eina_list_append(zone->obstacles, obs);
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_zone_obstacle_update(E_Zone *zone, E_Client *ec, Eina_Rectangle *geom, Eina_Bool vertical)
+{
+ E_Zone_Obstacle *obs;
+ Eina_List *l;
+ Eina_Bool changed = EINA_FALSE;
+
+ if (!zone) return EINA_FALSE;
+ if (!ec) return EINA_FALSE;
+ if (zone != ec->zone) return EINA_FALSE;
+
+ EINA_LIST_FOREACH(zone->obstacles, l, obs)
+ {
+ if (obs->ec == ec)
+ break;
+ }
+
+ if (!obs)
+ {
+ ELOGF("E_ZONE", "Not found in the obstacle list", ec);
+ return EINA_FALSE;
+ }
+
+ if (geom)
+ {
+ if ((obs->x != geom->x) ||
+ (obs->y != geom->y) ||
+ (obs->w != geom->w) ||
+ (obs->h != geom->h))
+ {
+ obs->x = geom->x;
+ obs->y = geom->y;
+ obs->w = geom->w;
+ obs->h = geom->h;
+ changed = EINA_TRUE;
+ }
+ }
+
+ if (obs->vertical != vertical)
+ {
+ obs->vertical = !!vertical;
+ changed = EINA_TRUE;
+ }
+
+ ELOGF("E_ZONE", "UPDATE obstacle... geo(%d,%d,%dx%d), vertical:%d", ec, obs->x, obs->y, obs->w, obs->h, obs->vertical);
+
+ if (changed)
+ {
+ // TODO: Generate event
+ }
+
+ return EINA_TRUE;
+}
+
+EINTERN void
+e_zone_obstacle_remove(E_Zone *zone, E_Client *ec)
+{
+ E_Zone_Obstacle *obs;
+ Eina_List *l, *ll;
+
+ if (!zone) return;
+ if (!ec) return;
+ if (zone != ec->zone) return;
+
+ EINA_LIST_FOREACH_SAFE(zone->obstacles, l, ll, obs)
+ {
+ if (obs->ec == ec)
+ {
+ ELOGF("E_ZONE", "REMOVE obstacle...", ec);
+ zone->obstacles = eina_list_remove_list(zone->obstacles, l);
+ E_FREE(obs);
+ break;
+ }
+ }
+}
+
+static void
+_e_zone_useful_geometry_calc(const E_Zone *zone, E_Desk *desk, int *x, int *y, int *w, int *h)
+{
+ Eina_Tiler *tiler;
+ E_Zone_Obstacle *obs;
+ Eina_List *l;
+ int zx, zy, zw, zh;
+ Eina_Iterator *it;
+ Eina_Rectangle geom = { 0 } , *rect;
+ int size = 0;
+
+ zx = zone->x;
+ zy = zone->y;
+ zw = zone->w;
+ zh = zone->h;
+
+ if (desk)
+ {
+ zx = desk->geom.x;
+ zy = desk->geom.y;
+ zw = desk->geom.w;
+ zh = desk->geom.h;
+ }
+
+ tiler = eina_tiler_new(zw, zh);
+ eina_tiler_tile_size_set(tiler, 1, 1);
+ eina_tiler_rect_add(tiler, &(Eina_Rectangle){0, 0, zw, zh});
+
+ EINA_LIST_FOREACH(zone->obstacles, l, obs)
+ {
+ if (!E_INTERSECTS(obs->x, obs->y, obs->w, obs->h, zx, zy, zw, zh)) continue;
+
+ if (obs->vertical)
+ eina_tiler_rect_del(tiler, &(Eina_Rectangle){obs->x - zx, 0, obs->w, zh});
+ else
+ eina_tiler_rect_del(tiler, &(Eina_Rectangle){0, obs->y - zy, zw, obs->h});
+ }
+
+ it = eina_tiler_iterator_new(tiler);
+ EINA_ITERATOR_FOREACH(it, rect)
+ {
+ if (rect->w * rect->h < size) continue;
+ size = rect->w * rect->h;
+ geom = *rect;
+ }
+ eina_iterator_free(it);
+ eina_tiler_free(tiler);
+
+ if (x) *x = geom.x + zx;
+ if (y) *y = geom.y + zy;
+ if (w) *w = geom.w;
+ if (h) *h = geom.h;
+}
+
/**
* Get (or calculate) the useful (or free, without any shelves) area.
*/
if (h) *h = zone->h;
}
+EINTERN void
+e_zone_desk_useful_geometry_get(E_Zone *zone, E_Desk *desk, int *x, int *y, int *w, int *h)
+{
+ E_OBJECT_CHECK(zone);
+ E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
+ E_OBJECT_CHECK(desk);
+ E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
+ E_OBJECT_CHECK(desk->zone);
+
+ if (desk->zone != zone)
+ {
+ ELOGF("E_ZONE", "CRI... Zone(%d) and Desk's zone(%d) mismatch!", NULL, zone->id, desk->zone->id);
+ return;
+ }
+
+ _e_zone_useful_geometry_calc(zone, desk, x, y, w, h);
+}
+
/**
* Mark as dirty so e_zone_useful_geometry_get() will need to recalculate.
*
_e_zone_free(E_Zone *zone)
{
int x, y;
+ E_Zone_Obstacle *obs;
+
//printf("@@@@@@@@@@ e_zone_free: %i %i | %i %i %ix%i = %p\n", zone->num, zone->id, zone->x, zone->y, zone->w, zone->h, zone);
/* Delete the edge windows if they exist */
E_FREE_FUNC(zone->edge.top, evas_object_del);
for (y = 0; y < zone->desk_y_count; y++)
e_object_del(E_OBJECT(zone->desks[x + (y * zone->desk_x_count)]));
}
+ EINA_LIST_FREE(zone->obstacles, obs)
+ {
+ E_FREE(obs);
+ }
free(zone->desks);
free(zone->output_id);
free(zone);
} E_Zone_Display_State;
typedef struct _E_Zone E_Zone;
+typedef struct _E_Zone_Obstacle E_Zone_Obstacle;
typedef struct _E_Event_Zone_Generic E_Event_Zone_Desk_Count_Set;
typedef struct _E_Event_Zone_Generic E_Event_Zone_Move_Resize;
E_Zone_Display_State display_state;
char *output_id; // same id we get from e_comp_screen so look it up there
+
+ Eina_List *obstacles;
+};
+
+struct _E_Zone_Obstacle
+{
+ E_Client *ec;
+ int x, y, w, h; // obstacle area, this can not be same to ec's geometry
+ Eina_Bool vertical;
};
struct _E_Event_Zone_Generic
E_API Eina_Bool e_zone_exists_direction(E_Zone *zone, E_Zone_Edge edge);
E_API void e_zone_edge_win_layer_set(E_Zone *zone, E_Layer layer);
+EINTERN Eina_Bool e_zone_obstacle_add(E_Zone *zone, E_Client *ec, Eina_Rectangle *geom, Eina_Bool vertical);
+EINTERN Eina_Bool e_zone_obstacle_update(E_Zone *zone, E_Client *ec, Eina_Rectangle *geom, Eina_Bool vertical);
+EINTERN void e_zone_obstacle_remove(E_Zone *zone, E_Client *ec);
+
E_API void e_zone_useful_geometry_dirty(E_Zone *zone);
E_API void e_zone_useful_geometry_get(E_Zone *zone, int *x, int *y, int *w, int *h);
+EINTERN void e_zone_desk_useful_geometry_get(E_Zone *zone, E_Desk *desk, int *x, int *y, int *w, int *h);
+
E_API void e_zone_stow(E_Zone *zone);
E_API void e_zone_unstow(E_Zone *zone);