Prefix xutil functions properly
[awesome.git] / statusbar.c
blobe5040a9860438e6c59a3848c0c53e3596d49f80d
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>
24 #include <xcb/xcb.h>
25 #include <xcb/xcb_aux.h>
27 #include "statusbar.h"
28 #include "screen.h"
29 #include "tag.h"
30 #include "widget.h"
31 #include "window.h"
33 extern AwesomeConf globalconf;
35 static void
36 statusbar_position_update(Statusbar *statusbar)
38 Statusbar *sb;
39 area_t area;
41 if(statusbar->position == Off)
43 xcb_unmap_window(globalconf.connection, statusbar->sw->window);
44 return;
47 xutil_map_raised(globalconf.connection, statusbar->sw->window);
49 /* Top and Bottom Statusbar have prio */
50 if(statusbar->position == Top || statusbar->position == Bottom)
51 area = screen_get_area(statusbar->screen,
52 NULL,
53 &globalconf.screens[statusbar->screen].padding);
54 else
55 area = screen_get_area(statusbar->screen,
56 globalconf.screens[statusbar->screen].statusbar,
57 &globalconf.screens[statusbar->screen].padding);
59 for(sb = globalconf.screens[statusbar->screen].statusbar; sb && sb != statusbar; sb = sb->next)
60 switch(sb->position)
62 case Top:
63 if(sb->position == statusbar->position)
64 area.y += sb->height;
65 break;
66 case Bottom:
67 if(sb->position == statusbar->position)
68 area.height -= sb->height;
69 break;
70 case Left:
71 /* we need to re-add our own value removed in the
72 * screen_get_area computation */
73 if(statusbar->position == Left
74 || statusbar->position == Right)
76 area.x -= statusbar->sw->geometry.width;
77 area.width += statusbar->sw->geometry.width;
79 break;
80 case Right:
81 if(statusbar->position == Left
82 || statusbar->position == Right)
83 area.width += statusbar->sw->geometry.width;
84 break;
85 default:
86 break;
89 switch(statusbar->position)
91 case Top:
92 simplewindow_move(statusbar->sw, area.x, area.y);
93 break;
94 case Bottom:
95 simplewindow_move(statusbar->sw, area.x, (area.y + area.height) - statusbar->sw->geometry.height);
96 break;
97 case Left:
98 simplewindow_move(statusbar->sw, area.x - statusbar->sw->geometry.width,
99 (area.y + area.height) - statusbar->sw->geometry.height);
100 break;
101 case Right:
102 simplewindow_move(statusbar->sw, area.x + area.width, area.y);
103 break;
104 default:
105 break;
109 static void
110 statusbar_draw(Statusbar *statusbar)
112 Widget *widget;
113 int left = 0, right = 0;
114 area_t rectangle = { 0, 0, 0, 0, NULL, NULL };
116 rectangle.width = statusbar->width;
117 rectangle.height = statusbar->height;
118 draw_rectangle(statusbar->ctx, rectangle, 1.0, true,
119 globalconf.screens[statusbar->screen].styles.normal.bg);
121 for(widget = statusbar->widgets; widget; widget = widget->next)
122 if (widget->alignment == AlignLeft)
124 widget->cache.needs_update = false;
125 left += widget->draw(widget, statusbar->ctx, left, (left + right));
128 /* renders right widget from last to first */
129 for(widget = *widget_list_last(&statusbar->widgets);
130 widget;
131 widget = widget_list_prev(&statusbar->widgets, widget))
132 if (widget->alignment == AlignRight)
134 widget->cache.needs_update = false;
135 right += widget->draw(widget, statusbar->ctx, right, (left + right));
138 for(widget = statusbar->widgets; widget; widget = widget->next)
139 if (widget->alignment == AlignFlex)
141 widget->cache.needs_update = false;
142 left += widget->draw(widget, statusbar->ctx, left, (left + right));
145 switch(statusbar->position)
147 case Right:
148 draw_rotate(statusbar->ctx, statusbar->sw->drawable,
149 statusbar->ctx->height, statusbar->ctx->width,
150 M_PI_2, statusbar->height, 0);
151 break;
152 case Left:
153 draw_rotate(statusbar->ctx, statusbar->sw->drawable,
154 statusbar->ctx->height, statusbar->ctx->width,
155 - M_PI_2, 0, statusbar->width);
156 break;
157 default:
158 break;
161 statusbar_display(statusbar);
164 void
165 statusbar_display(Statusbar *statusbar)
167 /* don't waste our time */
168 if(statusbar->position != Off)
169 simplewindow_refresh_drawable(statusbar->sw, statusbar->phys_screen);
172 void
173 statusbar_preinit(Statusbar *statusbar)
175 if(statusbar->height <= 0)
176 /* 1.5 as default factor, it fits nice but no one knows why */
177 statusbar->height = 1.5 * MAX(globalconf.screens[statusbar->screen].styles.normal.font->height,
178 MAX(globalconf.screens[statusbar->screen].styles.focus.font->height,
179 globalconf.screens[statusbar->screen].styles.urgent.font->height));
182 void
183 statusbar_init(Statusbar *statusbar)
185 Statusbar *sb;
186 xcb_drawable_t dw;
187 xcb_screen_t *s = NULL;
188 int phys_screen = screen_virttophys(statusbar->screen);
189 area_t area = screen_get_area(statusbar->screen,
190 globalconf.screens[statusbar->screen].statusbar,
191 &globalconf.screens[statusbar->screen].padding);
193 statusbar->phys_screen = phys_screen;
195 /* Top and Bottom Statusbar have prio */
196 for(sb = globalconf.screens[statusbar->screen].statusbar; sb; sb = sb->next)
197 switch(sb->position)
199 case Left:
200 case Right:
201 area.width += sb->height;
202 break;
203 default:
204 break;
207 if(statusbar->width <= 0)
209 if(statusbar->position == Right || statusbar->position == Left)
210 statusbar->width = area.height;
211 else
212 statusbar->width = area.width;
215 switch(statusbar->position)
217 case Right:
218 case Left:
219 statusbar->sw =
220 simplewindow_new(globalconf.connection, phys_screen, 0, 0,
221 statusbar->height, statusbar->width, 0);
222 break;
223 default:
224 statusbar->sw =
225 simplewindow_new(globalconf.connection, phys_screen, 0, 0,
226 statusbar->width, statusbar->height, 0);
227 break;
230 widget_calculate_alignments(statusbar->widgets);
232 statusbar_position_update(statusbar);
234 switch(statusbar->position)
236 case Off:
237 return;
238 case Right:
239 case Left:
240 s = xcb_aux_get_screen(globalconf.connection, phys_screen);
242 /* we need a new pixmap this way [ ] to render */
243 dw = xcb_generate_id(globalconf.connection);
244 xcb_create_pixmap(globalconf.connection,
245 s->root_depth, dw,
246 xutil_root_window(globalconf.connection, phys_screen),
247 statusbar->width, statusbar->height);
248 statusbar->ctx = draw_context_new(globalconf.connection,
249 phys_screen,
250 statusbar->width,
251 statusbar->height,
252 dw);
253 break;
254 default:
255 statusbar->ctx = draw_context_new(globalconf.connection,
256 phys_screen,
257 statusbar->width,
258 statusbar->height,
259 statusbar->sw->drawable);
260 break;
264 statusbar_draw(statusbar);
267 void
268 statusbar_refresh()
270 int screen;
271 Statusbar *statusbar;
272 Widget *widget;
274 for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
275 for(statusbar = globalconf.screens[screen].statusbar;
276 statusbar;
277 statusbar = statusbar->next)
278 for(widget = statusbar->widgets; widget; widget = widget->next)
279 if(widget->cache.needs_update)
281 statusbar_draw(statusbar);
282 break;
286 Statusbar *
287 statusbar_getbyname(int screen, const char *name)
289 Statusbar *sb;
291 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
292 if(!a_strcmp(sb->name, name))
293 return sb;
295 return NULL;
298 static void
299 statusbar_toggle(Statusbar *statusbar)
301 if(statusbar->position == Off)
302 statusbar->position = (statusbar->dposition == Off) ? Top : statusbar->dposition;
303 else
304 statusbar->position = Off;
306 globalconf.screens[statusbar->screen].need_arrange = true;
309 /** Toggle the statusbar on or off.
310 * Argument must be a statusbar name, or no argument for all statusbars.
311 * \param screen Screen ID
312 * \param arg statusbar name
313 * \ingroup ui_callback
315 void
316 uicb_statusbar_toggle(int screen, char *arg)
318 Statusbar *sb = statusbar_getbyname(screen, arg);
320 if(sb)
321 statusbar_toggle(sb);
322 else
323 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
324 statusbar_toggle(sb);
326 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
327 statusbar_position_update(sb);
330 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80