awesome-client send now everything in one message
[awesome.git] / statusbar.c
blob8460a228f07c9cba0dd743c57c7b319e034cb864
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 void
34 statusbar_draw(Statusbar *statusbar)
36 int phys_screen = get_phys_screen(statusbar->screen);
37 Widget *widget, *last_drawn = NULL;
38 int left = 0, right = 0;
40 /* don't waste our time */
41 if(statusbar->position == Off)
42 return;
44 XFreePixmap(globalconf.display, statusbar->drawable);
46 DrawCtx *ctx = draw_get_context(phys_screen,
47 statusbar->width,
48 statusbar->height);
50 draw_rectangle(ctx, 0, 0, statusbar->width, statusbar->height, True,
51 globalconf.screens[statusbar->screen].colors_normal[ColBG]);
53 for(widget = statusbar->widgets; widget; widget = widget->next)
54 if (widget->alignment == AlignLeft)
56 widget->cache.needs_update = False;
57 left += widget->draw(widget, ctx, left, (left + right));
60 /* renders right widget from last to first */
61 for(widget = statusbar->widgets; widget; widget = widget->next)
62 if (widget->alignment == AlignRight && last_drawn == widget->next)
64 widget->cache.needs_update = False;
65 right += widget->draw(widget, ctx, right, (left + right));
66 last_drawn = widget;
67 widget = statusbar->widgets;
70 for(widget = statusbar->widgets; widget; widget = widget->next)
71 if (widget->alignment == AlignFlex)
73 widget->cache.needs_update = False;
74 left += widget->draw(widget, ctx, left, (left + right));
77 if(statusbar->position == Right
78 || statusbar->position == Left)
80 if(statusbar->position == Right)
81 statusbar->drawable = draw_rotate(ctx, phys_screen, M_PI_2, statusbar->height, 0);
82 else
83 statusbar->drawable = draw_rotate(ctx, phys_screen, - M_PI_2, 0, statusbar->width);
85 draw_free_context(ctx);
87 else
89 statusbar->drawable = ctx->drawable;
90 /* just delete the struct, don't delete the drawable */
91 p_delete(&ctx);
94 statusbar_display(statusbar);
97 void
98 statusbar_display(Statusbar *statusbar)
100 int phys_screen = get_phys_screen(statusbar->screen);
102 /* don't waste our time */
103 if(statusbar->position == Off)
104 return;
106 if(statusbar->position == Right
107 || statusbar->position == Left)
108 XCopyArea(globalconf.display, statusbar->drawable,
109 statusbar->window,
110 DefaultGC(globalconf.display, phys_screen), 0, 0,
111 statusbar->height,
112 statusbar->width, 0, 0);
113 else
114 XCopyArea(globalconf.display, statusbar->drawable,
115 statusbar->window,
116 DefaultGC(globalconf.display, phys_screen), 0, 0,
117 statusbar->width, statusbar->height, 0, 0);
120 void
121 statusbar_init(Statusbar *statusbar, int screen)
123 Widget *widget;
124 XSetWindowAttributes wa;
125 int phys_screen = get_phys_screen(screen);
126 Area area = get_screen_area(statusbar->screen,
127 NULL,
128 &globalconf.screens[screen].padding);
130 if(statusbar->height <= 0)
132 /* 1.5 as default factor, it fits nice but no one know why */
133 statusbar->height = globalconf.screens[screen].font->height * 1.5;
135 for(widget = statusbar->widgets; widget; widget = widget->next)
136 if(widget->font)
137 statusbar->height = MAX(statusbar->height, widget->font->height * 1.5);
140 if(statusbar->width <= 0)
142 if(statusbar->position == Right || statusbar->position == Left)
143 statusbar->width = area.height;
144 else
145 statusbar->width = area.width;
148 statusbar->screen = screen;
150 wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
151 | EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
152 wa.cursor = globalconf.cursor[CurNormal];
153 wa.override_redirect = 1;
154 wa.background_pixmap = ParentRelative;
155 wa.event_mask = ButtonPressMask | ExposureMask;
156 if(statusbar->dposition == Right || statusbar->dposition == Left)
157 statusbar->window = XCreateWindow(globalconf.display,
158 RootWindow(globalconf.display,
159 phys_screen),
160 0, 0,
161 statusbar->height,
162 statusbar->width,
164 DefaultDepth(globalconf.display,
165 phys_screen),
166 CopyFromParent,
167 DefaultVisual(globalconf.display,
168 phys_screen),
169 CWOverrideRedirect |
170 CWBackPixmap |
171 CWEventMask,
172 &wa);
173 else
174 statusbar->window = XCreateWindow(globalconf.display,
175 RootWindow(globalconf.display,
176 phys_screen),
177 0, 0,
178 statusbar->width,
179 statusbar->height,
181 DefaultDepth(globalconf.display,
182 phys_screen),
183 CopyFromParent,
184 DefaultVisual(globalconf.display,
185 phys_screen),
186 CWOverrideRedirect |
187 CWBackPixmap |
188 CWEventMask,
189 &wa);
191 statusbar->drawable = XCreatePixmap(globalconf.display,
192 RootWindow(globalconf.display, phys_screen),
193 statusbar->width, statusbar->height,
194 DefaultDepth(globalconf.display, phys_screen));
197 XDefineCursor(globalconf.display,
198 statusbar->window,
199 globalconf.cursor[CurNormal]);
201 widget_calculate_alignments(statusbar->widgets);
203 statusbar_update_position(statusbar);
204 XMapRaised(globalconf.display, statusbar->window);
206 statusbar_draw(statusbar);
209 void
210 statusbar_update_position(Statusbar *statusbar)
212 XEvent ev;
213 Area area = get_screen_area(statusbar->screen,
214 NULL,
215 &globalconf.screens[statusbar->screen].padding);
217 XMapRaised(globalconf.display, statusbar->window);
218 switch(statusbar->position)
220 default:
221 XMoveWindow(globalconf.display, statusbar->window,
222 area.x, area.y);
223 break;
224 case Left:
225 XMoveWindow(globalconf.display, statusbar->window,
226 area.x, (area.y + area.height) - statusbar->width);
227 break;
228 case Right:
229 XMoveWindow(globalconf.display, statusbar->window,
230 area.x + (area.width - statusbar->height), area.y);
231 break;
232 case Bottom:
233 XMoveWindow(globalconf.display, statusbar->window,
234 area.x, area.height - statusbar->height);
235 break;
236 case Off:
237 XUnmapWindow(globalconf.display, statusbar->window);
238 break;
240 XSync(globalconf.display, False);
241 while(XCheckMaskEvent(globalconf.display, EnterWindowMask, &ev));
245 void
246 statusbar_refresh()
248 int screen;
249 Statusbar *statusbar;
250 Widget *widget;
252 for(screen = 0; screen < get_screen_count(); screen++)
253 for(statusbar = globalconf.screens[screen].statusbar;
254 statusbar;
255 statusbar = statusbar->next)
256 for(widget = statusbar->widgets; widget; widget = widget->next)
257 if(widget->cache.needs_update)
259 statusbar_draw(statusbar);
260 break;
264 Position
265 statusbar_get_position_from_str(const char *pos)
267 if(!a_strncmp(pos, "off", 3))
268 return Off;
269 else if(!a_strncmp(pos, "bottom", 6))
270 return Bottom;
271 else if(!a_strncmp(pos, "right", 5))
272 return Right;
273 else if(!a_strncmp(pos, "left", 4))
274 return Left;
275 return Top;
278 static Statusbar *
279 get_statusbar_byname(int screen, const char *name)
281 Statusbar *sb;
283 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
284 if(!a_strcmp(sb->name, name))
285 return sb;
287 return NULL;
290 static void
291 statusbar_toggle(Statusbar *statusbar)
293 if(statusbar->position == Off)
294 statusbar->position = (statusbar->dposition == Off) ? Top : statusbar->dposition;
295 else
296 statusbar->position = Off;
298 statusbar_update_position(statusbar);
301 /** Toggle statusbar
302 * \param screen Screen ID
303 * \param arg statusbar name
304 * \ingroup ui_callback
306 void
307 uicb_statusbar_toggle(int screen, char *arg)
309 Statusbar *sb = get_statusbar_byname(screen, arg);
311 if(sb)
312 statusbar_toggle(sb);
313 else
314 for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
315 statusbar_toggle(sb);
317 arrange(screen);
320 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80