Importing wm2-4
14 files changed, 266 insertions(+), 487 deletions(-)

M Border.C
M Border.h
M Buttons.C
M Client.C
M Client.h
M Config.h
M Events.C
M Makefile
M Manager.C
M Manager.h
M README
R listimpl.C => 
R listmacro.h => 
A => listmacro2.h
M Border.C +107 -222
@@ 4,19 4,6 @@ 
 #include "Manager.h"
 #include "Rotated.h"
 
-#if CONFIG_USE_PIXMAPS != False
-#include <X11/xpm.h>
-#include "background.xpm"
-#endif
-
-// These distances all exclude the 1-pixel borders.  You could
-// probably change these a certain amount before breaking the shoddy
-// code in the rest of this file.
-
-int Border::m_tabTopHeight = 2;
-int Border::m_frameWidth = CONFIG_FRAME_THICKNESS;
-int Border::m_transientFrameWidth = 4;
-
 // These are degenerate initialisations, don't change them
 int Border::m_tabWidth = -1;
 XRotFontStruct *Border::m_tabFont = 0;

          
@@ 27,11 14,30 @@ unsigned long Border::m_backgroundPixel;
 unsigned long Border::m_frameBackgroundPixel;
 unsigned long Border::m_buttonBackgroundPixel;
 unsigned long Border::m_borderPixel;
-Pixmap Border::m_backgroundPixmap = None;
 
 static int borderCounter = 0;
 
 
+declareList(RectangleList, XRectangle);
+implementList(RectangleList, XRectangle);
+
+class BorderRectangleList : public RectangleList
+{
+public:
+    BorderRectangleList() { }
+    ~BorderRectangleList() { }
+
+    void appendRect(int x, int y, int w, int h);
+};
+
+void BorderRectangleList::appendRect(int x, int y, int w, int h)
+{
+    XRectangle r;
+    r.x = x; r.y = y; r.width = w; r.height = h;
+    append(r);
+}
+
+
 Border::Border(Client *const c, Window child) :
     m_client(c), m_parent(0), m_tab(0),
     m_child(child), m_button(0), m_resize(0), m_label(0),

          
@@ 48,37 54,20 @@ Border::Border(Client *const c, Window c
 	}
 
 	m_tabWidth = m_tabFont->height + 4;
-	if (m_tabWidth < m_tabTopHeight * 2 + 8) {
-	    m_tabWidth = m_tabTopHeight * 2 + 8;
+	if (m_tabWidth < TAB_TOP_HEIGHT * 2 + 8) {
+	    m_tabWidth = TAB_TOP_HEIGHT * 2 + 8;
 	}
 
-	int screen = 0;		// !!
-	XColor nearest, ideal;
-
-	if (!XAllocNamedColor(display(), DefaultColormap(display(), screen),
-			      CONFIG_TAB_FOREGROUND, &nearest, &ideal)) {
-	    fatal("couldn't load tab foreground colour");
-	} else m_foregroundPixel = nearest.pixel;
-
-	if (!XAllocNamedColor(display(), DefaultColormap(display(), screen),
-			      CONFIG_TAB_BACKGROUND, &nearest, &ideal)) {
-	    fatal("couldn't load tab background colour");
-	} else m_backgroundPixel = nearest.pixel;
-
-	if (!XAllocNamedColor(display(), DefaultColormap(display(), screen),
-			      CONFIG_FRAME_BACKGROUND, &nearest, &ideal)) {
-	    fatal("couldn't load frame background colour");
-	} else m_frameBackgroundPixel = nearest.pixel;
-
-	if (!XAllocNamedColor(display(), DefaultColormap(display(), screen),
-			      CONFIG_BUTTON_BACKGROUND, &nearest, &ideal)) {
-	    fatal("couldn't load button background colour");
-	} else m_buttonBackgroundPixel = nearest.pixel;
-
-	if (!XAllocNamedColor(display(), DefaultColormap(display(), screen),
-			      CONFIG_BORDERS, &nearest, &ideal)) {
-	    fatal("couldn't load border colour");
-	} else m_borderPixel = nearest.pixel;
+	m_foregroundPixel = windowManager()->allocateColour
+	    (CONFIG_TAB_FOREGROUND, "tab foreground");
+	m_backgroundPixel = windowManager()->allocateColour
+	    (CONFIG_TAB_BACKGROUND, "tab background");
+	m_frameBackgroundPixel = windowManager()->allocateColour
+	    (CONFIG_FRAME_BACKGROUND, "frame background");
+	m_buttonBackgroundPixel = windowManager()->allocateColour
+	    (CONFIG_BUTTON_BACKGROUND, "button background");
+	m_borderPixel = windowManager()->allocateColour
+	    (CONFIG_BORDERS, "border");
 
 	XGCValues values;
 	values.foreground = m_foregroundPixel;

          
@@ 95,20 84,6 @@ Border::Border(Client *const c, Window c
 	if (!m_drawGC) {
 	    windowManager()->fatal("couldn't allocate border GC");
 	}
-
-#if CONFIG_USE_PIXMAPS != False
-	if (CONFIG_USE_PIXMAPS) {
-	    XpmAttributes attrs;
-	    attrs.valuemask = 0L;
-	    if (XpmCreatePixmapFromData(display(), root(), background,
-					&m_backgroundPixmap, NULL, &attrs)
-		!= XpmSuccess) {
-		fprintf(stderr, "wm2: couldn't create background pixmap\n"); 
-		m_backgroundPixmap = None;
-	    }
-	} else
-#endif
-	    m_backgroundPixmap = None;
     }
 
     ++borderCounter;

          
@@ 133,9 108,6 @@ Border::~Border()
 
     if (--borderCounter == 0) {
 	XFreeGC(display(), m_drawGC);
-	if (m_backgroundPixmap != None) {
-	    XFreePixmap(display(), m_backgroundPixmap);
-	}
     }
 }
 

          
@@ 235,10 207,6 @@ void Border::fixTabHeight(int maxHeight)
 }
 
 
-declareList(RectangleList, XRectangle);
-implementList(RectangleList, XRectangle);
-
-
 void Border::shapeTransientParent(int w, int h)
 {
     XRectangle r;

          
@@ 260,27 228,15 @@ void Border::shapeTransientParent(int w,
 void Border::setTransientFrameVisibility(Boolean visible, int w, int h)
 {
     int i;
-    XRectangle r;
-    RectangleList rl;
+    BorderRectangleList rl;
 
-    r.x = 0; r.y = 0;
-    r.width = w + 1; r.height = yIndent() - 1;
-    rl.append(r);
-
+    rl.appendRect(0, 0, w + 1, yIndent() - 1);
     for (i = 1; i < yIndent(); ++i) {
-	r.x = w + 1; r.y = i - 1;
-	r.width = i + 1; r.height = 1;
-	rl.append(r);
+	rl.appendRect(w + 1, i - 1, i + 1, 1);
     }
-
-    r.x = 0; r.y = yIndent() - 1;
-    r.width = xIndent() - 1; r.height = h - yIndent() + 2;
-    rl.append(r);
-
+    rl.appendRect(0, yIndent() - 1, xIndent() - 1, h - yIndent() + 2);
     for (i = 1; i < yIndent(); ++i) {
-	r.x = i - 1; r.y = h;
-	r.width = 1; r.height = i + 2;
-	rl.append(r);
+	rl.appendRect(i - 1, h, 1, i + 2);
     }
 
     XShapeCombineRectangles

          
@@ 290,24 246,13 @@ void Border::setTransientFrameVisibility
 
     rl.remove_all();
 
-    r.x = 1; r.y = 1;
-    r.width = w; r.height = yIndent() - 2;
-    rl.append(r);
-
+    rl.appendRect(1, 1, w, yIndent() - 2);
     for (i = 2; i < yIndent(); ++i) {
-	r.x = w + 1; r.y = i - 1;
-	r.width = i; r.height = 1;
-	rl.append(r);
+	rl.appendRect(w + 1, i - 1, i, 1);
     }
-
-    r.x = 1; r.y = yIndent() - 1;
-    r.width = xIndent() - 2; r.height = h - yIndent() + 1;
-    rl.append(r);
-
+    rl.appendRect(1, yIndent() - 1, xIndent() - 2, h - yIndent() + 1);
     for (i = 2; i < yIndent(); ++i) {
-	r.x = i - 1; r.y = h;
-	r.width = 1; r.height = i + 1;
-	rl.append(r);
+	rl.appendRect(i - 1, h, 1, i + 1);
     }
 
     XShapeCombineRectangles

          
@@ 320,9 265,8 @@ void Border::setTransientFrameVisibility
 void Border::shapeParent(int w, int h)
 {
     int i;
-    XRectangle r;
     int mainRect;
-    RectangleList rl;
+    BorderRectangleList rl;
 
     if (isTransient()) {
 	shapeTransientParent(w, h);

          
@@ 333,37 277,26 @@ void Border::shapeParent(int w, int h)
     // child window border
 
     // top of tab
-    r.x = 0; r.y = 0;
-    r.width = w + m_tabWidth + 1; r.height = m_tabTopHeight + 2;
-    rl.append(r);
-    
+    rl.appendRect(0, 0, w + m_tabWidth + 1, TAB_TOP_HEIGHT + 2);
+
     // struts in tab, left...
-    r.x = 0; r.y = m_tabTopHeight + 1;
-    r.width = m_tabTopHeight + 2; r.height = m_tabWidth - m_tabTopHeight*2 - 1;
-    rl.append(r);
+    rl.appendRect(0, TAB_TOP_HEIGHT + 1,
+		  TAB_TOP_HEIGHT + 2, m_tabWidth - TAB_TOP_HEIGHT*2 - 1);
 
     // ...and right
-    r.x = m_tabWidth - m_tabTopHeight; r.y = m_tabTopHeight + 1;
-    r.width = m_tabTopHeight + 2; r.height = m_tabWidth - m_tabTopHeight*2 - 1;
-    rl.append(r);
+    rl.appendRect(m_tabWidth - TAB_TOP_HEIGHT, TAB_TOP_HEIGHT + 1,
+		  TAB_TOP_HEIGHT + 2, m_tabWidth - TAB_TOP_HEIGHT*2 - 1);
 
-    // main window
-    r.x = xIndent() - 1; r.y = yIndent() - 1;
-    r.width = w + 2; r.height = h + 2;
     mainRect = rl.count();
-    rl.append(r);
+    rl.appendRect(xIndent() - 1, yIndent() - 1, w + 2, h + 2);
 
     // main tab
-    r.x = 0; r.y = m_tabWidth - m_tabTopHeight;
-    r.width = m_tabWidth + 2;
-    r.height = m_tabHeight - m_tabWidth + m_tabTopHeight;
-    rl.append(r);
+    rl.appendRect(0, m_tabWidth - TAB_TOP_HEIGHT, m_tabWidth + 2,
+		  m_tabHeight - m_tabWidth + TAB_TOP_HEIGHT);
 
     // diagonal
     for (i = 1; i < m_tabWidth - 1; ++i) {
-	r.x = i; r.y = m_tabHeight + i - 1;
-	r.width = m_tabWidth - i + 2; r.height = 1;
-	rl.append(r);
+	rl.appendRect(i, m_tabHeight + i - 1, m_tabWidth - i + 2, 1);
     }
 
     XShapeCombineRectangles

          
@@ 384,8 317,7 @@ void Border::shapeParent(int w, int h)
 void Border::shapeTab(int w, int)
 {
     int i;
-    XRectangle r;
-    RectangleList rl;
+    BorderRectangleList rl;
 
     if (isTransient()) {
 	return;

          
@@ 393,27 325,18 @@ void Border::shapeTab(int w, int)
 
     // Bounding rectangles
 
-    r.x = 0; r.y = 0;
-    r.width = w + m_tabWidth + 1; r.height = m_tabTopHeight + 2;
-    rl.append(r);
-    
-    r.x = 0; r.y = m_tabTopHeight + 1;
-    r.width = m_tabTopHeight + 2; r.height = m_tabWidth - m_tabTopHeight*2 - 1;
-    rl.append(r);
+    rl.appendRect(0, 0, w + m_tabWidth + 1, TAB_TOP_HEIGHT + 2);
+    rl.appendRect(0, TAB_TOP_HEIGHT + 1, TAB_TOP_HEIGHT + 2,
+		  m_tabWidth - TAB_TOP_HEIGHT*2 - 1);
 
-    r.x = m_tabWidth - m_tabTopHeight; r.y = m_tabTopHeight + 1;
-    r.width = m_tabTopHeight + 2; r.height = m_tabWidth - m_tabTopHeight*2 - 1;
-    rl.append(r);
+    rl.appendRect(m_tabWidth - TAB_TOP_HEIGHT, TAB_TOP_HEIGHT + 1,
+		  TAB_TOP_HEIGHT + 2, m_tabWidth - TAB_TOP_HEIGHT*2 - 1);
 
-    r.x = 0; r.y = m_tabWidth - m_tabTopHeight;
-    r.width = m_tabWidth + 2;
-    r.height = m_tabHeight - m_tabWidth + m_tabTopHeight;
-    rl.append(r);
+    rl.appendRect(0, m_tabWidth - TAB_TOP_HEIGHT, m_tabWidth + 2,
+		  m_tabHeight - m_tabWidth + TAB_TOP_HEIGHT);
 
     for (i = 1; i < m_tabWidth - 1; ++i) {
-	r.x = i; r.y = m_tabHeight + i - 1;
-	r.width = m_tabWidth - i + 2; r.height = 1;
-	rl.append(r);
+	rl.appendRect(i, m_tabHeight + i - 1, m_tabWidth - i + 2, 1);
     }
 
     XShapeCombineRectangles

          
@@ 424,34 347,24 @@ void Border::shapeTab(int w, int)
 
     // Clipping rectangles
 
-    r.x = 1; r.y = 1;
-    r.width = w + m_tabWidth - 1; r.height = m_tabTopHeight;
-    rl.append(r);
+    rl.appendRect(1, 1, w + m_tabWidth - 1, TAB_TOP_HEIGHT);
 
-    r.x = 1; r.y = m_tabTopHeight + 1;
-    r.width = m_tabTopHeight; r.height = m_tabWidth + m_tabTopHeight*2 - 1;
-    rl.append(r);
+    rl.appendRect(1, TAB_TOP_HEIGHT + 1, TAB_TOP_HEIGHT,
+		  m_tabWidth + TAB_TOP_HEIGHT*2 - 1);
 
-    r.x = m_tabWidth - m_tabTopHeight + 1; r.y = m_tabTopHeight + 1;
-    r.width = m_tabTopHeight; r.height = m_tabWidth + m_tabTopHeight*2 - 1;
-    rl.append(r);
+    rl.appendRect(m_tabWidth - TAB_TOP_HEIGHT + 1, TAB_TOP_HEIGHT + 1,
+		  TAB_TOP_HEIGHT, m_tabWidth + TAB_TOP_HEIGHT*2 - 1);
 
-    r.x = 1; r.y = m_tabWidth - m_tabTopHeight + 1;
-    r.width = m_tabWidth;
-    r.height = m_tabHeight - m_tabWidth + m_tabTopHeight - 1;
-    rl.append(r);
+    rl.appendRect(1, m_tabWidth - TAB_TOP_HEIGHT + 1, m_tabWidth,
+		  m_tabHeight - m_tabWidth + TAB_TOP_HEIGHT - 1);
 
     for (i = 1; i < m_tabWidth - 2; ++i) {
-	r.x = i + 1; r.y = m_tabHeight + i - 1;
-	r.width = m_tabWidth - i; r.height = 1;
-	rl.append(r);
+	rl.appendRect(i + 1, m_tabHeight + i - 1, m_tabWidth - i, 1);
     }
 
     XShapeCombineRectangles
 	(display(), m_tab, ShapeClip,
 	 0, 0, rl.array(0, rl.count()), rl.count(), ShapeSet, YXSorted);
-
-//    XSync(display(), False);
 }
 
 

          
@@ 459,7 372,7 @@ void Border::resizeTab(int h)
 {
     int i;
     XRectangle r;
-    RectangleList rl;
+    BorderRectangleList rl;
     int shorter, longer, operation;
 
     if (isTransient()) {

          
@@ 507,15 420,13 @@ void Border::resizeTab(int h)
     if (m_client->isActive()) {
 	// restore a bit of the frame edge
 	r.x = m_tabWidth + 1; r.y = shorter;
-	r.width = m_frameWidth - 1; r.height = longer - shorter;
+	r.width = FRAME_WIDTH - 1; r.height = longer - shorter;
 	XShapeCombineRectangles(display(), m_parent, ShapeBounding,
 				0, 0, &r, 1, ShapeUnion, YXBanded);
     }
 
     for (i = 1; i < m_tabWidth - 1; ++i) {
-	r.x = i; r.y = m_tabHeight + i - 1/*3*/;
-	r.width = m_tabWidth - i + 2; r.height = 1;
-	rl.append(r);
+	rl.appendRect(i, m_tabHeight + i - 1, m_tabWidth - i + 2, 1);
     }
 	
     XShapeCombineRectangles

          
@@ 540,20 451,16 @@ void Border::resizeTab(int h)
 	(display(), m_tab, ShapeClip,
 	 0, 0, rl.array(0, rl.count() - 1), rl.count() - 1,
 	 ShapeUnion, YXBanded);
-
-//    XSync(display(), False);
 }
 
 
 void Border::shapeResize()
 {
     int i;
-    XRectangle r;
-    RectangleList rl;
+    BorderRectangleList rl;
 
-    for (i = 0; i < m_frameWidth*2; ++i) {
-	r.x = m_frameWidth*2 - i - 1; r.y = i; r.width = i + 1; r.height = 1;
-	rl.append(r);
+    for (i = 0; i < FRAME_WIDTH*2; ++i) {
+	rl.appendRect(FRAME_WIDTH*2 - i - 1, i, i + 1, 1);
     }
 
     XShapeCombineRectangles

          
@@ 562,9 469,8 @@ void Border::shapeResize()
 
     rl.remove_all();
 
-    for (i = 1; i < m_frameWidth*2; ++i) {
-	r.x = m_frameWidth*2 - i; r.y = i; r.width = i; r.height = 1;
-	rl.append(r);
+    for (i = 1; i < FRAME_WIDTH*2; ++i) {
+	rl.appendRect(FRAME_WIDTH*2 - i, i, i, 1);
     }
 
     XShapeCombineRectangles

          
@@ 573,9 479,8 @@ void Border::shapeResize()
 
     rl.remove_all();
 
-    for (i = 0; i < m_frameWidth*2 - 3; ++i) {
-	r.x = m_frameWidth*2 - i - 1; r.y = i + 3; r.width = 1; r.height = 1;
-	rl.append(r);
+    for (i = 0; i < FRAME_WIDTH*2 - 3; ++i) {
+	rl.appendRect(FRAME_WIDTH*2 - i - 1, i + 3, 1, 1);
     }
 
     XShapeCombineRectangles

          
@@ 589,8 494,7 @@ void Border::shapeResize()
 
 void Border::setFrameVisibility(Boolean visible, int w, int h)
 {
-    XRectangle r;
-    RectangleList rl;
+    BorderRectangleList rl;
 
     if (CONFIG_PROD_SHAPE) {
 	shapeParent(w, h);

          
@@ 604,23 508,17 @@ void Border::setFrameVisibility(Boolean 
 
     // Bounding rectangles
 
-    r.x = m_tabWidth + w + 1; r.y = 0;
-    r.width = m_frameWidth + 1; r.height = m_frameWidth;
-    rl.append(r);
+    rl.appendRect(m_tabWidth + w + 1, 0, FRAME_WIDTH + 1, FRAME_WIDTH);
 
-    r.x = m_tabWidth + 2; r.y = m_tabTopHeight + 2;
-    r.width = w; r.height = m_frameWidth - m_tabTopHeight - 2;
-    rl.append(r);
+    rl.appendRect(m_tabWidth + 2, TAB_TOP_HEIGHT + 2, w,
+		  FRAME_WIDTH - TAB_TOP_HEIGHT - 2);
 
     // for button
-    r.width = r.height = m_tabWidth - m_tabTopHeight*2 - 4;
-    r.x = r.y = (m_tabWidth + 2 - r.width) / 2;
-    rl.append(r);
+    int ww = m_tabWidth - TAB_TOP_HEIGHT*2 - 4;
+    rl.appendRect((m_tabWidth + 2 - ww) / 2, (m_tabWidth+2 - ww) / 2, ww, ww);
 
-    r.x = m_tabWidth + 2; r.y = m_frameWidth;
-    r.width = m_frameWidth - 2;
-    r.height = m_tabHeight + m_tabWidth - m_frameWidth - 2;
-    rl.append(r);
+    rl.appendRect(m_tabWidth + 2, FRAME_WIDTH,
+		  FRAME_WIDTH - 2, m_tabHeight + m_tabWidth - FRAME_WIDTH - 2);
 
     // swap last two if sorted wrong
     if (rl.item(rl.count()-2).y > rl.item(rl.count()-1).y) {

          
@@ 628,9 526,12 @@ void Border::setFrameVisibility(Boolean 
 	rl.remove(rl.count()-3);
     }
 
-    r.x -= 1; r.y += r.height;
-    r.width += 1; r.height = h - r.height + 2;
-    rl.append(r);
+    int final = rl.count();
+    rl.append(rl.item(final-1));
+    rl.item(final).x -= 1;
+    rl.item(final).y += rl.item(final).height;
+    rl.item(final).width += 1;
+    rl.item(final).height = h - rl.item(final).height + 2;
 
     XShapeCombineRectangles(display(), m_parent, ShapeBounding,
 			    0, 0, rl.array(0, rl.count()), rl.count(),

          
@@ 639,22 540,17 @@ void Border::setFrameVisibility(Boolean 
 
     // Clip rectangles
 
-    r.x = m_tabWidth + w + 1; r.y = 1;
-    r.width = m_frameWidth; r.height = m_frameWidth - 1;
-    rl.append(r);
+    rl.appendRect(m_tabWidth + w + 1, 1, FRAME_WIDTH, FRAME_WIDTH - 1);
 
-    r.x = m_tabWidth + 2; r.y = m_tabTopHeight + 2;
-    r.width = w; r.height = m_frameWidth - m_tabTopHeight - 2;
-    rl.append(r);
+    rl.appendRect(m_tabWidth + 2, TAB_TOP_HEIGHT + 2, w,
+		  FRAME_WIDTH - TAB_TOP_HEIGHT - 2);
 
     // for button
-    r.width = r.height = m_tabWidth - m_tabTopHeight*2 - 6;
-    r.x = r.y = (m_tabWidth + 2 - r.width) / 2;
-    rl.append(r);
+    ww = m_tabWidth - TAB_TOP_HEIGHT*2 - 6;
+    rl.appendRect((m_tabWidth + 2 - ww) / 2, (m_tabWidth+2 - ww) / 2, ww, ww);
 
-    r.x = m_tabWidth + 2; r.y = m_frameWidth;
-    r.width = m_frameWidth - 2; r.height = h - m_frameWidth;
-    rl.append(r);
+    rl.appendRect(m_tabWidth + 2, FRAME_WIDTH,
+		  FRAME_WIDTH - 2, h - FRAME_WIDTH);
 
     // swap last two if sorted wrong
     if (rl.item(rl.count()-2).y > rl.item(rl.count()-1).y) {

          
@@ 662,9 558,7 @@ void Border::setFrameVisibility(Boolean 
 	rl.remove(rl.count()-3);
     }
 
-    r.x = m_tabWidth + 2; r.y = h;
-    r.width = m_frameWidth - 2; r.height = m_frameWidth + 1;
-    rl.append(r);
+    rl.appendRect(m_tabWidth + 2, h, FRAME_WIDTH - 2, FRAME_WIDTH + 1);
 
     XShapeCombineRectangles(display(), m_parent, ShapeClip,
 			    0, 0, rl.array(0, rl.count()), rl.count(),

          
@@ 676,8 570,6 @@ void Border::setFrameVisibility(Boolean 
     } else {
 	XUnmapWindow(display(), m_resize);
     }
-
-//    XSync(display(), False);	// doesn't seem to help much
 }
 
 

          
@@ 702,7 594,7 @@ void Border::configure(int x, int y, int
 	     m_borderPixel, m_buttonBackgroundPixel);
 
 	m_resize = XCreateWindow
-	    (display(), m_child, 1, 1, m_frameWidth*2, m_frameWidth*2, 0,
+	    (display(), m_child, 1, 1, FRAME_WIDTH*2, FRAME_WIDTH*2, 0,
 	     CopyFromParent, InputOutput, CopyFromParent, 0L, 0);
 
 	shapeResize();

          
@@ 721,14 613,6 @@ void Border::configure(int x, int y, int
 		     ButtonPressMask | ButtonReleaseMask/* | LeaveWindowMask*/);
 	XSelectInput(display(), m_resize, ButtonPressMask | ButtonReleaseMask);
 	mask |= CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
-
-	if (m_backgroundPixmap) {
-	    XSetWindowAttributes wa;
-	    wa.background_pixmap = m_backgroundPixmap;
-	    XChangeWindowAttributes(display(), m_parent, CWBackPixmap, &wa);
-	    XChangeWindowAttributes(display(), m_tab,    CWBackPixmap, &wa);
-	    XChangeWindowAttributes(display(), m_button, CWBackPixmap, &wa);
-	}
     }
 
     XWindowChanges wc;

          
@@ 744,8 628,8 @@ void Border::configure(int x, int y, int
     unsigned long rmask = 0L;
     if (mask & CWWidth)  rmask |= CWX;
     if (mask & CWHeight) rmask |= CWY;
-    wc.x = w - m_frameWidth*2;
-    wc.y = h - m_frameWidth*2;
+    wc.x = w - FRAME_WIDTH*2;
+    wc.y = h - FRAME_WIDTH*2;
     XConfigureWindow(display(), m_resize, rmask, &wc);
     
     if (force ||

          
@@ 778,8 662,9 @@ void Border::configure(int x, int y, int
 	resizeTab(h);
     }
 
-    wc.x = wc.y = m_tabTopHeight + 2;
-    wc.width = wc.height = m_tabWidth - m_tabTopHeight*2 - 4;
+    wc.x = TAB_TOP_HEIGHT + 2;
+    wc.y = wc.x;
+    wc.width = wc.height = m_tabWidth - TAB_TOP_HEIGHT*2 - 4;
     XConfigureWindow(display(), m_button, mask, &wc);
 }
 

          
M Border.h +12 -7
@@ 8,6 8,15 @@ 
 class Client;
 class WindowManager;
 
+// These distances exclude the 1-pixel borders.  You could probably
+// change these a certain amount before breaking the shoddy code in
+// the rest of this file.
+
+#define TAB_TOP_HEIGHT 2
+#define FRAME_WIDTH CONFIG_FRAME_THICKNESS
+#define TRANSIENT_FRAME_WIDTH 4
+// NB frameTopHeight = frameHeight-tabTopHeight
+
 class Border {			// friend of client
 public:
     Border(Client *const, Window child);

          
@@ 39,11 48,11 @@ public:
     void eventButton(XButtonEvent *); // in Buttons.C
 
     int yIndent() {
-	return isTransient() ? m_transientFrameWidth + 1 : m_frameWidth + 1;
+	return isTransient() ? TRANSIENT_FRAME_WIDTH + 1 : FRAME_WIDTH + 1;
     }
     int xIndent() {
-	return isTransient() ? m_transientFrameWidth + 1 :
-	    m_tabWidth + m_frameWidth + 1;
+	return isTransient() ? TRANSIENT_FRAME_WIDTH + 1 :
+	    m_tabWidth + FRAME_WIDTH + 1;
     }
 
     Boolean coordsInHole(int, int); // in Events.C of all places

          
@@ 78,9 87,6 @@ private:
 private:
     int        m_tabHeight;	// depends on the label
     static int m_tabWidth;	// depends on the label font
-    static int m_tabTopHeight;
-    static int m_frameWidth;	// NB frameTopHeight = frameHeight-tabTopHeight
-    static int m_transientFrameWidth;
     static XRotFontStruct *m_tabFont;
     static GC m_drawGC;
     static unsigned long m_foregroundPixel;

          
@@ 88,7 94,6 @@ private:
     static unsigned long m_frameBackgroundPixel;
     static unsigned long m_buttonBackgroundPixel;
     static unsigned long m_borderPixel;
-    static Pixmap m_backgroundPixmap;
 };
 
 

          
M Buttons.C +4 -3
@@ 146,8 146,9 @@ void WindowManager::menu(XButtonEvent *e
 
     if (CONFIG_EVERYTHING_ON_ROOT_MENU) {
 	for (i = 0; i < m_clients.count(); ++i) {
-	    if (m_clients.item(i)->isNormal())
+	    if (m_clients.item(i)->isNormal()) {
 		clients.append(m_clients.item(i));
+	    }
 	}
     }
     int n = clients.count() + 1;

          
@@ 653,7 654,7 @@ void Border::eventButton(XButtonEvent *e
     int x = e->x;
     int y = e->y;
     int action = 1;
-    int buttonSize = m_tabWidth - m_tabTopHeight*2 - 4;
+    int buttonSize = m_tabWidth - TAB_TOP_HEIGHT*2 - 4;
 
     XFillRectangle(display(), m_button, m_drawGC, 0, 0, buttonSize, buttonSize);
 

          
@@ 661,7 662,7 @@ void Border::eventButton(XButtonEvent *e
 
 	found = False;
 
-	if (tdiff > 1500L && action == 1) {
+	if (tdiff > CONFIG_DESTROY_WINDOW_DELAY && action == 1) {
 	    windowManager()->installCursor(WindowManager::DeleteCursor);
 	    action = 2;
 	}

          
M Client.C +18 -4
@@ 617,7 617,16 @@ void Client::getTransient()
     Window t = None;
 
     if (XGetTransientForHint(display(), m_window, &t) != 0) {
-	m_transient = t;
+
+	if (windowManager()->windowToClient(t) == this) {
+	    fprintf(stderr,
+		    "wm2: warning: client \"%s\" thinks it's a transient "
+		    "for\nitself -- ignoring WM_TRANSIENT_FOR property...\n",
+		    m_label ? m_label : "(no name)");
+	    m_transient = None;
+	} else {		
+	    m_transient = t;
+	}
     } else {
 	m_transient = None;
     }

          
@@ 682,8 691,10 @@ void Client::sendConfigureNotify()
 }
 
 
-void Client::withdraw()
+void Client::withdraw(Boolean changeState)
 {
+//    fprintf(stderr,"withdrawing\n");
+
     m_border->unmap();
 
     gravitate(True);

          
@@ 691,8 702,10 @@ void Client::withdraw()
 
     gravitate(False);
 
-    XRemoveFromSaveSet(display(), m_window);
-    setState(WithdrawnState);
+    if (changeState) {
+	XRemoveFromSaveSet(display(), m_window);
+	setState(WithdrawnState);
+    }
 
     ignoreBadWindowErrors = True;
     XSync(display(), False);

          
@@ 744,3 757,4 @@ void Client::lower()
     m_border->lower();
 }
 
+

          
M Client.h +1 -1
@@ 19,7 19,7 @@ public:
     void gravitate(Boolean invert);
     void installColormap();
     void unreparent();
-    void withdraw();
+    void withdraw(Boolean = True);
     void hide();
     void unhide(Boolean map);
     void rename();

          
M Config.h +1 -3
@@ 25,6 25,7 @@ 
 // windows such as xvt).
 #define CONFIG_AUTO_RAISE_DELAY       400
 #define CONFIG_POINTER_STOPPED_DELAY  80
+#define CONFIG_DESTROY_WINDOW_DELAY   1500L
 
 #define CONFIG_TAB_FOREGROUND	  "black"
 #define CONFIG_TAB_BACKGROUND     "gray80"

          
@@ 36,9 37,6 @@ 
 #define CONFIG_MENU_BACKGROUND    "gray80"
 #define CONFIG_MENU_BORDERS       "black"
 
-#define CONFIG_USE_PIXMAPS        False
-
-// I like 7 for plain frames, or 8 if using pixmaps
 #define CONFIG_FRAME_THICKNESS    7
 
 // If CONFIG_PROD_SHAPE is True, all frame element shapes will be

          
M Events.C +2 -1
@@ 147,7 147,8 @@ void WindowManager::nextEvent(XEvent *e)
 	t.tv_sec = 0; t.tv_usec = 20000;
 
 	if ((r = select(fd + 1, &rfds, NULL, NULL,
-			m_focusChanging ? &t : (struct timeval *)NULL)) == 1) {
+			(m_focusChanging) ? &t :
+			(struct timeval *)NULL)) == 1) {
 	    XNextEvent(m_display, e);
 	    return;
 	}

          
M Makefile +1 -2
@@ 1,11 1,10 @@ 
 
-# if you want pixmaps you'll need Xpm, so add -lXpm to the next line
 LIBS	=  -L/usr/X11/lib -lXext -lX11 -lXmu -lm
 
 CC	= gcc
 CCC	= gcc
 CFLAGS	= -O2
-OBJECTS	= Border.o Buttons.o Client.o Events.o Main.o Manager.o Rotated.o listimpl.o
+OBJECTS	= Border.o Buttons.o Client.o Events.o Main.o Manager.o Rotated.o
 
 .c.o:
 	$(CC) -c $(CFLAGS) $<

          
M Manager.C +23 -30
@@ 28,7 28,7 @@ WindowManager::WindowManager() :
     m_menuGC(0), m_menuWindow(0), m_menuFont(0), m_focusChanging(False)
 {
     fprintf(stderr, "\nwm2: Copyright (c) 1996-7 Chris Cannam."
-	    "  Third release, January 1997\n"
+	    "  Fourth release, March 1997\n"
 	    "     Parts derived from 9wm Copyright (c) 1994-96 David Hogan\n"
 	    "     %s\n     Copying and redistribution encouraged.  "
 	    "No warranty.\n\n", XV_COPYRIGHT);

          
@@ 70,12 70,6 @@ WindowManager::WindowManager() :
 	fprintf(stderr, "     Shape prodding off.  ");
     }
 
-    if (CONFIG_USE_PIXMAPS) {
-	fprintf(stderr, "Fancy borders.");
-    } else {
-	fprintf(stderr, "Plain borders.");
-    }
-
     fprintf(stderr, "\n     (To reconfigure, simply edit and recompile.)\n\n");
 
     m_display = XOpenDisplay(NULL);

          
@@ 282,22 276,12 @@ void WindowManager::initialiseScreen()
     XChangeWindowAttributes(m_display, m_root, CWCursor | CWEventMask, &attr);
     XSync(m_display, False);
 
-    XColor nearest;
-
-    if (!XAllocNamedColor(m_display, m_defaultColormap,
-			  CONFIG_MENU_FOREGROUND, &nearest, &temp)) {
-	fatal("couldn't load menu foreground colour");
-    } else m_menuForegroundPixel = nearest.pixel;
-    
-    if (!XAllocNamedColor(m_display, m_defaultColormap,
-			  CONFIG_MENU_BACKGROUND, &nearest, &temp)) {
-	fatal("couldn't load menu background colour");
-    } else m_menuBackgroundPixel = nearest.pixel;
-    
-    if (!XAllocNamedColor(m_display, m_defaultColormap,
-			  CONFIG_MENU_BORDERS, &nearest, &temp)) {
-	fatal("couldn't load menu border colour");
-    } else m_menuBorderPixel = nearest.pixel;
+    m_menuForegroundPixel =
+	allocateColour(CONFIG_MENU_FOREGROUND, "menu foreground");
+    m_menuBackgroundPixel =
+	allocateColour(CONFIG_MENU_BACKGROUND, "menu background");
+    m_menuBorderPixel =
+	allocateColour(CONFIG_MENU_BORDERS, "menu border");
 
     m_menuWindow = XCreateSimpleWindow
 	(m_display, m_root, 0, 0, 1, 1, 1,

          
@@ 328,6 312,22 @@ void WindowManager::initialiseScreen()
 }
 
 
+unsigned long WindowManager::allocateColour(char *name, char *desc)
+{
+    XColor nearest, ideal;
+
+    if (!XAllocNamedColor
+	(display(), DefaultColormap(display(), m_screenNumber), name,
+	 &nearest, &ideal)) {
+
+	char error[100];
+	sprintf(error, "couldn't load %s colour", desc);
+	fatal(error);
+
+    } else return nearest.pixel;
+}
+
+
 void WindowManager::installCursor(RootCursor c)
 {
     installCursorOnWindow(c, m_root);

          
@@ 399,10 399,6 @@ Client *WindowManager::windowToClient(Wi
     for (int i = m_clients.count()-1; i >= 0; --i) {
 
 	if (m_clients.item(i)->hasWindow(w)) {
-
-// fprintf(stderr, "WindowManager::windowToClient: located %p (\"%s\")\n",
-//	    m_clients.item(i), m_clients.item(i)->label());
-
 	    return m_clients.item(i);
 	}
     }

          
@@ 411,9 407,6 @@ Client *WindowManager::windowToClient(Wi
     else {
 	Client *newC = new Client(this, w);
 	m_clients.append(newC);
-
-//	fprintf(stderr, "I now have %d clients\n", (int)m_clients.count());
-
 	return newC;
     }
 }

          
M Manager.h +2 -1
@@ 3,7 3,7 @@ 
 #define _MANAGER_H_
 
 #include "General.h"
-#include "listmacro.h"
+#include "listmacro2.h"
 
 class Client;
 declarePList(ClientList, Client);

          
@@ 40,6 40,7 @@ public:
     void installCursor(RootCursor);
     void installCursorOnWindow(RootCursor, Window);
     void installColormap(Colormap);
+    unsigned long allocateColour(char *, char *);
 
     void considerFocusChange(Client *, Window, Time timestamp);
     void stopConsideringFocus();

          
M README +19 -22
@@ 24,8 24,8 @@ wm2 provides:
 This release
 ============
 
-This is the third release of wm2, made in January 1997.  It differs in
-some ways from the first and second releases.
+This is the fourth release of wm2, made in March 1997.  It differs in
+some ways from the first, second and third releases.
 
 
 Building wm2

          
@@ 34,10 34,8 @@ Building wm2
 You will need a Unix machine, X libraries and a C++ compiler such as
 gcc.  You will also need a mouse, with at least one button.  Your X
 server and libraries must be R4 or newer and must support the Shape
-extension.  If you want to use frame background-pixmaps (see "Pixmaps"
-below), you will need the Xpm header and library.  wm2 does NOT
-support multi-screen displays, because I don't have anything to test
-multi-screen code on.
+extension.  wm2 does NOT support multi-screen displays, because I
+don't have anything to test multi-screen code on.
 
 wm2 makes relatively heavy demands on the performance of your X
 server, because of the use of shaped windows, but it shouldn't place

          
@@ 90,22 88,22 @@ Available window manipulations are:
     second and a half until the cursor changes to a cross, then
     release.  (I know, it's not very easy.  On the other hand,
     things like Windows-95 tend to obscure the fact that most
-    windows already have a perfectly good Close option.)
+    windows already have a perfectly good Close option.  If the
+    default delay doesn't suit you, change it in Config.h and
+    recompile.)
 
  -- To resize a window: make sure it's in focus, then click and
     drag on its bottom-right corner.  For a constrained resize,
     click and drag on the bottom-left or top-right corner of
     the enclosing window frame.
 
- -- To lower a window: click with the right mouse button on its
-    tab or frame.  (This was the only new feature in the second
-    release.)
+ -- To flip around amongst the windows on-screen: click with the right
+    mouse button on the root window or on any window's frame or tab.
 
  -- To exit from wm2: move the mouse pointer to the very edge of the
     screen at the extreme lower-right corner, and click left button on
     the root window for the root menu.  The menu should have an extra
-    option labelled "Exit wm2"; select this.  (This is a new feature
-    in the third release.)
+    option labelled "Exit wm2"; select this.
 
 All move and resize operations are opaque.
 

          
@@ 127,21 125,20 @@ definable in Config.h.
 Pixmaps
 =======
 
-This third release of wm2 will allow you to specify a background
-pixmap for the window frames.  If you set CONFIG_USE_PIXMAPS to True
-in Config.h and supply a file ./background.xpm which contains an Xpm
-pixmap called "background", wm2 will use this to colour in the frames.
-An especially unpleasant example file, cribbed and modified from
-http://home.netscape.com/assist/net_sites/bg/marble/greenred_marble.gif,
-is included, although you're advised to find your own.
+This fourth release of wm2 no longer supports frame background
+pixmaps.  If you want them, consider using wmx (available from the
+same place as wm2) instead.
 
 
 xterm
 =====
 
-Some versions of xterm run badly under wm2.  If you use xterm and find
-that it refreshes the window excessively slowly, you might like to try
-using xvt or rxvt instead.
+Some versions of xterm and rxvt run badly with wm2.  If you use xterm
+and find that it refreshes the window excessively slowly, you might
+like to try experimenting with a different terminal emulation program.
+I think it might help to ensure that the scrollbar is on the
+right-hand side of the rxvt window and is thick enough that wmx's
+resize handle doesn't obscure any of the text area.
 
 
 Credits

          
R listimpl.C =>  +0 -23
@@ 1,23 0,0 @@ 
-
-#include <stdio.h>
-#include <stdlib.h>
-
-static long ListImpl_best_new_sizes[] = {
-    48, 112, 240, 496, 1008, 2032, 4080, 8176,
-    16368, 32752, 65520, 131056, 262128, 524272, 1048560,
-    2097136, 4194288, 8388592, 16777200, 33554416, 67108848
-};
-
-long ListImpl_best_new_count(long count, unsigned int size) {
-    for (int i = 0; i < sizeof(ListImpl_best_new_sizes)/sizeof(int); ++i) {
-        if (count * size < ListImpl_best_new_sizes[i]) {
-            return ListImpl_best_new_sizes[i] / size;
-        }
-    }
-    return count;
-}
-
-void ListImpl_range_error(long i) {
-    fprintf(stderr, "internal error: list index %ld out of range\n", i);
-    abort();
-}

          
R listmacro.h =>  +0 -168
@@ 1,168 0,0 @@ 
-
-#ifndef _LISTMACRO_H_
-#define _LISTMACRO_H_
-
-#define delete_list_items() delete [] items_
-
-extern void ListImpl_range_error(long index);
-extern long ListImpl_best_new_count(long count, unsigned size);
-
-
-#define declarePList(List,T)\
-\
-  typedef T *T##_pointer;\
-\
-  declareList(List,T##_pointer);
-
-#define implementPList(List,T)\
-\
-  typedef T *T##_pointer;\
-\
-  implementList(List,T##_pointer);
-
-
-#define declareList(List,T)\
-class List { \
-public: \
-    List(long size = 0); \
-    List(const List &); \
-    ~List(); \
-\
-    long count() const; \
-    T& item(long index) const; \
-    T* array(long index, long count); \
-\
-    void prepend(const T&); \
-    void append(const T&); \
-    void insert(long index,const T&); \
-    void remove(long index); \
-    void remove_all(); \
-    List &operator=(const List &); \
-private: \
-    T* items_; \
-    long size_; \
-    long count_; \
-    long free_; \
-}; \
-\
-inline long List::count() const { return count_; } \
-\
-inline T& List::item(long index) const { \
-    if (index < 0 || index >= count_) { \
-	ListImpl_range_error(index); \
-    } \
-    long i = index < free_ ? index : index + size_ - count_; \
-    return items_[i]; \
-} \
-\
-inline void List::append(const T& item) { insert(count_, item); } \
-inline void List::prepend(const T& item) { insert(0, item); }
-
-
-#define implementList(List,T) \
-List::List(long size) { \
-    if (size > 0) { \
-        size_ = ListImpl_best_new_count(size, sizeof(T)); \
-        items_ = new T[size_]; \
-    } else { \
-        size_ = 0; \
-        items_ = 0; \
-    } \
-    count_ = 0; \
-    free_ = 0; \
-} \
-\
-List::List(const List& list) : items_(0), size_(0), count_(0), free_(0) { \
-    for (long i = 0; i < list.count(); ++i) { \
-	append(list.item(i)); \
-    } \
-} \
-\
-List::~List() { \
-    delete_list_items(); \
-} \
-\
-T* List::array(long index, long count) { \
-    if (index + count <= free_) { \
-        return items_ + index; \
-    } else if (index >= free_) { \
-        return items_ + index + size_ - count_; \
-    } else { \
-        long i; \
-        for (i = 0; i < index + count - free_; ++i) { \
-            items_[free_ + i] = items_[free_ + size_ - count_ + i]; \
-        } \
-        free_ = index + count; \
-    } \
-    return items_ + index; \
-} \
-\
-void List::insert(long index, const T& item) { \
-    if (count_ == size_) { \
-        long size = ListImpl_best_new_count(size_ + 1, sizeof(T)); \
-        T* items = new T[size]; \
-        if (items_ != 0) { \
-            register long i; \
-            for (i = 0; i < free_; ++i) { \
-                items[i] = items_[i]; \
-            } \
-            for (i = 0; i < count_ - free_; ++i) { \
-                items[free_ + size - count_ + i] = \
-                    items_[free_ + size_ - count_ + i]; \
-            } \
-            delete_list_items(); \
-        } \
-        items_ = items; \
-        size_ = size; \
-    } \
-    if (index >= 0 && index <= count_) { \
-	if (index < free_) { \
-            for (register long i = free_ - index - 1; i >= 0; --i) { \
-                items_[index + size_ - count_ + i] = items_[index + i]; \
-            } \
-        } else if (index > free_) { \
-            for (register long i = 0; i < index - free_; ++i) { \
-                items_[free_ + i] = items_[free_ + size_ - count_ + i]; \
-            } \
-        } \
-        free_ = index + 1; \
-        count_ += 1; \
-        items_[index] = (T)item; \
-    } \
-} \
-\
-void List::remove(long index) { \
-    if (index >= 0 && index <= count_) { \
-        if (index < free_) { \
-            for (register long i = free_ - index - 2; i >= 0; --i) { \
-                items_[size_ - count_ + index + 1 + i] = \
-		    items_[index + 1 + i]; \
-            } \
-        } else if (index > free_) { \
-            for (register long i = 0; i < index - free_; ++i) { \
-                items_[free_ + i] = items_[free_ + size_ - count_ + i]; \
-            } \
-        } \
-        free_ = index; \
-        count_ -= 1; \
-    } \
-} \
-\
-void List::remove_all() { \
-    count_ = 0; \
-    free_ = 0; \
-} \
-\
-List & List::operator=(const List& list) { \
-    if (this != &list) { \
-	remove_all(); \
-	for (long i = 0; i < list.count(); ++i) { \
-	    append(list.item(i)); \
-	} \
-    } \
-    return *this; \
-}
-
-
-#endif
-

          
A => listmacro2.h +76 -0
@@ 0,0 1,76 @@ 
+
+#ifndef _LISTMACRO_H_
+#define _LISTMACRO_H_
+
+#include <assert.h>
+
+// assumes efficient realloc()
+
+#define declarePList(List, T) \
+  typedef T *T##_pointer; \
+  declareList(List, T##_pointer);
+
+#define implementPList(List, T) \
+  typedef T *T##_pointer; \
+  implementList(List, T##_pointer);
+
+#define declareList(List, T) \
+class List { \
+public: \
+    List(); \
+    ~List(); \
+\
+    long count() const { return m_count; } \
+    T &item(long index) const { \
+	assert(index >= 0 && index < m_count); \
+	return m_items[index]; \
+    } \
+    T *array(long index, long count) { \
+	return m_items + index; \
+    } \
+\
+    void append(const T &); \
+    void remove(long index); \
+    void remove_all(); \
+    void move_to_start(long index); \
+\
+private: \
+    T *m_items; \
+    long m_count; \
+};
+
+#define implementList(List, T) \
+\
+List::List() : m_count(0), m_items(0) { } \
+\
+List::~List() { remove_all(); } \
+\
+void List::append(const T &item) { \
+    if (m_items) { \
+        m_items = (T *)realloc(m_items, (m_count + 1) * sizeof(T)); \
+    } else { \
+	m_items = (T *)malloc(sizeof(T)); \
+    } \
+    assert(m_items); \
+    m_items[m_count++] = (T)item; \
+} \
+\
+void List::remove(long index) { \
+    assert(index >= 0 && index < m_count); \
+    memcpy(m_items+index, m_items+index+1, (m_count-index-1) * sizeof(T)); \
+    m_items = (T *)realloc(m_items, (m_count - 1) * sizeof(T)); \
+    --m_count; \
+} \
+\
+void List::remove_all() { \
+    while (m_count > 0) remove(0); \
+} \
+\
+void List::move_to_start(long index) { \
+    assert(index >= 0 && index < m_count); \
+    T temp = item(index); \
+    if (index > 0) memcpy(m_items+1, m_items, index * sizeof(T)); \
+    m_items[0] = temp; \
+}
+
+#endif