add window placement routines to the kernel
This commit is contained in:
parent
db4b0e6270
commit
5e06be6abb
3 changed files with 148 additions and 18 deletions
20
Makefile.am
20
Makefile.am
|
@ -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
136
openbox/place.c
Normal 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
10
openbox/place.h
Normal 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
|
Loading…
Reference in a new issue