Add an optional clock!
5 files changed, 135 insertions(+), 72 deletions(-)

M Channel.C
M Config.h
M Events.C
M Manager.C
M Manager.h
M Channel.C +97 -61
@@ 18,36 18,74 @@ static const char *numerals[10][7] = {
 };
 
 
+Window WindowManager::createNumberWindow(int screen, const char *colour)
+{
+    XColor nearest, ideal;
+            
+    if (!XAllocNamedColor(display(), DefaultColormap(display(), screen),
+                          colour, &nearest, &ideal)) {
+	    
+        if (!XAllocNamedColor(display(), DefaultColormap(display(), screen),
+                              "black", &nearest, &ideal)) {
+		
+            fatal("Couldn't allocate requested numeral colour or black");
+        }
+    }
+            
+    XSetWindowAttributes wa;
+    wa.background_pixel = nearest.pixel;
+    wa.override_redirect = True;
+	
+    Window w = XCreateWindow
+        (display(), mroot(screen),
+         0, 0, 1, 1, 0, CopyFromParent, CopyFromParent,
+         CopyFromParent, CWOverrideRedirect | CWBackPixel, &wa);
+
+    return w;
+}
+
+
+int WindowManager::shapeNumberWindow(Window w, int n, int minDigits)
+{
+    int i, x, y;
+    XRectangle r;
+    Boolean first = True;
+    char number[7];
+    sprintf(number, "%0*d", minDigits, n);
+
+    for (i = 0; i < (int)strlen(number); ++i) {
+	for (y = 0; y < 7; ++y) {
+	    for (x = 0; x < 5; ++x) {
+		if (numerals[number[i]-'0'][y][x] != ' ') {
+
+                    r.x = 10 + (i * 6 + x) * CONFIG_CHANNEL_NUMBER_SIZE;
+                    r.y = y * CONFIG_CHANNEL_NUMBER_SIZE;
+                    r.width = r.height = CONFIG_CHANNEL_NUMBER_SIZE;
+
+		    XShapeCombineRectangles
+                          (display(), w, ShapeBounding,
+                           0, 0, &r, 1, first ? ShapeSet : ShapeUnion,
+                           YXBanded);
+
+		    first = False;
+		}
+	    }
+	}
+    }
+
+    return (5 * CONFIG_CHANNEL_NUMBER_SIZE + 10) * strlen(number);
+}
+    
+    
 void WindowManager::flipChannel(Boolean statusOnly, Boolean flipDown,
 				Boolean quickFlip, Client *push)
 {
-    int x, y, i, sc;
+    int wid, i, sc;
     if (!CONFIG_CHANNEL_SURF) return;
 
-    for (sc = 0; sc < screensTotal(); sc++)
-    {
+    for (sc = 0; sc < screensTotal(); sc++) {
 	if (!m_channelWindow[sc]) {
-
-	XColor nearest, ideal;
-
-	    if (!XAllocNamedColor(display(), DefaultColormap(display(), sc),
-			      CONFIG_CHANNEL_NUMBER, &nearest, &ideal)) {
-	    
-		if (!XAllocNamedColor(display(), DefaultColormap(display(), sc),
-				  "black", &nearest, &ideal)) {
-		
-		fatal("Couldn't allocate green or black");
-	    }
-	}
-
-	XSetWindowAttributes wa;
-	wa.background_pixel = nearest.pixel;
-	wa.override_redirect = True;
-	
-	    m_channelWindow[sc] = XCreateWindow
-		(display(), mroot(sc),
-		 0, 0, 1, 1, 0, CopyFromParent, CopyFromParent,
-	     CopyFromParent, CWOverrideRedirect | CWBackPixel, &wa);
+            m_channelWindow[sc] = createNumberWindow(sc, CONFIG_CHANNEL_NUMBER);
 	}
     }
 

          
@@ 64,46 102,14 @@ void WindowManager::flipChannel(Boolean 
 	}
     }
 
-    XRectangle r;
-    Boolean first = True;
-    char number[7];
-    sprintf(number, "%d", nextChannel);
+    for (sc = 0; sc < screensTotal(); sc++) {
 
-    for (i = 0; i < (int)strlen(number); ++i) {
-	for (y = 0; y < 7; ++y) {
-	    for (x = 0; x < 5; ++x) {
-		if (numerals[number[i]-'0'][y][x] != ' ') {
-/*		    
-		    r.x = i * 110 + x * 20; r.y = y * 20;
-		    r.width = r.height = 20;
- */      
-                    r.x = 10 + (i * 6 + x) * CONFIG_CHANNEL_NUMBER_SIZE;
-                    r.y = y * CONFIG_CHANNEL_NUMBER_SIZE;
-                    r.width = r.height = CONFIG_CHANNEL_NUMBER_SIZE;
-                    for(sc = 0; sc < screensTotal(); sc++)
-                    {
-		    XShapeCombineRectangles
-                          (display(), m_channelWindow[sc], ShapeBounding,
-                           0, 0, &r, 1, first ? ShapeSet : ShapeUnion,
-                           YXBanded);
-                    }
-		    first = False;
-		}
-	    }
-	}
-    }
-
-    for(sc = 0; sc < screensTotal(); sc++) {
-/*
-        XMoveResizeWindow(display(), m_channelWindow[sc],
-			  DisplayWidth(display(), sc) - 30 -
-		      110 * strlen(number), 30, 500, 160);
- */
+        wid = shapeNumberWindow(m_channelWindow[sc], nextChannel, 1);
 
         XMoveResizeWindow(display(), m_channelWindow[sc],
-                          DisplayWidth(display(), sc) - 30 -
-                          (5 * CONFIG_CHANNEL_NUMBER_SIZE + 10) *
-                          strlen(number), 30, 500, 160);
+                          DisplayWidth(display(), sc) - 30 - wid,
+                          30, 500, 160);
+
 	XMapRaised(display(), m_channelWindow[sc]);
     }
 

          
@@ 230,3 236,33 @@ WindowManager::ensureChannelExists(int c
         netwmUpdateChannelList();
     }
 }
+
+void
+WindowManager::updateClock()
+{
+    time_t t;
+    struct tm *lt;
+
+    fprintf(stderr, "updateClock\n");
+
+    time(&t);
+    lt = localtime(&t);
+    
+    if (!m_clockWindow[0]) {
+        m_clockWindow[0] = createNumberWindow(0, CONFIG_CLOCK_NUMBER);
+        m_clockWindow[1] = createNumberWindow(0, CONFIG_CLOCK_NUMBER);
+    }
+
+    shapeNumberWindow(m_clockWindow[0], lt->tm_hour, 2);
+    shapeNumberWindow(m_clockWindow[1], lt->tm_min, 2);
+    
+    XMoveResizeWindow(display(), m_clockWindow[0],
+                      30, 30, 500, 160);
+    
+    XMoveResizeWindow(display(), m_clockWindow[1],
+                      30, 9 * CONFIG_CHANNEL_NUMBER_SIZE + 30, 500, 160);
+
+    XMapWindow(display(), m_clockWindow[0]);
+    XMapWindow(display(), m_clockWindow[1]);
+}
+

          
M Config.h +14 -8
@@ 79,8 79,7 @@ private:
 
 // What to run to get a new window (from the "New" menu option)
 #define CONFIG_NEW_WINDOW_LABEL "New"
-#define CONFIG_NEW_WINDOW_COMMAND "xterm"
-//#define CONFIG_NEW_WINDOW_COMMAND "/home/ccannam/.wmx/terminal"
+#define CONFIG_NEW_WINDOW_COMMAND "x-terminal-emulator"
 #define CONFIG_NEW_WINDOW_COMMAND_OPTIONS 0
 // or, for example,
 //#define CONFIG_NEW_WINDOW_COMMAND_OPTIONS "-ls","-sb","-sl","1024",0

          
@@ 329,6 328,7 @@ private:
 #define CONFIG_BUTTON_BACKGROUND  (DynamicConfig::config.frameBackground())
 #define CONFIG_BORDERS            "black"
 #define CONFIG_CHANNEL_NUMBER	  "green"
+#define CONFIG_CLOCK_NUMBER       "gray90"
 
 #define CONFIG_MENU_FOREGROUND    (DynamicConfig::config.tabForeground())
 #define CONFIG_MENU_BACKGROUND    (DynamicConfig::config.tabBackground())

          
@@ 369,10 369,10 @@ private:
 // FLIP_DELAY is the length of time the big green number stays in the
 // top-right when flipping channels, before the windows reappear.
 // QUICK_FLIP_DELAY is the equivalent figure used when flipping with
-// the Alt-Fn keys.  Milliseconds.
+// the Alt-Fn keys or mouse wheel.  Milliseconds.
 
 #define CONFIG_FLIP_DELAY         1000
-#define CONFIG_QUICK_FLIP_DELAY   200
+#define CONFIG_QUICK_FLIP_DELAY   500
 
 // Set MAD_FEEDBACK for skeletal representations of windows when
 // flicking through the client menu and changing channels.  The DELAY

          
@@ 385,16 385,16 @@ private:
 #define CONFIG_MAD_FEEDBACK       (DynamicConfig::config.useFeedback())
 #define CONFIG_FEEDBACK_DELAY     (DynamicConfig::config.feedbackDelay())
 
-// Groups are fun. you can bind a bunch of windows to a number key
-// and when you press CONFIG_ALT_KEY_MASK and the number key
-// all the windows of that group are raised.
-
 // Position of the geometry window:
 // X < 0 left, X > 0 right,  X = 0 center
 // Y < 0 top,  Y > 0 bottom, Y = 0 center
 #define CONFIG_GEOMETRY_X_POS     0
 #define CONFIG_GEOMETRY_Y_POS     0
 
+// Groups are fun. you can bind a bunch of windows to a number key
+// and when you press CONFIG_ALT_KEY_MASK and the number key
+// all the windows of that group are raised.
+
 // You bind a window to a group by pressing the 
 // CONFIG_ALT_KEY_MASK + CONFIG_GROUP_ADD + a number key
 

          
@@ 405,6 405,12 @@ private:
 #define CONFIG_GROUP_ADD          ControlMask  
 #define CONFIG_GROUP_REMOVE_ALL   ShiftMask
 
+// Set CLOCK if you want wmx to display a clock permanently in the
+// background at top-left of screen 0.  Use CONFIG_CLOCK_NUMBER
+// to control the colour of the clock digits.
+
+#define CONFIG_CLOCK              False
+
 // This lets you choose whether to keep the regular wmx
 // mouse button behaviour, or go w/ the GNOME-described one.
 // If this is True, the left mouse button (button1) lets you 

          
M Events.C +10 -2
@@ 144,11 144,19 @@ void WindowManager::nextEvent(XEvent *e)
 
     waiting:
 
-	if (m_channelChangeTime > 0) {
+	if (m_channelChangeTime > 0 || CONFIG_CLOCK) {
+
 	    Time t = timestamp(True);
-	    if (t >= m_channelChangeTime) {
+
+	    if (m_channelChangeTime > 0 && t >= m_channelChangeTime) {
 		instateChannel();
 	    }
+
+            if (CONFIG_CLOCK && (m_clockUpdateTime == CurrentTime ||
+                                 t >= m_clockUpdateTime + 60000)) {
+                m_clockUpdateTime = t;
+                updateClock();
+            }
 	}
 
 	if (QLength(m_display) > 0) {

          
M Manager.C +8 -1
@@ 291,6 291,8 @@ WindowManager::WindowManager(int argc, c
     m_currentChannel = 1;
     m_channelChangeTime = 0;
     m_channelWindow = 0;
+    m_clockWindow = 0;
+    m_clockUpdateTime = CurrentTime;
 
     Atoms::wm_state      = XInternAtom(m_display, "WM_STATE",            False);
     Atoms::wm_changeState= XInternAtom(m_display, "WM_CHANGE_STATE",     False);

          
@@ 534,7 536,8 @@ void WindowManager::initialiseScreen()
     m_defaultColormap = (Colormap *) malloc(m_screensTotal * sizeof(Colormap));
 //    m_minimumColormaps = (int *) malloc(m_screensTotal * sizeof(int));
     m_channelWindow = (Window *) malloc(m_screensTotal * sizeof(Window));
-    
+    m_clockWindow = (Window *) malloc(2 * sizeof(Window));
+
     for (i = 0 ; i < m_screensTotal ; i++) {
 
         m_screenNumber = i;

          
@@ 587,6 590,10 @@ void WindowManager::initialiseScreen()
         XSync(m_display, False);
     }
 
+    for (i = 0; i < 2; ++i) {
+        m_clockWindow[i] = 0;
+    }
+
     m_screenNumber = 0;
 }
 

          
M Manager.h +6 -0
@@ 152,12 152,18 @@ private:
     int m_currentChannel;	// from 1 to ...
     void flipChannel(Boolean statusOnly, Boolean flipDown,
 		     Boolean quickFlip, Client *push); // bleah!
+    Window createNumberWindow(int screen, const char *colour);
+    int shapeNumberWindow(Window w, int number, int minDigits); // returns width in pixels
     void instateChannel();
     void createNewChannel();
     void checkChannel(int);
     Time m_channelChangeTime;
     Window *m_channelWindow;
 
+    void updateClock();
+    Window *m_clockWindow;
+    Time m_clockUpdateTime;
+
     Boolean m_looping;
     int m_returnCode;