enlightenment/src/place.c

581 lines
12 KiB
C

#include "debug.h"
#include "config.h"
#include "place.h"
#include "actions.h"
#include "guides.h"
#include "util.h"
static void e_mouse_down(Ecore_Event * ev);
static void e_mouse_up(Ecore_Event * ev);
static void e_mouse_move(Ecore_Event * ev);
static int prx, pry;
static Window win_place = 0;
static void
e_mouse_down(Ecore_Event * ev)
{
Ecore_Event_Mouse_Down *e;
D_ENTER;
e = ev->event;
if (!win_place)
D_RETURN;
D_RETURN;
}
static void
e_mouse_up(Ecore_Event * ev)
{
Ecore_Event_Mouse_Up *e;
D_ENTER;
e = ev->event;
if (!win_place)
D_RETURN;
e_action_stop("Window_Place", ACT_MOUSE_UP, 1, NULL,
ECORE_EVENT_KEY_MODIFIER_NONE, NULL, NULL, e->x, e->y, e->rx,
e->ry);
ecore_window_destroy(win_place);
win_place = 0;
D_RETURN;
}
static void
e_mouse_move(Ecore_Event * ev)
{
Ecore_Event_Mouse_Move *e;
D_ENTER;
e = ev->event;
if (!win_place)
D_RETURN;
e_action_cont("Window_Place", ACT_MOUSE_MOVE, 1, NULL,
ECORE_EVENT_KEY_MODIFIER_NONE, NULL, NULL, e->x, e->y, e->rx,
e->ry, e->rx - prx, e->ry - pry);
prx = e->rx;
pry = e->ry;
D_RETURN;
}
static int
e_place_manual(E_Border * b, E_Desktop * desk, int *x, int *y)
{
int w, h;
int mx, my, rx, ry;
int move_mode = E_GUIDES_BOX;
D_ENTER;
move_mode = config_data->window->move_mode;
w = b->current.requested.w;
h = b->current.requested.h;
if (!win_place)
{
win_place = ecore_window_input_new(0, 0, 0, desk->real.w, desk->real.h);
ecore_window_set_events(win_place, XEV_MOUSE_MOVE | XEV_BUTTON);
ecore_window_raise(win_place);
ecore_window_show(win_place);
}
else
{
e_action_stop_by_type("Window_Place");
}
/* get mouse coords */
/* ecore_pointer_xy(desk->win.main, &mx, &my); */
ecore_pointer_xy(0, &mx, &my);
rx = mx;
ry = my;
prx = rx;
pry = ry;
/* grab mouse to desktop */
ecore_pointer_ungrab(CurrentTime);
ecore_pointer_grab(win_place, CurrentTime);
*x = mx - (w / 2);
*y = my - (h / 2);
/* start a move mode */
e_action_stop_by_type("Window_Place");
e_action_start("Window_Place", ACT_MOUSE_CLICK, 1, NULL,
ECORE_EVENT_KEY_MODIFIER_NONE, E_OBJECT(b), NULL, mx, my, rx,
ry);
if (move_mode != E_GUIDES_OPAQUE)
D_RETURN_(0);
D_RETURN_(1);
}
static int
e_place_smart(E_Border * b, E_Desktop * desk, int *x, int *y)
{
int w, h;
int a_w = 0, a_h = 0;
int *a_x = NULL, *a_y = NULL;
Evas_List * l;
D_ENTER;
w = b->current.requested.w;
h = b->current.requested.h;
a_w = 2;
a_h = 2;
a_x = NEW(int, 2);
a_y = NEW(int, 2);
a_x[0] = 0;
a_x[1] = desk->real.w;
a_y[0] = 0;
a_y[1] = desk->real.h;
for (l = desk->windows; l; l = l->next)
{
E_Border *bd;
bd = l->data;
if ((bd != b) && (bd->current.visible))
{
if (INTERSECTS(bd->current.x, bd->current.y,
bd->current.w, bd->current.h,
0, 0, desk->real.w, desk->real.h))
{
int i, j;
for (i = 0; i < a_w; i++)
{
int ok = 1;
if (bd->current.x > 0)
{
if (a_x[i] == bd->current.x)
ok = 0;
else if (a_x[i] > bd->current.x)
{
a_w++;
REALLOC(a_x, int, a_w);
for (j = a_w - 1; j > i; j--)
a_x[j] = a_x[j - 1];
a_x[i] = bd->current.x;
ok = 0;
}
}
if (!ok)
break;
}
for (i = 0; i < a_w; i++)
{
int ok = 1;
if (bd->current.x + bd->current.w < desk->real.w)
{
if (a_x[i] == bd->current.x + bd->current.w)
ok = 0;
else if (a_x[i] > bd->current.x + bd->current.w)
{
a_w++;
REALLOC(a_x, int, a_w);
for (j = a_w - 1; j > i; j--)
a_x[j] = a_x[j - 1];
a_x[i] = bd->current.x + bd->current.w;
ok = 0;
}
}
if (!ok)
break;
}
for (i = 0; i < a_h; i++)
{
int ok = 1;
if (bd->current.y > 0)
{
if (a_y[i] == bd->current.y)
ok = 0;
else if (a_y[i] > bd->current.y)
{
a_h++;
REALLOC(a_y, int, a_h);
for (j = a_h - 1; j > i; j--)
a_y[j] = a_y[j - 1];
a_y[i] = bd->current.y;
ok = 0;
}
}
if (!ok)
break;
}
for (i = 0; i < a_h; i++)
{
int ok = 1;
if (bd->current.y + bd->current.h < desk->real.h)
{
if (a_y[i] == bd->current.y + bd->current.h)
ok = 0;
else if (a_y[i] > bd->current.y + bd->current.h)
{
a_h++;
REALLOC(a_y, int, a_h);
for (j = a_h - 1; j > i; j--)
a_y[j] = a_y[j - 1];
a_y[i] = bd->current.y + bd->current.h;
ok = 0;
}
}
if (!ok)
break;
}
}
}
}
{
int i, j;
int area = 0x7fffffff;
for (j = 0; j < a_h - 1; j++)
{
for (i = 0; i < a_w - 1; i++)
{
if ((a_x[i] < (desk->real.w - w)) &&
(a_y[j] < (desk->real.h - h)))
{
int ar = 0;
for (l = desk->windows; l; l = l->next)
{
E_Border *bd;
int x1, y1, w1, h1, x2, y2, w2, h2;
bd = l->data;
x1 = a_x[i];
y1 = a_y[j];
w1 = w;
h1 = h;
x2 = bd->current.x;
y2 = bd->current.y;
w2 = bd->current.w;
h2 = bd->current.h;
if ((bd != b) && (bd->current.visible) &&
INTERSECTS(x1, y1, w1, h1, x2, y2, w2, h2))
{
int iw, ih;
int x0, x00, y0, y00;
x0 = x1;
if (x1 < x2)
x0 = x2;
x00 = (x1 + w1);
if ((x2 + w2) < (x1 + w1))
x00 = (x2 + w2);
y0 = y1;
if (y1 < y2)
y0 = y2;
y00 = (y1 + h1);
if ((y2 + h2) < (y1 + h1))
y00 = (y2 + h2);
iw = x00 - x0;
ih = y00 - y0;
ar += (iw * ih);
}
}
if (ar < area)
{
area = ar;
*x = a_x[i];
*y = a_y[j];
if (ar == 0)
goto done;
}
}
if ((a_x[i + 1] - w > 0) && (a_y[j] < (desk->real.h - h)))
{
int ar = 0;
for (l = desk->windows; l; l = l->next)
{
E_Border *bd;
int x1, y1, w1, h1, x2, y2, w2, h2;
bd = l->data;
x1 = a_x[i + 1] - w;
y1 = a_y[j];
w1 = w;
h1 = h;
x2 = bd->current.x;
y2 = bd->current.y;
w2 = bd->current.w;
h2 = bd->current.h;
if ((bd != b) && (bd->current.visible) &&
INTERSECTS(x1, y1, w1, h1, x2, y2, w2, h2))
{
int iw, ih;
int x0, x00, y0, y00;
x0 = x1;
if (x1 < x2)
x0 = x2;
x00 = (x1 + w1);
if ((x2 + w2) < (x1 + w1))
x00 = (x2 + w2);
y0 = y1;
if (y1 < y2)
y0 = y2;
y00 = (y1 + h1);
if ((y2 + h2) < (y1 + h1))
y00 = (y2 + h2);
iw = x00 - x0;
ih = y00 - y0;
ar += (iw * ih);
}
}
if (ar < area)
{
area = ar;
*x = a_x[i + 1] - w;
*y = a_y[j];
if (ar == 0)
goto done;
}
}
if ((a_x[i + 1] - w > 0) && (a_y[j + 1] - h > 0))
{
int ar = 0;
for (l = desk->windows; l; l = l->next)
{
E_Border *bd;
int x1, y1, w1, h1, x2, y2, w2, h2;
bd = l->data;
x1 = a_x[i + 1] - w;
y1 = a_y[j + 1] - h;
w1 = w;
h1 = h;
x2 = bd->current.x;
y2 = bd->current.y;
w2 = bd->current.w;
h2 = bd->current.h;
if ((bd != b) && (bd->current.visible) &&
INTERSECTS(x1, y1, w1, h1, x2, y2, w2, h2))
{
int iw, ih;
int x0, x00, y0, y00;
x0 = x1;
if (x1 < x2)
x0 = x2;
x00 = (x1 + w1);
if ((x2 + w2) < (x1 + w1))
x00 = (x2 + w2);
y0 = y1;
if (y1 < y2)
y0 = y2;
y00 = (y1 + h1);
if ((y2 + h2) < (y1 + h1))
y00 = (y2 + h2);
iw = x00 - x0;
ih = y00 - y0;
ar += (iw * ih);
}
}
if (ar < area)
{
area = ar;
*x = a_x[i + 1] - w;
*y = a_y[j + 1] - h;
if (ar == 0)
goto done;
}
}
if ((a_x[i] < (desk->real.w - w)) && (a_y[j + 1] - h > 0))
{
int ar = 0;
for (l = desk->windows; l; l = l->next)
{
E_Border *bd;
int x1, y1, w1, h1, x2, y2, w2, h2;
bd = l->data;
x1 = a_x[i];
y1 = a_y[j + 1] - h;
w1 = w;
h1 = h;
x2 = bd->current.x;
y2 = bd->current.y;
w2 = bd->current.w;
h2 = bd->current.h;
if ((bd != b) && (bd->current.visible) &&
INTERSECTS(x1, y1, w1, h1, x2, y2, w2, h2))
{
int iw, ih;
int x0, x00, y0, y00;
x0 = x1;
if (x1 < x2)
x0 = x2;
x00 = (x1 + w1);
if ((x2 + w2) < (x1 + w1))
x00 = (x2 + w2);
y0 = y1;
if (y1 < y2)
y0 = y2;
y00 = (y1 + h1);
if ((y2 + h2) < (y1 + h1))
y00 = (y2 + h2);
iw = x00 - x0;
ih = y00 - y0;
ar += (iw * ih);
}
}
if (ar < area)
{
area = ar;
*x = a_x[i];
*y = a_y[j + 1] - h;
if (ar == 0)
goto done;
}
}
}
}
}
done:
FREE(a_x);
FREE(a_y);
D_RETURN_(1);
}
static int
e_place_middle(E_Border * b, E_Desktop * desk, int *x, int *y)
{
int w, h;
D_ENTER;
w = b->current.requested.w;
h = b->current.requested.h;
*x = (desk->real.w - w) / 2;
*y = (desk->real.h - h) / 2;
D_RETURN_(1);
}
static int
e_place_cascade(E_Border * b, E_Desktop * desk, int *x, int *y)
{
int w, h;
static int count_x = 0;
static int count_y = 0;
int pl, pr, pt, pb;
D_ENTER;
pl = pr = pt = pb = 0;
if (b->bits.b)
ebits_get_insets(b->bits.b, &pl, &pr, &pt, &pb);
w = b->current.requested.w;
h = b->current.requested.h;
if ((count_x + w) > desk->real.w)
count_x = 0;
if ((count_y + h) > desk->real.h)
count_y = 0;
*x = count_x;
*y = count_y;
count_x += pl;
count_y += pt;
D_RETURN_(1);
}
static int
e_place_random(E_Border * b, E_Desktop * desk, int *x, int *y)
{
int w, h;
D_ENTER;
w = b->current.requested.w;
h = b->current.requested.h;
if (w < desk->real.w)
*x = (rand() % (desk->real.w - w));
else
*x = 0;
if (h < desk->real.h)
*y = (rand() % (desk->real.h - h));
else
*y = 0;
D_RETURN_(1);
}
int
e_place_border(E_Border * b, E_Desktop * desk, int *x, int *y,
E_Placement_Mode mode)
{
int result = 1;
D_ENTER;
if (b->client.no_place)
D_RETURN_(1);
switch (mode)
{
case E_PLACE_MANUAL:
result = e_place_manual(b, desk, x, y);
break;
case E_PLACE_SMART:
result = e_place_smart(b, desk, x, y);
break;
case E_PLACE_MIDDLE:
result = e_place_middle(b, desk, x, y);
break;
case E_PLACE_CASCADE:
result = e_place_cascade(b, desk, x, y);
break;
case E_PLACE_RANDOM:
result = e_place_random(b, desk, x, y);
break;
default:
break;
}
D_RETURN_(result);
}
void
e_place_init(void)
{
D_ENTER;
ecore_event_filter_handler_add(ECORE_EVENT_MOUSE_DOWN, e_mouse_down);
ecore_event_filter_handler_add(ECORE_EVENT_MOUSE_UP, e_mouse_up);
ecore_event_filter_handler_add(ECORE_EVENT_MOUSE_MOVE, e_mouse_move);
D_RETURN;
}