e - randr - handle missing relative display and use priority for zone

this makes highest priority screen the lowest (0) zone. this also
handles missing screesn that you are relative "of". missing clones are
not working atm. also zone reconfigure moves windows now too
This commit is contained in:
Carsten Haitzler 2015-02-13 19:23:04 +09:00
parent 2fe0ac249d
commit 054adb6351
4 changed files with 184 additions and 32 deletions

View File

@ -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

View File

@ -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;

View File

@ -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++;

View File

@ -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;
}