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 \
kernel/mwm.h \
kernel/openbox.c \
kernel/openbox.h \
+ kernel/place.c \
+ kernel/place.h \
kernel/plugin.c \
kernel/plugin.h \
kernel/popup.c \
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 = \
--- /dev/null
+#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 */
+}