struct key {
unsigned int mod;
KeySym keysym;
- void (*func)(const union arg *);
+ void (*func)(const union arg*);
const union arg arg;
};
struct layout {
const char *symbol;
- void (*arrange)(struct monitor *);
+ void (*arrange)(struct monitor*);
};
struct monitor {
int monitor;
};
-struct systray {
- Window win;
- struct client *icons;
-};
-
/* function declarations */
static void applyrules(struct client *c);
static Bool applysizehints(struct client *c, int *x, int *y,
static void propertynotify(XEvent *e);
static void quit(const union arg *arg);
static struct monitor *recttomon(int x, int y, int w, int h);
-static void removesystrayicon(struct client *i);
static void resize(struct client *c, int x, int y, int w, int h, Bool interact);
static void resizebarwin(struct monitor *m);
static void resizeclient(struct client *c, int x, int y, int w, int h);
static void resizemouse(const union arg *arg);
-static void resizerequest(XEvent *e);
static void restack(struct monitor *m);
static void run(void);
static void scan(void);
static void tag(const union arg *arg);
static void tagmon(const union arg *arg);
static int textnw(const char *text, unsigned int len);
-#ifndef M10K
-static void togglebar(const union arg *arg);
-#endif /* ! M10K */
static void togglefloating(const union arg *arg);
static void toggletag(const union arg *arg);
static void toggleview(const union arg *arg);
static void updatenumlockmask(void);
static void updatesizehints(struct client *c);
static void updatestatus(void);
-static void updatesystray(void);
-static void updatesystrayicongeom(struct client *i, int w, int h);
-static void updatesystrayiconstate(struct client *i, XPropertyEvent *ev);
static void updatewindowtype(struct client *c);
static void updatetitle(struct client *c);
static void updatewmhints(struct client *c);
static void view(const union arg *arg);
static struct client *wintoclient(Window w);
static struct monitor *wintomon(Window w);
-static struct 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 union arg *arg);
static Atom getatomprop(struct client *c, Atom prop);
-static unsigned int getsystraywidth(void);
static void bookshelf(struct monitor *mon);
static void bookstack(struct monitor *mon);
-/* variables */
-static struct systray *systray = NULL;
-static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
static const char broken[] = "broken";
static char stext[512];
static int screen;
[MotionNotify] = NULL,
#endif /* ! M10K */
[PropertyNotify] = propertynotify,
- [ResizeRequest] = resizerequest,
[UnmapNotify] = unmapnotify
};
static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
cleanupmon(mons);
}
- XUnmapWindow(dpy, systray->win);
- XDestroyWindow(dpy, systray->win);
- free(systray);
-
XSync(dpy, False);
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
void clientmessage(XEvent *e)
{
- XWindowAttributes wa;
- XSetWindowAttributes swa;
- XClientMessageEvent *cme = &e->xclient;
- struct client *c = wintoclient(cme->window);
-
- if(cme->window == systray->win &&
- cme->message_type == netatom[NetSystemTrayOP]) {
- /* add systray icons */
- if(cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
- c = (struct client*)calloc(1, sizeof(*c));
-
- if(!c) {
- die("fatal: could not malloc() %u bytes\n", sizeof(*c));
- }
-
- c->win = cme->data.l[2];
- c->mon = selmon;
- c->next = systray->icons;
- systray->icons = c;
- XGetWindowAttributes(dpy, c->win, &wa);
-
- c->geom.x = 0;
- c->geom.y = 0;
- c->geom.w = wa.width;
- c->geom.h = wa.height;
- memcpy(&c->old_geom, &c->geom, sizeof(c->old_geom));
-
- c->border.oldw = wa.border_width;
- c->border.w = 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 pixmap */
- swa.background_pixmap = ParentRelative;
- swa.background_pixel = dc.norm[ColBG];
- XChangeWindowAttributes(dpy, c->win,
- CWBackPixmap | 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);
-
- resizebarwin(selmon);
- updatesystray();
- setclientstate(c, NormalState);
- }
+ XClientMessageEvent *cme;
+ struct client *c;
- return;
- }
+ cme = &e->xclient;
+ c = wintoclient(cme->window);
if(!c) {
return;
if((c = wintoclient(ev->window))) {
unmanage(c, True);
- } else if((c = wintosystrayicon(ev->window))) {
- removesystrayicon(c);
- resizebarwin(selmon);
- updatesystray();
}
return;
x = dc.geom.x;
dc.geom.w = TEXTW(stext);
- dc.geom.x = m->win_geom.w - dc.geom.w - getsystraywidth();
+ dc.geom.x = m->win_geom.w - dc.geom.w;
if(dc.geom.x < x) {
dc.geom.x = x;
drawbar(m);
}
- updatesystray();
-
return;
}
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;
return(result);
}
-unsigned int getsystraywidth(void)
-{
- struct client *client;
- unsigned int width;
-
- width = 0;
-
- for(client = systray->icons; client; client = client->next) {
- width += client->geom.w + systrayspacing;
- }
-
- return(width ? width + systrayspacing : 1);
-}
-
Bool gettextprop(Window w, Atom atom, char *text, unsigned int size)
{
XTextProperty name;
{
static XWindowAttributes wa;
XMapRequestEvent *ev;
- struct client *i;
ev = &e->xmaprequest;
- 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) && !wa.override_redirect) {
if(!wintoclient(ev->window)) {
manage(ev->window, &wa);
Window trans;
XPropertyEvent *ev = &e->xproperty;
- if((c = wintosystrayicon(ev->window))) {
- if(ev->atom == XA_WM_NORMAL_HINTS) {
- updatesizehints(c);
- updatesystrayicongeom(c, c->geom.w, c->geom.h);
- }
- else
- updatesystrayiconstate(c, ev);
- resizebarwin(selmon);
- updatesystray();
- }
if((ev->window == root) && (ev->atom == XA_WM_NAME))
updatestatus();
else if(ev->state == PropertyDelete)
return(r);
}
-void removesystrayicon(struct client *client)
-{
- struct client **cur;
-
- if(!client) {
- return;
- }
-
- for(cur = &systray->icons; *cur && *cur != client; cur = &(*cur)->next);
-
- *cur = client->next;
-
- free(client);
- return;
-}
-
-
void resize(struct client *c, int x, int y, int w, int h, Bool interact)
{
if(applysizehints(c, &x, &y, &w, &h, interact)) {
void resizebarwin(struct monitor *m)
{
- unsigned int w;
-
- w = m->win_geom.w - getsystraywidth();
-
- XMoveResizeWindow(dpy, m->barwin, m->win_geom.x, m->by, w, bar_height);
+ XMoveResizeWindow(dpy, m->barwin, m->win_geom.x, m->by, m->win_geom.w, bar_height);
return;
}
wc.height = h;
wc.border_width = c->border.w;
- XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
+ XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
configure(c);
XSync(dpy, False);
c->geom.h + c->border.w - 1);
do {
- XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
+ XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);
switch(ev.type) {
case ConfigureRequest:
return;
}
-void resizerequest(XEvent *e)
-{
- XResizeRequestEvent *ev;
- struct client *client;
-
- ev = &e->xresizerequest;
- client = wintosystrayicon(ev->window);
-
- if(client) {
- updatesystrayicongeom(client, ev->width, ev->height);
- resizebarwin(selmon);
- updatesystray();
- }
-
- return;
-}
-
void restack(struct monitor *m)
{
struct client *c;
XEvent ev;
XSync(dpy, False);
+
while(running && !XNextEvent(dpy, &ev)) {
if(handler[ev.type]) {
handler[ev.type](&ev);
long data[] = { state, None };
XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
- PropModeReplace, (unsigned char *)data, 2);
+ PropModeReplace, (unsigned char*)data, 2);
return;
}
c->mon->geom.w, c->mon->geom.h);
XRaiseWindow(dpy, c->win);
} else {
- XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
- PropModeReplace, (unsigned char*)0, 0);
+ XChangeProperty(dpy, c->win, netatom[NetWMState],
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char*)0, 0);
c->isfullscreen = False;
c->isfloating = c->oldstate;
c->border.w = c->border.oldw;
screen_height = DisplayHeight(dpy, screen);
bar_height = dc.geom.h = dc.font.height + 2;
updategeom();
+
/* init atoms */
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
+
/* init cursors */
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
+
/* init appearance */
dc.norm[ColBorder] = getcolor(normbordercolor, dc.xft.norm + ColBorder);
dc.norm[ColBG] = getcolor(normbgcolor, dc.xft.norm + ColBG);
DefaultColormap(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, NULL);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
- updatesystray();
+
/* init bars */
updatebars();
updatestatus();
wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | ButtonPressMask |
PointerMotionMask | EnterWindowMask | LeaveWindowMask | StructureNotifyMask |
PropertyChangeMask;
+
XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
XSelectInput(dpy, root, wa.event_mask);
grabkeys();
} else {
unmanage(c, False);
}
- } else if((c = wintosystrayicon(ev->window))) {
- removesystrayicon(c);
- resizebarwin(selmon);
- updatesystray();
}
return;
};
for(m = mons; m; m = m->next) {
- w = m->win_geom.w - getsystraywidth();
+ w = m->win_geom.w;
m->barwin = XCreateWindow(dpy, root, m->win_geom.x, m->by,
w, bar_height, 0, DefaultDepth(dpy, screen),
if(n <= nn) {
for(i = 0; i < (nn - n); i++) { /* new monitors available */
- for(m = mons; m && m->next; m = m->next);
+ struct monitor **ptr;
- if(m) {
- m->next = createmon();
- } else {
- mons = createmon();
- }
+ for(ptr = &mons; *ptr; ptr = &((*ptr)->next));
+ *ptr = createmon();
}
for(i = 0, m = mons; i < nn && m; m = m->next, i++) {
void updatestatus(void)
{
if(!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) {
- strcpy(stext, "dwm-"VERSION);
+ strcpy(stext, "d "VERSION);
}
drawbar(selmon);
return;
}
-void updatesystrayicongeom(struct client *i, int w, int h)
-{
- if(!i) {
- return;
- }
-
- i->geom.h = bar_height;
-
- if(w == h) {
- i->geom.w = bar_height;
- } else if(h == bar_height) {
- i->geom.w = w;
- } else {
- i->geom.w = (int) ((float)bar_height * ((float)w / (float)h));
- }
-
- applysizehints(i, &(i->geom.x), &(i->geom.y), &(i->geom.w), &(i->geom.h), False);
- /* force icons into the systray dimenons if they don't want to */
- if(i->geom.h > bar_height) {
- if(i->geom.w == i->geom.h) {
- i->geom.w = bar_height;
- } else {
- i->geom.w = (int) ((float)bar_height * ((float)i->geom.w /
- (float)i->geom.h));
- }
-
- i->geom.h = bar_height;
- }
-
- return;
-}
-
-void updatesystrayiconstate(struct client *i, XPropertyEvent *ev)
-{
- long flags;
- int code = 0;
-
- if(!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);
-
- return;
-}
-
-void updatesystray(void)
-{
- XSetWindowAttributes wa;
- struct client *i;
- unsigned int x;
- unsigned int w;
-
- x = selmon->geom.x + selmon->geom.w;
- w = 1;
-
- if(!systray) {
- /* init systray */
- if(!(systray = (struct systray*)calloc(1, sizeof(*systray)))) {
- die("fatal: could not malloc() %u bytes\n", sizeof(*systray));
- }
-
- systray->win = XCreateSimpleWindow(dpy, root, x, selmon->by,
- w, bar_height, 0, 0, dc.sel[ColBG]);
- wa.event_mask = ButtonPressMask | ExposureMask;
- wa.override_redirect = True;
- wa.background_pixmap = ParentRelative;
- wa.background_pixel = dc.norm[ColBG];
- 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 | CWBackPixmap, &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) {
- XMapRaised(dpy, i->win);
- w += systrayspacing;
- i->geom.x = w;
- XMoveResizeWindow(dpy, i->win, i->geom.x, 0,
- i->geom.w, i->geom.h);
- w += i->geom.w;
-
- if(i->mon != selmon) {
- i->mon = selmon;
- }
- }
-
- w = w ? w + systrayspacing : 1;
- x -= w;
- XMoveResizeWindow(dpy, systray->win, x, selmon->by, w, bar_height);
- /* redraw background */
- XSetForeground(dpy, dc.gc, dc.norm[ColBG]);
- XFillRectangle(dpy, systray->win, dc.gc, 0, 0, w, bar_height);
- XSync(dpy, False);
-
- return;
-}
-
void updatewindowtype(struct client *c)
{
Atom state = getatomprop(c, netatom[NetWMState]);
return(selmon);
}
-struct client *wintosystrayicon(Window w)
-{
- struct client *client;
+static int _can_ignore_error(XErrorEvent *ee)
+{
+ static struct {
+ unsigned char error_code;
+ unsigned char request_code;
+ } ignorable[] = {
+ { BadMatch, X_SetInputFocus },
+ { BadDrawable, X_PolyText8 },
+ { BadDrawable, X_PolyFillRectangle },
+ { BadDrawable, X_PolySegment },
+ { BadMatch, X_ConfigureWindow },
+ { BadAccess, X_GrabButton },
+ { BadAccess, X_GrabKey },
+ { BadDrawable, X_CopyArea }
+ };
+ int i;
- if(w) {
- for(client = systray->icons; client; client = client->next) {
- if(client->win == w) {
- return(client);
- }
+ for(i = 0; i < LENGTH(ignorable); i++) {
+ if(ee->request_code == ignorable[i].request_code &&
+ ee->error_code == ignorable[i].error_code) {
+ return(1);
}
}
- return(NULL);
+ return(0);
}
/* There's no way to check accesses to destroyed windows, thus those cases are
* 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)) {
+
+ if(ee->error_code == BadWindow || _can_ignore_error(ee)) {
return 0;
}
int main(int argc, char *argv[])
{
if(argc == 2 && !strcmp("-v", argv[1])) {
- die("dwm-"VERSION", © 2006-2011 dwm engineers, see LICENSE for details\n");
+ die("d "VERSION", © 2020-2021 Matthias Kruk, based on dwm-6.0\n");
} else if(argc != 1) {
die("usage: dwm [-v]\n");
}