Re: [dwm] Xinerama

From: Chris (Ducky) Chapin <ducky_AT_duckpond.org>
Date: Tue, 26 Feb 2008 14:35:10 -0800

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);
Received on Tue Feb 26 2008 - 23:35:17 UTC

This archive was generated by hypermail 2.2.0 : Sun Jul 13 2008 - 15:21:46 UTC