From 22431c203c4f3b516cb5a8acd297384fdda0444c Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Thu, 13 Nov 2008 08:03:56 +0100 Subject: [PATCH] infobar: New infobar with new BarWindow; Add shadow, better rendering, improve system... --- src/bar.c | 53 ++++++++++++++---- src/client.c | 5 +- src/config.c | 1 + src/draw.c | 7 +-- src/event.c | 75 ++++++++++--------------- src/frame.c | 29 +++++----- src/infobar.c | 152 ++++++++++++++++++-------------------------------- src/structs.h | 19 +++++-- src/tag.c | 2 + src/wmfs.c | 4 +- src/wmfs.h | 8 ++- 11 files changed, 164 insertions(+), 191 deletions(-) diff --git a/src/bar.c b/src/bar.c index 38d436a..3a4a51d 100644 --- a/src/bar.c +++ b/src/bar.c @@ -37,14 +37,15 @@ * \param x X position * \param y Y position * \param w BarWindow Width - * \param h BarWindow Height - * \param bord Bord width + * \param h BarWindow HeightXS * \param color BarWindow color * \param entermask Bool for know if the EnterMask mask is needed * \return The new BarWindow pointer */ BarWindow* -bar_create(Window parent, int x, int y, uint w, uint h, int bord, uint color, Bool entermask) +bar_create(Window parent, + int x, int y, uint w, uint h, + uint color, Bool entermask) { XSetWindowAttributes at; BarWindow *bw; @@ -61,17 +62,25 @@ bar_create(Window parent, int x, int y, uint w, uint h, int bord, uint color, Bo at.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | ButtonPressMask | ExposureMask | StructureNotifyMask; - bw->win = XCreateWindow(dpy, parent, x, y, w, h, bord, DefaultDepth(dpy, screen), + /* Create window */ + bw->win = XCreateWindow(dpy, parent, x, y, w, h, 0, DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), CWOverrideRedirect | CWBackPixmap | CWEventMask, &at); bw->dr = XCreatePixmap(dpy, parent, w, h, DefaultDepth(dpy, screen)); + /* His border */ + CWIN(bw->border.left, bw->win, 0, 0, SHADH, h, 0, CWBackPixel, color_enlight(color), &at); + CWIN(bw->border.top, bw->win, 0, 0, w, SHADH, 0, CWBackPixel, color_enlight(color), &at); + CWIN(bw->border.bottom, bw->win, 0, h - SHADH, w, SHADH, 0, CWBackPixel, SHADC, &at); + CWIN(bw->border.right, bw->win, w - SHADH, 0, SHADH, h, 0, CWBackPixel, SHADC, &at); + bw->geo.x = x; bw->geo.y = y; bw->geo.width = w; bw->geo.height = h; - bw->bord = bord; bw->color = color; + bw->border.light = color_enlight(color); + bw->border.dark = SHADC; return bw; } @@ -83,6 +92,7 @@ void bar_delete(BarWindow *bw) { XSelectInput(dpy, bw->win, NoEventMask); + XDestroySubwindows(dpy, bw->win); XDestroyWindow(dpy, bw->win); XFreePixmap(dpy, bw->dr); free(bw); @@ -98,9 +108,10 @@ bar_map(BarWindow *bw) { CHECK(!bw->mapped); - XMapRaised(dpy, bw->win); - bw->mapped = True; + XMapWindow(dpy, bw->win); + XMapSubwindows(dpy, bw->win); + bw->mapped = True; return; } @@ -113,7 +124,9 @@ bar_unmap(BarWindow *bw) { CHECK(bw->mapped); + XUnmapSubwindows(dpy, bw->win); XUnmapWindow(dpy, bw->win); + bw->mapped = False; return; @@ -146,27 +159,43 @@ bar_resize(BarWindow *bw, uint w, uint h) bw->geo.width = w; bw->geo.height = h; XFreePixmap(dpy, bw->dr); - bw->dr = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); + /* Frame */ + bw->dr = XCreatePixmap(dpy, root, w - SHADH, h - SHADH, DefaultDepth(dpy, screen)); XResizeWindow(dpy, bw->win, w, h); + /* Border */ + XResizeWindow(dpy, bw->border.left, SHADH, h); + XResizeWindow(dpy, bw->border.top, w, SHADH); + XResizeWindow(dpy, bw->border.bottom, w, SHADH); + XMoveResizeWindow(dpy, bw->border.right, w - SHADH, 0, SHADH, h); + + return; } -/** Refresh the BarWindowColor +/** Refresh the BarWindow Color * \param bw BarWindow pointer */ void bar_refresh_color(BarWindow *bw) { draw_rectangle(bw->dr, 0, 0, bw->geo.width, bw->geo.height, bw->color); - if(bw->bord) - XSetWindowBorder(dpy, bw->win, bw->color); + + XSetWindowBackground(dpy, bw->border.left , bw->border.light); + XSetWindowBackground(dpy, bw->border.top , bw->border.light); + XSetWindowBackground(dpy, bw->border.bottom , bw->border.dark); + XSetWindowBackground(dpy, bw->border.right , bw->border.dark); + + XClearWindow(dpy, bw->border.left); + XClearWindow(dpy, bw->border.top); + XClearWindow(dpy, bw->border.bottom); + XClearWindow(dpy, bw->border.right); return; } -/** Refresh a BarWindow +/** Refresh the BarWindow * \param bw BarWindow pointer */ void diff --git a/src/client.c b/src/client.c index 6cb8ca9..be98638 100644 --- a/src/client.c +++ b/src/client.c @@ -223,7 +223,7 @@ client_focus(Client *c) { Client *c; - for(c = clients; c && c->titlebar != w; c = c->next); + for(c = clients; c && c->titlebar->win != w; c = c->next); return c; } @@ -313,6 +313,7 @@ client_map(Client *c) XMapWindow(dpy, c->frame); XMapSubwindows(dpy, c->frame); + bar_map(c->titlebar); return; } @@ -563,6 +564,7 @@ client_unmanage(Client *c) setwinstate(c->win, WithdrawnState); XDestroySubwindows(dpy, c->frame); XDestroyWindow(dpy, c->frame); + bar_delete(c->titlebar); XFree(c->title); efree(c); XSync(dpy, False); @@ -581,6 +583,7 @@ client_unmap(Client *c) XUnmapWindow(dpy, c->frame); XUnmapSubwindows(dpy, c->frame); + bar_unmap(c->titlebar); return; } diff --git a/src/config.c b/src/config.c index a3e972c..2d12b6b 100644 --- a/src/config.c +++ b/src/config.c @@ -491,6 +491,7 @@ init_conf(void) fprintf(stderr, "WMFS Configuration: Warning! " "tag \"%s\" is already defined\n", conf.tag[j].name); seltag = 1; + prevtag = 0; for(i = 0; i < conf.ntag; ++i) tags[i + 1] = conf.tag[i]; diff --git a/src/draw.c b/src/draw.c index 83c3a1c..23709f6 100644 --- a/src/draw.c +++ b/src/draw.c @@ -37,12 +37,11 @@ * \param x X position * \param y Y position * \param fg Foreground text color - * \param bg Background text color * \param pad Text padding * \param str String that will be draw */ void -draw_text(Drawable d, int x, int y, char* fg, uint bg, int pad, char *str) +draw_text(Drawable d, int x, int y, char* fg, int pad, char *str) { XftColor xftcolor; XftDraw *xftd; @@ -50,10 +49,6 @@ draw_text(Drawable d, int x, int y, char* fg, uint bg, int pad, char *str) /* Transform X Drawable -> Xft Drawable */ xftd = XftDrawCreate(dpy, d, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen)); - /* Color the text font */ - draw_rectangle(d, x - pad/2, 0, textw(str) + pad, infobar->geo.height, bg); - - /* Alloc text color */ XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), fg, &xftcolor); diff --git a/src/event.c b/src/event.c index 270aa3d..e22ab7e 100644 --- a/src/event.c +++ b/src/event.c @@ -67,55 +67,32 @@ buttonpress(XButtonEvent *ev) if(conf.root.mouse[i].func) conf.root.mouse[i].func(conf.root.mouse[i].cmd); - /* Bar */ + /* Tag */ + for(i = 1; i < conf.ntag + 1; ++i) { - if(ev->window == infobar->bar->win) + ITOA(s, i); + if(ev->window == infobar->tags[i]->win) { - /* Tag*/ - for(i = 0; i < conf.ntag + 1; ++i) - { - if(ev->x > taglen[i-1] - 3 - && ev->x < (taglen[i] - 3)) - { - ITOA(s, i); - if(ev->button == Button1) - uicb_tag(s); - if(ev->button == Button3) - uicb_tagtransfert(s); - } - } - if(ev->x < taglen[conf.ntag]) - { - if(ev->button == Button4) - uicb_tag("+1"); - if (ev->button == Button5) - uicb_tag("-1"); - } + if(ev->button == Button1) + uicb_tag(s); + if(ev->button == Button3) + uicb_tagtransfert(s); + if(ev->button == Button4) + uicb_tag("+1"); + if (ev->button == Button5) + uicb_tag("-1"); } - /* Layout */ - { - if(ev->window == infobar->layout_switch->win) - { - if(ev->button == Button1 - || ev->button == Button4) - layoutswitch(True); + } - if(ev->button == Button3 - || ev->button == Button5) - layoutswitch(False); - } - - if(ev->window == infobar->layout_type_switch->win) - { - if(ev->button == Button1 - || ev->button == Button4) - layout_tile_switch(True); - - if(ev->button == Button3 - || ev->button == Button5) - layout_tile_switch(False); - } - } + /* Layout button */ + if(ev->window == infobar->layout_button->win) + { + if(ev->button == Button1 + || ev->button == Button4) + layoutswitch(True); + if(ev->button == Button3 + || ev->button == Button5) + layoutswitch(False); } return; @@ -220,11 +197,19 @@ void expose(XExposeEvent *ev) { Client *c; + int i; if(ev->count == 0 && (ev->window == infobar->bar->win)) infobar_draw(); + for(i = 1; i < conf.ntag + 1; ++i) + if(ev->window == infobar->tags[i]->win) + infobar_draw_taglist(); + + if(ev->window == infobar->layout_button->win) + infobar_draw_layout(); + if((c = client_gb_titlebar(ev->window))) frame_update(c); diff --git a/src/frame.c b/src/frame.c index 42ef6ba..65ae55c 100644 --- a/src/frame.c +++ b/src/frame.c @@ -67,15 +67,8 @@ frame_create(Client *c) /* Create titlebar window */ if(TBARH) - { - CWIN(c->titlebar, c->frame, 0, 0, - c->frame_geo.width, - (TBARH + SHADH/2) + BORDH, - 1, CWEventMask|CWBackPixel, - c->colors.frame, &at); - XSetWindowBorder(dpy, c->titlebar, SHADC); - } - /* Titlebar buttons */ + c->titlebar = bar_create(c->frame, 0, 0, c->frame_geo.width, TBARH + BORDH, c->colors.frame, True); + at.event_mask &= ~(EnterWindowMask | LeaveWindowMask); /* <- Delete useless mask */ /* Create resize area */ @@ -124,7 +117,7 @@ frame_moveresize(Client *c, XRectangle geo) /* Titlebar */ if(TBARH) - XResizeWindow(dpy, c->titlebar, c->frame_geo.width, (TBARH - SHADH*2) + BORDH); + bar_resize(c->titlebar, c->frame_geo.width, TBARH + BORDH); /* Resize area */ XMoveWindow(dpy, c->resize, c->frame_geo.width - RESHW, c->frame_geo.height - RESHW); @@ -139,7 +132,7 @@ frame_moveresize(Client *c, XRectangle geo) } /** Update the client frame; Set the new color - * and the title ---> refresh all + * and the title --> refresh * \param c Client pointer */ void @@ -147,10 +140,10 @@ frame_update(Client *c) { if(TBARH) { - XSetWindowBackground(dpy, c->titlebar, c->colors.frame); - XSetWindowBorder(dpy, c->titlebar, SHADC); - XClearWindow(dpy, c->titlebar); + c->titlebar->color = c->colors.frame; + bar_refresh_color(c->titlebar); } + XSetWindowBackground(dpy, c->frame, c->colors.frame); XSetWindowBackground(dpy, c->resize, c->colors.resizecorner); XSetWindowBackground(dpy, c->left, color_enlight(c->colors.frame)); @@ -166,10 +159,14 @@ frame_update(Client *c) XClearWindow(dpy, c->bottom); if((TBARH + BORDH + 1) > font->height) - draw_text(c->titlebar, + { + draw_text(c->titlebar->dr, (c->frame_geo.width / 2) - (textw(c->title) / 2), (font->height - (font->descent)) + (((TBARH + BORDH) - font->height) / 2), - conf.titlebar.fg, c->colors.frame, 0, c->title); + conf.titlebar.fg, 0, c->title); + bar_refresh(c->titlebar); + } + return; } diff --git a/src/infobar.c b/src/infobar.c index 895fe2b..8525bc9 100644 --- a/src/infobar.c +++ b/src/infobar.c @@ -37,25 +37,37 @@ void infobar_init(void) { - infobar = emalloc(1, sizeof(InfoBar)); + int i, j = 0; + infobar = emalloc(1, sizeof(InfoBar)); infobar->geo.height = font->height * 1.5; infobar->geo.y = (conf.bartop) ? 0 : MAXH - infobar->geo.height; /* Create infobar barwindow */ - infobar->bar = bar_create(root, 0, infobar->geo.y, MAXW, infobar->geo.height, 0, conf.colors.bar, False); + infobar->bar = bar_create(root, 0, infobar->geo.y, MAXW, infobar->geo.height, conf.colors.bar, False); + + + /* Create tags window */ + for(i = 1; i < conf.ntag + 1; ++i) + { + infobar->tags[i] = bar_create(infobar->bar->win, j, 0, textw(tags[i].name) + PAD, + infobar->geo.height, conf.colors.bar, False); + j += textw(tags[i].name) + PAD; + XMapSubwindows(dpy, infobar->tags[i]->win); + } /* Create layout switch & layout type switch barwindow */ - infobar->layout_switch = bar_create(infobar->bar->win, 0, 0, - 1, infobar->geo.height - 1, 0, - conf.colors.layout_bg, False); - infobar->layout_type_switch = bar_create(infobar->bar->win, 0, 0, - 1, infobar->geo.height, - 0, conf.colors.layout_bg, False); + infobar->layout_button = bar_create(infobar->bar->win, j + PAD / 2, 0, + textw(tags[seltag].layout.symbol) + PAD, + infobar->geo.height, conf.colors.layout_bg, False); /* Map all */ bar_map(infobar->bar); - bar_map(infobar->layout_switch); + bar_refresh_color(infobar->bar); + bar_refresh(infobar->bar); + + XMapSubwindows(dpy, infobar->layout_button->win); + strcpy(infobar->statustext, "WMFS-" WMFS_VERSION); infobar_draw(); @@ -67,96 +79,32 @@ infobar_init(void) void infobar_draw(void) { - char buf[256]; - /* Refresh bar color */ - bar_refresh_color(infobar->bar); - /* Draw taglist */ infobar_draw_taglist(); - - /* Draw layout symbol */ infobar_draw_layout(); - - /* Draw mwfact && nmaster info */ - sprintf(buf, "mwfact: %.2f - nmaster: %d", - tags[seltag].mwfact, - tags[seltag].nmaster); - draw_text(infobar->bar->dr, infobar->lastsep + PAD/1.5, font->height, conf.colors.text, conf.colors.bar, 0, buf); - draw_rectangle(infobar->bar->dr, textw(buf) + infobar->lastsep + PAD, - 0, conf.tagbordwidth, infobar->geo.height, conf.colors.tagbord); + bar_refresh_color(infobar->bar); /* Draw status text */ draw_text(infobar->bar->dr, MAXW - textw(infobar->statustext), font->height, - conf.colors.text, - conf.colors.bar, 0, infobar->statustext); + conf.colors.text, 0, infobar->statustext); - /* Bar border */ - if(conf.tagbordwidth) - { - draw_rectangle(infobar->bar->dr, 0, ((conf.bartop) ? infobar->geo.height - 1: 0), - MAXW, 1, conf.colors.tagbord); - draw_rectangle(infobar->bar->dr, MAXW - textw(infobar->statustext) - 5, - 0, conf.tagbordwidth, infobar->geo.height, conf.colors.tagbord); - } - - /* Refresh the bar */ bar_refresh(infobar->bar); return; } /** Draw the layout button in the InfoBar -*/ + */ void infobar_draw_layout(void) { - int px, py, width; - char symbol[256]; - - /* Set symbol & position */ - px = width = taglen[conf.ntag]; - if(tags[seltag].layout.func == freelayout - || tags[seltag].layout.func == maxlayout) - strcpy(symbol, tags[seltag].layout.symbol); - else - strcpy(symbol, conf.tile_symbol); - - /* Draw layout name/symbol */ - bar_refresh_color(infobar->layout_switch); - - bar_move(infobar->layout_switch, px, 0); - bar_resize(infobar->layout_switch, textw(symbol) + PAD, infobar->geo.height); - draw_text(infobar->layout_switch->dr, PAD/2, font->height, - conf.colors.layout_fg, - conf.colors.layout_bg, - PAD, symbol); - width += textw(symbol) + PAD; - bar_refresh(infobar->layout_switch); - - if(tags[seltag].layout.func != freelayout - && tags[seltag].layout.func != maxlayout) - { - bar_map(infobar->layout_type_switch); - bar_refresh_color(infobar->layout_type_switch); - bar_move(infobar->layout_type_switch, px + infobar->layout_switch->geo.width + PAD/2, py); - bar_resize(infobar->layout_type_switch, textw(tags[seltag].layout.symbol) + PAD, infobar->geo.height); - draw_text(infobar->layout_type_switch->dr, PAD/2, font->height, - conf.colors.layout_fg, - conf.colors.layout_bg, - PAD, tags[seltag].layout.symbol); - width += textw(tags[seltag].layout.symbol) + PAD * 1.5; - - bar_refresh(infobar->layout_type_switch); - } - else - bar_unmap(infobar->layout_type_switch); - - /* Draw right separation */ - infobar->lastsep = width + PAD / 2; - draw_rectangle(infobar->bar->dr, infobar->lastsep, 0, - conf.tagbordwidth, infobar->geo.height, conf.colors.tagbord); + bar_resize(infobar->layout_button, textw(tags[seltag].layout.symbol) + PAD, infobar->geo.height); + bar_refresh_color(infobar->layout_button); + draw_text(infobar->layout_button->dr, PAD / 2, font->height, + conf.colors.layout_fg, 0, tags[seltag].layout.symbol); + bar_refresh(infobar->layout_button); return; } @@ -167,31 +115,37 @@ void infobar_draw_taglist(void) { int i; - char buf[conf.ntag][256]; - char p[4]; - taglen[0] = PAD/2; - for(i = 0; i < conf.ntag; ++i) + for(i = 1; i < conf.ntag + 1; ++i) { - /* Make the tags string */ - ITOA(p, client_pertag(i+1)); - sprintf(buf[i], "%s<%s>", tags[i+1].name, (client_pertag(i+1)) ? p : ""); - /* Draw the string */ - draw_text(infobar->bar->dr, taglen[i], font->height, - ((i+1 == seltag) ? conf.colors.tagselfg : conf.colors.text), - ((i+1 == seltag) ? conf.colors.tagselbg : conf.colors.bar), PAD, buf[i]); - - /* Draw the tag separation */ - draw_rectangle(infobar->bar->dr, taglen[i] + textw(buf[i]) + PAD/2, - 0, conf.tagbordwidth, infobar->geo.height, conf.colors.tagbord); - - /* Edit taglen[i+1] for the next time */ - taglen[i+1] = taglen[i] + textw(buf[i]) + PAD + conf.tagbordwidth; + infobar->tags[i]->color = ((i == seltag) ? conf.colors.tagselbg : conf.colors.bar); + bar_refresh_color(infobar->tags[i]); + draw_text(infobar->tags[i]->dr, PAD / 2, font->height, + ((i == seltag) ? conf.colors.tagselfg : conf.colors.text), + 0, tags[i].name); + bar_refresh(infobar->tags[i]); } return; } +void +infobar_destroy(void) +{ + int i; + + bar_delete(infobar->bar); + for(i = 1; i < conf.ntag + 1; ++i) + { + XFreePixmap(dpy, infobar->tags[i]->dr); + XDestroySubwindows(dpy, infobar->tags[i]->win); + } + XDestroySubwindows(dpy, infobar->layout_button->win); + + return; +} + + /** Toggle the infobar position * \param cmd uicb_t type unused */ diff --git a/src/structs.h b/src/structs.h index 66f467d..9c0217d 100644 --- a/src/structs.h +++ b/src/structs.h @@ -59,11 +59,18 @@ typedef enum { CloseButton = 0, MaxButton = 1, FreeButton = 2, LastButton } Butt */ typedef struct { + /* Frame window */ Window win; Drawable dr; - XRectangle geo; + struct + { + /* Border Window */ + Window left, right, top, bottom; + /* Border color */ + uint dark, light; + } border; uint color; - int bord; + XRectangle geo; Bool mapped; } BarWindow; @@ -86,7 +93,8 @@ struct Client int minax, maxax, minay, maxay; /* Client composant */ Window win; - Window frame, resize, titlebar; + BarWindow *titlebar; + Window frame, resize; Window right, left, top, bottom; struct { @@ -122,10 +130,9 @@ typedef struct typedef struct { BarWindow *bar; - BarWindow *layout_switch; - BarWindow *layout_type_switch; + BarWindow *layout_button; + BarWindow *tags[MAXTAG]; XRectangle geo; - int lastsep; char statustext[1024]; } InfoBar; diff --git a/src/tag.c b/src/tag.c index 7ec373d..149c3e6 100644 --- a/src/tag.c +++ b/src/tag.c @@ -48,6 +48,7 @@ uicb_tag(uicb_t cmd) if(tmp + seltag < 1 || tmp + seltag > conf.ntag) return; + prevtag = seltag; seltag += tmp; } else @@ -55,6 +56,7 @@ uicb_tag(uicb_t cmd) if(tmp == seltag || tmp > conf.ntag) return; + prevtag = seltag; seltag = tmp; } arrange(); diff --git a/src/wmfs.c b/src/wmfs.c index 15002b4..c966c17 100644 --- a/src/wmfs.c +++ b/src/wmfs.c @@ -72,9 +72,7 @@ quit(void) XFreeCursor(dpy, cursor[CurNormal]); XFreeCursor(dpy, cursor[CurMove]); XFreeCursor(dpy, cursor[CurResize]); - bar_delete(infobar->bar); - bar_delete(infobar->layout_switch); - bar_delete(infobar->layout_type_switch); + infobar_destroy(); efree(infobar); efree(keys); efree(conf.titlebar.mouse); diff --git a/src/wmfs.h b/src/wmfs.h index 2093c3b..ce56b20 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -84,10 +84,10 @@ #define CHECK(x) if(!x) return #define ITOA(p ,n) sprintf(p, "%d", n) #define deb(p) fprintf(stderr, "debug: %d\n", p) -#define PAD 8 +#define PAD 14 /* bar.c */ -BarWindow *bar_create(Window parent, int x, int y, uint w, uint h, int bord, uint color, Bool entermask); +BarWindow *bar_create(Window parent, int x, int y, uint w, uint h, uint color, Bool entermask); void bar_delete(BarWindow *bw); void bar_map(BarWindow *bw); void bar_unmap(BarWindow *bw); @@ -97,7 +97,7 @@ void bar_refresh_color(BarWindow *bw); void bar_refresh(BarWindow *bw); /* draw.c */ -void draw_text(Drawable d, int x, int y, char* fg, uint bg, int pad, char *str); +void draw_text(Drawable d, int x, int y, char* fg, int pad, char *str); void draw_rectangle(Drawable dr, int x, int y, uint w, uint h, uint color); ushort textw(const char *text); @@ -106,6 +106,7 @@ void infobar_init(void); void infobar_draw(void); void infobar_draw_layout(void); void infobar_draw_taglist(void); +void infobar_destroy(void); void uicb_infobar_togglepos(uicb_t cmd); /* client.c */ @@ -249,6 +250,7 @@ InfoBar *infobar; Tag tags[MAXTAG]; int taglen[MAXTAG]; int seltag; +int prevtag; /* Important Client */ Client *clients;