Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/config.def.h b/config.def.h
- index 7054c06..c6cf7ee 100644
- --- a/config.def.h
- +++ b/config.def.h
- @@ -1,52 +1,65 @@
- /* See LICENSE file for copyright and license details. */
- +#include <X11/XF86keysym.h>
- /* appearance */
- static const char *fonts[] = {
- - "monospace:size=10"
- + "Terminus:pixelsize=9"
- };
- -static const char dmenufont[] = "monospace:size=10";
- -static const char normbordercolor[] = "#444444";
- -static const char normbgcolor[] = "#222222";
- -static const char normfgcolor[] = "#bbbbbb";
- -static const char selbordercolor[] = "#005577";
- -static const char selbgcolor[] = "#005577";
- -static const char selfgcolor[] = "#eeeeee";
- -static const unsigned int borderpx = 1; /* border pixel of windows */
- +static const char dmenufont[] = "Terminus:pixelsize=9";
- +static const char normbordercolor[] = "#fdf6e3";
- +static const char normbgcolor[] = "#002b36";
- +static const char normfgcolor[] = "#93a1a1";
- +static const char selbordercolor[] = "#002b36";
- +static const char selbgcolor[] = "#586e75";
- +static const char selfgcolor[] = "#fdf6e3";
- +static const char urgbordercolor[] = "#dc322f";
- +static const unsigned int borderpx = 3; /* border pixel of windows */
- static const unsigned int snap = 32; /* snap pixel */
- +static const unsigned int systraypinning = 1; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
- +static const unsigned int systrayspacing = 1; /* systray spacing */
- +static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, 0: display systray on the last monitor*/
- +static const int showsystray = 1; /* 0 means no systray */
- static const int showbar = 1; /* 0 means no bar */
- static const int topbar = 1; /* 0 means bottom bar */
- /* tagging */
- -static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
- +static const char *tags[] = { "term", "web", "ide", "doc", "fm", "media", "gfx", "bt" };
- static const Rule rules[] = {
- - /* xprop(1):
- - * WM_CLASS(STRING) = instance, class
- - * WM_NAME(STRING) = title
- - */
- - /* class instance title tags mask isfloating monitor */
- - { "Gimp", NULL, NULL, 0, 1, -1 },
- - { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
- + /* class instance title tags mask isfloating ispermanent monitor */
- + { "Display", NULL, NULL, 0, True, False, -1 },
- + { "feh", NULL, NULL, 0, True, False, -1 },
- + { "Firefox", NULL, NULL, 1 << 1, False, False, -1 },
- + { "Jumanji", NULL, NULL, 1 << 1, False, False, -1 },
- + { "QtCreator",NULL, NULL, 1 << 2, False, False, -1 },
- + { "Zathura", NULL, NULL, 1 << 3, False, False, -1 },
- + { "Thunar", NULL, NULL, 1 << 4, False, False, -1 },
- + { "mpv", NULL, NULL, 1 << 5, False, -1 },
- + { "Blender", NULL, NULL, 1 << 6, False, -1 },
- + { "Gimp", NULL, NULL, 1 << 6, False, -1 },
- + { "Transmission-gtk",NULL,NULL, 1 << 7, False, -1 },
- + { "Deluge", NULL, NULL, 1 << 7, False, -1 },
- };
- /* layout(s) */
- -static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
- +static const float mfact = 0.65; /* factor of master area size [0.05..0.95] */
- static const int nmaster = 1; /* number of clients in master area */
- -static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
- +static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
- static const Layout layouts[] = {
- /* symbol arrange function */
- - { "[]=", tile }, /* first entry is default */
- - { "><>", NULL }, /* no layout function means floating behavior */
- - { "[M]", monocle },
- + { "T", tile }, /* first entry is default */
- + { "F", NULL }, /* no layout function means floating behavior */
- + { "M", monocle },
- + { "G", htile },
- };
- /* key definitions */
- -#define MODKEY Mod1Mask
- +#define MODKEY Mod4Mask
- #define TAGKEYS(KEY,TAG) \
- - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
- + { MODKEY, KEY, comboview, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
- - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
- + { MODKEY|ShiftMask, KEY, combotag, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
- /* helper for spawning shell commands in the pre dwm-5.0 fashion */
- @@ -55,25 +68,34 @@ static const Layout layouts[] = {
- /* commands */
- static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
- static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
- -static const char *termcmd[] = { "st", NULL };
- +static const char *termcmd[] = { "urxvtc", NULL };
- +static const char *webcmd[] = { "firefox", NULL };
- +static const char *fmcmd[] = { "thunar", NULL };
- +static const char *logoutcmd[] = { "xfce4-session-logout", NULL );
- static Key keys[] = {
- /* modifier key function argument */
- { MODKEY, XK_p, spawn, {.v = dmenucmd } },
- - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
- + { MODKEY, XK_a, spawn, {.v = termcmd } },
- + { MODKEY, XK_w, spawn, {.v = webcmd } },
- + { MODKEY, XK_q, spawn, {.v = fmcmd } },
- { MODKEY, XK_b, togglebar, {0} },
- { MODKEY, XK_j, focusstack, {.i = +1 } },
- { MODKEY, XK_k, focusstack, {.i = -1 } },
- { MODKEY, XK_i, incnmaster, {.i = +1 } },
- - { MODKEY, XK_d, incnmaster, {.i = -1 } },
- + { MODKEY, XK_u, incnmaster, {.i = -1 } },
- { MODKEY, XK_h, setmfact, {.f = -0.05} },
- { MODKEY, XK_l, setmfact, {.f = +0.05} },
- + { MODKEY, XK_o, setcfact, {.f = +0.25} },
- + { MODKEY, XK_y, setcfact, {.f = -0.25} },
- + { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} },
- { MODKEY, XK_Return, zoom, {0} },
- { MODKEY, XK_Tab, view, {0} },
- { MODKEY|ShiftMask, XK_c, killclient, {0} },
- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
- { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
- + { MODKEY, XK_g, setlayout, {.v = &layouts[3]} },
- { MODKEY, XK_space, setlayout, {0} },
- { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
- { MODKEY, XK_0, view, {.ui = ~0 } },
- @@ -90,8 +112,7 @@ static Key keys[] = {
- TAGKEYS( XK_6, 5)
- TAGKEYS( XK_7, 6)
- TAGKEYS( XK_8, 7)
- - TAGKEYS( XK_9, 8)
- - { MODKEY|ShiftMask, XK_q, quit, {0} },
- + { MODKEY|ShiftMask, XK_q, spawn, {.v = logoutcmd } },
- };
- /* button definitions */
- diff --git a/dwm.c b/dwm.c
- index 0362114..89aadd8 100644
- --- a/dwm.c
- +++ b/dwm.c
- @@ -49,7 +49,8 @@
- #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 ISVISIBLEONTAG(C, T) ((C->tags & T))
- +#define ISVISIBLE(C) ISVISIBLEONTAG(C, 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)
- @@ -57,12 +58,30 @@
- #define TAGMASK ((1 << LENGTH(tags)) - 1)
- #define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h)
- +#define SYSTEM_TRAY_REQUEST_DOCK 0
- +#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
- +
- +/* XEMBED messages */
- +#define XEMBED_EMBEDDED_NOTIFY 0
- +#define XEMBED_WINDOW_ACTIVATE 1
- +#define XEMBED_FOCUS_IN 4
- +#define XEMBED_MODALITY_ON 10
- +
- +#define XEMBED_MAPPED (1 << 0)
- +#define XEMBED_WINDOW_ACTIVATE 1
- +#define XEMBED_WINDOW_DEACTIVATE 2
- +
- +#define VERSION_MAJOR 0
- +#define VERSION_MINOR 0
- +#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
- +
- /* enums */
- enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
- enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */
- -enum { NetSupported, NetWMName, NetWMState,
- - NetWMFullscreen, NetActiveWindow, NetWMWindowType,
- - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
- +enum { NetSupported, NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation,
- + NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, NetWMWindowType,
- + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
- +enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
- enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
- enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
- ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
- @@ -87,12 +106,13 @@ typedef struct Client Client;
- struct Client {
- char name[256];
- float mina, maxa;
- + float cfact;
- int x, y, w, h;
- int oldx, oldy, oldw, oldh;
- int basew, baseh, incw, inch, maxw, maxh, minw, minh;
- int bw, oldbw;
- unsigned int tags;
- - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
- + int isfixed, ispermanent, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
- Client *next;
- Client *snext;
- Monitor *mon;
- @@ -111,6 +131,7 @@ typedef struct {
- void (*arrange)(Monitor *);
- } Layout;
- +typedef struct Pertag Pertag;
- struct Monitor {
- char ltsymbol[16];
- float mfact;
- @@ -130,6 +151,7 @@ struct Monitor {
- Monitor *next;
- Window barwin;
- const Layout *lt[2];
- + Pertag *pertag;
- };
- typedef struct {
- @@ -138,15 +160,23 @@ typedef struct {
- const char *title;
- unsigned int tags;
- int isfloating;
- + int ispermanent;
- int monitor;
- } Rule;
- +typedef struct Systray Systray;
- +struct Systray {
- + Window win;
- + Client *icons;
- +};
- +
- /* 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 attachaside(Client *c);
- static void attachstack(Client *c);
- static void buttonpress(XEvent *e);
- static void checkotherwm(void);
- @@ -162,6 +192,7 @@ static void destroynotify(XEvent *e);
- static void detach(Client *c);
- static void detachstack(Client *c);
- static Monitor *dirtomon(int dir);
- +static void dmenuspawn(const Arg *arg);
- static void drawbar(Monitor *m);
- static void drawbars(void);
- static void enternotify(XEvent *e);
- @@ -170,8 +201,10 @@ 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 unsigned int getsystraywidth();
- static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
- static void grabbuttons(Client *c, int focused);
- static void grabkeys(void);
- @@ -184,31 +217,38 @@ static void maprequest(XEvent *e);
- static void monocle(Monitor *m);
- static void motionnotify(XEvent *e);
- static void movemouse(const Arg *arg);
- +static Client *nexttagged(Client *c);
- static Client *nexttiled(Client *c);
- static void pop(Client *);
- static void propertynotify(XEvent *e);
- static void quit(const Arg *arg);
- static Monitor *recttomon(int x, int y, int w, int h);
- +static void removesystrayicon(Client *i);
- static void resize(Client *c, int x, int y, int w, int h, int interact);
- +static void resizebarwin(Monitor *m);
- static void resizeclient(Client *c, int x, int y, int w, int h);
- static void resizemouse(const Arg *arg);
- +static void resizerequest(XEvent *e);
- static void restack(Monitor *m);
- static void run(void);
- static void scan(void);
- -static int sendevent(Client *c, Atom proto);
- +static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
- 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 setlayout(const Arg *arg);
- +static void setcfact(const Arg *arg);
- static void setmfact(const Arg *arg);
- static void setup(void);
- static void showhide(Client *c);
- static void sigchld(int unused);
- static void spawn(const Arg *arg);
- +static Monitor *systraytomon(Monitor *m);
- static void tag(const Arg *arg);
- static void tagmon(const Arg *arg);
- static void tile(Monitor *);
- +static void htile(Monitor *);
- static void togglebar(const Arg *arg);
- static void togglefloating(const Arg *arg);
- static void toggletag(const Arg *arg);
- @@ -223,18 +263,30 @@ static void updateclientlist(void);
- static void updatenumlockmask(void);
- static void updatesizehints(Client *c);
- static void updatestatus(void);
- +static void updatesystray(void);
- +static void updatesystrayicongeom(Client *i, int w, int h);
- +static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
- static void updatewindowtype(Client *c);
- static void updatetitle(Client *c);
- static void updatewmhints(Client *c);
- static void view(const Arg *arg);
- +static void warp(const Client *c);
- static Client *wintoclient(Window w);
- static Monitor *wintomon(Window w);
- +static Client *wintosystrayicon(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 zoom(const Arg *arg);
- +static void keyrelease(XEvent *e);
- +static void combotag(const Arg *arg);
- +static void comboview(const Arg *arg);
- +
- +
- /* variables */
- +static Systray *systray = NULL;
- +static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
- static const char broken[] = "broken";
- static char stext[256];
- static int screen;
- @@ -244,6 +296,7 @@ static int (*xerrorxlib)(Display *, XErrorEvent *);
- static unsigned int numlockmask = 0;
- static void (*handler[LASTEvent]) (XEvent *) = {
- [ButtonPress] = buttonpress,
- + [ButtonRelease] = keyrelease,
- [ClientMessage] = clientmessage,
- [ConfigureRequest] = configurerequest,
- [ConfigureNotify] = configurenotify,
- @@ -251,14 +304,16 @@ static void (*handler[LASTEvent]) (XEvent *) = {
- [EnterNotify] = enternotify,
- [Expose] = expose,
- [FocusIn] = focusin,
- + [KeyRelease] = keyrelease,
- [KeyPress] = keypress,
- [MappingNotify] = mappingnotify,
- [MapRequest] = maprequest,
- [MotionNotify] = motionnotify,
- [PropertyNotify] = propertynotify,
- + [ResizeRequest] = resizerequest,
- [UnmapNotify] = unmapnotify
- };
- -static Atom wmatom[WMLast], netatom[NetLast];
- +static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
- static int running = 1;
- static Cur *cursor[CurLast];
- static ClrScheme scheme[SchemeLast];
- @@ -270,10 +325,54 @@ static Window root;
- /* configuration, allows nested code to access above variables */
- #include "config.h"
- +struct Pertag {
- + unsigned int curtag, prevtag; /* current and previous tag */
- + int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
- + float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
- + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */
- + const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */
- +};
- +
- /* compile-time check if all tags fit into an unsigned int bit array. */
- struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
- /* function implementations */
- +static int combo = 0;
- +
- +void
- +keyrelease(XEvent *e) {
- + combo = 0;
- +}
- +
- +void
- +combotag(const Arg *arg) {
- + if(selmon->sel && arg->ui & TAGMASK) {
- + if (combo) {
- + selmon->sel->tags |= arg->ui & TAGMASK;
- + } else {
- + combo = 1;
- + selmon->sel->tags = arg->ui & TAGMASK;
- + }
- + focus(NULL);
- + arrange(selmon);
- + }
- +}
- +
- +void
- +comboview(const Arg *arg) {
- + unsigned newtags = arg->ui & TAGMASK;
- + if (combo) {
- + selmon->tagset[selmon->seltags] |= newtags;
- + } else {
- + selmon->seltags ^= 1; /*toggle tagset*/
- + combo = 1;
- + if (newtags)
- + selmon->tagset[selmon->seltags] = newtags;
- + }
- + focus(NULL);
- + arrange(selmon);
- +}
- +
- void
- applyrules(Client *c)
- {
- @@ -297,6 +396,7 @@ applyrules(Client *c)
- && (!r->instance || strstr(instance, r->instance)))
- {
- c->isfloating = r->isfloating;
- + c->ispermanent = r->ispermanent;
- c->tags |= r->tags;
- for (m = mons; m && m->num != r->monitor; m = m->next);
- if (m)
- @@ -310,6 +410,34 @@ applyrules(Client *c)
- c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
- }
- +void
- +adjustborders(Monitor *m) {
- + Client *c, *l = NULL;
- + int visible = 0;
- +
- + for(c = m->clients; c; c = c->next) {
- + if (ISVISIBLE(c) && !c->isfloating && m->lt[m->sellt]->arrange) {
- + if (m->lt[m->sellt]->arrange == monocle) {
- + visible = 1;
- + c->oldbw = c->bw;
- + c->bw = 0;
- + } else {
- + visible++;
- + c->oldbw = c->bw;
- + c->bw = borderpx;
- + }
- +
- + l = c;
- + }
- + }
- +
- + if (l && visible == 1 && l->bw) {
- + l->oldbw = l->bw;
- + l->bw = 0;
- + resizeclient(l, l->x, l->y, l->w, l->h);
- + }
- +}
- +
- int
- applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
- {
- @@ -379,10 +507,13 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
- void
- arrange(Monitor *m)
- {
- - if (m)
- + if (m) {
- + adjustborders(m);
- showhide(m->stack);
- - else for (m = mons; m; m = m->next)
- + } else for (m = mons; m; m = m->next) {
- + adjustborders(m);
- showhide(m->stack);
- + }
- if (m) {
- arrangemon(m);
- restack(m);
- @@ -406,6 +537,17 @@ attach(Client *c)
- }
- void
- +attachaside(Client *c) {
- + Client *at = nexttagged(c);
- + if(!at) {
- + attach(c);
- + return;
- + }
- + c->next = at->next;
- + at->next = c;
- +}
- +
- +void
- attachstack(Client *c)
- {
- c->snext = c->mon->stack;
- @@ -479,6 +621,11 @@ cleanup(void)
- XUngrabKey(dpy, AnyKey, AnyModifier, root);
- while (mons)
- cleanupmon(mons);
- + if (showsystray) {
- + XUnmapWindow(dpy, systray->win);
- + XDestroyWindow(dpy, systray->win);
- + free(systray);
- + }
- for (i = 0; i < CurLast; i++)
- drw_cur_free(drw, cursor[i]);
- for (i = 0; i < SchemeLast; i++) {
- @@ -524,9 +671,50 @@ clearurgent(Client *c)
- void
- clientmessage(XEvent *e)
- {
- + XWindowAttributes wa;
- + XSetWindowAttributes swa;
- XClientMessageEvent *cme = &e->xclient;
- Client *c = wintoclient(cme->window);
- + if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
- + /* add systray icons */
- + if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
- + if (!(c = (Client *)calloc(1, sizeof(Client))))
- + die("fatal: could not malloc() %u bytes\n", sizeof(Client));
- + c->win = cme->data.l[2];
- + c->mon = selmon;
- + c->next = systray->icons;
- + systray->icons = c;
- + XGetWindowAttributes(dpy, c->win, &wa);
- + c->x = c->oldx = c->y = c->oldy = 0;
- + c->w = c->oldw = wa.width;
- + c->h = c->oldh = wa.height;
- + c->oldbw = wa.border_width;
- + c->bw = 0;
- + c->isfloating = True;
- + /* reuse tags field as mapped status */
- + c->tags = 1;
- + updatesizehints(c);
- + updatesystrayicongeom(c, wa.width, wa.height);
- + XAddToSaveSet(dpy, c->win);
- + XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
- + XReparentWindow(dpy, c->win, systray->win, 0, 0);
- + /* use parents background color */
- + swa.background_pixel = scheme[SchemeNorm].bg->pix;
- + XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
- + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
- + /* FIXME not sure if I have to send these events, too */
- + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
- + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
- + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
- + XSync(dpy, False);
- + resizebarwin(selmon);
- + updatesystray();
- + setclientstate(c, NormalState);
- + }
- + return;
- + }
- +
- if (!c)
- return;
- if (cme->message_type == netatom[NetWMState]) {
- @@ -577,7 +765,7 @@ configurenotify(XEvent *e)
- drw_resize(drw, sw, bh);
- updatebars();
- for (m = mons; m; m = m->next)
- - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
- + resizebarwin(m);
- focus(NULL);
- arrange(NULL);
- }
- @@ -640,6 +828,7 @@ Monitor *
- createmon(void)
- {
- Monitor *m;
- + int i;
- m = ecalloc(1, sizeof(Monitor));
- m->tagset[0] = m->tagset[1] = 1;
- @@ -650,6 +839,21 @@ createmon(void)
- m->lt[0] = &layouts[0];
- m->lt[1] = &layouts[1 % LENGTH(layouts)];
- strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
- + if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag))))
- + die("fatal: could not malloc() %u bytes\n", sizeof(Pertag));
- + m->pertag->curtag = m->pertag->prevtag = 1;
- + for (i=0; i <= LENGTH(tags); i++) {
- + /* init nmaster */
- + m->pertag->nmasters[i] = m->nmaster;
- +
- + /* init mfacts */
- + m->pertag->mfacts[i] = m->mfact;
- +
- + /* init layouts */
- + m->pertag->ltidxs[i][0] = m->lt[0];
- + m->pertag->ltidxs[i][1] = m->lt[1];
- + m->pertag->sellts[i] = m->sellt;
- + }
- return m;
- }
- @@ -661,6 +865,11 @@ destroynotify(XEvent *e)
- if ((c = wintoclient(ev->window)))
- unmanage(c, 1);
- + else if ((c = wintosystrayicon(ev->window))) {
- + removesystrayicon(c);
- + resizebarwin(selmon);
- + updatesystray();
- + }
- }
- void
- @@ -702,6 +911,17 @@ dirtomon(int dir)
- }
- void
- +dmenuspawn(const Arg *arg) {
- + char monstr[2] = "0";
- + const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-m", monstr, "-nb",
- + normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf",
- + selfgcolor, NULL };
- + Arg a = { .v = dmenucmd };
- + monstr[0] = '0' + selmon->num;
- + spawn(&a);
- +}
- +
- +void
- drawbar(Monitor *m)
- {
- int x, xx, w, dx;
- @@ -710,6 +930,7 @@ drawbar(Monitor *m)
- dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4;
- + resizebarwin(m);
- for (c = m->clients; c; c = c->next) {
- occ |= c->tags;
- if (c->isurgent)
- @@ -732,6 +953,9 @@ drawbar(Monitor *m)
- if (m == selmon) { /* status is only drawn on selected monitor */
- w = TEXTW(stext);
- x = m->ww - w;
- + if (showsystray && m == systraytomon(m)) {
- + x -= getsystraywidth();
- + }
- if (x < xx) {
- x = xx;
- w = m->ww - xx;
- @@ -760,6 +984,7 @@ drawbars(void)
- for (m = mons; m; m = m->next)
- drawbar(m);
- + updatesystray();
- }
- void
- @@ -787,8 +1012,11 @@ expose(XEvent *e)
- Monitor *m;
- XExposeEvent *ev = &e->xexpose;
- - if (ev->count == 0 && (m = wintomon(ev->window)))
- + if (ev->count == 0 && (m = wintomon(ev->window))) {
- drawbar(m);
- + if (m == selmon)
- + updatesystray();
- + }
- }
- void
- @@ -840,6 +1068,7 @@ focusmon(const Arg *arg)
- in gedit and anjuta */
- selmon = m;
- focus(NULL);
- + warp(selmon->sel);
- }
- void
- @@ -875,10 +1104,17 @@ getatomprop(Client *c, Atom prop)
- unsigned long dl;
- unsigned char *p = NULL;
- Atom da, atom = None;
- + /* FIXME getatomprop should return the number of items and a pointer to
- + * the stored data instead of this workaround */
- + Atom req = XA_ATOM;
- + if (prop == xatom[XembedInfo])
- + req = xatom[XembedInfo];
- - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
- + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
- &da, &di, &dl, &dl, &p) == Success && p) {
- atom = *(Atom *)p;
- + if (da == xatom[XembedInfo] && dl == 2)
- + atom = ((Atom *)p)[1];
- XFree(p);
- }
- return atom;
- @@ -912,6 +1148,15 @@ getstate(Window w)
- return result;
- }
- +unsigned int
- +getsystraywidth() {
- + unsigned int w = 0;
- + Client *i;
- + if (showsystray)
- + for (i = systray->icons; i; w += i->w + systrayspacing, i = i->next);
- + return w ? w + systrayspacing : 1;
- +}
- +
- int
- gettextprop(Window w, Atom atom, char *text, unsigned int size)
- {
- @@ -981,7 +1226,7 @@ grabkeys(void)
- void
- incnmaster(const Arg *arg)
- {
- - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
- + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
- arrange(selmon);
- }
- @@ -1016,9 +1261,9 @@ keypress(XEvent *e)
- void
- killclient(const Arg *arg)
- {
- - if (!selmon->sel)
- + if(!selmon->sel || selmon->sel->ispermanent)
- return;
- - if (!sendevent(selmon->sel, wmatom[WMDelete])) {
- + if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
- XGrabServer(dpy);
- XSetErrorHandler(xerrordummy);
- XSetCloseDownMode(dpy, DestroyAll);
- @@ -1052,6 +1297,7 @@ manage(Window w, XWindowAttributes *wa)
- c->w = c->oldw = wa->width;
- c->h = c->oldh = wa->height;
- c->oldbw = wa->border_width;
- + c->cfact = 1.0;
- if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
- c->x = c->mon->mx + c->mon->mw - WIDTH(c);
- @@ -1061,7 +1307,20 @@ manage(Window w, XWindowAttributes *wa)
- /* only fix client y-offset, if the client center might cover the bar */
- c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
- && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
- - c->bw = borderpx;
- +
- + updatewindowtype(c);
- + if (c->isfloating) {
- + c->bw = c->isfullscreen ? 0 : borderpx;
- + } else {
- + c->bw = 0;
- + for(t = c->mon->clients; t; t = c->next) {
- + if (!t->isfloating && c != t && c->tags & t->tags) {
- + c->bw = borderpx;
- + break;
- + }
- + }
- + adjustborders(c->mon);
- + }
- wc.border_width = c->bw;
- XConfigureWindow(dpy, w, CWBorderWidth, &wc);
- @@ -1076,7 +1335,7 @@ manage(Window w, XWindowAttributes *wa)
- c->isfloating = c->oldstate = trans != None || c->isfixed;
- if (c->isfloating)
- XRaiseWindow(dpy, c->win);
- - attach(c);
- + attachaside(c);
- attachstack(c);
- XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
- @@ -1105,6 +1364,12 @@ maprequest(XEvent *e)
- {
- static XWindowAttributes wa;
- XMapRequestEvent *ev = &e->xmaprequest;
- + Client *i;
- + if ((i = wintosystrayicon(ev->window))) {
- + sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
- + resizebarwin(selmon);
- + updatesystray();
- + }
- if (!XGetWindowAttributes(dpy, ev->window, &wa))
- return;
- @@ -1210,6 +1475,16 @@ movemouse(const Arg *arg)
- }
- Client *
- +nexttagged(Client *c) {
- + Client *walked = c->mon->clients;
- + for(;
- + walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags));
- + walked = walked->next
- + );
- + return walked;
- +}
- +
- +Client *
- nexttiled(Client *c)
- {
- for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
- @@ -1232,6 +1507,16 @@ propertynotify(XEvent *e)
- Window trans;
- XPropertyEvent *ev = &e->xproperty;
- + if ((c = wintosystrayicon(ev->window))) {
- + if (ev->atom == XA_WM_NORMAL_HINTS) {
- + updatesizehints(c);
- + updatesystrayicongeom(c, c->w, c->h);
- + }
- + else
- + updatesystrayiconstate(c, ev);
- + resizebarwin(selmon);
- + updatesystray();
- + }
- if ((ev->window == root) && (ev->atom == XA_WM_NAME))
- updatestatus();
- else if (ev->state == PropertyDelete)
- @@ -1283,6 +1568,19 @@ recttomon(int x, int y, int w, int h)
- }
- void
- +removesystrayicon(Client *i) {
- + Client **ii;
- +
- + if (!showsystray || !i)
- + return;
- + for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
- + if (ii)
- + *ii = i->next;
- + free(i);
- +}
- +
- +
- +void
- resize(Client *c, int x, int y, int w, int h, int interact)
- {
- if (applysizehints(c, &x, &y, &w, &h, interact))
- @@ -1290,6 +1588,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
- }
- void
- +resizebarwin(Monitor *m) {
- + unsigned int w = m->ww;
- + if (showsystray && m == systraytomon(m))
- + w -= getsystraywidth();
- + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
- +}
- +
- +void
- resizeclient(Client *c, int x, int y, int w, int h)
- {
- XWindowChanges wc;
- @@ -1362,6 +1668,18 @@ resizemouse(const Arg *arg)
- }
- void
- +resizerequest(XEvent *e) {
- + XResizeRequestEvent *ev = &e->xresizerequest;
- + Client *i;
- +
- + if ((i = wintosystrayicon(ev->window))) {
- + updatesystrayicongeom(i, ev->width, ev->height);
- + resizebarwin(selmon);
- + updatesystray();
- + }
- +}
- +
- +void
- restack(Monitor *m)
- {
- Client *c;
- @@ -1384,6 +1702,8 @@ restack(Monitor *m)
- }
- XSync(dpy, False);
- while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
- + if (m == selmon && (m->tagset[m->seltags] & m->sel->tags))
- + warp(m->sel);
- }
- void
- @@ -1434,7 +1754,7 @@ sendmon(Client *c, Monitor *m)
- detachstack(c);
- c->mon = m;
- c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
- - attach(c);
- + attachaside(c);
- attachstack(c);
- focus(NULL);
- arrange(NULL);
- @@ -1450,26 +1770,36 @@ setclientstate(Client *c, long state)
- }
- int
- -sendevent(Client *c, Atom proto)
- +sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
- {
- int n;
- - Atom *protocols;
- + Atom *protocols, mt;
- int exists = 0;
- XEvent ev;
- - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
- - while (!exists && n--)
- - exists = protocols[n] == proto;
- - XFree(protocols);
- + if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
- + mt = wmatom[WMProtocols];
- + if (XGetWMProtocols(dpy, w, &protocols, &n)) {
- + while(!exists && n--)
- + exists = protocols[n] == proto;
- + XFree(protocols);
- + }
- + }
- + else {
- + exists = True;
- + mt = proto;
- }
- if (exists) {
- ev.type = ClientMessage;
- - ev.xclient.window = c->win;
- - ev.xclient.message_type = wmatom[WMProtocols];
- + ev.xclient.window = w;
- + ev.xclient.message_type = mt;
- ev.xclient.format = 32;
- - ev.xclient.data.l[0] = proto;
- - ev.xclient.data.l[1] = CurrentTime;
- - XSendEvent(dpy, c->win, False, NoEventMask, &ev);
- + ev.xclient.data.l[0] = d0;
- + ev.xclient.data.l[1] = d1;
- + ev.xclient.data.l[2] = d2;
- + ev.xclient.data.l[3] = d3;
- + ev.xclient.data.l[4] = d4;
- + XSendEvent(dpy, w, False, mask, &ev);
- }
- return exists;
- }
- @@ -1483,7 +1813,7 @@ setfocus(Client *c)
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char *) &(c->win), 1);
- }
- - sendevent(c, wmatom[WMTakeFocus]);
- + sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
- }
- void
- @@ -1517,10 +1847,13 @@ setfullscreen(Client *c, int fullscreen)
- void
- setlayout(const Arg *arg)
- {
- - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
- - selmon->sellt ^= 1;
- + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) {
- + selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
- + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
- + }
- if (arg && arg->v)
- - selmon->lt[selmon->sellt] = (Layout *)arg->v;
- + selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
- + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
- strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
- if (selmon->sel)
- arrange(selmon);
- @@ -1528,6 +1861,23 @@ setlayout(const Arg *arg)
- drawbar(selmon);
- }
- +void setcfact(const Arg *arg) {
- + float f;
- + Client *c;
- +
- + c = selmon->sel;
- +
- + if(!arg || !c || !selmon->lt[selmon->sellt]->arrange)
- + return;
- + f = arg->f + c->cfact;
- + if(arg->f == 0.0)
- + f = 1.0;
- + else if(f < 0.25 || f > 4.0)
- + return;
- + c->cfact = f;
- + arrange(selmon);
- +}
- +
- /* arg > 1.0 will set mfact absolutly */
- void
- setmfact(const Arg *arg)
- @@ -1539,7 +1889,7 @@ setmfact(const Arg *arg)
- f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
- if (f < 0.1 || f > 0.9)
- return;
- - selmon->mfact = f;
- + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
- arrange(selmon);
- }
- @@ -1569,12 +1919,18 @@ setup(void)
- wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
- netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
- netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
- + netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
- + netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
- + netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
- netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
- netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", 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);
- + xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
- + xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
- + xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
- /* init cursors */
- cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
- cursor[CurResize] = drw_cur_create(drw, XC_sizing);
- @@ -1586,6 +1942,8 @@ setup(void)
- scheme[SchemeSel].border = drw_clr_create(drw, selbordercolor);
- scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor);
- scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor);
- + /* init system tray */
- + updatesystray();
- /* init bars */
- updatebars();
- updatestatus();
- @@ -1645,6 +2003,22 @@ spawn(const Arg *arg)
- }
- }
- +Monitor *
- +systraytomon(Monitor *m) {
- + Monitor *t;
- + int i, n;
- + if (!systraypinning) {
- + if (!m)
- + return selmon;
- + return m == selmon ? m : NULL;
- + }
- + for (n = 1, t = mons; t && t->next; n++, t = t->next);
- + for (i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next);
- + if (systraypinningfailfirst && n < systraypinning)
- + return mons;
- + return t;
- +}
- +
- void
- tag(const Arg *arg)
- {
- @@ -1667,9 +2041,15 @@ void
- tile(Monitor *m)
- {
- unsigned int i, n, h, mw, my, ty;
- + float mfacts = 0, sfacts = 0;
- Client *c;
- - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
- + for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
- + if(n < m->nmaster)
- + mfacts += c->cfact;
- + else
- + sfacts += c->cfact;
- + }
- if (n == 0)
- return;
- @@ -1679,22 +2059,61 @@ tile(Monitor *m)
- mw = m->ww;
- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
- if (i < m->nmaster) {
- - h = (m->wh - my) / (MIN(n, m->nmaster) - i);
- + h = (m->wh - my) * (c->cfact / mfacts);
- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
- my += HEIGHT(c);
- + mfacts -= c->cfact;
- } else {
- - h = (m->wh - ty) / (n - i);
- + h = (m->wh - ty) * (c->cfact / sfacts);
- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
- ty += HEIGHT(c);
- + sfacts -= c->cfact;
- }
- }
- void
- -togglebar(const Arg *arg)
- +htile(Monitor *m) {
- + unsigned int i, n, w, mh, mx, tx;
- + Client *c;
- +
- + for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
- + if(n == 0)
- + return;
- +
- + if(n > m->nmaster)
- + mh = m->nmaster ? m->wh * m->mfact : 0;
- + else
- + mh = m->wh;
- + for(i = mx = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
- + if(i < m->nmaster) {
- + w = (m->ww - mx) / (MIN(n, m->nmaster) - i);
- + resize(c, m->wx + mx, m->wy, w - (2*c->bw), mh - (2*c->bw), False);
- + mx += WIDTH(c);
- + }
- + else {
- + w = (m->ww - tx) / (n - i);
- + resize(c, m->wx + tx, m->wy + mh, w - (2*c->bw), m->wh - mh - (2*c->bw), False);
- + tx += WIDTH(c);
- + }
- +}
- +
- +void
- +ogglebar(const Arg *arg)
- {
- selmon->showbar = !selmon->showbar;
- updatebarpos(selmon);
- - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
- + resizebarwin(selmon);
- + if (showsystray) {
- + XWindowChanges wc;
- + if (!selmon->showbar)
- + wc.y = -bh;
- + else if (selmon->showbar) {
- + wc.y = 0;
- + if (!selmon->topbar)
- + wc.y = selmon->mh - bh;
- + }
- + XConfigureWindow(dpy, systray->win, CWY, &wc);
- + }
- arrange(selmon);
- }
- @@ -1731,9 +2150,27 @@ void
- toggleview(const Arg *arg)
- {
- unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
- + int i;
- if (newtagset) {
- + if (newtagset == ~0) {
- + selmon->pertag->prevtag = selmon->pertag->curtag;
- + selmon->pertag->curtag = 0;
- + }
- + /* test if the user did not select the same tag */
- + if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
- + selmon->pertag->prevtag = selmon->pertag->curtag;
- + for (i=0; !(newtagset & 1 << i); i++) ;
- + selmon->pertag->curtag = i + 1;
- + }
- selmon->tagset[selmon->seltags] = newtagset;
- +
- + /* apply settings for this view */
- + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
- + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
- + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
- + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
- + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
- focus(NULL);
- arrange(selmon);
- }
- @@ -1790,11 +2227,17 @@ unmapnotify(XEvent *e)
- else
- unmanage(c, 0);
- }
- + else if ((c = wintosystrayicon(ev->window))) {
- + removesystrayicon(c);
- + resizebarwin(selmon);
- + updatesystray();
- + }
- }
- void
- updatebars(void)
- {
- + unsigned int w;
- Monitor *m;
- XSetWindowAttributes wa = {
- .override_redirect = True,
- @@ -1804,10 +2247,15 @@ updatebars(void)
- for (m = mons; m; m = m->next) {
- if (m->barwin)
- continue;
- - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
- + w = m->ww;
- + if (showsystray && m == systraytomon(m))
- + w -= getsystraywidth();
- + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
- CopyFromParent, DefaultVisual(dpy, screen),
- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
- XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
- + if (showsystray && m == systraytomon(m))
- + XMapRaised(dpy, systray->win);
- XMapRaised(dpy, m->barwin);
- }
- }
- @@ -1891,7 +2339,7 @@ updategeom(void)
- m->clients = c->next;
- detachstack(c);
- c->mon = mons;
- - attach(c);
- + attachaside(c);
- attachstack(c);
- }
- if (m == selmon)
- @@ -1998,6 +2446,117 @@ updatestatus(void)
- }
- void
- +updatesystrayicongeom(Client *i, int w, int h) {
- + if (i) {
- + i->h = bh;
- + if (w == h)
- + i->w = bh;
- + else if (h == bh)
- + i->w = w;
- + else
- + i->w = (int) ((float)bh * ((float)w / (float)h));
- + applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
- + /* force icons into the systray dimenons if they don't want to */
- + if (i->h > bh) {
- + if (i->w == i->h)
- + i->w = bh;
- + else
- + i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
- + i->h = bh;
- + }
- + }
- +}
- +
- +void
- +updatesystrayiconstate(Client *i, XPropertyEvent *ev) {
- + long flags;
- + int code = 0;
- +
- + if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
- + !(flags = getatomprop(i, xatom[XembedInfo])))
- + return;
- +
- + if (flags & XEMBED_MAPPED && !i->tags) {
- + i->tags = 1;
- + code = XEMBED_WINDOW_ACTIVATE;
- + XMapRaised(dpy, i->win);
- + setclientstate(i, NormalState);
- + }
- + else if (!(flags & XEMBED_MAPPED) && i->tags) {
- + i->tags = 0;
- + code = XEMBED_WINDOW_DEACTIVATE;
- + XUnmapWindow(dpy, i->win);
- + setclientstate(i, WithdrawnState);
- + }
- + else
- + return;
- + sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
- + systray->win, XEMBED_EMBEDDED_VERSION);
- +}
- +
- +void
- +updatesystray(void) {
- + XSetWindowAttributes wa;
- + XWindowChanges wc;
- + Client *i;
- + Monitor *m = systraytomon(NULL);
- + unsigned int x = m->mx + m->mw;
- + unsigned int w = 1;
- +
- + if (!showsystray)
- + return;
- + if (!systray) {
- + /* init systray */
- + if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
- + die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
- + systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel].bg->pix);
- + wa.event_mask = ButtonPressMask | ExposureMask;
- + wa.override_redirect = True;
- + wa.background_pixel = scheme[SchemeNorm].bg->pix;
- + XSelectInput(dpy, systray->win, SubstructureNotifyMask);
- + XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
- + PropModeReplace, (unsigned char *)&systrayorientation, 1);
- + XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
- + XMapRaised(dpy, systray->win);
- + XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
- + if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
- + sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
- + XSync(dpy, False);
- + }
- + else {
- + fprintf(stderr, "dwm: unable to obtain system tray.\n");
- + free(systray);
- + systray = NULL;
- + return;
- + }
- + }
- + for (w = 0, i = systray->icons; i; i = i->next) {
- + /* make sure the background color stays the same */
- + wa.background_pixel = scheme[SchemeNorm].bg->pix;
- + XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
- + XMapRaised(dpy, i->win);
- + w += systrayspacing;
- + i->x = w;
- + XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
- + w += i->w;
- + if (i->mon != m)
- + i->mon = m;
- + }
- + w = w ? w + systrayspacing : 1;
- + x -= w;
- + XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
- + wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
- + wc.stack_mode = Above; wc.sibling = m->barwin;
- + XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
- + XMapWindow(dpy, systray->win);
- + XMapSubwindows(dpy, systray->win);
- + /* redraw background */
- + XSetForeground(dpy, drw->gc, scheme[SchemeNorm].bg->pix);
- + XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
- + XSync(dpy, False);
- +}
- +
- +void
- updatewindowtype(Client *c)
- {
- Atom state = getatomprop(c, netatom[NetWMState]);
- @@ -2031,15 +2590,56 @@ updatewmhints(Client *c)
- void
- view(const Arg *arg)
- {
- + int i;
- + unsigned int tmptag;
- +
- if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
- return;
- selmon->seltags ^= 1; /* toggle sel tagset */
- - if (arg->ui & TAGMASK)
- + if (arg->ui & TAGMASK) {
- + selmon->pertag->prevtag = selmon->pertag->curtag;
- selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
- + if (arg->ui == ~0)
- + selmon->pertag->curtag = 0;
- + else {
- + for (i=0; !(arg->ui & 1 << i); i++) ;
- + selmon->pertag->curtag = i + 1;
- + }
- + } else {
- + tmptag = selmon->pertag->prevtag;
- + selmon->pertag->prevtag = selmon->pertag->curtag;
- + selmon->pertag->curtag = tmptag;
- + }
- + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
- + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
- + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
- + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
- + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
- focus(NULL);
- arrange(selmon);
- }
- +void
- +warp(const Client *c)
- +{
- + Window dummy;
- + int x, y, di;
- + unsigned int dui;
- +
- + if (!c) {
- + XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww / 2, selmon->wy + selmon->wh/2);
- + return;
- + }
- +
- + XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui);
- +
- + if ((x > c->x && y > c->y && x < c->x + c->w && y < c->y + c->h) ||
- + (y > c->mon->by && y < c->mon->by + bh))
- + return;
- +
- + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
- +}
- +
- Client *
- wintoclient(Window w)
- {
- @@ -2070,6 +2670,16 @@ wintomon(Window w)
- return selmon;
- }
- +Client *
- +wintosystrayicon(Window w) {
- + Client *i = NULL;
- +
- + if (!showsystray || !w)
- + return i;
- + for (i = systray->icons; i && i->win != w; i = i->next);
- + return i;
- +}
- +
- /* 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. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement