fix some cache flags
[awesome.git] / tag.c
blobc9db0c26890e8184cfbc80065d6548ab453ef1f1
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"
31 #include "widget.h"
33 extern AwesomeConf globalconf;
35 static void
36 detach_tagclientlink(TagClientLink *tc)
38 TagClientLink *tmp;
40 if(globalconf.tclink == tc)
41 globalconf.tclink = tc->next;
42 else
44 for(tmp = globalconf.tclink; tmp && tmp->next != tc; tmp = tmp->next);
45 tmp->next = tc->next;
48 p_delete(&tc);
51 void
52 tag_client(Client *c, Tag *t)
54 TagClientLink *tc, *new_tc;
56 /* don't tag twice */
57 if(is_client_tagged(c, t))
58 return;
60 new_tc = p_new(TagClientLink, 1);
62 if(!globalconf.tclink)
63 globalconf.tclink = new_tc;
64 else
66 for(tc = globalconf.tclink; tc->next; tc = tc->next);
67 tc->next = new_tc;
70 new_tc->client = c;
71 new_tc->tag = t;
73 widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
76 void
77 untag_client(Client *c, Tag *t)
79 TagClientLink *tc;
81 for(tc = globalconf.tclink; tc; tc = tc->next)
82 if(tc->client == c && tc->tag == t)
84 detach_tagclientlink(tc);
85 break;
88 widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
91 Bool
92 is_client_tagged(Client *c, Tag *t)
94 TagClientLink *tc;
96 if(!c)
97 return False;
99 for(tc = globalconf.tclink; tc; tc = tc->next)
100 if(tc->client == c && tc->tag == t)
101 return True;
103 return False;
106 void
107 tag_client_with_current_selected(Client *c)
109 Tag *tag;
110 VirtScreen vscreen = globalconf.screens[c->screen];
112 for(tag = vscreen.tags; tag; tag = tag->next)
113 if(tag->selected)
114 tag_client(c, tag);
115 else
116 untag_client(c, tag);
119 void
120 tag_client_with_rules(Client *c)
122 Rule *r;
123 Tag *tag;
124 Bool matched = False;
126 for(r = globalconf.rules; r; r = r->next)
127 if(client_match_rule(c, r))
129 switch(r->isfloating)
131 case Tile:
132 c->isfloating = False;
133 break;
134 case Float:
135 c->isfloating = True;
136 break;
137 default:
138 break;
141 if(r->screen != RULE_NOSCREEN && r->screen != c->screen)
142 move_client_to_screen(c, r->screen, True);
144 for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next)
145 if(is_tag_match_rules(tag, r))
147 matched = True;
148 tag_client(c, tag);
150 else
151 untag_client(c, tag);
153 if(!matched)
154 tag_client_with_current_selected(c);
155 break;
160 Tag **
161 get_current_tags(int screen)
163 Tag *tag, **tags = NULL;
164 int n = 1;
166 tags = p_new(Tag *, n);
167 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
168 if(tag->selected)
170 p_realloc(&tags, ++n);
171 tags[n - 2] = tag;
174 /* finish with null */
175 tags[n - 1] = NULL;
177 return tags;
180 /** Tag selected window with tag
181 * \param screen Screen ID
182 * \param arg Tag name
183 * \ingroup ui_callback
185 void
186 uicb_client_tag(int screen, char *arg)
188 int tag_id = -1;
189 Tag *tag, *target_tag;
190 Client *sel = globalconf.focus->client;
192 if(!sel)
193 return;
195 if(arg)
197 tag_id = atoi(arg) - 1;
198 if(tag_id != -1)
200 for(target_tag = globalconf.screens[screen].tags; target_tag && tag_id > 0;
201 target_tag = target_tag->next, tag_id--);
202 if(target_tag)
204 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
205 untag_client(sel, tag);
206 tag_client(sel, target_tag);
210 else
211 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
212 tag_client(sel, tag);
214 client_saveprops(sel);
215 arrange(screen);
218 /** Toggle a tag on client
219 * \param screen Screen ID
220 * \param arg Tag name
221 * \ingroup ui_callback
223 void
224 uicb_client_toggletag(int screen, char *arg)
226 Client *sel = globalconf.focus->client;
227 int i;
228 Tag *tag, *target_tag;
230 if(!sel)
231 return;
233 if(arg)
235 i = atoi(arg) - 1;
236 for(target_tag = globalconf.screens[screen].tags; target_tag && i > 0;
237 target_tag = target_tag->next, i--);
238 if(target_tag)
240 if(is_client_tagged(sel, target_tag))
241 untag_client(sel, target_tag);
242 else
243 tag_client(sel, target_tag);
246 /* check that there's at least one tag selected for this client*/
247 for(tag = globalconf.screens[screen].tags; tag
248 && !is_client_tagged(sel, tag); tag = tag->next)
250 if(!tag)
251 tag_client(sel, target_tag);
253 else
254 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
255 if(is_client_tagged(sel, tag))
256 tag_client(sel, tag);
257 else
258 untag_client(sel, tag);
260 client_saveprops(sel);
261 arrange(screen);
264 /** Add a tag to viewed tags
265 * \param screen Screen ID
266 * \param arg Tag name
267 * \ingroup ui_callback
269 void
270 uicb_tag_toggleview(int screen, char *arg)
272 int i;
273 Tag *tag, *target_tag;
275 if(arg)
277 i = atoi(arg) - 1;
278 for(target_tag = globalconf.screens[screen].tags; target_tag && i > 0;
279 target_tag = target_tag->next, i--);
281 if(target_tag)
282 target_tag->selected = !target_tag->selected;
284 /* check that there's at least one tag selected */
285 for(tag = globalconf.screens[screen].tags; tag && !tag->selected; tag = tag->next);
286 if(!tag)
287 target_tag->selected = True;
289 else
290 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
291 tag->selected = !tag->selected;
293 saveawesomeprops(screen);
294 arrange(screen);
295 ewmh_update_net_current_desktop(get_phys_screen(screen));
298 void
299 tag_view(int screen, int dindex)
301 Tag *target_tag, *tag;
303 if(dindex < 0)
304 return;
306 for(target_tag = globalconf.screens[screen].tags; target_tag && dindex > 0;
307 target_tag = target_tag->next, dindex--);
308 if(target_tag)
310 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
311 tag->selected = False;
312 target_tag->selected = True;
314 saveawesomeprops(screen);
315 arrange(screen);
316 ewmh_update_net_current_desktop(get_phys_screen(screen));
319 /** View tag
320 * \param screen Screen ID
321 * \param arg tag to view
322 * \ingroup ui_callback
324 void
325 uicb_tag_view(int screen, char *arg)
327 Tag *tag;
329 if(arg)
330 tag_view(screen, atoi(arg) - 1);
331 else
333 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
334 tag->selected = True;
335 saveawesomeprops(screen);
336 arrange(screen);
337 ewmh_update_net_current_desktop(get_phys_screen(screen));
341 /** View previously selected tags
342 * \param screen Screen ID
343 * \param arg unused
344 * \ingroup ui_callback
346 void
347 uicb_tag_prev_selected(int screen, char *arg __attribute__ ((unused)))
349 Tag *tag;
350 Bool t;
352 for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
354 t = tag->selected;
355 tag->selected = tag->was_selected;
356 tag->was_selected = t;
358 arrange(screen);
359 ewmh_update_net_current_desktop(get_phys_screen(screen));
362 /** View next tag
363 * \param screen Screen ID
364 * \param arg unused
365 * \ingroup ui_callback
367 void
368 uicb_tag_viewnext(int screen, char *arg __attribute__ ((unused)))
370 Tag **curtags = get_current_tags(screen);
372 if(!curtags[0]->next)
373 return;
375 curtags[0]->selected = False;
376 curtags[0]->next->selected = True;
378 p_delete(&curtags);
380 saveawesomeprops(screen);
381 arrange(screen);
382 ewmh_update_net_current_desktop(get_phys_screen(screen));
385 /** View previous tag
386 * \param screen Screen ID
387 * \param arg unused
388 * \ingroup ui_callback
390 void
391 uicb_tag_viewprev(int screen, char *arg __attribute__ ((unused)))
393 Tag *tag, **curtags = get_current_tags(screen);
395 for(tag = globalconf.screens[screen].tags; tag && tag->next != curtags[0]; tag = tag->next);
396 if(tag)
398 tag->selected = True;
399 curtags[0]->selected = False;
400 saveawesomeprops(screen);
401 arrange(screen);
403 p_delete(&curtags);
404 ewmh_update_net_current_desktop(get_phys_screen(screen));
407 void
408 uicb_tag_create(int screen, char *arg)
410 Tag *last_tag, *tag;
412 if(!a_strlen(arg))
413 return;
415 for(last_tag = globalconf.screens[screen].tags; last_tag && last_tag->next; last_tag = last_tag->next);
416 last_tag->next = tag = p_new(Tag, 1);
417 tag->name = a_strdup(arg);
418 tag->layout = globalconf.screens[screen].layouts;
419 tag->mwfact = 0.5;
420 tag->nmaster = 1;
421 tag->ncol = 1;
424 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80