add window placement routines to the kernel

This commit is contained in:
Dana Jansens 2003-08-29 06:40:35 +00:00
parent db4b0e6270
commit 5e06be6abb
3 changed files with 148 additions and 18 deletions

View file

@ -26,7 +26,6 @@ bin_PROGRAMS = \
tools/kdetrayproxy/kdetrayproxy
plugin_LTLIBRARIES = \
plugins/placement/placement.la \
plugins/menu/client_menu.la \
plugins/menu/client_list_menu.la
# plugins/menu/timed_menu.la \
@ -168,6 +167,8 @@ kernel_openbox_SOURCES = \
kernel/mwm.h \
kernel/openbox.c \
kernel/openbox.h \
kernel/place.c \
kernel/place.h \
kernel/plugin.c \
kernel/plugin.h \
kernel/popup.c \
@ -194,23 +195,6 @@ kernel_openbox_SOURCES = \
kernel/xerror.h \
plugins/interface.h
## plugins/placement ##
plugins_placement_placement_la_CPPFLAGS = \
$(XFT_CFLAGS) \
$(GLIB_CFLAGS) \
$(LIBSN_CFLAGS) \
$(XML_CFLAGS) \
-DPLUGINDIR=\"$(plugindir)\" \
-DG_LOG_DOMAIN=\"Plugin-Placement\"
plugins_placement_placement_la_LDFLAGS = \
-module \
-avoid-version
plugins_placement_placement_la_SOURCES = \
plugins/placement/placement.c \
plugins/placement/history.c \
plugins/placement/history.h
## plugins/menu ##
plugins_menu_timed_menu_la_CPPFLAGS = \

136
openbox/place.c Normal file
View file

@ -0,0 +1,136 @@
#include "client.h"
#include "group.h"
#include "screen.h"
#include "frame.h"
static Rect* pick_head(ObClient *c)
{
/* try direct parent first */
if (c->transient_for && c->transient_for != OB_TRAN_GROUP) {
return screen_area_monitor(c->desktop,
client_monitor(c->transient_for));
}
/* more than one guy in his group (more than just him) */
if (c->group && c->group->members->next) {
GSList *it;
/* try on the client's desktop */
for (it = c->group->members; it; it = g_slist_next(it)) {
ObClient *itc = it->data;
if (itc != c &&
(itc->desktop == c->desktop ||
itc->desktop == DESKTOP_ALL || c->desktop == DESKTOP_ALL))
return screen_area_monitor(c->desktop,
client_monitor(it->data));
}
/* try on all desktops */
for (it = c->group->members; it; it = g_slist_next(it)) {
ObClient *itc = it->data;
if (itc != c)
return screen_area_monitor(c->desktop,
client_monitor(it->data));
}
}
return NULL;
}
static gboolean place_random(ObClient *client, gint *x, gint *y)
{
int l, r, t, b;
Rect *area;
area = pick_head(client);
if (!area)
area = screen_area_monitor(client->desktop,
g_random_int_range(0, screen_num_monitors));
l = area->x;
t = area->y;
r = area->x + area->width - client->frame->area.width;
b = area->y + area->height - client->frame->area.height;
if (r > l) *x = g_random_int_range(l, r + 1);
else *x = 0;
if (b > t) *y = g_random_int_range(t, b + 1);
else *y = 0;
/* get where the client should be */
frame_frame_gravity(client->frame, x, y);
return TRUE;
}
static gboolean place_transient(ObClient *client, gint *x, gint *y)
{
if (client->transient_for) {
if (client->transient_for != OB_TRAN_GROUP) {
ObClient *c = client;
ObClient *p = client->transient_for;
*x = (p->frame->area.width - c->frame->area.width) / 2 +
p->frame->area.x;
*y = (p->frame->area.height - c->frame->area.height) / 2 +
p->frame->area.y;
return TRUE;
} else {
GSList *it;
gboolean first = TRUE;
int l, r, t, b;
for (it = client->group->members; it; it = it->next) {
ObClient *m = it->data;
if (!(m == client || m->transient_for)) {
if (first) {
l = m->frame->area.x;
t = m->frame->area.y;
r = m->frame->area.x + m->frame->area.width - 1;
b = m->frame->area.y + m->frame->area.height - 1;
first = FALSE;
} else {
l = MIN(l, m->frame->area.x);
t = MIN(t, m->frame->area.y);
r = MAX(r, m->frame->area.x +m->frame->area.width - 1);
b = MAX(b, m->frame->area.y +m->frame->area.height -1);
}
}
}
if (!first) {
*x = ((r + 1 - l) - client->frame->area.width) / 2 + l;
*y = ((b + 1 - t) - client->frame->area.height) / 2 + t;
return TRUE;
}
}
}
return FALSE;
}
static gboolean place_dialog(ObClient *client, gint *x, gint *y)
{
/* center parentless dialogs on the screen */
if (client->type == OB_CLIENT_TYPE_DIALOG) {
Rect *area;
area = pick_head(client);
if (!area)
area = screen_area_monitor(client->desktop, 0);
*x = (area->width - client->frame->area.width) / 2 + area->x;
*y = (area->height - client->frame->area.height) / 2 + area->y;
return TRUE;
}
return FALSE;
}
void place_client(ObClient *client, gint *x, gint *y)
{
if (client->positioned)
return;
if (place_transient(client, x, y))
return;
if (place_dialog(client, x, y))
return;
if (place_random(client, x, y))
return;
g_assert_not_reached(); /* the last one better succeed */
}

10
openbox/place.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef ob__place_h
#define ob__place_h
#include <glib.h>
struct _ObClient;
void place_client(ObClient *client, gint *x, gint *y);
#endif