diff --git a/src/bin/e_comp_x.c b/src/bin/e_comp_x.c index 431e98145..bb98932d3 100644 --- a/src/bin/e_comp_x.c +++ b/src/bin/e_comp_x.c @@ -4560,35 +4560,114 @@ _e_comp_x_pre_swap(void *data, Evas *e EINA_UNUSED) c->grabbed = 0; } +static int +_e_comp_x_cinerama_screen_sort_cb(const void *data1, const void *data2) +{ + const E_Randr2_Screen *s1 = data1, *s2 = data2; + int dif; + + dif = -(s1->config.priority - s2->config.priority); + if (dif == 0) + { + dif = s1->config.geom.x - s2->config.geom.x; + if (dif == 0) + dif = s1->config.geom.y - s2->config.geom.y; + } + return dif; +} + static Eina_Bool _e_comp_x_xinerama_setup(int rw, int rh) { int i; E_Screen *screen; + Eina_List *screens = NULL, *screens_rem; Eina_List *all_screens = NULL; - Eina_List *l; - E_Randr2_Screen *s; + Eina_List *l, *ll; + E_Randr2_Screen *s, *s2, *s_chosen; + Eina_Bool removed; - i = 0; + // put screens in tmp list EINA_LIST_FOREACH(e_randr2->screens, l, s) { if ((s->config.enabled) && (s->config.geom.w > 0) && (s->config.geom.h > 0)) { - screen = E_NEW(E_Screen, 1); - screen->escreen = screen->screen = i; - screen->x = s->config.geom.x; - screen->y = s->config.geom.y; - screen->w = s->config.geom.w; - screen->h = s->config.geom.h; - all_screens = eina_list_append(all_screens, screen); - printf("xinerama screen %i %i %ix%i\n", screen->x, screen->y, screen->w, screen->h); - INF("E INIT: XINERAMA SCREEN: [%i][%i], %ix%i+%i+%i", - i, i, screen->w, screen->h, screen->x, screen->y); - i++; + screens = eina_list_append(screens, s); } } + // remove overlapping screens - if a set of screens overlap, keep the + // smallest/lowest res + do + { + removed = EINA_FALSE; + + EINA_LIST_FOREACH(screens, l, s) + { + screens_rem = NULL; + + EINA_LIST_FOREACH(l->next, ll, s2) + { + if (E_INTERSECTS(s->config.geom.x, s->config.geom.y, + s->config.geom.w, s->config.geom.h, + s2->config.geom.x, s2->config.geom.y, + s2->config.geom.w, s2->config.geom.h)) + { + if (!screens_rem) + screens_rem = eina_list_append(screens_rem, s); + screens_rem = eina_list_append(screens_rem, s2); + } + } + // we have intersecting screens - choose the lowest res one + if (screens_rem) + { + removed = EINA_TRUE; + // find the smallest screen (chosen one) + s_chosen = NULL; + EINA_LIST_FOREACH(screens_rem, ll, s2) + { + if (!s_chosen) s_chosen = s2; + else + { + if ((s_chosen->config.geom.w * + s_chosen->config.geom.h) > + (s2->config.geom.w * + s2->config.geom.h)) + s_chosen = s2; + } + } + // remove all from screens but the chosen one + EINA_LIST_FREE(screens_rem, s2) + { + if (s2 != s_chosen) + screens = eina_list_remove_list(screens, l); + } + // break our list walk and try again + break; + } + } + } + while (removed); + // sort screens by priority etc. + screens = eina_list_sort(screens, eina_list_count(screens), + _e_comp_x_cinerama_screen_sort_cb); + i = 0; + EINA_LIST_FOREACH(screens, l, s) + { + screen = E_NEW(E_Screen, 1); + screen->escreen = screen->screen = i; + screen->x = s->config.geom.x; + screen->y = s->config.geom.y; + screen->w = s->config.geom.w; + screen->h = s->config.geom.h; + all_screens = eina_list_append(all_screens, screen); + printf("xinerama screen %i %i %ix%i\n", screen->x, screen->y, screen->w, screen->h); + INF("E INIT: XINERAMA SCREEN: [%i][%i], %ix%i+%i+%i", + i, i, screen->w, screen->h, screen->x, screen->y); + i++; + } + eina_list_free(screens); // if we have NO screens at all (above - i will be 0) AND we have no // existing screens set up in xinerama - then just say root window size // is the entire screen. this should handle the case where you unplug ALL diff --git a/src/bin/e_randr2.c b/src/bin/e_randr2.c index bc8b21216..808d42472 100644 --- a/src/bin/e_randr2.c +++ b/src/bin/e_randr2.c @@ -423,6 +423,7 @@ _config_apply(E_Randr2 *r, E_Config_Randr2 *cfg) s->config.mode.preferred = EINA_FALSE; s->config.rotation = cs->rotation; s->config.priority = cs->priority; + printf("RRR: ... priority = %i\n", cs->priority); free(s->config.relative.to); if (cs->rel_to) s->config.relative.to = strdup(cs->rel_to); else s->config.relative.to = NULL; @@ -659,6 +660,49 @@ _screen_config_takeover(void) } } +static E_Config_Randr2_Screen *_config_screen_string_find(E_Config_Randr2 *cfg, const char *id); +static E_Randr2_Screen *_screen_fuzzy_fallback_find(E_Config_Randr2 *cfg, const char *id); + +static E_Config_Randr2_Screen * +_config_screen_string_find(E_Config_Randr2 *cfg, const char *id) +{ + Eina_List *l; + E_Config_Randr2_Screen *cs; + + if ((!id) || (!cfg)) return NULL; + EINA_LIST_FOREACH(cfg->screens, l, cs) + { + if (!cs->id) continue; + if (!strcmp(cs->id, id)) return cs; + } + return NULL; +} + +static E_Randr2_Screen * +_screen_fuzzy_fallback_find(E_Config_Randr2 *cfg, const char *id) +{ + E_Randr2_Screen *s = NULL; + char *p, *name; + + // strip out everythng in the string from / on as that is edid + // and fall back to finding just the output name in the rel + // to identifier, rather than the specific screen id + name = alloca(strlen(id) + 1); + strcpy(name, id); + if ((p = strchr(name, '/'))) *p = 0; + + s = _screen_id_find(id); + if (!s) s = _screen_id_find(name); + if (!s) + { + E_Config_Randr2_Screen *cs; + + cs = _config_screen_string_find(cfg, id); + if ((cs) && (cs->id)) return _screen_fuzzy_fallback_find(cfg, cs->id); + } + return s; +} + static int _config_do_recurse = 0; static void @@ -680,18 +724,7 @@ _screen_config_do(E_Randr2_Screen *s) { // if this screen is relative TO something (clone or left/right etc. // then calculate what it is relative to first - s2 = _screen_id_find(s->config.relative.to); - printf("RRR: '%s' is relative to %p\n", s->info.name, s2); - if (!s2) - { - // strip out everythng in the string from / on as that is edid - // and fall back to finding just the output name in the rel - // to identifier, rather than the specific screen id - char *p, *str = alloca(strlen(s->config.relative.to) + 1); - strcpy(str, s->config.relative.to); - if ((p = strchr(str, '/'))) *p = 0; - s2 = _screen_output_find(str); - } + s2 = _screen_fuzzy_fallback_find(e_randr2_cfg, s->config.relative.to); printf("RRR: '%s' is relative to %p\n", s->info.name, s2); if (s2) _screen_config_do(s2); } @@ -1137,9 +1170,11 @@ _info_get(void) { Ecore_X_Randr_Mode *modes; Ecore_X_Randr_Edid_Display_Interface_Type conn; - int modes_num = 0, modes_pref = 0; + int modes_num = 0, modes_pref = 0, priority; + E_Config_Randr2_Screen *cs; E_Randr2_Screen *s = calloc(1, sizeof(E_Randr2_Screen)); if (!s) continue; + s->info.name = _output_name_get(root, outputs[i]); printf("RRR: ...... out %s\n", s->info.name); if (!s->info.name) @@ -1215,8 +1250,14 @@ _info_get(void) } free(modes); } - if (ecore_x_randr_primary_output_get(root) == outputs[i]) - s->config.priority = 100; + cs = NULL; + priority = 0; + if (e_randr2_cfg) cs = _config_screen_find(s, e_randr2_cfg); + if (cs) + priority = cs->priority; + else if (ecore_x_randr_primary_output_get(root) == outputs[i]) + priority = 100; + s->config.priority = priority; for (j = 0; j < crtcs_num; j++) { Eina_Bool ok, possible; diff --git a/src/bin/e_xinerama.c b/src/bin/e_xinerama.c index e75704f84..10ee4ad71 100644 --- a/src/bin/e_xinerama.c +++ b/src/bin/e_xinerama.c @@ -132,8 +132,6 @@ _e_xinerama_update(void) INF("======================= screens:"); EINA_LIST_FOREACH(chosen_screens, l, scr) { - scr->screen = n; - scr->escreen = n; INF("E INIT: XINERAMA CHOSEN: [%i][%i], %ix%i+%i+%i", scr->screen, scr->escreen, scr->w, scr->h, scr->x, scr->y); n++; diff --git a/src/bin/e_zone.c b/src/bin/e_zone.c index 8da9ad17f..65aa1a341 100644 --- a/src/bin/e_zone.c +++ b/src/bin/e_zone.c @@ -270,17 +270,40 @@ e_zone_name_set(E_Zone *zone, zone->name = eina_stringshare_add(name); } +static void +e_zone_reconfigure_clients(E_Zone *zone, int dx, int dy, int dw, int dh) +{ + E_Client *ec; + + E_CLIENT_FOREACH(zone->comp, ec) + { + if (ec->zone != zone) continue; + + if ((dx != 0) || (dy != 0)) + evas_object_move(ec->frame, ec->x + dx, ec->y + dy); + // we shrank the zone - adjust windows more + if ((dw < 0) || (dh < 0)) + { + e_client_res_change_geometry_save(ec); + e_client_res_change_geometry_restore(ec); + } + } +} + EAPI void e_zone_move(E_Zone *zone, int x, int y) { E_Event_Zone_Move_Resize *ev; + int dx, dy; E_OBJECT_CHECK(zone); E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE); if ((x == zone->x) && (y == zone->y)) return; + dx = x - zone->x; + dy = y - zone->y; zone->x = x; zone->y = y; evas_object_move(zone->bg_object, x, y); @@ -294,6 +317,7 @@ e_zone_move(E_Zone *zone, _e_zone_edge_move_resize(zone); e_zone_bg_reconfigure(zone); + e_zone_reconfigure_clients(zone, dx, dy, 0, 0); } EAPI void @@ -302,11 +326,15 @@ e_zone_resize(E_Zone *zone, int h) { E_Event_Zone_Move_Resize *ev; + int dw, dh; E_OBJECT_CHECK(zone); E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE); if ((w == zone->w) && (h == zone->h)) return; + + dw = w - zone->w; + dh = h - zone->h; zone->w = w; zone->h = h; evas_object_resize(zone->bg_object, w, h); @@ -321,6 +349,7 @@ e_zone_resize(E_Zone *zone, _e_zone_edge_move_resize(zone); e_zone_bg_reconfigure(zone); + e_zone_reconfigure_clients(zone, 0, 0, dw, dh); } EAPI Eina_Bool @@ -331,6 +360,7 @@ e_zone_move_resize(E_Zone *zone, int h) { E_Event_Zone_Move_Resize *ev; + int dx, dy, dw, dh; E_OBJECT_CHECK_RETURN(zone, EINA_FALSE); E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, EINA_FALSE); @@ -338,6 +368,10 @@ e_zone_move_resize(E_Zone *zone, if ((x == zone->x) && (y == zone->y) && (w == zone->w) && (h == zone->h)) return EINA_FALSE; + dx = x - zone->x; + dy = y - zone->y; + dw = w - zone->w; + dh = h - zone->h; zone->x = x; zone->y = y; zone->w = w; @@ -357,8 +391,8 @@ e_zone_move_resize(E_Zone *zone, _e_zone_event_generic_free, NULL); _e_zone_edge_move_resize(zone); - e_zone_bg_reconfigure(zone); + e_zone_reconfigure_clients(zone, dx, dy, dw, dh); return EINA_TRUE; }