Compare commits

...

23 Commits
5.6.1 ... 5.7

Author SHA1 Message Date
91e902f7fe switching to release flags 2009-09-22 20:34:03 +01:00
30fed9a211 implemented nn < n case, k-zed please recheck 2009-09-22 20:33:42 +01:00
c45d46ad9a use buffer instead of pointer for mon->ltsymbol 2009-09-22 09:53:11 +01:00
6f55de8310 added missing scan 2009-09-22 09:16:48 +01:00
07ad298133 implemented different version of updategeom 2009-09-21 19:51:17 +01:00
f0a4845e7d added TODO to updategeom in order to implement a decent version of it soon 2009-09-19 11:52:16 +01:00
82ec7a7ed4 new experimental updategeom() additions that should avoid several problems with Xinerama, this is EXPERIMENTAL and might break something, the algorithms in use are quite complex and cumbersome, patches and comments welcome 2009-09-18 21:18:00 +01:00
e7300e0f6f implemented dynamic layout symbol stuff 2009-09-16 15:59:54 +01:00
c3feffa1e2 applied Tony Lainson's config.def.h patch 2009-09-15 13:50:41 +01:00
956a430054 update 2009-09-08 13:33:58 +01:00
01056b6636 hard-core destruction 2009-09-08 13:30:18 +01:00
eb260b1a41 renaming isdestroyed into destroyed 2009-09-08 13:18:05 +01:00
7fe81359d4 sync when a client is being killed 2009-09-08 13:16:54 +01:00
a3a859b4e9 added isdestroyed flag to unmanage 2009-09-08 13:13:03 +01:00
9c066c24b3 always updategeom when root is configured 2009-09-07 11:46:02 +02:00
0a668922a4 another small optimisation 2009-08-18 15:59:38 +01:00
5762964232 also update title if the client is on an unfocused monitor 2009-08-18 15:42:55 +01:00
cba6b211c2 applied nsz's dwm.1 patch, also added wmname 2009-08-16 21:39:24 +01:00
42750a621b applied Jukka's cosmetic patch 2009-08-16 08:18:54 +01:00
8ef465d592 applied Jukka's sigchld patch 2009-08-16 08:18:25 +01:00
33fe200b52 added merged patch of anydot and Neale 2009-08-13 10:45:59 +01:00
91fffb3f7d fixed nn declaration 2009-07-27 12:01:58 +01:00
1fa31efebf Added tag 5.6.1 for changeset e47a47bd3ed4 2009-07-26 14:02:28 +01:00
6 changed files with 202 additions and 147 deletions

View File

@ -62,3 +62,4 @@ e4bcaca8e6ef13d2c3b81f1218ad15e5da4d68bd 5.2
85a78d8afa0fe8b106a8223b5327e5bddb5dd5e3 5.4.1 85a78d8afa0fe8b106a8223b5327e5bddb5dd5e3 5.4.1
deaa276abac17ca08fbeb936916e4c8292d293a4 5.5 deaa276abac17ca08fbeb936916e4c8292d293a4 5.5
5550702215773aad462f22a774dced9b87437c51 5.6 5550702215773aad462f22a774dced9b87437c51 5.6
e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1

View File

@ -2,7 +2,7 @@ MIT/X Consortium License
© 2006-2009 Anselm R Garbe <garbeam at gmail dot com> © 2006-2009 Anselm R Garbe <garbeam at gmail dot com>
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com> © 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
© 2006-2007 Jukka Salmi <jukka at salmi dot ch> © 2006-2009 Jukka Salmi <jukka at salmi dot ch>
© 2007-2009 Premysl Hruby <dfenze at gmail dot com> © 2007-2009 Premysl Hruby <dfenze at gmail dot com>
© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com> © 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com>
© 2007-2009 Christof Musik <christof at sendfax dot de> © 2007-2009 Christof Musik <christof at sendfax dot de>

View File

@ -24,7 +24,7 @@ static const Rule rules[] = {
/* layout(s) */ /* layout(s) */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const Bool resizehints = True; /* False means respect size hints in tiled resizals */ static const Bool resizehints = True; /* True means respect size hints in tiled resizals */
static const Layout layouts[] = { static const Layout layouts[] = {
/* symbol arrange function */ /* symbol arrange function */
@ -84,8 +84,7 @@ static Key keys[] = {
}; };
/* button definitions */ /* button definitions */
/* click can be a tag number (starting at 0), /* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
* ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = { static Button buttons[] = {
/* click event mask button function argument */ /* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, setlayout, {0} }, { ClkLtSymbol, 0, Button1, setlayout, {0} },

View File

@ -1,5 +1,5 @@
# dwm version # dwm version
VERSION = 5.6.1 VERSION = 5.7
# Customize below to fit your system # Customize below to fit your system

31
dwm.1
View File

@ -20,14 +20,13 @@ Windows are grouped by tags. Each window can be tagged with one or multiple
tags. Selecting certain tags displays all windows with these tags. tags. Selecting certain tags displays all windows with these tags.
.P .P
Each screen contains a small status bar which displays all available tags, the Each screen contains a small status bar which displays all available tags, the
layout, the number of visible windows, the title of the focused window, and the layout, the title of the focused window, and the text read from the root window
text read from the root window name property, if the screen is focused. A name property, if the screen is focused. A floating window is indicated with an
floating window is indicated with an empty square and a maximised floating empty square and a maximised floating window is indicated with a filled square
window is indicated with a filled square before the windows title. The before the windows title. The selected tags are indicated with a different
selected tags are indicated with a different color. The tags of the focused color. The tags of the focused window are indicated with a filled square in the
window are indicated with a filled square in the top left corner. The tags top left corner. The tags which are applied to one or more windows are
which are applied to one or more windows are indicated with an empty square in indicated with an empty square in the top left corner.
the top left corner.
.P .P
dwm draws a small border around windows to indicate the focus state. dwm draws a small border around windows to indicate the focus state.
.SH OPTIONS .SH OPTIONS
@ -149,11 +148,17 @@ code. This keeps it fast, secure and simple.
.SH BUGS .SH BUGS
Java applications which use the XToolkit/XAWT backend may draw grey windows Java applications which use the XToolkit/XAWT backend may draw grey windows
only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early
JDK 1.6 versions, because it assumes a reparenting window manager. As a workaround JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds
you can use JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or you are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the
can set the following environment variable (to use the older Motif environment variable
backend instead): .BR AWT_TOOLKIT=MToolkit
.BR AWT_TOOLKIT=MToolkit . (to use the older Motif backend instead) or running
.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D
or
.B wmname LG3D
(to pretend that a non-reparenting window manager is running that the
XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable
.BR _JAVA_AWT_WM_NONREPARENTING=1 .
.P .P
GTK 2.10.9+ versions contain a broken GTK 2.10.9+ versions contain a broken
.BR Save\-As .BR Save\-As

308
dwm.c
View File

@ -121,6 +121,7 @@ typedef struct {
} Layout; } Layout;
struct Monitor { struct Monitor {
char ltsymbol[16];
float mfact; float mfact;
int num; int num;
int by; /* bar geometry */ int by; /* bar geometry */
@ -157,11 +158,12 @@ static void attachstack(Client *c);
static void buttonpress(XEvent *e); static void buttonpress(XEvent *e);
static void checkotherwm(void); static void checkotherwm(void);
static void cleanup(void); static void cleanup(void);
static void cleanupmons(void); static void cleanupmon(Monitor *mon);
static void clearurgent(Client *c); static void clearurgent(Client *c);
static void configure(Client *c); static void configure(Client *c);
static void configurenotify(XEvent *e); static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e); static void configurerequest(XEvent *e);
static Monitor *createmon(void);
static void destroynotify(XEvent *e); static void destroynotify(XEvent *e);
static void detach(Client *c); static void detach(Client *c);
static void detachstack(Client *c); static void detachstack(Client *c);
@ -207,7 +209,7 @@ static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg); static void setmfact(const Arg *arg);
static void setup(void); static void setup(void);
static void showhide(Client *c); static void showhide(Client *c);
static void sigchld(int signal); static void sigchld(int unused);
static void spawn(const Arg *arg); static void spawn(const Arg *arg);
static void tag(const Arg *arg); static void tag(const Arg *arg);
static void tagmon(const Arg *arg); static void tagmon(const Arg *arg);
@ -218,9 +220,9 @@ static void togglefloating(const Arg *arg);
static void toggletag(const Arg *arg); static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg); static void toggleview(const Arg *arg);
static void unfocus(Client *c); static void unfocus(Client *c);
static void unmanage(Client *c); static void unmanage(Client *c, Bool destroyed);
static void unmapnotify(XEvent *e); static void unmapnotify(XEvent *e);
static void updategeom(void); static Bool updategeom(void);
static void updatebarpos(Monitor *m); static void updatebarpos(Monitor *m);
static void updatebars(void); static void updatebars(void);
static void updatenumlockmask(void); static void updatenumlockmask(void);
@ -238,7 +240,7 @@ static void zoom(const Arg *arg);
/* variables */ /* variables */
static const char broken[] = "broken"; static const char broken[] = "broken";
static char stext[256], ntext[8]; static char stext[256];
static int screen; static int screen;
static int sw, sh; /* X display screen geometry width, height */ static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */ static int bh, blw = 0; /* bar geometry */
@ -384,6 +386,7 @@ arrange(void) {
showhide(m->stack); showhide(m->stack);
focus(NULL); focus(NULL);
for(m = mons; m; m = m->next) { for(m = mons; m; m = m->next) {
strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
if(m->lt[m->sellt]->arrange) if(m->lt[m->sellt]->arrange)
m->lt[m->sellt]->arrange(m); m->lt[m->sellt]->arrange(m);
restack(m); restack(m);
@ -466,7 +469,7 @@ cleanup(void) {
selmon->lt[selmon->sellt] = &foo; selmon->lt[selmon->sellt] = &foo;
for(m = mons; m; m = m->next) for(m = mons; m; m = m->next)
while(m->stack) while(m->stack)
unmanage(m->stack); unmanage(m->stack, False);
if(dc.font.set) if(dc.font.set)
XFreeFontSet(dpy, dc.font.set); XFreeFontSet(dpy, dc.font.set);
else else
@ -477,22 +480,25 @@ cleanup(void) {
XFreeCursor(dpy, cursor[CurNormal]); XFreeCursor(dpy, cursor[CurNormal]);
XFreeCursor(dpy, cursor[CurResize]); XFreeCursor(dpy, cursor[CurResize]);
XFreeCursor(dpy, cursor[CurMove]); XFreeCursor(dpy, cursor[CurMove]);
cleanupmons(); while(mons)
cleanupmon(mons);
XSync(dpy, False); XSync(dpy, False);
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
} }
void void
cleanupmons(void) { cleanupmon(Monitor *mon) {
Monitor *m; Monitor *m;
while(mons) { if(mon == mons)
m = mons->next; mons = mons->next;
XUnmapWindow(dpy, mons->barwin); else {
XDestroyWindow(dpy, mons->barwin); for(m = mons; m && m->next != mon; m = m->next);
free(mons); m->next = mon->next;
mons = m;
} }
XUnmapWindow(dpy, mon->barwin);
XDestroyWindow(dpy, mon->barwin);
free(mon);
} }
void void
@ -530,17 +536,18 @@ configurenotify(XEvent *e) {
Monitor *m; Monitor *m;
XConfigureEvent *ev = &e->xconfigure; XConfigureEvent *ev = &e->xconfigure;
if(ev->window == root && (ev->width != sw || ev->height != sh)) { if(ev->window == root) {
sw = ev->width; sw = ev->width;
sh = ev->height; sh = ev->height;
updategeom(); if(updategeom()) {
if(dc.drawable != 0) if(dc.drawable != 0)
XFreePixmap(dpy, dc.drawable); XFreePixmap(dpy, dc.drawable);
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
updatebars(); updatebars();
for(m = mons; m; m = m->next) for(m = mons; m; m = m->next)
XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
arrange(); arrange();
}
} }
} }
@ -564,9 +571,9 @@ configurerequest(XEvent *e) {
c->w = ev->width; c->w = ev->width;
if(ev->value_mask & CWHeight) if(ev->value_mask & CWHeight)
c->h = ev->height; c->h = ev->height;
if((c->x - m->mx + c->w) > m->mw && c->isfloating) if((c->x + c->w) > m->mx + m->mw && c->isfloating)
c->x = m->mx + (m->mw / 2 - c->w / 2); /* center in x direction */ c->x = m->mx + (m->mw / 2 - c->w / 2); /* center in x direction */
if((c->y - m->my + c->h) > m->mh && c->isfloating) if((c->y + c->h) > m->my + m->mh && c->isfloating)
c->y = m->my + (m->mh / 2 - c->h / 2); /* center in y direction */ c->y = m->my + (m->mh / 2 - c->h / 2); /* center in y direction */
if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
configure(c); configure(c);
@ -589,13 +596,29 @@ configurerequest(XEvent *e) {
XSync(dpy, False); XSync(dpy, False);
} }
Monitor *
createmon(void) {
Monitor *m;
if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
m->tagset[0] = m->tagset[1] = 1;
m->mfact = mfact;
m->showbar = showbar;
m->topbar = topbar;
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
return m;
}
void void
destroynotify(XEvent *e) { 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); unmanage(c, True);
} }
void void
@ -649,13 +672,11 @@ dirtomon(int dir) {
void void
drawbar(Monitor *m) { drawbar(Monitor *m) {
int x; int x;
unsigned int i, n = 0, occ = 0, urg = 0; unsigned int i, occ = 0, urg = 0;
unsigned long *col; unsigned long *col;
Client *c; Client *c;
for(c = m->clients; c; c = c->next) { for(c = m->clients; c; c = c->next) {
if(ISVISIBLE(c))
n++;
occ |= c->tags; occ |= c->tags;
if(c->isurgent) if(c->isurgent)
urg |= c->tags; urg |= c->tags;
@ -669,15 +690,10 @@ drawbar(Monitor *m) {
occ & 1 << i, urg & 1 << i, col); occ & 1 << i, urg & 1 << i, col);
dc.x += dc.w; dc.x += dc.w;
} }
if(blw > 0) { dc.w = blw = TEXTW(m->ltsymbol);
dc.w = blw; drawtext(m->ltsymbol, dc.norm, False);
drawtext(m->lt[m->sellt]->symbol, dc.norm, False); dc.x += dc.w;
dc.x += dc.w; x = dc.x;
}
snprintf(ntext, sizeof ntext, "%u", n);
dc.w = TEXTW(ntext);
drawtext(ntext, dc.norm, False);
x = (dc.x += dc.w);
if(m == selmon) { /* status is only drawn on selected monitor */ if(m == selmon) { /* status is only drawn on selected monitor */
dc.w = TEXTW(stext); dc.w = TEXTW(stext);
dc.x = m->ww - dc.w; dc.x = m->ww - dc.w;
@ -1009,6 +1025,19 @@ isprotodel(Client *c) {
return ret; return ret;
} }
#ifdef XINERAMA
static Bool
isuniquegeom(XineramaScreenInfo *unique, size_t len, XineramaScreenInfo *info) {
unsigned int i;
for(i = 0; i < len; i++)
if(unique[i].x_org == info->x_org && unique[i].y_org == info->y_org
&& unique[i].width == info->width && unique[i].height == info->height)
return False;
return True;
}
#endif /* XINERAMA */
void void
keypress(XEvent *e) { keypress(XEvent *e) {
unsigned int i; unsigned int i;
@ -1039,8 +1068,15 @@ killclient(const Arg *arg) {
ev.xclient.data.l[1] = CurrentTime; ev.xclient.data.l[1] = CurrentTime;
XSendEvent(dpy, selmon->sel->win, False, NoEventMask, &ev); XSendEvent(dpy, selmon->sel->win, False, NoEventMask, &ev);
} }
else else {
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XSetCloseDownMode(dpy, DestroyAll);
XKillClient(dpy, selmon->sel->win); XKillClient(dpy, selmon->sel->win);
XSync(dpy, False);
XSetErrorHandler(xerror);
XUngrabServer(dpy);
}
} }
void void
@ -1130,8 +1166,14 @@ maprequest(XEvent *e) {
void void
monocle(Monitor *m) { monocle(Monitor *m) {
unsigned int n = 0;
Client *c; Client *c;
for(c = m->clients; c; c = c->next)
if(ISVISIBLE(c))
n++;
if(n > 0) /* override layout symbol */
snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) for(c = nexttiled(m->clients); c; c = nexttiled(c->next))
resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False); resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False);
} }
@ -1235,8 +1277,8 @@ propertynotify(XEvent *e) {
} }
if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
updatetitle(c); updatetitle(c);
if(c == selmon->sel) if(c == c->mon->sel)
drawbars(); drawbar(c->mon);
} }
} }
} }
@ -1424,10 +1466,11 @@ setmfact(const Arg *arg) {
void void
setup(void) { setup(void) {
unsigned int i;
int w;
XSetWindowAttributes wa; XSetWindowAttributes wa;
/* clean up any zombies immediately */
sigchld(0);
/* init screen */ /* init screen */
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen); root = RootWindow(dpy, screen);
@ -1459,10 +1502,6 @@ setup(void) {
if(!dc.font.set) if(!dc.font.set)
XSetFont(dpy, dc.gc, dc.font.xfont->fid); XSetFont(dpy, dc.gc, dc.font.xfont->fid);
/* init bars */ /* init bars */
for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) {
w = TEXTW(layouts[i].symbol);
blw = MAX(blw, w);
}
updatebars(); updatebars();
updatestatus(); updatestatus();
/* EWMH support per view */ /* EWMH support per view */
@ -1496,13 +1535,14 @@ showhide(Client *c) {
void void
sigchld(int signal) { sigchld(int unused) {
if(signal(SIGCHLD, sigchld) == SIG_ERR)
die("Can't install SIGCHLD handler");
while(0 < waitpid(-1, NULL, WNOHANG)); while(0 < waitpid(-1, NULL, WNOHANG));
} }
void void
spawn(const Arg *arg) { spawn(const Arg *arg) {
signal(SIGCHLD, sigchld);
if(fork() == 0) { if(fork() == 0) {
if(dpy) if(dpy)
close(ConnectionNumber(dpy)); close(ConnectionNumber(dpy));
@ -1591,23 +1631,23 @@ togglefloating(const Arg *arg) {
void void
toggletag(const Arg *arg) { toggletag(const Arg *arg) {
unsigned int mask; unsigned int newtags;
if(!selmon->sel) if(!selmon->sel)
return; return;
mask = selmon->sel->tags ^ (arg->ui & TAGMASK); newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
if(mask) { if(newtags) {
selmon->sel->tags = mask; selmon->sel->tags = newtags;
arrange(); arrange();
} }
} }
void void
toggleview(const Arg *arg) { toggleview(const Arg *arg) {
unsigned int mask = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
if(mask) { if(newtagset) {
selmon->tagset[selmon->seltags] = mask; selmon->tagset[selmon->seltags] = newtagset;
arrange(); arrange();
} }
} }
@ -1622,22 +1662,24 @@ unfocus(Client *c) {
} }
void void
unmanage(Client *c) { unmanage(Client *c, Bool destroyed) {
XWindowChanges wc; XWindowChanges wc;
wc.border_width = c->oldbw;
/* The server grab construct avoids race conditions. */ /* The server grab construct avoids race conditions. */
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
detach(c); detach(c);
detachstack(c); detachstack(c);
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); if(!destroyed) {
setclientstate(c, WithdrawnState); wc.border_width = c->oldbw;
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
setclientstate(c, WithdrawnState);
XSync(dpy, False);
XSetErrorHandler(xerror);
XUngrabServer(dpy);
}
free(c); free(c);
XSync(dpy, False);
XSetErrorHandler(xerror);
XUngrabServer(dpy);
focus(NULL); focus(NULL);
arrange(); arrange();
} }
@ -1648,7 +1690,7 @@ unmapnotify(XEvent *e) {
XUnmapEvent *ev = &e->xunmap; XUnmapEvent *ev = &e->xunmap;
if((c = wintoclient(ev->window))) if((c = wintoclient(ev->window)))
unmanage(c); unmanage(c, False);
} }
void void
@ -1681,79 +1723,87 @@ updatebarpos(Monitor *m) {
m->by = -bh; m->by = -bh;
} }
void Bool
updategeom(void) { updategeom(void) {
int i, n = 1, nn; Bool dirty = False;
Client *c;
Monitor *newmons = NULL, *m = NULL, *tm;
#ifdef XINERAMA
XineramaScreenInfo *info = NULL;
if(XineramaIsActive(dpy))
info = XineramaQueryScreens(dpy, &n);
for(i = 1, nn = n; i < n; i++)
if(info[i - 1].x_org == info[i].x_org && info[i - 1].y_org == info[i].y_org
&& info[i - 1].width == info[i].width && info[i - 1].height == info[i].height)
--nn;
n = nn; /* we only consider unique geometries as separate screens */
#endif /* XINERAMA */
/* allocate monitor(s) for the new geometry setup */
for(i = 0; i < n; i++) {
if(!(m = (Monitor *)malloc(sizeof(Monitor))))
die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
m->next = newmons;
newmons = m;
}
/* initialise monitor(s) */
#ifdef XINERAMA #ifdef XINERAMA
if(XineramaIsActive(dpy)) { if(XineramaIsActive(dpy)) {
for(i = 0, m = newmons; m; m = m->next, i++) { int i, j, n, nn;
m->num = info[i].screen_number; Client *c;
m->mx = m->wx = info[i].x_org; Monitor *m;
m->my = m->wy = info[i].y_org; XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
m->mw = m->ww = info[i].width; XineramaScreenInfo *unique = NULL;
m->mh = m->wh = info[i].height;
} info = XineramaQueryScreens(dpy, &nn);
for(n = 0, m = mons; m; m = m->next, n++);
/* only consider unique geometries as separate screens */
if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn)))
die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn);
for(i = 0, j = 0; i < nn; i++)
if(isuniquegeom(unique, j, &info[i]))
memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
XFree(info); XFree(info);
nn = j;
if(n <= nn) {
for(i = 0; i < (nn - n); i++) { /* new monitors available */
for(m = mons; m && m->next; m = m->next);
if(m)
m->next = createmon();
else
mons = createmon();
}
for(i = 0, m = mons; i < nn && m; m = m->next, i++)
if(i >= n
|| (unique[i].x_org != m->mx || unique[i].y_org != m->my
|| unique[i].width != m->mw || unique[i].height != m->mh))
{
dirty = True;
m->num = i;
m->mx = m->wx = unique[i].x_org;
m->my = m->wy = unique[i].y_org;
m->mw = m->ww = unique[i].width;
m->mh = m->wh = unique[i].height;
updatebarpos(m);
}
}
else { /* less monitors available nn < n */
for(i = nn; i < n; i++) {
for(m = mons; m && m->next; m = m->next);
while(m->clients) {
dirty = True;
c = m->clients;
m->clients = c->next;
detachstack(c);
c->mon = mons;
attach(c);
attachstack(c);
}
if(m == selmon)
selmon = mons;
cleanupmon(m);
}
}
free(unique);
} }
else else
#endif /* XINERAMA */ #endif /* XINERAMA */
/* default monitor setup */ /* default monitor setup */
{ {
m->num = 0; if(!mons)
m->mx = m->wx = 0; mons = createmon();
m->my = m->wy = 0; if(mons->mw != sw || mons->mh != sh) {
m->mw = m->ww = sw; dirty = True;
m->mh = m->wh = sh; mons->mw = mons->ww = sw;
} mons->mh = mons->wh = sh;
/* bar geometry setup */ updatebarpos(mons);
for(m = newmons; m; m = m->next) {
m->sel = m->stack = m->clients = NULL;
m->seltags = 0;
m->sellt = 0;
m->tagset[0] = m->tagset[1] = 1;
m->mfact = mfact;
m->showbar = showbar;
m->topbar = topbar;
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
updatebarpos(m);
}
/* reassign left over clients of disappeared monitors */
for(tm = mons; tm; tm = tm->next)
while(tm->clients) {
c = tm->clients;
tm->clients = c->next;
detachstack(c);
c->mon = newmons;
attach(c);
attachstack(c);
} }
/* select focused monitor */ }
cleanupmons(); if(dirty) {
selmon = mons = newmons; selmon = mons;
selmon = wintomon(root); selmon = wintomon(root);
}
return dirty;
} }
void void