]>
Dogcows Code - chaz/openbox/blob - plugins/resistance.c
1 #include "kernel/dispatch.h"
2 #include "kernel/client.h"
3 #include "kernel/frame.h"
4 #include "kernel/parse.h"
5 #include "kernel/stacking.h"
6 #include "kernel/screen.h"
10 static gboolean resist_windows
;
12 static void parse_assign(char *name
, ParseToken
*value
)
14 if (!g_ascii_strcasecmp(name
, "strength")) {
15 if (value
->type
!= TOKEN_INTEGER
)
16 yyerror("invalid value");
18 if (value
->data
.integer
>= 0)
19 resistance
= value
->data
.integer
;
21 } else if (!g_ascii_strcasecmp(name
, "windows")) {
22 if (value
->type
!= TOKEN_BOOL
)
23 yyerror("invalid value");
25 resist_windows
= value
->data
.bool;
27 yyerror("invalid option");
28 parse_free_token(value
);
31 void plugin_setup_config()
34 resist_windows
= TRUE
;
36 parse_reg_section("resistance", NULL
, parse_assign
);
39 static void resist_move(Client
*c
, int *x
, int *y
)
43 int l
, t
, r
, b
; /* requested edges */
44 int al
, at
, ar
, ab
; /* screen area edges */
45 int cl
, ct
, cr
, cb
; /* current edges */
46 int w
, h
; /* current size */
47 Client
*snapx
= NULL
, *snapy
= NULL
;
49 w
= c
->frame
->area
.width
;
50 h
= c
->frame
->area
.height
;
57 cl
= c
->frame
->area
.x
;
58 ct
= c
->frame
->area
.y
;
59 cr
= cl
+ c
->frame
->area
.width
- 1;
60 cb
= ct
+ c
->frame
->area
.height
- 1;
62 /* snap to other clients */
64 for (it
= stacking_list
; it
!= NULL
; it
= it
->next
) {
66 int tl
, tt
, tr
, tb
; /* 1 past the target's edges on each side */
69 /* don't snap to self or non-visibles */
70 if (!target
->frame
->visible
|| target
== c
) continue;
72 tl
= target
->frame
->area
.x
- 1;
73 tt
= target
->frame
->area
.y
- 1;
74 tr
= tl
+ target
->frame
->area
.width
+ 1;
75 tb
= tt
+ target
->frame
->area
.height
+ 1;
77 /* snapx and snapy ensure that the window snaps to the top-most
78 window edge available, without going all the way from
79 bottom-to-top in the stacking list
82 if (ct
< tb
&& cb
> tt
) {
83 if (cl
>= tr
&& l
< tr
&& l
>= tr
- resistance
)
84 *x
= tr
, snapx
= target
;
85 else if (cr
<= tl
&& r
> tl
&& r
<= tl
+ resistance
)
86 *x
= tl
- w
+ 1, snapx
= target
;
88 /* try to corner snap to the window */
89 if (ct
> tt
&& t
<= tt
&& t
> tt
- resistance
)
90 *y
= tt
+ 1, snapy
= target
;
91 else if (cb
< tb
&& b
>= tb
&& b
< tb
+ resistance
)
92 *y
= tb
- h
, snapy
= target
;
97 if (cl
< tr
&& cr
> tl
) {
98 if (ct
>= tb
&& t
< tb
&& t
>= tb
- resistance
)
99 *y
= tb
, snapy
= target
;
100 else if (cb
<= tt
&& b
> tt
&& b
<= tt
+ resistance
)
101 *y
= tt
- h
+ 1, snapy
= target
;
103 /* try to corner snap to the window */
104 if (cl
> tl
&& l
<= tl
&& l
> tl
- resistance
)
105 *x
= tl
+ 1, snapx
= target
;
106 else if (cr
< tr
&& r
>= tr
&& r
< tr
+ resistance
)
107 *x
= tr
- w
, snapx
= target
;
112 if (snapx
&& snapy
) break;
115 /* get the screen boundaries */
116 area
= screen_area(c
->desktop
);
119 ar
= al
+ area
->width
- 1;
120 ab
= at
+ area
->height
- 1;
122 /* snap to screen edges */
123 if (cl
>= al
&& l
< al
&& l
>= al
- resistance
)
125 else if (cr
<= ar
&& r
> ar
&& r
<= ar
+ resistance
)
127 if (ct
>= at
&& t
< at
&& t
>= at
- resistance
)
129 else if (cb
<= ab
&& b
> ab
&& b
< ab
+ resistance
)
133 static void resist_size(Client
*c
, int *w
, int *h
, Corner corn
)
136 Client
*target
; /* target */
137 int l
, t
, r
, b
; /* my left, top, right and bottom sides */
138 int dlt
, drb
; /* my destination left/top and right/bottom sides */
139 int tl
, tt
, tr
, tb
; /* target's left, top, right and bottom bottom sides */
141 int al
, at
, ar
, ab
; /* screen boundaries */
142 Client
*snapx
= NULL
, *snapy
= NULL
;
144 /* don't snap windows with size increments */
145 if (c
->size_inc
.width
> 1 || c
->size_inc
.height
> 1)
148 l
= c
->frame
->area
.x
;
149 r
= l
+ c
->frame
->area
.width
- 1;
150 t
= c
->frame
->area
.y
;
151 b
= t
+ c
->frame
->area
.height
- 1;
153 /* get the screen boundaries */
154 area
= screen_area(c
->desktop
);
157 ar
= al
+ area
->width
- 1;
158 ab
= at
+ area
->height
- 1;
160 /* snap to other windows */
161 if (resist_windows
) {
162 for (it
= stacking_list
; it
!= NULL
; it
= it
->next
) {
165 /* don't snap to invisibles or ourself */
166 if (!target
->frame
->visible
|| target
== c
) continue;
168 tl
= target
->frame
->area
.x
;
169 tr
= target
->frame
->area
.x
+ target
->frame
->area
.width
- 1;
170 tt
= target
->frame
->area
.y
;
171 tb
= target
->frame
->area
.y
+ target
->frame
->area
.height
- 1;
174 /* horizontal snapping */
175 if (t
< tb
&& b
> tt
) {
178 case Corner_BottomLeft
:
180 drb
= r
+ *w
- c
->frame
->area
.width
;
181 if (r
< tl
&& drb
>= tl
&& drb
< tl
+ resistance
)
182 *w
= tl
- l
, snapx
= target
;
184 case Corner_TopRight
:
185 case Corner_BottomRight
:
186 dlt
= l
- *w
+ c
->frame
->area
.width
;
188 if (l
> tr
&& dlt
<= tr
&& dlt
> tr
- resistance
)
189 *w
= r
- tr
, snapx
= target
;
196 /* vertical snapping */
197 if (l
< tr
&& r
> tl
) {
200 case Corner_TopRight
:
202 drb
= b
+ *h
- c
->frame
->area
.height
;
203 if (b
< tt
&& drb
>= tt
&& drb
< tt
+ resistance
)
204 *h
= tt
- t
, snapy
= target
;
206 case Corner_BottomLeft
:
207 case Corner_BottomRight
:
208 dlt
= t
- *h
+ c
->frame
->area
.height
;
210 if (t
> tb
&& dlt
<= tb
&& dlt
> tb
- resistance
)
211 *h
= b
- tb
, snapy
= target
;
217 /* snapped both ways */
218 if (snapx
&& snapy
) break;
222 /* snap to screen edges */
224 /* horizontal snapping */
227 case Corner_BottomLeft
:
229 drb
= r
+ *w
- c
->frame
->area
.width
;
230 if (r
<= ar
&& drb
> ar
&& drb
<= ar
+ resistance
)
233 case Corner_TopRight
:
234 case Corner_BottomRight
:
235 dlt
= l
- *w
+ c
->frame
->area
.width
;
237 if (l
>= al
&& dlt
< al
&& dlt
>= al
- resistance
)
242 /* vertical snapping */
245 case Corner_TopRight
:
247 drb
= b
+ *h
- c
->frame
->area
.height
;
248 if (b
<= ab
&& drb
> ab
&& drb
<= ab
+ resistance
)
251 case Corner_BottomLeft
:
252 case Corner_BottomRight
:
253 dlt
= t
- *h
+ c
->frame
->area
.height
;
255 if (t
>= at
&& dlt
< at
&& dlt
>= at
- resistance
)
261 static void event(ObEvent
*e
, void *foo
)
263 if (e
->type
== Event_Client_Moving
)
264 resist_move(e
->data
.c
.client
, &e
->data
.c
.num
[0], &e
->data
.c
.num
[1]);
265 else if (e
->type
== Event_Client_Resizing
)
266 resist_size(e
->data
.c
.client
, &e
->data
.c
.num
[0], &e
->data
.c
.num
[1],
270 void plugin_startup()
272 dispatch_register(Event_Client_Moving
| Event_Client_Resizing
,
273 (EventHandler
)event
, NULL
);
276 void plugin_shutdown()
278 dispatch_register(0, (EventHandler
)event
, NULL
);
This page took 0.052135 seconds and 4 git commands to generate.