For what it's worth, the attached diff is what I just ported to 4.7 over
the weekend from what I concocted for 4.4.1 (which I had been using till
yesterday).
It's really just a layout hack than xinerama support, but all I was
after was splitting the real estate into left and right sides and make
the right side a mirror the of the tile layout. Something like this:
+----+--+--+----+
| | | | |
| +--+--+ |
| | | | |
+----+--+--+----+
The limitation is that any client may be tied to only one screen (side)
at a time - but this suits me because I leave mail and IM on one side
and apply them to all tags (I need to keep *very* on top of those two
services).
The togglescreen() function cycles through screens (duh =P).
The other thing mixed in here is a version of view() called
viewselmain() which always sets the focus to main window when changing
tags (something more intuitive to me).
Warning: I'm a perl/bourne scripter - C is not my forte.
-Ducky
Anselm R. Garbe wrote:
Hi there again,
well I cleaned up Christof's initial multihead implementation a
lot, and I played around with experimental tag sharing between
different views (I decided to call a Xinerama screen view, which
allows aiming Xinerama on a single head as well and which is
more precise in the dwm terminology, so far we only had 1
view, with each Xinerama screen we get an additional view).
But unfortunately I more and more come to the conclusion that
allowing to assign a certain tag to a specific view at runtime
sucks. It is not very predictable at all when tags are dropped
in clients and how (the heuristic I told about the last time
does not really work well -- and this heuristic even has to be
used after the rules are applied, because there might be some
rule which assigns tags used by different views).
I can imagine that this concept works quite well in xmonad,
because there the limitation of selecting one tag/workspace per
view (screen) seems to be design decision. Also what I dislike
about the mutex tag sharing is, that we still need additional
functions to select a certain screen (besides the fact, that all
those quirks necessary to resolve tag selection conflicts
clutter the code a lot). But I don't want to follow the
workspace paradigm, because I think the way dwm treats multiple
tags being viewed is really a nice feature and makes it unique
to all other clones and related projects.
So I'm back at the point I was already last week (but with a
much cleaner codebase now). I propose again to go the way
with partitioned tag sets, which allows to get rid of explicit
screen selection functions and which avoids the tag selection
joins between partitions - the tag partition setup will be done
in config.h.
So, tag() can move a client to a different screen (if the chosen
tag is in a different partition), view() can focus a different
screen (if the related tag is in a different partition).
toggletag() and toggleview() only work in the currently valid
partition (related on the focused client resp. view) and will
not allow any conflicts. applyrules() needs special treatment as
well.
But it's all a question of the right data structure. I will
decide tonight/tomorrow which data structures fit best this
idea.
Kind regards,
diff -wc dwm-4.7-orig/config.def.h dwm-4.7/config.def.h
*** dwm-4.7-orig/config.def.h 2007-11-21 12:18:41.000000000 -0800
--- dwm-4.7/config.def.h 2008-02-25 11:20:33.000000000 -0800
***************
*** 10,15 ****
--- 10,16 ----
#define SELBORDERCOLOR "#0066ff"
#define SELBGCOLOR "#0066ff"
#define SELFGCOLOR "#ffffff"
+ #define NUMSCREENS 2
/* tagging */
const char tags[][MAXTAGLEN] = { "1", "2", "3", "4", "5", "6", "7", "8",
"www" };
***************
*** 28,34 ****
#define SNAP 32 /* snap pixel */
Layout layouts[] = {
/* symbol function */
! { "[]=", tile }, /* first entry is default */
{ "><>", floating },
};
--- 29,35 ----
#define SNAP 32 /* snap pixel */
Layout layouts[] = {
/* symbol function */
! { "[]==[]", tile }, /* first entry is default */
{ "><>", floating },
};
diff -wc dwm-4.7-orig/dwm.c dwm-4.7/dwm.c
*** dwm-4.7-orig/dwm.c 2007-11-21 12:18:41.000000000 -0800
--- dwm-4.7/dwm.c 2008-02-25 10:24:31.000000000 -0800
***************
*** 64,69 ****
--- 64,70 ----
int rx, ry, rw, rh; /* revert geometry */
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int minax, maxax, minay, maxay;
+ int screen;
long flags;
unsigned int border, oldborder;
Bool isbanned, isfixed, ismax, isfloating, wasfloating;
***************
*** 177,182 ****
--- 178,184 ----
void tile(void);
void togglebar(const char *arg);
void togglefloating(const char *arg);
+ void togglescreen(const char *arg);
void togglemax(const char *arg);
void toggletag(const char *arg);
void toggleview(const char *arg);
***************
*** 187,192 ****
--- 189,195 ----
void updatesizehints(Client *c);
void updatetitle(Client *c);
void view(const char *arg);
+ void viewselmain(const char *arg);
void viewprevtag(const char *arg); /* views previous selected tags */
int xerror(Display *dpy, XErrorEvent *ee);
int xerrordummy(Display *dsply, XErrorEvent *ee);
***************
*** 1044,1049 ****
--- 1047,1053 ----
if(t)
memcpy(c->tags, t->tags, sizeof seltags);
applyrules(c);
+ c->screen = 0;
if(!c->isfloating)
c->isfloating = (rettrans == Success) || c->isfixed;
attach(c);
***************
*** 1580,1624 ****
void
tile(void) {
! unsigned int i, n, nx, ny, nw, nh, mw, th;
! Client *c, *mc;
domwfact = dozoom = True;
! for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
! n++;
/* window geoms */
! mw = (n == 1) ? waw : mwfact * waw;
! th = (n > 1) ? wah / (n - 1) : 0;
! if(n > 1 && th < bh)
! th = wah;
- nx = wax;
- ny = way;
nw = 0; /* gcc stupidity requires this */
! for(i = 0, c = mc = nexttiled(clients); c; c = nexttiled(c->next), i++)
{
! c->ismax = False;
! if(i == 0) { /* master */
! nw = mw - 2 * c->border;
nh = wah - 2 * c->border;
}
else { /* tile window */
! if(i == 1) {
! ny = way;
! nx += mc->w + 2 * mc->border;
! nw = waw - nx - 2 * c->border;
}
! if(i + 1 == n) /* remainder */
! nh = (way + wah) - ny - 2 * c->border;
else
! nh = th - 2 * c->border;
}
! resize(c, nx, ny, nw, nh, RESIZEHINTS);
if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh)
|| (c->w > nw)))
/* client doesn't accept size constraints */
! resize(c, nx, ny, nw, nh, False);
! if(n > 1 && th != wah)
! ny = c->y + c->h + 2 * c->border;
}
}
--- 1584,1636 ----
void
tile(void) {
! unsigned int i, n[NUMSCREENS], nx, ny[NUMSCREENS], nw, nh,
mw[NUMSCREENS], th[NUMSCREENS];
! Client *c, *mc[NUMSCREENS];
domwfact = dozoom = True;
! for(i = 0; i < NUMSCREENS ; i++) n[i] = 0 ;
! for(c = nexttiled(clients); c; c = nexttiled(c->next)) n[c->screen]++;
! for(i = 0; i < NUMSCREENS ; i++) {
! mc[i] = NULL;
/* window geoms */
! mw[i] = (n[i] == 1) ? waw / NUMSCREENS : mwfact * waw /
NUMSCREENS;
! th[i] = (n[i] > 1) ? wah / (n[i] - 1) : 0;
! if(n[i] > 1 && th[i] < bh)
! th[i] = wah;
! ny[i] = way;
! }
nw = 0; /* gcc stupidity requires this */
! for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next), i++) {
! nx = wax + waw / NUMSCREENS * c->screen;
nh = wah - 2 * c->border;
+ c->ismax = False;
+ if(!mc[c->screen]) { /* master */
+ mc[c->screen] = c;
+ nw = mw[c->screen] - 2 * c->border;
+ if(c->screen % 2)
+ nx += waw / NUMSCREENS - mw[c->screen];
}
else { /* tile window */
! if(c->screen % 2) {
! nw = waw / NUMSCREENS - mc[c->screen]->w - 2 *
mc[c->screen]->border - 2 * c->border;
! }
! else {
! nx += mc[c->screen]->w + 2 *
mc[c->screen]->border;
! nw = waw / NUMSCREENS * (c->screen + 1) - nx -
2 * c->border;
}
! if(--n[c->screen] == 1) /* remainder */
! nh = (way + wah) - ny[c->screen] - 2 *
c->border;
else
! nh = th[c->screen] - 2 * c->border;
}
! resize(c, nx, ny[c->screen], nw, nh, RESIZEHINTS);
if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh)
|| (c->w > nw)))
/* client doesn't accept size constraints */
! resize(c, nx, ny[c->screen], nw, nh, False);
! if(n[c->screen] > 1 && th[c->screen] != wah && mc[c->screen] !=
c )
! ny[c->screen] = c->y + c->h + 2 * c->border;
}
}
***************
*** 1643,1648 ****
--- 1655,1667 ----
}
void
+ togglescreen(const char *arg) {
+ if(!sel) return;
+ sel->screen = (sel->screen + 1) % NUMSCREENS;
+ arrange();
+ }
+
+ void
togglemax(const char *arg) {
XEvent ev;
***************
*** 1863,1868 ****
--- 1882,1901 ----
arrange();
}
+ /* Focus on first visible client with the same screen as what was
+ * previously selected */
+ void
+ viewselmain(const char *arg) {
+ Client *c;
+
+ int s = (sel ? sel->screen : 0);
+
+ view(arg);
+
+ for(c = clients; c && !(isvisible(c) && c->screen == s); c = c->next);
+ if(c) focus(c);
+ }
+
void
viewprevtag(const char *arg) {
static Bool tmp[LENGTH(tags)];
***************
*** 1880,1887 ****
if(!sel || !dozoom || sel->isfloating)
return;
if((c = sel) == nexttiled(clients))
! if(!(c = nexttiled(c->next)))
! return;
detach(c);
attach(c);
focus(c);
--- 1913,1920 ----
if(!sel || !dozoom || sel->isfloating)
return;
if((c = sel) == nexttiled(clients))
! while((c = nexttiled(c->next)) && c->screen != sel->screen);
! if(!c) return;
detach(c);
attach(c);
focus(c);