diff --git a/src/bin/e_desk.c b/src/bin/e_desk.c index 8fe0b82f6..01bfcd09e 100644 --- a/src/bin/e_desk.c +++ b/src/bin/e_desk.c @@ -677,6 +677,11 @@ e_desks_count(void) static void _e_desk_free(E_Desk *desk) { + while (desk->obstacles) + { + E_Object *obs = (void*)EINA_INLIST_CONTAINER_GET(desk->obstacles, E_Zone_Obstacle); + e_object_del(obs); + } eina_stringshare_del(desk->name); desk->name = NULL; free(desk); diff --git a/src/bin/e_desk.h b/src/bin/e_desk.h index 4ccd6f6d5..389b1beea 100644 --- a/src/bin/e_desk.h +++ b/src/bin/e_desk.h @@ -37,6 +37,7 @@ struct _E_Desk Evas_Object *bg_object; unsigned int animate_count; + Eina_Inlist *obstacles; }; struct _E_Event_Desk_Show diff --git a/src/bin/e_int_shelf_config.c b/src/bin/e_int_shelf_config.c index 1771369a0..d22b1a594 100644 --- a/src/bin/e_int_shelf_config.c +++ b/src/bin/e_int_shelf_config.c @@ -403,7 +403,7 @@ _basic_apply(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) else if ((!cfdata->escfg->autohide) && (cfdata->es->hidden)) e_shelf_toggle(cfdata->es, 1); - e_zone_useful_geometry_dirty(cfdata->es->zone); + e_shelf_obstacles_update(cfdata->es); e_config_save_queue(); cfdata->es->config_dialog = cfd; return 1; diff --git a/src/bin/e_shelf.c b/src/bin/e_shelf.c index b955b18e9..4957cd34a 100644 --- a/src/bin/e_shelf.c +++ b/src/bin/e_shelf.c @@ -82,9 +82,7 @@ static const char *orient_names[] = E_API int E_EVENT_SHELF_RENAME = -1; E_API int E_EVENT_SHELF_ADD = -1; E_API int E_EVENT_SHELF_DEL = -1; -static Ecore_Event_Handler *_e_shelf_gadcon_populate_handler = NULL; -static Ecore_Event_Handler *_e_shelf_module_init_end_handler = NULL; -static Ecore_Event_Handler *_e_shelf_zone_moveresize_handler = NULL; +static Eina_List *handlers; static void _e_shelf_remaximize(E_Shelf *es) @@ -104,6 +102,18 @@ _e_shelf_remaximize(E_Shelf *es) } } +static Eina_Bool +_e_shelf_desk_count_handler(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Zone_Desk_Count_Set *ev) +{ + Eina_List *l; + E_Shelf *es; + + EINA_LIST_FOREACH(shelves, l, es) + if (ev->zone == es->zone) + e_shelf_obstacles_update(es); + return ECORE_CALLBACK_RENEW; +} + /* externally accessible functions */ EINTERN int e_shelf_init(void) @@ -111,7 +121,8 @@ e_shelf_init(void) E_EVENT_SHELF_RENAME = ecore_event_type_new(); E_EVENT_SHELF_ADD = ecore_event_type_new(); E_EVENT_SHELF_DEL = ecore_event_type_new(); - _e_shelf_gadcon_populate_handler = ecore_event_handler_add(E_EVENT_GADCON_POPULATE, _e_shelf_gadcon_populate_handler_cb, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_GADCON_POPULATE, _e_shelf_gadcon_populate_handler_cb, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DESK_COUNT_SET, _e_shelf_desk_count_handler, NULL); return 1; } @@ -126,12 +137,7 @@ e_shelf_shutdown(void) es = eina_list_data_get(shelves); e_object_del(E_OBJECT(es)); } - if (_e_shelf_gadcon_populate_handler) - _e_shelf_gadcon_populate_handler = ecore_event_handler_del(_e_shelf_gadcon_populate_handler); - if (_e_shelf_module_init_end_handler) - _e_shelf_module_init_end_handler = ecore_event_handler_del(_e_shelf_module_init_end_handler); - if (_e_shelf_zone_moveresize_handler) - _e_shelf_zone_moveresize_handler = ecore_event_handler_del(_e_shelf_zone_moveresize_handler); + E_FREE_LIST(handlers, ecore_event_handler_del); return 1; } @@ -234,8 +240,6 @@ e_shelf_zone_new(E_Zone *zone, const char *name, const char *style, E_Layer laye es->h = 32; es->zone = zone; e_object_del_attach_func_set(E_OBJECT(es), _e_shelf_del_cb); - e_zone_useful_geometry_dirty(zone); - es->ee = e_comp->ee; es->evas = e_comp->evas; @@ -962,6 +966,31 @@ e_shelf_autohide_set(E_Shelf *es, int autohide_type) */ } +E_API void +e_shelf_obstacles_update(E_Shelf *es) +{ + E_FREE_LIST(es->zone_obstacles, e_object_del); + if (es->cfg->overlap || es->cfg->autohide) return; + if (es->cfg->desk_show_mode) + { + Eina_List *l; + E_Config_Shelf_Desk *sd; + + EINA_LIST_FOREACH(es->cfg->desk_list, l, sd) + { + E_Desk *desk; + + desk = e_desk_at_xy_get(es->zone, sd->x, sd->y); + if (!desk) continue; + es->zone_obstacles = eina_list_append(es->zone_obstacles, + e_zone_obstacle_add(es->zone, desk, &(Eina_Rectangle){es->x, es->y, es->w, es->h})); + } + } + else + es->zone_obstacles = eina_list_append(es->zone_obstacles, + e_zone_obstacle_add(es->zone, NULL, &(Eina_Rectangle){es->x, es->y, es->w, es->h})); +} + E_API E_Shelf * e_shelf_config_new(E_Zone *zone, E_Config_Shelf *cf_es) { @@ -992,6 +1021,7 @@ e_shelf_config_new(E_Zone *zone, E_Config_Shelf *cf_es) e_shelf_show(es); e_shelf_toggle(es, 0); + e_shelf_obstacles_update(es); return es; } @@ -1108,9 +1138,8 @@ _e_shelf_free(E_Shelf *es) if (!es->dummy) _e_shelf_bindings_del(es); - if (!stopping) - e_zone_useful_geometry_dirty(es->zone); E_FREE_LIST(es->handlers, ecore_event_handler_del); + E_FREE_LIST(es->zone_obstacles, e_object_del); E_FREE_FUNC(es->autohide, ecore_event_handler_del); E_FREE_FUNC(es->hide_animator, ecore_animator_del); diff --git a/src/bin/e_shelf.h b/src/bin/e_shelf.h index e0ac3593b..9a7d9a850 100644 --- a/src/bin/e_shelf.h +++ b/src/bin/e_shelf.h @@ -40,6 +40,7 @@ struct _E_Shelf Ecore_Timer *module_init_end_timer; Eina_List *handlers; Ecore_Event_Handler *autohide; + Eina_List *zone_obstacles; unsigned char fit_along : 1; unsigned char fit_size : 1; unsigned char hidden : 1; @@ -94,5 +95,6 @@ E_API void e_shelf_name_set(E_Shelf *es, const char *name); E_API void e_shelf_rename_dialog(E_Shelf *es); E_API void e_shelf_autohide_set(E_Shelf *es, int autohide_type); E_API Eina_Bool e_shelf_desk_visible(const E_Shelf *es, const E_Desk *desk); +E_API void e_shelf_obstacles_update(E_Shelf *es); #endif #endif diff --git a/src/bin/e_zone.c b/src/bin/e_zone.c index 4f19d638c..baf5c92ef 100644 --- a/src/bin/e_zone.c +++ b/src/bin/e_zone.c @@ -18,6 +18,7 @@ static void _e_zone_event_generic_free(void *data, void *ev); static void _e_zone_object_del_attach(void *o); static E_Zone_Edge _e_zone_detect_edge(E_Zone *zone, Evas_Object *obj); static void _e_zone_edge_move_resize(E_Zone *zone); +static void _e_zone_obstacle_free(E_Zone_Obstacle *obs); E_API int E_EVENT_ZONE_DESK_COUNT_SET = 0; E_API int E_EVENT_POINTER_WARP = 0; @@ -1220,98 +1221,49 @@ e_zone_fade_handle(E_Zone *zone, int out, double tim) static void _e_zone_useful_geometry_calc(const E_Zone *zone, int dx, int dy, int *x, int *y, int *w, int *h) { - const E_Shelf *shelf; - Eina_List *shelves; - int x0, x1, yy0, yy1; + E_Desk *desk; + E_Zone_Obstacle *obs; + Eina_Tiler *tiler; + int zx, zy, zw, zh; + Eina_Iterator *it; + Eina_Rectangle geom, *rect; + int size = 0; - x0 = 0; - yy0 = 0; - x1 = zone->w; - yy1 = zone->h; - shelves = e_shelf_list_all(); - EINA_LIST_FREE(shelves, shelf) + zx = zone->x; + zy = zone->y; + zw = zone->w; + zh = zone->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_INLIST_FOREACH(zone->obstacles, obs) { - E_Config_Shelf_Desk *sd; - E_Gadcon_Orient orient; - Eina_List *ll; - int skip_shelf = 0; - - if (shelf->zone != zone) - continue; - - if (shelf->cfg) + if (!E_INTERSECTS(obs->x, obs->y, obs->w, obs->h, zx, zy, zw, zh)) continue; + eina_tiler_rect_del(tiler, &(Eina_Rectangle){obs->x - zx, obs->y - zy, obs->w, obs->h}); + } + desk = e_desk_at_xy_get(zone, dx, dy); + if (desk) + { + EINA_INLIST_FOREACH(zone->obstacles, obs) { - if (shelf->cfg->overlap) - continue; - - if (shelf->cfg->autohide) - continue; - orient = shelf->cfg->orient; - - if (shelf->cfg->desk_show_mode) - { - skip_shelf = 1; - EINA_LIST_FOREACH(shelf->cfg->desk_list, ll, sd) - { - if (!sd) continue; - if ((sd->x == dx) && (sd->y == dy)) - { - skip_shelf = 0; - break; - } - } - if (skip_shelf) - continue; - } - } - else - orient = shelf->gadcon->orient; - - switch (orient) - { - /* these are non-edje orientations */ - case E_GADCON_ORIENT_FLOAT: - case E_GADCON_ORIENT_HORIZ: - case E_GADCON_ORIENT_VERT: - break; - - case E_GADCON_ORIENT_TOP: - case E_GADCON_ORIENT_CORNER_TL: - case E_GADCON_ORIENT_CORNER_TR: - if (yy0 < shelf->h) - yy0 = shelf->h; - break; - - case E_GADCON_ORIENT_BOTTOM: - case E_GADCON_ORIENT_CORNER_BL: - case E_GADCON_ORIENT_CORNER_BR: - if (yy1 > zone->h - shelf->h) - yy1 = zone->h - shelf->h; - break; - - case E_GADCON_ORIENT_LEFT: - case E_GADCON_ORIENT_CORNER_LT: - case E_GADCON_ORIENT_CORNER_LB: - if (x0 < shelf->w) - x0 = shelf->w; - break; - - case E_GADCON_ORIENT_RIGHT: - case E_GADCON_ORIENT_CORNER_RT: - case E_GADCON_ORIENT_CORNER_RB: - if (x1 > zone->w - shelf->w) - x1 = zone->w - shelf->w; - break; - - default: - break; + if (!E_INTERSECTS(obs->x, obs->y, obs->w, obs->h, zx, zy, zw, zh)) continue; + eina_tiler_rect_del(tiler, &(Eina_Rectangle){obs->x - zx, obs->y - zy, obs->w, 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 = zone->x + x0; - if (y) *y = zone->y + yy0; - if (w) *w = x1 - x0; - if (h) *h = yy1 - yy0; + if (x) *x = geom.x; + if (y) *y = geom.y; + if (w) *w = geom.w; + if (h) *h = geom.h; } /** @@ -1324,39 +1276,20 @@ e_zone_useful_geometry_get(E_Zone *zone, int *w, int *h) { - E_Shelf *shelf; int zx, zy, zw, zh; - Eina_Bool calc = EINA_TRUE; E_OBJECT_CHECK(zone); E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE); - if (!zone->useful_geometry.dirty) - { - Eina_List *l = e_shelf_list_all(); - calc = EINA_FALSE; - EINA_LIST_FREE(l, shelf) - { - if (!shelf->cfg) continue; - if (shelf->cfg->desk_show_mode) - { - _e_zone_useful_geometry_calc(zone, zone->desk_x_current, zone->desk_y_current, &zx, &zy, &zw, &zh); - calc = EINA_TRUE; - break; - } - } - eina_list_free(l); - } - else - _e_zone_useful_geometry_calc(zone, zone->desk_x_current, zone->desk_y_current, &zx, &zy, &zw, &zh); - zone->useful_geometry.dirty = 0; - if (calc) + if (zone->useful_geometry.dirty) { + _e_zone_useful_geometry_calc(zone, zone->desk_x_current, zone->desk_y_current, &zx, &zy, &zw, &zh); zone->useful_geometry.x = zx; zone->useful_geometry.y = zy; zone->useful_geometry.w = zw; zone->useful_geometry.h = zh; } + zone->useful_geometry.dirty = 0; if (x) *x = zone->useful_geometry.x; if (y) *y = zone->useful_geometry.y; @@ -1400,6 +1333,68 @@ e_zone_useful_geometry_dirty(E_Zone *zone) zone->useful_geometry.h = -1; } +E_API E_Zone_Obstacle * +e_zone_obstacle_add(E_Zone *zone, E_Desk *desk, Eina_Rectangle *geom) +{ + E_Zone_Obstacle *obs; + + E_OBJECT_CHECK_RETURN(zone, NULL); + E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL); + if (desk) + { + E_OBJECT_CHECK_RETURN(desk, NULL); + E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, NULL); + if (desk->zone != zone) + { + ERR("zone != desk->zone"); + return NULL; + } + } + obs = E_OBJECT_ALLOC(E_Zone_Obstacle, E_ZONE_OBSTACLE_TYPE, _e_zone_obstacle_free); + obs->x = geom->x, obs->y = geom->y; + obs->w = geom->w, obs->h = geom->h; + obs->owner = E_OBJECT(desk) ?: E_OBJECT(zone); + if (desk) + { + desk->obstacles = eina_inlist_append(desk->obstacles, EINA_INLIST_GET(obs)); + if (desk->visible) + desk->zone->useful_geometry.dirty = 1; + } + else + { + zone->obstacles = eina_inlist_append(zone->obstacles, EINA_INLIST_GET(obs)); + zone->useful_geometry.dirty = 1; + } + return obs; +} + +E_API void +e_zone_obstacle_modify(E_Zone_Obstacle *obs, Eina_Rectangle *geom) +{ + E_Zone *zone; + E_Desk *desk; + + E_OBJECT_CHECK(obs); + E_OBJECT_TYPE_CHECK(obs, E_ZONE_OBSTACLE_TYPE); + EINA_SAFETY_ON_NULL_RETURN(geom); + if ((obs->x == geom->x) && (obs->y == geom->y) && (obs->w == geom->w) && (obs->h == geom->h)) + return; + obs->x = geom->x, obs->y = geom->y; + obs->w = geom->w, obs->h = geom->h; + + if (obs->owner->type == E_DESK_TYPE) + { + desk = (E_Desk*)obs->owner; + if (desk->visible) + desk->zone->useful_geometry.dirty = 1; + } + else + { + zone = (E_Zone*)obs->owner; + zone->useful_geometry.dirty = 1; + } +} + E_API void e_zone_stow(E_Zone *zone) { @@ -1492,6 +1487,11 @@ _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)])); } + while (zone->obstacles) + { + E_Object *obs = (void*)EINA_INLIST_CONTAINER_GET(zone->obstacles, E_Zone_Obstacle); + e_object_del(obs); + } free(zone->desks); free(zone->randr2_id); free(zone); @@ -1673,3 +1673,25 @@ _e_zone_edge_move_resize(E_Zone *zone) evas_object_geometry_set(zone->corner.bottom_left, zone->x + zone->w - cw - 2, zone->y + zone->h - 1, cw, 1); } + +static void +_e_zone_obstacle_free(E_Zone_Obstacle *obs) +{ + E_Zone *zone; + E_Desk *desk; + + if (obs->owner->type == E_DESK_TYPE) + { + desk = (E_Desk*)obs->owner; + desk->obstacles = eina_inlist_remove(desk->obstacles, EINA_INLIST_GET(obs)); + if (desk->visible) + desk->zone->useful_geometry.dirty = 1; + } + else + { + zone = (E_Zone*)obs->owner; + zone->obstacles = eina_inlist_remove(zone->obstacles, EINA_INLIST_GET(obs)); + zone->useful_geometry.dirty = 1; + } + free(obs); +} diff --git a/src/bin/e_zone.h b/src/bin/e_zone.h index 2314fdb37..bb7762eda 100644 --- a/src/bin/e_zone.h +++ b/src/bin/e_zone.h @@ -25,11 +25,14 @@ typedef struct _E_Event_Zone_Edge E_Event_Zone_Edge; typedef struct _E_Event_Zone_Generic E_Event_Zone_Stow; typedef struct _E_Event_Zone_Generic E_Event_Zone_Unstow; +typedef struct _E_Zone_Obstacle E_Zone_Obstacle; + #else #ifndef E_ZONE_H #define E_ZONE_H #define E_ZONE_TYPE (int)0xE0b0100d +#define E_ZONE_OBSTACLE_TYPE (int)0xE0b0110d struct _E_Zone { @@ -52,6 +55,7 @@ struct _E_Zone int desk_x_current, desk_y_current; int desk_x_prev, desk_y_prev; E_Desk **desks; + Eina_Inlist *obstacles; Eina_List *handlers; @@ -119,6 +123,14 @@ struct _E_Event_Zone_Edge Eina_Bool drag : 1; }; +struct _E_Zone_Obstacle +{ + E_Object e_obj_inherit; + EINA_INLIST; + int x, y, w, h; + E_Object *owner; +}; + EINTERN int e_zone_init(void); EINTERN int e_zone_shutdown(void); E_API E_Zone *e_zone_new(int num, int id, int x, int y, int w, int h); @@ -152,6 +164,9 @@ E_API void e_zone_unstow(E_Zone *zone); E_API void e_zone_fade_handle(E_Zone *zone, int out, double tim); +E_API E_Zone_Obstacle *e_zone_obstacle_add(E_Zone *zone, E_Desk *desk, Eina_Rectangle *geom); +E_API void e_zone_obstacle_modify(E_Zone_Obstacle *obs, Eina_Rectangle *geom); + extern E_API int E_EVENT_ZONE_DESK_COUNT_SET; extern E_API int E_EVENT_ZONE_MOVE_RESIZE; extern E_API int E_EVENT_ZONE_ADD;