swallow and some cleanup

This commit is contained in:
speedie 2023-07-04 18:50:24 +02:00
parent 7849a60e12
commit 740092e560
4 changed files with 362 additions and 27 deletions

View file

@ -3,6 +3,7 @@
/* appearance */ /* appearance */
static unsigned int borderpx = 1; /* border pixel of windows */ static unsigned int borderpx = 1; /* border pixel of windows */
static unsigned int snap = 32; /* snap pixel */ static unsigned int snap = 32; /* snap pixel */
static int swallowfloating = 0; /* 1 means swallow floating windows by default */
static unsigned int gappih = 20; /* horiz inner gap between windows */ static unsigned int gappih = 20; /* horiz inner gap between windows */
static unsigned int gappiv = 10; /* vert inner gap between windows */ static unsigned int gappiv = 10; /* vert inner gap between windows */
static unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ static unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */
@ -23,18 +24,25 @@ static char col_cyan[] = "#005577";
static int hidevacant = 1; static int hidevacant = 1;
static int monoclenogaps = 1; static int monoclenogaps = 1;
static const char *const autostart[] = {
"/bin/sh", "-c", "$HOME/.config/speedwm/autostart.sh", NULL,
NULL /* terminate */
};
/* tagging */ /* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const char *usedtags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static char *usedtags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const Rule rules[] = { static const Rule rules[] = {
/* xprop(1): /* xprop(1):
* WM_CLASS(STRING) = instance, class * WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title * WM_NAME(STRING) = title
*/ */
/* class instance title tags mask isfloating monitor */ /* class instance title tags mask isfloating isterminal noswallow monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 }, { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 },
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 }, { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 },
{ "St", NULL, NULL, 0, 0, 1, 0, -1 },
{ NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
}; };
/* Bar rules allow you to configure what is shown where on the bar, as well as /* Bar rules allow you to configure what is shown where on the bar, as well as
@ -61,12 +69,12 @@ static const BarRule barrules[] = {
}; };
/* layout(s) */ /* layout(s) */
static const float mfact = 0.50; /* factor of master area size [0.05..0.95] */ static float mfact = 0.50; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */ static int nmaster = 1; /* number of clients in master area */
static const int nstack = 0; /* number of clients in primary stack area */ static int nstack = 0; /* number of clients in primary stack area */
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ static int resizehints = 0; /* 1 means respect size hints in tiled resizals */
static const int attachdirection = 4; /* 0 default, 1 above, 2 aside, 3 below, 4 bottom, 5 top */ static int attachdirection = 4; /* 0 default, 1 above, 2 aside, 3 below, 4 bottom, 5 top */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ static int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
static const Layout layouts[] = { static const Layout layouts[] = {
/* symbol arrange function, { nmaster, nstack, layout, master axis, stack axis, secondary stack axis } */ /* symbol arrange function, { nmaster, nstack, layout, master axis, stack axis, secondary stack axis } */
@ -108,6 +116,8 @@ static const Key keys[] = {
{ MODKEY|ShiftMask, XK_semicolon, spawn, {.v = spmenucmd } }, { MODKEY|ShiftMask, XK_semicolon, spawn, {.v = spmenucmd } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
{ MODKEY|ShiftMask, XK_w, spawn, {.v = browser } }, { MODKEY|ShiftMask, XK_w, spawn, {.v = browser } },
{ MODKEY|ShiftMask, XK_s, spawn, SHCMD("screenshot-spmenu -s") },
{ MODKEY|ControlMask, XK_s, spawn, SHCMD("screenshot-spmenu -f") },
{ MODKEY, XK_b, togglebar, {0} }, { MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_k, focusstack, {.i = -1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } },
@ -115,8 +125,8 @@ static const Key keys[] = {
{ MODKEY, XK_n, incnmaster, {.i = -1 } }, { MODKEY, XK_n, incnmaster, {.i = -1 } },
{ MODKEY|ControlMask, XK_i, incnstack, {.i = +1 } }, { MODKEY|ControlMask, XK_i, incnstack, {.i = +1 } },
{ MODKEY|ControlMask, XK_u, incnstack, {.i = -1 } }, { MODKEY|ControlMask, XK_u, incnstack, {.i = -1 } },
{ MODKEY, XK_a, setmfact, {.f = -0.05} }, { MODKEY|ShiftMask, XK_a, setmfact, {.f = -0.05} },
{ MODKEY, XK_d, setmfact, {.f = +0.05} }, { MODKEY|ShiftMask, XK_d, setmfact, {.f = +0.05} },
{ MODKEY|ShiftMask, XK_k, setcfact, {.f = +0.25} }, { MODKEY|ShiftMask, XK_k, setcfact, {.f = +0.25} },
{ MODKEY|ShiftMask, XK_j, setcfact, {.f = -0.25} }, { MODKEY|ShiftMask, XK_j, setcfact, {.f = -0.25} },
{ MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} }, { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} },

View file

@ -14,12 +14,14 @@ X11LIB = /usr/X11R6/lib
XINERAMALIBS = -lXinerama XINERAMALIBS = -lXinerama
XINERAMAFLAGS = -DXINERAMA XINERAMAFLAGS = -DXINERAMA
# OpenBSD (uncomment) # OpenBSD (uncomment)
#MANPREFIX = ${PREFIX}/man #MANPREFIX = ${PREFIX}/man
#KVMLIB = -lkvm
# includes and libs # includes and libs
INCS = -I${X11INC} `pkg-config --cflags cairo pango pangocairo` INCS = -I${X11INC} `pkg-config --cflags cairo pango pangocairo`
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} `pkg-config --libs cairo pango pangocairo` -lXrender LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} `pkg-config --libs cairo pango pangocairo` -lXrender -lX11-xcb -lxcb -lxcb-res ${KVMLIB}
# flags # flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}

347
dwm.c
View file

@ -40,6 +40,12 @@
#ifdef XINERAMA #ifdef XINERAMA
#include <X11/extensions/Xinerama.h> #include <X11/extensions/Xinerama.h>
#endif /* XINERAMA */ #endif /* XINERAMA */
#include <X11/Xlib-xcb.h>
#include <xcb/res.h>
#ifdef __OpenBSD__
#include <sys/sysctl.h>
#include <kvm.h>
#endif /* __OpenBSD */
#include <X11/Xresource.h> #include <X11/Xresource.h>
#include "drw.h" #include "drw.h"
@ -67,7 +73,8 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
NetWMFullscreen, NetActiveWindow, NetWMWindowType, NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation,
NetSystemTrayVisual, NetWMWindowTypeDock, NetSystemTrayOrientationHorz, NetSystemTrayVisual, NetWMWindowTypeDock, NetSystemTrayOrientationHorz,
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ NetWMWindowTypeDialog, NetClientList, NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop,
NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
@ -150,9 +157,11 @@ struct Client {
int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
int bw, oldbw; int bw, oldbw;
unsigned int tags; unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow;
pid_t pid;
Client *next; Client *next;
Client *snext; Client *snext;
Client *swallowing;
Monitor *mon; Monitor *mon;
Window win; Window win;
}; };
@ -213,6 +222,8 @@ typedef struct {
const char *title; const char *title;
unsigned int tags; unsigned int tags;
int isfloating; int isfloating;
int isterminal;
int noswallow;
int monitor; int monitor;
} Rule; } Rule;
@ -293,11 +304,15 @@ static void scan(void);
static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); 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 sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state); static void setclientstate(Client *c, long state);
static void setcurrentdesktop(void);
static void setdesktopnames(void);
static void setfocus(Client *c); static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen); static void setfullscreen(Client *c, int fullscreen);
static void setlayout(const Arg *arg); static void setlayout(const Arg *arg);
static void setcfact(const Arg *arg); static void setcfact(const Arg *arg);
static void setmfact(const Arg *arg); static void setmfact(const Arg *arg);
static void setnumdesktops(void);
static void setviewport(void);
static void setup(void); static void setup(void);
static void seturgent(Client *c, int urg); static void seturgent(Client *c, int urg);
static void showhide(Client *c); static void showhide(Client *c);
@ -311,6 +326,7 @@ static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus); static void unfocus(Client *c, int setfocus);
static void unmanage(Client *c, int destroyed); static void unmanage(Client *c, int destroyed);
static void unmapnotify(XEvent *e); static void unmapnotify(XEvent *e);
static void updatecurrentdesktop(void);
static void updatebarpos(Monitor *m); static void updatebarpos(Monitor *m);
static void updatebars(void); static void updatebars(void);
static void xinitvisual(void); static void xinitvisual(void);
@ -329,6 +345,7 @@ static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg); static void zoom(const Arg *arg);
static void autostart_exec(void);
static void load_xresources(void); static void load_xresources(void);
static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst); static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
static void xrdb(void); static void xrdb(void);
@ -337,6 +354,12 @@ static void xrdb(void);
#include "libs/lt/tile.h" #include "libs/lt/tile.h"
#include "libs/gaps.h" #include "libs/gaps.h"
static pid_t getparentprocess(pid_t p);
static int isdescprocess(pid_t p, pid_t c);
static Client *swallowingclient(Window w);
static Client *termforwin(const Client *c);
static pid_t winpid(Window w);
/* variables */ /* variables */
static const char broken[] = "broken"; static const char broken[] = "broken";
static char stext[1024]; static char stext[1024];
@ -378,6 +401,8 @@ static Visual *visual;
static int depth; static int depth;
static Colormap cmap; static Colormap cmap;
static xcb_connection_t *xcon;
/* configuration, allows nested code to access above variables */ /* configuration, allows nested code to access above variables */
#include "config.h" #include "config.h"
@ -403,6 +428,34 @@ struct Pertag {
/* compile-time check if all tags fit into an unsigned int bit array. */ /* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
/* dwm will keep pid's of processes from autostart array and kill them at quit */
static pid_t *autostart_pids;
static size_t autostart_len;
/* execute command from autostart array */
static void
autostart_exec() {
const char *const *p;
size_t i = 0;
/* count entries */
for (p = autostart; *p; autostart_len++, p++)
while (*++p);
autostart_pids = malloc(autostart_len * sizeof(pid_t));
for (p = autostart; *p; i++, p++) {
if ((autostart_pids[i] = fork()) == 0) {
setsid();
execvp(*p, (char *const *)p);
fprintf(stderr, "dwm: execvp %s\n", *p);
perror(" failed");
_exit(EXIT_FAILURE);
}
/* skip arguments */
while (*++p);
}
}
/* function implementations */ /* function implementations */
void void
applyrules(Client *c) applyrules(Client *c)
@ -426,6 +479,8 @@ applyrules(Client *c)
&& (!r->class || strstr(class, r->class)) && (!r->class || strstr(class, r->class))
&& (!r->instance || strstr(instance, r->instance))) && (!r->instance || strstr(instance, r->instance)))
{ {
c->isterminal = r->isterminal;
c->noswallow = r->noswallow;
c->isfloating = r->isfloating; c->isfloating = r->isfloating;
c->tags |= r->tags; c->tags |= r->tags;
for (m = mons; m && m->num != r->monitor; m = m->next); for (m = mons; m && m->num != r->monitor; m = m->next);
@ -613,6 +668,53 @@ attachstack(Client *c)
c->mon->stack = c; c->mon->stack = c;
} }
void
swallow(Client *p, Client *c)
{
if (c->noswallow || c->isterminal)
return;
if (c->noswallow && !swallowfloating && c->isfloating)
return;
detach(c);
detachstack(c);
setclientstate(c, WithdrawnState);
XUnmapWindow(dpy, p->win);
p->swallowing = c;
c->mon = p->mon;
Window w = p->win;
p->win = c->win;
c->win = w;
updatetitle(p);
XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
arrange(p->mon);
configure(p);
updateclientlist();
}
void
unswallow(Client *c)
{
c->win = c->swallowing->win;
free(c->swallowing);
c->swallowing = NULL;
/* unfullscreen the client */
setfullscreen(c, 0);
updatetitle(c);
arrange(c->mon);
XMapWindow(dpy, c->win);
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
setclientstate(c, NormalState);
focus(NULL);
arrange(c->mon);
}
void void
buttonpress(XEvent *e) buttonpress(XEvent *e)
{ {
@ -998,12 +1100,14 @@ destroynotify(XEvent *e)
Client *c; Client *c;
XDestroyWindowEvent *ev = &e->xdestroywindow; XDestroyWindowEvent *ev = &e->xdestroywindow;
if ((c = wintoclient(ev->window))) if ((c = wintoclient(ev->window))) {
unmanage(c, 1); unmanage(c, 1);
else if (showsystray && (c = wintosystrayicon(ev->window))) { } else if (showsystray && (c = wintosystrayicon(ev->window))) {
removesystrayicon(c); removesystrayicon(c);
drawbarwin(systray->bar); drawbarwin(systray->bar);
} } else if ((c = swallowingclient(ev->window))) {
unmanage(c->swallowing, 1);
}
} }
void void
@ -1056,7 +1160,6 @@ void
drawbars(void) drawbars(void)
{ {
Monitor *m; Monitor *m;
int i;
for (m = mons; m; m = m->next) for (m = mons; m; m = m->next)
drawbar(m); drawbar(m);
@ -1468,12 +1571,13 @@ killclient(const Arg *arg)
void void
manage(Window w, XWindowAttributes *wa) manage(Window w, XWindowAttributes *wa)
{ {
Client *c, *t = NULL; Client *c, *t = NULL, *term = NULL;
Window trans = None; Window trans = None;
XWindowChanges wc; XWindowChanges wc;
c = ecalloc(1, sizeof(Client)); c = ecalloc(1, sizeof(Client));
c->win = w; c->win = w;
c->pid = winpid(w);
/* geometry */ /* geometry */
c->x = c->oldx = wa->x; c->x = c->oldx = wa->x;
c->y = c->oldy = wa->y; c->y = c->oldy = wa->y;
@ -1489,6 +1593,7 @@ manage(Window w, XWindowAttributes *wa)
} else { } else {
c->mon = selmon; c->mon = selmon;
applyrules(c); applyrules(c);
term = termforwin(c);
} }
if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww)
@ -1561,6 +1666,8 @@ manage(Window w, XWindowAttributes *wa)
arrange(c->mon); arrange(c->mon);
if (!HIDDEN(c)) if (!HIDDEN(c))
XMapWindow(dpy, c->win); XMapWindow(dpy, c->win);
if (term)
swallow(term, c);
focus(NULL); focus(NULL);
} }
@ -1746,6 +1853,16 @@ propertynotify(XEvent *e)
void void
quit(const Arg *arg) quit(const Arg *arg)
{ {
size_t i;
/* kill child processes */
for (i = 0; i < autostart_len; i++) {
if (0 < autostart_pids[i]) {
kill(autostart_pids[i], SIGTERM);
waitpid(autostart_pids[i], NULL, 0);
}
}
running = 0; running = 0;
} }
@ -1947,6 +2064,16 @@ setclientstate(Client *c, long state)
XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
PropModeReplace, (unsigned char *)data, 2); PropModeReplace, (unsigned char *)data, 2);
} }
void
setcurrentdesktop(void){
long data[] = { 0 };
XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
}
void setdesktopnames(void){
XTextProperty text;
Xutf8TextListToTextProperty(dpy, tags, LENGTH(tags), XUTF8StringStyle, &text);
XSetTextProperty(dpy, root, &text, netatom[NetDesktopNames]);
}
int int
sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
@ -1983,6 +2110,12 @@ sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, lo
return exists; return exists;
} }
void
setnumdesktops(void){
long data[] = { LENGTH(tags) };
XChangeProperty(dpy, root, netatom[NetNumberOfDesktops], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
}
void void
setfocus(Client *c) setfocus(Client *c)
{ {
@ -2095,6 +2228,7 @@ setup(void)
XSetWindowAttributes wa; XSetWindowAttributes wa;
Atom utf8string; Atom utf8string;
struct sigaction sa; struct sigaction sa;
pid_t pid;
/* do not transform children into zombies when they terminate */ /* do not transform children into zombies when they terminate */
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
@ -2103,7 +2237,21 @@ setup(void)
sigaction(SIGCHLD, &sa, NULL); sigaction(SIGCHLD, &sa, NULL);
/* clean up any zombies (inherited from .xinitrc etc) immediately */ /* clean up any zombies (inherited from .xinitrc etc) immediately */
while (waitpid(-1, NULL, WNOHANG) > 0); while (0 < (pid = waitpid(-1, NULL, WNOHANG))) {
pid_t *p, *lim;
if (!(p = autostart_pids))
continue;
lim = &p[autostart_len];
for (; p < lim; p++) {
if (*p == pid) {
*p = -1;
break;
}
}
}
/* init screen */ /* init screen */
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
@ -2141,6 +2289,10 @@ setup(void)
netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
netatom[NetDesktopViewport] = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False);
netatom[NetNumberOfDesktops] = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
netatom[NetCurrentDesktop] = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
netatom[NetDesktopNames] = XInternAtom(dpy, "_NET_DESKTOP_NAMES", False);
/* init cursors */ /* init cursors */
cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
cursor[CurResize] = drw_cur_create(drw, XC_sizing); cursor[CurResize] = drw_cur_create(drw, XC_sizing);
@ -2159,6 +2311,10 @@ setup(void)
/* EWMH support per view */ /* EWMH support per view */
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
PropModeReplace, (unsigned char *) netatom, NetLast); PropModeReplace, (unsigned char *) netatom, NetLast);
setnumdesktops();
setcurrentdesktop();
setdesktopnames();
setviewport();
XDeleteProperty(dpy, root, netatom[NetClientList]); XDeleteProperty(dpy, root, netatom[NetClientList]);
/* select events */ /* select events */
wa.cursor = cursor[CurNormal]->cursor; wa.cursor = cursor[CurNormal]->cursor;
@ -2170,6 +2326,11 @@ setup(void)
grabkeys(); grabkeys();
focus(NULL); focus(NULL);
} }
void
setviewport(void){
long data[] = { 0, 0 };
XChangeProperty(dpy, root, netatom[NetDesktopViewport], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 2);
}
void void
seturgent(Client *c, int urg) seturgent(Client *c, int urg)
@ -2310,6 +2471,7 @@ toggleview(const Arg *arg)
focus(NULL); focus(NULL);
arrange(selmon); arrange(selmon);
} }
updatecurrentdesktop();
} }
void void
@ -2341,6 +2503,7 @@ unfocus(Client *c, int setfocus)
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
XDeleteProperty(dpy, root, netatom[NetActiveWindow]); XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
} }
updatecurrentdesktop();
} }
void void
@ -2349,6 +2512,20 @@ unmanage(Client *c, int destroyed)
Monitor *m = c->mon; Monitor *m = c->mon;
XWindowChanges wc; XWindowChanges wc;
if (c->swallowing) {
unswallow(c);
return;
}
Client *s = swallowingclient(c->win);
if (s) {
free(s->swallowing);
s->swallowing = NULL;
arrange(m);
focus(NULL);
return;
}
detach(c); detach(c);
detachstack(c); detachstack(c);
if (!destroyed) { if (!destroyed) {
@ -2364,9 +2541,12 @@ unmanage(Client *c, int destroyed)
XUngrabServer(dpy); XUngrabServer(dpy);
} }
free(c); free(c);
focus(NULL);
updateclientlist(); if (!s) {
arrange(m); arrange(m);
focus(NULL);
updateclientlist();
}
} }
void void
@ -2501,6 +2681,15 @@ updateclientlist()
XA_WINDOW, 32, PropModeAppend, XA_WINDOW, 32, PropModeAppend,
(unsigned char *) &(c->win), 1); (unsigned char *) &(c->win), 1);
} }
void updatecurrentdesktop(void){
long rawdata[] = { selmon->tagset[selmon->seltags] };
int i=0;
while(*rawdata >> (i + 1)){
i++;
}
long data[] = { i };
XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
}
int int
updategeom(void) updategeom(void)
@ -2756,6 +2945,137 @@ view(const Arg *arg)
togglebar(NULL); togglebar(NULL);
focus(NULL); focus(NULL);
arrange(selmon); arrange(selmon);
updatecurrentdesktop();
}
pid_t
winpid(Window w)
{
pid_t result = 0;
#ifdef __linux__
xcb_res_client_id_spec_t spec = {0};
spec.client = w;
spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
xcb_generic_error_t *e = NULL;
xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
if (!r)
return (pid_t)0;
xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
for (; i.rem; xcb_res_client_id_value_next(&i)) {
spec = i.data->spec;
if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
uint32_t *t = xcb_res_client_id_value_value(i.data);
result = *t;
break;
}
}
free(r);
if (result == (pid_t)-1)
result = 0;
#endif /* __linux__ */
#ifdef __OpenBSD__
Atom type;
int format;
unsigned long len, bytes;
unsigned char *prop;
pid_t ret;
if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop)
return 0;
ret = *(pid_t*)prop;
XFree(prop);
result = ret;
#endif /* __OpenBSD__ */
return result;
}
pid_t
getparentprocess(pid_t p)
{
unsigned int v = 0;
#ifdef __linux__
FILE *f;
char buf[256];
snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
if (!(f = fopen(buf, "r")))
return 0;
fscanf(f, "%*u %*s %*c %u", &v);
fclose(f);
#endif /* __linux__*/
#ifdef __OpenBSD__
int n;
kvm_t *kd;
struct kinfo_proc *kp;
kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL);
if (!kd)
return 0;
kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n);
v = kp->p_ppid;
#endif /* __OpenBSD__ */
return (pid_t)v;
}
int
isdescprocess(pid_t p, pid_t c)
{
while (p != c && c != 0)
c = getparentprocess(c);
return (int)c;
}
Client *
termforwin(const Client *w)
{
Client *c;
Monitor *m;
if (!w->pid || w->isterminal)
return NULL;
for (m = mons; m; m = m->next) {
for (c = m->clients; c; c = c->next) {
if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
return c;
}
}
return NULL;
}
Client *
swallowingclient(Window w)
{
Client *c;
Monitor *m;
for (m = mons; m; m = m->next) {
for (c = m->clients; c; c = c->next) {
if (c->swallowing && c->swallowing->win == w)
return c;
}
}
return NULL;
} }
Client * Client *
@ -2913,12 +3233,15 @@ main(int argc, char *argv[])
fputs("warning: no locale support\n", stderr); fputs("warning: no locale support\n", stderr);
if (!(dpy = XOpenDisplay(NULL))) if (!(dpy = XOpenDisplay(NULL)))
die("dwm: cannot open display"); die("dwm: cannot open display");
if (!(xcon = XGetXCBConnection(dpy)))
die("dwm: cannot get xcb connection\n");
checkotherwm(); checkotherwm();
autostart_exec();
XrmInitialize(); XrmInitialize();
load_xresources(); load_xresources();
setup(); setup();
#ifdef __OpenBSD__ #ifdef __OpenBSD__
if (pledge("stdio rpath proc exec", NULL) == -1) if (pledge("stdio rpath proc exec ps", NULL) == -1)
die("pledge"); die("pledge");
#endif /* __OpenBSD__ */ #endif /* __OpenBSD__ */
scan(); scan();

View file

@ -7,7 +7,7 @@ width_awesomebar(Bar *bar, BarWidthArg *a)
int int
draw_awesomebar(Bar *bar, BarDrawArg *a) draw_awesomebar(Bar *bar, BarDrawArg *a)
{ {
int n = 0, scm, remainder = 0, tabw, pad; int n = 0, remainder = 0, tabw, pad;
unsigned int i; unsigned int i;
int x = a->x + lrpad / 2, w = a->w - lrpad; int x = a->x + lrpad / 2, w = a->w - lrpad;