[config] add missing documentation
[awesome.git] / statusbar.c
blobafd296035641fc3f0d76f1feb44946a6092e1f27
1 /*
2 * statusbar.c - statusbar functions
4 * Copyright © 2007-2008 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 "tag.h"
28 #include "widget.h"
29 #include "window.h"
31 extern AwesomeConf globalconf;
33 static void
34 statusbar_position_update(Statusbar *statusbar)
36 Statusbar *sb;
37 area_t area;
39 if(statusbar->position == Off)
41 XUnmapWindow(globalconf.display, statusbar->sw->window);
42 return;
45 XMapRaised(globalconf.display, statusbar->sw->window);
47 /* Top and Bottom Statusbar have prio */
48 if(statusbar->position == Top || statusbar->position == Bottom)
49 area = screen_get_area(statusbar->screen,
50 NULL,
51 &globalconf.screens[statusbar->screen].padding);
52 else
53 area = screen_get_area(statusbar->screen,
54 globalconf.screens[statusbar->screen].statusbar,
55 &globalconf.screens[statusbar->screen].padding);
57 for(sb = globalconf.screens[statusbar->screen].statusbar; sb && sb != statusbar; sb = sb->next)
58 switch(sb->position)
60 case Top:
61 if(sb->position == statusbar->position)
62 area.y += sb->height;
63 break;
64 case Bottom:
65 if(sb->position == statusbar->position)
66 area.height -= sb->height;
67 break;
68 case Left:
69 /* we need to re-add our own value removed in the
70 * screen_get_area computation */
71 if(statusbar->position == Left
72 || statusbar->position == Right)
74 area.x -= statusbar->sw->geometry.width;
75 area.width += statusbar->sw->geometry.width;
77 break;
78 case Right:
79 if(statusbar->position == Left
80 || statusbar->position == Right)
81 area.width += statusbar->sw->geometry.width;
82 break;
83 default:
84 break;
87 switch(statusbar->position)
89 case Top:
90 simplewindow_move(statusbar->sw, area.x, area.y);
91 break;
92 case Bottom:
93 simplewindow_move(statusbar->sw, area.x, (area.y + area.height) - statusbar->sw->geometry.height);
94 break;
95 case Left:
96 simplewindow_move(statusbar->sw, area.x - statusbar->sw->geometry.width,
97 (area.y + area.height) - statusbar->sw->geometry.height);
98 break;
99 case Right:
100 simplewindow_move(statusbar->sw, area.x + area.width, area.y);
101 break;
102 default:
103 break;
107 static void
108 statusbar_draw(Statusbar *statusbar)
110 Widget *widget;
111 int left = 0, right = 0;
112 area_t rectangle = { 0, 0, 0, 0, NULL, NULL };
114 rectangle.width = statusbar->width;
115 rectangle.height = statusbar->height;
116 draw_rectangle(statusbar->ctx, rectangle, 1.0, True,
117 globalconf.screens[statusbar->screen].styles.normal.bg);
119 for(widget = statusbar->widgets; widget; widget = widget->next)
120 if (widget->alignment == AlignLeft)
122 widget->cache.needs_update = False;
123 left += widget->draw(widget, statusbar->ctx, left, (left + right));
126 /* renders right widget from last to first */
127 for(widget = *widget_list_last(&statusbar->widgets);
128 widget;
129 widget = widget_list_prev(&statusbar->widgets, widget))
130 if (widget->alignment == AlignRight)
132 widget->cache.needs_update = False;
133 right += widget->draw(widget, statusbar->ctx, right, (left + right));
136 for(widget = statusbar->widgets; widget; widget = widget->next)
137 if (widget->alignment == AlignFlex)
139 widget->cache.needs_update = False;
140 left += widget->draw(widget, statusbar->ctx, left, (left + right));
143 switch(statusbar->position)
145 case Right:
146 draw_rotate(statusbar->ctx, statusbar->sw->drawable,
147 statusbar->ctx->height, statusbar->ctx->width,
148 M_PI_2, statusbar->height, 0);
149 break;
150 case Left:
151 draw_rotate(statusbar->ctx, statusbar->sw->drawable,
152 statusbar->ctx->height, statusbar->ctx->width,
153 - M_PI_2, 0, statusbar->width);
154 break;
155 default:
156 break;
159 statusbar_display(statusbar);
162 void
163 statusbar_display(Statusbar *statusbar)
165 /* don't waste our time */
166 if(statusbar->position != Off)
167 simplewindow_refresh_drawable(statusbar->sw, statusbar->phys_screen);
170 void
171 statusbar_preinit(Statusbar *statusbar)
173 if(statusbar->height <= 0)
174 /* 1.5 as default factor, it fits nice but no one knows why */
175 statusbar->height = 1.5 * MAX(globalconf.screens[statusbar->screen].styles.normal.font->height,
176 MAX(globalconf.screens[statusbar->screen].styles.focus.font->height,
177 globalconf.screens[statusbar->screen].styles.urgent.font->height));
180 void
181 statusbar_init(Statusbar *statusbar)
183 Statusbar *sb;
184 Drawable dw;
185 int phys_screen = screen_virttophys(statusbar->screen);
186 area_t area = screen_get_area(statusbar->screen,
187 globalconf.screens[statusbar->screen].statusbar,
188 &globalconf.screens[statusbar->screen].padding);
190 statusbar->phys_screen = phys_screen;
192 /* Top and Bottom Statusbar have prio */
193 for(sb = globalconf.screens[statusbar->screen].statusbar; sb; sb = sb->next)
194 switch(sb->position)
196 case Left:
197 case Right:
198 area.width += sb->height;
199 break;
200 default:
201 break;
204 if(statusbar->width <= 0)
206 if(statusbar->position == Right || statusbar->position == Left)
207 statusbar->width = area.height;
208 else
209 statusbar->width = area.width;
212 switch(statusbar->position)
214 case Right:
215 case Left:
216 statusbar->sw =
217 simplewindow_new(globalconf.display, phys_screen, 0, 0,
218 statusbar->height, statusbar->width, 0);
219 break;
220 default:
221 statusbar->sw =
222 simplewindow_new(globalconf.display, phys_screen, 0, 0,
223 statusbar->width, statusbar->height, 0);
224 break;
227 widget_calculate_alignments(statusbar->widgets);
229 statusbar_position_update(statusbar);
231 switch(statusbar->position)
233 case Off:
234 return;
235 case Right:
236 case Left:
237 /* we need a new pixmap this way [ ] to render */
238 dw = XCreatePixmap(globalconf.display,
239 RootWindow(globalconf.display, phys_screen),
240 statusbar->width, statusbar->height,
241 DefaultDepth(globalconf.display, phys_screen));
242 statusbar->ctx = draw_context_new(globalconf.display,
243 phys_screen,
244 statusbar->width,
245 statusbar->height,
246 dw);
247 break;
248 default:
249 statusbar->ctx = draw_context_new(globalconf.display,
250 phys_screen,
251 statusbar->width,
252 statusbar->height,
253 statusbar->sw->drawable);
254 break;
258 statusbar_draw(statusbar);
261 void
262 statusbar_refresh()
264 int screen;
265 Statusbar *statusbar;
266 Widget *widget;
268 for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
269 for(statusbar = globalconf.screens[screen].statusbar;
270 statusbar;
271 statusbar = statusbar->next)
272 for(widget = statusbar->widgets; widget; widget = widget->next)
273 if(widget->cache.needs_update)
275 statusbar_draw(statusbar);
276 break;
280 static Statusbar *
281 statusbar_get_byname(int screen, const char *name)
283 Statusbar *sb;
285 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
286 if(!a_strcmp(sb->name, name))
287 return sb;
289 return NULL;
292 static void
293 statusbar_toggle(Statusbar *statusbar)
295 if(statusbar->position == Off)
296 statusbar->position = (statusbar->dposition == Off) ? Top : statusbar->dposition;
297 else
298 statusbar->position = Off;
300 globalconf.screens[statusbar->screen].need_arrange = True;
303 /** Toggle statusbar
304 * \param screen Screen ID
305 * \param arg statusbar name
306 * \ingroup ui_callback
308 void
309 uicb_statusbar_toggle(int screen, char *arg)
311 Statusbar *sb = statusbar_get_byname(screen, arg);
313 if(sb)
314 statusbar_toggle(sb);
315 else
316 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
317 statusbar_toggle(sb);
319 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
320 statusbar_position_update(sb);
324 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80