forked from enlightenment/enlightenment
213 lines
5.1 KiB
C
213 lines
5.1 KiB
C
#include "e.h"
|
|
|
|
static void _e_xinerama_clean(void);
|
|
static void _e_xinerama_update(void);
|
|
static int _e_xinerama_cb_screen_sort(const void *data1, const void *data2);
|
|
|
|
static Eina_List *all_screens = NULL;
|
|
static Eina_List *chosen_screens = NULL;
|
|
static Eina_List *fake_screens = NULL;
|
|
|
|
static void
|
|
_screen_free(E_Screen *scr)
|
|
{
|
|
free(scr->id);
|
|
free(scr);
|
|
}
|
|
|
|
EINTERN int
|
|
e_xinerama_init(void)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
EINTERN int
|
|
e_xinerama_shutdown(void)
|
|
{
|
|
_e_xinerama_clean();
|
|
return 1;
|
|
}
|
|
|
|
E_API void
|
|
e_xinerama_update(void)
|
|
{
|
|
_e_xinerama_clean();
|
|
_e_xinerama_update();
|
|
}
|
|
|
|
E_API const Eina_List *
|
|
e_xinerama_screens_get(void)
|
|
{
|
|
if (fake_screens) return fake_screens;
|
|
return chosen_screens;
|
|
}
|
|
|
|
E_API const Eina_List *
|
|
e_xinerama_screens_all_get(void)
|
|
{
|
|
if (fake_screens) return fake_screens;
|
|
return all_screens;
|
|
}
|
|
|
|
E_API void
|
|
e_xinerama_screens_set(Eina_List *screens)
|
|
{
|
|
E_FREE_LIST(all_screens, _screen_free);
|
|
chosen_screens = eina_list_free(chosen_screens);
|
|
all_screens = screens;
|
|
_e_xinerama_update();
|
|
}
|
|
|
|
EINTERN void
|
|
e_xinerama_fake_screen_del(int num)
|
|
{
|
|
Eina_List *l;
|
|
E_Screen *scr, *lscr;
|
|
int n = 0, x = 0;
|
|
|
|
/* this assumes X number of identical horizontal screens */
|
|
EINA_SAFETY_ON_NULL_RETURN(fake_screens);
|
|
l = eina_list_nth_list(fake_screens, num);
|
|
EINA_SAFETY_ON_NULL_RETURN(l);
|
|
scr = eina_list_data_get(l);
|
|
free(scr);
|
|
fake_screens = eina_list_remove_list(fake_screens, l);
|
|
EINA_LIST_FOREACH(fake_screens, l, lscr)
|
|
{
|
|
lscr->screen = n++;
|
|
lscr->x = x;
|
|
lscr->w = e_comp->w / eina_list_count(fake_screens);
|
|
x = lscr->x + lscr->w;
|
|
}
|
|
e_comp_canvas_update();
|
|
ecore_event_add(E_EVENT_RANDR_CHANGE, NULL, NULL, NULL);
|
|
}
|
|
|
|
EINTERN void
|
|
e_xinerama_fake_screen_append(void)
|
|
{
|
|
Eina_List *l;
|
|
E_Screen *lscr;
|
|
int n, x = 0;
|
|
|
|
/* this assumes X number of identical horizontal screens */
|
|
n = eina_list_count(fake_screens) + 1;
|
|
EINA_LIST_FOREACH(fake_screens, l, lscr)
|
|
{
|
|
lscr->x = x;
|
|
lscr->w = e_comp->w / n;
|
|
x = lscr->x + lscr->w;
|
|
}
|
|
e_xinerama_fake_screen_add(e_comp->w - (e_comp->w / n), 0, e_comp->w / n, e_comp->h);
|
|
e_comp_canvas_update();
|
|
ecore_event_add(E_EVENT_RANDR_CHANGE, NULL, NULL, NULL);
|
|
}
|
|
|
|
E_API void
|
|
e_xinerama_fake_screen_add(int x, int y, int w, int h)
|
|
{
|
|
E_Screen *scr;
|
|
|
|
scr = E_NEW(E_Screen, 1);
|
|
scr->screen = eina_list_count(fake_screens);
|
|
scr->escreen = scr->screen;
|
|
scr->x = x;
|
|
scr->y = y;
|
|
scr->w = w;
|
|
scr->h = h;
|
|
fake_screens = eina_list_append(fake_screens, scr);
|
|
}
|
|
|
|
E_API Eina_Bool
|
|
e_xinerama_fake_screens_exist(void)
|
|
{
|
|
return !!fake_screens;
|
|
}
|
|
|
|
/* local subsystem functions */
|
|
static void
|
|
_e_xinerama_clean(void)
|
|
{
|
|
E_FREE_LIST(all_screens, _screen_free);
|
|
chosen_screens = eina_list_free(chosen_screens);
|
|
E_FREE_LIST(fake_screens, _screen_free);
|
|
}
|
|
|
|
static void
|
|
_e_xinerama_update(void)
|
|
{
|
|
Eina_List *l;
|
|
E_Screen *scr;
|
|
unsigned int n = 0;
|
|
|
|
/* now go through all_screens... and build a list of chosen screens */
|
|
EINA_LIST_FOREACH(all_screens, l, scr)
|
|
{
|
|
Eina_List *ll;
|
|
E_Screen *scr2;
|
|
int add = 1;
|
|
Eina_List *removes;
|
|
|
|
removes = NULL;
|
|
/* does this screen intersect with any we have chosen? */
|
|
EINA_LIST_FOREACH(chosen_screens, ll, scr2)
|
|
{
|
|
/* if they intersect */
|
|
if (E_INTERSECTS(scr->x, scr->y, scr->w, scr->h,
|
|
scr2->x, scr2->y, scr2->w, scr2->h))
|
|
{
|
|
int sz, sz2;
|
|
|
|
/* calculate pixel area */
|
|
sz = scr->w * scr->h;
|
|
sz2 = scr2->w * scr2->h;
|
|
/* if the one we already have is bigger, DON'T add the new */
|
|
if (sz > sz2)
|
|
removes = eina_list_append(removes, scr2);
|
|
/* add the old to a list to remove */
|
|
else
|
|
add = 0;
|
|
}
|
|
}
|
|
/* if there are screens to remove - remove them */
|
|
EINA_LIST_FREE(removes, scr2)
|
|
{
|
|
chosen_screens = eina_list_remove(chosen_screens, scr2);
|
|
}
|
|
/* if this screen is to be added, add it */
|
|
if (add)
|
|
chosen_screens = eina_list_append(chosen_screens, scr);
|
|
}
|
|
chosen_screens = eina_list_sort(chosen_screens,
|
|
eina_list_count(chosen_screens),
|
|
_e_xinerama_cb_screen_sort);
|
|
INF("======================= screens:");
|
|
EINA_LIST_FOREACH(chosen_screens, l, scr)
|
|
{
|
|
INF("E INIT: XINERAMA CHOSEN: [%i][%i], %ix%i+%i+%i",
|
|
scr->screen, scr->escreen, scr->w, scr->h, scr->x, scr->y);
|
|
n++;
|
|
}
|
|
}
|
|
|
|
static int
|
|
_e_xinerama_cb_screen_sort(const void *data1, const void *data2)
|
|
{
|
|
const E_Screen *scr, *scr2;
|
|
int dif;
|
|
|
|
scr = data1;
|
|
scr2 = data2;
|
|
if (scr->x != scr2->x)
|
|
return scr->x - scr2->x;
|
|
else if (scr->y != scr2->y)
|
|
return scr->y - scr2->y;
|
|
else
|
|
{
|
|
dif = (scr2->w * scr2->h) - (scr->w * scr->h);
|
|
if (dif == 0) return scr->screen - scr2->screen;
|
|
}
|
|
return dif;
|
|
}
|
|
|