cosmetic
[awesome.git] / tag.c
blob9fce6c956da420a74f9533b0a1593ed9881be821
1 /*
2 * tag.c - tag management
4 * Copyright © 2007 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include <stdio.h>
23 #include <X11/Xutil.h>
25 #include "screen.h"
26 #include "tag.h"
27 #include "util.h"
28 #include "rules.h"
29 #include "client.h"
30 #include "ewmh.h"
32 extern AwesomeConf globalconf;
34 static void
35 detach_tagclientlink(TagClientLink *tc)
37 TagClientLink *tmp;
39 if(globalconf.tclink == tc)
40 globalconf.tclink = tc->next;
41 else
43 for(tmp = globalconf.tclink; tmp && tmp->next != tc; tmp = tmp->next);
44 tmp->next = tc->next;
47 p_delete(&tc);
50 void
51 tag_client(Client *c, Tag *t)
53 TagClientLink *tc, *new_tc;
55 /* don't tag twice */
56 if(is_client_tagged(c, t))
57 return;
59 new_tc = p_new(TagClientLink, 1);
61 if(!globalconf.tclink)
62 globalconf.tclink = new_tc;
63 else
65 for(tc = globalconf.tclink; tc->next; tc = tc->next);
66 tc->next = new_tc;
69 new_tc->client = c;
70 new_tc->tag = t;
73 void
74 untag_client(Client *c, Tag *t)
76 TagClientLink *tc;
78 for(tc = globalconf.tclink; tc; tc = tc->next)
79 if(tc->client == c && tc->tag == t)
80 detach_tagclientlink(tc);
83 Bool
84 is_client_tagged(Client *c, Tag *t)
86 TagClientLink *tc;
88 if(!c)
89 return False;
91 for(tc = globalconf.tclink; tc; tc = tc->next)
92 if(tc->client == c && tc->tag == t)
93 return True;
95 return False;
98 void
99 tag_client_with_current_selected(Client *c)
101 Tag *tag;
102 VirtScreen vscreen = globalconf.screens[c->screen];
104 for(tag = vscreen.tags; tag; tag = tag->next)
105 if(tag->selected)
106 tag_client(c, tag);
107 else
108 untag_client(c, tag);
111 void
112 tag_client_with_rules(Client *c)
114 Rule *r;
115 Tag *tag;
116 Bool matched = False;
118 for(r = globalconf.rules; r; r = r->next)
119 if(client_match_rule(c, r))
121 c->isfloating = r->isfloating;
123 if(r->screen != RULE_NOSCREEN && r->screen != c->screen)
124 move_client_to_screen(c, r->screen, True);
126 for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next)
127 if(is_tag_match_rules(tag, r))
129 matched = True;
130 tag_client(c, tag);
132 else
133 untag_client(c, tag);
135 if(!matched)
136 tag_client_with_current_selected(c);
137 break;
142 Tag **
143 get_current_tags(int screen)
145 Tag *tag, **tags = NULL;
146 int n = 1;
148 tags = p_new(Tag *, n);
149 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
150 if(tag->selected)
152 p_realloc(&tags, ++n);
153 tags[n - 2] = tag;
156 /* finish with null */
157 tags[n - 1] = NULL;
159 return tags;
162 /** Tag selected window with tag
163 * \param screen Screen ID
164 * \param arg Tag name
165 * \ingroup ui_callback
167 void
168 uicb_client_tag(int screen, char *arg)
170 int tag_id = -1;
171 Tag *tag, *target_tag;
172 Client *sel = globalconf.focus->client;
174 if(!sel)
175 return;
177 if(arg)
179 tag_id = atoi(arg) - 1;
180 if(tag_id != -1)
182 for(target_tag = globalconf.screens[screen].tags; target_tag && tag_id > 0;
183 target_tag = target_tag->next, tag_id--);
184 if(target_tag)
186 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
187 untag_client(sel, tag);
188 tag_client(sel, target_tag);
192 else
193 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
194 tag_client(sel, tag);
196 client_saveprops(sel);
197 arrange(screen);
200 /** Toggle floating state of a client
201 * \param screen Screen ID
202 * \param arg unused
203 * \ingroup ui_callback
205 void
206 uicb_client_togglefloating(int screen, char *arg __attribute__ ((unused)))
208 Client *sel = globalconf.focus->client;
210 if(!sel)
211 return;
213 sel->isfloating = !sel->isfloating;
215 if (arg == NULL)
216 client_resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True, False);
217 else
218 client_resize(sel, sel->x, sel->y, sel->w, sel->h, True, True);
220 client_saveprops(sel);
221 arrange(screen);
224 /** Toggle a tag on client
225 * \param screen Screen ID
226 * \param arg Tag name
227 * \ingroup ui_callback
229 void
230 uicb_client_toggletag(int screen, char *arg)
232 Client *sel = globalconf.focus->client;
233 int i;
234 Tag *tag, *target_tag;
236 if(!sel)
237 return;
239 if(arg)
241 i = atoi(arg) - 1;
242 for(target_tag = globalconf.screens[screen].tags; target_tag && i > 0;
243 target_tag = target_tag->next, i--);
244 if(target_tag)
246 if(is_client_tagged(sel, target_tag))
247 untag_client(sel, target_tag);
248 else
249 tag_client(sel, target_tag);
252 /* check that there's at least one tag selected for this client*/
253 for(tag = globalconf.screens[screen].tags; tag
254 && !is_client_tagged(sel, tag); tag = tag->next)
256 if(!tag)
257 tag_client(sel, target_tag);
259 else
260 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
261 if(is_client_tagged(sel, tag))
262 tag_client(sel, tag);
263 else
264 untag_client(sel, tag);
266 client_saveprops(sel);
267 arrange(screen);
270 /** Add a tag to viewed tags
271 * \param screen Screen ID
272 * \param arg Tag name
273 * \ingroup ui_callback
275 void
276 uicb_tag_toggleview(int screen, char *arg)
278 int i;
279 Tag *tag, *target_tag;
281 if(arg)
283 i = atoi(arg) - 1;
284 for(target_tag = globalconf.screens[screen].tags; target_tag && i > 0;
285 target_tag = target_tag->next, i--);
287 if(target_tag)
288 target_tag->selected = !target_tag->selected;
290 /* check that there's at least one tag selected */
291 for(tag = globalconf.screens[screen].tags; tag && !tag->selected; tag = tag->next);
292 if(!tag)
293 target_tag->selected = True;
295 else
296 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
297 tag->selected = !tag->selected;
299 saveawesomeprops(screen);
300 arrange(screen);
301 ewmh_update_net_current_desktop(get_phys_screen(screen));
304 void
305 tag_view(int screen, int dindex)
307 Tag *target_tag, *tag;
309 if(dindex < 0)
310 return;
312 for(target_tag = globalconf.screens[screen].tags; target_tag && dindex > 0;
313 target_tag = target_tag->next, dindex--);
314 if(target_tag)
316 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
317 tag->selected = False;
318 target_tag->selected = True;
320 saveawesomeprops(screen);
321 arrange(screen);
322 ewmh_update_net_current_desktop(get_phys_screen(screen));
325 /** View tag
326 * \param screen Screen ID
327 * \param arg tag to view
328 * \ingroup ui_callback
330 void
331 uicb_tag_view(int screen, char *arg)
333 Tag *tag;
335 if(arg)
336 tag_view(screen, atoi(arg) - 1);
337 else
339 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
340 tag->selected = True;
341 saveawesomeprops(screen);
342 arrange(screen);
343 ewmh_update_net_current_desktop(get_phys_screen(screen));
347 /** View previously selected tags
348 * \param screen Screen ID
349 * \param arg unused
350 * \ingroup ui_callback
352 void
353 uicb_tag_prev_selected(int screen, char *arg __attribute__ ((unused)))
355 Tag *tag;
356 Bool t;
358 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
360 t = tag->selected;
361 tag->selected = tag->was_selected;
362 tag->was_selected = t;
364 arrange(screen);
365 ewmh_update_net_current_desktop(get_phys_screen(screen));
368 /** View next tag
369 * \param screen Screen ID
370 * \param arg unused
371 * \ingroup ui_callback
373 void
374 uicb_tag_viewnext(int screen, char *arg __attribute__ ((unused)))
376 Tag **curtags = get_current_tags(screen);
378 if(!curtags[0]->next)
379 return;
381 curtags[0]->selected = False;
382 curtags[0]->next->selected = True;
384 p_delete(&curtags);
386 saveawesomeprops(screen);
387 arrange(screen);
388 ewmh_update_net_current_desktop(get_phys_screen(screen));
391 /** View previous tag
392 * \param screen Screen ID
393 * \param arg unused
394 * \ingroup ui_callback
396 void
397 uicb_tag_viewprev(int screen, char *arg __attribute__ ((unused)))
399 Tag *tag, **curtags = get_current_tags(screen);
401 for(tag = globalconf.screens[screen].tags; tag && tag->next != curtags[0]; tag = tag->next);
402 if(tag)
404 tag->selected = True;
405 curtags[0]->selected = False;
406 saveawesomeprops(screen);
407 arrange(screen);
409 p_delete(&curtags);
410 ewmh_update_net_current_desktop(get_phys_screen(screen));
413 void
414 uicb_tag_create(int screen, char *arg)
416 Tag *last_tag, *tag;
418 if(!a_strlen(arg))
419 return;
421 for(last_tag = globalconf.screens[screen].tags; last_tag && last_tag->next; last_tag = last_tag->next);
422 last_tag->next = tag = p_new(Tag, 1);
423 tag->name = a_strdup(arg);
424 tag->layout = globalconf.screens[screen].layouts;
425 tag->mwfact = 0.5;
426 tag->nmaster = 1;
427 tag->ncol = 1;
430 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80