]>
Dogcows Code - chaz/openbox/blob - openbox/resist.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 resist.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
25 #include "parser/parse.h"
29 void resist_move_windows(ObClient
*c
, gint resist
, gint
*x
, gint
*y
)
32 gint l
, t
, r
, b
; /* requested edges */
33 gint cl
, ct
, cr
, cb
; /* current edges */
34 gint w
, h
; /* current size */
35 ObClient
*snapx
= NULL
, *snapy
= NULL
;
39 frame_client_gravity(c
->frame
, x
, y
, c
->area
.width
, c
->area
.height
);
41 w
= c
->frame
->area
.width
;
42 h
= c
->frame
->area
.height
;
49 cl
= RECT_LEFT(c
->frame
->area
);
50 ct
= RECT_TOP(c
->frame
->area
);
51 cr
= RECT_RIGHT(c
->frame
->area
);
52 cb
= RECT_BOTTOM(c
->frame
->area
);
54 for (it
= stacking_list
; it
; it
= g_list_next(it
)) {
56 gint tl
, tt
, tr
, tb
; /* 1 past the target's edges on each side */
58 if (!WINDOW_IS_CLIENT(it
->data
))
62 /* don't snap to self or non-visibles */
63 if (!target
->frame
->visible
|| target
== c
) continue;
64 /* don't snap to windows set to below and skip_taskbar (desklets) */
65 if (target
->below
&& !c
->below
&& target
->skip_taskbar
) continue;
67 tl
= RECT_LEFT(target
->frame
->area
) - 1;
68 tt
= RECT_TOP(target
->frame
->area
) - 1;
69 tr
= RECT_RIGHT(target
->frame
->area
) + 1;
70 tb
= RECT_BOTTOM(target
->frame
->area
) + 1;
72 /* snapx and snapy ensure that the window snaps to the top-most
73 window edge available, without going all the way from
74 bottom-to-top in the stacking list
77 if (ct
< tb
&& cb
> tt
) {
78 if (cl
>= tr
&& l
< tr
&& l
>= tr
- resist
)
79 *x
= tr
, snapx
= target
;
80 else if (cr
<= tl
&& r
> tl
&&
82 *x
= tl
- w
+ 1, snapx
= target
;
84 /* try to corner snap to the window */
85 if (ct
> tt
&& t
<= tt
&&
87 *y
= tt
+ 1, snapy
= target
;
88 else if (cb
< tb
&& b
>= tb
&&
90 *y
= tb
- h
, snapy
= target
;
95 if (cl
< tr
&& cr
> tl
) {
96 if (ct
>= tb
&& t
< tb
&& t
>= tb
- resist
)
97 *y
= tb
, snapy
= target
;
98 else if (cb
<= tt
&& b
> tt
&&
100 *y
= tt
- h
+ 1, snapy
= target
;
102 /* try to corner snap to the window */
103 if (cl
> tl
&& l
<= tl
&&
105 *x
= tl
+ 1, snapx
= target
;
106 else if (cr
< tr
&& r
>= tr
&&
108 *x
= tr
- w
, snapx
= target
;
113 if (snapx
&& snapy
) break;
116 frame_frame_gravity(c
->frame
, x
, y
, c
->area
.width
, c
->area
.height
);
119 void resist_move_monitors(ObClient
*c
, gint resist
, gint
*x
, gint
*y
)
123 gint l
, t
, r
, b
; /* requested edges */
124 gint al
, at
, ar
, ab
; /* screen area edges */
125 gint pl
, pt
, pr
, pb
; /* physical screen area edges */
126 gint cl
, ct
, cr
, cb
; /* current edges */
127 gint w
, h
; /* current size */
132 frame_client_gravity(c
->frame
, x
, y
, c
->area
.width
, c
->area
.height
);
134 w
= c
->frame
->area
.width
;
135 h
= c
->frame
->area
.height
;
142 cl
= RECT_LEFT(c
->frame
->area
);
143 ct
= RECT_TOP(c
->frame
->area
);
144 cr
= RECT_RIGHT(c
->frame
->area
);
145 cb
= RECT_BOTTOM(c
->frame
->area
);
147 RECT_SET(desired_area
, *x
, *y
, c
->area
.width
, c
->area
.height
);
149 for (i
= 0; i
< screen_num_monitors
; ++i
) {
150 parea
= screen_physical_area_monitor(i
);
152 if (!RECT_INTERSECTS_RECT(*parea
, c
->frame
->area
)) {
157 area
= screen_area(c
->desktop
, SCREEN_AREA_ALL_MONITORS
,
160 al
= RECT_LEFT(*area
);
161 at
= RECT_TOP(*area
);
162 ar
= RECT_RIGHT(*area
);
163 ab
= RECT_BOTTOM(*area
);
164 pl
= RECT_LEFT(*parea
);
165 pt
= RECT_TOP(*parea
);
166 pr
= RECT_RIGHT(*parea
);
167 pb
= RECT_BOTTOM(*parea
);
169 if (cl
>= al
&& l
< al
&& l
>= al
- resist
)
171 else if (cr
<= ar
&& r
> ar
&& r
<= ar
+ resist
)
173 else if (cl
>= pl
&& l
< pl
&& l
>= pl
- resist
)
175 else if (cr
<= pr
&& r
> pr
&& r
<= pr
+ resist
)
178 if (ct
>= at
&& t
< at
&& t
>= at
- resist
)
180 else if (cb
<= ab
&& b
> ab
&& b
< ab
+ resist
)
182 else if (ct
>= pt
&& t
< pt
&& t
>= pt
- resist
)
184 else if (cb
<= pb
&& b
> pb
&& b
< pb
+ resist
)
191 frame_frame_gravity(c
->frame
, x
, y
, c
->area
.width
, c
->area
.height
);
194 void resist_size_windows(ObClient
*c
, gint resist
, gint
*w
, gint
*h
,
198 ObClient
*target
; /* target */
199 gint l
, t
, r
, b
; /* my left, top, right and bottom sides */
200 gint dlt
, drb
; /* my destination left/top and right/bottom sides */
201 gint tl
, tt
, tr
, tb
; /* target's left, top, right and bottom bottom sides*/
203 ObClient
*snapx
= NULL
, *snapy
= NULL
;
207 incw
= c
->size_inc
.width
;
208 inch
= c
->size_inc
.height
;
210 l
= RECT_LEFT(c
->frame
->area
);
211 r
= RECT_RIGHT(c
->frame
->area
);
212 t
= RECT_TOP(c
->frame
->area
);
213 b
= RECT_BOTTOM(c
->frame
->area
);
215 for (it
= stacking_list
; it
; it
= g_list_next(it
)) {
216 if (!WINDOW_IS_CLIENT(it
->data
))
220 /* don't snap to invisibles or ourself */
221 if (!target
->frame
->visible
|| target
== c
) continue;
222 /* don't snap to windows set to below and skip_taskbar (desklets) */
223 if (target
->below
&& !c
->below
&& target
->skip_taskbar
) continue;
225 tl
= RECT_LEFT(target
->frame
->area
);
226 tr
= RECT_RIGHT(target
->frame
->area
);
227 tt
= RECT_TOP(target
->frame
->area
);
228 tb
= RECT_BOTTOM(target
->frame
->area
);
231 /* horizontal snapping */
232 if (t
< tb
&& b
> tt
) {
234 case OB_CORNER_TOPLEFT
:
235 case OB_CORNER_BOTTOMLEFT
:
237 drb
= r
+ *w
- c
->frame
->area
.width
;
238 if (r
< tl
&& drb
>= tl
&&
240 *w
= tl
- l
, snapx
= target
;
242 case OB_CORNER_TOPRIGHT
:
243 case OB_CORNER_BOTTOMRIGHT
:
244 dlt
= l
- *w
+ c
->frame
->area
.width
;
246 if (l
> tr
&& dlt
<= tr
&&
248 *w
= r
- tr
, snapx
= target
;
255 /* vertical snapping */
256 if (l
< tr
&& r
> tl
) {
258 case OB_CORNER_TOPLEFT
:
259 case OB_CORNER_TOPRIGHT
:
261 drb
= b
+ *h
- c
->frame
->area
.height
;
262 if (b
< tt
&& drb
>= tt
&&
264 *h
= tt
- t
, snapy
= target
;
266 case OB_CORNER_BOTTOMLEFT
:
267 case OB_CORNER_BOTTOMRIGHT
:
268 dlt
= t
- *h
+ c
->frame
->area
.height
;
270 if (t
> tb
&& dlt
<= tb
&&
272 *h
= b
- tb
, snapy
= target
;
278 /* snapped both ways */
279 if (snapx
&& snapy
) break;
283 void resist_size_monitors(ObClient
*c
, gint resist
, gint
*w
, gint
*h
,
286 gint l
, t
, r
, b
; /* my left, top, right and bottom sides */
287 gint dlt
, drb
; /* my destination left/top and right/bottom sides */
289 gint al
, at
, ar
, ab
; /* screen boundaries */
290 gint pl
, pt
, pr
, pb
; /* physical screen boundaries */
297 l
= RECT_LEFT(c
->frame
->area
);
298 r
= RECT_RIGHT(c
->frame
->area
);
299 t
= RECT_TOP(c
->frame
->area
);
300 b
= RECT_BOTTOM(c
->frame
->area
);
302 incw
= c
->size_inc
.width
;
303 inch
= c
->size_inc
.height
;
305 RECT_SET(desired_area
, c
->area
.x
, c
->area
.y
, *w
, *h
);
307 for (i
= 0; i
< screen_num_monitors
; ++i
) {
308 parea
= screen_physical_area_monitor(i
);
310 if (!RECT_INTERSECTS_RECT(*parea
, c
->frame
->area
)) {
315 area
= screen_area(c
->desktop
, SCREEN_AREA_ALL_MONITORS
,
318 /* get the screen boundaries */
319 al
= RECT_LEFT(*area
);
320 at
= RECT_TOP(*area
);
321 ar
= RECT_RIGHT(*area
);
322 ab
= RECT_BOTTOM(*area
);
323 pl
= RECT_LEFT(*parea
);
324 pt
= RECT_TOP(*parea
);
325 pr
= RECT_RIGHT(*parea
);
326 pb
= RECT_BOTTOM(*parea
);
328 /* horizontal snapping */
330 case OB_CORNER_TOPLEFT
:
331 case OB_CORNER_BOTTOMLEFT
:
333 drb
= r
+ *w
- c
->frame
->area
.width
;
334 if (r
<= ar
&& drb
> ar
&& drb
<= ar
+ resist
)
336 else if (r
<= pr
&& drb
> pr
&& drb
<= pr
+ resist
)
339 case OB_CORNER_TOPRIGHT
:
340 case OB_CORNER_BOTTOMRIGHT
:
341 dlt
= l
- *w
+ c
->frame
->area
.width
;
343 if (l
>= al
&& dlt
< al
&& dlt
>= al
- resist
)
345 else if (l
>= pl
&& dlt
< pl
&& dlt
>= pl
- resist
)
350 /* vertical snapping */
352 case OB_CORNER_TOPLEFT
:
353 case OB_CORNER_TOPRIGHT
:
355 drb
= b
+ *h
- c
->frame
->area
.height
;
356 if (b
<= ab
&& drb
> ab
&& drb
<= ab
+ resist
)
358 else if (b
<= pb
&& drb
> pb
&& drb
<= pb
+ resist
)
361 case OB_CORNER_BOTTOMLEFT
:
362 case OB_CORNER_BOTTOMRIGHT
:
363 dlt
= t
- *h
+ c
->frame
->area
.height
;
365 if (t
>= at
&& dlt
< at
&& dlt
>= at
- resist
)
367 else if (t
>= pt
&& dlt
< pt
&& dlt
>= pt
- resist
)
This page took 0.053377 seconds and 4 git commands to generate.