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 len
+= a_strlen(ch
.res_class
) + a_strlen(ch
.res_name
) + a_strlen(c
->name
);
72 prop
= p_new(char, len
+ 1);
75 XGetClassHint(c
->display
, c
->win
, &ch
);
76 snprintf(prop
, len
+ 1, "%s:%s:%s",
77 ch
.res_class
? ch
.res_class
: "", ch
.res_name
? ch
.res_name
: "", c
->name
);
78 for(i
= 0; i
< awesomeconf
->nrules
; i
++)
79 if(regs
[i
].propregex
&& !regexec(regs
[i
].propregex
, prop
, 1, &tmp
, 0))
81 c
->isfloating
= awesomeconf
->rules
[i
].isfloating
;
82 for(j
= 0; regs
[i
].tagregex
&& j
< awesomeconf
->ntags
; j
++)
83 if(!regexec(regs
[i
].tagregex
, awesomeconf
->tags
[j
].name
, 1, &tmp
, 0))
95 for(i
= 0; i
< awesomeconf
->ntags
; i
++)
96 c
->tags
[i
] = awesomeconf
->tags
[i
].selected
;
100 compileregs(Rule
* rules
, int nrules
)
107 regs
= p_new(Regs
, nrules
);
108 for(i
= 0; i
< nrules
; i
++)
112 reg
= p_new(regex_t
, 1);
113 if(regcomp(reg
, rules
[i
].prop
, REG_EXTENDED
))
116 regs
[i
].propregex
= reg
;
120 reg
= p_new(regex_t
, 1);
121 if(regcomp(reg
, rules
[i
].tags
, REG_EXTENDED
))
124 regs
[i
].tagregex
= reg
;
130 /** Returns True if a client is tagged
131 * with one of the tags
133 * \param tags tag to check
134 * \param ntags number of tags in *tags
135 * \return True or False
138 isvisible(Client
* c
, int screen
, Tag
* tags
, int ntags
)
142 if(c
->screen
!= screen
)
145 for(i
= 0; i
< ntags
; i
++)
146 if(c
->tags
[i
] && tags
[i
].selected
)
152 /** Tag selected window with tag
153 * \param disp Display ref
154 * \param drawcontext Drawcontext ref
155 * \param arg Tag name
156 * \ingroup ui_callback
159 uicb_tag(Display
*disp
,
161 awesome_config
*awesomeconf
,
168 for(i
= 0; i
< awesomeconf
->ntags
; i
++)
169 sel
->tags
[i
] = arg
== NULL
;
170 i
= idxoftag(arg
, awesomeconf
->tags
, awesomeconf
->ntags
);
171 if(i
>= 0 && i
< awesomeconf
->ntags
)
173 saveprops(sel
, awesomeconf
->ntags
);
174 arrange(disp
, drawcontext
, awesomeconf
);
177 /** Toggle floating state of a client
178 * \param disp Display ref
179 * \param drawcontext Drawcontext ref
181 * \ingroup ui_callback
184 uicb_togglefloating(Display
*disp
,
186 awesome_config
* awesomeconf
,
187 const char *arg
__attribute__ ((unused
)))
191 sel
->isfloating
= !sel
->isfloating
;
193 /*restore last known float dimensions*/
194 resize(sel
, sel
->rx
, sel
->ry
, sel
->rw
, sel
->rh
, True
);
197 /*save last known float dimensions*/
203 saveprops(sel
, awesomeconf
->ntags
);
204 arrange(disp
, drawcontext
, awesomeconf
);
208 * \param disp Display ref
209 * \param drawcontext Drawcontext ref
210 * \param arg Tag name
211 * \ingroup ui_callback
214 uicb_toggletag(Display
*disp
,
216 awesome_config
*awesomeconf
,
224 i
= idxoftag(arg
, awesomeconf
->tags
, awesomeconf
->ntags
);
225 sel
->tags
[i
] = !sel
->tags
[i
];
226 for(j
= 0; j
< awesomeconf
->ntags
&& !sel
->tags
[j
]; j
++);
227 if(j
== awesomeconf
->ntags
)
229 saveprops(sel
, awesomeconf
->ntags
);
230 arrange(disp
, drawcontext
, awesomeconf
);
233 /** Add a tag to viewed tags
234 * \param disp Display ref
235 * \param drawcontext Drawcontext ref
236 * \param arg Tag name
237 * \ingroup ui_callback
240 uicb_toggleview(Display
*disp
,
242 awesome_config
*awesomeconf
,
248 i
= idxoftag(arg
, awesomeconf
->tags
, awesomeconf
->ntags
);
249 awesomeconf
->tags
[i
].selected
= !awesomeconf
->tags
[i
].selected
;
250 for(j
= 0; j
< awesomeconf
->ntags
&& !awesomeconf
->tags
[j
].selected
; j
++);
251 if(j
== awesomeconf
->ntags
)
252 awesomeconf
->tags
[i
].selected
= True
;
253 saveawesomeprops(disp
, awesomeconf
);
254 arrange(disp
, drawcontext
, awesomeconf
);
258 * \param disp Display ref
259 * \param awesomeconf awesome config ref
260 * \param arg tag to view
261 * \ingroup ui_callback
264 uicb_view(Display
*disp
,
266 awesome_config
*awesomeconf
,
271 for(i
= 0; i
< awesomeconf
->ntags
; i
++)
273 awesomeconf
->tags
[i
].was_selected
= awesomeconf
->tags
[i
].selected
;
274 awesomeconf
->tags
[i
].selected
= arg
== NULL
;
276 i
= idxoftag(arg
, awesomeconf
->tags
, awesomeconf
->ntags
);
277 if(i
>= 0 && i
< awesomeconf
->ntags
)
279 awesomeconf
->tags
[i
].selected
= True
;
280 awesomeconf
->current_layout
= awesomeconf
->tags
[i
].layout
;
282 saveawesomeprops(disp
, awesomeconf
);
283 arrange(disp
, drawcontext
, awesomeconf
);
286 /** View previously selected tags
287 * \param disp Display ref
288 * \param awesomeconf awesome config ref
290 * \ingroup ui_callback
293 uicb_tag_prev_selected(Display
* disp
,
295 awesome_config
*awesomeconf
,
296 const char *arg
__attribute__ ((unused
)))
301 for(i
= 0; i
< awesomeconf
->ntags
; i
++)
303 t
= awesomeconf
->tags
[i
].selected
;
304 awesomeconf
->tags
[i
].selected
= awesomeconf
->tags
[i
].was_selected
;
305 awesomeconf
->tags
[i
].was_selected
= t
;
307 arrange(disp
, drawcontext
, awesomeconf
);
311 * \param disp Display ref
312 * \param drawcontext Drawcontext ref
314 * \ingroup ui_callback
317 uicb_tag_viewnext(Display
*disp
,
319 awesome_config
*awesomeconf
,
320 const char *arg
__attribute__ ((unused
)))
325 for(i
= 0; i
< awesomeconf
->ntags
; i
++)
327 if(firsttag
< 0 && awesomeconf
->tags
[i
].selected
)
329 awesomeconf
->tags
[i
].selected
= False
;
331 if(++firsttag
>= awesomeconf
->ntags
)
333 awesomeconf
->tags
[firsttag
].selected
= True
;
334 awesomeconf
->current_layout
= awesomeconf
->tags
[firsttag
].layout
;
335 saveawesomeprops(disp
, awesomeconf
);
336 arrange(disp
, drawcontext
, awesomeconf
);
339 /** View previous tag
340 * \param disp Display ref
341 * \param drawcontext Drawcontext ref
343 * \ingroup ui_callback
346 uicb_tag_viewprev(Display
*disp
,
348 awesome_config
*awesomeconf
,
349 const char *arg
__attribute__ ((unused
)))
354 for(i
= awesomeconf
->ntags
- 1; i
>= 0; i
--)
356 if(firsttag
< 0 && awesomeconf
->tags
[i
].selected
)
358 awesomeconf
->tags
[i
].selected
= False
;
361 firsttag
= awesomeconf
->ntags
- 1;
362 awesomeconf
->tags
[firsttag
].selected
= True
;
363 awesomeconf
->current_layout
= awesomeconf
->tags
[firsttag
].layout
;
364 saveawesomeprops(disp
, awesomeconf
);
365 arrange(disp
, drawcontext
, awesomeconf
);