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.
23 #include <X11/Xutil.h>
33 extern AwesomeConf globalconf
;
36 detach_tagclientlink(TagClientLink
*tc
)
40 if(globalconf
.tclink
== tc
)
41 globalconf
.tclink
= tc
->next
;
44 for(tmp
= globalconf
.tclink
; tmp
&& tmp
->next
!= tc
; tmp
= tmp
->next
);
52 tag_client(Client
*c
, Tag
*t
)
54 TagClientLink
*tc
, *new_tc
;
57 if(is_client_tagged(c
, t
))
60 new_tc
= p_new(TagClientLink
, 1);
62 if(!globalconf
.tclink
)
63 globalconf
.tclink
= new_tc
;
66 for(tc
= globalconf
.tclink
; tc
->next
; tc
= tc
->next
);
73 widget_invalidate_cache(c
->screen
, WIDGET_CACHE_CLIENTS
);
77 untag_client(Client
*c
, Tag
*t
)
81 for(tc
= globalconf
.tclink
; tc
; tc
= tc
->next
)
82 if(tc
->client
== c
&& tc
->tag
== t
)
84 detach_tagclientlink(tc
);
88 widget_invalidate_cache(c
->screen
, WIDGET_CACHE_CLIENTS
);
92 is_client_tagged(Client
*c
, Tag
*t
)
99 for(tc
= globalconf
.tclink
; tc
; tc
= tc
->next
)
100 if(tc
->client
== c
&& tc
->tag
== t
)
107 tag_client_with_current_selected(Client
*c
)
110 VirtScreen vscreen
= globalconf
.screens
[c
->screen
];
112 for(tag
= vscreen
.tags
; tag
; tag
= tag
->next
)
116 untag_client(c
, tag
);
120 tag_client_with_rules(Client
*c
)
124 Bool matched
= False
;
126 for(r
= globalconf
.rules
; r
; r
= r
->next
)
127 if(client_match_rule(c
, r
))
129 switch(r
->isfloating
)
132 c
->isfloating
= False
;
135 c
->isfloating
= True
;
136 client_resize(c
, c
->f_geometry
, False
);
142 if(r
->screen
!= RULE_NOSCREEN
&& r
->screen
!= c
->screen
)
143 move_client_to_screen(c
, r
->screen
, True
);
145 for(tag
= globalconf
.screens
[c
->screen
].tags
; tag
; tag
= tag
->next
)
146 if(is_tag_match_rules(tag
, r
))
152 untag_client(c
, tag
);
155 tag_client_with_current_selected(c
);
162 get_current_tags(int screen
)
164 Tag
*tag
, **tags
= NULL
;
167 tags
= p_new(Tag
*, n
);
168 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
171 p_realloc(&tags
, ++n
);
175 /* finish with null */
181 /** Tag selected window with tag
182 * \param screen Screen ID
183 * \param arg Tag name
184 * \ingroup ui_callback
187 uicb_client_tag(int screen
, char *arg
)
190 Tag
*tag
, *target_tag
;
191 Client
*sel
= globalconf
.focus
->client
;
198 tag_id
= atoi(arg
) - 1;
201 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& tag_id
> 0;
202 target_tag
= target_tag
->next
, tag_id
--);
205 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
206 untag_client(sel
, tag
);
207 tag_client(sel
, target_tag
);
212 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
213 tag_client(sel
, tag
);
215 client_saveprops(sel
);
219 /** Toggle a tag on client
220 * \param screen Screen ID
221 * \param arg Tag name
222 * \ingroup ui_callback
225 uicb_client_toggletag(int screen
, char *arg
)
227 Client
*sel
= globalconf
.focus
->client
;
229 Tag
*tag
, *target_tag
;
237 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
238 target_tag
= target_tag
->next
, i
--);
241 if(is_client_tagged(sel
, target_tag
))
242 untag_client(sel
, target_tag
);
244 tag_client(sel
, target_tag
);
247 /* check that there's at least one tag selected for this client*/
248 for(tag
= globalconf
.screens
[screen
].tags
; tag
249 && !is_client_tagged(sel
, tag
); tag
= tag
->next
)
252 tag_client(sel
, target_tag
);
255 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
256 if(is_client_tagged(sel
, tag
))
257 tag_client(sel
, tag
);
259 untag_client(sel
, tag
);
261 client_saveprops(sel
);
265 /** Add a tag to viewed tags
266 * \param screen Screen ID
267 * \param arg Tag name
268 * \ingroup ui_callback
271 uicb_tag_toggleview(int screen
, char *arg
)
274 Tag
*tag
, *target_tag
;
279 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
280 target_tag
= target_tag
->next
, i
--);
283 target_tag
->selected
= !target_tag
->selected
;
285 /* check that there's at least one tag selected */
286 for(tag
= globalconf
.screens
[screen
].tags
; tag
&& !tag
->selected
; tag
= tag
->next
);
288 target_tag
->selected
= True
;
291 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
292 tag
->selected
= !tag
->selected
;
294 saveawesomeprops(screen
);
296 ewmh_update_net_current_desktop(get_phys_screen(screen
));
297 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
301 tag_view(int screen
, int dindex
)
303 Tag
*target_tag
, *tag
;
308 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& dindex
> 0;
309 target_tag
= target_tag
->next
, dindex
--);
312 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
313 tag
->selected
= False
;
314 target_tag
->selected
= True
;
316 saveawesomeprops(screen
);
318 ewmh_update_net_current_desktop(get_phys_screen(screen
));
319 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
323 * \param screen Screen ID
324 * \param arg tag to view
325 * \ingroup ui_callback
328 uicb_tag_view(int screen
, char *arg
)
333 tag_view(screen
, atoi(arg
) - 1);
336 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
337 tag
->selected
= True
;
338 saveawesomeprops(screen
);
340 ewmh_update_net_current_desktop(get_phys_screen(screen
));
341 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
345 /** View previously selected tags
346 * \param screen Screen ID
348 * \ingroup ui_callback
351 uicb_tag_prev_selected(int screen
, char *arg
__attribute__ ((unused
)))
356 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
359 tag
->selected
= tag
->was_selected
;
360 tag
->was_selected
= t
;
363 ewmh_update_net_current_desktop(get_phys_screen(screen
));
364 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
368 * \param screen Screen ID
370 * \ingroup ui_callback
373 uicb_tag_viewnext(int screen
, char *arg
__attribute__ ((unused
)))
375 Tag
**curtags
= get_current_tags(screen
);
377 if(!curtags
[0]->next
)
380 curtags
[0]->selected
= False
;
381 curtags
[0]->next
->selected
= True
;
385 saveawesomeprops(screen
);
387 ewmh_update_net_current_desktop(get_phys_screen(screen
));
388 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
391 /** View previous tag
392 * \param screen Screen ID
394 * \ingroup ui_callback
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
);
404 tag
->selected
= True
;
405 curtags
[0]->selected
= False
;
406 saveawesomeprops(screen
);
410 ewmh_update_net_current_desktop(get_phys_screen(screen
));
411 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
415 uicb_tag_create(int screen
, char *arg
)
422 for(last_tag
= globalconf
.screens
[screen
].tags
; last_tag
&& last_tag
->next
; last_tag
= last_tag
->next
);
423 last_tag
->next
= tag
= p_new(Tag
, 1);
424 tag
->name
= a_strdup(arg
);
425 tag
->layout
= globalconf
.screens
[screen
].layouts
;
429 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
432 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80