allow to have several statusbar

This commit is contained in:
Julien Danjou 2007-12-30 21:00:34 +01:00
parent 64e44421dd
commit f7f6951957
13 changed files with 219 additions and 181 deletions

View File

@ -292,6 +292,7 @@ main(int argc, char *argv[])
int screen;
event_handler **handler;
struct sockaddr_un *addr;
Statusbar *statusbar;
if(argc >= 2)
{
@ -342,8 +343,8 @@ main(int argc, char *argv[])
{
/* set screen */
setup(screen);
statusbar_init(screen);
statusbar_draw(screen);
for(statusbar = globalconf.screens[screen].statusbar; statusbar; statusbar = statusbar->next)
statusbar_init(statusbar, screen);
}
/* do this only for real screen */

View File

@ -21,7 +21,7 @@ screen 0
layout dwindle { image = "/usr/local/share/awesome/icons/layouts/dwindle.png" }
layout floating { image = "/usr/local/share/awesome/icons/layouts/floating.png" }
}
statusbar
statusbar mystatusbar
{
position = "top"

View File

@ -254,7 +254,7 @@ focus(Client *c, Bool selscreen, int screen)
/* save sel in focus history */
focus_add_client(c);
statusbar_draw(screen);
statusbar_draw_all(screen);
if(globalconf.focus->client)
{

View File

@ -313,7 +313,8 @@ config_parse_screen(cfg_t *cfg, int screen)
const char *tmp;
Layout *layout = NULL;
Tag *tag = NULL;
cfg_t *cfg_general, *cfg_colors, *cfg_screen, *cfg_statusbar, *cfg_tags,
Statusbar *statusbar = NULL;
cfg_t *cfg_general, *cfg_colors, *cfg_screen, *cfg_tags,
*cfg_layouts, *cfg_padding, *cfgsectmp;
VirtScreen *virtscreen = &globalconf.screens[screen];
unsigned int i;
@ -331,7 +332,6 @@ config_parse_screen(cfg_t *cfg, int screen)
}
/* get screen specific sections */
cfg_statusbar = cfg_getsec(cfg_screen, "statusbar");
cfg_tags = cfg_getsec(cfg_screen, "tags");
cfg_colors = cfg_getsec(cfg_screen, "colors");
cfg_general = cfg_getsec(cfg_screen, "general");
@ -371,14 +371,24 @@ config_parse_screen(cfg_t *cfg, int screen)
cfg_getstr(cfg_colors, "urgent_fg"));
/* Statusbar */
virtscreen->statusbar = p_new(Statusbar, 1);
virtscreen->statusbar->position = virtscreen->statusbar->dposition =
statusbar_get_position_from_str(cfg_getstr(cfg_statusbar, "position"));
virtscreen->statusbar->height = cfg_getint(cfg_statusbar, "height");
virtscreen->statusbar->width = cfg_getint(cfg_statusbar, "width");
if(cfg_size(cfg_screen, "statusbar"))
{
virtscreen->statusbar = statusbar = p_new(Statusbar, 1);
for(i = 0; i < cfg_size(cfg_screen, "statusbar"); i++)
{
cfgsectmp = cfg_getnsec(cfg_screen, "statusbar", i);
statusbar->position = statusbar->dposition =
statusbar_get_position_from_str(cfg_getstr(cfgsectmp, "position"));
statusbar->height = cfg_getint(cfgsectmp, "height");
statusbar->width = cfg_getint(cfgsectmp, "width");
statusbar->name = a_strdup(cfg_title(cfgsectmp));
create_widgets(cfgsectmp, statusbar);
create_widgets(cfg_statusbar, virtscreen->statusbar);
if(i < cfg_size(cfg_screen, "statusbar") - 1)
statusbar = statusbar->next = p_new(Statusbar, 1);
}
}
/* Layouts */
virtscreen->layouts = layout = p_new(Layout, 1);
@ -397,12 +407,10 @@ config_parse_screen(cfg_t *cfg, int screen)
if(i < cfg_size(cfg_layouts, "layout") - 1)
layout = layout->next = p_new(Layout, 1);
else
layout->next = NULL;
}
else
{
warn("fatal: no default layout available\n");
warn("no default layout available\n");
layout->arrange = layout_tile;
}
@ -583,7 +591,7 @@ config_parse(const char *confpatharg)
static cfg_opt_t screen_opts[] =
{
CFG_SEC((char *) "general", general_opts, CFGF_NONE),
CFG_SEC((char *) "statusbar", statusbar_opts, CFGF_NONE),
CFG_SEC((char *) "statusbar", statusbar_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
CFG_SEC((char *) "tags", tags_opts, CFGF_NONE),
CFG_SEC((char *) "colors", colors_opts, CFGF_NONE),
CFG_SEC((char *) "layouts", layouts_opts, CFGF_NONE),

View File

@ -81,10 +81,42 @@ struct Button
Button *next;
};
/** Status bar */
/** Widget */
typedef struct Widget Widget;
typedef struct
typedef struct Statusbar Statusbar;
struct Widget
{
/** Widget name */
char *name;
/** Draw function */
int (*draw)(Widget *, DrawCtx *, int, int);
/** Update function */
void (*tell)(Widget *, char *);
/** ButtonPressedEvent handler */
void (*button_press)(Widget *, XButtonPressedEvent *);
/** Statusbar */
Statusbar *statusbar;
/** Alignement */
int alignment;
/** Misc private data */
void *data;
/** Location on status bar */
int location;
/** Widget width */
int width;
/** Buttons bindings */
Button *buttons;
/** Font */
XftFont *font;
/** Next widget */
Widget *next;
};
/** Status bar */
struct Statusbar
{
/** Statusbar name */
char *name;
/** Bar width */
int width;
/** Bar height */
@ -103,7 +135,9 @@ typedef struct
Widget *widgets;
/** Drawable */
Drawable drawable;
} Statusbar;
/** Next statusbar */
Statusbar *next;
};
typedef struct Client Client;
struct Client
@ -225,24 +259,6 @@ typedef struct
XftFont *font;
} VirtScreen;
struct Widget
{
char *name;
int (*draw)(Widget *, DrawCtx *, int, int);
void (*tell)(Widget *, char *);
void (*button_press)(Widget *, XButtonPressedEvent *);
Statusbar *statusbar;
int alignment;
void *data;
int location;
int width;
Button *buttons;
XftFont *font;
Widget *next;
};
/** Main configuration structure */
struct AwesomeConf
{

40
event.c
View File

@ -66,33 +66,34 @@ handle_event_buttonpress(XEvent *e)
Client *c;
Window wdummy;
Widget *widget;
Statusbar *statusbar;
XButtonPressedEvent *ev = &e->xbutton;
for(screen = 0; screen < get_screen_count(); screen++)
if(globalconf.screens[screen].statusbar->window == ev->window)
for(statusbar = globalconf.screens[screen].statusbar; statusbar; statusbar = statusbar->next)
if(statusbar->window == ev->window)
{
if(globalconf.screens[screen].statusbar->position == BarTop
if(statusbar->position == BarTop
|| globalconf.screens[screen].statusbar->position == BarBot)
for(widget = globalconf.screens[screen].statusbar->widgets; widget; widget = widget->next)
for(widget = statusbar->widgets; widget; widget = widget->next)
if(ev->x >= widget->location && ev->x <= widget->location + widget->width)
{
widget->button_press(widget, ev);
return;
}
if(globalconf.screens[screen].statusbar->position == BarRight)
for(widget = globalconf.screens[screen].statusbar->widgets; widget; widget = widget->next)
if(statusbar->position == BarRight)
for(widget = statusbar->widgets; widget; widget = widget->next)
if(ev->y >= widget->location && ev->y <= widget->location + widget->width)
{
widget->button_press(widget, ev);
return;
}
if(globalconf.screens[screen].statusbar->position == BarLeft)
for(widget = globalconf.screens[screen].statusbar->widgets; widget; widget = widget->next)
if(globalconf.screens[screen].statusbar->width - ev->y >= widget->location
&& globalconf.screens[screen].statusbar->width - ev->y
<= widget->location + widget->width)
if(statusbar->position == BarLeft)
for(widget = statusbar->widgets; widget; widget = widget->next)
if(statusbar->width - ev->y >= widget->location
&& statusbar->width - ev->y <= widget->location + widget->width)
{
widget->button_press(widget, ev);
return;
@ -155,8 +156,8 @@ handle_event_configurerequest(XEvent * e)
if(old_screen != c->screen)
{
move_client_to_screen(c, c->screen, False);
statusbar_draw(old_screen);
statusbar_draw(c->screen);
statusbar_draw_all(old_screen);
statusbar_draw_all(c->screen);
}
tag_client_with_rules(c);
XMoveResizeWindow(e->xany.display, c->win, c->rx, c->ry, c->rw, c->rh);
@ -203,7 +204,7 @@ handle_event_configurenotify(XEvent * e)
globalconf.screens[screen].statusbar->width,
globalconf.screens[screen].statusbar->height);
statusbar_update_position(screen);
statusbar_draw_all(screen);
arrange(screen);
}
}
@ -247,11 +248,16 @@ handle_event_expose(XEvent *e)
{
XExposeEvent *ev = &e->xexpose;
int screen;
Statusbar *statusbar;
if(!ev->count)
for(screen = 0; screen < get_screen_count(); screen++)
if(globalconf.screens[screen].statusbar->window == ev->window)
statusbar_display(screen);
for(statusbar = globalconf.screens[screen].statusbar; statusbar; statusbar = statusbar->next)
if(statusbar->window == ev->window)
{
statusbar_display(statusbar);
return;
}
}
void
@ -357,14 +363,14 @@ handle_event_propertynotify(XEvent * e)
break;
case XA_WM_HINTS:
client_updatewmhints(c);
statusbar_draw(c->screen);
statusbar_draw_all(c->screen);
break;
}
if(ev->atom == XA_WM_NAME || ev->atom == XInternAtom(globalconf.display, "_NET_WM_NAME", False))
{
client_updatetitle(c);
if(c == globalconf.focus->client)
statusbar_draw(c->screen);
statusbar_draw_all(c->screen);
}
}
}

View File

@ -153,7 +153,7 @@ restack(int screen)
XWindowChanges wc;
Tag **curtags;
statusbar_draw(screen);
statusbar_draw_all(screen);
if(!sel)
return;
@ -169,18 +169,13 @@ restack(int screen)
if(!(curtags[0]->layout->arrange == layout_floating))
{
wc.stack_mode = Below;
wc.sibling = globalconf.screens[screen].statusbar->window;
if(!sel->isfloating)
{
XConfigureWindow(globalconf.display, sel->win, CWSibling | CWStackMode, &wc);
wc.sibling = sel->win;
}
XConfigureWindow(globalconf.display, sel->win, CWStackMode, &wc);
for(c = globalconf.clients; c; c = c->next)
{
if(!IS_TILED(c, screen) || c == sel)
continue;
XConfigureWindow(globalconf.display, c->win, CWSibling | CWStackMode, &wc);
wc.sibling = c->win;
XConfigureWindow(globalconf.display, c->win, CWStackMode, &wc);
}
}
p_delete(&curtags);
@ -247,7 +242,7 @@ uicb_tag_setlayout(int screen, char *arg)
if(globalconf.focus->client)
arrange(screen);
else
statusbar_draw(screen);
statusbar_draw_all(screen);
saveawesomeprops(screen);
}

View File

@ -76,7 +76,7 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused)))
RootWindow(globalconf.display, c->phys_screen),
&dummy, &dummy, &x1, &y, &di, &di, &dui);
c->ismax = False;
statusbar_draw(c->screen);
statusbar_draw_all(c->screen);
for(;;)
{
XMaskEvent(globalconf.display, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);

View File

@ -40,6 +40,7 @@ get_screen_area(int screen, Statusbar *statusbar, Padding *padding)
int screen_number = 0;
XineramaScreenInfo *si;
Area area;
Statusbar *sb;
if(XineramaIsActive(globalconf.display))
{
@ -70,18 +71,18 @@ get_screen_area(int screen, Statusbar *statusbar, Padding *padding)
area.height -= padding->top + padding->bottom;
}
if (statusbar)
switch(statusbar->position)
for(sb = statusbar; sb; sb = sb->next)
switch(sb->position)
{
case BarTop:
area.y += statusbar->height;
area.y += sb->height;
case BarBot:
area.height -= statusbar->height;
area.height -= sb->height;
break;
case BarLeft:
area.x += statusbar->height;
area.x += sb->height;
case BarRight:
area.width -= statusbar->height;
area.width -= sb->height;
break;
}
@ -98,13 +99,18 @@ Area
get_display_area(int screen, Statusbar *statusbar, Padding *padding)
{
Area area;
Statusbar *sb;
area.x = 0;
area.y = statusbar && statusbar->position == BarTop ? statusbar->height : 0;
area.y = 0;
area.width = DisplayWidth(globalconf.display, screen);
area.height = DisplayHeight(globalconf.display, screen) -
(statusbar &&
(statusbar->position == BarTop || statusbar->position == BarBot) ? statusbar->height : 0);
area.height = DisplayHeight(globalconf.display, screen);
for(sb = statusbar; sb; sb = sb->next)
{
area.y -= sb->position == BarTop ? statusbar->height : 0;
area.height -= (statusbar->position == BarTop || statusbar->position == BarBot) ? statusbar->height : 0;
}
/* make padding corrections */
if(padding)
@ -217,8 +223,8 @@ move_client_to_screen(Client *c, int new_screen, Bool doresize)
focus(c, True, c->screen);
/* redraw statusbar on all screens */
statusbar_draw(old_screen);
statusbar_draw(new_screen);
statusbar_draw_all(old_screen);
statusbar_draw_all(new_screen);
}
/** Move mouse pointer to x_org and y_xorg of specified screen

View File

@ -32,113 +32,106 @@
extern AwesomeConf globalconf;
void
statusbar_draw(int screen)
static void
statusbar_draw(Statusbar *statusbar)
{
int phys_screen = get_phys_screen(screen);
VirtScreen vscreen;
int phys_screen = get_phys_screen(statusbar->screen);
Widget *widget, *last_drawn = NULL;
int left = 0, right = 0;
vscreen = globalconf.screens[screen];
/* don't waste our time */
if(vscreen.statusbar->position == BarOff)
if(statusbar->position == BarOff)
return;
XFreePixmap(globalconf.display, vscreen.statusbar->drawable);
XFreePixmap(globalconf.display, statusbar->drawable);
DrawCtx *ctx = draw_get_context(phys_screen,
vscreen.statusbar->width,
vscreen.statusbar->height);
draw_rectangle(ctx,
0,
0,
vscreen.statusbar->width,
vscreen.statusbar->height,
True,
vscreen.colors_normal[ColBG]);
for(widget = vscreen.statusbar->widgets; widget; widget = widget->next)
statusbar->width,
statusbar->height);
draw_rectangle(ctx, 0, 0, statusbar->width, statusbar->height, True,
globalconf.screens[statusbar->screen].colors_normal[ColBG]);
for(widget = statusbar->widgets; widget; widget = widget->next)
if (widget->alignment == AlignLeft)
left += widget->draw(widget, ctx, left, (left + right));
/* renders right widget from last to first */
for(widget = vscreen.statusbar->widgets; widget; widget = widget->next)
for(widget = statusbar->widgets; widget; widget = widget->next)
if (widget->alignment == AlignRight && last_drawn == widget->next)
{
right += widget->draw(widget, ctx, right, (left + right));
last_drawn = widget;
widget = vscreen.statusbar->widgets;
widget = statusbar->widgets;
}
for(widget = vscreen.statusbar->widgets; widget; widget = widget->next)
for(widget = statusbar->widgets; widget; widget = widget->next)
if (widget->alignment == AlignFlex)
left += widget->draw(widget, ctx, left, (left + right));
if(vscreen.statusbar->position == BarRight
|| vscreen.statusbar->position == BarLeft)
if(statusbar->position == BarRight
|| statusbar->position == BarLeft)
{
Drawable d;
if(vscreen.statusbar->position == BarRight)
d = draw_rotate(ctx,
phys_screen,
M_PI_2,
vscreen.statusbar->height,
0);
if(statusbar->position == BarRight)
d = draw_rotate(ctx, phys_screen, M_PI_2, statusbar->height, 0);
else
d = draw_rotate(ctx,
phys_screen,
- M_PI_2,
0,
vscreen.statusbar->width);
d = draw_rotate(ctx, phys_screen, - M_PI_2, 0, statusbar->width);
vscreen.statusbar->drawable = d;
statusbar->drawable = d;
draw_free_context(ctx);
}
else
{
vscreen.statusbar->drawable = ctx->drawable;
statusbar->drawable = ctx->drawable;
/* just delete the struct, don't delete the drawable */
p_delete(&ctx);
}
statusbar_display(screen);
statusbar_display(statusbar);
}
void
statusbar_draw_all(int screen)
{
Statusbar *statusbar;
for(statusbar = globalconf.screens[screen].statusbar; statusbar; statusbar = statusbar->next)
statusbar_draw(statusbar);
}
void
statusbar_display(int screen)
statusbar_display(Statusbar *statusbar)
{
VirtScreen vscreen = globalconf.screens[screen];
int phys_screen = get_phys_screen(screen);
int phys_screen = get_phys_screen(statusbar->screen);
/* don't waste our time */
if(vscreen.statusbar->position == BarOff)
if(statusbar->position == BarOff)
return;
if(vscreen.statusbar->position == BarRight
|| vscreen.statusbar->position == BarLeft)
XCopyArea(globalconf.display, vscreen.statusbar->drawable,
vscreen.statusbar->window,
if(statusbar->position == BarRight
|| statusbar->position == BarLeft)
XCopyArea(globalconf.display, statusbar->drawable,
statusbar->window,
DefaultGC(globalconf.display, phys_screen), 0, 0,
vscreen.statusbar->height,
vscreen.statusbar->width, 0, 0);
statusbar->height,
statusbar->width, 0, 0);
else
XCopyArea(globalconf.display, vscreen.statusbar->drawable,
vscreen.statusbar->window,
XCopyArea(globalconf.display, statusbar->drawable,
statusbar->window,
DefaultGC(globalconf.display, phys_screen), 0, 0,
vscreen.statusbar->width, vscreen.statusbar->height, 0, 0);
statusbar->width, statusbar->height, 0, 0);
}
void
statusbar_init(int screen)
statusbar_init(Statusbar *statusbar, int screen)
{
Widget *widget;
XSetWindowAttributes wa;
int phys_screen = get_phys_screen(screen);
Area area = get_screen_area(screen,
Area area = get_screen_area(statusbar->screen,
NULL,
&globalconf.screens[screen].padding);
Statusbar *statusbar = globalconf.screens[screen].statusbar;
if(statusbar->height <= 0)
{
@ -213,21 +206,20 @@ statusbar_init(int screen)
widget_calculate_alignments(statusbar->widgets);
statusbar_update_position(screen);
statusbar_update_position(statusbar);
XMapRaised(globalconf.display, statusbar->window);
}
void
statusbar_update_position(int screen)
statusbar_update_position(Statusbar *statusbar)
{
XEvent ev;
Statusbar *statusbar = globalconf.screens[screen].statusbar;
Area area = get_screen_area(statusbar->screen,
NULL,
&globalconf.screens[screen].padding);
&globalconf.screens[statusbar->screen].padding);
XMapRaised(globalconf.display, statusbar->window);
switch (statusbar->position)
switch(statusbar->position)
{
default:
XMoveWindow(globalconf.display,
@ -256,7 +248,7 @@ statusbar_update_position(int screen)
}
int
statusbar_get_position_from_str(const char * pos)
statusbar_get_position_from_str(const char *pos)
{
if(!a_strncmp(pos, "off", 3))
return BarOff;
@ -269,34 +261,47 @@ statusbar_get_position_from_str(const char * pos)
return BarTop;
}
static Statusbar *
get_statusbar_byname(int screen, const char *name)
{
Statusbar *sb;
for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
if(!a_strcmp(sb->name, name))
return sb;
return NULL;
}
static void
statusbar_toggle(Statusbar *statusbar)
{
if(statusbar->position == BarOff)
statusbar->position = (statusbar->dposition == BarOff) ? BarTop : statusbar->dposition;
else
statusbar->position = BarOff;
statusbar_update_position(statusbar);
}
/** Toggle statusbar
* \param screen Screen ID
* \param arg Unused
* \ingroup ui_callback
*/
void
uicb_statusbar_toggle(int screen, char *arg __attribute__ ((unused)))
uicb_statusbar_toggle(int screen, char *arg)
{
if(globalconf.screens[screen].statusbar->position == BarOff)
globalconf.screens[screen].statusbar->position = (globalconf.screens[screen].statusbar->dposition == BarOff) ? BarTop : globalconf.screens[screen].statusbar->dposition;
Statusbar *sb = get_statusbar_byname(screen, arg);
if(sb)
statusbar_toggle(sb);
else
globalconf.screens[screen].statusbar->position = BarOff;
statusbar_update_position(screen);
for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
statusbar_toggle(sb);
arrange(screen);
}
/** Set statusbar position
* \param screen Screen ID
* \param arg off | bottom | right | left | top
* \ingroup ui_callback
*/
void
uicb_statusbar_set_position(int screen, char *arg)
{
globalconf.screens[screen].statusbar->dposition =
globalconf.screens[screen].statusbar->position =
statusbar_get_position_from_str(arg);
statusbar_update_position(screen);
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -24,14 +24,13 @@
#include "common.h"
void statusbar_init(int);
void statusbar_draw(int);
void statusbar_display(int);
void statusbar_draw_all(int);
void statusbar_init(Statusbar *, int);
void statusbar_display(Statusbar *);
int statusbar_get_position_from_str(const char *);
void statusbar_update_position(int);
void statusbar_update_position(Statusbar *);
UICB_PROTO(uicb_statusbar_toggle);
UICB_PROTO(uicb_statusbar_set_position);
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

1
uicb.c
View File

@ -74,7 +74,6 @@ const NameFuncLink UicbList[] =
{"quit", uicb_quit},
/* statusbar.c */
{"statusbar_toggle", uicb_statusbar_toggle},
{"statusbar_set_position", uicb_statusbar_set_position},
/* mouse.c */
{"client_movemouse", uicb_client_movemouse},
{"client_resizemouse", uicb_client_resizemouse},

View File

@ -74,10 +74,13 @@ static Widget *
widget_find(char *name, int screen)
{
Widget *widget;
widget = globalconf.screens[screen].statusbar->widgets;
for(; widget; widget = widget->next)
if (strcmp(name, widget->name) == 0)
Statusbar *sb;
for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
for(widget = sb->widgets; widget; widget = widget->next)
if(a_strcmp(name, widget->name) == 0)
return widget;
return NULL;
}
@ -153,7 +156,7 @@ uicb_widget_tell(int screen, char *arg)
else
widget->tell(widget, NULL);
statusbar_draw(screen);
statusbar_draw_all(screen);
return;
}