2 * tag.c - tag management
4 * Copyright © 2007-2008 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>
32 extern AwesomeConf globalconf
;
35 tag_new(const char *name
, Layout
*layout
, double mwfact
, int nmaster
, int ncol
)
40 tag
->name
= a_strdup(name
);
44 if(tag
->mwfact
<= 0 || tag
->mwfact
>= 1)
47 if((tag
->nmaster
= nmaster
) < 0)
50 if((tag
->ncol
= ncol
) < 1)
57 tag_append_to_screen(Tag
*tag
, int screen
)
59 int phys_screen
= screen_virttophys(screen
);
62 tag_list_append(&globalconf
.screens
[screen
].tags
, tag
);
63 ewmh_update_net_numbers_of_desktop(phys_screen
);
64 ewmh_update_net_desktop_names(phys_screen
);
65 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
69 tag_push_to_screen(Tag
*tag
, int screen
)
72 tag_list_push(&globalconf
.screens
[screen
].tags
, tag
);
73 widget_invalidate_cache(screen
, WIDGET_CACHE_TAGS
);
77 tag_client(Client
*c
, Tag
*t
)
79 tag_client_node_t
*tc
;
82 if(is_client_tagged(c
, t
))
85 tc
= p_new(tag_client_node_t
, 1);
88 tag_client_node_list_push(&globalconf
.tclink
, tc
);
91 widget_invalidate_cache(c
->screen
, WIDGET_CACHE_CLIENTS
);
92 globalconf
.screens
[c
->screen
].need_arrange
= True
;
96 untag_client(Client
*c
, Tag
*t
)
98 tag_client_node_t
*tc
;
100 for(tc
= globalconf
.tclink
; tc
; tc
= tc
->next
)
101 if(tc
->client
== c
&& tc
->tag
== t
)
103 tag_client_node_list_detach(&globalconf
.tclink
, tc
);
109 widget_invalidate_cache(c
->screen
, WIDGET_CACHE_CLIENTS
);
110 globalconf
.screens
[c
->screen
].need_arrange
= True
;
114 is_client_tagged(Client
*c
, Tag
*t
)
116 tag_client_node_t
*tc
;
121 for(tc
= globalconf
.tclink
; tc
; tc
= tc
->next
)
122 if(tc
->client
== c
&& tc
->tag
== t
)
129 tag_client_with_current_selected(Client
*c
)
132 VirtScreen vscreen
= globalconf
.screens
[c
->screen
];
134 for(tag
= vscreen
.tags
; tag
; tag
= tag
->next
)
138 untag_client(c
, tag
);
142 tag_client_with_rule(Client
*c
, Rule
*r
)
145 Bool matched
= False
;
149 /* check if at least one tag match */
150 for(tag
= globalconf
.screens
[c
->screen
].tags
; tag
; tag
= tag
->next
)
151 if(tag_match_rule(tag
, r
))
158 for(tag
= globalconf
.screens
[c
->screen
].tags
; tag
; tag
= tag
->next
)
159 if(tag_match_rule(tag
, r
))
162 untag_client(c
, tag
);
166 tags_get_current(int screen
)
168 Tag
*tag
, **tags
= NULL
;
171 tags
= p_new(Tag
*, n
);
172 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
175 p_realloc(&tags
, ++n
);
179 /* finish with null */
185 /** Tag selected window with tag
186 * \param screen Screen ID
187 * \param arg Tag name
188 * \ingroup ui_callback
191 uicb_client_tag(int screen
, char *arg
)
194 Tag
*tag
, *target_tag
;
195 Client
*sel
= globalconf
.focus
->client
;
202 tag_id
= atoi(arg
) - 1;
205 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& tag_id
> 0;
206 target_tag
= target_tag
->next
, tag_id
--);
209 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
210 untag_client(sel
, tag
);
211 tag_client(sel
, target_tag
);
216 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
217 tag_client(sel
, tag
);
220 /** Toggle a tag on client
221 * \param screen Screen ID
222 * \param arg Tag name
223 * \ingroup ui_callback
226 uicb_client_toggletag(int screen
, char *arg
)
228 Client
*sel
= globalconf
.focus
->client
;
230 Tag
*tag
, *target_tag
;
238 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
239 target_tag
= target_tag
->next
, i
--);
242 if(is_client_tagged(sel
, target_tag
))
243 untag_client(sel
, target_tag
);
245 tag_client(sel
, target_tag
);
248 /* check that there's at least one tag selected for this client*/
249 for(tag
= globalconf
.screens
[screen
].tags
; tag
250 && !is_client_tagged(sel
, tag
); tag
= tag
->next
);
253 tag_client(sel
, target_tag
);
256 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
257 if(is_client_tagged(sel
, tag
))
258 tag_client(sel
, tag
);
260 untag_client(sel
, tag
);
263 /** Add a tag to viewed tags
264 * \param screen Screen ID
265 * \param arg Tag name
266 * \ingroup ui_callback
269 uicb_tag_toggleview(int screen
, char *arg
)
272 Tag
*tag
, *target_tag
;
277 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
278 target_tag
= target_tag
->next
, i
--);
281 tag_view(target_tag
, !target_tag
->selected
);
283 /* check that there's at least one tag selected */
284 for(tag
= globalconf
.screens
[screen
].tags
; tag
&& !tag
->selected
; tag
= tag
->next
);
286 tag_view(target_tag
, True
);
289 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
290 tag_view(tag
, !tag
->selected
);
294 tag_view_only(Tag
*target
)
300 for(tag
= globalconf
.screens
[target
->screen
].tags
; tag
; tag
= tag
->next
)
301 tag_view(tag
, tag
== target
);
305 tag_view_byindex(int screen
, int dindex
, Bool view
)
312 for(tag
= globalconf
.screens
[screen
].tags
; tag
&& dindex
> 0;
313 tag
= tag
->next
, dindex
--);
318 tag_view_only_byindex(int screen
, int dindex
)
325 for(tag
= globalconf
.screens
[screen
].tags
; tag
&& dindex
> 0;
326 tag
= tag
->next
, dindex
--);
331 tag_view(Tag
*tag
, Bool view
)
333 tag
->was_selected
= tag
->selected
;
334 tag
->selected
= view
;
335 ewmh_update_net_current_desktop(screen_virttophys(tag
->screen
));
336 widget_invalidate_cache(tag
->screen
, WIDGET_CACHE_TAGS
);
337 globalconf
.screens
[tag
->screen
].need_arrange
= True
;
341 * \param screen Screen ID
342 * \param arg tag to view
343 * \ingroup ui_callback
346 uicb_tag_view(int screen
, char *arg
)
351 tag_view_only_byindex(screen
, atoi(arg
) - 1);
353 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
357 /** View previously selected tags
358 * \param screen Screen ID
360 * \ingroup ui_callback
363 uicb_tag_prev_selected(int screen
, char *arg
__attribute__ ((unused
)))
367 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
368 tag_view(tag
, tag
->was_selected
);
372 * \param screen Screen ID
374 * \ingroup ui_callback
377 uicb_tag_viewnext(int screen
, char *arg
__attribute__ ((unused
)))
379 Tag
*tag
, **curtags
= tags_get_current(screen
);
381 tag
= tag_list_next_cycle(&globalconf
.screens
[screen
].tags
, curtags
[0]);
383 tag_view(curtags
[0], False
);
389 /** View previous tag
390 * \param screen Screen ID
392 * \ingroup ui_callback
395 uicb_tag_viewprev(int screen
, char *arg
__attribute__ ((unused
)))
397 Tag
*tag
, **curtags
= tags_get_current(screen
);
399 tag
= tag_list_prev_cycle(&globalconf
.screens
[screen
].tags
, curtags
[0]);
401 tag_view(curtags
[0], False
);
408 uicb_tag_create(int screen
, char *arg
)
415 tag
= tag_new(arg
, globalconf
.screens
[screen
].layouts
, 0.5, 1, 1);
416 tag_append_to_screen(tag
, screen
);
419 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80