]>
Dogcows Code - chaz/openbox/blob - openbox/place.c
27df69f5d337802fa581aa86d59250f658b0ada6
8 static Rect
* pick_head(ObClient
*c
)
10 /* try direct parent first */
11 if (c
->transient_for
&& c
->transient_for
!= OB_TRAN_GROUP
) {
12 return screen_area_monitor(c
->desktop
,
13 client_monitor(c
->transient_for
));
16 /* more than one guy in his group (more than just him) */
17 if (c
->group
&& c
->group
->members
->next
) {
20 /* try on the client's desktop */
21 for (it
= c
->group
->members
; it
; it
= g_slist_next(it
)) {
22 ObClient
*itc
= it
->data
;
24 (itc
->desktop
== c
->desktop
||
25 itc
->desktop
== DESKTOP_ALL
|| c
->desktop
== DESKTOP_ALL
))
26 return screen_area_monitor(c
->desktop
,
27 client_monitor(it
->data
));
30 /* try on all desktops */
31 for (it
= c
->group
->members
; it
; it
= g_slist_next(it
)) {
32 ObClient
*itc
= it
->data
;
34 return screen_area_monitor(c
->desktop
,
35 client_monitor(it
->data
));
42 static gboolean
place_random(ObClient
*client
, gint
*x
, gint
*y
)
47 area
= pick_head(client
);
49 area
= screen_area_monitor(client
->desktop
,
50 g_random_int_range(0, screen_num_monitors
));
54 r
= area
->x
+ area
->width
- client
->frame
->area
.width
;
55 b
= area
->y
+ area
->height
- client
->frame
->area
.height
;
57 if (r
> l
) *x
= g_random_int_range(l
, r
+ 1);
59 if (b
> t
) *y
= g_random_int_range(t
, b
+ 1);
65 static GSList
* area_add(GSList
*list
, Rect
*a
)
67 Rect
*r
= g_new(Rect
, 1);
69 return g_slist_prepend(list
, r
);
72 static GSList
* area_remove(GSList
*list
, Rect
*a
)
75 GSList
*result
= NULL
;
77 for (sit
= list
; sit
; sit
= g_slist_next(sit
)) {
80 if (!RECT_INTERSECTS_RECT(*r
, *a
)) {
81 result
= g_slist_prepend(result
, r
);
82 r
= NULL
; /* dont free it */
86 /* Use an intersection of a and r to determine the space
87 around r that we can use.
89 NOTE: the spaces calculated can overlap.
92 RECT_SET_INTERSECTION(isect
, *r
, *a
);
94 if (RECT_LEFT(isect
) > RECT_LEFT(*r
)) {
95 RECT_SET(extra
, r
->x
, r
->y
,
96 RECT_LEFT(isect
) - r
->x
, r
->height
);
97 result
= area_add(result
, &extra
);
100 if (RECT_TOP(isect
) > RECT_TOP(*r
)) {
101 RECT_SET(extra
, r
->x
, r
->y
,
102 r
->width
, RECT_TOP(isect
) - r
->y
+ 1);
103 result
= area_add(result
, &extra
);
106 if (RECT_RIGHT(isect
) < RECT_RIGHT(*r
)) {
107 RECT_SET(extra
, RECT_RIGHT(isect
) + 1, r
->y
,
108 RECT_RIGHT(*r
) - RECT_RIGHT(isect
), r
->height
);
109 result
= area_add(result
, &extra
);
112 if (RECT_BOTTOM(isect
) < RECT_BOTTOM(*r
)) {
113 RECT_SET(extra
, r
->x
, RECT_BOTTOM(isect
) + 1,
114 r
->width
, RECT_BOTTOM(*r
) - RECT_BOTTOM(isect
));
115 result
= area_add(result
, &extra
);
125 static gint
area_cmp(gconstpointer p1
, gconstpointer p2
)
127 const Rect
*a1
= p1
, *a2
= p2
;
129 return a1
->width
* a1
->height
- a2
->width
* a2
->height
;
132 static gboolean
place_smart(ObClient
*client
, gint
*x
, gint
*y
,
133 gboolean only_focused
)
136 gboolean ret
= FALSE
;
137 GSList
*spaces
= NULL
, *sit
;
140 list
= focus_order
[client
->desktop
== DESKTOP_ALL
?
141 screen_desktop
: client
->desktop
];
143 for (i
= 0; i
< screen_num_monitors
; ++i
)
144 spaces
= area_add(spaces
, screen_area_monitor(client
->desktop
, i
));
146 for (it
= list
; it
; it
= g_list_next(it
)) {
147 ObClient
*c
= it
->data
;
149 if (c
!= client
&& !c
->shaded
&& client_normal(c
)) {
150 spaces
= area_remove(spaces
, &c
->frame
->area
);
156 spaces
= g_slist_sort(spaces
, area_cmp
);
158 for (sit
= spaces
; sit
; sit
= g_slist_next(sit
)) {
162 if (r
->width
>= client
->frame
->area
.width
&&
163 r
->height
>= client
->frame
->area
.height
) {
165 *x
= r
->x
+ (r
->width
- client
->frame
->area
.width
) / 2;
166 *y
= r
->y
+ (r
->height
- client
->frame
->area
.height
) / 2;
172 g_slist_free(spaces
);
177 static gboolean
place_under_mouse(ObClient
*client
, gint
*x
, gint
*y
)
184 screen_pointer_pos(&px
, &py
);
186 for (i
= 0; i
< screen_num_monitors
; ++i
) {
187 area
= screen_area_monitor(client
->desktop
, i
);
188 if (RECT_CONTAINS(*area
, px
, py
))
191 if (i
== screen_num_monitors
)
192 area
= screen_area_monitor(client
->desktop
, 0);
196 r
= area
->x
+ area
->width
- client
->frame
->area
.width
;
197 b
= area
->y
+ area
->height
- client
->frame
->area
.height
;
199 *x
= px
- client
->area
.width
/ 2 - client
->frame
->size
.left
;
200 *x
= MIN(MAX(*x
, l
), r
);
201 *y
= py
- client
->area
.height
/ 2 - client
->frame
->size
.top
;
202 *y
= MIN(MAX(*y
, t
), b
);
207 static gboolean
place_transient(ObClient
*client
, gint
*x
, gint
*y
)
209 if (client
->transient_for
) {
210 if (client
->transient_for
!= OB_TRAN_GROUP
) {
211 ObClient
*c
= client
;
212 ObClient
*p
= client
->transient_for
;
213 *x
= (p
->frame
->area
.width
- c
->frame
->area
.width
) / 2 +
215 *y
= (p
->frame
->area
.height
- c
->frame
->area
.height
) / 2 +
220 gboolean first
= TRUE
;
222 for (it
= client
->group
->members
; it
; it
= it
->next
) {
223 ObClient
*m
= it
->data
;
224 if (!(m
== client
|| m
->transient_for
)) {
226 l
= RECT_LEFT(m
->frame
->area
);
227 t
= RECT_TOP(m
->frame
->area
);
228 r
= RECT_RIGHT(m
->frame
->area
);
229 b
= RECT_BOTTOM(m
->frame
->area
);
232 l
= MIN(l
, RECT_LEFT(m
->frame
->area
));
233 t
= MIN(t
, RECT_TOP(m
->frame
->area
));
234 r
= MAX(r
, RECT_RIGHT(m
->frame
->area
));
235 b
= MAX(b
, RECT_BOTTOM(m
->frame
->area
));
240 *x
= ((r
+ 1 - l
) - client
->frame
->area
.width
) / 2 + l
;
241 *y
= ((b
+ 1 - t
) - client
->frame
->area
.height
) / 2 + t
;
249 static gboolean
place_dialog(ObClient
*client
, gint
*x
, gint
*y
)
251 /* center parentless dialogs on the screen */
252 if (client
->type
== OB_CLIENT_TYPE_DIALOG
) {
255 area
= pick_head(client
);
257 area
= screen_area_monitor(client
->desktop
, 0);
259 *x
= (area
->width
- client
->frame
->area
.width
) / 2 + area
->x
;
260 *y
= (area
->height
- client
->frame
->area
.height
) / 2 + area
->y
;
266 void place_client(ObClient
*client
, gint
*x
, gint
*y
)
268 if (client
->positioned
)
270 if (place_transient(client
, x
, y
) ||
271 place_dialog(client
, x
, y
) ||
272 place_smart(client
, x
, y
, FALSE
) ||
273 place_smart(client
, x
, y
, TRUE
) ||
274 (config_focus_follow
?
275 place_under_mouse(client
, x
, y
) :
276 place_random(client
, x
, y
)))
278 /* get where the client should be */
279 frame_frame_gravity(client
->frame
, x
, y
);
281 g_assert_not_reached(); /* the last one better succeed */
This page took 0.05092 seconds and 4 git commands to generate.