diff --git a/config.def.h b/config.def.h index aaaf38d..bcf49d8 100644 --- a/config.def.h +++ b/config.def.h @@ -3,6 +3,9 @@ #define MOD Mod4Mask +const int handle_bar_thickness = 20; +const char *handlebar_colour = "#ffffff"; + const char* menu[] = {"dmenu_run", 0}; const char* term[] = {"st", 0}; const char* scrot[] = {"scr", 0}; diff --git a/sowm.c b/sowm.c index bc14c4e..42bd732 100644 --- a/sowm.c +++ b/sowm.c @@ -54,6 +54,9 @@ static unsigned int ww, wh; static Display *d; static XButtonEvent mouse; +static Window hb = 0; +static XColor hbc; + static void (*events[LASTEvent])(XEvent *e) = { [ButtonPress] = button_press, [ButtonRelease] = button_release, @@ -75,8 +78,36 @@ static void (*events[LASTEvent])(XEvent *e) = { XGetGeometry(d, W, &(Window){0}, gx, gy, gw, gh, \ &(unsigned int){0}, &(unsigned int){0}) +void configure_hb_for_window(Window w) { + XWindowAttributes wa; + XGetWindowAttributes(d, w, &wa); + if (!hb) { + int s = DefaultScreen(d); + hb = XCreateSimpleWindow(d, RootWindow(d, s), + wa.x, wa.y - handle_bar_thickness, + wa.width + 2*wa.border_width, handle_bar_thickness, + 0, + hbc.pixel, hbc.pixel); + XMapWindow(d, hb); + XGrabButton(d, AnyButton, AnyModifier, hb, True, + ButtonPressMask|ButtonReleaseMask|PointerMotionMask, + GrabModeAsync, GrabModeAsync, 0, 0); + } else + XMoveResizeWindow(d, hb, wa.x, wa.y - handle_bar_thickness, + wa.width, handle_bar_thickness); + XRaiseWindow(d, hb); +} + +void destroy_hb(void) { + if (!hb) return; + XUnmapWindow(d, hb); + XDestroyWindow(d, hb); + hb = 0; +} + void win_focus(client *c) { cur = c; + configure_hb_for_window(c->w); XSetInputFocus(d, cur->w, RevertToParent, CurrentTime); } @@ -93,7 +124,22 @@ void notify_enter(XEvent *e) { } void notify_motion(XEvent *e) { - if (!mouse.subwindow || cur->f) return; + if (e->xmotion.window == hb) { + while(XCheckTypedEvent(d, MotionNotify, e)); + + int xd = e->xbutton.x_root - mouse.x_root; + int yd = e->xbutton.y_root - mouse.y_root; + + XMoveResizeWindow(d, cur->w, + wx + (mouse.button == 1 ? xd : 0), + wy + (mouse.button == 1 ? yd : 0), + ww + (mouse.button == 3 ? xd : 0), + wh + (mouse.button == 3 ? yd : 0)); + + configure_hb_for_window(cur->w); + } + + if (!mouse.subwindow || mouse.subwindow == hb || cur->f) return; while(XCheckTypedEvent(d, MotionNotify, e)); @@ -105,6 +151,8 @@ void notify_motion(XEvent *e) { wy + (mouse.button == 1 ? yd : 0), ww + (mouse.button == 3 ? xd : 0), wh + (mouse.button == 3 ? yd : 0)); + + if (mouse.subwindow == cur->w) configure_hb_for_window(cur->w); } void key_press(XEvent *e) { @@ -116,6 +164,13 @@ void key_press(XEvent *e) { } void button_press(XEvent *e) { + if (e->xbutton.window == hb) { + mouse = e->xbutton; + win_size(cur->w, &wx, &wy, &ww, &wh); + XRaiseWindow(d, cur->w); + return; + } + if (!e->xbutton.subwindow) return; win_size(e->xbutton.subwindow, &wx, &wy, &ww, &wh); @@ -154,6 +209,8 @@ void win_del(Window w) { for win if (c->w == w) x = c; + if (x == cur) destroy_hb(); + if (!list || !x) return; if (x->prev == x) list = 0; if (list == x) list = x->next; @@ -174,6 +231,8 @@ void win_center() { win_size(cur->w, &(int){0}, &(int){0}, &ww, &wh); XMoveWindow(d, cur->w, (sw - ww) / 2, (sh - wh) / 2); + + configure_hb_for_window(cur->w); } void win_fs() { @@ -182,9 +241,11 @@ void win_fs() { if ((cur->f = cur->f ? 0 : 1)) { win_size(cur->w, &cur->wx, &cur->wy, &cur->ww, &cur->wh); XMoveResizeWindow(d, cur->w, 0, 0, sw, sh); - - } else + destroy_hb(); + } else { XMoveResizeWindow(d, cur->w, cur->wx, cur->wy, cur->ww, cur->wh); + configure_hb_for_window(cur->w); + } } void win_to_ws(const Arg arg) { @@ -201,6 +262,8 @@ void win_to_ws(const Arg arg) { XUnmapWindow(d, cur->w); ws_save(tmp); + destroy_hb(); + if (list) win_focus(list); } @@ -227,6 +290,8 @@ void ws_go(const Arg arg) { ws_sel(arg.i); + destroy_hb(); + if (list) win_focus(list); else cur = 0; } @@ -290,6 +355,10 @@ int main(void) { ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, 0, 0); + Colormap cm = DefaultColormap(d, s); + XParseColor(d, cm, handlebar_colour, &hbc); + XAllocColor(d, cm, &hbc); + while (1 && !XNextEvent(d, &ev)) if (events[ev.type]) events[ev.type](&ev); }