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
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;
}
}
+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
{
// 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);
}
{
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)
}
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;
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++;
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);
_e_zone_edge_move_resize(zone);
e_zone_bg_reconfigure(zone);
+ e_zone_reconfigure_clients(zone, dx, dy, 0, 0);
}
EAPI void
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);
_e_zone_edge_move_resize(zone);
e_zone_bg_reconfigure(zone);
+ e_zone_reconfigure_clients(zone, 0, 0, dw, dh);
}
EAPI Eina_Bool
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);
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;
_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;
}