move comp_x screen setup code into e_randr

this was not x-specific, so move it for use in wl compositors
This commit is contained in:
Mike Blumenkrantz 2015-04-22 19:24:33 -04:00
parent e64998b042
commit a452baafca
4 changed files with 141 additions and 143 deletions

View File

@ -2497,7 +2497,8 @@ e_comp_wl_init(void)
/* add event handlers to catch E events */
if (e_comp->comp_type != E_PIXMAP_TYPE_X)
e_randr2_init();
if (e_randr2_init())
e_randr2_screens_setup(-1, -1);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_RANDR_CHANGE,
_e_comp_wl_cb_randr_change, NULL);

View File

@ -4532,139 +4532,6 @@ _e_comp_x_cb_frame_extents_request(void *data EINA_UNUSED, int ev_type EINA_UNUS
return ECORE_CALLBACK_RENEW;
}
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, *ll;
E_Randr2_Screen *s, *s2, *s_chosen;
Eina_Bool removed;
e_comp_x_randr_screen_iface_set();
if (!e_randr2_init()) return 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))
{
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
// screens from an existing setup (unplug external monitors and/or close
// laptop lid), in which case as long as at least one screen is configured
// in xinerama, it will be left-as is until next time we re-eval screen
// setup and have at least one screen
printf("xinerama setup............... %i %p\n", i, e_xinerama_screens_all_get());
if ((i == 0) && (!e_xinerama_screens_all_get()))
{
screen = E_NEW(E_Screen, 1);
screen->escreen = screen->screen = 0;
screen->x = 0;
screen->y = 0;
screen->w = rw;
screen->h = rh;
all_screens = eina_list_append(all_screens, screen);
}
e_xinerama_screens_set(all_screens);
return EINA_TRUE;
}
static Eina_Bool
_e_comp_x_randr_change(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event_info EINA_UNUSED)
{
@ -4678,7 +4545,7 @@ _e_comp_x_randr_change(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev
E_Client *ec;
ecore_x_netwm_desk_size_set(e_comp->root, e_comp->w, e_comp->h);
_e_comp_x_xinerama_setup(e_comp->w, e_comp->h);
e_randr2_screens_setup(e_comp->w, e_comp->h);
e_comp_canvas_update();
E_CLIENT_FOREACH(ec)
@ -4696,7 +4563,7 @@ _e_comp_x_ee_resize(Ecore_Evas *ee EINA_UNUSED)
E_Client *ec;
ecore_x_netwm_desk_size_set(e_comp->root, e_comp->w, e_comp->h);
_e_comp_x_xinerama_setup(e_comp->w, e_comp->h);
e_randr2_screens_setup(e_comp->w, e_comp->h);
e_comp_canvas_update();
E_CLIENT_FOREACH(ec)
@ -5102,6 +4969,8 @@ _e_comp_x_screens_setup(void)
Ecore_X_Window *roots;
Eina_Bool success = EINA_FALSE;
e_comp_x_randr_screen_iface_set();
if (!e_randr2_init()) return 0;
roots = ecore_x_window_root_list(&n);
if ((!roots) || (n <= 0))
{
@ -5116,13 +4985,8 @@ _e_comp_x_screens_setup(void)
Ecore_X_Window root = roots[i];
ecore_x_window_size_get(root, &rw, &rh);
if (n == 1)
{
/* more than 1 root window - xinerama wont be active */
success = _e_comp_x_xinerama_setup(rw, rh);
if (!success) break;
}
if (!success) break;
e_randr2_screens_setup(rw, rh);
success = _e_comp_x_setup(root, rw, rh);
if (!success) break;
}

View File

@ -843,6 +843,22 @@ _screen_config_maxsize(void)
e_randr2->h = maxy;
}
static int
_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;
}
EAPI void
e_randr2_screen_refresh_queue(Eina_Bool lid_event)
{
@ -870,3 +886,119 @@ e_randr2_config_screen_find(E_Randr2_Screen *s, E_Config_Randr2 *cfg)
}
return NULL;
}
EAPI void
e_randr2_screens_setup(int rw, int rh)
{
int i;
E_Screen *screen;
Eina_List *screens = NULL, *screens_rem;
Eina_List *all_screens = NULL;
Eina_List *l, *ll;
E_Randr2_Screen *s, *s2, *s_chosen;
Eina_Bool removed;
if ((!e_randr2) || (!e_randr2->screens)) goto out;
// 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))
{
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, 0, _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
// screens from an existing setup (unplug external monitors and/or close
// laptop lid), in which case as long as at least one screen is configured
// in xinerama, it will be left-as is until next time we re-eval screen
// setup and have at least one screen
printf("xinerama setup............... %i %p\n", i, e_xinerama_screens_all_get());
if ((i == 0) && (!e_xinerama_screens_all_get()))
{
out:
screen = E_NEW(E_Screen, 1);
screen->escreen = screen->screen = 0;
screen->x = 0;
screen->y = 0;
if ((rw > 0) && (rh > 0))
screen->w = rw, screen->h = rh;
else
ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &screen->w, &screen->h);
all_screens = eina_list_append(all_screens, screen);
}
e_xinerama_screens_set(all_screens);
}

View File

@ -122,5 +122,6 @@ EAPI void e_randr2_screeninfo_update(void);
EAPI void e_randr2_screen_refresh_queue(Eina_Bool lid_event);
EAPI E_Config_Randr2_Screen *e_randr2_config_screen_find(E_Randr2_Screen *s, E_Config_Randr2 *cfg);
EAPI void e_randr2_screens_setup(int rw, int rh);
#endif
#endif