[uicb] uicb_client_toggletag() with NULL use as sticky toggle
[awesome.git] / widgets / taglist.c
blobe7285c55f59117e93fc925bb8dd068ee1c6ab52d
1 /*
2 * taglist.c - tag list widget
4 * Copyright © 2007 Aldo Cortesi <aldo@nullcube.com>
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 "config.h"
23 #include "client.h"
24 #include "widget.h"
25 #include "tag.h"
26 #include "event.h"
27 #include "common/util.h"
28 #include "common/configopts.h"
30 extern AwesomeConf globalconf;
32 /** Check if at least one client is tagged with tag number t and is on screen
33 * screen
34 * \param screen screen number
35 * \param t tag
36 * \return True or False
38 static Bool
39 isoccupied(Tag *t)
41 Client *c;
43 for(c = globalconf.clients; c; c = c->next)
44 if(is_client_tagged(c, t) && !c->skip && c != globalconf.scratch.client)
45 return True;
47 return False;
50 static Bool
51 isurgent(Tag *t)
53 Client *c;
55 for(c = globalconf.clients; c; c = c->next)
56 if(is_client_tagged(c, t) && c->isurgent)
57 return True;
59 return False;
62 static style_t
63 taglist_style_get(VirtScreen vscreen, Tag *tag)
65 if(tag->selected)
66 return vscreen.styles.focus;
67 else if(isurgent(tag))
68 return vscreen.styles.urgent;
70 return vscreen.styles.normal;
73 static int
74 taglist_draw(Widget *widget,
75 DrawCtx *ctx,
76 int offset,
77 int used __attribute__ ((unused)))
79 Tag *tag;
80 Client *sel = globalconf.focus->client;
81 VirtScreen vscreen = globalconf.screens[widget->statusbar->screen];
82 int w = 0, flagsize;
83 style_t style;
84 area_t area;
86 flagsize = (vscreen.styles.normal.font->height + 2) / 3;
88 widget->area.width = 0;
90 for(tag = vscreen.tags; tag; tag = tag->next)
92 style = tag->selected ? vscreen.styles.focus : vscreen.styles.normal;
93 widget->area.width += draw_textwidth(ctx->display, style.font, tag->name)
94 + style.font->height;
97 if(!widget->user_supplied_x)
98 widget->area.x = widget_calculate_offset(widget->statusbar->width,
99 widget->area.width,
100 offset,
101 widget->alignment);
103 if(!widget->user_supplied_y)
104 widget->area.y = 0;
106 widget->area.width = 0;
107 for(tag = vscreen.tags; tag; tag = tag->next)
109 style = taglist_style_get(vscreen, tag);
110 w = draw_textwidth(ctx->display, style.font, tag->name) + style.font->height;
111 area.x = widget->area.x + widget->area.width;
112 area.y = widget->area.y;
113 area.width = w;
114 area.height = widget->statusbar->height;
115 draw_text(ctx, area,
116 AlignCenter,
117 style.font->height / 2,
118 tag->name,
119 style);
121 if(isoccupied(tag))
123 area_t rectangle = { widget->area.x + widget->area.width,
124 widget->area.y,
125 flagsize,
126 flagsize,
127 NULL, NULL };
128 draw_rectangle(ctx, rectangle, 1.0, sel && is_client_tagged(sel, tag), style.fg);
130 widget->area.width += w;
133 widget->area.height = widget->statusbar->height;
134 return widget->area.width;
137 static void
138 taglist_button_press(Widget *widget, XButtonPressedEvent *ev)
140 VirtScreen vscreen = globalconf.screens[widget->statusbar->screen];
141 Button *b;
142 Tag *tag;
143 char buf[4];
144 int prev_width = 0, width = 0, i = 1;
145 style_t style;
147 for(b = widget->buttons; b; b = b->next)
148 if(ev->button == b->button && CLEANMASK(ev->state) == b->mod && b->func)
149 switch(widget->statusbar->position)
151 case Top:
152 case Bottom:
153 for(tag = vscreen.tags; tag; tag = tag->next, i++)
155 style = taglist_style_get(vscreen, tag);
156 width = draw_textwidth(globalconf.display, style.font, tag->name)
157 + style.font->height;
158 if(ev->x >= widget->area.x + prev_width
159 && ev->x < widget->area.x + prev_width + width)
161 snprintf(buf, sizeof(buf), "%d", i);
162 b->func(widget->statusbar->screen, buf);
163 return;
165 prev_width += width;
167 break;
168 case Right:
169 for(tag = vscreen.tags; tag; tag = tag->next, i++)
171 style = taglist_style_get(vscreen, tag);
172 width = draw_textwidth(globalconf.display, style.font, tag->name) + style.font->height;
173 if(ev->y >= widget->area.x + prev_width
174 && ev->y < widget->area.x + prev_width + width)
176 snprintf(buf, sizeof(buf), "%d", i);
177 b->func(widget->statusbar->screen, buf);
178 return;
180 prev_width += width;
182 break;
183 default:
184 for(tag = vscreen.tags; tag; tag = tag->next, i++)
186 style = taglist_style_get(vscreen, tag);
187 width = draw_textwidth(globalconf.display, style.font, tag->name) + style.font->height;
188 if(widget->statusbar->width - ev->y >= widget->area.x + prev_width
189 && widget->statusbar->width - ev->y < widget->area.x + prev_width + width)
191 snprintf(buf, sizeof(buf), "%d", i);
192 b->func(widget->statusbar->screen, buf);
193 return;
195 prev_width += width;
197 break;
201 Widget *
202 taglist_new(Statusbar *statusbar, cfg_t *config)
204 Widget *w;
205 w = p_new(Widget, 1);
206 widget_common_new(w, statusbar, config);
207 w->draw = taglist_draw;
208 w->button_press = taglist_button_press;
209 w->alignment = cfg_getalignment(config, "align");
211 /* Set cache property */
212 w->cache.flags = WIDGET_CACHE_TAGS | WIDGET_CACHE_CLIENTS;
214 return w;
217 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80