rename draw_get_context() to draw_context_new()
[awesome.git] / statusbar.c
blob8802453a5900d5d4f9a1d41ef50c5e31cd3bc24e
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 "tag.h"
28 #include "widget.h"
29 #include "window.h"
30 #include "common/util.h"
32 extern AwesomeConf globalconf;
34 static void
35 statusbar_update_position(Statusbar *statusbar)
37 Area area;
39 XMapRaised(globalconf.display, statusbar->sw->window);
41 /* Top and Bottom Statusbar have prio */
42 if(statusbar->position == Top || statusbar->position == Bottom)
43 area = get_screen_area(statusbar->screen,
44 NULL,
45 &globalconf.screens[statusbar->screen].padding);
46 else
47 area = get_screen_area(statusbar->screen,
48 globalconf.screens[statusbar->screen].statusbar,
49 &globalconf.screens[statusbar->screen].padding);
51 switch(statusbar->position)
53 case Top:
54 simplewindow_move(statusbar->sw, area.x, area.y);
55 break;
56 case Bottom:
57 simplewindow_move(statusbar->sw, area.x, (area.y + area.height) - statusbar->sw->geometry.height);
58 break;
59 case Left:
60 simplewindow_move(statusbar->sw, area.x - statusbar->sw->geometry.width,
61 (area.y + area.height) - statusbar->sw->geometry.height);
62 break;
63 case Right:
64 simplewindow_move(statusbar->sw, area.x + area.width, area.y);
65 break;
66 case Off:
67 XUnmapWindow(globalconf.display, statusbar->sw->window);
68 break;
72 static void
73 statusbar_draw(Statusbar *statusbar)
75 int phys_screen = get_phys_screen(statusbar->screen);
76 Widget *widget, *last_drawn = NULL;
77 int left = 0, right = 0;
78 Area rectangle = { 0, 0, 0, 0 };
79 Drawable d;
81 /* don't waste our time */
82 switch(statusbar->position)
84 case Off:
85 return;
86 break;
87 case Right:
88 case Left:
89 /* we need a new pixmap this way [ ] to render */
90 XFreePixmap(globalconf.display, statusbar->sw->drawable);
91 d = XCreatePixmap(globalconf.display,
92 RootWindow(globalconf.display, phys_screen),
93 statusbar->width, statusbar->height,
94 DefaultDepth(globalconf.display, phys_screen));
95 statusbar->sw->drawable = d;
96 break;
97 default:
98 break;
101 DrawCtx *ctx = draw_context_new(globalconf.display,
102 phys_screen,
103 statusbar->width,
104 statusbar->height,
105 statusbar->sw->drawable);
107 rectangle.width = statusbar->width;
108 rectangle.height = statusbar->height;
109 draw_rectangle(ctx, rectangle, True,
110 globalconf.screens[statusbar->screen].colors_normal[ColBG]);
112 for(widget = statusbar->widgets; widget; widget = widget->next)
113 if (widget->alignment == AlignLeft)
115 widget->cache.needs_update = False;
116 left += widget->draw(widget, ctx, left, (left + right));
119 /* renders right widget from last to first */
120 for(widget = statusbar->widgets; widget; widget = widget->next)
121 if (widget->alignment == AlignRight && last_drawn == widget->next)
123 widget->cache.needs_update = False;
124 right += widget->draw(widget, ctx, right, (left + right));
125 last_drawn = widget;
126 widget = statusbar->widgets;
129 for(widget = statusbar->widgets; widget; widget = widget->next)
130 if (widget->alignment == AlignFlex)
132 widget->cache.needs_update = False;
133 left += widget->draw(widget, ctx, left, (left + right));
136 switch(statusbar->position)
138 case Right:
139 d = draw_rotate(ctx, phys_screen, M_PI_2,
140 statusbar->height, 0);
141 XFreePixmap(globalconf.display, statusbar->sw->drawable);
142 statusbar->sw->drawable = d;
143 break;
144 case Left:
145 d = draw_rotate(ctx, phys_screen, - M_PI_2,
146 0, statusbar->width);
147 XFreePixmap(globalconf.display, statusbar->sw->drawable);
148 statusbar->sw->drawable = d;
149 break;
150 default:
151 break;
154 p_delete(&ctx);
156 statusbar_display(statusbar);
159 void
160 statusbar_display(Statusbar *statusbar)
162 /* don't waste our time */
163 if(statusbar->position != Off)
164 simplewindow_refresh_drawable(statusbar->sw, get_phys_screen(statusbar->screen));
167 void
168 statusbar_preinit(Statusbar *statusbar)
170 Widget *widget;
172 if(statusbar->height <= 0)
174 /* 1.5 as default factor, it fits nice but no one know why */
175 statusbar->height = globalconf.screens[statusbar->screen].font->height * 1.5;
177 for(widget = statusbar->widgets; widget; widget = widget->next)
178 if(widget->font)
179 statusbar->height = MAX(statusbar->height, widget->font->height * 1.5);
183 void
184 statusbar_init(Statusbar *statusbar)
186 Statusbar *sb;
187 int phys_screen = get_phys_screen(statusbar->screen);
188 Area area = get_screen_area(statusbar->screen,
189 globalconf.screens[statusbar->screen].statusbar,
190 &globalconf.screens[statusbar->screen].padding);
193 /* Top and Bottom Statusbar have prio */
194 for(sb = globalconf.screens[statusbar->screen].statusbar; sb; sb = sb->next)
195 switch(sb->position)
197 case Left:
198 case Right:
199 area.width += sb->height;
200 break;
201 default:
202 break;
205 if(statusbar->width <= 0)
207 if(statusbar->position == Right || statusbar->position == Left)
208 statusbar->width = area.height;
209 else
210 statusbar->width = area.width;
213 switch(statusbar->dposition)
215 case Right:
216 case Left:
217 statusbar->sw =
218 simplewindow_new(globalconf.display, phys_screen, 0, 0,
219 statusbar->height, statusbar->width, 0);
220 break;
221 default:
222 statusbar->sw =
223 simplewindow_new(globalconf.display, phys_screen, 0, 0,
224 statusbar->width, statusbar->height, 0);
225 break;
228 widget_calculate_alignments(statusbar->widgets);
230 statusbar_update_position(statusbar);
232 statusbar_draw(statusbar);
235 void
236 statusbar_refresh()
238 int screen;
239 Statusbar *statusbar;
240 Widget *widget;
242 for(screen = 0; screen < globalconf.nscreen; screen++)
243 for(statusbar = globalconf.screens[screen].statusbar;
244 statusbar;
245 statusbar = statusbar->next)
246 for(widget = statusbar->widgets; widget; widget = widget->next)
247 if(widget->cache.needs_update)
249 statusbar_draw(statusbar);
250 break;
254 Position
255 statusbar_get_position_from_str(const char *pos)
257 if(!a_strncmp(pos, "off", 3))
258 return Off;
259 else if(!a_strncmp(pos, "bottom", 6))
260 return Bottom;
261 else if(!a_strncmp(pos, "right", 5))
262 return Right;
263 else if(!a_strncmp(pos, "left", 4))
264 return Left;
265 return Top;
268 static Statusbar *
269 get_statusbar_byname(int screen, const char *name)
271 Statusbar *sb;
273 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
274 if(!a_strcmp(sb->name, name))
275 return sb;
277 return NULL;
280 static void
281 statusbar_toggle(Statusbar *statusbar)
283 if(statusbar->position == Off)
284 statusbar->position = (statusbar->dposition == Off) ? Top : statusbar->dposition;
285 else
286 statusbar->position = Off;
288 statusbar_update_position(statusbar);
289 globalconf.screens[statusbar->screen].need_arrange = True;
292 /** Toggle statusbar
293 * \param screen Screen ID
294 * \param arg statusbar name
295 * \ingroup ui_callback
297 void
298 uicb_statusbar_toggle(int screen, char *arg)
300 Statusbar *sb = get_statusbar_byname(screen, arg);
302 if(sb)
303 statusbar_toggle(sb);
304 else
305 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
306 statusbar_toggle(sb);
309 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80