]>
Dogcows Code - chaz/openbox/blob - plugins/resistance/resistance.c
1 #include "kernel/dispatch.h"
2 #include "kernel/client.h"
3 #include "kernel/frame.h"
4 #include "kernel/stacking.h"
5 #include "kernel/screen.h"
6 #include "parser/parse.h"
7 #include "resistance.h"
10 static int win_resistance
;
11 static int edge_resistance
;
12 static gboolean resist_windows
;
14 static void parse_xml(xmlDocPtr doc
, xmlNodePtr node
, void *d
)
18 node
= node
->xmlChildrenNode
;
19 if ((n
= parse_find_node("strength", node
)))
20 win_resistance
= parse_int(doc
, n
);
21 if ((n
= parse_find_node("screen_edge_strength", node
)))
22 edge_resistance
= parse_int(doc
, n
);
23 if ((n
= parse_find_node("windows", node
)))
24 resist_windows
= parse_bool(doc
, n
);
27 void plugin_setup_config()
29 win_resistance
= edge_resistance
= DEFAULT_RESISTANCE
;
30 resist_windows
= DEFAULT_RESIST_WINDOWS
;
32 parse_register("resistance", parse_xml
, NULL
);
35 static void resist_move(ObClient
*c
, int *x
, int *y
)
40 int l
, t
, r
, b
; /* requested edges */
41 int al
, at
, ar
, ab
; /* screen area edges */
42 int cl
, ct
, cr
, cb
; /* current edges */
43 int w
, h
; /* current size */
44 ObClient
*snapx
= NULL
, *snapy
= NULL
;
46 w
= c
->frame
->area
.width
;
47 h
= c
->frame
->area
.height
;
54 cl
= c
->frame
->area
.x
;
55 ct
= c
->frame
->area
.y
;
56 cr
= cl
+ c
->frame
->area
.width
- 1;
57 cb
= ct
+ c
->frame
->area
.height
- 1;
59 /* snap to other clients */
61 for (it
= stacking_list
; it
!= NULL
; it
= it
->next
) {
63 int tl
, tt
, tr
, tb
; /* 1 past the target's edges on each side */
65 if (!WINDOW_IS_CLIENT(it
->data
))
68 /* don't snap to self or non-visibles */
69 if (!target
->frame
->visible
|| target
== c
) continue;
71 tl
= target
->frame
->area
.x
- 1;
72 tt
= target
->frame
->area
.y
- 1;
73 tr
= tl
+ target
->frame
->area
.width
+ 1;
74 tb
= tt
+ target
->frame
->area
.height
+ 1;
76 /* snapx and snapy ensure that the window snaps to the top-most
77 window edge available, without going all the way from
78 bottom-to-top in the stacking list
81 if (ct
< tb
&& cb
> tt
) {
82 if (cl
>= tr
&& l
< tr
&& l
>= tr
- win_resistance
)
83 *x
= tr
, snapx
= target
;
84 else if (cr
<= tl
&& r
> tl
&& r
<= tl
+ win_resistance
)
85 *x
= tl
- w
+ 1, snapx
= target
;
87 /* try to corner snap to the window */
88 if (ct
> tt
&& t
<= tt
&& t
> tt
- win_resistance
)
89 *y
= tt
+ 1, snapy
= target
;
90 else if (cb
< tb
&& b
>= tb
&& b
< tb
+ win_resistance
)
91 *y
= tb
- h
, snapy
= target
;
96 if (cl
< tr
&& cr
> tl
) {
97 if (ct
>= tb
&& t
< tb
&& t
>= tb
- win_resistance
)
98 *y
= tb
, snapy
= target
;
99 else if (cb
<= tt
&& b
> tt
&& b
<= tt
+ win_resistance
)
100 *y
= tt
- h
+ 1, snapy
= target
;
102 /* try to corner snap to the window */
103 if (cl
> tl
&& l
<= tl
&& l
> tl
- win_resistance
)
104 *x
= tl
+ 1, snapx
= target
;
105 else if (cr
< tr
&& r
>= tr
&& r
< tr
+ win_resistance
)
106 *x
= tr
- w
, snapx
= target
;
111 if (snapx
&& snapy
) break;
114 /* get the screen boundaries */
115 for (i
= 0; i
< screen_num_monitors
; ++i
) {
116 area
= screen_area_monitor(c
->desktop
, i
);
118 if (!RECT_INTERSECTS_RECT(*area
, c
->frame
->area
))
123 ar
= al
+ area
->width
- 1;
124 ab
= at
+ area
->height
- 1;
126 /* snap to screen edges */
127 if (cl
>= al
&& l
< al
&& l
>= al
- edge_resistance
)
129 else if (cr
<= ar
&& r
> ar
&& r
<= ar
+ edge_resistance
)
131 if (ct
>= at
&& t
< at
&& t
>= at
- edge_resistance
)
133 else if (cb
<= ab
&& b
> ab
&& b
< ab
+ edge_resistance
)
138 static void resist_size(ObClient
*c
, int *w
, int *h
, ObCorner corn
)
141 ObClient
*target
; /* target */
142 int l
, t
, r
, b
; /* my left, top, right and bottom sides */
143 int dlt
, drb
; /* my destination left/top and right/bottom sides */
144 int tl
, tt
, tr
, tb
; /* target's left, top, right and bottom bottom sides */
146 int al
, at
, ar
, ab
; /* screen boundaries */
147 ObClient
*snapx
= NULL
, *snapy
= NULL
;
149 /* don't snap windows with size increments */
150 if (c
->size_inc
.width
> 1 || c
->size_inc
.height
> 1)
153 l
= c
->frame
->area
.x
;
154 r
= l
+ c
->frame
->area
.width
- 1;
155 t
= c
->frame
->area
.y
;
156 b
= t
+ c
->frame
->area
.height
- 1;
158 /* get the screen boundaries */
159 area
= screen_area(c
->desktop
);
162 ar
= al
+ area
->width
- 1;
163 ab
= at
+ area
->height
- 1;
165 /* snap to other windows */
166 if (resist_windows
) {
167 for (it
= stacking_list
; it
!= NULL
; it
= it
->next
) {
168 if (!WINDOW_IS_CLIENT(it
->data
))
172 /* don't snap to invisibles or ourself */
173 if (!target
->frame
->visible
|| target
== c
) continue;
175 tl
= target
->frame
->area
.x
;
176 tr
= target
->frame
->area
.x
+ target
->frame
->area
.width
- 1;
177 tt
= target
->frame
->area
.y
;
178 tb
= target
->frame
->area
.y
+ target
->frame
->area
.height
- 1;
181 /* horizontal snapping */
182 if (t
< tb
&& b
> tt
) {
184 case OB_CORNER_TOPLEFT
:
185 case OB_CORNER_BOTTOMLEFT
:
187 drb
= r
+ *w
- c
->frame
->area
.width
;
188 if (r
< tl
&& drb
>= tl
&& drb
< tl
+ win_resistance
)
189 *w
= tl
- l
, snapx
= target
;
191 case OB_CORNER_TOPRIGHT
:
192 case OB_CORNER_BOTTOMRIGHT
:
193 dlt
= l
- *w
+ c
->frame
->area
.width
;
195 if (l
> tr
&& dlt
<= tr
&& dlt
> tr
- win_resistance
)
196 *w
= r
- tr
, snapx
= target
;
203 /* vertical snapping */
204 if (l
< tr
&& r
> tl
) {
206 case OB_CORNER_TOPLEFT
:
207 case OB_CORNER_TOPRIGHT
:
209 drb
= b
+ *h
- c
->frame
->area
.height
;
210 if (b
< tt
&& drb
>= tt
&& drb
< tt
+ win_resistance
)
211 *h
= tt
- t
, snapy
= target
;
213 case OB_CORNER_BOTTOMLEFT
:
214 case OB_CORNER_BOTTOMRIGHT
:
215 dlt
= t
- *h
+ c
->frame
->area
.height
;
217 if (t
> tb
&& dlt
<= tb
&& dlt
> tb
- win_resistance
)
218 *h
= b
- tb
, snapy
= target
;
224 /* snapped both ways */
225 if (snapx
&& snapy
) break;
229 /* snap to screen edges */
231 /* horizontal snapping */
233 case OB_CORNER_TOPLEFT
:
234 case OB_CORNER_BOTTOMLEFT
:
236 drb
= r
+ *w
- c
->frame
->area
.width
;
237 if (r
<= ar
&& drb
> ar
&& drb
<= ar
+ edge_resistance
)
240 case OB_CORNER_TOPRIGHT
:
241 case OB_CORNER_BOTTOMRIGHT
:
242 dlt
= l
- *w
+ c
->frame
->area
.width
;
244 if (l
>= al
&& dlt
< al
&& dlt
>= al
- edge_resistance
)
249 /* vertical snapping */
251 case OB_CORNER_TOPLEFT
:
252 case OB_CORNER_TOPRIGHT
:
254 drb
= b
+ *h
- c
->frame
->area
.height
;
255 if (b
<= ab
&& drb
> ab
&& drb
<= ab
+ edge_resistance
)
258 case OB_CORNER_BOTTOMLEFT
:
259 case OB_CORNER_BOTTOMRIGHT
:
260 dlt
= t
- *h
+ c
->frame
->area
.height
;
262 if (t
>= at
&& dlt
< at
&& dlt
>= at
- edge_resistance
)
268 static void event(ObEvent
*e
, void *foo
)
270 if (e
->type
== Event_Client_Moving
)
271 resist_move(e
->data
.c
.client
, &e
->data
.c
.num
[0], &e
->data
.c
.num
[1]);
272 else if (e
->type
== Event_Client_Resizing
)
273 resist_size(e
->data
.c
.client
, &e
->data
.c
.num
[0], &e
->data
.c
.num
[1],
277 void plugin_startup()
279 dispatch_register(Event_Client_Moving
| Event_Client_Resizing
,
280 (EventHandler
)event
, NULL
);
283 void plugin_shutdown()
285 dispatch_register(0, (EventHandler
)event
, NULL
);
This page took 0.047831 seconds and 4 git commands to generate.