From 370089549fa9387393853efa0099732aefb30e09 Mon Sep 17 00:00:00 2001 From: WanderingPenwing Date: Wed, 31 Jul 2024 12:07:04 +0200 Subject: [PATCH] added key functions, changed keybinds --- config.h | 34 +- dwm.c | 379 +-- dwm.c.orig | 2236 ----------------- dwm.c.rej | 20 - dwm.o | Bin 54240 -> 56832 bytes ...ac6d6e39cd9e3fc4fae526e3d1e8df5e34b2.patch | 114 - 6 files changed, 216 insertions(+), 2567 deletions(-) delete mode 100644 dwm.c.orig delete mode 100644 dwm.c.rej delete mode 100644 mitch-06-rounded_corners-f04cac6d6e39cd9e3fc4fae526e3d1e8df5e34b2.patch diff --git a/config.h b/config.h index 0cd107e..103a7af 100644 --- a/config.h +++ b/config.h @@ -29,8 +29,8 @@ static const Rule rules[] = { * WM_NAME(STRING) = title */ /* class instance title tags mask isfloating monitor */ - { "Chromium-browser", NULL, NULL, 0, 0, -1}, - { "Jellyfin Media Player", NULL, NULL, 0, 0, -1}, + { "chromium-browser", NULL, NULL, 0, 0, -1}, + { "jellyfinmediaplayer", NULL, NULL, 0, 0, -1}, { "calcifer", NULL, NULL, 1<<2, 0, -1}, { "jiji", NULL, NULL, 1<<3, 0, -1}, { "discord", NULL, NULL, 1<<3, 0, -1}, @@ -70,26 +70,36 @@ static const char *screenlock[] = { "betterlockscreen", "-l", NULL }; static const Key keys[] = { /* modifier key function argument */ { MODKEY, XK_d, spawn, {.v = dmenucmd } }, - { MODKEY, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_less, spawn, {.v = termcmd } }, { MODKEY, XK_i, spawn, {.v = chromium } }, { MODKEY, XK_twosuperior, spawn, {.v = screenlock } }, { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XK_m, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_f, fullscreen, {0} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_z, incnmaster, {.i = +1 } }, - { MODKEY, XK_s, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_f, togglefullscreen, {0} }, + { MODKEY, XK_Up, focusstack, {.i = +1 } }, + { MODKEY, XK_Down, focusstack, {.i = -1 } }, + { MODKEY, XK_F12, incnmaster, {.i = +1 } }, + { MODKEY, XK_F11, incnmaster, {.i = -1 } }, + { MODKEY, XK_Left, setmfact, {.f = -0.05} }, + { MODKEY, XK_Right, setmfact, {.f = +0.05} }, { MODKEY|ShiftMask, XK_a, killclient, {0} }, { MODKEY, XK_Tab, view, {.ui = ~0 } }, { MODKEY|ShiftMask, XK_Tab, tag, {.ui = ~0 } }, { MODKEY, XK_comma, focusmon, {.i = -1 } }, - { MODKEY, XK_semicolon, focusmon, {.i = +1 } }, + { MODKEY, XK_semicolon, focusmon, {.i = +1 } }, { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_semicolon, tagmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_semicolon, tagmon, {.i = +1 } }, { MODKEY|ShiftMask, XK_q, quit, {0} }, + { MODKEY, XK_F1, spawn, SHCMD("pamixer -t && notify-send -u normal \"volume\" \"$(pamixer --get-volume-human)\"") }, + { MODKEY, XK_F2, spawn, SHCMD("pamixer -d 5 -u && notify-send -u normal \"volume\" \"$(pamixer --get-volume-human)\"") }, + { MODKEY, XK_F3, spawn, SHCMD("pamixer -i 5 -u && notify-send -u normal \"volume\" \"$(pamixer --get-volume-human)\"") }, + { MODKEY, XK_F4, spawn, SHCMD("brightnessctl -d \"amdgpu_bl1\" set 10%- && notify-send -u normal -a \"brightness\" \"$(brightnessctl -d 'amdgpu_bl1' get)\"") }, + { MODKEY, XK_F5, spawn, SHCMD("brightnessctl -d \"amdgpu_bl1\" set +10% && notify-send -u normal -a \"brightness\" \"$(brightnessctl -d 'amdgpu_bl1' get)\"") }, + { MODKEY, XK_F6, spawn, SHCMD("~/nixos/scripts/usb_guest.sh") }, + { MODKEY, XK_F7, spawn, SHCMD("~/nixos/scripts/susuwatari/client.sh") }, + { MODKEY, XK_F8, spawn, SHCMD("~/nixos/scripts/hdmi_paint.sh") }, + { MODKEY, XK_F9, spawn, SHCMD("~/nixos/scripts/screen_sleep.sh") }, + { ShiftMask, XK_Print, spawn, SHCMD("maim --select \"/home/penwing/Pictures/screenshots/$(date '+%Y_%m_%d %H:%M:%S').png\"") }, TAGKEYS( XK_ampersand, 0) TAGKEYS( XK_eacute, 1) TAGKEYS( XK_quotedbl, 2) diff --git a/dwm.c b/dwm.c index b59db91..363e554 100644 --- a/dwm.c +++ b/dwm.c @@ -188,15 +188,15 @@ static void mappingnotify(XEvent *e); static void maprequest(XEvent *e); static void monocle(Monitor *m); static void motionnotify(XEvent *e); -static void movemouse(const Arg *arg); +//static void movemouse(const Arg *arg); static Client *nexttiled(Client *c); -static void pop(Client *c); +//static void pop(Client *c); static void propertynotify(XEvent *e); static void quit(const Arg *arg); static Monitor *recttomon(int x, int y, int w, int h); static void resize(Client *c, int x, int y, int w, int h, int interact); static void resizeclient(Client *c, int x, int y, int w, int h); -static void resizemouse(const Arg *arg); +//static void resizemouse(const Arg *arg); static void restack(Monitor *m); static void run(void); static void scan(void); @@ -205,8 +205,9 @@ static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); static void setfocus(Client *c); static void setfullscreen(Client *c, int fullscreen); -static void fullscreen(const Arg *arg); -static void setgaps(const Arg *arg); +//static void fullscreen(const Arg *arg); +static void togglefullscreen(const Arg *arg); +//static void setgaps(const Arg *arg); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); @@ -216,8 +217,8 @@ static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); static void tile(Monitor *m); -static void togglebar(const Arg *arg); -static void togglefloating(const Arg *arg); +//static void togglebar(const Arg *arg); +//static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); static void unfocus(Client *c, int setfocus); @@ -240,7 +241,7 @@ static int xerror(Display *dpy, XErrorEvent *ee); static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee); static void xinitvisual(); -static void zoom(const Arg *arg); +//static void zoom(const Arg *arg); /* variables */ static const char broken[] = "broken"; @@ -287,6 +288,14 @@ static Colormap cmap; /* compile-time check if all tags fit into an unsigned int bit array. */ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; +void togglefullscreen(const Arg *arg) { + Client *c = selmon->sel; // Get the currently focused client + if (!c) return; // Exit if there is no focused client + + // Toggle fullscreen state + setfullscreen(c, !c->isfullscreen); +} + /* function implementations */ void applyrules(Client *c) @@ -717,8 +726,8 @@ void drawbar(Monitor *m) { int x, w, tw = 0; - int boxs = drw->fonts->h / 9; - int boxw = drw->fonts->h / 6 + 2; + //int boxs = drw->fonts->h / 9; + //int boxw = drw->fonts->h / 6 + 2; unsigned int i, occ = 0, urg = 0; Client *c; @@ -1152,65 +1161,65 @@ motionnotify(XEvent *e) mon = m; } -void -movemouse(const Arg *arg) -{ - int x, y, ocx, ocy, nx, ny; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - if (!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nx = ocx + (ev.xmotion.x - x); - ny = ocy + (ev.xmotion.y - y); - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} +// void +// movemouse(const Arg *arg) +// { +// int x, y, ocx, ocy, nx, ny; +// Client *c; +// Monitor *m; +// XEvent ev; +// Time lasttime = 0; +// +// if (!(c = selmon->sel)) +// return; +// if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ +// return; +// restack(selmon); +// ocx = c->x; +// ocy = c->y; +// if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, +// None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) +// return; +// if (!getrootptr(&x, &y)) +// return; +// do { +// XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); +// switch(ev.type) { +// case ConfigureRequest: +// case Expose: +// case MapRequest: +// handler[ev.type](&ev); +// break; +// case MotionNotify: +// if ((ev.xmotion.time - lasttime) <= (1000 / 60)) +// continue; +// lasttime = ev.xmotion.time; +// +// nx = ocx + (ev.xmotion.x - x); +// ny = ocy + (ev.xmotion.y - y); +// if (abs(selmon->wx - nx) < snap) +// nx = selmon->wx; +// else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) +// nx = selmon->wx + selmon->ww - WIDTH(c); +// if (abs(selmon->wy - ny) < snap) +// ny = selmon->wy; +// else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) +// ny = selmon->wy + selmon->wh - HEIGHT(c); +// if (!c->isfloating && selmon->lt[selmon->sellt]->arrange +// && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) +// togglefloating(NULL); +// if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) +// resize(c, nx, ny, c->w, c->h, 1); +// break; +// } +// } while (ev.type != ButtonRelease); +// XUngrabPointer(dpy, CurrentTime); +// if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { +// sendmon(c, m); +// selmon = m; +// focus(NULL); +// } +// } Client * nexttiled(Client *c) @@ -1219,14 +1228,14 @@ nexttiled(Client *c) return c; } -void -pop(Client *c) -{ - detach(c); - attach(c); - focus(c); - arrange(c->mon); -} +// void +// pop(Client *c) +// { +// detach(c); +// attach(c); +// focus(c); +// arrange(c->mon); +// } void propertynotify(XEvent *e) @@ -1304,62 +1313,62 @@ resizeclient(Client *c, int x, int y, int w, int h) XSync(dpy, False); } -void -resizemouse(const Arg *arg) -{ - int ocx, ocy, nw, nh; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) - return; - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); - nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); - if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww - && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) - { - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) - togglefloating(NULL); - } - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, nw, nh, 1); - break; - } - } while (ev.type != ButtonRelease); - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - XUngrabPointer(dpy, CurrentTime); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} +// void +// resizemouse(const Arg *arg) +// { +// int ocx, ocy, nw, nh; +// Client *c; +// Monitor *m; +// XEvent ev; +// Time lasttime = 0; +// +// if (!(c = selmon->sel)) +// return; +// if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ +// return; +// restack(selmon); +// ocx = c->x; +// ocy = c->y; +// if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, +// None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) +// return; +// XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); +// do { +// XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); +// switch(ev.type) { +// case ConfigureRequest: +// case Expose: +// case MapRequest: +// handler[ev.type](&ev); +// break; +// case MotionNotify: +// if ((ev.xmotion.time - lasttime) <= (1000 / 60)) +// continue; +// lasttime = ev.xmotion.time; +// +// nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); +// nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); +// if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww +// && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) +// { +// if (!c->isfloating && selmon->lt[selmon->sellt]->arrange +// && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) +// togglefloating(NULL); +// } +// if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) +// resize(c, c->x, c->y, nw, nh, 1); +// break; +// } +// } while (ev.type != ButtonRelease); +// XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); +// XUngrabPointer(dpy, CurrentTime); +// while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +// if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { +// sendmon(c, m); +// selmon = m; +// focus(NULL); +// } +// } void restack(Monitor *m) @@ -1514,28 +1523,28 @@ setfullscreen(Client *c, int fullscreen) } } -void -setgaps(const Arg *arg) -{ - if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) - selmon->gappx = 0; - else - selmon->gappx += arg->i; - arrange(selmon); -} +// void +// setgaps(const Arg *arg) +// { +// if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) +// selmon->gappx = 0; +// else +// selmon->gappx += arg->i; +// arrange(selmon); +// } Layout *last_layout; -void -fullscreen(const Arg *arg) -{ - if (selmon->showbar) { - for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); - setlayout(&((Arg) { .v = &layouts[2] })); - } else { - setlayout(&((Arg) { .v = last_layout })); - } - togglebar(arg); -} +// void +// fullscreen(const Arg *arg) +// { +// if (selmon->showbar) { +// for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); +// setlayout(&((Arg) { .v = &layouts[2] })); +// } else { +// setlayout(&((Arg) { .v = last_layout })); +// } +// togglebar(arg); +// } void setlayout(const Arg *arg) @@ -1744,28 +1753,28 @@ tile(Monitor *m) } } -void -togglebar(const Arg *arg) -{ - selmon->showbar = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); -} +// void +// togglebar(const Arg *arg) +// { +// selmon->showbar = !selmon->showbar; +// updatebarpos(selmon); +// XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); +// arrange(selmon); +// } -void -togglefloating(const Arg *arg) -{ - if (!selmon->sel) - return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ - return; - selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if (selmon->sel->isfloating) - resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); - arrange(selmon); -} +// void +// togglefloating(const Arg *arg) +// { +// if (!selmon->sel) +// return; +// if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ +// return; +// selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; +// if (selmon->sel->isfloating) +// resize(selmon->sel, selmon->sel->x, selmon->sel->y, +// selmon->sel->w, selmon->sel->h, 0); +// arrange(selmon); +// } void toggletag(const Arg *arg) @@ -2199,17 +2208,17 @@ xinitvisual() } } -void -zoom(const Arg *arg) -{ - Client *c = selmon->sel; - - if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) - return; - if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) - return; - pop(c); -} +// void +// zoom(const Arg *arg) +// { +// Client *c = selmon->sel; +// +// if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) +// return; +// if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) +// return; +// pop(c); +// } int main(int argc, char *argv[]) diff --git a/dwm.c.orig b/dwm.c.orig deleted file mode 100644 index b59db91..0000000 --- a/dwm.c.orig +++ /dev/null @@ -1,2236 +0,0 @@ -/* See LICENSE file for copyright and license details. - * - * dynamic window manager is designed like any other X client as well. It is - * driven through handling X events. In contrast to other X clients, a window - * manager selects for SubstructureRedirectMask on the root window, to receive - * events about window (dis-)appearance. Only one X connection at a time is - * allowed to select for this event mask. - * - * The event handlers of dwm are organized in an array which is accessed - * whenever a new event has been fetched. This allows event dispatching - * in O(1) time. - * - * Each child of the root window is called a client, except windows which have - * set the override_redirect flag. Clients are organized in a linked client - * list on each monitor, the focus history is remembered through a stack list - * on each monitor. Each client contains a bit array to indicate the tags of a - * client. - * - * Keys and tagging rules are organized as arrays and defined in config.h. - * - * To understand everything else, start reading main(). - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef XINERAMA -#include -#endif /* XINERAMA */ -#include - -#include "drw.h" -#include "util.h" - -/* macros */ -#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) -#define LENGTH(X) (sizeof X / sizeof X[0]) -#define MOUSEMASK (BUTTONMASK|PointerMotionMask) -#define WIDTH(X) ((X)->w + 2 * (X)->bw) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -#define TAGMASK ((1 << LENGTH(tags)) - 1) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -#define OPAQUE 0xffU - -#define OPAQUE 0xffU - -/* enums */ -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { SchemeNorm, SchemeSel }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkClientWin, - ClkRootWin, ClkLast }; /* clicks */ - -typedef union { - int i; - unsigned int ui; - float f; - const void *v; -} Arg; - -typedef struct { - unsigned int click; - unsigned int mask; - unsigned int button; - void (*func)(const Arg *arg); - const Arg arg; -} Button; - -typedef struct Monitor Monitor; -typedef struct Client Client; -struct Client { - char name[256]; - float mina, maxa; - int x, y, w, h; - int oldx, oldy, oldw, oldh; - int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; - Client *next; - Client *snext; - Monitor *mon; - Window win; -}; - -typedef struct { - unsigned int mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Key; - -typedef struct { - const char *symbol; - void (*arrange)(Monitor *); -} Layout; - -struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - int gappx; /* gaps between windows */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - int showbar; - int topbar; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; - const Layout *lt[2]; -}; - -typedef struct { - const char *class; - const char *instance; - const char *title; - unsigned int tags; - int isfloating; - int monitor; -} Rule; - -/* function declarations */ -static void applyrules(Client *c); -static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -static void arrange(Monitor *m); -static void arrangemon(Monitor *m); -static void attach(Client *c); -static void attachstack(Client *c); -static void buttonpress(XEvent *e); -static void checkotherwm(void); -static void cleanup(void); -static void cleanupmon(Monitor *mon); -static void clientmessage(XEvent *e); -static void configure(Client *c); -static void configurenotify(XEvent *e); -static void configurerequest(XEvent *e); -static Monitor *createmon(void); -static void destroynotify(XEvent *e); -static void detach(Client *c); -static void detachstack(Client *c); -static Monitor *dirtomon(int dir); -static void drawbar(Monitor *m); -static void drawbars(void); -static void enternotify(XEvent *e); -static void expose(XEvent *e); -static void focus(Client *c); -static void focusin(XEvent *e); -static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); -static Atom getatomprop(Client *c, Atom prop); -static int getrootptr(int *x, int *y); -static long getstate(Window w); -static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void grabbuttons(Client *c, int focused); -static void grabkeys(void); -static void incnmaster(const Arg *arg); -static void keypress(XEvent *e); -static void killclient(const Arg *arg); -static void manage(Window w, XWindowAttributes *wa); -static void mappingnotify(XEvent *e); -static void maprequest(XEvent *e); -static void monocle(Monitor *m); -static void motionnotify(XEvent *e); -static void movemouse(const Arg *arg); -static Client *nexttiled(Client *c); -static void pop(Client *c); -static void propertynotify(XEvent *e); -static void quit(const Arg *arg); -static Monitor *recttomon(int x, int y, int w, int h); -static void resize(Client *c, int x, int y, int w, int h, int interact); -static void resizeclient(Client *c, int x, int y, int w, int h); -static void resizemouse(const Arg *arg); -static void restack(Monitor *m); -static void run(void); -static void scan(void); -static int sendevent(Client *c, Atom proto); -static void sendmon(Client *c, Monitor *m); -static void setclientstate(Client *c, long state); -static void setfocus(Client *c); -static void setfullscreen(Client *c, int fullscreen); -static void fullscreen(const Arg *arg); -static void setgaps(const Arg *arg); -static void setlayout(const Arg *arg); -static void setmfact(const Arg *arg); -static void setup(void); -static void seturgent(Client *c, int urg); -static void showhide(Client *c); -static void spawn(const Arg *arg); -static void tag(const Arg *arg); -static void tagmon(const Arg *arg); -static void tile(Monitor *m); -static void togglebar(const Arg *arg); -static void togglefloating(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void unfocus(Client *c, int setfocus); -static void unmanage(Client *c, int destroyed); -static void unmapnotify(XEvent *e); -static void updatebarpos(Monitor *m); -static void updatebars(void); -static void updateclientlist(void); -static int updategeom(void); -static void updatenumlockmask(void); -static void updatesizehints(Client *c); -static void updatestatus(void); -static void updatetitle(Client *c); -static void updatewindowtype(Client *c); -static void updatewmhints(Client *c); -static void view(const Arg *arg); -static Client *wintoclient(Window w); -static Monitor *wintomon(Window w); -static int xerror(Display *dpy, XErrorEvent *ee); -static int xerrordummy(Display *dpy, XErrorEvent *ee); -static int xerrorstart(Display *dpy, XErrorEvent *ee); -static void xinitvisual(); -static void zoom(const Arg *arg); - -/* variables */ -static const char broken[] = "broken"; -static char stext[256]; -static int screen; -static int sw, sh; /* X display screen geometry width, height */ -static int bh; /* bar height */ -static int lrpad; /* sum of left and right padding for text */ -static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int numlockmask = 0; -static void (*handler[LASTEvent]) (XEvent *) = { - [ButtonPress] = buttonpress, - [ClientMessage] = clientmessage, - [ConfigureRequest] = configurerequest, - [ConfigureNotify] = configurenotify, - [DestroyNotify] = destroynotify, - [EnterNotify] = enternotify, - [Expose] = expose, - [FocusIn] = focusin, - [KeyPress] = keypress, - [MappingNotify] = mappingnotify, - [MapRequest] = maprequest, - [MotionNotify] = motionnotify, - [PropertyNotify] = propertynotify, - [UnmapNotify] = unmapnotify -}; -static Atom wmatom[WMLast], netatom[NetLast]; -static int running = 1; -static Cur *cursor[CurLast]; -static Clr **scheme; -static Display *dpy; -static Drw *drw; -static Monitor *mons, *selmon; -static Window root, wmcheckwin; - -static int useargb = 0; -static Visual *visual; -static int depth; -static Colormap cmap; - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -/* compile-time check if all tags fit into an unsigned int bit array. */ -struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -/* function implementations */ -void -applyrules(Client *c) -{ - const char *class, *instance; - unsigned int i; - const Rule *r; - Monitor *m; - XClassHint ch = { NULL, NULL }; - - /* rule matching */ - c->isfloating = 0; - c->tags = 0; - XGetClassHint(dpy, c->win, &ch); - class = ch.res_class ? ch.res_class : broken; - instance = ch.res_name ? ch.res_name : broken; - - for (i = 0; i < LENGTH(rules); i++) { - r = &rules[i]; - if ((!r->title || strstr(c->name, r->title)) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { - c->isfloating = r->isfloating; - c->tags |= r->tags; - for (m = mons; m && m->num != r->monitor; m = m->next); - if (m) - c->mon = m; - } - } - if (ch.res_class) - XFree(ch.res_class); - if (ch.res_name) - XFree(ch.res_name); - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; -} - -int -applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) -{ - int baseismin; - Monitor *m = c->mon; - - /* set minimum possible */ - *w = MAX(1, *w); - *h = MAX(1, *h); - if (interact) { - if (*x > sw) - *x = sw - WIDTH(c); - if (*y > sh) - *y = sh - HEIGHT(c); - if (*x + *w + 2 * c->bw < 0) - *x = 0; - if (*y + *h + 2 * c->bw < 0) - *y = 0; - } else { - if (*x >= m->wx + m->ww) - *x = m->wx + m->ww - WIDTH(c); - if (*y >= m->wy + m->wh) - *y = m->wy + m->wh - HEIGHT(c); - if (*x + *w + 2 * c->bw <= m->wx) - *x = m->wx; - if (*y + *h + 2 * c->bw <= m->wy) - *y = m->wy; - } - if (*h < bh) - *h = bh; - if (*w < bh) - *w = bh; - if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { - if (!c->hintsvalid) - updatesizehints(c); - /* see last two sentences in ICCCM 4.1.2.3 */ - baseismin = c->basew == c->minw && c->baseh == c->minh; - if (!baseismin) { /* temporarily remove base dimensions */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for aspect limits */ - if (c->mina > 0 && c->maxa > 0) { - if (c->maxa < (float)*w / *h) - *w = *h * c->maxa + 0.5; - else if (c->mina < (float)*h / *w) - *h = *w * c->mina + 0.5; - } - if (baseismin) { /* increment calculation requires this */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for increment value */ - if (c->incw) - *w -= *w % c->incw; - if (c->inch) - *h -= *h % c->inch; - /* restore base dimensions */ - *w = MAX(*w + c->basew, c->minw); - *h = MAX(*h + c->baseh, c->minh); - if (c->maxw) - *w = MIN(*w, c->maxw); - if (c->maxh) - *h = MIN(*h, c->maxh); - } - return *x != c->x || *y != c->y || *w != c->w || *h != c->h; -} - -void -arrange(Monitor *m) -{ - if (m) - showhide(m->stack); - else for (m = mons; m; m = m->next) - showhide(m->stack); - if (m) { - arrangemon(m); - restack(m); - } else for (m = mons; m; m = m->next) - arrangemon(m); -} - -void -arrangemon(Monitor *m) -{ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -} - -void -attach(Client *c) -{ - c->next = c->mon->clients; - c->mon->clients = c; -} - -void -attachstack(Client *c) -{ - c->snext = c->mon->stack; - c->mon->stack = c; -} - -void -buttonpress(XEvent *e) -{ - unsigned int i, x, click; - Arg arg = {0}; - Client *c; - Monitor *m; - XButtonPressedEvent *ev = &e->xbutton; - - click = ClkRootWin; - /* focus monitor if necessary */ - if ((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - if (ev->window == selmon->barwin) { - i = x = 0; - unsigned int occ = 0; - for(c = m->clients; c; c=c->next) - occ |= c->tags == TAGMASK ? 0 : c->tags; - do { - /* Do not reserve space for vacant tags */ - if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) - continue; - x += TEXTW(tags[i]); - } while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; - } else if (ev->x < x + TEXTW(selmon->ltsymbol)) - click = ClkLtSymbol; - else - click = ClkStatusText; - } else if ((c = wintoclient(ev->window))) { - focus(c); - restack(selmon); - XAllowEvents(dpy, ReplayPointer, CurrentTime); - click = ClkClientWin; - } - for (i = 0; i < LENGTH(buttons); i++) - if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); -} - -void -checkotherwm(void) -{ - xerrorxlib = XSetErrorHandler(xerrorstart); - /* this causes an error if some other window manager is running */ - XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); - XSync(dpy, False); - XSetErrorHandler(xerror); - XSync(dpy, False); -} - -void -cleanup(void) -{ - Arg a = {.ui = ~0}; - Layout foo = { "", NULL }; - Monitor *m; - size_t i; - - view(&a); - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) - while (m->stack) - unmanage(m->stack, 0); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - while (mons) - cleanupmon(mons); - for (i = 0; i < CurLast; i++) - drw_cur_free(drw, cursor[i]); - for (i = 0; i < LENGTH(colors); i++) - free(scheme[i]); - free(scheme); - XDestroyWindow(dpy, wmcheckwin); - drw_free(drw); - XSync(dpy, False); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -} - -void -cleanupmon(Monitor *mon) -{ - Monitor *m; - - if (mon == mons) - mons = mons->next; - else { - for (m = mons; m && m->next != mon; m = m->next); - m->next = mon->next; - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); - free(mon); -} - -void -clientmessage(XEvent *e) -{ - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); - - if (!c) - return; - if (cme->message_type == netatom[NetWMState]) { - if (cme->data.l[1] == netatom[NetWMFullscreen] - || cme->data.l[2] == netatom[NetWMFullscreen]) - setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ - || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } else if (cme->message_type == netatom[NetActiveWindow]) { - if (c != selmon->sel && !c->isurgent) - seturgent(c, 1); - } -} - -void -configure(Client *c) -{ - XConfigureEvent ce; - - ce.type = ConfigureNotify; - ce.display = dpy; - ce.event = c->win; - ce.window = c->win; - ce.x = c->x; - ce.y = c->y; - ce.width = c->w; - ce.height = c->h; - ce.border_width = c->bw; - ce.above = None; - ce.override_redirect = False; - XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); -} - -void -configurenotify(XEvent *e) -{ - Monitor *m; - Client *c; - XConfigureEvent *ev = &e->xconfigure; - int dirty; - - /* TODO: updategeom handling sucks, needs to be simplified */ - if (ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); - sw = ev->width; - sh = ev->height; - if (updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) - if (c->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - } - focus(NULL); - arrange(NULL); - } - } -} - -void -configurerequest(XEvent *e) -{ - Client *c; - Monitor *m; - XConfigureRequestEvent *ev = &e->xconfigurerequest; - XWindowChanges wc; - - if ((c = wintoclient(ev->window))) { - if (ev->value_mask & CWBorderWidth) - c->bw = ev->border_width; - else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { - m = c->mon; - if (ev->value_mask & CWX) { - c->oldx = c->x; - c->x = m->mx + ev->x; - } - if (ev->value_mask & CWY) { - c->oldy = c->y; - c->y = m->my + ev->y; - } - if (ev->value_mask & CWWidth) { - c->oldw = c->w; - c->w = ev->width; - } - if (ev->value_mask & CWHeight) { - c->oldh = c->h; - c->h = ev->height; - } - if ((c->x + c->w) > m->mx + m->mw && c->isfloating) - c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ - if ((c->y + c->h) > m->my + m->mh && c->isfloating) - c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ - if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) - configure(c); - if (ISVISIBLE(c)) - XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - } else - configure(c); - } else { - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); - } - XSync(dpy, False); -} - -Monitor * -createmon(void) -{ - Monitor *m; - - m = ecalloc(1, sizeof(Monitor)); - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; - m->gappx = gappx; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); - return m; -} - -void -destroynotify(XEvent *e) -{ - Client *c; - XDestroyWindowEvent *ev = &e->xdestroywindow; - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -} - -void -detach(Client *c) -{ - Client **tc; - - for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); - *tc = c->next; -} - -void -detachstack(Client *c) -{ - Client **tc, *t; - - for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); - *tc = c->snext; - - if (c == c->mon->sel) { - for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); - c->mon->sel = t; - } -} - -Monitor * -dirtomon(int dir) -{ - Monitor *m = NULL; - - if (dir > 0) { - if (!(m = selmon->next)) - m = mons; - } else if (selmon == mons) - for (m = mons; m->next; m = m->next); - else - for (m = mons; m->next != selmon; m = m->next); - return m; -} - -void -drawbar(Monitor *m) -{ - int x, w, tw = 0; - int boxs = drw->fonts->h / 9; - int boxw = drw->fonts->h / 6 + 2; - unsigned int i, occ = 0, urg = 0; - Client *c; - - if (!m->showbar) - return; - - /* draw status first so it can be overdrawn by tags later */ - if (m == selmon) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); - tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); - } - - for (c = m->clients; c; c = c->next) { - occ |= c->tags == TAGMASK ? 0 : c->tags; - if (c->isurgent) - urg |= c->tags; - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { - /* Do not draw vacant tags */ - if(!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) - continue; - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - x += w; - } - w = TEXTW(m->ltsymbol); - drw_setscheme(drw, scheme[SchemeNorm]); - x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - - if ((w = m->ww - tw - x) > bh) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w, bh, 1, 1); - } - drw_map(drw, m->barwin, 0, 0, m->ww, bh); -} - -void -drawbars(void) -{ - Monitor *m; - - for (m = mons; m; m = m->next) - drawbar(m); -} - -void -enternotify(XEvent *e) -{ - Client *c; - Monitor *m; - XCrossingEvent *ev = &e->xcrossing; - - if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) - return; - c = wintoclient(ev->window); - m = c ? c->mon : wintomon(ev->window); - if (m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - } else if (!c || c == selmon->sel) - return; - focus(c); -} - -void -expose(XEvent *e) -{ - Monitor *m; - XExposeEvent *ev = &e->xexpose; - - if (ev->count == 0 && (m = wintomon(ev->window))) - drawbar(m); -} - -void -focus(Client *c) -{ - if (!c || !ISVISIBLE(c)) - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if (selmon->sel && selmon->sel != c) - unfocus(selmon->sel, 0); - if (c) { - if (c->mon != selmon) - selmon = c->mon; - if (c->isurgent) - seturgent(c, 0); - detachstack(c); - attachstack(c); - grabbuttons(c, 1); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); - setfocus(c); - } else { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } - selmon->sel = c; - drawbars(); -} - -/* there are some broken focus acquiring clients needing extra handling */ -void -focusin(XEvent *e) -{ - XFocusChangeEvent *ev = &e->xfocus; - - if (selmon->sel && ev->window != selmon->sel->win) - setfocus(selmon->sel); -} - -void -focusmon(const Arg *arg) -{ - Monitor *m; - - if (!mons->next) - return; - if ((m = dirtomon(arg->i)) == selmon) - return; - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); -} - -void -focusstack(const Arg *arg) -{ - Client *c = NULL, *i; - - if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) - return; - if (arg->i > 0) { - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); - if (!c) - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); - } else { - for (i = selmon->clients; i != selmon->sel; i = i->next) - if (ISVISIBLE(i)) - c = i; - if (!c) - for (; i; i = i->next) - if (ISVISIBLE(i)) - c = i; - } - if (c) { - focus(c); - restack(selmon); - } -} - -Atom -getatomprop(Client *c, Atom prop) -{ - int di; - unsigned long dl; - unsigned char *p = NULL; - Atom da, atom = None; - - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; - XFree(p); - } - return atom; -} - -int -getrootptr(int *x, int *y) -{ - int di; - unsigned int dui; - Window dummy; - - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); -} - -long -getstate(Window w) -{ - int format; - long result = -1; - unsigned char *p = NULL; - unsigned long n, extra; - Atom real; - - if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if (n != 0) - result = *p; - XFree(p); - return result; -} - -int -gettextprop(Window w, Atom atom, char *text, unsigned int size) -{ - char **list = NULL; - int n; - XTextProperty name; - - if (!text || size == 0) - return 0; - text[0] = '\0'; - if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) - return 0; - if (name.encoding == XA_STRING) { - strncpy(text, (char *)name.value, size - 1); - } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { - strncpy(text, *list, size - 1); - XFreeStringList(list); - } - text[size - 1] = '\0'; - XFree(name.value); - return 1; -} - -void -grabbuttons(Client *c, int focused) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if (!focused) - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeSync, GrabModeSync, None, None); - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].click == ClkClientWin) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); - } -} - -void -grabkeys(void) -{ - updatenumlockmask(); - { - unsigned int i, j, k; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - int start, end, skip; - KeySym *syms; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - XDisplayKeycodes(dpy, &start, &end); - syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); - if (!syms) - return; - for (k = start; k <= end; k++) - for (i = 0; i < LENGTH(keys); i++) - /* skip modifier codes, we do that ourselves */ - if (keys[i].keysym == syms[(k - start) * skip]) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, k, - keys[i].mod | modifiers[j], - root, True, - GrabModeAsync, GrabModeAsync); - XFree(syms); - } -} - -void -incnmaster(const Arg *arg) -{ - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); -} - -#ifdef XINERAMA -static int -isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) -{ - while (n--) - if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org - && unique[n].width == info->width && unique[n].height == info->height) - return 0; - return 1; -} -#endif /* XINERAMA */ - -void -keypress(XEvent *e) -{ - unsigned int i; - KeySym keysym; - XKeyEvent *ev; - - ev = &e->xkey; - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); - for (i = 0; i < LENGTH(keys); i++) - if (keysym == keys[i].keysym - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) - && keys[i].func) - keys[i].func(&(keys[i].arg)); -} - -void -killclient(const Arg *arg) -{ - if (!selmon->sel) - return; - if (!sendevent(selmon->sel, wmatom[WMDelete])) { - XGrabServer(dpy); - XSetErrorHandler(xerrordummy); - XSetCloseDownMode(dpy, DestroyAll); - XKillClient(dpy, selmon->sel->win); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } -} - -void -manage(Window w, XWindowAttributes *wa) -{ - Client *c, *t = NULL; - Window trans = None; - XWindowChanges wc; - - c = ecalloc(1, sizeof(Client)); - c->win = w; - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; - c->tags = t->tags; - } else { - c->mon = selmon; - applyrules(c); - } - - if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) - c->x = c->mon->wx + c->mon->ww - WIDTH(c); - if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) - c->y = c->mon->wy + c->mon->wh - HEIGHT(c); - c->x = MAX(c->x, c->mon->wx); - c->y = MAX(c->y, c->mon->wy); - c->bw = borderpx; - - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); - configure(c); /* propagates border_width, if size doesn't change */ - updatewindowtype(c); - updatesizehints(c); - updatewmhints(c); - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, 0); - if (!c->isfloating) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); - attach(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); - XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - setclientstate(c, NormalState); - if (c->mon == selmon) - unfocus(selmon->sel, 0); - c->mon->sel = c; - arrange(c->mon); - XMapWindow(dpy, c->win); - focus(NULL); -} - -void -mappingnotify(XEvent *e) -{ - XMappingEvent *ev = &e->xmapping; - - XRefreshKeyboardMapping(ev); - if (ev->request == MappingKeyboard) - grabkeys(); -} - -void -maprequest(XEvent *e) -{ - static XWindowAttributes wa; - XMapRequestEvent *ev = &e->xmaprequest; - - if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) - return; - if (!wintoclient(ev->window)) - manage(ev->window, &wa); -} - -void -monocle(Monitor *m) -{ - unsigned int n = 0; - Client *c; - - for (c = m->clients; c; c = c->next) - if (ISVISIBLE(c)) - n++; - if (n > 0) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); - for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); -} - -void -motionnotify(XEvent *e) -{ - static Monitor *mon = NULL; - Monitor *m; - XMotionEvent *ev = &e->xmotion; - - if (ev->window != root) - return; - if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - mon = m; -} - -void -movemouse(const Arg *arg) -{ - int x, y, ocx, ocy, nx, ny; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - if (!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nx = ocx + (ev.xmotion.x - x); - ny = ocy + (ev.xmotion.y - y); - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -Client * -nexttiled(Client *c) -{ - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); - return c; -} - -void -pop(Client *c) -{ - detach(c); - attach(c); - focus(c); - arrange(c->mon); -} - -void -propertynotify(XEvent *e) -{ - Client *c; - Window trans; - XPropertyEvent *ev = &e->xproperty; - - if ((ev->window == root) && (ev->atom == XA_WM_NAME)) - updatestatus(); - else if (ev->state == PropertyDelete) - return; /* ignore */ - else if ((c = wintoclient(ev->window))) { - switch(ev->atom) { - default: break; - case XA_WM_TRANSIENT_FOR: - if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)) != NULL)) - arrange(c->mon); - break; - case XA_WM_NORMAL_HINTS: - c->hintsvalid = 0; - break; - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); - break; - } - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) - updatetitle(c); - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } -} - -void -quit(const Arg *arg) -{ - running = 0; -} - -Monitor * -recttomon(int x, int y, int w, int h) -{ - Monitor *m, *r = selmon; - int a, area = 0; - - for (m = mons; m; m = m->next) - if ((a = INTERSECT(x, y, w, h, m)) > area) { - area = a; - r = m; - } - return r; -} - -void -resize(Client *c, int x, int y, int w, int h, int interact) -{ - if (applysizehints(c, &x, &y, &w, &h, interact)) - resizeclient(c, x, y, w, h); -} - -void -resizeclient(Client *c, int x, int y, int w, int h) -{ - XWindowChanges wc; - - c->oldx = c->x; c->x = wc.x = x; - c->oldy = c->y; c->y = wc.y = y; - c->oldw = c->w; c->w = wc.width = w; - c->oldh = c->h; c->h = wc.height = h; - wc.border_width = c->bw; - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); -} - -void -resizemouse(const Arg *arg) -{ - int ocx, ocy, nw, nh; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) - return; - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); - nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); - if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww - && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) - { - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) - togglefloating(NULL); - } - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, nw, nh, 1); - break; - } - } while (ev.type != ButtonRelease); - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - XUngrabPointer(dpy, CurrentTime); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -void -restack(Monitor *m) -{ - Client *c; - XEvent ev; - XWindowChanges wc; - - drawbar(m); - if (!m->sel) - return; - if (m->sel->isfloating || !m->lt[m->sellt]->arrange) - XRaiseWindow(dpy, m->sel->win); - if (m->lt[m->sellt]->arrange) { - wc.stack_mode = Below; - wc.sibling = m->barwin; - for (c = m->stack; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) { - XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); - wc.sibling = c->win; - } - } - XSync(dpy, False); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); -} - -void -run(void) -{ - XEvent ev; - /* main event loop */ - XSync(dpy, False); - while (running && !XNextEvent(dpy, &ev)) - if (handler[ev.type]) - handler[ev.type](&ev); /* call handler */ -} - -void -scan(void) -{ - unsigned int i, num; - Window d1, d2, *wins = NULL; - XWindowAttributes wa; - - if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { - for (i = 0; i < num; i++) { - if (!XGetWindowAttributes(dpy, wins[i], &wa) - || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) - continue; - if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) - manage(wins[i], &wa); - } - for (i = 0; i < num; i++) { /* now the transients */ - if (!XGetWindowAttributes(dpy, wins[i], &wa)) - continue; - if (XGetTransientForHint(dpy, wins[i], &d1) - && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) - manage(wins[i], &wa); - } - if (wins) - XFree(wins); - } -} - -void -sendmon(Client *c, Monitor *m) -{ - if (c->mon == m) - return; - unfocus(c, 1); - detach(c); - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attach(c); - attachstack(c); - focus(NULL); - arrange(NULL); -} - -void -setclientstate(Client *c, long state) -{ - long data[] = { state, None }; - - XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); -} - -int -sendevent(Client *c, Atom proto) -{ - int n; - Atom *protocols; - int exists = 0; - XEvent ev; - - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { - while (!exists && n--) - exists = protocols[n] == proto; - XFree(protocols); - } - if (exists) { - ev.type = ClientMessage; - ev.xclient.window = c->win; - ev.xclient.message_type = wmatom[WMProtocols]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = proto; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(dpy, c->win, False, NoEventMask, &ev); - } - return exists; -} - -void -setfocus(Client *c) -{ - if (!c->neverfocus) { - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); - } - sendevent(c, wmatom[WMTakeFocus]); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - if (fullscreen && !c->isfullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = 1; - c->oldstate = c->isfloating; - c->oldbw = c->bw; - c->bw = 0; - c->isfloating = 1; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); - } else if (!fullscreen && c->isfullscreen){ - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = 0; - c->isfloating = c->oldstate; - c->bw = c->oldbw; - c->x = c->oldx; - c->y = c->oldy; - c->w = c->oldw; - c->h = c->oldh; - resizeclient(c, c->x, c->y, c->w, c->h); - arrange(c->mon); - } -} - -void -setgaps(const Arg *arg) -{ - if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) - selmon->gappx = 0; - else - selmon->gappx += arg->i; - arrange(selmon); -} - -Layout *last_layout; -void -fullscreen(const Arg *arg) -{ - if (selmon->showbar) { - for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); - setlayout(&((Arg) { .v = &layouts[2] })); - } else { - setlayout(&((Arg) { .v = last_layout })); - } - togglebar(arg); -} - -void -setlayout(const Arg *arg) -{ - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if (selmon->sel) - arrange(selmon); - else - drawbar(selmon); -} - -/* arg > 1.0 will set mfact absolutely */ -void -setmfact(const Arg *arg) -{ - float f; - - if (!arg || !selmon->lt[selmon->sellt]->arrange) - return; - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.05 || f > 0.95) - return; - selmon->mfact = f; - arrange(selmon); -} - -void -setup(void) -{ - int i; - XSetWindowAttributes wa; - Atom utf8string; - struct sigaction sa; - - /* do not transform children into zombies when they terminate */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; - sa.sa_handler = SIG_IGN; - sigaction(SIGCHLD, &sa, NULL); - - /* clean up any zombies (inherited from .xinitrc etc) immediately */ - while (waitpid(-1, NULL, WNOHANG) > 0); - - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - root = RootWindow(dpy, screen); - xinitvisual(); - drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; - bh = drw->fonts->h + 2; - updategeom(); - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); - netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); - /* init cursors */ - cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); - cursor[CurResize] = drw_cur_create(drw, XC_sizing); - cursor[CurMove] = drw_cur_create(drw, XC_fleur); - /* init appearance */ - scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); - unsigned int alphas[] = {borderalpha, baralpha, OPAQUE}; - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], alphas, 3); - /* init bars */ - updatebars(); - updatestatus(); - /* supporting window for NetWMCheck */ - wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 3); - XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - /* EWMH support per view */ - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); - XDeleteProperty(dpy, root, netatom[NetClientList]); - /* select events */ - wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask - |ButtonPressMask|PointerMotionMask|EnterWindowMask - |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); - focus(NULL); -} - -void -seturgent(Client *c, int urg) -{ - XWMHints *wmh; - - c->isurgent = urg; - if (!(wmh = XGetWMHints(dpy, c->win))) - return; - wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); - XSetWMHints(dpy, c->win, wmh); - XFree(wmh); -} - -void -showhide(Client *c) -{ - if (!c) - return; - if (ISVISIBLE(c)) { - /* show clients top down */ - XMoveWindow(dpy, c->win, c->x, c->y); - if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, 0); - showhide(c->snext); - } else { - /* hide clients bottom up */ - showhide(c->snext); - XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); - } -} - -void -spawn(const Arg *arg) -{ - struct sigaction sa; - - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); - setsid(); - - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigaction(SIGCHLD, &sa, NULL); - - execvp(((char **)arg->v)[0], (char **)arg->v); - die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); - } -} - -void -tag(const Arg *arg) -{ - if (selmon->sel && arg->ui & TAGMASK) { - selmon->sel->tags = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); - } -} - -void -tagmon(const Arg *arg) -{ - if (!selmon->sel || !mons->next) - return; - sendmon(selmon->sel, dirtomon(arg->i)); -} - -void -tile(Monitor *m) -{ - unsigned int i, n, h, mw, my, ty; - Client *c; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - if (n == 0) - return; - - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else - mw = m->ww - m->gappx; - for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; - resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); - if (my + HEIGHT(c) + m->gappx < m->wh) - my += HEIGHT(c) + m->gappx; - } else { - h = (m->wh - ty) / (n - i) - m->gappx; - resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); - if (ty + HEIGHT(c) + m->gappx < m->wh) - ty += HEIGHT(c) + m->gappx; - } -} - -void -togglebar(const Arg *arg) -{ - selmon->showbar = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); -} - -void -togglefloating(const Arg *arg) -{ - if (!selmon->sel) - return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ - return; - selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if (selmon->sel->isfloating) - resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); - arrange(selmon); -} - -void -toggletag(const Arg *arg) -{ - unsigned int newtags; - - if (!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - selmon->sel->tags = newtags; - focus(NULL); - arrange(selmon); - } -} - -void -toggleview(const Arg *arg) -{ - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); - arrange(selmon); - } -} - -void -unfocus(Client *c, int setfocus) -{ - if (!c) - return; - grabbuttons(c, 0); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); - if (setfocus) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } -} - -void -unmanage(Client *c, int destroyed) -{ - Monitor *m = c->mon; - XWindowChanges wc; - - detach(c); - detachstack(c); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ - XSetErrorHandler(xerrordummy); - XSelectInput(dpy, c->win, NoEventMask); - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - setclientstate(c, WithdrawnState); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } - free(c); - focus(NULL); - updateclientlist(); - arrange(m); -} - -void -unmapnotify(XEvent *e) -{ - Client *c; - XUnmapEvent *ev = &e->xunmap; - - if ((c = wintoclient(ev->window))) { - if (ev->send_event) - setclientstate(c, WithdrawnState); - else - unmanage(c, 0); - } -} - -void -updatebars(void) -{ - Monitor *m; - XSetWindowAttributes wa = { - .override_redirect = True, - .background_pixel = 0, - .border_pixel = 0, - .colormap = cmap, - .event_mask = ButtonPressMask|ExposureMask - }; - XClassHint ch = {"dwm", "dwm"}; - for (m = mons; m; m = m->next) { - if (m->barwin) - continue; - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, depth, - InputOutput, visual, - CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); - XSetClassHint(dpy, m->barwin, &ch); - } -} - -void -updatebarpos(Monitor *m) -{ - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; - m->wy = m->topbar ? m->wy + bh : m->wy; - } else - m->by = -bh; -} - -void -updateclientlist(void) -{ - Client *c; - Monitor *m; - - XDeleteProperty(dpy, root, netatom[NetClientList]); - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - XChangeProperty(dpy, root, netatom[NetClientList], - XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -} - -int -updategeom(void) -{ - int dirty = 0; - -#ifdef XINERAMA - if (XineramaIsActive(dpy)) { - int i, j, n, nn; - Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); - XineramaScreenInfo *unique = NULL; - - for (n = 0, m = mons; m; m = m->next, n++); - /* only consider unique geometries as separate screens */ - unique = ecalloc(nn, sizeof(XineramaScreenInfo)); - for (i = 0, j = 0; i < nn; i++) - if (isuniquegeom(unique, j, &info[i])) - memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); - XFree(info); - nn = j; - - /* new monitors if nn > n */ - for (i = n; i < nn; i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); - } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - /* removed monitors if n > nn */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); - } - free(unique); - } else -#endif /* XINERAMA */ - { /* default monitor setup */ - if (!mons) - mons = createmon(); - if (mons->mw != sw || mons->mh != sh) { - dirty = 1; - mons->mw = mons->ww = sw; - mons->mh = mons->wh = sh; - updatebarpos(mons); - } - } - if (dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; -} - -void -updatenumlockmask(void) -{ - unsigned int i, j; - XModifierKeymap *modmap; - - numlockmask = 0; - modmap = XGetModifierMapping(dpy); - for (i = 0; i < 8; i++) - for (j = 0; j < modmap->max_keypermod; j++) - if (modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Num_Lock)) - numlockmask = (1 << i); - XFreeModifiermap(modmap); -} - -void -updatesizehints(Client *c) -{ - long msize; - XSizeHints size; - - if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) - /* size is uninitialized, ensure that size.flags aren't used */ - size.flags = PSize; - if (size.flags & PBaseSize) { - c->basew = size.base_width; - c->baseh = size.base_height; - } else if (size.flags & PMinSize) { - c->basew = size.min_width; - c->baseh = size.min_height; - } else - c->basew = c->baseh = 0; - if (size.flags & PResizeInc) { - c->incw = size.width_inc; - c->inch = size.height_inc; - } else - c->incw = c->inch = 0; - if (size.flags & PMaxSize) { - c->maxw = size.max_width; - c->maxh = size.max_height; - } else - c->maxw = c->maxh = 0; - if (size.flags & PMinSize) { - c->minw = size.min_width; - c->minh = size.min_height; - } else if (size.flags & PBaseSize) { - c->minw = size.base_width; - c->minh = size.base_height; - } else - c->minw = c->minh = 0; - if (size.flags & PAspect) { - c->mina = (float)size.min_aspect.y / size.min_aspect.x; - c->maxa = (float)size.max_aspect.x / size.max_aspect.y; - } else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); - c->hintsvalid = 1; -} - -void -updatestatus(void) -{ - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); - drawbar(selmon); -} - -void -updatetitle(Client *c) -{ - if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) - gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); - if (c->name[0] == '\0') /* hack to mark broken clients */ - strcpy(c->name, broken); -} - -void -updatewindowtype(Client *c) -{ - Atom state = getatomprop(c, netatom[NetWMState]); - Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - - if (state == netatom[NetWMFullscreen]) - setfullscreen(c, 1); - if (wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = 1; -} - -void -updatewmhints(Client *c) -{ - XWMHints *wmh; - - if ((wmh = XGetWMHints(dpy, c->win))) { - if (c == selmon->sel && wmh->flags & XUrgencyHint) { - wmh->flags &= ~XUrgencyHint; - XSetWMHints(dpy, c->win, wmh); - } else - c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; - if (wmh->flags & InputHint) - c->neverfocus = !wmh->input; - else - c->neverfocus = 0; - XFree(wmh); - } -} - -void -view(const Arg *arg) -{ - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); -} - -Client * -wintoclient(Window w) -{ - Client *c; - Monitor *m; - - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - if (c->win == w) - return c; - return NULL; -} - -Monitor * -wintomon(Window w) -{ - int x, y; - Client *c; - Monitor *m; - - if (w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for (m = mons; m; m = m->next) - if (w == m->barwin) - return m; - if ((c = wintoclient(w))) - return c->mon; - return selmon; -} - -/* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ -int -xerror(Display *dpy, XErrorEvent *ee) -{ - if (ee->error_code == BadWindow - || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) - || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) - || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) - || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) - || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) - || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) - || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) - || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) - return 0; - fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); - return xerrorxlib(dpy, ee); /* may call exit */ -} - -int -xerrordummy(Display *dpy, XErrorEvent *ee) -{ - return 0; -} - -/* Startup Error handler to check if another window manager - * is already running. */ -int -xerrorstart(Display *dpy, XErrorEvent *ee) -{ - die("dwm: another window manager is already running"); - return -1; -} - -void -xinitvisual() -{ - XVisualInfo *infos; - XRenderPictFormat *fmt; - int nitems; - int i; - - XVisualInfo tpl = { - .screen = screen, - .depth = 32, - .class = TrueColor - }; - long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; - - infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); - visual = NULL; - for(i = 0; i < nitems; i ++) { - fmt = XRenderFindVisualFormat(dpy, infos[i].visual); - if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { - visual = infos[i].visual; - depth = infos[i].depth; - cmap = XCreateColormap(dpy, root, visual, AllocNone); - useargb = 1; - break; - } - } - - XFree(infos); - - if (! visual) { - visual = DefaultVisual(dpy, screen); - depth = DefaultDepth(dpy, screen); - cmap = DefaultColormap(dpy, screen); - } -} - -void -zoom(const Arg *arg) -{ - Client *c = selmon->sel; - - if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) - return; - if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) - return; - pop(c); -} - -int -main(int argc, char *argv[]) -{ - if (argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION); - else if (argc != 1) - die("usage: dwm [-v]"); - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); - checkotherwm(); - setup(); -#ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec", NULL) == -1) - die("pledge"); -#endif /* __OpenBSD__ */ - scan(); - run(); - cleanup(); - XCloseDisplay(dpy); - return EXIT_SUCCESS; -} diff --git a/dwm.c.rej b/dwm.c.rej deleted file mode 100644 index 544687d..0000000 --- a/dwm.c.rej +++ /dev/null @@ -1,20 +0,0 @@ ---- dwm.c Mon Feb 24 21:41:55 2020 -+++ dwm.c Mon Feb 24 21:48:42 2020 -@@ -242,6 +243,7 @@ - static int xerrordummy(Display *dpy, XErrorEvent *ee); - static int xerrorstart(Display *dpy, XErrorEvent *ee); - static void xinitvisual(); -+static void drawroundedcorners(Client *c); - - /* variables */ - static const char broken[] = "broken"; -@@ -1446,6 +1500,9 @@ - - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, nw, nh, 1); -+ -+ drawroundedcorners(c); -+ - break; - } - } while (ev.type != ButtonRelease); diff --git a/dwm.o b/dwm.o index d1ab97f48697fa03524d8c50ea50df2c4cf70861..9dd1dacd8ae05a98dadeeccd1ea11fd82d1ba436 100644 GIT binary patch literal 56832 zcmeHweSB2K)&JcjXh7VJ6>C~;T{UP>z(i3K!J35)+~^|F1c`u!kOUG5NlbPjR4dUX z!uArS)mB?=YhRw$KKfKzTZ^v*!<%mvQCsUPTGU`rsVGq2^822db2gJ9_wo1peV#v` zfz7@5J7>Ndf0u&cKzRj#KiYajs5FoMWA@I<9wX2k2dI za*Nw_VT)UQFn)~N*&WYuyH>ZWj1D^Vz3qCd)O9N07JsKcF;*;c@xT(qYJ#OkCG0jh|pNm{4PT4KQcDL)TRi!VCdX?XcoxGMx$KU8F z>`o0MDSKS+7&^M0JK`sz%K60RD{k@n)kJrc!RFHTzLyHSQLv}n?K+>z6n6L0A-S!8 zc26{P|I~1#<6vfJWeV6#H}!Ev@1|a#b4CAX z5^Hv0_na$8TrOLIg045K9X*gZ#!acheaE_<3*;a15pHT5nx6Qe?<_Y}-tKz$bx<9i zYN%@FP!MX{O?A1cQKQ>&3>~3rN$#2NdVe7eGJ{&z%Nm`p2%~vbh23uI4Y#W@FIzE2 zt;5}|(Y)+zBJgnHrXF)s88$;HN-V*?GA~T*A1AuXJl9R#T%zfA@abJ0 z@zeH&PK)Ig;cql=(!S8QH>&ICzR*!gl2YL%g!dh}RUv4O6PnfSC8{-PBe$70t^9Qc{Ta zLmzZdT94=D>*~=>L&;R%!v;_=NQ``M70H;lRmUrs1Ww&Ve_=eSRbd5=!ry3W6&+Hm@)V?6pv@LsbF{Rn*L$D+qQ9T5 zv2cI74f#XpwO~$9g*VN8Fh}YBj;*WJ@hs-F)%B)ilat7t)4y|0Px+&_A$tR=b`$|@ z?t!PD8hHT$?t}DKojn@<;Ag)Mhe>!Bp6^KDI4zIiQ|WeHlC!m>j>q-P3irA_D#QB*E*(R~EAyxv23FTKdAV*^V_t5ot2Qrt-`za;X?)Gk z>VR2A^IDWdP)@tsrMwFDHpU#Z<#xUtTKRKua+42%80Onae6o1Laq0eXz>iZgv>4L+pzuG>WVnR7*CE|gZ5`b_y@Xl%u@P ze7tZ+nfIr>)u3d3pc`^eB$-gCg#2MVuLzhMR#;VEw+aq(d1Tll!LL(Qx!Nm5)H;AyX%`>nL_@duPVdgMgblOU=@)okfna`wMfqexFY zm~y@E)VrPim@mDXRO5=>aD3SA7W7b0WLDwhk;@{Fl2DPEk;<8c?^RsNtxqY#(E_D< zN>d-Fc9$0Jiaht0ml-ME)OKd*-p#I8k^Sh3{N}*oxZ~C;J$fC}A%-n4@4xu{=0Dt(sqZ;m{mo1*HBsCFqqXJ1~H{5&i1cv*5&czW^M ziQo2b?)yG;rCR}khw_6(WLR30J*-1F^?5~V9~2oLq{v(-awIH+71>3$Ftj4G(~8W| ziX5dx=zKYGM&yB!Xg20^rF9hd6dzXLm5%4aTMj+S)(#*<|pJgRByUCt#thg_6F9jjFhm1E=DjI=viKIS) zbAdYkG9RrSJmNH8%n_4ZF9-eWrnYzN`l7URSNt$KeJbFlGF|V_YRIHsGHr+LS6Qwa z*Q$<7eAw4X@QNxt1QA!(C-OoM?#yocCaRMPv;n%PCzYuL>pRljcrZJ;Gmz>e(F?ox zX9nWK3%iq7XFG^MQk~>TAjs@FS138E5JqBF{{lWDvYsMOgc`{w`(XtLB(y8gbqulz z3@-9(G_$}5W+P_C;4%Ilug*)#FO^OxfWJM)O~TJYo7d!J$1_9spP(~+3=}iUi*tIQ zp?|Bf?RqO<#zvq?dnYI zu!Zy$&-Icjs!6I)CNd!!*p^brfh}2-e~gz@;Y~8ESQMqy<$*2PoT=iQq>67MlTt~# z)Fr$b`JFqWT7XFChmUoQ8WRb0M~b&!JHB+~j`$ewW@?`9wXUr4A4d)xjHG%}+vp^< zF|a#2<{v4Kr1xfw^)%myNYcq&qlO2z7XSU)al|Hn2sWv$!X+Abe9XU79u+&VC6gpR zGWqt%1OkfJd*^;k+D|Hll}Ekk+Stj-N)W~qo+{woOqFA0K|>+xdDJpAM@4zsrj!Bn zO(kX_FzcIyPIJ9W3Sd|{t`|Y1J}M8_MPzBYUIg>z8x*l-r#^(m^2kC~m<>re#xIHg z;P+G%tBNGA&JQFGo3s1R|L*Uf)1xL58ujdbE)Ctktg>)Ntn2Ri=qqy|m!&qvifghH zr|1#lWu8@9o_r$Xz>X6i>v;3?LVDUNp<6*bAKW$+LeVMeA@Ay`{Nmb?I7wo@KS2l@jX;9v~n(tSf)|9S7Qm7mbd2JDPe! z(M4uQ=0HjFOAGr;3wOZfKv`ovwR}(g^}0{`VJV@~4ka3YWvQMgq<$g7m?re0G;v}DXPg>Xq#D>~O#SEAAT zA0Q7@!Gu3%VGjH|wcDtEanZLUsm=4EW8NCGd7|pPYbT~T>T0<&xjdCd=%})E%n_wP zL`gRLa^5MR^#X;yyiQ8OR97BEO=j1o$wD-LS|E|pKx;+Qc z4#T~#R6PU_U!`cLAP|Lz-w7h#14^9XRltGY^4w}*Zt^?XP8^tJu z=hq^BPyuFd?}z>UV6oV2BQ~@0-|O#Z0aTZ!9V8nSn?OlDt7s_NuJixBXE2x9I(q0y z_uyTSZcq=>(iuI7zt|Q@EEKUZ(zCsGy$I7)Ar{7b@|L=QGeBH{ovu-N8;&9dJ5qWv zs7XCUR+tU8q_6Z|9YzM%MCzl8hfv>LfJuE=(zMJ>eO$PoOfOR2`-KW3SQ%=rlD
  • LH$&`yiH6DEhjh>YFBQNUwUu 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 delta 18927 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 - #endif /* XINERAMA */ -+#include - #include - - #include "drw.h" -@@ -241,6 +242,7 @@ - static int xerrordummy(Display *dpy, XErrorEvent *ee); - static int xerrorstart(Display *dpy, XErrorEvent *ee); - static void xinitvisual(); -+static void drawroundedcorners(Client *c); - - /* variables */ - static const char broken[] = "broken"; -@@ -1133,6 +1135,9 @@ - unfocus(selmon->sel, 0); - c->mon->sel = c; - arrange(c->mon); -+ -+ drawroundedcorners(c); -+ - XMapWindow(dpy, c->win); - focus(NULL); - } -@@ -1337,6 +1342,55 @@ - XSync(dpy, False); - } - -+void drawroundedcorners(Client *c) { -+ // if set to zero in config.h, do not attempt to round -+ if(CORNER_RADIUS < 0) return; -+ -+ // NOTE: this is extremely hacky and surely could be optimized. -+ // Any X wizards out there reading this, please pull request. -+ if (CORNER_RADIUS > 0 && c && !c->isfullscreen) { -+ Window win; -+ win = c->win; -+ if(!win) return; -+ -+ XWindowAttributes win_attr; -+ if(!XGetWindowAttributes(dpy, win, &win_attr)) return; -+ -+ // set in config.h: -+ int dia = 2 * CORNER_RADIUS; -+ int w = c->w; -+ int h = c->h; -+ if(w < dia || h < dia) return; -+ -+ Pixmap mask; -+ mask = XCreatePixmap(dpy, win, w, h, 1); -+ if(!mask) return; -+ -+ XGCValues xgcv; -+ GC shape_gc; -+ shape_gc = XCreateGC(dpy, mask, 0, &xgcv); -+ -+ if(!shape_gc) { -+ XFreePixmap(dpy, mask); -+ free(shape_gc); -+ return; -+ } -+ -+ XSetForeground(dpy, shape_gc, 0); -+ XFillRectangle(dpy, mask, shape_gc, 0, 0, w, h); -+ XSetForeground(dpy, shape_gc, 1); -+ XFillArc(dpy, mask, shape_gc, 0, 0, dia, dia, 0, 23040); -+ XFillArc(dpy, mask, shape_gc, w-dia-1, 0, dia, dia, 0, 23040); -+ XFillArc(dpy, mask, shape_gc, 0, h-dia-1, dia, dia, 0, 23040); -+ XFillArc(dpy, mask, shape_gc, w-dia-1, h-dia-1, dia, dia, 0, 23040); -+ XFillRectangle(dpy, mask, shape_gc, CORNER_RADIUS, 0, w-dia, h); -+ XFillRectangle(dpy, mask, shape_gc, 0, CORNER_RADIUS, w, h-dia); -+ XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, mask, ShapeSet); -+ XFreePixmap(dpy, mask); -+ XFreeGC(dpy, shape_gc); -+ } -+} -+ - void - resizemouse(const Arg *arg) - { -@@ -1393,6 +1447,9 @@ - - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, nw, nh, 1); -+ -+ drawroundedcorners(c); -+ - break; - } - } while (ev.type != ButtonRelease); -@@ -1406,6 +1463,7 @@ - selmon = m; - focus(NULL); - } -+ drawroundedcorners(c); - } - - void