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>
32 extern AwesomeConf globalconf
;
35 detach_tagclientlink(TagClientLink
*tc
)
39 if(globalconf
.tclink
== tc
)
40 globalconf
.tclink
= tc
->next
;
43 for(tmp
= globalconf
.tclink
; tmp
&& tmp
->next
!= tc
; tmp
= tmp
->next
);
51 tag_client(Client
*c
, Tag
*t
)
53 TagClientLink
*tc
, *new_tc
;
56 if(is_client_tagged(c
, t
))
59 new_tc
= p_new(TagClientLink
, 1);
61 if(!globalconf
.tclink
)
62 globalconf
.tclink
= new_tc
;
65 for(tc
= globalconf
.tclink
; tc
->next
; tc
= tc
->next
);
74 untag_client(Client
*c
, Tag
*t
)
78 for(tc
= globalconf
.tclink
; tc
; tc
= tc
->next
)
79 if(tc
->client
== c
&& tc
->tag
== t
)
81 detach_tagclientlink(tc
);
87 is_client_tagged(Client
*c
, Tag
*t
)
94 for(tc
= globalconf
.tclink
; tc
; tc
= tc
->next
)
95 if(tc
->client
== c
&& tc
->tag
== t
)
102 tag_client_with_current_selected(Client
*c
)
105 VirtScreen vscreen
= globalconf
.screens
[c
->screen
];
107 for(tag
= vscreen
.tags
; tag
; tag
= tag
->next
)
111 untag_client(c
, tag
);
115 tag_client_with_rules(Client
*c
)
119 Bool matched
= False
;
121 for(r
= globalconf
.rules
; r
; r
= r
->next
)
122 if(client_match_rule(c
, r
))
124 c
->isfloating
= r
->isfloating
;
126 if(r
->screen
!= RULE_NOSCREEN
&& r
->screen
!= c
->screen
)
127 move_client_to_screen(c
, r
->screen
, True
);
129 for(tag
= globalconf
.screens
[c
->screen
].tags
; tag
; tag
= tag
->next
)
130 if(is_tag_match_rules(tag
, r
))
136 untag_client(c
, tag
);
139 tag_client_with_current_selected(c
);
146 get_current_tags(int screen
)
148 Tag
*tag
, **tags
= NULL
;
151 tags
= p_new(Tag
*, n
);
152 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
155 p_realloc(&tags
, ++n
);
159 /* finish with null */
165 /** Tag selected window with tag
166 * \param screen Screen ID
167 * \param arg Tag name
168 * \ingroup ui_callback
171 uicb_client_tag(int screen
, char *arg
)
174 Tag
*tag
, *target_tag
;
175 Client
*sel
= globalconf
.focus
->client
;
182 tag_id
= atoi(arg
) - 1;
185 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& tag_id
> 0;
186 target_tag
= target_tag
->next
, tag_id
--);
189 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
190 untag_client(sel
, tag
);
191 tag_client(sel
, target_tag
);
196 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
197 tag_client(sel
, tag
);
199 client_saveprops(sel
);
203 /** Toggle floating state of a client
204 * \param screen Screen ID
206 * \ingroup ui_callback
209 uicb_client_togglefloating(int screen
, char *arg
__attribute__ ((unused
)))
211 Client
*sel
= globalconf
.focus
->client
;
216 sel
->isfloating
= !sel
->isfloating
;
219 client_resize(sel
, sel
->f_geometry
.x
, sel
->f_geometry
.y
,
220 sel
->f_geometry
.width
, sel
->f_geometry
.height
, True
, False
);
222 client_resize(sel
, sel
->geometry
.x
, sel
->geometry
.y
,
223 sel
->geometry
.width
, sel
->geometry
.height
, True
, True
);
225 client_saveprops(sel
);
229 /** Toggle a tag on client
230 * \param screen Screen ID
231 * \param arg Tag name
232 * \ingroup ui_callback
235 uicb_client_toggletag(int screen
, char *arg
)
237 Client
*sel
= globalconf
.focus
->client
;
239 Tag
*tag
, *target_tag
;
247 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
248 target_tag
= target_tag
->next
, i
--);
251 if(is_client_tagged(sel
, target_tag
))
252 untag_client(sel
, target_tag
);
254 tag_client(sel
, target_tag
);
257 /* check that there's at least one tag selected for this client*/
258 for(tag
= globalconf
.screens
[screen
].tags
; tag
259 && !is_client_tagged(sel
, tag
); tag
= tag
->next
)
262 tag_client(sel
, target_tag
);
265 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
266 if(is_client_tagged(sel
, tag
))
267 tag_client(sel
, tag
);
269 untag_client(sel
, tag
);
271 client_saveprops(sel
);
275 /** Add a tag to viewed tags
276 * \param screen Screen ID
277 * \param arg Tag name
278 * \ingroup ui_callback
281 uicb_tag_toggleview(int screen
, char *arg
)
284 Tag
*tag
, *target_tag
;
289 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
290 target_tag
= target_tag
->next
, i
--);
293 target_tag
->selected
= !target_tag
->selected
;
295 /* check that there's at least one tag selected */
296 for(tag
= globalconf
.screens
[screen
].tags
; tag
&& !tag
->selected
; tag
= tag
->next
);
298 target_tag
->selected
= True
;
301 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
302 tag
->selected
= !tag
->selected
;
304 saveawesomeprops(screen
);
306 ewmh_update_net_current_desktop(get_phys_screen(screen
));
310 tag_view(int screen
, int dindex
)
312 Tag
*target_tag
, *tag
;
317 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& dindex
> 0;
318 target_tag
= target_tag
->next
, dindex
--);
321 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
322 tag
->selected
= False
;
323 target_tag
->selected
= True
;
325 saveawesomeprops(screen
);
327 ewmh_update_net_current_desktop(get_phys_screen(screen
));
331 * \param screen Screen ID
332 * \param arg tag to view
333 * \ingroup ui_callback
336 uicb_tag_view(int screen
, char *arg
)
341 tag_view(screen
, atoi(arg
) - 1);
344 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
345 tag
->selected
= True
;
346 saveawesomeprops(screen
);
348 ewmh_update_net_current_desktop(get_phys_screen(screen
));
352 /** View previously selected tags
353 * \param screen Screen ID
355 * \ingroup ui_callback
358 uicb_tag_prev_selected(int screen
, char *arg
__attribute__ ((unused
)))
363 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
366 tag
->selected
= tag
->was_selected
;
367 tag
->was_selected
= t
;
370 ewmh_update_net_current_desktop(get_phys_screen(screen
));
374 * \param screen Screen ID
376 * \ingroup ui_callback
379 uicb_tag_viewnext(int screen
, char *arg
__attribute__ ((unused
)))
381 Tag
**curtags
= get_current_tags(screen
);
383 if(!curtags
[0]->next
)
386 curtags
[0]->selected
= False
;
387 curtags
[0]->next
->selected
= True
;
391 saveawesomeprops(screen
);
393 ewmh_update_net_current_desktop(get_phys_screen(screen
));
396 /** View previous tag
397 * \param screen Screen ID
399 * \ingroup ui_callback
402 uicb_tag_viewprev(int screen
, char *arg
__attribute__ ((unused
)))
404 Tag
*tag
, **curtags
= get_current_tags(screen
);
406 for(tag
= globalconf
.screens
[screen
].tags
; tag
&& tag
->next
!= curtags
[0]; tag
= tag
->next
);
409 tag
->selected
= True
;
410 curtags
[0]->selected
= False
;
411 saveawesomeprops(screen
);
415 ewmh_update_net_current_desktop(get_phys_screen(screen
));
419 uicb_tag_create(int screen
, char *arg
)
426 for(last_tag
= globalconf
.screens
[screen
].tags
; last_tag
&& last_tag
->next
; last_tag
= last_tag
->next
);
427 last_tag
->next
= tag
= p_new(Tag
, 1);
428 tag
->name
= a_strdup(arg
);
429 tag
->layout
= globalconf
.screens
[screen
].layouts
;
435 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80