new window placement, but i was a lil tipsy when i started this so maybe its not so good. smart placement was just as useless anyways though, so yeah. and this code is much cleaner. on to stealing fvwm code now.
This commit is contained in:
parent
68a100bde3
commit
adfca324da
1 changed files with 93 additions and 164 deletions
257
openbox/place.c
257
openbox/place.c
|
@ -213,176 +213,107 @@ static GSList* area_remove(GSList *list, Rect *a)
|
|||
return result;
|
||||
}
|
||||
|
||||
static gint area_cmp(gconstpointer p1, gconstpointer p2, gpointer data)
|
||||
enum {
|
||||
IGNORE_FULLSCREEN = 1 << 0,
|
||||
IGNORE_MAXIMIZED = 1 << 1,
|
||||
IGNORE_MENUTOOL = 1 << 2,
|
||||
IGNORE_SHADED = 1 << 3,
|
||||
IGNORE_NONGROUP = 1 << 4,
|
||||
IGNORE_BELOW = 1 << 5,
|
||||
IGNORE_END = 1 << 6
|
||||
};
|
||||
|
||||
static gboolean place_nooverlap(ObClient *c, gint *x, gint *y)
|
||||
{
|
||||
ObClient *c = data;
|
||||
Rect *carea = &c->frame->area;
|
||||
const Rect *a1 = p1, *a2 = p2;
|
||||
gboolean diffhead = FALSE;
|
||||
guint i;
|
||||
Rect *a;
|
||||
|
||||
for (i = 0; i < screen_num_monitors; ++i) {
|
||||
a = screen_physical_area_monitor(i);
|
||||
if (RECT_CONTAINS(*a, a1->x, a1->y) &&
|
||||
!RECT_CONTAINS(*a, a2->x, a2->y))
|
||||
{
|
||||
diffhead = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* has to be more than me in the group */
|
||||
if (diffhead && client_has_group_siblings(c)) {
|
||||
guint *num, most;
|
||||
GSList *it;
|
||||
|
||||
/* find how many clients in the group are on each monitor, use the
|
||||
monitor with the most in it */
|
||||
num = g_new0(guint, screen_num_monitors);
|
||||
for (it = c->group->members; it; it = g_slist_next(it))
|
||||
if (it->data != c)
|
||||
++num[client_monitor(it->data)];
|
||||
most = 0;
|
||||
for (i = 1; i < screen_num_monitors; ++i)
|
||||
if (num[i] > num[most])
|
||||
most = i;
|
||||
|
||||
g_free(num);
|
||||
|
||||
a = screen_physical_area_monitor(most);
|
||||
if (RECT_CONTAINS(*a, a1->x, a1->y))
|
||||
return -1;
|
||||
if (RECT_CONTAINS(*a, a2->x, a2->y))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return MIN((a1->width - carea->width), (a1->height - carea->height)) -
|
||||
MIN((a2->width - carea->width), (a2->height - carea->height));
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SMART_FULL,
|
||||
SMART_GROUP,
|
||||
SMART_FOCUSED
|
||||
} ObSmartType;
|
||||
|
||||
#define SMART_IGNORE(placer, c) \
|
||||
(placer == c || c->shaded || !c->frame->visible || \
|
||||
c->type == OB_CLIENT_TYPE_SPLASH || c->type == OB_CLIENT_TYPE_DESKTOP || \
|
||||
((c->type == OB_CLIENT_TYPE_MENU || c->type == OB_CLIENT_TYPE_TOOLBAR) &&\
|
||||
client_has_parent(c)) || \
|
||||
(c->desktop != DESKTOP_ALL && \
|
||||
c->desktop != (placer->desktop == DESKTOP_ALL ? \
|
||||
screen_desktop : placer->desktop)))
|
||||
|
||||
static gboolean place_smart(ObClient *client, gint *x, gint *y,
|
||||
ObSmartType type, gboolean ignore_max)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GSList *spaces = NULL, *sit;
|
||||
GList *it;
|
||||
Rect **areas;
|
||||
guint i;
|
||||
gint ignore;
|
||||
gboolean ret;
|
||||
gint maxsize;
|
||||
GSList *spaces = NULL, *sit, *maxit;
|
||||
|
||||
if (type == SMART_GROUP) {
|
||||
/* has to be more than me in the group */
|
||||
if (!client_has_group_siblings(client))
|
||||
return FALSE;
|
||||
}
|
||||
areas = pick_head(c);
|
||||
ret = FALSE;
|
||||
maxsize = 0;
|
||||
maxit = NULL;
|
||||
|
||||
areas = pick_head(client);
|
||||
/* try ignoring different things to find empty space */
|
||||
for (ignore = 0; ignore < IGNORE_END && !ret; ignore = (ignore << 1) + 1) {
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < screen_num_monitors && !ret; ++i) {
|
||||
spaces = area_add(spaces, areas[i]);
|
||||
/* try all monitors in order of preference */
|
||||
for (i = 0; i < screen_num_monitors && !ret; ++i) {
|
||||
/* add the whole monitor */
|
||||
spaces = area_add(spaces, areas[i]);
|
||||
|
||||
/* stay out from under windows in higher layers */
|
||||
for (it = stacking_list; it; it = g_list_next(it)) {
|
||||
ObClient *c;
|
||||
/* go thru all the windows */
|
||||
for (sit = client_list; sit; sit = g_slist_next(sit)) {
|
||||
ObClient *test = sit->data;
|
||||
|
||||
if (WINDOW_IS_CLIENT(it->data)) {
|
||||
c = it->data;
|
||||
if (ignore_max &&
|
||||
(c->fullscreen || (c->max_vert && c->max_horz)))
|
||||
continue;
|
||||
} else
|
||||
continue;
|
||||
|
||||
if (c->layer > client->layer) {
|
||||
if (!SMART_IGNORE(client, c))
|
||||
spaces = area_remove(spaces, &c->frame->area);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == SMART_FULL || type == SMART_FOCUSED) {
|
||||
gboolean found_foc = FALSE, stop = FALSE;
|
||||
ObClient *foc;
|
||||
|
||||
foc = focus_order_find_first(client->desktop == DESKTOP_ALL ?
|
||||
screen_desktop : client->desktop);
|
||||
|
||||
for (; it && !stop; it = g_list_next(it)) {
|
||||
ObClient *c;
|
||||
|
||||
if (WINDOW_IS_CLIENT(it->data)) {
|
||||
c = it->data;
|
||||
if (ignore_max &&
|
||||
(c->fullscreen || (c->max_vert && c->max_horz)))
|
||||
continue;
|
||||
} else
|
||||
continue;
|
||||
|
||||
if (!SMART_IGNORE(client, c)) {
|
||||
if (type == SMART_FOCUSED)
|
||||
if (found_foc)
|
||||
stop = TRUE;
|
||||
if (!stop)
|
||||
spaces = area_remove(spaces, &c->frame->area);
|
||||
/* should we ignore this client? */
|
||||
if (screen_showing_desktop) continue;
|
||||
if (c == test) continue;
|
||||
if (test->iconic) continue;
|
||||
if (c->desktop != DESKTOP_ALL) {
|
||||
if (test->desktop != c->desktop &&
|
||||
test->desktop != DESKTOP_ALL) continue;
|
||||
} else {
|
||||
if (test->desktop != screen_desktop &&
|
||||
test->desktop != DESKTOP_ALL) continue;
|
||||
}
|
||||
if (test->type == OB_CLIENT_TYPE_SPLASH ||
|
||||
test->type == OB_CLIENT_TYPE_DESKTOP) continue;
|
||||
|
||||
if (c == foc)
|
||||
found_foc = TRUE;
|
||||
|
||||
if ((ignore & IGNORE_FULLSCREEN) &&
|
||||
test->fullscreen) continue;
|
||||
if ((ignore & IGNORE_MAXIMIZED) &&
|
||||
test->max_horz && test->max_vert) continue;
|
||||
if ((ignore & IGNORE_MENUTOOL) &&
|
||||
(test->type == OB_CLIENT_TYPE_MENU ||
|
||||
test->type == OB_CLIENT_TYPE_TOOLBAR) &&
|
||||
client_has_parent(c)) continue;
|
||||
if ((ignore & IGNORE_SHADED) &&
|
||||
test->shaded) continue;
|
||||
if ((ignore & IGNORE_NONGROUP) &&
|
||||
client_has_group_siblings(test) &&
|
||||
test->group != c->group) continue;
|
||||
if ((ignore & IGNORE_BELOW) &&
|
||||
test->layer < c->layer) continue;
|
||||
|
||||
/* don't ignore this window, so remove it from the available
|
||||
area */
|
||||
spaces = area_remove(spaces, &test->frame->area);
|
||||
}
|
||||
} else if (type == SMART_GROUP) {
|
||||
for (sit = client->group->members; sit; sit = g_slist_next(sit)) {
|
||||
ObClient *c = sit->data;
|
||||
if (!SMART_IGNORE(client, c))
|
||||
spaces = area_remove(spaces, &c->frame->area);
|
||||
}
|
||||
} else
|
||||
g_assert_not_reached();
|
||||
|
||||
spaces = g_slist_sort_with_data(spaces, area_cmp, client);
|
||||
for (sit = spaces; sit; sit = g_slist_next(sit)) {
|
||||
Rect *r = sit->data;
|
||||
|
||||
for (sit = spaces; sit; sit = g_slist_next(sit)) {
|
||||
Rect *r = sit->data;
|
||||
|
||||
if (!ret) {
|
||||
if (r->width >= client->frame->area.width &&
|
||||
r->height >= client->frame->area.height) {
|
||||
ret = TRUE;
|
||||
if (client->type == OB_CLIENT_TYPE_DIALOG ||
|
||||
type != SMART_FULL)
|
||||
{
|
||||
*x = r->x + (r->width - client->frame->area.width)/2;
|
||||
*y = r->y + (r->height - client->frame->area.height)/2;
|
||||
} else {
|
||||
*x = r->x;
|
||||
*y = r->y;
|
||||
}
|
||||
if (r->width >= c->frame->area.width &&
|
||||
r->height >= c->frame->area.height &&
|
||||
r->width > maxsize)
|
||||
{
|
||||
maxsize = r->width;
|
||||
maxit = sit;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(r);
|
||||
if (maxit) {
|
||||
Rect *r = maxit->data;
|
||||
|
||||
/* center it in the area */
|
||||
*x = r->x + (r->width - c->frame->area.width) / 2;
|
||||
*y = r->y + (r->height - c->frame->area.height) / 2;
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
while (spaces) {
|
||||
g_free(spaces->data);
|
||||
spaces = g_slist_delete_link(spaces, spaces);
|
||||
}
|
||||
}
|
||||
g_slist_free(spaces);
|
||||
spaces = NULL;
|
||||
}
|
||||
|
||||
g_free(areas);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -500,22 +431,20 @@ static gboolean place_transient_splash(ObClient *client, gint *x, gint *y)
|
|||
gboolean place_client(ObClient *client, gint *x, gint *y,
|
||||
ObAppSettings *settings)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
gboolean ret;
|
||||
|
||||
if (client->positioned)
|
||||
return FALSE;
|
||||
if (place_transient_splash(client, x, y))
|
||||
ret = TRUE;
|
||||
else if (!(
|
||||
|
||||
/* try a number of methods */
|
||||
ret = place_transient_splash(client, x, y) ||
|
||||
place_per_app_setting(client, x, y, settings) ||
|
||||
((config_place_policy == OB_PLACE_POLICY_MOUSE) ?
|
||||
place_under_mouse(client, x, y) :
|
||||
place_smart(client, x, y, SMART_FULL, FALSE) ||
|
||||
place_smart(client, x, y, SMART_FULL, TRUE) ||
|
||||
place_smart(client, x, y, SMART_GROUP, FALSE) ||
|
||||
place_smart(client, x, y, SMART_GROUP, TRUE) ||
|
||||
place_smart(client, x, y, SMART_FOCUSED, TRUE) ||
|
||||
place_random(client, x, y))))
|
||||
g_assert_not_reached(); /* the last one better succeed */
|
||||
(config_place_policy == OB_PLACE_POLICY_MOUSE &&
|
||||
place_under_mouse(client, x, y)) ||
|
||||
place_nooverlap(client, x, y) ||
|
||||
place_random(client, x, y);
|
||||
g_assert(ret);
|
||||
|
||||
/* get where the client should be */
|
||||
frame_frame_gravity(client->frame, x, y,
|
||||
client->area.width, client->area.height);
|
||||
|
|
Loading…
Reference in a new issue