bug fix: correctly check if tag is occupied by checking screen number
[awesome.git] / tag.c
blob81452bfb7d90f146a89c6bec009be67b427fcd2c
1 /*
2 * tag.c - tag management
3 *
4 * Copyright © 2007 Julien Danjou <julien@danjou.info>
5 *
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.
22 #include <stdio.h>
23 #include <X11/Xutil.h>
25 #include "layout.h"
26 #include "tag.h"
27 #include "util.h"
29 extern Client *sel; /* global client list */
31 static Regs *regs = NULL;
33 /** This function returns the index of
34 * the tag given un argument in *tags
35 * \param tag_to_find tag name
36 * \return index of tag
38 static int
39 idxoftag(const char *tag_to_find, const char **tags, int ntags)
41 int i;
43 if(!tag_to_find)
44 return 0;
46 for(i = 0; i < ntags; i++)
47 if(!strcmp(tags[i], tag_to_find))
48 return i;
50 return 0;
53 void
54 applyrules(Client * c, awesome_config *awesomeconf)
56 int i, j, len = 0;
57 regmatch_t tmp;
58 Bool matched = False;
59 XClassHint ch = { 0, 0 };
60 char *prop;
62 len += a_strlen(ch.res_class) + a_strlen(ch.res_name) + a_strlen(c->name);
64 prop = p_new(char, len + 1);
66 /* rule matching */
67 XGetClassHint(c->display, c->win, &ch);
68 snprintf(prop, len + 1, "%s:%s:%s",
69 ch.res_class ? ch.res_class : "", ch.res_name ? ch.res_name : "", c->name);
70 for(i = 0; i < awesomeconf->nrules; i++)
71 if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0))
73 c->isfloating = awesomeconf->rules[i].isfloating;
74 for(j = 0; regs[i].tagregex && j < awesomeconf->ntags; j++)
75 if(!regexec(regs[i].tagregex, awesomeconf->tags[j], 1, &tmp, 0))
77 matched = True;
78 c->tags[j] = True;
81 p_delete(&prop);
82 if(ch.res_class)
83 XFree(ch.res_class);
84 if(ch.res_name)
85 XFree(ch.res_name);
86 if(!matched)
87 for(i = 0; i < awesomeconf->ntags; i++)
88 c->tags[i] = awesomeconf->selected_tags[i];
91 void
92 compileregs(Rule * rules, int nrules)
94 int i;
95 regex_t *reg;
97 if(regs)
98 return;
99 regs = p_new(Regs, nrules);
100 for(i = 0; i < nrules; i++)
102 if(rules[i].prop)
104 reg = p_new(regex_t, 1);
105 if(regcomp(reg, rules[i].prop, REG_EXTENDED))
106 p_delete(&reg);
107 else
108 regs[i].propregex = reg;
110 if(rules[i].tags)
112 reg = p_new(regex_t, 1);
113 if(regcomp(reg, rules[i].tags, REG_EXTENDED))
114 p_delete(&reg);
115 else
116 regs[i].tagregex = reg;
122 /** Returns True if a client is tagged
123 * with one of the tags
124 * \param c Client
125 * \param tags tag to check
126 * \param ntags number of tags in *tags
127 * \return True or False
129 Bool
130 isvisible(Client * c, int screen, Bool * tags, int ntags)
132 int i;
134 for(i = 0; i < ntags; i++)
135 if(c->tags[i] && tags[i] && c->screen == screen)
136 return True;
137 return False;
141 /** Tag selected window with tag
142 * \param disp Display ref
143 * \param arg Tag name
144 * \ingroup ui_callback
146 void
147 uicb_tag(Display *disp,
148 int screen,
149 DC *drawcontext,
150 awesome_config *awesomeconf,
151 const char *arg)
153 int i;
155 if(!sel)
156 return;
157 for(i = 0; i < awesomeconf->ntags; i++)
158 sel->tags[i] = arg == NULL;
159 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
160 if(i >= 0 && i < awesomeconf->ntags)
161 sel->tags[i] = True;
162 saveprops(sel, awesomeconf->ntags);
163 arrange(disp, screen, drawcontext, awesomeconf);
166 /** Toggle floating state of a client
167 * \param disp Display ref
168 * \param arg unused
169 * \ingroup ui_callback
171 void
172 uicb_togglefloating(Display *disp,
173 int screen,
174 DC *drawcontext,
175 awesome_config * awesomeconf,
176 const char *arg __attribute__ ((unused)))
178 if(!sel)
179 return;
180 sel->isfloating = !sel->isfloating;
181 if(sel->isfloating)
182 /*restore last known float dimensions*/
183 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
184 else
186 /*save last known float dimensions*/
187 sel->rx = sel->x;
188 sel->ry = sel->y;
189 sel->rw = sel->w;
190 sel->rh = sel->h;
192 saveprops(sel, awesomeconf->ntags);
193 arrange(disp, screen, drawcontext, awesomeconf);
196 /** Toggle tag view
197 * \param disp Display ref
198 * \param arg Tag name
199 * \ingroup ui_callback
201 void
202 uicb_toggletag(Display *disp,
203 int screen,
204 DC *drawcontext,
205 awesome_config *awesomeconf,
206 const char *arg)
208 unsigned int i;
209 int j;
211 if(!sel)
212 return;
213 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
214 sel->tags[i] = !sel->tags[i];
215 for(j = 0; j < awesomeconf->ntags && !sel->tags[j]; j++);
216 if(j == awesomeconf->ntags)
217 sel->tags[i] = True;
218 saveprops(sel, awesomeconf->ntags);
219 arrange(disp, screen, drawcontext, awesomeconf);
222 /** Add a tag to viewed tags
223 * \param disp Display ref
224 * \param arg Tag name
225 * \ingroup ui_callback
227 void
228 uicb_toggleview(Display *disp,
229 int screen,
230 DC *drawcontext,
231 awesome_config *awesomeconf,
232 const char *arg)
234 unsigned int i;
235 int j;
237 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
238 awesomeconf->selected_tags[i] = !awesomeconf->selected_tags[i];
239 for(j = 0; j < awesomeconf->ntags && !awesomeconf->selected_tags[j]; j++);
240 if(j == awesomeconf->ntags)
241 awesomeconf->selected_tags[i] = True; /* cannot toggle last view */
242 saveawesomeprops(disp, screen, awesomeconf);
243 arrange(disp, screen, drawcontext, awesomeconf);
246 /** View tag
247 * \param disp Display ref
248 * \param awesomeconf awesome config ref
249 * \param arg tag to view
250 * \ingroup ui_callback
252 void
253 uicb_view(Display *disp,
254 int screen,
255 DC *drawcontext,
256 awesome_config *awesomeconf,
257 const char *arg)
259 int i;
261 for(i = 0; i < awesomeconf->ntags; i++)
263 awesomeconf->prev_selected_tags[i] = awesomeconf->selected_tags[i];
264 awesomeconf->selected_tags[i] = arg == NULL;
266 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
267 if(i >= 0 && i < awesomeconf->ntags)
269 awesomeconf->selected_tags[i] = True;
270 awesomeconf->current_layout = awesomeconf->tag_layouts[i];
272 saveawesomeprops(disp, screen, awesomeconf);
273 arrange(disp, screen, drawcontext, awesomeconf);
276 /** View previously selected tags
277 * \param disp Display ref
278 * \param awesomeconf awesome config ref
279 * \param arg unused
280 * \ingroup ui_callback
282 void
283 uicb_viewprevtags(Display * disp,
284 int screen,
285 DC *drawcontext,
286 awesome_config *awesomeconf,
287 const char *arg __attribute__ ((unused)))
289 int i;
290 Bool t;
292 for(i = 0; i < awesomeconf->ntags; i++)
294 t = awesomeconf->selected_tags[i];
295 awesomeconf->selected_tags[i] = awesomeconf->prev_selected_tags[i];
296 awesomeconf->prev_selected_tags[i] = t;
298 arrange(disp, screen, drawcontext, awesomeconf);
301 /** View next tag
302 * \param disp Display ref
303 * \param arg unused
304 * \ingroup ui_callback
306 void
307 uicb_tag_viewnext(Display *disp,
308 int screen,
309 DC * drawcontext,
310 awesome_config *awesomeconf,
311 const char *arg __attribute__ ((unused)))
313 int i;
314 int firsttag = -1;
316 for(i = 0; i < awesomeconf->ntags; i++)
318 if(firsttag < 0 && awesomeconf->selected_tags[i])
319 firsttag = i;
320 awesomeconf->selected_tags[i] = False;
322 if(++firsttag >= awesomeconf->ntags)
323 firsttag = 0;
324 awesomeconf->selected_tags[firsttag] = True;
325 saveawesomeprops(disp, screen, awesomeconf);
326 arrange(disp, screen, drawcontext, awesomeconf);
329 /** View previous tag
330 * \param disp Display ref
331 * \param arg unused
332 * \ingroup ui_callback
334 void
335 uicb_tag_viewprev(Display *disp,
336 int screen __attribute__ ((unused)),
337 DC *drawcontext,
338 awesome_config *awesomeconf,
339 const char *arg __attribute__ ((unused)))
341 int i;
342 int firsttag = -1;
344 for(i = awesomeconf->ntags - 1; i >= 0; i--)
346 if(firsttag < 0 && awesomeconf->selected_tags[i])
347 firsttag = i;
348 awesomeconf->selected_tags[i] = False;
350 if(--firsttag < 0)
351 firsttag = awesomeconf->ntags - 1;
352 awesomeconf->selected_tags[firsttag] = True;
353 saveawesomeprops(disp, screen, awesomeconf);
354 arrange(disp, screen, drawcontext, awesomeconf);