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>
29 extern Client
*sel
; /* global client list */
37 static Regs
*regs
= NULL
;
39 /** This function returns the index of
40 * the tag given un argument in *tags
41 * \param tag_to_find tag name
42 * \param tags tag list
43 * \param ntags number of tags in tag list
44 * \return index of tag
47 idxoftag(const char *tag_to_find
, Tag
*tags
, int ntags
)
54 for(i
= 0; i
< ntags
; i
++)
55 if(!a_strcmp(tags
[i
].name
, tag_to_find
))
62 applyrules(Client
* c
, awesome_config
*awesomeconf
)
67 XClassHint ch
= { 0, 0 };
70 XGetClassHint(c
->display
, c
->win
, &ch
);
72 len
= a_strlen(ch
.res_class
) + a_strlen(ch
.res_name
) + a_strlen(c
->name
);
74 prop
= p_new(char, len
+ 3);
77 snprintf(prop
, len
+ 3, "%s:%s:%s",
78 ch
.res_class
? ch
.res_class
: "", ch
.res_name
? ch
.res_name
: "", c
->name
);
79 for(i
= 0; i
< awesomeconf
->nrules
; i
++)
80 if(regs
[i
].propregex
&& !regexec(regs
[i
].propregex
, prop
, 1, &tmp
, 0))
82 c
->isfloating
= awesomeconf
->rules
[i
].isfloating
;
83 for(j
= 0; regs
[i
].tagregex
&& j
< awesomeconf
->ntags
; j
++)
84 if(!regexec(regs
[i
].tagregex
, awesomeconf
->tags
[j
].name
, 1, &tmp
, 0))
98 for(i
= 0; i
< awesomeconf
->ntags
; i
++)
99 c
->tags
[i
] = awesomeconf
->tags
[i
].selected
;
103 compileregs(Rule
* rules
, int nrules
)
110 regs
= p_new(Regs
, nrules
);
111 for(i
= 0; i
< nrules
; i
++)
115 reg
= p_new(regex_t
, 1);
116 if(regcomp(reg
, rules
[i
].prop
, REG_EXTENDED
))
119 regs
[i
].propregex
= reg
;
123 reg
= p_new(regex_t
, 1);
124 if(regcomp(reg
, rules
[i
].tags
, REG_EXTENDED
))
127 regs
[i
].tagregex
= reg
;
133 /** Returns True if a client is tagged
134 * with one of the tags
136 * \param tags tag to check
137 * \param ntags number of tags in *tags
138 * \return True or False
141 isvisible(Client
* c
, int screen
, Tag
* tags
, int ntags
)
145 if(c
->screen
!= screen
)
148 for(i
= 0; i
< ntags
; i
++)
149 if(c
->tags
[i
] && tags
[i
].selected
)
155 /** Tag selected window with tag
156 * \param disp Display ref
157 * \param drawcontext Drawcontext ref
158 * \param arg Tag name
159 * \ingroup ui_callback
162 uicb_tag(Display
*disp
,
164 awesome_config
*awesomeconf
,
171 for(i
= 0; i
< awesomeconf
->ntags
; i
++)
172 sel
->tags
[i
] = arg
== NULL
;
173 i
= idxoftag(arg
, awesomeconf
->tags
, awesomeconf
->ntags
);
174 if(i
>= 0 && i
< awesomeconf
->ntags
)
176 saveprops(sel
, awesomeconf
->ntags
);
177 arrange(disp
, drawcontext
, awesomeconf
);
180 /** Toggle floating state of a client
181 * \param disp Display ref
182 * \param drawcontext Drawcontext ref
184 * \ingroup ui_callback
187 uicb_togglefloating(Display
*disp
,
189 awesome_config
* awesomeconf
,
190 const char *arg
__attribute__ ((unused
)))
194 sel
->isfloating
= !sel
->isfloating
;
196 /*restore last known float dimensions*/
197 resize(sel
, sel
->rx
, sel
->ry
, sel
->rw
, sel
->rh
, awesomeconf
, True
);
200 /*save last known float dimensions*/
206 saveprops(sel
, awesomeconf
->ntags
);
207 arrange(disp
, drawcontext
, awesomeconf
);
211 * \param disp Display ref
212 * \param drawcontext Drawcontext ref
213 * \param arg Tag name
214 * \ingroup ui_callback
217 uicb_toggletag(Display
*disp
,
219 awesome_config
*awesomeconf
,
227 i
= idxoftag(arg
, awesomeconf
->tags
, awesomeconf
->ntags
);
228 sel
->tags
[i
] = !sel
->tags
[i
];
229 for(j
= 0; j
< awesomeconf
->ntags
&& !sel
->tags
[j
]; j
++);
230 if(j
== awesomeconf
->ntags
)
232 saveprops(sel
, awesomeconf
->ntags
);
233 arrange(disp
, drawcontext
, awesomeconf
);
236 /** Add a tag to viewed tags
237 * \param disp Display ref
238 * \param drawcontext Drawcontext ref
239 * \param arg Tag name
240 * \ingroup ui_callback
243 uicb_toggleview(Display
*disp
,
245 awesome_config
*awesomeconf
,
251 i
= idxoftag(arg
, awesomeconf
->tags
, awesomeconf
->ntags
);
252 awesomeconf
->tags
[i
].selected
= !awesomeconf
->tags
[i
].selected
;
253 for(j
= 0; j
< awesomeconf
->ntags
&& !awesomeconf
->tags
[j
].selected
; j
++);
254 if(j
== awesomeconf
->ntags
)
255 awesomeconf
->tags
[i
].selected
= True
;
256 saveawesomeprops(disp
, awesomeconf
);
257 arrange(disp
, drawcontext
, awesomeconf
);
261 * \param disp Display ref
262 * \param awesomeconf awesome config ref
263 * \param arg tag to view
264 * \ingroup ui_callback
267 uicb_view(Display
*disp
,
269 awesome_config
*awesomeconf
,
274 for(i
= 0; i
< awesomeconf
->ntags
; i
++)
276 awesomeconf
->tags
[i
].was_selected
= awesomeconf
->tags
[i
].selected
;
277 awesomeconf
->tags
[i
].selected
= arg
== NULL
;
279 i
= idxoftag(arg
, awesomeconf
->tags
, awesomeconf
->ntags
);
280 if(i
>= 0 && i
< awesomeconf
->ntags
)
282 awesomeconf
->tags
[i
].selected
= True
;
283 awesomeconf
->current_layout
= awesomeconf
->tags
[i
].layout
;
285 saveawesomeprops(disp
, awesomeconf
);
286 arrange(disp
, drawcontext
, awesomeconf
);
289 /** View previously selected tags
290 * \param disp Display ref
291 * \param awesomeconf awesome config ref
293 * \ingroup ui_callback
296 uicb_tag_prev_selected(Display
* disp
,
298 awesome_config
*awesomeconf
,
299 const char *arg
__attribute__ ((unused
)))
304 for(i
= 0; i
< awesomeconf
->ntags
; i
++)
306 t
= awesomeconf
->tags
[i
].selected
;
307 awesomeconf
->tags
[i
].selected
= awesomeconf
->tags
[i
].was_selected
;
308 awesomeconf
->tags
[i
].was_selected
= t
;
310 arrange(disp
, drawcontext
, awesomeconf
);
314 * \param disp Display ref
315 * \param drawcontext Drawcontext ref
317 * \ingroup ui_callback
320 uicb_tag_viewnext(Display
*disp
,
322 awesome_config
*awesomeconf
,
323 const char *arg
__attribute__ ((unused
)))
328 for(i
= 0; i
< awesomeconf
->ntags
; i
++)
330 if(firsttag
< 0 && awesomeconf
->tags
[i
].selected
)
332 awesomeconf
->tags
[i
].selected
= False
;
334 if(++firsttag
>= awesomeconf
->ntags
)
336 awesomeconf
->tags
[firsttag
].selected
= True
;
337 awesomeconf
->current_layout
= awesomeconf
->tags
[firsttag
].layout
;
338 saveawesomeprops(disp
, awesomeconf
);
339 arrange(disp
, drawcontext
, awesomeconf
);
342 /** View previous tag
343 * \param disp Display ref
344 * \param drawcontext Drawcontext ref
346 * \ingroup ui_callback
349 uicb_tag_viewprev(Display
*disp
,
351 awesome_config
*awesomeconf
,
352 const char *arg
__attribute__ ((unused
)))
357 for(i
= awesomeconf
->ntags
- 1; i
>= 0; i
--)
359 if(firsttag
< 0 && awesomeconf
->tags
[i
].selected
)
361 awesomeconf
->tags
[i
].selected
= False
;
364 firsttag
= awesomeconf
->ntags
- 1;
365 awesomeconf
->tags
[firsttag
].selected
= True
;
366 awesomeconf
->current_layout
= awesomeconf
->tags
[firsttag
].layout
;
367 saveawesomeprops(disp
, awesomeconf
);
368 arrange(disp
, drawcontext
, awesomeconf
);