diff --git a/CMakeLists.txt b/CMakeLists.txt index 486a15b..0a2ec09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,7 +38,7 @@ set(wmfs_src src/bar.c src/draw.c src/client.c - src/titlebar.c + src/frame.c src/infobar.c) # Set the executable from the wmfs_src diff --git a/src/bar.c b/src/bar.c index cdb3e6d..1879dfb 100644 --- a/src/bar.c +++ b/src/bar.c @@ -79,11 +79,11 @@ bar_delete(BarWindow *bw) void bar_map(BarWindow *bw) { - if(!bw->mapped) - { - XMapRaised(dpy, bw->win); - bw->mapped = True; - } + CHECK(!bw->mapped); + + XMapRaised(dpy, bw->win); + bw->mapped = True; + return; } @@ -91,11 +91,10 @@ bar_map(BarWindow *bw) void bar_unmap(BarWindow *bw) { - if(bw->mapped) - { - XUnmapWindow(dpy, bw->win); - bw->mapped = False; - } + CHECK(bw->mapped); + + XUnmapWindow(dpy, bw->win); + bw->mapped = False; return; } diff --git a/src/client.c b/src/client.c index 3bd2871..6ae3e70 100644 --- a/src/client.c +++ b/src/client.c @@ -119,20 +119,24 @@ uicb_client_next(uicb_t cmd) void client_focus(Client *c) { - Client *cc; - 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); - XSetWindowBorder(dpy, sel->win, conf.client.bordernormal); } selbytag[seltag] = sel = 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); - XSetWindowBorder(dpy, c->win, conf.client.borderfocus); if(conf.raisefocus) client_raise(c); XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); @@ -140,11 +144,6 @@ client_focus(Client *c) else XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - /* Update all visible titlebar */ - for(cc = clients; cc; cc = cc->next) - if(!ishide(cc)) - titlebar_update(cc); - return; } @@ -158,6 +157,19 @@ client_get(Window w) return c; } +void +client_get_name(Client *c) +{ + + XFetchName(dpy, c->win, &(c->title)); + if(!c->title) + c->title = strdup("WMFS"); + + frame_update(c); + + return; +} + void client_hide(Client *c) { @@ -182,8 +194,7 @@ uicb_client_kill(uicb_t cmd) { XEvent ev; - if(!sel) - return; + CHECK(sel); ev.type = ClientMessage; ev.xclient.window = sel->win; @@ -199,16 +210,10 @@ uicb_client_kill(uicb_t cmd) void client_map(Client *c) { - if(!c) - return; + CHECK(c); - XMapWindow(dpy, c->win); - XMapSubwindows(dpy, c->win); - if(conf.titlebar.exist) - { - XMapWindow(dpy, c->tbar->win); - bar_refresh(c->tbar); - } + XMapWindow(dpy, c->frame); + XMapSubwindows(dpy, c->frame); return; } @@ -219,7 +224,6 @@ client_manage(Window w, XWindowAttributes *wa) Client *c, *t = NULL; Window trans; Status rettrans; - XWindowChanges winc; c = emalloc(1, sizeof(Client)); c->win = w; @@ -228,33 +232,24 @@ client_manage(Window w, XWindowAttributes *wa) c->geo.width = wa->width; c->geo.height = wa->height; c->tag = seltag; - c->border = conf.client.borderheight; - /* Create titlebar */ - if(conf.titlebar.exist) - titlebar_create(c); + frame_create(c); - winc.border_width = c->border; - XConfigureWindow(dpy, w, CWBorderWidth, &winc); - XSetWindowBorder(dpy, w, conf.client.bordernormal); + XSelectInput(dpy, c->win, PropertyChangeMask | StructureNotifyMask); mouse_grabbuttons(c, False); - XSelectInput(dpy, w, EnterWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask); client_size_hints(c); - titlebar_update(c); if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success)) for(t = clients; t && t->win != trans; t = t->next); - if(t) - c->tag = t->tag; - if(!c->free) - c->free = (rettrans == Success) || c->hint; + if(t) c->tag = t->tag; + if(!c->free) c->free = (rettrans == Success) || c->hint; efree(t); client_attach(c); - XMoveResizeWindow(dpy, c->win, c->geo.x, c->geo.y, c->geo.width, c->geo.height); client_map(c); + client_get_name(c); client_raise(c); - setwinstate(c->win, NormalState); client_focus(c); + setwinstate(c->win, NormalState); arrange(); return; @@ -263,8 +258,7 @@ client_manage(Window w, XWindowAttributes *wa) void client_moveresize(Client *c, XRectangle geo, bool r) { - if(!c) - return; + CHECK(c); /* Resize hints {{{ */ if(r) @@ -319,13 +313,8 @@ client_moveresize(Client *c, XRectangle geo, bool r) || c->geo.height != geo.height) { c->geo = geo; - - XMoveResizeWindow(dpy, c->win, geo.x, geo.y, - geo.width, geo.height); - if(conf.titlebar.exist) - titlebar_update_position(c); - - titlebar_update(c); + frame_moveresize(c, geo); + XResizeWindow(dpy, c->win, geo.width, geo.height); XSync(dpy, False); } @@ -409,12 +398,7 @@ client_raise(Client *c) if(!c || c->max || c->tile) return; - XRaiseWindow(dpy, c->win); - if(conf.titlebar.exist) - { - XRaiseWindow(dpy, c->tbar->win); - titlebar_update(c); - } + XRaiseWindow(dpy, c->frame); return; } @@ -457,8 +441,10 @@ client_unmanage(Client *c) * and set the withdraw state */ client_detach(c); setwinstate(c->win, WithdrawnState); - if(conf.titlebar.exist) - titlebar_delete(c); + + XDestroySubwindows(dpy, c->frame); + XDestroyWindow(dpy, c->frame); + XFree(c->title); efree(c); XSync(dpy, False); arrange(); @@ -469,13 +455,10 @@ client_unmanage(Client *c) void client_unmap(Client *c) { - if(!c) - return; + CHECK(c); - XUnmapWindow(dpy, c->win); - XUnmapSubwindows(dpy, c->win); - if(conf.titlebar.exist) - XUnmapWindow(dpy, c->tbar->win); + XUnmapWindow(dpy, c->frame); + XUnmapSubwindows(dpy, c->frame); return; } diff --git a/src/config.c b/src/config.c index 0de9b71..59f896a 100644 --- a/src/config.c +++ b/src/config.c @@ -204,13 +204,9 @@ init_conf(void) static cfg_opt_t titlebar_opts[] = { - CFG_STR("position", "top", CFGF_NONE), CFG_INT("height", 0, CFGF_NONE), - CFG_STR("bg_normal", "#090909", CFGF_NONE), - CFG_STR("bg_focus", "#090909", CFGF_NONE), CFG_STR("fg_focus", "#FFFFFF", CFGF_NONE), CFG_STR("fg_normal", "#FFFFFF", CFGF_NONE), - CFG_STR("text_align", "left", CFGF_NONE), CFG_SEC("mouse", mouse_button_opts, CFGF_MULTI), CFG_END() }; @@ -220,8 +216,11 @@ init_conf(void) CFG_INT("border_height", 1, CFGF_NONE), CFG_STR("border_normal", "#354B5C", CFGF_NONE), CFG_STR("border_focus", "#6286A1", CFGF_NONE), + CFG_STR("resize_corner_normal", "#ff0000", CFGF_NONE), + CFG_STR("resize_corner_focus", "#ff0000", CFGF_NONE), CFG_STR("modifier", "Alt", CFGF_NONE), CFG_SEC("mouse", mouse_button_opts, CFGF_MULTI), + CFG_SEC("titlebar", titlebar_opts, CFGF_NONE), CFG_END() }; @@ -294,7 +293,6 @@ init_conf(void) CFG_SEC("misc", misc_opts, CFGF_NONE), CFG_SEC("variables", variables_opts, CFGF_NONE), CFG_SEC("root", root_opts, CFGF_NONE), - CFG_SEC("titlebar", titlebar_opts, CFGF_NONE), CFG_SEC("client", client_opts, CFGF_NONE), CFG_SEC("bar", bar_opts, CFGF_NONE), CFG_SEC("layouts", layouts_opts, CFGF_NONE), @@ -308,15 +306,13 @@ init_conf(void) cfg_t *cfg_bar; cfg_t *cfg_variables; cfg_t *cfg_root; - cfg_t *cfg_titlebar; cfg_t *cfg_client; cfg_t *cfg_layouts; cfg_t *cfg_tags; cfg_t *cfg_keys; - cfg_t *cfgtmp; + cfg_t *cfgtmp, *cfgtmp2; char final_path[128]; char sfinal_path[128]; - char buf[256] = {0}; int ret, i, j, l; @@ -338,7 +334,6 @@ init_conf(void) cfg_misc = cfg_getsec(cfg, "misc"); cfg_variables = cfg_getsec(cfg, "variables"); cfg_root = cfg_getsec(cfg, "root"); - cfg_titlebar = cfg_getsec(cfg, "titlebar"); cfg_client = cfg_getsec(cfg, "client"); cfg_bar = cfg_getsec(cfg, "bar"); cfg_layouts = cfg_getsec(cfg, "layouts"); @@ -381,47 +376,15 @@ init_conf(void) conf.root.mouse[i].cmd = strdup(var_to_str(cfg_getstr(cfgtmp, "cmd"))); } - /* titlebar */ - strcpy(buf, var_to_str(cfg_getstr(cfg_titlebar, "position"))); - if(strcmp(buf, "bottom") == 0) - conf.titlebar.pos = Bottom; - else if(strcmp(buf, "top") == 0) - conf.titlebar.pos = Top; - - conf.titlebar.height = cfg_getint(cfg_titlebar, "height"); - conf.titlebar.exist = conf.titlebar.height ? True : False; - conf.titlebar.bg_normal = getcolor(var_to_str(cfg_getstr(cfg_titlebar, "bg_normal"))); - conf.titlebar.bg_focus = getcolor(var_to_str(cfg_getstr(cfg_titlebar, "bg_focus"))); - conf.titlebar.fg_focus = var_to_str(cfg_getstr(cfg_titlebar, "fg_focus")); - conf.titlebar.fg_normal = var_to_str(cfg_getstr(cfg_titlebar, "fg_normal")); - - strcpy(buf, var_to_str(cfg_getstr(cfg_titlebar, "text_align"))); - if(strcmp(buf, "center") == 0) - conf.titlebar.text_align = Center; - else if(strcmp(buf, "right") == 0) - conf.titlebar.text_align = Right; - else if(strcmp(buf, "left") == 0) - conf.titlebar.text_align = Left; - - conf.titlebar.nmouse = cfg_size(cfg_titlebar, "mouse"); - conf.titlebar.mouse = emalloc(conf.titlebar.nmouse, sizeof(MouseBinding)); - - for(i = 0; i < conf.titlebar.nmouse; ++i) - { - cfgtmp = cfg_getnsec(cfg_titlebar, "mouse", i); - conf.titlebar.mouse[i].button = char_to_button(cfg_getstr(cfgtmp, "button")); - conf.titlebar.mouse[i].func = name_to_func(cfg_getstr(cfgtmp, "func"), func_list); - conf.titlebar.mouse[i].cmd = strdup(var_to_str(cfg_getstr(cfgtmp, "cmd"))); - } - /* client */ - conf.client.borderheight = cfg_getint(cfg_client, "border_height"); - conf.client.bordernormal = getcolor(var_to_str(cfg_getstr(cfg_client, "border_normal"))); - conf.client.borderfocus = getcolor(var_to_str(cfg_getstr(cfg_client, "border_focus"))); - conf.client.mod |= char_to_modkey(cfg_getstr(cfg_client, "modifier")); - - conf.client.nmouse = cfg_size(cfg_titlebar, "mouse"); - conf.client.mouse = emalloc(conf.client.nmouse, sizeof(MouseBinding)); + conf.client.borderheight = cfg_getint(cfg_client, "border_height"); + conf.client.bordernormal = getcolor(var_to_str(cfg_getstr(cfg_client, "border_normal"))); + conf.client.borderfocus = getcolor(var_to_str(cfg_getstr(cfg_client, "border_focus"))); + conf.client.resizecorner_normal = getcolor(var_to_str(cfg_getstr(cfg_client, "resize_corner_normal"))); + conf.client.resizecorner_focus = getcolor(var_to_str(cfg_getstr(cfg_client, "resize_corner_focus"))); + conf.client.mod |= char_to_modkey(cfg_getstr(cfg_client, "modifier")); + conf.client.nmouse = cfg_size(cfg_client, "mouse"); + conf.client.mouse = emalloc(conf.client.nmouse, sizeof(MouseBinding)); for(i = 0; i < conf.client.nmouse; ++i) { @@ -431,6 +394,22 @@ init_conf(void) conf.client.mouse[i].cmd = strdup(var_to_str(cfg_getstr(cfgtmp, "cmd"))); } + /* 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.nmouse = cfg_size(cfgtmp, "mouse"); + conf.titlebar.mouse = emalloc(conf.titlebar.nmouse, sizeof(MouseBinding)); + + for(i = 0; i < conf.titlebar.nmouse; ++i) + { + cfgtmp2 = cfg_getnsec(cfgtmp, "mouse", i); + conf.titlebar.mouse[i].button = char_to_button(cfg_getstr(cfgtmp2, "button")); + conf.titlebar.mouse[i].func = name_to_func(cfg_getstr(cfgtmp2, "func"), func_list); + conf.titlebar.mouse[i].cmd = strdup(var_to_str(cfg_getstr(cfgtmp2, "cmd"))); + } + /* layout */ conf.colors.layout_fg = strdup(var_to_str(cfg_getstr(cfg_layouts, "fg"))); diff --git a/src/event.c b/src/event.c index 445a3b7..52b4c10 100644 --- a/src/event.c +++ b/src/event.c @@ -40,13 +40,16 @@ buttonpress(XEvent ev) int i; char s[6]; - /* Titlebar */ - if(conf.titlebar.exist) - if((c = titlebar_get(ev.xbutton.window))) - for(i = 0; i < conf.titlebar.nmouse; ++i) - if(ev.xbutton.button == conf.titlebar.mouse[i].button) - if(conf.titlebar.mouse[i].func) - conf.titlebar.mouse[i].func(conf.titlebar.mouse[i].cmd); + /* Frame & titlebar */ + if((c = frame_get_titlebar(ev.xbutton.window))) + for(i = 0; i < conf.titlebar.nmouse; ++i) + if(ev.xbutton.button == conf.titlebar.mouse[i].button) + if(conf.titlebar.mouse[i].func) + conf.titlebar.mouse[i].func(conf.titlebar.mouse[i].cmd); + + /* Frame Resize Area */ + if((c = frame_get_resize(ev.xbutton.window))) + mouse_resize(c); /* Client */ if((c = client_get(ev.xbutton.window))) @@ -123,9 +126,11 @@ configurerequest(XEvent ev) Client *c; XWindowChanges wc; XRectangle geo; + if((c = client_get(ev.xconfigurerequest.window))) - if(c->tile || c->lmax) + if(c->tile || c->lmax) return; + geo.x = wc.x = ev.xconfigurerequest.x; geo.y = wc.y = ev.xconfigurerequest.y; geo.width = wc.width = ev.xconfigurerequest.width; @@ -133,11 +138,18 @@ configurerequest(XEvent ev) wc.border_width = ev.xconfigurerequest.border_width; wc.sibling = ev.xconfigurerequest.above; wc.stack_mode = ev.xconfigurerequest.detail; + XConfigureWindow(dpy, ev.xconfigurerequest.window, ev.xconfigurerequest.value_mask, &wc); + if((c = client_get(ev.xconfigurerequest.window))) - if(wc.y < MAXW && wc.x < MAXH) - client_moveresize(c, geo, True); + { + client_moveresize(c, geo, True); + XReparentWindow(dpy, c->win, c->frame, + conf.client.borderheight, + conf.titlebar.height + conf.client.borderheight); + } + XSync(dpy, False); return; } @@ -163,7 +175,9 @@ enternotify(XEvent ev) || ev.xcrossing.detail == NotifyInferior) return; if((c = client_get(ev.xcrossing.window)) - || (c = titlebar_get(ev.xcrossing.window))) + || (c = frame_get(ev.xcrossing.window)) + || (c = frame_get_titlebar(ev.xcrossing.window)) + || (c = frame_get_resize(ev.xcrossing.window))) client_focus(c); else client_focus(NULL); @@ -181,10 +195,9 @@ expose(XEvent ev) && (ev.xexpose.window == infobar.bar->win)) infobar_draw(); - if(conf.titlebar.exist) - for(c = clients; c; c = c->next) - if(ev.xexpose.window == c->tbar->win) - titlebar_update(c); + for(c = clients; c; c = c->next) + if(ev.xexpose.window == c->titlebar) + frame_update(c); return; } @@ -253,10 +266,8 @@ maprequest(XEvent ev) { XWindowAttributes at; - if(!XGetWindowAttributes(dpy, ev.xmaprequest.window, &at)) - return; - if(at.override_redirect) - return; + CHECK(XGetWindowAttributes(dpy, ev.xmaprequest.window, &at)); + CHECK(!at.override_redirect); if(!client_get(ev.xmaprequest.window)) client_manage(ev.xmaprequest.window, &at); @@ -289,7 +300,7 @@ propertynotify(XEvent ev) } if(ev.xproperty.atom == XA_WM_NAME || ev.xproperty.atom == net_atom[NetWMName]) - titlebar_update(c); + client_get_name(c); } return; diff --git a/src/frame.c b/src/frame.c new file mode 100644 index 0000000..606c560 --- /dev/null +++ b/src/frame.c @@ -0,0 +1,173 @@ +/* +* frame.c +* Copyright © 2008 Martin Duquesnoy +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* * Neither the name of the nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "wmfs.h" + +void +frame_create(Client *c) +{ + XSetWindowAttributes at; + + at.background_pixel = conf.client.bordernormal; + at.background_pixmap = ParentRelative; + at.override_redirect = True; + at.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | + ExposureMask | VisibilityChangeMask | EnterWindowMask | + FocusChangeMask | KeyMask | ButtonMask | MouseMask; + + /* Set size */ + c->frame_geo.x = c->geo.x - conf.client.borderheight; + c->frame_geo.y = c->geo.y - conf.titlebar.height; + c->frame_geo.width = FRAMEW(c->geo.width); + 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); + + /* Create titlebar window */ + c->titlebar = XCreateWindow(dpy, c->frame, 0, 0, + c->frame_geo.width, + TBARH + BORDH, 0, + CopyFromParent, InputOutput, CopyFromParent, + CWEventMask|CWBackPixel, &at); + + /* 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); + + /* Reparent window with the frame */ + XReparentWindow(dpy, c->win, c->frame, + conf.client.borderheight, + conf.titlebar.height + conf.client.borderheight); + + return; +} + +void +frame_moveresize(Client *c, XRectangle geo) +{ + c->frame_geo.x = geo.x - conf.client.borderheight; + c->frame_geo.y = geo.y - conf.titlebar.height; + c->frame_geo.width = FRAMEW(geo.width); + c->frame_geo.height = FRAMEH(geo.height); + + /* Frame */ + XMoveResizeWindow(dpy, c->frame, + c->frame_geo.x, + c->frame_geo.y, + c->frame_geo.width, + c->frame_geo.height); + /* Titlebar */ + 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); + + return; +} + +void +frame_update(Client *c) +{ + int px, py; + + 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) + { + /* 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); + } + + return; +} + +Client* +frame_get(Window w) +{ + Client *c; + + for(c = clients; c && c->frame != w; c = c->next); + + return c; +} + +Client* +frame_get_titlebar(Window w) +{ + Client *c; + + for(c = clients; c && c->titlebar != w; c = c->next); + + return c; +} + +Client* +frame_get_resize(Window w) +{ + Client *c; + + for(c = clients; c && c->resize != w; c = c->next); + + return c; +} + diff --git a/src/infobar.c b/src/infobar.c index 4acc301..ec65352 100644 --- a/src/infobar.c +++ b/src/infobar.c @@ -190,9 +190,10 @@ uicb_infobar_togglepos(uicb_t cmd) { conf.bartop = !conf.bartop; if(conf.bartop) - sgeo.y = conf.titlebar.pos ? infobar.geo.height : infobar.geo.height + conf.titlebar.height; + sgeo.y = infobar.geo.height + TBARH; else - sgeo.y = conf.titlebar.pos ? 0 : conf.titlebar.height; + sgeo.y = TBARH; + infobar.geo.y = (conf.bartop) ? 0 : MAXH - infobar.geo.height; bar_move(infobar.bar, 0, infobar.geo.y); infobar_draw(); diff --git a/src/init.c b/src/init.c index 8aaf500..2730085 100644 --- a/src/init.c +++ b/src/init.c @@ -49,7 +49,7 @@ init(void) grabkeys(); /* Warning about font */ - if(conf.titlebar.height < font->height) + if(TBARH + BORDH < font->height) fprintf(stderr, "WMFS Warning: Font too big, can't draw any text in the titlebar.\n"); return; @@ -122,7 +122,6 @@ init_root(void) SubstructureRedirectMask | SubstructureNotifyMask | EnterWindowMask | LeaveWindowMask | StructureNotifyMask ; at.cursor = cursor[CurNormal]; - at.override_redirect = 1; XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &at); if(conf.root.background_command) uicb_spawn(conf.root.background_command); @@ -133,18 +132,16 @@ init_root(void) void init_geometry(void) { - sgeo.y = sgeo.x = 0; + sgeo.x = BORDH; + sgeo.y = infobar.geo.height; if(conf.bartop) - sgeo.y = (conf.titlebar.pos) - ? infobar.geo.height - : infobar.geo.height + conf.titlebar.height; + sgeo.y += TBARH; else - if(conf.titlebar.pos) - sgeo.y = conf.titlebar.height; + sgeo.y = TBARH; sgeo.width = MAXW; - sgeo.height = MAXH - (infobar.geo.height + conf.titlebar.height); + sgeo.height = MAXH - infobar.geo.height - TBARH; return; } diff --git a/src/layout.c b/src/layout.c index 9454475..a2050d8 100644 --- a/src/layout.c +++ b/src/layout.c @@ -179,8 +179,7 @@ uicb_set_mwfact(uicb_t cmd) { double c; - if(!(sscanf(cmd, "%lf", &c))) - return; + CHECK((sscanf(cmd, "%lf", &c))); if(tags[seltag].mwfact + c > 0.95 || tags[seltag].mwfact + c < 0.05) @@ -216,11 +215,10 @@ grid(void) Client *c; XRectangle cgeo = {sgeo.x, sgeo.y, 0, 0}; unsigned int i, n, cols, rows, cpcols = 0; - unsigned int border = conf.client.borderheight * 2; + unsigned int border = BORDH * 2; for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), ++n); - if(!n) - return; + CHECK(n); for(rows = 0; rows <= n / 2; ++rows) if(rows * rows >= n) @@ -248,13 +246,13 @@ grid(void) /* Last column's client remainder */ if(i >= rows * (cols - 1)) - cgeo.width = sgeo.width - cgeo.x - border; + cgeo.width = sgeo.width - cgeo.x - BORDH; /* Resize */ client_moveresize(c, cgeo, tags[seltag].resizehint); /* Set all the other size with current client info */ - cgeo.y = c->geo.y + c->geo.height + border + conf.titlebar.height; + cgeo.y = c->geo.y + c->geo.height + border + TBARH; if(cpcols + 1 > rows) { cpcols = 0; @@ -273,11 +271,10 @@ multi_tile(Position type) XRectangle mastergeo = {sgeo.x, sgeo.y, 0, 0}; XRectangle cgeo = {sgeo.x, sgeo.y, 0, 0}; uint i , n, tilesize, mwfact, nmaster = tags[seltag].nmaster; - uint border = conf.client.borderheight * 2; + uint border = BORDH * 2; for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), ++n); - if(!n) - return; + CHECK(n); /* FIX NMASTER */ nmaster = (n < nmaster) ? n : nmaster; @@ -292,13 +289,13 @@ multi_tile(Position type) { if(type == Top) mastergeo.y = (n <= nmaster) ? sgeo.y : sgeo.y + (sgeo.height - mwfact) - border; - mastergeo.width = (sgeo.width / nmaster) - border; - mastergeo.height = (n <= nmaster) ? sgeo.height - border : mwfact; + mastergeo.width = (sgeo.width / nmaster) - BORDH; + mastergeo.height = (n <= nmaster) ? sgeo.height - BORDH : mwfact; } else { if(type == Left) - mastergeo.x = (n <= nmaster) ? sgeo.x : sgeo.width - mwfact - border; + mastergeo.x = (n <= nmaster) ? sgeo.x : sgeo.width - mwfact - BORDH; mastergeo.width = (n <= nmaster) ? sgeo.width - border : mwfact; mastergeo.height = (sgeo.height / nmaster) - border; } @@ -332,7 +329,7 @@ multi_tile(Position type) else { cgeo.x = mastergeo.x; - cgeo.height -= (conf.titlebar.height + border); + cgeo.height -= (TBARH + border); } } @@ -349,7 +346,7 @@ multi_tile(Position type) cgeo.x = sgeo.x; break; case Bottom: - cgeo.y += mastergeo.height + conf.titlebar.height + border; + cgeo.y += mastergeo.height + TBARH + border; cgeo.x = sgeo.x; break; default: @@ -363,13 +360,13 @@ multi_tile(Position type) { cgeo.width = tilesize; cgeo.width -= border; - cgeo.height = sgeo.height - mastergeo.height - conf.titlebar.height - border*2; + cgeo.height = sgeo.height - mastergeo.height - TBARH - border*2; } else { cgeo.width = sgeo.width - mastergeo.width - border*2; cgeo.height = tilesize; - cgeo.height -= border + conf.titlebar.height; + cgeo.height -= border + TBARH; } } @@ -377,7 +374,7 @@ multi_tile(Position type) if(i + 1 == n || i + 1 == (n < nmaster ? n : nmaster)) { if(type == Top || type == Bottom) - cgeo.width = sgeo.width - cgeo.x - border; + cgeo.width = sgeo.width - cgeo.x - BORDH; else cgeo.height = (sgeo.y + sgeo.height) - cgeo.y - border; } diff --git a/src/mouse.c b/src/mouse.c index 13a5ad5..e3b95e8 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -96,7 +96,7 @@ mouse_resize(Client *c) return; if(!c->tile) - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geo.width, c->geo.height); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geo.width + conf.client.borderheight, c->geo.height); /* Warp pointer for mwfact resize {{{ */ if(c->tile) @@ -126,7 +126,7 @@ mouse_resize(Client *c) if(ev.type == ButtonRelease) { if(!c->tile) - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geo.width, c->geo.height); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geo.width + conf.client.borderheight, c->geo.height); XUngrabPointer(dpy, CurrentTime); return; } @@ -142,7 +142,7 @@ mouse_resize(Client *c) } else { - fy = (round(((ev.xmotion.y * 50) / sgeo.height))) / 50; + fy = (round(((ev.xmotion.y * 50) / sgeo.height))) / 50; fx = (round(((ev.xmotion.x * 50) / sgeo.width))) / 50; if(tags[seltag].layout.func == tile) @@ -200,8 +200,8 @@ mouse_grabbuttons(Client *c, Bool focused) void uicb_mouse_move(uicb_t cmd) { - if(sel) - mouse_move(sel); + CHECK(sel); + mouse_move(sel); return; } @@ -209,8 +209,8 @@ uicb_mouse_move(uicb_t cmd) void uicb_mouse_resize(uicb_t cmd) { - if(sel) - mouse_resize(sel); + CHECK(sel); + mouse_resize(sel); return; } diff --git a/src/structs.h b/src/structs.h index ce84dcb..7e8e57a 100644 --- a/src/structs.h +++ b/src/structs.h @@ -37,7 +37,6 @@ #define NBUTTON 8 #define MAXTAG 36 - #define NUM_OF_LAYOUT 7 /* Typedef */ @@ -75,16 +74,23 @@ struct Client int tag; /* Window attribute */ XRectangle geo; + XRectangle frame_geo; /* Old window attribute */ XRectangle ogeo; /* For resizehint usage */ int basew, baseh, incw, inch; int maxw, maxh, minw, minh; int minax, maxax, minay, maxay; - /* Window */ + /* Client composant */ Window win; - /* Titlebar */ - BarWindow *tbar; + Window frame; + Window resize, titlebar; + struct + { + uint frame; + uint resizecorner; + char *titlebar; + } colors; /* Border */ int border; /* Client Layout Information */ @@ -185,20 +191,17 @@ typedef struct int borderheight; uint bordernormal; uint borderfocus; + uint resizecorner_normal; + uint resizecorner_focus; uint mod; MouseBinding *mouse; int nmouse; } client; struct { - Bool exist; - Position pos; int height; - uint bg_normal; - uint bg_focus; char *fg_focus; char *fg_normal; - Position text_align; MouseBinding *mouse; int nmouse; } titlebar; diff --git a/src/titlebar.c b/src/titlebar.c deleted file mode 100644 index 80b925d..0000000 --- a/src/titlebar.c +++ /dev/null @@ -1,147 +0,0 @@ -/* -* titlebar.c -* Copyright © 2008 Martin Duquesnoy -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are -* met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above -* copyright notice, this list of conditions and the following disclaimer -* in the documentation and/or other materials provided with the -* distribution. -* * Neither the name of the nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "wmfs.h" - -void -titlebar_create(Client *c) -{ - c->tbar = bar_create(c->geo.x, c->geo.y, c->geo.width, - conf.titlebar.height - conf.client.borderheight, - 0, conf.titlebar.bg_normal, True); - titlebar_update_position(c); - - return; -} - -void -titlebar_delete(Client *c) -{ - if(c->title) - XFree(c->title); - bar_delete(c->tbar); - c->tbar = NULL; - - return; -} - - -Client* -titlebar_get(Window w) -{ - Client *c; - - if(!conf.titlebar.exist) - return NULL; - - for(c = clients; c && c->tbar->win != w; c = c->next); - - return c; -} - -void -titlebar_update_position(Client *c) -{ - int y; - - /* Set titlebar position : Top/Bottom */ - switch(conf.titlebar.pos) - { - default: - case Top: - y = c->geo.y - conf.titlebar.height; - break; - case Bottom: - y = c->geo.y + c->geo.height + conf.client.borderheight; - break; - } - bar_move(c->tbar, c->geo.x, y); - bar_resize(c->tbar, c->geo.width + c->border * 2, conf.titlebar.height); - - return; -} - -void -titlebar_update(Client *c) -{ - int pos_y, pos_x; - uint bg; - char *fg; - - /* Get the window name, will be free by XFree later... */ - XFetchName(dpy, c->win, &(c->title)); - if(!c->title) - c->title = strdup("WMFS"); - - if(!conf.titlebar.exist) - return; - - /* Set titlebar color */ - bg = (c == sel) - ? conf.titlebar.bg_focus - : conf.titlebar.bg_normal; - fg = (c == sel) - ? conf.titlebar.fg_focus - : conf.titlebar.fg_normal; - c->tbar->color = bg; - - /* Refresh titlebar color */ - bar_refresh_color(c->tbar); - - /* Draw the client title in the titlebar *logeek* */ - if(conf.titlebar.height + 1 > font->height) - { - /* Set the text alignement */ - switch(conf.titlebar.text_align) - { - case Center: - pos_x = (c->geo.width / 2) - (textw(c->title) / 2); - break; - case Right: - pos_x = c->geo.width - textw(c->title) - 2; - break; - default: - case Left: - pos_x = 2; - break; - } - - /* Set y text position (always at the middle) and fg color */ - pos_y = (font->height - (font->descent )) + ((conf.titlebar.height - font->height) / 2); - - /* Draw title */ - draw_text(c->tbar->dr, pos_x, pos_y, fg, bg, 0, c->title); - } - bar_refresh(c->tbar); - - return; -} diff --git a/src/wmfs.h b/src/wmfs.h index c326b94..6ae157a 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -53,12 +53,21 @@ #include "config.h" #include "structs.h" -/* Defines */ +/* MACRO */ #define ButtonMask (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask) #define MouseMask (ButtonMask | PointerMotionMask) #define KeyMask (KeyPressMask | KeyReleaseMask) + #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 CHECK(x) if(!x) return #define ITOA(p ,n) sprintf(p, "%d", n) #define debug(p) fprintf(stderr, "debug: %d\n", p) #define PAD 8 @@ -91,6 +100,7 @@ void client_attach(Client *c); void client_detach(Client *c); void client_focus(Client *c); Client *client_get(Window w); +void client_get_name(Client *c); void client_hide(Client *c); Bool ishide(Client *c); void client_map(Client *c); @@ -106,6 +116,15 @@ void uicb_client_prev(uicb_t); void uicb_client_next(uicb_t); void uicb_client_kill(uicb_t); +/* frame.c */ +void frame_create(Client *c); +void frame_moveresize(Client *c, XRectangle geo); +Client* frame_get(Window w); +void frame_update(Client *c); +void frame_set_color(Client *c, uint bg); +Client* frame_get_titlebar(Window w); +Client* frame_get_resize(Window w); + /* config.c */ void init_conf(void); @@ -146,13 +165,6 @@ void uicb_tag_next(uicb_t); void uicb_tag_prev(uicb_t); void uicb_tagtransfert(uicb_t); -/* titlebar.c */ -void titlebar_create(Client *c); -void titlebar_delete(Client *c); -Client* titlebar_get(Window w); -void titlebar_update_position(Client *c); -void titlebar_update(Client *c); - /* layout.c */ void arrange(void); void freelayout(void); @@ -160,14 +172,13 @@ void layoutswitch(Bool b); void layout_tile_switch(Bool b); void maxlayout(void); Client *nexttiled(Client *c); - -/* tile */ -void grid(void); -void tile(void); -void tile_left(void); -void tile_top(void); -void tile_bottom(void); - +/* tile {{{ */ + void grid(void); + void tile(void); + void tile_left(void); + void tile_top(void); + void tile_bottom(void); +/* }}} */ void uicb_tile_switch(uicb_t); void uicb_togglemax(uicb_t); void uicb_layout_prev(uicb_t); diff --git a/wmfsrc b/wmfsrc index 00e7a2e..31ef37c 100644 --- a/wmfsrc +++ b/wmfsrc @@ -66,34 +66,34 @@ root client { - border_height = 2 - border_normal = "#191919" - border_focus = "#003366" - modifier = "Alt" + border_height = 3 + border_normal = "#191919" + border_focus = "#003366" + resize_corner_normal = "#191919" + resize_corner_focus = "#771103" + modifier = "Alt" mouse { button = "1" func = "client_raise" } mouse { button = "1" func = "mouse_move" } mouse { button = "2" func = "tile_switch" } mouse { button = "3" func = "client_raise" } mouse { button = "3" func = "mouse_resize" } + + titlebar + { + height = 11 + fg_normal = "#B4B4B4" + fg_focus = "#D4D4D4" + + mouse { button = "1" func = "client_raise" } + mouse { button = "1" func = "mouse_move" } + mouse { button = "2" func = "tile_switch" } + mouse { button = "3" func = "client_raise" } + mouse { button = "3" func = "mouse_resize" } + } + } -titlebar -{ - position = "top" - height = 12 - bg_normal = "#191919" - bg_focus = "#003366" - fg_normal = "#D4D4D4" - fg_focus = "#B4B4B4" - text_align = "center" - - mouse { button = "1" func = "client_raise" } - mouse { button = "1" func = "mouse_move" } - mouse { button = "2" func = "client_kill" } - mouse { button = "3" func = "client_raise" } - mouse { button = "3" func = "mouse_resize" } -} keys {