From 76ddf235acf52434076aaae3a751254d95bc9097 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 15 Dec 2007 17:53:53 +1100 Subject: [PATCH] Widget-ise the statusbar. We now have the beginnings of a flexible widget structure for the statusbar. For now, there is no behavioural change, and the interface is a bit crude, but watch this space! --- Makefile | 7 +- config.h | 17 +++++ config.mk | 2 + statusbar.c | 175 +++++++------------------------------------ widget.c | 34 +++++++++ widget.h | 19 +++++ widgets/focustitle.c | 48 ++++++++++++ widgets/layoutinfo.c | 42 +++++++++++ widgets/taglist.c | 81 ++++++++++++++++++++ widgets/textbox.c | 35 +++++++++ 10 files changed, 308 insertions(+), 152 deletions(-) create mode 100644 widget.c create mode 100644 widget.h create mode 100644 widgets/focustitle.c create mode 100644 widgets/layoutinfo.c create mode 100644 widgets/taglist.c create mode 100644 widgets/textbox.c diff --git a/Makefile b/Makefile index b3c4801e..f6a3acd2 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ include config.mk -SRC = focus.c client.c draw.c event.c layout.c awesome.c tag.c util.c xutil.c config.c screen.c statusbar.c uicb.c window.c rules.c mouse.c awesome-client-common.c -OBJ = ${SRC:.c=.o} ${LAYOUTS:.c=.o} +SRC = focus.c client.c draw.c event.c layout.c awesome.c tag.c util.c xutil.c config.c screen.c statusbar.c uicb.c window.c rules.c mouse.c awesome-client-common.c widget.c +OBJ = ${SRC:.c=.o} ${LAYOUTS:.c=.o} ${WIDGETS:.c=.o} DOCS = awesome.1.txt awesome-client.1.txt awesomerc.1.txt SRCCLIENT = awesome-client.c awesome-client-common.c util.c @@ -15,6 +15,7 @@ all: options awesome awesome-client options: @echo awesome build options: @echo "LAYOUTS = ${LAYOUTS}" + @echo "WIDGETS = ${WIDGETS}" @echo "CFLAGS = ${CFLAGS}" @echo "LDFLAGS = ${LDFLAGS}" @echo "CC = ${CC}" @@ -59,10 +60,12 @@ dist: clean @echo creating dist tarball @mkdir awesome-${VERSION} @mkdir awesome-${VERSION}/layouts + @mkdir awesome-${VERSION}/widgets @cp -fR STYLE LICENSE AUTHORS Makefile README awesomerc config.mk \ awesome-client.1.txt awesome.1.txt awesomerc.1.txt ${SRCCLIENT} ${SRCCLIENT:.c=.h} ${SRC} ${SRC:.c=.h} \ common.h awesome-${VERSION} || true @cp -R ${LAYOUTS} ${LAYOUTS:.c=.h} awesome-${VERSION}/layouts + @cp -R ${WIDGETS} ${WIDGETS:.c=.h} awesome-${VERSION}/layouts @tar -cf awesome-${VERSION}.tar awesome-${VERSION} @gzip -9 awesome-${VERSION}.tar @rm -rf awesome-${VERSION} diff --git a/config.h b/config.h index 743d865c..dccbb709 100644 --- a/config.h +++ b/config.h @@ -25,6 +25,7 @@ #include #include #include +#include /** Bar possible position */ enum @@ -79,6 +80,7 @@ struct Button }; /** Status bar */ +typedef struct Widget Widget; typedef struct { /** Bar width */ @@ -95,6 +97,8 @@ typedef struct Window window; /** Screen */ int screen; + /** Screen */ + Widget *widgets; } Statusbar; typedef struct Client Client; @@ -216,6 +220,19 @@ typedef struct XftFont *font; } VirtScreen; + +struct Widget +{ + char *name; + int (*draw)(DrawCtx *, + awesome_config *, + VirtScreen, int, int, int, int); + Statusbar *statusbar; + int alignment; + Widget *next; +}; + + /** Main configuration structure */ struct awesome_config { diff --git a/config.mk b/config.mk index d55d7718..2d93f486 100644 --- a/config.mk +++ b/config.mk @@ -7,6 +7,8 @@ RELEASE = "Productivity Breaker" # additional layouts LAYOUTS = layouts/tile.c layouts/floating.c layouts/max.c layouts/fibonacci.c +WIDGETS = widgets/taglist.c widgets/layoutinfo.c widgets/textbox.c widgets/focustitle.c + # paths PREFIX = /usr/local MANPREFIX = ${PREFIX}/share/man diff --git a/statusbar.c b/statusbar.c index 4189dafb..70e29221 100644 --- a/statusbar.c +++ b/statusbar.c @@ -28,158 +28,17 @@ #include "screen.h" #include "util.h" #include "tag.h" +#include "widget.h" #include "layouts/tile.h" - -enum { AlignLeft, AlignRight, AlignFlex }; - -/** Check if at least a client is tagged with tag number t and is on screen - * screen - * \param t tag number - * \param screen screen number - * \return True or False - */ -static Bool -isoccupied(TagClientLink *tc, int screen, Client *head, Tag *t) -{ - Client *c; - - for(c = head; c; c = c->next) - if(c->screen == screen && is_client_tagged(tc, c, t)) - return True; - return False; -} - - -static int -calculate_offset(int barwidth, int widgetwidth, int offset, int alignment) -{ - if (alignment == AlignLeft || alignment == AlignFlex) - return offset; - else - return barwidth - offset - widgetwidth; -} - - -static int -tagwidget_draw(DrawCtx *ctx, - awesome_config *awesomeconf, - VirtScreen vscreen, - int screen, - int offset, - int used __attribute__ ((unused)), - int align __attribute__ ((unused))) -{ - Tag *tag; - Client *sel = awesomeconf->focus->client; - int w = 0, width = 0, location; - int flagsize; - XColor *colors; - - flagsize = (vscreen.font->height + 2) / 4; - - for(tag = vscreen.tags; tag; tag = tag->next) - width += textwidth(ctx, vscreen.font, tag->name); - - location = calculate_offset(vscreen.statusbar.width, width, offset, align); - - width = 0; - for(tag = vscreen.tags; tag; tag = tag->next) - { - w = textwidth(ctx, vscreen.font, tag->name); - if(tag->selected) - colors = vscreen.colors_selected; - else - colors = vscreen.colors_normal; - drawtext(ctx, location + width, 0, w, - vscreen.statusbar.height, vscreen.font, tag->name, colors); - if(isoccupied(vscreen.tclink, screen, awesomeconf->clients, tag)) - drawrectangle(ctx, location + width, 0, flagsize, flagsize, - sel && is_client_tagged(vscreen.tclink, sel, tag), - colors[ColFG]); - width += w; - } - return width; -} - - -static int -layoutsymbol_draw(DrawCtx *ctx, - awesome_config *awesomeconf __attribute__ ((unused)), - VirtScreen vscreen, - int screen __attribute__ ((unused)), - int offset, - int used __attribute__ ((unused)), - int align __attribute__ ((unused))) -{ - int width = 0, location; - Layout *l; - for(l = vscreen.layouts ; l; l = l->next) - width = MAX(width, (textwidth(ctx, vscreen.font, l->symbol))); - location = calculate_offset(vscreen.statusbar.width, width, offset, align); - drawtext(ctx, location, 0, - width, - vscreen.statusbar.height, - vscreen.font, - get_current_layout(vscreen)->symbol, - vscreen.colors_normal); - return width; -} - - -static int -statustext_draw(DrawCtx *ctx, - awesome_config *awesomeconf __attribute__ ((unused)), - VirtScreen vscreen, - int screen __attribute__ ((unused)), - int offset, - int used __attribute__ ((unused)), - int align) -{ - int width = textwidth(ctx, vscreen.font, vscreen.statustext); - int location = calculate_offset(vscreen.statusbar.width, width, offset, align); - drawtext(ctx, location, 0, width, vscreen.statusbar.height, - vscreen.font, vscreen.statustext, vscreen.colors_normal); - return width; -} - - -static int -focustitle_draw(DrawCtx *ctx, - awesome_config *awesomeconf __attribute__ ((unused)), - VirtScreen vscreen, - int screen __attribute__ ((unused)), - int offset, - int used, - int align) -{ - Client *sel = awesomeconf->focus->client; - int location = calculate_offset(vscreen.statusbar.width, 0, offset, align); - - if(sel) - { - drawtext(ctx, location, 0, vscreen.statusbar.width - used, - vscreen.statusbar.height, vscreen.font, sel->name, - vscreen.colors_selected); - if(sel->isfloating) - drawcircle(ctx, location, 0, - (vscreen.font->height + 2) / 4, - sel->ismax, - vscreen.colors_selected[ColFG]); - } - else - drawtext(ctx, location, 0, vscreen.statusbar.width - used, - vscreen.statusbar.height, vscreen.font, NULL, - vscreen.colors_normal); - return vscreen.statusbar.width - used; -} - +#include "widget.h" void statusbar_draw(awesome_config *awesomeconf, int screen) { - int x = 0, split; int phys_screen = get_phys_screen(awesomeconf->display, screen); VirtScreen vscreen; + Widget *widget; + int left = 0, right = 0; vscreen = awesomeconf->screens[screen]; /* don't waste our time */ @@ -188,11 +47,16 @@ statusbar_draw(awesome_config *awesomeconf, int screen) DrawCtx *ctx = draw_get_context(awesomeconf->display, phys_screen, vscreen.statusbar.width, vscreen.statusbar.height); - x += tagwidget_draw(ctx, awesomeconf, vscreen, screen, x, x, AlignLeft); - x += layoutsymbol_draw(ctx, awesomeconf, vscreen, screen, x, x, AlignLeft); - split = x; - x += statustext_draw(ctx, awesomeconf, vscreen, screen, 0, x, AlignRight); - focustitle_draw(ctx, awesomeconf, vscreen, screen, split, x, AlignFlex); + + for(widget = vscreen.statusbar.widgets; widget; widget = widget->next) + if (widget->alignment == AlignLeft) + left += widget->draw(ctx, awesomeconf, vscreen, screen, left, (left + right), AlignLeft); + else if (widget->alignment == AlignRight) + right += widget->draw(ctx, awesomeconf, vscreen, screen, right, (left + right), AlignRight); + + for(widget = vscreen.statusbar.widgets; widget; widget = widget->next) + if (widget->alignment == AlignFlex) + left += widget->draw(ctx, awesomeconf, vscreen, screen, left, (left + right), AlignFlex); if(vscreen.statusbar.position == BarRight || vscreen.statusbar.position == BarLeft) { @@ -224,6 +88,7 @@ statusbar_init(Display *disp, int screen, Statusbar *statusbar, Cursor cursor, X XSetWindowAttributes wa; int phys_screen = get_phys_screen(disp, screen); ScreenInfo *si = get_screen_info(disp, screen, NULL, padding); + Widget *widget; statusbar->height = font->height * 1.5; @@ -257,6 +122,15 @@ statusbar_init(Display *disp, int screen, Statusbar *statusbar, Cursor cursor, X DefaultVisual(disp, phys_screen), CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); XDefineCursor(disp, statusbar->window, cursor); + + /* For now, we just create a standard set of widgets by hand. As the refactoring continues, + * these will become configurable. */ + statusbar->widgets = widget = taglist_new(statusbar); + widget->next = layoutinfo_new(statusbar); widget = widget->next; + widget->next = focustitle_new(statusbar); widget = widget->next; + widget->next = textbox_new(statusbar); + calculate_alignments(statusbar->widgets); + statusbar_update_position(disp, *statusbar, padding); XMapRaised(disp, statusbar->window); } @@ -336,4 +210,5 @@ uicb_statusbar_set_text(awesome_config *awesomeconf, int screen, const char *arg statusbar_draw(awesomeconf, screen); } + // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 diff --git a/widget.c b/widget.c new file mode 100644 index 00000000..41f9de9a --- /dev/null +++ b/widget.c @@ -0,0 +1,34 @@ + +#include "widget.h" + + +void +calculate_alignments(Widget *widget) +{ + while (widget){ + printf("%s\n", widget->name); + if (widget->alignment == AlignFlex){ + widget = widget->next; + break; + } + widget->alignment = AlignLeft; + widget = widget->next; + } + if (widget){ + while (widget){ + widget->alignment = AlignRight; + widget = widget->next; + } + } +} + +int +calculate_offset(int barwidth, int widgetwidth, int offset, int alignment) +{ + if (alignment == AlignLeft || alignment == AlignFlex) + return offset; + else + return barwidth - offset - widgetwidth; +} + +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 diff --git a/widget.h b/widget.h new file mode 100644 index 00000000..fefddce2 --- /dev/null +++ b/widget.h @@ -0,0 +1,19 @@ +#ifndef AWESOME_WIDGET_H +#define AWESOME_WIDGET_H + +#include "config.h" +#include "draw.h" + +enum { AlignLeft, AlignRight, AlignFlex }; + +int calculate_offset(int, int, int, int); +void calculate_alignments(Widget *widget); + +Widget *layoutinfo_new(Statusbar*); +Widget *taglist_new(Statusbar*); +Widget *textbox_new(Statusbar*); +Widget *focustitle_new(Statusbar*); + +#endif + +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 diff --git a/widgets/focustitle.c b/widgets/focustitle.c new file mode 100644 index 00000000..8cd5e3a5 --- /dev/null +++ b/widgets/focustitle.c @@ -0,0 +1,48 @@ +#include "util.h" +#include "widget.h" + +static char name[] = "focustitle"; + +static int +focustitle_draw(DrawCtx *ctx, + awesome_config *awesomeconf __attribute__ ((unused)), + VirtScreen vscreen, + int screen __attribute__ ((unused)), + int offset, + int used, + int align) +{ + Client *sel = awesomeconf->focus->client; + int location = calculate_offset(vscreen.statusbar.width, 0, offset, align); + + if(sel) + { + drawtext(ctx, location, 0, vscreen.statusbar.width - used, + vscreen.statusbar.height, vscreen.font, sel->name, + vscreen.colors_selected); + if(sel->isfloating) + drawcircle(ctx, location, 0, + (vscreen.font->height + 2) / 4, + sel->ismax, + vscreen.colors_selected[ColFG]); + } + else + drawtext(ctx, location, 0, vscreen.statusbar.width - used, + vscreen.statusbar.height, vscreen.font, NULL, + vscreen.colors_normal); + return vscreen.statusbar.width - used; +} + +Widget * +focustitle_new(Statusbar *statusbar) +{ + Widget *w; + w = p_new(Widget, 1); + w->draw = (void*) focustitle_draw; + w->statusbar = statusbar; + w->name = name; + w->alignment = AlignFlex; + return w; +} + +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 diff --git a/widgets/layoutinfo.c b/widgets/layoutinfo.c new file mode 100644 index 00000000..52d12d9a --- /dev/null +++ b/widgets/layoutinfo.c @@ -0,0 +1,42 @@ +#include "widget.h" +#include "util.h" +#include "layout.h" + +static char name[] = "layoutinfo"; + +static int +layoutinfo_draw(DrawCtx *ctx, + awesome_config *awesomeconf __attribute__ ((unused)), + VirtScreen vscreen, + int screen __attribute__ ((unused)), + int offset, + int used __attribute__ ((unused)), + int align __attribute__ ((unused))) +{ + int width = 0, location; + Layout *l; + for(l = vscreen.layouts ; l; l = l->next) + width = MAX(width, (textwidth(ctx, vscreen.font, l->symbol))); + location = calculate_offset(vscreen.statusbar.width, width, offset, align); + drawtext(ctx, location, 0, + width, + vscreen.statusbar.height, + vscreen.font, + get_current_layout(vscreen)->symbol, + vscreen.colors_normal); + return width; +} + + +Widget * +layoutinfo_new(Statusbar *statusbar) +{ + Widget *w; + w = p_new(Widget, 1); + w->draw = (void*) layoutinfo_draw; + w->statusbar = statusbar; + w->name = name; + return w; +} + +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 diff --git a/widgets/taglist.c b/widgets/taglist.c new file mode 100644 index 00000000..58d4f8ce --- /dev/null +++ b/widgets/taglist.c @@ -0,0 +1,81 @@ +#include "config.h" +#include "util.h" +#include "widget.h" +#include "tag.h" + +static char name[] = "taglist"; + +/** Check if at least a client is tagged with tag number t and is on screen + * screen + * \param t tag number + * \param screen screen number + * \return True or False + */ +static Bool +isoccupied(TagClientLink *tc, int screen, Client *head, Tag *t) +{ + Client *c; + + for(c = head; c; c = c->next) + if(c->screen == screen && is_client_tagged(tc, c, t)) + return True; + return False; +} + + +static int +taglist_draw(DrawCtx *ctx, + awesome_config *awesomeconf, + VirtScreen vscreen, + int screen, + int offset, + int used __attribute__ ((unused)), + int align __attribute__ ((unused))) +{ + Tag *tag; + Client *sel = awesomeconf->focus->client; + int w = 0, width = 0, location; + int flagsize; + XColor *colors; + + flagsize = (vscreen.font->height + 2) / 4; + + for(tag = vscreen.tags; tag; tag = tag->next) + { + width += textwidth(ctx, vscreen.font, tag->name); + } + location = calculate_offset(vscreen.statusbar.width, width, offset, align); + + width = 0; + for(tag = vscreen.tags; tag; tag = tag->next) + { + w = textwidth(ctx, vscreen.font, tag->name); + if(tag->selected) + colors = vscreen.colors_selected; + else + colors = vscreen.colors_normal; + drawtext(ctx, location + width, 0, w, + vscreen.statusbar.height, vscreen.font, tag->name, colors); + if(isoccupied(vscreen.tclink, screen, awesomeconf->clients, tag)) + drawrectangle(ctx, location + width, 0, flagsize, flagsize, + sel && is_client_tagged(vscreen.tclink, sel, tag), + colors[ColFG]); + width += w; + } + return width; +} + + +Widget * +taglist_new(Statusbar *statusbar) +{ + Widget *w; + w = p_new(Widget, 1); + w->draw = (void*) taglist_draw; + w->statusbar = statusbar; + w->name = name; + return w; +} + + +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 diff --git a/widgets/textbox.c b/widgets/textbox.c new file mode 100644 index 00000000..505f0363 --- /dev/null +++ b/widgets/textbox.c @@ -0,0 +1,35 @@ +#include "util.h" +#include "widget.h" + + +static char name[] = "textbox"; + +static int +textbox_draw(DrawCtx *ctx, + awesome_config *awesomeconf __attribute__ ((unused)), + VirtScreen vscreen, + int screen __attribute__ ((unused)), + int offset, + int used __attribute__ ((unused)), + int align) +{ + int width = textwidth(ctx, vscreen.font, vscreen.statustext); + int location = calculate_offset(vscreen.statusbar.width, width, offset, align); + drawtext(ctx, location, 0, width, vscreen.statusbar.height, + vscreen.font, vscreen.statustext, vscreen.colors_normal); + return width; +} + + +Widget * +textbox_new(Statusbar *statusbar) +{ + Widget *w; + w = p_new(Widget, 1); + w->draw = (void*) textbox_draw; + w->statusbar = statusbar; + w->name = name; + return w; +} + +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99