summaryrefslogtreecommitdiff
path: root/dwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwm.c')
-rw-r--r--dwm.c187
1 files changed, 90 insertions, 97 deletions
diff --git a/dwm.c b/dwm.c
index 97cf3c5..46c1501 100644
--- a/dwm.c
+++ b/dwm.c
@@ -54,7 +54,10 @@
#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 NUMTAGS (LENGTH(tags) + LENGTH(scratchpads))
+#define TAGMASK ((1 << NUMTAGS) - 1)
+#define SPTAG(i) ((1 << LENGTH(tags)) << (i))
+#define SPTAGMASK (((1 << LENGTH(scratchpads))-1) << LENGTH(tags))
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
#define SYSTEM_TRAY_REQUEST_DOCK 0
@@ -180,7 +183,6 @@ static void clientmessage(XEvent *e);
static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
-static void copyvalidchars(char *text, char *rawtext);
static Monitor *createmon(void);
static void destroynotify(XEvent *e);
static void detach(Client *c);
@@ -188,12 +190,12 @@ 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 int getdwmblockspid();
static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
@@ -208,6 +210,7 @@ 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 *);
@@ -234,7 +237,6 @@ static void setup(void);
static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
-static void sigdwmblocks(const Arg *arg);
static void spawn(const Arg *arg);
static Monitor *systraytomon(Monitor *m);
static void tag(const Arg *arg);
@@ -242,6 +244,7 @@ static void tagmon(const Arg *arg);
static void tile(Monitor *);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
+static void togglescratch(const Arg *arg);
static void togglefullscr(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
@@ -262,7 +265,6 @@ static void updatetitle(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
-static void scrollview(const Arg *arg);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
static Client *wintosystrayicon(Window w);
@@ -275,9 +277,6 @@ static void zoom(const Arg *arg);
static Systray *systray = NULL;
static const char broken[] = "broken";
static char stext[256];
-static char rawstext[256];
-static int dwmblockssig;
-pid_t dwmblockspid = 0;
static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */
@@ -290,11 +289,13 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[ConfigureRequest] = configurerequest,
[ConfigureNotify] = configurenotify,
[DestroyNotify] = destroynotify,
+ [EnterNotify] = enternotify,
[Expose] = expose,
[FocusIn] = focusin,
[KeyPress] = keypress,
[MappingNotify] = mappingnotify,
[MapRequest] = maprequest,
+ [MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify,
[ResizeRequest] = resizerequest,
[UnmapNotify] = unmapnotify
@@ -339,6 +340,11 @@ applyrules(Client *c)
{
c->isfloating = r->isfloating;
c->tags |= r->tags;
+ if ((r->tags & SPTAGMASK) && r->isfloating) {
+ c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
+ c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
+ }
+
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
@@ -348,7 +354,7 @@ applyrules(Client *c)
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];
+ c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK);
}
int
@@ -464,8 +470,7 @@ buttonpress(XEvent *e)
click = ClkRootWin;
/* focus monitor if necessary */
- if ((m = wintomon(ev->window)) && m != selmon
- && (focusonwheel || (ev->button != Button4 && ev->button != Button5))) {
+ if ((m = wintomon(ev->window)) && m != selmon) {
unfocus(selmon->sel, 1);
selmon = m;
focus(NULL);
@@ -480,31 +485,15 @@ buttonpress(XEvent *e)
arg.ui = 1 << i;
} else if (ev->x < x + blw)
click = ClkLtSymbol;
- else if (ev->x > (x = selmon->ww - TEXTW(stext) + lrpad - getsystraywidth())) {
+ else if (ev->x > selmon->ww - TEXTW(stext) - getsystraywidth())
click = ClkStatusText;
- char *text = rawstext;
- int i = -1;
- char ch;
- dwmblockssig = 0;
- while (text[++i]) {
- if ((unsigned char)text[i] < ' ') {
- ch = text[i];
- text[i] = '\0';
- x += TEXTW(text) - lrpad;
- text[i] = ch;
- text += i+1;
- i = -1;
- if (x >= ev->x) break;
- dwmblockssig = ch;
- }
- }
- } else
+ else
click = ClkWinTitle;
} else if ((c = wintoclient(ev->window))) {
- if (focusonwheel || (ev->button != Button4 && ev->button != Button5))
- focus(c);
- XAllowEvents(dpy, ReplayPointer, CurrentTime);
- click = ClkClientWin;
+ 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
@@ -737,19 +726,6 @@ configurerequest(XEvent *e)
XSync(dpy, False);
}
-void
-copyvalidchars(char *text, char *rawtext)
-{
- int i = -1, j = 0;
-
- while(rawtext[++i]) {
- if ((unsigned char)rawtext[i] >= ' ') {
- text[j++] = rawtext[i];
- }
- }
- text[j] = '\0';
-}
-
Monitor *
createmon(void)
{
@@ -884,6 +860,25 @@ drawbars(void)
}
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;
@@ -995,18 +990,6 @@ getatomprop(Client *c, Atom prop)
}
int
-getdwmblockspid()
-{
- char buf[16];
- FILE *fp = popen("pidof -s dwmblocks", "r");
- fgets(buf, sizeof(buf), fp);
- pid_t pid = strtoul(buf, NULL, 10);
- pclose(fp);
- dwmblockspid = pid;
- return pid != 0 ? 0 : -1;
-}
-
-int
getrootptr(int *x, int *y)
{
int di;
@@ -1086,7 +1069,7 @@ grabbuttons(Client *c, int focused)
XGrabButton(dpy, buttons[i].button,
buttons[i].mask | modifiers[j],
c->win, False, BUTTONMASK,
- GrabModeSync, GrabModeSync, None, None);
+ GrabModeAsync, GrabModeSync, None, None);
}
}
@@ -1267,6 +1250,23 @@ monocle(Monitor *m)
}
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;
@@ -1814,6 +1814,10 @@ showhide(Client *c)
if (!c)
return;
if (ISVISIBLE(c)) {
+ if ((c->tags & SPTAGMASK) && c->isfloating) {
+ c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
+ c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
+ }
/* show clients top down */
XMoveWindow(dpy, c->win, c->x, c->y);
if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
@@ -1835,23 +1839,6 @@ sigchld(int unused)
}
void
-sigdwmblocks(const Arg *arg)
-{
- union sigval sv;
- sv.sival_int = (dwmblockssig << 8) | arg->i;
- if (!dwmblockspid)
- if (getdwmblockspid() == -1)
- return;
-
- if (sigqueue(dwmblockspid, SIGUSR1, sv) == -1) {
- if (errno == ESRCH) {
- if (!getdwmblockspid())
- sigqueue(dwmblockspid, SIGUSR1, sv);
- }
- }
-}
-
-void
spawn(const Arg *arg)
{
if (arg->v == dmenucmd)
@@ -1956,6 +1943,32 @@ togglefullscr(const Arg *arg)
}
void
+togglescratch(const Arg *arg)
+{
+ Client *c;
+ unsigned int found = 0;
+ unsigned int scratchtag = SPTAG(arg->ui);
+ Arg sparg = {.v = scratchpads[arg->ui].cmd};
+
+ for (c = selmon->clients; c && !(found = c->tags & scratchtag); c = c->next);
+ if (found) {
+ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ scratchtag;
+ if (newtagset) {
+ selmon->tagset[selmon->seltags] = newtagset;
+ focus(NULL);
+ arrange(selmon);
+ }
+ if (ISVISIBLE(c)) {
+ focus(c);
+ restack(selmon);
+ }
+ } else {
+ selmon->tagset[selmon->seltags] |= scratchtag;
+ spawn(&sparg);
+ }
+}
+
+void
toggletag(const Arg *arg)
{
unsigned int newtags;
@@ -2235,10 +2248,8 @@ updatesizehints(Client *c)
void
updatestatus(void)
{
- if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext)))
+ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
- else
- copyvalidchars(stext, rawstext);
drawbar(selmon);
updatesystray();
}
@@ -2409,24 +2420,6 @@ view(const Arg *arg)
arrange(selmon);
}
-void
-scrollview(const Arg *arg)
-{
- int ui = 0;
- if (arg->i < 0)
- ui = selmon->tagset[selmon->seltags] >> 1;
- else if (arg->i > 0)
- ui = selmon->tagset[selmon->seltags] << 1;
-
- if ((ui & TAGMASK) == 0 || (ui & TAGMASK) == selmon->tagset[selmon->seltags])
- return;
- selmon->seltags ^= 1; /* toggle sel tagset */
- if (ui & TAGMASK)
- selmon->tagset[selmon->seltags] = ui;
- focus(NULL);
- arrange(selmon);
-}
-
Client *
wintoclient(Window w)
{