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>
31 #include "common/util.h"
33 extern AwesomeConf globalconf
;
36 tag_new(const char *name
, Layout
*layout
, double mwfact
, int nmaster
, int ncol
)
41 tag
->name
= a_strdup(name
);
44 tag
->nmaster
= nmaster
;
51 tag_append_to_screen(Tag
*tag
, int screen
)
54 tag_list_append(&globalconf
.screens
[screen
].tags
, tag
);
55 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
59 tag_push_to_screen(Tag
*tag
, int screen
)
62 tag_list_push(&globalconf
.screens
[screen
].tags
, tag
);
63 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
67 tag_client(Client
*c
, Tag
*t
)
69 tag_client_node_t
*tc
;
72 if(is_client_tagged(c
, t
))
75 tc
= p_new(tag_client_node_t
, 1);
78 tag_client_node_list_push(&globalconf
.tclink
, tc
);
81 widget_invalidate_cache(c
->screen
, WIDGET_CACHE_CLIENTS
);
82 globalconf
.screens
[c
->screen
].need_arrange
= True
;
86 untag_client(Client
*c
, Tag
*t
)
88 tag_client_node_t
*tc
;
90 for(tc
= globalconf
.tclink
; tc
; tc
= tc
->next
)
91 if(tc
->client
== c
&& tc
->tag
== t
)
93 tag_client_node_list_detach(&globalconf
.tclink
, tc
);
99 widget_invalidate_cache(c
->screen
, WIDGET_CACHE_CLIENTS
);
100 globalconf
.screens
[c
->screen
].need_arrange
= True
;
104 is_client_tagged(Client
*c
, Tag
*t
)
106 tag_client_node_t
*tc
;
111 for(tc
= globalconf
.tclink
; tc
; tc
= tc
->next
)
112 if(tc
->client
== c
&& tc
->tag
== t
)
119 tag_client_with_current_selected(Client
*c
)
122 VirtScreen vscreen
= globalconf
.screens
[c
->screen
];
124 for(tag
= vscreen
.tags
; tag
; tag
= tag
->next
)
128 untag_client(c
, tag
);
132 tag_client_with_rule(Client
*c
, Rule
*r
)
135 Bool matched
= False
;
139 /* check if at least one tag match */
140 for(tag
= globalconf
.screens
[c
->screen
].tags
; tag
; tag
= tag
->next
)
141 if(tag_match_rule(tag
, r
))
148 for(tag
= globalconf
.screens
[c
->screen
].tags
; tag
; tag
= tag
->next
)
149 if(tag_match_rule(tag
, r
))
152 untag_client(c
, tag
);
156 get_current_tags(int screen
)
158 Tag
*tag
, **tags
= NULL
;
161 tags
= p_new(Tag
*, n
);
162 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
165 p_realloc(&tags
, ++n
);
169 /* finish with null */
175 /** Tag selected window with tag
176 * \param screen Screen ID
177 * \param arg Tag name
178 * \ingroup ui_callback
181 uicb_client_tag(int screen
, char *arg
)
184 Tag
*tag
, *target_tag
;
185 Client
*sel
= globalconf
.focus
->client
;
192 tag_id
= atoi(arg
) - 1;
195 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& tag_id
> 0;
196 target_tag
= target_tag
->next
, tag_id
--);
199 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
200 untag_client(sel
, tag
);
201 tag_client(sel
, target_tag
);
206 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
207 tag_client(sel
, tag
);
210 /** Toggle a tag on client
211 * \param screen Screen ID
212 * \param arg Tag name
213 * \ingroup ui_callback
216 uicb_client_toggletag(int screen
, char *arg
)
218 Client
*sel
= globalconf
.focus
->client
;
220 Tag
*tag
, *target_tag
;
228 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
229 target_tag
= target_tag
->next
, i
--);
232 if(is_client_tagged(sel
, target_tag
))
233 untag_client(sel
, target_tag
);
235 tag_client(sel
, target_tag
);
238 /* check that there's at least one tag selected for this client*/
239 for(tag
= globalconf
.screens
[screen
].tags
; tag
240 && !is_client_tagged(sel
, tag
); tag
= tag
->next
)
243 tag_client(sel
, target_tag
);
246 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
247 if(is_client_tagged(sel
, tag
))
248 tag_client(sel
, tag
);
250 untag_client(sel
, tag
);
253 /** Add a tag to viewed tags
254 * \param screen Screen ID
255 * \param arg Tag name
256 * \ingroup ui_callback
259 uicb_tag_toggleview(int screen
, char *arg
)
262 Tag
*tag
, *target_tag
;
267 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
268 target_tag
= target_tag
->next
, i
--);
271 tag_view(target_tag
, !target_tag
->selected
);
273 /* check that there's at least one tag selected */
274 for(tag
= globalconf
.screens
[screen
].tags
; tag
&& !tag
->selected
; tag
= tag
->next
);
276 tag_view(target_tag
, True
);
279 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
280 tag_view(tag
, !tag
->selected
);
284 tag_view_only(Tag
*target
)
290 for(tag
= globalconf
.screens
[target
->screen
].tags
; tag
; tag
= tag
->next
)
291 tag_view(tag
, False
);
293 tag_view(target
, True
);
297 tag_view_only_byindex(int screen
, int dindex
)
304 for(tag
= globalconf
.screens
[screen
].tags
; tag
&& dindex
> 0;
305 tag
= tag
->next
, dindex
--);
310 tag_view(Tag
*tag
, Bool view
)
312 tag
->selected
= view
;
313 ewmh_update_net_current_desktop(get_phys_screen(tag
->screen
));
314 widget_invalidate_cache(tag
->screen
, WIDGET_CACHE_TAGS
);
315 saveawesomeprops(tag
->screen
);
316 globalconf
.screens
[tag
->screen
].need_arrange
= True
;
320 * \param screen Screen ID
321 * \param arg tag to view
322 * \ingroup ui_callback
325 uicb_tag_view(int screen
, char *arg
)
330 tag_view_only_byindex(screen
, atoi(arg
) - 1);
332 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
336 /** View previously selected tags
337 * \param screen Screen ID
339 * \ingroup ui_callback
342 uicb_tag_prev_selected(int screen
, char *arg
__attribute__ ((unused
)))
347 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
350 tag_view(tag
, tag
->was_selected
);
351 tag
->was_selected
= t
;
356 * \param screen Screen ID
358 * \ingroup ui_callback
361 uicb_tag_viewnext(int screen
, char *arg
__attribute__ ((unused
)))
363 Tag
*tag
, **curtags
= get_current_tags(screen
);
365 tag
= tag_list_next_cycle(&globalconf
.screens
[screen
].tags
, curtags
[0]);
367 tag_view(curtags
[0], False
);
373 /** View previous tag
374 * \param screen Screen ID
376 * \ingroup ui_callback
379 uicb_tag_viewprev(int screen
, char *arg
__attribute__ ((unused
)))
381 Tag
*tag
, **curtags
= get_current_tags(screen
);
383 tag
= tag_list_prev_cycle(&globalconf
.screens
[screen
].tags
, curtags
[0]);
385 tag_view(curtags
[0], False
);
392 uicb_tag_create(int screen
, char *arg
)
399 tag
= tag_new(arg
, globalconf
.screens
[screen
].layouts
, 0.5, 1, 1);
400 tag_append_to_screen(tag
, screen
);
403 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80