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 Ben 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
*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
;
37 w
= c
->frame
->area
.width
;
38 h
= c
->frame
->area
.height
;
45 cl
= RECT_LEFT(c
->frame
->area
);
46 ct
= RECT_TOP(c
->frame
->area
);
47 cr
= RECT_RIGHT(c
->frame
->area
);
48 cb
= RECT_BOTTOM(c
->frame
->area
);
50 if (config_resist_win
)
51 for (it
= stacking_list
; it
; it
= g_list_next(it
)) {
53 gint tl
, tt
, tr
, tb
; /* 1 past the target's edges on each side */
55 if (!WINDOW_IS_CLIENT(it
->data
))
59 /* don't snap to self or non-visibles */
60 if (!target
->frame
->visible
|| target
== c
) continue;
62 /* don't snap to windows in layers beneath */
63 if(target
->layer
< c
->layer
&& !config_resist_layers_below
)
66 tl
= RECT_LEFT(target
->frame
->area
) - 1;
67 tt
= RECT_TOP(target
->frame
->area
) - 1;
68 tr
= RECT_RIGHT(target
->frame
->area
) + 1;
69 tb
= RECT_BOTTOM(target
->frame
->area
) + 1;
71 /* snapx and snapy ensure that the window snaps to the top-most
72 window edge available, without going all the way from
73 bottom-to-top in the stacking list
76 if (ct
< tb
&& cb
> tt
) {
77 if (cl
>= tr
&& l
< tr
&& l
>= tr
- config_resist_win
)
78 *x
= tr
, snapx
= target
;
79 else if (cr
<= tl
&& r
> tl
&&
80 r
<= tl
+ config_resist_win
)
81 *x
= tl
- w
+ 1, snapx
= target
;
83 /* try to corner snap to the window */
84 if (ct
> tt
&& t
<= tt
&&
85 t
> tt
- config_resist_win
)
86 *y
= tt
+ 1, snapy
= target
;
87 else if (cb
< tb
&& b
>= tb
&&
88 b
< tb
+ config_resist_win
)
89 *y
= tb
- h
, snapy
= target
;
94 if (cl
< tr
&& cr
> tl
) {
95 if (ct
>= tb
&& t
< tb
&& t
>= tb
- config_resist_win
)
96 *y
= tb
, snapy
= target
;
97 else if (cb
<= tt
&& b
> tt
&&
98 b
<= tt
+ config_resist_win
)
99 *y
= tt
- h
+ 1, snapy
= target
;
101 /* try to corner snap to the window */
102 if (cl
> tl
&& l
<= tl
&&
103 l
> tl
- config_resist_win
)
104 *x
= tl
+ 1, snapx
= target
;
105 else if (cr
< tr
&& r
>= tr
&&
106 r
< tr
+ config_resist_win
)
107 *x
= tr
- w
, snapx
= target
;
112 if (snapx
&& snapy
) break;
116 void resist_move_monitors(ObClient
*c
, gint
*x
, gint
*y
)
120 gint l
, t
, r
, b
; /* requested edges */
121 gint al
, at
, ar
, ab
; /* screen area edges */
122 gint pl
, pt
, pr
, pb
; /* physical screen area edges */
123 gint cl
, ct
, cr
, cb
; /* current edges */
124 gint w
, h
; /* current size */
126 w
= c
->frame
->area
.width
;
127 h
= c
->frame
->area
.height
;
134 cl
= RECT_LEFT(c
->frame
->area
);
135 ct
= RECT_TOP(c
->frame
->area
);
136 cr
= RECT_RIGHT(c
->frame
->area
);
137 cb
= RECT_BOTTOM(c
->frame
->area
);
139 if (config_resist_edge
) {
140 for (i
= 0; i
< screen_num_monitors
; ++i
) {
141 area
= screen_area_monitor(c
->desktop
, i
);
142 parea
= screen_physical_area_monitor(i
);
144 if (!RECT_INTERSECTS_RECT(*parea
, c
->frame
->area
))
147 al
= RECT_LEFT(*area
);
148 at
= RECT_TOP(*area
);
149 ar
= RECT_RIGHT(*area
);
150 ab
= RECT_BOTTOM(*area
);
151 pl
= RECT_LEFT(*parea
);
152 pt
= RECT_TOP(*parea
);
153 pr
= RECT_RIGHT(*parea
);
154 pb
= RECT_BOTTOM(*parea
);
156 if (cl
>= al
&& l
< al
&& l
>= al
- config_resist_edge
)
158 else if (cr
<= ar
&& r
> ar
&& r
<= ar
+ config_resist_edge
)
160 else if (cl
>= pl
&& l
< pl
&& l
>= pl
- config_resist_edge
)
162 else if (cr
<= pr
&& r
> pr
&& r
<= pr
+ config_resist_edge
)
165 if (ct
>= at
&& t
< at
&& t
>= at
- config_resist_edge
)
167 else if (cb
<= ab
&& b
> ab
&& b
< ab
+ config_resist_edge
)
169 else if (ct
>= pt
&& t
< pt
&& t
>= pt
- config_resist_edge
)
171 else if (cb
<= pb
&& b
> pb
&& b
< pb
+ config_resist_edge
)
177 void resist_size_windows(ObClient
*c
, gint
*w
, gint
*h
, ObCorner corn
)
180 ObClient
*target
; /* target */
181 gint l
, t
, r
, b
; /* my left, top, right and bottom sides */
182 gint dlt
, drb
; /* my destination left/top and right/bottom sides */
183 gint tl
, tt
, tr
, tb
; /* target's left, top, right and bottom bottom sides*/
185 ObClient
*snapx
= NULL
, *snapy
= NULL
;
187 incw
= c
->size_inc
.width
;
188 inch
= c
->size_inc
.height
;
190 l
= RECT_LEFT(c
->frame
->area
);
191 r
= RECT_RIGHT(c
->frame
->area
);
192 t
= RECT_TOP(c
->frame
->area
);
193 b
= RECT_BOTTOM(c
->frame
->area
);
195 if (config_resist_win
) {
196 for (it
= stacking_list
; it
; it
= g_list_next(it
)) {
197 if (!WINDOW_IS_CLIENT(it
->data
))
201 /* don't snap to invisibles or ourself */
202 if (!target
->frame
->visible
|| target
== c
) continue;
204 /* don't snap to windows in layers beneath */
205 if(target
->layer
< c
->layer
&& !config_resist_layers_below
)
208 tl
= RECT_LEFT(target
->frame
->area
);
209 tr
= RECT_RIGHT(target
->frame
->area
);
210 tt
= RECT_TOP(target
->frame
->area
);
211 tb
= RECT_BOTTOM(target
->frame
->area
);
214 /* horizontal snapping */
215 if (t
< tb
&& b
> tt
) {
217 case OB_CORNER_TOPLEFT
:
218 case OB_CORNER_BOTTOMLEFT
:
220 drb
= r
+ *w
- c
->frame
->area
.width
;
221 if (r
< tl
&& drb
>= tl
&&
222 drb
< tl
+ config_resist_win
)
223 *w
= tl
- l
, snapx
= target
;
225 case OB_CORNER_TOPRIGHT
:
226 case OB_CORNER_BOTTOMRIGHT
:
227 dlt
= l
- *w
+ c
->frame
->area
.width
;
229 if (l
> tr
&& dlt
<= tr
&&
230 dlt
> tr
- config_resist_win
)
231 *w
= r
- tr
, snapx
= target
;
238 /* vertical snapping */
239 if (l
< tr
&& r
> tl
) {
241 case OB_CORNER_TOPLEFT
:
242 case OB_CORNER_TOPRIGHT
:
244 drb
= b
+ *h
- c
->frame
->area
.height
;
245 if (b
< tt
&& drb
>= tt
&&
246 drb
< tt
+ config_resist_win
)
247 *h
= tt
- t
, snapy
= target
;
249 case OB_CORNER_BOTTOMLEFT
:
250 case OB_CORNER_BOTTOMRIGHT
:
251 dlt
= t
- *h
+ c
->frame
->area
.height
;
253 if (t
> tb
&& dlt
<= tb
&&
254 dlt
> tb
- config_resist_win
)
255 *h
= b
- tb
, snapy
= target
;
261 /* snapped both ways */
262 if (snapx
&& snapy
) break;
267 void resist_size_monitors(ObClient
*c
, gint
*w
, gint
*h
, ObCorner corn
)
269 gint l
, t
, r
, b
; /* my left, top, right and bottom sides */
270 gint dlt
, drb
; /* my destination left/top and right/bottom sides */
272 gint al
, at
, ar
, ab
; /* screen boundaries */
273 gint pl
, pt
, pr
, pb
; /* physical screen boundaries */
277 l
= RECT_LEFT(c
->frame
->area
);
278 r
= RECT_RIGHT(c
->frame
->area
);
279 t
= RECT_TOP(c
->frame
->area
);
280 b
= RECT_BOTTOM(c
->frame
->area
);
282 incw
= c
->size_inc
.width
;
283 inch
= c
->size_inc
.height
;
285 for (i
= 0; i
< screen_num_monitors
; ++i
) {
286 area
= screen_area_monitor(c
->desktop
, i
);
287 parea
= screen_physical_area_monitor(i
);
289 if (!RECT_INTERSECTS_RECT(*parea
, c
->frame
->area
))
292 /* get the screen boundaries */
293 al
= RECT_LEFT(*area
);
294 at
= RECT_TOP(*area
);
295 ar
= RECT_RIGHT(*area
);
296 ab
= RECT_BOTTOM(*area
);
297 pl
= RECT_LEFT(*parea
);
298 pt
= RECT_TOP(*parea
);
299 pr
= RECT_RIGHT(*parea
);
300 pb
= RECT_BOTTOM(*parea
);
302 if (config_resist_edge
) {
303 /* horizontal snapping */
305 case OB_CORNER_TOPLEFT
:
306 case OB_CORNER_BOTTOMLEFT
:
308 drb
= r
+ *w
- c
->frame
->area
.width
;
309 if (r
<= ar
&& drb
> ar
&& drb
<= ar
+ config_resist_edge
)
311 else if (r
<= pr
&& drb
> pr
&& drb
<= pr
+ config_resist_edge
)
314 case OB_CORNER_TOPRIGHT
:
315 case OB_CORNER_BOTTOMRIGHT
:
316 dlt
= l
- *w
+ c
->frame
->area
.width
;
318 if (l
>= al
&& dlt
< al
&& dlt
>= al
- config_resist_edge
)
320 else if (l
>= pl
&& dlt
< pl
&& dlt
>= pl
- config_resist_edge
)
325 /* vertical snapping */
327 case OB_CORNER_TOPLEFT
:
328 case OB_CORNER_TOPRIGHT
:
330 drb
= b
+ *h
- c
->frame
->area
.height
;
331 if (b
<= ab
&& drb
> ab
&& drb
<= ab
+ config_resist_edge
)
333 else if (b
<= pb
&& drb
> pb
&& drb
<= pb
+ config_resist_edge
)
336 case OB_CORNER_BOTTOMLEFT
:
337 case OB_CORNER_BOTTOMRIGHT
:
338 dlt
= t
- *h
+ c
->frame
->area
.height
;
340 if (t
>= at
&& dlt
< at
&& dlt
>= at
- config_resist_edge
)
342 else if (t
>= pt
&& dlt
< pt
&& dlt
>= pt
- config_resist_edge
)