1 /*
2  * pwm/thing.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2001.
5  *
6  * You may distribute and modify this program under the terms of either
7  * the Clarified Artistic License or the GNU GPL, version 2 or later.
8  */
9 
10 #include "common.h"
11 #include "thing.h"
12 #include "frame.h"
13 #include "clientwin.h"
14 
15 
destroy_thing(WThing * t)16 void destroy_thing(WThing *t)
17 {
18 	if(WTHING_IS(t, WTHING_FRAME))
19 		destroy_frame((WFrame*)t);
20 	else if(WTHING_IS(t, WTHING_DOCK))
21 		destroy_dock((WDock*)t);
22 	else if(WTHING_IS(t, WTHING_MENU))
23 		destroy_menu_tree((WMenu*)t);
24 	else if(WTHING_IS(t, WTHING_CLIENTWIN))
25 		unmanage_clientwin((WClientWin*)t);
26 }
27 
28 
free_thing(WThing * t)29 void free_thing(WThing *t)
30 {
31 	if(wglobal.focus_next==t)
32 		wglobal.focus_next=NULL/*(WThing*)SCREEN*/;
33 	if(wglobal.grab_holder==t)
34 		wglobal.grab_holder=NULL;
35 	free(t);
36 }
37 
38 
destroy_subthings(WThing * parent)39 void destroy_subthings(WThing *parent)
40 {
41 	WThing *t, *prev=NULL;
42 
43 	/* assert(!(parent->flags&WTHING_SUBDEST)); */
44     if (parent->flags & WTHING_SUBDEST) {
45         fprintf(stderr, __FILE__ ": %d: destroy_subthings: "
46             "parent->flags & WTHING_SUBDEST\n", __LINE__);
47         /* Do nothing - we're in some weird trouble here. */
48     } else {
49         parent->flags |= WTHING_SUBDEST;
50 
51 	/* destroy children */
52         while ((t = parent->t_children) != NULL) {
53 		assert(t!=prev);
54 		prev=t;
55 		destroy_thing(t);
56 	}
57 
58 	parent->flags&=~WTHING_SUBDEST;
59     }
60 }
61 
62 
63 /* */
64 
65 
link_thing(WThing * parent,WThing * thing)66 void link_thing(WThing *parent, WThing *thing)
67 {
68 	LINK_ITEM(parent->t_children, thing, t_next, t_prev);
69 	thing->t_parent=parent;
70 }
71 
72 
link_thing_before(WThing * before,WThing * thing)73 void link_thing_before(WThing *before, WThing *thing)
74 {
75 	WThing *parent=before->t_parent;
76 	LINK_ITEM_BEFORE(parent->t_children, before, thing, t_next, t_prev);
77 	thing->t_parent=parent;
78 }
79 
80 
unlink_thing(WThing * thing)81 void unlink_thing(WThing *thing)
82 {
83 	WThing *parent=thing->t_parent;
84 
85 	if(parent==NULL)
86 		return;
87 
88 	UNLINK_ITEM(parent->t_children, thing, t_next, t_prev);
89 }
90 
91 
92 /* */
93 
94 
get_next_thing(WThing * first,int filt)95 static WThing *get_next_thing(WThing *first, int filt)
96 {
97 	while(first!=NULL){
98 		if(filt==0 || WTHING_IS(first, filt))
99 			break;
100 		first=first->t_next;
101 	};
102 
103 	return first;
104 }
105 
106 
next_thing(WThing * first,int filt)107 WThing *next_thing(WThing *first, int filt)
108 {
109 	if(first==NULL)
110 		return NULL;
111 
112 	return get_next_thing(first->t_next, filt);
113 }
114 
get_prev_thing(WThing * first,int filt)115 static WThing *get_prev_thing(WThing *first, int filt)
116 {
117 	while(first!=NULL){
118 		if(filt==0 || WTHING_IS(first, filt))
119 			break;
120 		first=first->t_prev;
121 	};
122 
123 	return first;
124 }
125 
prev_thing(WThing * first,int filt)126 WThing *prev_thing(WThing *first, int filt)
127 {
128 	if(first==NULL)
129 		return NULL;
130 
131 	return get_prev_thing(first->t_prev, filt);
132 }
133 
subthing(WThing * parent,int filt)134 WThing *subthing(WThing *parent, int filt)
135 {
136 	if(parent==NULL)
137 		return NULL;
138 
139 	return get_next_thing(parent->t_children, filt);
140 }
141 
142 
next_clientwin(WClientWin * cwin)143 WClientWin *next_clientwin(WClientWin *cwin)
144 {
145 	return (WClientWin*)next_thing((WThing*)cwin, WTHING_CLIENTWIN);
146 }
147 
148 
prev_clientwin(WClientWin * cwin)149 WClientWin *prev_clientwin(WClientWin *cwin)
150 {
151 	return (WClientWin*)prev_thing((WThing*)cwin, WTHING_CLIENTWIN);
152 }
153 
first_clientwin(WThing * thing)154 WClientWin *first_clientwin(WThing *thing)
155 {
156 	return (WClientWin*)subthing(thing, WTHING_CLIENTWIN);
157 }
158 
159 
nth_thing(WThing * first,int num)160 WThing *nth_thing(WThing *first, int num)
161 {
162 	if(first==NULL)
163 		return NULL;
164 
165 	while(num!=0){
166 		if(num<0){
167 			num++;
168 			first=first->t_prev;
169 		}else if(num>0){
170 			num--;
171 			if(first->t_next!=NULL)
172 				first=first->t_next;
173 			else
174 				first=first->t_parent->t_children;
175 		}
176 		if(num==0)
177 			break;
178 	}
179 
180 	return first;
181 }
182 
183 
nth_subthing(WThing * parent,int num)184 WThing *nth_subthing(WThing *parent, int num)
185 {
186 	if(parent==NULL)
187 		return NULL;
188 
189 	return nth_thing(parent->t_children, num);
190 }
191 
192 
193 /* */
194 
195 
find_thing(Window win)196 WThing *find_thing(Window win)
197 {
198 	WThing *thing;
199 
200 	if(XFindContext(wglobal.dpy, win, wglobal.win_context,
201 					(XPointer*)&thing)!=0)
202 		return NULL;
203 
204 	return thing;
205 }
206 
207 
find_thing_t(Window win,int type)208 WThing *find_thing_t(Window win, int type)
209 {
210 	WThing *thing=find_thing(win);
211 
212 	if(thing==NULL || !WTHING_IS(thing, type))
213 		return NULL;
214 
215 	return thing;
216 }
217 
218 
find_clientwin(Window win)219 WClientWin *find_clientwin(Window win)
220 {
221 	return (WClientWin*)find_thing_t(win, WTHING_CLIENTWIN);
222 }
223 
224 
225 /* */
226 
227 
find_frame_of(Window win)228 WFrame *find_frame_of(Window win)
229 {
230 	WWinObj *winobj=find_winobj_of(win);
231 
232 	if(winobj==NULL || !WTHING_IS(winobj, WTHING_FRAME))
233 		return NULL;
234 
235 	return (WFrame*)winobj;
236 }
237 
238 
find_winobj_of(Window win)239 WWinObj *find_winobj_of(Window win)
240 {
241 	WThing *thing=find_thing(win);
242 
243 	if(thing==NULL)
244 		return NULL;
245 
246 	if(WTHING_IS(thing, WTHING_FRAME))
247 		return (WWinObj*)thing;
248 
249 	if(WTHING_IS(thing, WTHING_CLIENTWIN) && thing->t_parent!=NULL &&
250 	   WTHING_IS(thing->t_parent, WTHING_WINOBJ))
251 		return (WWinObj*)thing->t_parent;
252 
253 	return NULL;
254 }
255 
256 
257 /* */
258 
259 
winobj_of(WThing * thing)260 WWinObj *winobj_of(WThing *thing)
261 {
262 	if(WTHING_IS(thing, WTHING_WINOBJ))
263 		return (WWinObj*)thing;
264 
265 	if(WTHING_IS(thing, WTHING_CLIENTWIN))
266 		return (WWinObj*)CWIN_FRAME((WClientWin*)thing);
267 
268 	return NULL;
269 }
270