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(int screen
, TagClientLink
*tc
)
39 if(globalconf
.screens
[screen
].tclink
== tc
)
40 globalconf
.screens
[screen
].tclink
= tc
->next
;
43 for(tmp
= globalconf
.screens
[screen
].tclink
; tmp
&& tmp
->next
!= tc
; tmp
= tmp
->next
);
51 tag_client(Client
*c
, Tag
*t
, int screen
)
53 TagClientLink
*tc
, *new_tc
;
56 if(is_client_tagged(c
, t
, screen
))
59 new_tc
= p_new(TagClientLink
, 1);
61 if(!globalconf
.screens
[screen
].tclink
)
62 globalconf
.screens
[screen
].tclink
= new_tc
;
65 for(tc
= globalconf
.screens
[screen
].tclink
; tc
->next
; tc
= tc
->next
);
74 untag_client(Client
*c
, Tag
*t
, int screen
)
78 for(tc
= globalconf
.screens
[screen
].tclink
; tc
; tc
= tc
->next
)
79 if(tc
->client
== c
&& tc
->tag
== t
)
80 detach_tagclientlink(screen
, tc
);
84 is_client_tagged(Client
*c
, Tag
*t
, int screen
)
88 if(!c
|| c
->screen
!= screen
)
91 for(tc
= globalconf
.screens
[screen
].tclink
; tc
; tc
= tc
->next
)
92 if(tc
->client
== c
&& tc
->tag
== t
)
98 tag_client_with_current_selected(Client
*c
)
101 VirtScreen vscreen
= globalconf
.screens
[c
->screen
];
103 for(tag
= vscreen
.tags
; tag
; tag
= tag
->next
)
105 tag_client(c
, tag
, c
->screen
);
107 untag_client(c
, tag
, c
->screen
);
111 tag_client_with_rules(Client
*c
)
115 Bool matched
= False
;
117 for(r
= globalconf
.rules
; r
; r
= r
->next
)
118 if(client_match_rule(c
, r
))
120 c
->isfloating
= r
->isfloating
;
122 if(r
->screen
!= RULE_NOSCREEN
&& r
->screen
!= c
->screen
)
123 move_client_to_screen(c
, r
->screen
, True
);
125 for(tag
= globalconf
.screens
[c
->screen
].tags
; tag
; tag
= tag
->next
)
126 if(is_tag_match_rules(tag
, r
))
129 tag_client(c
, tag
, c
->screen
);
132 untag_client(c
, tag
, c
->screen
);
135 tag_client_with_current_selected(c
);
142 get_current_tags(int screen
)
144 Tag
*tag
, **tags
= NULL
;
147 tags
= p_new(Tag
*, n
);
148 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
151 p_realloc(&tags
, ++n
);
155 /* finish with null */
161 /** Tag selected window with tag
162 * \param screen Screen ID
163 * \param arg Tag name
164 * \ingroup ui_callback
167 uicb_client_tag(int screen
, char *arg
)
170 Tag
*tag
, *target_tag
;
171 Client
*sel
= globalconf
.focus
->client
;
178 tag_id
= atoi(arg
) - 1;
181 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& tag_id
> 0;
182 target_tag
= target_tag
->next
, tag_id
--);
185 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
186 untag_client(sel
, tag
, screen
);
187 tag_client(sel
, target_tag
, screen
);
192 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
193 tag_client(sel
, tag
, screen
);
195 client_saveprops(sel
, screen
);
199 /** Toggle floating state of a client
200 * \param screen Screen ID
202 * \ingroup ui_callback
205 uicb_client_togglefloating(int screen
, char *arg
__attribute__ ((unused
)))
207 Client
*sel
= globalconf
.focus
->client
;
212 sel
->isfloating
= !sel
->isfloating
;
215 client_resize(sel
, sel
->rx
, sel
->ry
, sel
->rw
, sel
->rh
, True
, False
);
217 client_resize(sel
, sel
->x
, sel
->y
, sel
->w
, sel
->h
, True
, True
);
219 client_saveprops(sel
, screen
);
223 /** Toggle a tag on client
224 * \param screen Screen ID
225 * \param arg Tag name
226 * \ingroup ui_callback
229 uicb_client_toggletag(int screen
, char *arg
)
231 Client
*sel
= globalconf
.focus
->client
;
233 Tag
*tag
, *target_tag
;
241 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
242 target_tag
= target_tag
->next
, i
--);
245 if(is_client_tagged(sel
, target_tag
, screen
))
246 untag_client(sel
, target_tag
, screen
);
248 tag_client(sel
, target_tag
, screen
);
251 /* check that there's at least one tag selected for this client*/
252 for(tag
= globalconf
.screens
[screen
].tags
; tag
253 && !is_client_tagged(sel
, tag
, screen
); tag
= tag
->next
)
256 tag_client(sel
, target_tag
, screen
);
259 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
260 if(is_client_tagged(sel
, tag
, screen
))
261 tag_client(sel
, tag
, screen
);
263 untag_client(sel
, tag
, screen
);
265 client_saveprops(sel
, screen
);
269 /** Add a tag to viewed tags
270 * \param screen Screen ID
271 * \param arg Tag name
272 * \ingroup ui_callback
275 uicb_tag_toggleview(int screen
, char *arg
)
278 Tag
*tag
, *target_tag
;
283 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
284 target_tag
= target_tag
->next
, i
--);
287 target_tag
->selected
= !target_tag
->selected
;
289 /* check that there's at least one tag selected */
290 for(tag
= globalconf
.screens
[screen
].tags
; tag
&& !tag
->selected
; tag
= tag
->next
);
292 target_tag
->selected
= True
;
295 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
296 tag
->selected
= !tag
->selected
;
298 saveawesomeprops(screen
);
300 ewmh_update_net_current_desktop(get_phys_screen(screen
));
304 * \param screen Screen ID
305 * \param arg tag to view
306 * \ingroup ui_callback
309 uicb_tag_view(int screen
, char *arg
)
312 Tag
*tag
, *target_tag
;
317 for(target_tag
= globalconf
.screens
[screen
].tags
; target_tag
&& i
> 0;
318 target_tag
= target_tag
->next
, i
--);
321 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
322 tag
->selected
= False
;
323 target_tag
->selected
= True
;
327 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
328 tag
->selected
= True
;
330 saveawesomeprops(screen
);
332 ewmh_update_net_current_desktop(get_phys_screen(screen
));
335 /** View previously selected tags
336 * \param screen Screen ID
338 * \ingroup ui_callback
341 uicb_tag_prev_selected(int screen
, char *arg
__attribute__ ((unused
)))
346 for(tag
= globalconf
.screens
[screen
].tags
; tag
; tag
= tag
->next
)
349 tag
->selected
= tag
->was_selected
;
350 tag
->was_selected
= t
;
353 ewmh_update_net_current_desktop(get_phys_screen(screen
));
357 * \param screen Screen ID
359 * \ingroup ui_callback
362 uicb_tag_viewnext(int screen
, char *arg
__attribute__ ((unused
)))
364 Tag
**curtags
= get_current_tags(screen
);
366 if(!curtags
[0]->next
)
369 curtags
[0]->selected
= False
;
370 curtags
[0]->next
->selected
= True
;
374 saveawesomeprops(screen
);
376 ewmh_update_net_current_desktop(get_phys_screen(screen
));
379 /** View previous tag
380 * \param screen Screen ID
382 * \ingroup ui_callback
385 uicb_tag_viewprev(int screen
, char *arg
__attribute__ ((unused
)))
387 Tag
*tag
, **curtags
= get_current_tags(screen
);
389 for(tag
= globalconf
.screens
[screen
].tags
; tag
&& tag
->next
!= curtags
[0]; tag
= tag
->next
);
392 tag
->selected
= True
;
393 curtags
[0]->selected
= False
;
394 saveawesomeprops(screen
);
398 ewmh_update_net_current_desktop(get_phys_screen(screen
));
400 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80