]> Dogcows Code - chaz/openbox/blob - openbox/place.c
add window placement routines to the kernel
[chaz/openbox] / openbox / place.c
1 #include "client.h"
2 #include "group.h"
3 #include "screen.h"
4 #include "frame.h"
5
6 static Rect* pick_head(ObClient *c)
7 {
8 /* try direct parent first */
9 if (c->transient_for && c->transient_for != OB_TRAN_GROUP) {
10 return screen_area_monitor(c->desktop,
11 client_monitor(c->transient_for));
12 }
13
14 /* more than one guy in his group (more than just him) */
15 if (c->group && c->group->members->next) {
16 GSList *it;
17
18 /* try on the client's desktop */
19 for (it = c->group->members; it; it = g_slist_next(it)) {
20 ObClient *itc = it->data;
21 if (itc != c &&
22 (itc->desktop == c->desktop ||
23 itc->desktop == DESKTOP_ALL || c->desktop == DESKTOP_ALL))
24 return screen_area_monitor(c->desktop,
25 client_monitor(it->data));
26 }
27
28 /* try on all desktops */
29 for (it = c->group->members; it; it = g_slist_next(it)) {
30 ObClient *itc = it->data;
31 if (itc != c)
32 return screen_area_monitor(c->desktop,
33 client_monitor(it->data));
34 }
35 }
36
37 return NULL;
38 }
39
40 static gboolean place_random(ObClient *client, gint *x, gint *y)
41 {
42 int l, r, t, b;
43 Rect *area;
44
45 area = pick_head(client);
46 if (!area)
47 area = screen_area_monitor(client->desktop,
48 g_random_int_range(0, screen_num_monitors));
49
50 l = area->x;
51 t = area->y;
52 r = area->x + area->width - client->frame->area.width;
53 b = area->y + area->height - client->frame->area.height;
54
55 if (r > l) *x = g_random_int_range(l, r + 1);
56 else *x = 0;
57 if (b > t) *y = g_random_int_range(t, b + 1);
58 else *y = 0;
59
60 /* get where the client should be */
61 frame_frame_gravity(client->frame, x, y);
62
63 return TRUE;
64 }
65
66 static gboolean place_transient(ObClient *client, gint *x, gint *y)
67 {
68 if (client->transient_for) {
69 if (client->transient_for != OB_TRAN_GROUP) {
70 ObClient *c = client;
71 ObClient *p = client->transient_for;
72 *x = (p->frame->area.width - c->frame->area.width) / 2 +
73 p->frame->area.x;
74 *y = (p->frame->area.height - c->frame->area.height) / 2 +
75 p->frame->area.y;
76 return TRUE;
77 } else {
78 GSList *it;
79 gboolean first = TRUE;
80 int l, r, t, b;
81 for (it = client->group->members; it; it = it->next) {
82 ObClient *m = it->data;
83 if (!(m == client || m->transient_for)) {
84 if (first) {
85 l = m->frame->area.x;
86 t = m->frame->area.y;
87 r = m->frame->area.x + m->frame->area.width - 1;
88 b = m->frame->area.y + m->frame->area.height - 1;
89 first = FALSE;
90 } else {
91 l = MIN(l, m->frame->area.x);
92 t = MIN(t, m->frame->area.y);
93 r = MAX(r, m->frame->area.x +m->frame->area.width - 1);
94 b = MAX(b, m->frame->area.y +m->frame->area.height -1);
95 }
96 }
97 }
98 if (!first) {
99 *x = ((r + 1 - l) - client->frame->area.width) / 2 + l;
100 *y = ((b + 1 - t) - client->frame->area.height) / 2 + t;
101 return TRUE;
102 }
103 }
104 }
105 return FALSE;
106 }
107
108 static gboolean place_dialog(ObClient *client, gint *x, gint *y)
109 {
110 /* center parentless dialogs on the screen */
111 if (client->type == OB_CLIENT_TYPE_DIALOG) {
112 Rect *area;
113
114 area = pick_head(client);
115 if (!area)
116 area = screen_area_monitor(client->desktop, 0);
117
118 *x = (area->width - client->frame->area.width) / 2 + area->x;
119 *y = (area->height - client->frame->area.height) / 2 + area->y;
120 return TRUE;
121 }
122 return FALSE;
123 }
124
125 void place_client(ObClient *client, gint *x, gint *y)
126 {
127 if (client->positioned)
128 return;
129 if (place_transient(client, x, y))
130 return;
131 if (place_dialog(client, x, y))
132 return;
133 if (place_random(client, x, y))
134 return;
135 g_assert_not_reached(); /* the last one better succeed */
136 }
This page took 0.046326 seconds and 5 git commands to generate.