From 5ba931d1d6ec6d5c0d25253a4aaed6a8a989b721 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Mon, 10 Nov 2008 04:06:14 +0100 Subject: [PATCH] frame: Add frame buttons support: 3 buttons at the top-right of the client for multiple usage --- src/client.c | 21 +++++++--- src/config.c | 13 +++---- src/event.c | 22 +++++++---- src/frame.c | 104 +++++++++++++++++++++++++++++--------------------- src/layout.c | 8 ++-- src/structs.h | 20 +++++----- src/wmfs.h | 20 ++++++++-- wmfsrc | 5 +-- 8 files changed, 129 insertions(+), 84 deletions(-) diff --git a/src/client.c b/src/client.c index ea2bcf7..56ba194 100644 --- a/src/client.c +++ b/src/client.c @@ -165,7 +165,6 @@ client_focus(Client *c) if(sel && sel != c) { sel->colors.frame = conf.client.bordernormal; - sel->colors.titlebar = conf.titlebar.fg_normal; sel->colors.resizecorner = conf.client.resizecorner_normal; frame_update(sel); mouse_grabbuttons(sel, False); @@ -176,7 +175,6 @@ client_focus(Client *c) if(c) { c->colors.frame = conf.client.borderfocus; - c->colors.titlebar = conf.titlebar.fg_focus; c->colors.resizecorner = conf.client.resizecorner_focus; frame_update(c); mouse_grabbuttons(c, True); @@ -242,6 +240,21 @@ client_focus(Client *c) return c; } + +/** Get a client->button[button_number] with a window + * \param b Button type + * \param w Window + * \return The client +*/ + Client* client_gb_button(ButtonType b, Window w) + { + Client *c; + + for(c = clients; c && c->button[b] != w; c = c->next); + + return c; + } + /* }}} */ /** Get a client name @@ -333,13 +346,12 @@ client_manage(Window w, XWindowAttributes *wa) c = emalloc(1, sizeof(Client)); c->win = w; c->geo.x = wa->x; - c->geo.y = wa->y + sgeo.y + conf.titlebar.height; + c->geo.y = wa->y + sgeo.y; c->geo.width = wa->width; c->geo.height = wa->height; c->tag = seltag; frame_create(c); - XSelectInput(dpy, c->win, PropertyChangeMask | StructureNotifyMask); mouse_grabbuttons(c, False); client_size_hints(c); @@ -498,7 +510,6 @@ client_size_hints(Client *c) c->maxay = size.max_aspect.y; } else - c->minax = c->maxax = c->minay = c->maxay = 0; c->hint = (c->maxw && c->minw && c->maxh && c->minh && c->maxw == c->minw && c->maxh == c->minh); diff --git a/src/config.c b/src/config.c index 3c4b916..79d3016 100644 --- a/src/config.c +++ b/src/config.c @@ -206,10 +206,9 @@ init_conf(void) static cfg_opt_t titlebar_opts[] = { - CFG_INT("height", 0, CFGF_NONE), - CFG_STR("fg_focus", "#FFFFFF", CFGF_NONE), - CFG_STR("fg_normal", "#FFFFFF", CFGF_NONE), - CFG_SEC("mouse", mouse_button_opts, CFGF_MULTI), + CFG_INT("height", 0, CFGF_NONE), + CFG_STR("fg", "#FFFFFF", CFGF_NONE), + CFG_SEC("mouse", mouse_button_opts, CFGF_MULTI), CFG_END() }; @@ -399,8 +398,7 @@ init_conf(void) /* titlebar (in client) */ cfgtmp = cfg_getsec(cfg_client, "titlebar"); conf.titlebar.height = cfg_getint(cfgtmp, "height"); - conf.titlebar.fg_focus = var_to_str(cfg_getstr(cfgtmp, "fg_focus")); - conf.titlebar.fg_normal = var_to_str(cfg_getstr(cfgtmp, "fg_normal")); + conf.titlebar.fg = var_to_str(cfg_getstr(cfgtmp, "fg")); conf.titlebar.nmouse = cfg_size(cfgtmp, "mouse"); conf.titlebar.mouse = emalloc(conf.titlebar.nmouse, sizeof(MouseBinding)); @@ -451,7 +449,8 @@ init_conf(void) /* tag */ /* if there is no tag in the conf or more than - * MAXTAG (32) print an error and create only one. */ + * MAXTAG (32) print an error and create only one. + */ conf.colors.tagselfg = strdup(var_to_str(cfg_getstr(cfg_tags, "sel_fg"))); conf.colors.tagselbg = getcolor(var_to_str(cfg_getstr(cfg_tags, "sel_bg"))); conf.tagbordwidth = cfg_getint(cfg_tags, "border_width"); diff --git a/src/event.c b/src/event.c index 10b0151..270aa3d 100644 --- a/src/event.c +++ b/src/event.c @@ -42,7 +42,7 @@ buttonpress(XButtonEvent *ev) int i; char s[6]; - /* Frame & titlebar */ + /* Titlebar */ if((c = client_gb_titlebar(ev->window))) for(i = 0; i < conf.titlebar.nmouse; ++i) if(ev->button == conf.titlebar.mouse[i].button) @@ -145,11 +145,18 @@ configurerequest(XConfigureRequestEvent *ev) if(ev->value_mask & CWHeight) geo.height = ev->height; - if(geo.x != c->geo.x || geo.y != c->geo.y - || geo.width != c->geo.width || geo.height != c->geo.height) + if(geo.x != c->geo.x + || geo.y != c->geo.y + || geo.width != c->geo.width + || geo.height != c->geo.height) { + /* + * Adjust the client's future geo to + * set the correct position of the frame + */ geo.x += BORDH; geo.y += TBARH; + /* Resize */ client_moveresize(c, geo, True); } else @@ -197,9 +204,9 @@ enternotify(XCrossingEvent *ev) return; if((c = client_gb_win(ev->window)) || (c = client_gb_frame(ev->window)) - || (c = client_gb_titlebar(ev->window)) - || (c = client_gb_resize(ev->window))) + || (c = client_gb_titlebar(ev->window))) client_focus(c); + else client_focus(NULL); @@ -218,9 +225,8 @@ expose(XExposeEvent *ev) && (ev->window == infobar->bar->win)) infobar_draw(); - for(c = clients; c; c = c->next) - if(ev->window == c->titlebar) - frame_update(c); + if((c = client_gb_titlebar(ev->window))) + frame_update(c); return; } diff --git a/src/frame.c b/src/frame.c index 5e19234..b1debf2 100644 --- a/src/frame.c +++ b/src/frame.c @@ -40,6 +40,7 @@ void frame_create(Client *c) { XSetWindowAttributes at; + int i; at.background_pixel = conf.client.bordernormal; at.background_pixmap = ParentRelative; @@ -54,41 +55,48 @@ frame_create(Client *c) c->frame_geo.height = FRAMEH(c->geo.height); c->colors.frame = conf.client.bordernormal; c->colors.resizecorner = conf.client.resizecorner_normal; - c->colors.titlebar = conf.titlebar.fg_normal; /* Create frame window */ - c->frame = XCreateWindow(dpy, root, - c->frame_geo.x, - c->frame_geo.y, - c->frame_geo.width, - c->frame_geo.height, 0, - CopyFromParent, InputOutput, CopyFromParent, - CWOverrideRedirect|CWBackPixmap|CWEventMask, &at); + CWIN(c->frame, root, + c->frame_geo.x, + c->frame_geo.y, + c->frame_geo.width, + c->frame_geo.height, 0, + CWOverrideRedirect|CWBackPixmap|CWEventMask, c->colors.frame, &at); /* Create titlebar window */ - c->titlebar = XCreateWindow(dpy, c->frame, 0, 0, - c->frame_geo.width, - TBARH + BORDH, 0, - CopyFromParent, InputOutput, CopyFromParent, - CWEventMask|CWBackPixel, &at); + if(TBARH) + CWIN(c->titlebar, c->frame, 0, 0, + c->frame_geo.width, + TBARH + BORDH, + 0, CWEventMask|CWBackPixel, + c->colors.frame, &at); + + /* Titlebar buttons */ + at.event_mask &= ~EnterWindowMask; /* <- Delete the EnterWindow mask */ + if(CTBAR) + for(i = 0; i < LastButton; ++i) + { + CWIN(c->button[i], c->frame, + BUTX(i), 2, + BUTHW, BUTHW, + 1, CWEventMask|CWBackPixel, + c->colors.frame, &at); + XSetWindowBorder(dpy, c->button[i], getcolor(conf.titlebar.fg)); + } /* Create resize area */ at.cursor = cursor[CurResize]; - c->resize = XCreateWindow(dpy, c->frame, - c->frame_geo.width - RESHW, - c->frame_geo.height - RESHW, - RESHW, RESHW, 0, CopyFromParent, - InputOutput, CopyFromParent, - CWEventMask|CWBackPixel|CWCursor, &at); - - /* Color it */ - XSetWindowBackground(dpy, c->resize, c->colors.resizecorner); - XSetWindowBackground(dpy, c->titlebar, c->colors.frame); - XSetWindowBackground(dpy, c->frame, c->colors.frame); + if(BORDH) + CWIN(c->resize, c->frame, + c->frame_geo.width - RESHW, + c->frame_geo.height - RESHW, + RESHW, + RESHW, 0, + CWEventMask|CWBackPixel|CWCursor, c->colors.resizecorner, &at); /* Reparent window with the frame */ XReparentWindow(dpy, c->win, c->frame, BORDH, BORDH + TBARH); - return; } @@ -111,10 +119,12 @@ frame_moveresize(Client *c, XRectangle geo) c->frame_geo.width, c->frame_geo.height); /* Titlebar */ - XResizeWindow(dpy, c->titlebar, c->frame_geo.width, TBARH + BORDH); + if(TBARH) + XResizeWindow(dpy, c->titlebar, c->frame_geo.width, TBARH + BORDH); /* Resize area */ - XMoveWindow(dpy, c->resize, c->frame_geo.width - RESHW, c->frame_geo.height - RESHW); + if(BORDH) + XMoveWindow(dpy, c->resize, c->frame_geo.width - RESHW, c->frame_geo.height - RESHW); return; } @@ -125,27 +135,33 @@ frame_moveresize(Client *c, XRectangle geo) void frame_update(Client *c) { - int px, py; + int i; - XSetWindowBackground(dpy, c->frame, c->colors.frame); - XSetWindowBackground(dpy, c->titlebar, c->colors.frame); - XSetWindowBackground(dpy, c->resize, c->colors.resizecorner); - - XClearWindow(dpy, c->frame); - XClearWindow(dpy, c->titlebar); - XClearWindow(dpy, c->resize); - - /* Draw the client title \in the titlebar *logeek* */ - if((conf.titlebar.height + BORDH + 1) > font->height) + if(CTBAR) + for(i = 0; i < LastButton; ++i) + { + XSetWindowBackground(dpy, c->button[i], c->colors.frame); + XClearWindow(dpy, c->button[i]); + } + if(BORDH) { - /* x position of the text (center) */ - px = (c->frame_geo.width / 2) - (textw(c->title) / 2); - /* y position of the text (center too) */ - py = (font->height - (font->descent )) + (((TBARH + BORDH) - font->height) / 2); - - draw_text(c->titlebar, px, py, c->colors.titlebar, c->colors.frame, 0, c->title); + XSetWindowBackground(dpy, c->resize, c->colors.resizecorner); + XClearWindow(dpy, c->resize); + } + if(TBARH) + { + XSetWindowBackground(dpy, c->titlebar, c->colors.frame); + XClearWindow(dpy, c->titlebar); } + XSetWindowBackground(dpy, c->frame, c->colors.frame); + XClearWindow(dpy, c->frame); + + if((TBARH + BORDH + 1) > font->height) + draw_text(c->titlebar, + (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); return; } diff --git a/src/layout.c b/src/layout.c index 350b821..cea83af 100644 --- a/src/layout.c +++ b/src/layout.c @@ -198,7 +198,7 @@ nexttiled(Client *c) } /** Set the mwfact - * \param cmd Mwfact + * \param cmd Mwfact (string) */ void uicb_set_mwfact(uicb_t cmd) @@ -218,7 +218,7 @@ uicb_set_mwfact(uicb_t cmd) } /** Set the nmaster - * \param cmd nmaster + * \param cmd Nmaster (string) */ void uicb_set_nmaster(uicb_t cmd) @@ -324,7 +324,7 @@ multi_tile(Position type) if(type == Top) mastergeo.y = (n <= nmaster) ? sgeo.y : sgeo.y + (sgeo.height - mwfact) - border; mastergeo.width = (sgeo.width / nmaster) - BORDH; - mastergeo.height = (n <= nmaster) ? sgeo.height - BORDH : mwfact; + mastergeo.height = (n <= nmaster) ? sgeo.height - border : mwfact; } else { @@ -346,7 +346,7 @@ multi_tile(Position type) for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next), ++i) { - /* Set client property, 'don't care */ + /* Set client property */ c->max = c->lmax = False; c->tile = True; c->ogeo.x = c->geo.x; c->ogeo.y = c->geo.y; diff --git a/src/structs.h b/src/structs.h index 2031b7a..7a655ec 100644 --- a/src/structs.h +++ b/src/structs.h @@ -51,9 +51,12 @@ enum { CurNormal, CurResize, CurMove, CurLast }; enum { WMState, WMProtocols, WMName, WMDelete, WMLast }; enum { NetSupported, NetWMName, NetLast }; typedef enum { Top = 0, Bottom, Right, Left, Center, PositionLast } Position; +typedef enum { CloseButton = 0, MaxButton = 1, FreeButton = 2, LastButton } ButtonType; -/* BarWindow Structure - * (titlebar, topbar..) */ +/* + * BarWindow Structure + * (titlebar, topbar..) + */ typedef struct { Window win; @@ -85,14 +88,12 @@ struct Client Window win; Window frame; Window resize, titlebar; + Window button[LastButton]; struct { uint frame; uint resizecorner; - char *titlebar; } colors; - /* Border */ - int border; /* Client Layout Information */ Bool max, tile, free, hide; Bool hint, lmax, havetbar; @@ -157,8 +158,10 @@ typedef struct int tagbordwidth; struct { - /* Only the colors will be use for text - * are 'char*' (for xprint -> XftColorAllocName) */ + /* + * Only the colors will be use for text + * are 'char*' (for xprint -> XftColorAllocName) + */ uint bar; char *text; char *tagselfg; @@ -187,8 +190,7 @@ typedef struct struct { int height; - char *fg_focus; - char *fg_normal; + char *fg; MouseBinding *mouse; int nmouse; } titlebar; diff --git a/src/wmfs.h b/src/wmfs.h index f224549..98e6f86 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -59,18 +59,29 @@ #define MouseMask (ButtonMask | PointerMotionMask) #define KeyMask (KeyPressMask | KeyReleaseMask) +#define CWIN(win, parent, x, y, w, h, b, mask, col, at) \ + win = XCreateWindow(dpy, parent, x, y, w, h, b, CopyFromParent, \ + InputOutput, CopyFromParent, mask, at); \ + XSetWindowBackground(dpy, win, col); + #define MAXH DisplayHeight(dpy, screen) #define MAXW DisplayWidth(dpy, screen) -#define FRAMEW(w) w + conf.client.borderheight * 2 -#define FRAMEH(h) h + (conf.client.borderheight * 2) + conf.titlebar.height #define BORDH conf.client.borderheight #define TBARH conf.titlebar.height -#define RESHW 15 +#define FRAMEW(w) w + BORDH * 2 +#define FRAMEH(h) h + (BORDH * 2) + TBARH + +/* To checking if wmfs can create and use the titlebar buttons */ +#define CTBAR TBARH - BORDH > 1 + +#define BUTHW (BORDH + TBARH) - 6 +#define BUTX(b) (b + 0.5) * BUTHW + BORDH + 1 +#define RESHW 5 * BORDH #define CHECK(x) if(!x) return #define ITOA(p ,n) sprintf(p, "%d", n) -#define debug(p) fprintf(stderr, "debug: %d\n", p) +#define deb(p) fprintf(stderr, "debug: %d\n", p) #define PAD 8 /* bar.c */ @@ -106,6 +117,7 @@ Client* client_gb_win(Window w); Client* client_gb_frame(Window w); Client* client_gb_titlebar(Window w); Client* client_gb_resize(Window w); +Client* client_gb_button(ButtonType b, Window w); /* }}} */ void client_get_name(Client *c); void client_hide(Client *c); diff --git a/wmfsrc b/wmfsrc index c71c51f..06b2847 100644 --- a/wmfsrc +++ b/wmfsrc @@ -81,9 +81,8 @@ client titlebar { - height = 11 - fg_normal = "#B4B4B4" - fg_focus = "#D4D4D4" + height = 11 + fg = "#D4D4D4" mouse { button = "1" func = "client_raise" } mouse { button = "1" func = "mouse_move" }