From: Doyoun Kang Date: Fri, 28 Apr 2023 10:30:05 +0000 (+0900) Subject: e_zone: add E_Zone_Obstacle feature X-Git-Tag: accepted/tizen/7.0/unified/20230505.170237~11 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F10%2F292210%2F1;p=platform%2Fupstream%2Fenlightenment.git e_zone: add E_Zone_Obstacle feature Change-Id: I8366c9bff5d9dc3b83b52e8831aa235a485a0858 --- diff --git a/src/bin/e_zone.c b/src/bin/e_zone.c index 4ca4828b94..139e55a2d9 100644 --- a/src/bin/e_zone.c +++ b/src/bin/e_zone.c @@ -1129,6 +1129,172 @@ e_zone_fade_handle(E_Zone *zone, int out, double tim) 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. */ @@ -1148,6 +1314,24 @@ e_zone_useful_geometry_get(E_Zone *zone, 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. * @@ -1281,6 +1465,8 @@ static void _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); @@ -1326,6 +1512,10 @@ _e_zone_free(E_Zone *zone) 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); diff --git a/src/bin/e_zone.h b/src/bin/e_zone.h index d6d73433d6..8472ec5862 100644 --- a/src/bin/e_zone.h +++ b/src/bin/e_zone.h @@ -20,6 +20,7 @@ typedef enum _E_Zone_Display_State } 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; @@ -151,6 +152,15 @@ struct _E_Zone 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 @@ -229,8 +239,14 @@ E_API void e_zone_edges_desk_flip_capable(E_Zone *zone, Eina_Bool l, Eina_B 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);