clean some tag stuff
[awesome.git] / statusbar.c
blob9ccd6947ec02eb1bc4a0cbf4c32745a73a0ec148
1 /*
2 * statusbar.c - statusbar functions
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.
22 #include <stdio.h>
23 #include <math.h>
25 #include "statusbar.h"
26 #include "screen.h"
27 #include "util.h"
28 #include "tag.h"
29 #include "widget.h"
31 extern AwesomeConf globalconf;
33 static void
34 statusbar_update_position(Statusbar *statusbar)
36 Area area = get_screen_area(statusbar->screen,
37 NULL,
38 &globalconf.screens[statusbar->screen].padding);
40 XMapRaised(globalconf.display, statusbar->window);
41 switch(statusbar->position)
43 default:
44 XMoveWindow(globalconf.display, statusbar->window,
45 area.x, area.y);
46 break;
47 case Left:
48 XMoveWindow(globalconf.display, statusbar->window,
49 area.x, (area.y + area.height) - statusbar->width);
50 break;
51 case Right:
52 XMoveWindow(globalconf.display, statusbar->window,
53 area.x + (area.width - statusbar->height), area.y);
54 break;
55 case Bottom:
56 XMoveWindow(globalconf.display, statusbar->window,
57 area.x, area.height - statusbar->height);
58 break;
59 case Off:
60 XUnmapWindow(globalconf.display, statusbar->window);
61 break;
65 static void
66 statusbar_draw(Statusbar *statusbar)
68 int phys_screen = get_phys_screen(statusbar->screen);
69 Widget *widget, *last_drawn = NULL;
70 int left = 0, right = 0;
71 Area rectangle = { 0, 0, 0, 0 };
73 /* don't waste our time */
74 if(statusbar->position == Off)
75 return;
77 XFreePixmap(globalconf.display, statusbar->drawable);
79 DrawCtx *ctx = draw_get_context(phys_screen,
80 statusbar->width,
81 statusbar->height);
83 rectangle.width = statusbar->width;
84 rectangle.height = statusbar->height;
85 draw_rectangle(ctx, rectangle, True,
86 globalconf.screens[statusbar->screen].colors_normal[ColBG]);
88 for(widget = statusbar->widgets; widget; widget = widget->next)
89 if (widget->alignment == AlignLeft)
91 widget->cache.needs_update = False;
92 left += widget->draw(widget, ctx, left, (left + right));
95 /* renders right widget from last to first */
96 for(widget = statusbar->widgets; widget; widget = widget->next)
97 if (widget->alignment == AlignRight && last_drawn == widget->next)
99 widget->cache.needs_update = False;
100 right += widget->draw(widget, ctx, right, (left + right));
101 last_drawn = widget;
102 widget = statusbar->widgets;
105 for(widget = statusbar->widgets; widget; widget = widget->next)
106 if (widget->alignment == AlignFlex)
108 widget->cache.needs_update = False;
109 left += widget->draw(widget, ctx, left, (left + right));
112 if(statusbar->position == Right
113 || statusbar->position == Left)
115 if(statusbar->position == Right)
116 statusbar->drawable = draw_rotate(ctx, phys_screen, M_PI_2, statusbar->height, 0);
117 else
118 statusbar->drawable = draw_rotate(ctx, phys_screen, - M_PI_2, 0, statusbar->width);
120 draw_free_context(ctx);
122 else
124 statusbar->drawable = ctx->drawable;
125 /* just delete the struct, don't delete the drawable */
126 p_delete(&ctx);
129 statusbar_display(statusbar);
132 void
133 statusbar_display(Statusbar *statusbar)
135 int phys_screen = get_phys_screen(statusbar->screen);
137 /* don't waste our time */
138 if(statusbar->position == Off)
139 return;
141 if(statusbar->position == Right
142 || statusbar->position == Left)
143 XCopyArea(globalconf.display, statusbar->drawable,
144 statusbar->window,
145 DefaultGC(globalconf.display, phys_screen), 0, 0,
146 statusbar->height,
147 statusbar->width, 0, 0);
148 else
149 XCopyArea(globalconf.display, statusbar->drawable,
150 statusbar->window,
151 DefaultGC(globalconf.display, phys_screen), 0, 0,
152 statusbar->width, statusbar->height, 0, 0);
155 void
156 statusbar_init(Statusbar *statusbar, int screen)
158 Widget *widget;
159 XSetWindowAttributes wa;
160 int phys_screen = get_phys_screen(screen);
161 Area area = get_screen_area(screen,
162 globalconf.screens[screen].statusbar,
163 &globalconf.screens[screen].padding);
165 if(statusbar->height <= 0)
167 /* 1.5 as default factor, it fits nice but no one know why */
168 statusbar->height = globalconf.screens[screen].font->height * 1.5;
170 for(widget = statusbar->widgets; widget; widget = widget->next)
171 if(widget->font)
172 statusbar->height = MAX(statusbar->height, widget->font->height * 1.5);
175 if(statusbar->width <= 0)
177 if(statusbar->position == Right || statusbar->position == Left)
178 statusbar->width = area.height;
179 else
180 statusbar->width = area.width;
183 statusbar->screen = screen;
185 wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
186 | EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
187 wa.cursor = globalconf.cursor[CurNormal];
188 wa.override_redirect = 1;
189 wa.background_pixmap = ParentRelative;
190 wa.event_mask = ButtonPressMask | ExposureMask;
191 if(statusbar->dposition == Right || statusbar->dposition == Left)
192 statusbar->window = XCreateWindow(globalconf.display,
193 RootWindow(globalconf.display,
194 phys_screen),
195 0, 0,
196 statusbar->height,
197 statusbar->width,
199 DefaultDepth(globalconf.display,
200 phys_screen),
201 CopyFromParent,
202 DefaultVisual(globalconf.display,
203 phys_screen),
204 CWOverrideRedirect |
205 CWBackPixmap |
206 CWEventMask,
207 &wa);
208 else
209 statusbar->window = XCreateWindow(globalconf.display,
210 RootWindow(globalconf.display,
211 phys_screen),
212 0, 0,
213 statusbar->width,
214 statusbar->height,
216 DefaultDepth(globalconf.display,
217 phys_screen),
218 CopyFromParent,
219 DefaultVisual(globalconf.display,
220 phys_screen),
221 CWOverrideRedirect |
222 CWBackPixmap |
223 CWEventMask,
224 &wa);
226 statusbar->drawable = XCreatePixmap(globalconf.display,
227 RootWindow(globalconf.display, phys_screen),
228 statusbar->width, statusbar->height,
229 DefaultDepth(globalconf.display, phys_screen));
232 XDefineCursor(globalconf.display,
233 statusbar->window,
234 globalconf.cursor[CurNormal]);
236 widget_calculate_alignments(statusbar->widgets);
238 statusbar_update_position(statusbar);
239 XMapRaised(globalconf.display, statusbar->window);
241 statusbar_draw(statusbar);
244 void
245 statusbar_refresh()
247 int screen;
248 Statusbar *statusbar;
249 Widget *widget;
251 for(screen = 0; screen < globalconf.nscreens; screen++)
252 for(statusbar = globalconf.screens[screen].statusbar;
253 statusbar;
254 statusbar = statusbar->next)
255 for(widget = statusbar->widgets; widget; widget = widget->next)
256 if(widget->cache.needs_update)
258 statusbar_draw(statusbar);
259 break;
263 Position
264 statusbar_get_position_from_str(const char *pos)
266 if(!a_strncmp(pos, "off", 3))
267 return Off;
268 else if(!a_strncmp(pos, "bottom", 6))
269 return Bottom;
270 else if(!a_strncmp(pos, "right", 5))
271 return Right;
272 else if(!a_strncmp(pos, "left", 4))
273 return Left;
274 return Top;
277 static Statusbar *
278 get_statusbar_byname(int screen, const char *name)
280 Statusbar *sb;
282 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
283 if(!a_strcmp(sb->name, name))
284 return sb;
286 return NULL;
289 static void
290 statusbar_toggle(Statusbar *statusbar)
292 if(statusbar->position == Off)
293 statusbar->position = (statusbar->dposition == Off) ? Top : statusbar->dposition;
294 else
295 statusbar->position = Off;
297 statusbar_update_position(statusbar);
300 /** Toggle statusbar
301 * \param screen Screen ID
302 * \param arg statusbar name
303 * \ingroup ui_callback
305 void
306 uicb_statusbar_toggle(int screen, char *arg)
308 Statusbar *sb = get_statusbar_byname(screen, arg);
310 if(sb)
311 statusbar_toggle(sb);
312 else
313 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
314 statusbar_toggle(sb);
316 arrange(screen);
319 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80