a small clock for X11 that displays time as pixels
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

initial revision

jcs 20ac7567

+281
+34
Makefile
··· 1 + # $Id: Makefile,v 1.1 2005/06/28 21:05:19 jcs Exp $ 2 + # vim:ts=8 3 + 4 + CC = cc 5 + CFLAGS = -O2 -Wall -Wunused -Wmissing-prototypes -Wstrict-prototypes 6 + 7 + PREFIX = /usr/local 8 + BINDIR = $(DESTDIR)$(PREFIX)/bin 9 + 10 + INSTALL_PROGRAM = install -s 11 + 12 + X11BASE = /usr/X11R6 13 + INCLUDES= -I$(X11BASE)/include 14 + LDPATH = -L$(X11BASE)/lib 15 + LIBS = -lX11 16 + 17 + PROG = pixelclock 18 + OBJS = pixelclock.o 19 + 20 + all: $(PROG) 21 + 22 + $(PROG): $(OBJS) 23 + $(CC) $(OBJS) $(LDPATH) $(LIBS) -o $@ 24 + 25 + $(OBJS): *.o 26 + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ 27 + 28 + install: all 29 + $(INSTALL_PROGRAM) $(PROG) $(BINDIR) 30 + 31 + clean: 32 + rm -f $(PROG) $(OBJS) 33 + 34 + .PHONY: all install clean
+247
pixelclock.c
··· 1 + /* vim:ts=8 2 + * $Id: pixelclock.c,v 1.1 2005/06/28 21:05:19 jcs Exp $ 3 + * 4 + * pixelclock 5 + * a different way of looking at time 6 + * 7 + * Copyright (c) 2005 joshua stein <jcs@jcs.org> 8 + * 9 + * Redistribution and use in source and binary forms, with or without 10 + * modification, are permitted provided that the following conditions 11 + * are met: 12 + * 13 + * 1. Redistributions of source code must retain the above copyright 14 + * notice, this list of conditions and the following disclaimer. 15 + * 2. Redistributions in binary form must reproduce the above copyright 16 + * notice, this list of conditions and the following disclaimer in the 17 + * documentation and/or other materials provided with the distribution. 18 + * 3. The name of the author may not be used to endorse or promote products 19 + * derived from this software without specific prior written permission. 20 + * 21 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 + */ 32 + 33 + #include <err.h> 34 + #include <getopt.h> 35 + #include <signal.h> 36 + #include <stdio.h> 37 + #include <stdlib.h> 38 + #include <string.h> 39 + #include <time.h> 40 + #include <unistd.h> 41 + #include <sys/types.h> 42 + 43 + #include <X11/Xlib.h> 44 + #include <X11/Xutil.h> 45 + 46 + struct xinfo { 47 + Display* dpy; 48 + int dpy_width, dpy_height; 49 + 50 + int screen; 51 + 52 + Window win; 53 + 54 + int width; 55 + 56 + GC gc; 57 + 58 + Colormap win_colormap; 59 + } x; 60 + 61 + extern char *__progname; 62 + 63 + /* so our window manager knows us */ 64 + char* win_name = "pixelclock"; 65 + 66 + /* hours to highlight (start work, lunch, etc.) */ 67 + int hihours[] = { 9, 12, 17 }; 68 + 69 + const struct option longopts[] = { 70 + { "display", required_argument, NULL, 'd' }, 71 + { "width", required_argument, NULL, 'w' }, 72 + 73 + { NULL, 0, NULL, 0 } 74 + }; 75 + 76 + long getcolor(const char *); 77 + void handler(int sig); 78 + void init_x(const char *); 79 + void usage(void); 80 + 81 + int 82 + main(int argc, char* argv[]) 83 + { 84 + char *display = NULL, *p; 85 + int c, hi, y, z; 86 + int hourtick, lastpos = -1, newpos = 0; 87 + 88 + struct timeval tv[2]; 89 + time_t now; 90 + struct tm *t; 91 + 92 + bzero(&x, sizeof(struct xinfo)); 93 + 94 + /* default clock width */ 95 + x.width = 3; 96 + 97 + while ((c = getopt_long_only(argc, argv, "", longopts, NULL)) != -1) { 98 + switch (c) { 99 + case 'd': 100 + display = optarg; 101 + break; 102 + 103 + case 'w': 104 + x.width = strtol(optarg, &p, 10); 105 + if (*p || x.width < 1) 106 + errx(1, "illegal value -- %s", optarg); 107 + /* NOTREACHED */ 108 + break; 109 + 110 + default: 111 + usage(); 112 + /* NOTREACHED */ 113 + } 114 + } 115 + 116 + init_x(display); 117 + 118 + signal(SIGINT, handler); 119 + signal(SIGTERM, handler); 120 + 121 + /* each hour will be this many pixels away */ 122 + hourtick = x.dpy_height / 24; 123 + 124 + for (;;) { 125 + if (gettimeofday(&tv[0], NULL)) 126 + errx(1, "gettimeofday"); 127 + /* NOTREACHED */ 128 + 129 + now = tv[0].tv_sec; 130 + if ((t = localtime(&now)) == NULL) 131 + errx(1, "localtime"); 132 + /* NOTREACHED */ 133 + 134 + newpos = (hourtick * t->tm_hour) + 135 + (float)(((float)t->tm_min / 60.0) * hourtick) - 3; 136 + 137 + if (newpos != lastpos) { 138 + XClearWindow(x.dpy, x.win); 139 + 140 + XSetForeground(x.dpy, x.gc, getcolor("yellow")); 141 + XFillRectangle(x.dpy, x.win, x.gc, 142 + 0, newpos, 143 + x.width, 6); 144 + 145 + /* draw the hour marks */ 146 + for (y = 1; y <= 23; y++) { 147 + hi = 0; 148 + for (z = 0; z < sizeof(&hihours); z++) 149 + if (y == hihours[z]) { 150 + hi = 1; 151 + break; 152 + } 153 + 154 + if (hi) 155 + XSetForeground(x.dpy, x.gc, 156 + getcolor("green")); 157 + else 158 + XSetForeground(x.dpy, x.gc, 159 + getcolor("blue")); 160 + 161 + XFillRectangle(x.dpy, x.win, x.gc, 162 + 0, (y * hourtick), 163 + x.width, 2); 164 + } 165 + 166 + lastpos = newpos; 167 + 168 + XFlush(x.dpy); 169 + } 170 + 171 + sleep(1); 172 + } 173 + 174 + exit(1); 175 + } 176 + 177 + void 178 + init_x(const char *display) 179 + { 180 + int rc; 181 + XGCValues values; 182 + XTextProperty win_name_prop; 183 + 184 + if (!(x.dpy = XOpenDisplay(display))) 185 + errx(1, "Unable to open display %s", XDisplayName(display)); 186 + /* NOTREACHED */ 187 + 188 + x.screen = DefaultScreen(x.dpy); 189 + 190 + x.dpy_width = DisplayWidth(x.dpy, x.screen); 191 + x.dpy_height = DisplayHeight(x.dpy, x.screen); 192 + 193 + x.win_colormap = DefaultColormap(x.dpy, DefaultScreen(x.dpy)); 194 + 195 + x.win = XCreateSimpleWindow(x.dpy, RootWindow(x.dpy, x.screen), 196 + x.dpy_width - x.width, 0, 197 + x.width, x.dpy_height, 198 + 0, 199 + BlackPixel(x.dpy, x.screen), 200 + BlackPixel(x.dpy, x.screen)); 201 + 202 + if (!(x.gc = XCreateGC(x.dpy, x.win, 0, &values))) 203 + errx(1, "XCreateGC"); 204 + /* NOTREACHED */ 205 + 206 + if (!(rc = XStringListToTextProperty(&win_name, 1, &win_name_prop))) 207 + errx(1, "XStringListToTextProperty"); 208 + /* NOTREACHED */ 209 + 210 + XSetWMName(x.dpy, x.win, &win_name_prop); 211 + 212 + XMapWindow(x.dpy, x.win); 213 + 214 + XFlush(x.dpy); 215 + XSync(x.dpy, False); 216 + } 217 + 218 + long 219 + getcolor(const char *color) 220 + { 221 + int rc; 222 + 223 + XColor tcolor; 224 + 225 + if (!(rc = XAllocNamedColor(x.dpy, x.win_colormap, color, &tcolor, 226 + &tcolor))) 227 + errx(1, "can't allocate %s", color); 228 + 229 + return tcolor.pixel; 230 + } 231 + 232 + void 233 + handler(int sig) 234 + { 235 + XCloseDisplay(x.dpy); 236 + 237 + exit(0); 238 + /* NOTREACHED */ 239 + } 240 + 241 + void 242 + usage(void) 243 + { 244 + fprintf(stderr, "usage: %s %s\n", __progname, 245 + "[-display host:dpy] [-width]"); 246 + exit(1); 247 + }