Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

revert a revert #4

Open
wants to merge 15 commits into from

2 participants

@polachok

Hi,
commit #7bc72f5dafa90eda6feae266009671a417efa939 reverted my _NET_WM_PARTIAL_STRUTS and DisplayWidth() stuff.
This is just a recommit (with a small bugfix).

I'll push more changes later (here's a screenshot of what I have now: http://ompldr.org/vYmczYQ).

and others added some commits
@ryanflannery Use default width of screen-width rather than hardcoded 1280.
From Alexander Polakov <polachok@gmail.com>
a521989
@ryanflannery Patch from Alexander Polakov <polachok@gmail.com> to add support
for window manager hints (specifically _NET_WM_PARTIAL_STRUTS).
ea97ef1
Alexander Polakov Skip 2 pixels from right and left
 Looks a bit better to me
a665234
Alexander Polakov Use COLOR_BLACK instead of BlackPixel() 04bb308
Alexander Polakov Center text vertically 53ad269
Alexander Polakov Store window name. This allows WM's to match on it. 0908adb
Alexander Polakov Make use of X Resource Database for colors
Correct lookup order (not implemented here):
 * classname in app-defaults directory
 * classname in XUSERFILESEARCHPATH & XAPPLRESDIR
 * XresourceManagerString() and ~/.Xdefaults
 * XENVIROMENT, if not set ~/.Xdefaults-hostname
 * command line.
We do only (3).
917c6f3
Alexander Polakov Add new color COLOR_GREY for future use a2d4e72
Alexander Polakov Inner border support
 * it's drawn inside the window
 * set width with -b (0 by default)
 * window border isn't used because some WMs reset it to 0
906b4c5
Alexander Polakov Make cpu_draw() to be like other *_draw functions 5a4def4
Alexander Polakov Introduce struct applet
 At the moment it contains applet drawing function and color argument.
 Can be extended for something more interesting. This allows us to
 iterate over an array of applets.
1472f54
Alexander Polakov Implement `grow-only' policy for applets
 So they don't move from left to right and back.
7bdc7b5
Alexander Polakov Use select instead of sleep() and handle Expose events 1d898ac
Alexander Polakov Invert swap detection logic (nswaps == 0 means no swap) ef704fd
@polachok polachok Change the order of colors to match XTerm resources 04ef8c8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 25, 2011
  1. Use default width of screen-width rather than hardcoded 1280.

    authored Alexander Polakov committed
    From Alexander Polakov <polachok@gmail.com>
  2. Patch from Alexander Polakov <polachok@gmail.com> to add support

    authored Alexander Polakov committed
    for window manager hints (specifically _NET_WM_PARTIAL_STRUTS).
  3. Skip 2 pixels from right and left

    Alexander Polakov authored
     Looks a bit better to me
  4. Use COLOR_BLACK instead of BlackPixel()

    Alexander Polakov authored
  5. Center text vertically

    Alexander Polakov authored
  6. Store window name. This allows WM's to match on it.

    Alexander Polakov authored
  7. Make use of X Resource Database for colors

    Alexander Polakov authored
    Correct lookup order (not implemented here):
     * classname in app-defaults directory
     * classname in XUSERFILESEARCHPATH & XAPPLRESDIR
     * XresourceManagerString() and ~/.Xdefaults
     * XENVIROMENT, if not set ~/.Xdefaults-hostname
     * command line.
    We do only (3).
  8. Add new color COLOR_GREY for future use

    Alexander Polakov authored
  9. Inner border support

    Alexander Polakov authored
     * it's drawn inside the window
     * set width with -b (0 by default)
     * window border isn't used because some WMs reset it to 0
  10. Make cpu_draw() to be like other *_draw functions

    Alexander Polakov authored
  11. Introduce struct applet

    Alexander Polakov authored
     At the moment it contains applet drawing function and color argument.
     Can be extended for something more interesting. This allows us to
     iterate over an array of applets.
  12. Implement `grow-only' policy for applets

    Alexander Polakov authored
     So they don't move from left to right and back.
  13. Use select instead of sleep() and handle Expose events

    Alexander Polakov authored
Commits on Nov 29, 2011
  1. Invert swap detection logic (nswaps == 0 means no swap)

    Alexander Polakov authored
Commits on Dec 3, 2012
  1. @polachok
This page is out of date. Refresh to see the latest.
Showing with 188 additions and 55 deletions.
  1. +31 −3 stats.c
  2. +2 −1  stats.h
  3. +4 −0 xstatbar.1
  4. +147 −51 xstatbar.c
  5. +4 −0 xstatbar.h
View
34 stats.c
@@ -443,7 +443,7 @@ sysinfo_update()
/* get swap status */
sysinfo.swap_used = sysinfo.swap_total = 0;
- if ((nswaps = swapctl(SWAP_NSWAP, 0, 0)) == 0) {
+ if ((nswaps = swapctl(SWAP_NSWAP, 0, 0)) != 0) {
if ((swapdev = calloc(nswaps, sizeof(*swapdev))) == NULL)
err(1, "sysinfo update: swapdev calloc failed (%d)", nswaps);
if (swapctl(SWAP_STATS, swapdev, nswaps) == -1)
@@ -512,7 +512,7 @@ sysinfo_close()
}
int
-cpu_draw(int cpu, XColor color, int x, int y)
+cpu_draw_one(int cpu, XColor color, int x, int y)
{
static char str[1000];
static char *cpuStateNames[] = { "u", "n", "s", "i", "I" };
@@ -588,6 +588,23 @@ cpu_draw(int cpu, XColor color, int x, int y)
}
int
+cpu_draw(XColor color, int x, int y)
+{
+ int cpu, startx;
+ int nw, spacing = 10;
+ static int width = 0;
+
+ startx = x;
+ for (cpu = 0; cpu < sysinfo.ncpu; cpu++) {
+ nw = cpu_draw_one(cpu, COLOR_WHITE, x, y) + spacing;
+ width = nw > width ? nw : width;
+ x += width;
+ }
+ x -= spacing; /* trailing spacing */
+ return x - startx;
+}
+
+int
mem_draw(XColor color, int x, int y)
{
int h, total;
@@ -696,7 +713,18 @@ time_draw(XColor color, int x, int y)
strftime(timestr, sizeof(timestr), time_fmt, localtime(&now));
/* XXX hack to right-align it - rethink a more general way for this */
- width = XTextWidth(XINFO.font, timestr, strlen(timestr));
+ width = XTextWidth(XINFO.font, timestr, strlen(timestr)) + 2;
return render_text(color, XINFO.width - width, y, timestr);
}
+int
+border_draw(XColor color, int x, int y)
+{
+ int bw = XINFO.border;
+ if (!bw)
+ return 0;
+ XSetForeground(XINFO.disp, XINFO.gc, color.pixel);
+ XSetLineAttributes(XINFO.disp, XINFO.gc, bw, LineSolid, CapNotLast, JoinMiter);
+ XDrawRectangle(XINFO.disp, XINFO.buf, XINFO.gc, bw/2, bw/2, XINFO.width-bw, XINFO.height-bw);
+ return 0;
+}
View
3  stats.h
@@ -131,9 +131,10 @@ void sysinfo_close();
int volume_draw(XColor c, int x, int y);
int power_draw(XColor c, int x, int y);
-int cpu_draw(int cpu, XColor c, int x, int y);
+int cpu_draw(XColor c, int x, int y);
int mem_draw(XColor c, int x, int y);
int procs_draw(XColor c, int x, int y);
int time_draw(XColor c, int x, int y);
+int border_draw(XColor c, int x, int y);
#endif
View
4 xstatbar.1
@@ -68,6 +68,10 @@ edit the source.
.Pp
The following options are supported:
.Bl -tag -width Fl
+.It Fl b Ar width
+Inner border width, in pixels.
+.Pp
+The default is 0.
.It Fl x Ar offset
The x coordinate, in pixels, of the upper-left corner of the window.
.Pp
View
198 xstatbar.c
@@ -13,6 +13,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/types.h>
+#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -30,7 +32,7 @@
xinfo_t XINFO;
XColor COLOR_RED, COLOR_GREEN, COLOR_BLUE,
COLOR_YELLOW, COLOR_MAGENTA, COLOR_CYAN,
- COLOR_WHITE, COLOR_BLACK;
+ COLOR_WHITE, COLOR_BLACK, COLOR_GREY;
/* signal flags */
@@ -42,9 +44,22 @@ void signal_handler(int sig);
void process_signals();
void cleanup();
void usage(const char *pname);
-void setup_x(int x, int y, int w, int h, const char *font);
+void setup_x(int x, int y, int w, int h, int b, const char *font);
void draw();
+struct applet {
+ int (*draw) (XColor, int, int);
+ XColor *color;
+ int width;
+} applets[] = {
+ { cpu_draw, &COLOR_WHITE },
+ { mem_draw, &COLOR_WHITE },
+ { procs_draw, &COLOR_WHITE },
+ { power_draw, &COLOR_WHITE },
+ { volume_draw, &COLOR_WHITE },
+ { time_draw, &COLOR_CYAN },
+ { border_draw, &COLOR_GREY },
+};
int
main (int argc, char *argv[])
@@ -52,21 +67,32 @@ main (int argc, char *argv[])
const char *errstr;
char *font;
char ch;
- int x, y, w, h;
+ int x, y, w, h, b;
int sleep_seconds;
+ fd_set rd;
+ int xfd, rv;
+ struct timeval tv;
+ XEvent ev;
/* set defaults */
x = 0;
y = 0;
- w = 1280;
+ w = 0;
h = 13;
+ b = 0;
font = "*-fixed-*-9-*";
time_fmt = "%a %d %b %Y %I:%M:%S %p";
sleep_seconds = 1;
/* parse command line */
- while ((ch = getopt(argc, argv, "x:y:w:h:s:f:t:T")) != -1) {
+ while ((ch = getopt(argc, argv, "b:x:y:w:h:s:f:t:T")) != -1) {
switch (ch) {
+ case 'b':
+ b = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "illegal b value \"%s\": %s", optarg, errstr);
+ break;
+
case 'x':
x = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr)
@@ -127,26 +153,43 @@ main (int argc, char *argv[])
sysinfo_init(45);
/* setup X window */
- setup_x(x, y, w, h, font);
+ setup_x(x, y, w, h, b, font);
+ xfd = ConnectionNumber(XINFO.disp);
/* shutdown function */
- signal(SIGINT, signal_handler);
-
- while (1) {
-
- /* handle any signals */
- process_signals();
+ signal(SIGINT, signal_handler);
- /* update stats */
- volume_update();
- power_update();
- sysinfo_update();
+ volume_update();
+ power_update();
+ sysinfo_update();
- /* draw */
- draw();
-
- /* sleep */
- sleep(sleep_seconds);
+ while (1) {
+ tv.tv_sec = sleep_seconds;
+ tv.tv_usec = 0;
+ FD_ZERO(&rd);
+ FD_SET(xfd, &rd);
+
+ rv = select(xfd + 1, &rd, NULL, NULL, &tv);
+ if (rv == -1) {
+ process_signals();
+ perror("select()");
+ return 1;
+ } else if (rv > 0) { /* X event */
+ while (XPending(XINFO.disp)) {
+ XNextEvent(XINFO.disp, &ev);
+ if (ev.type == Expose)
+ draw();
+ }
+ } else if (rv == 0) { /* timeout */
+ /* handle any signals */
+ process_signals();
+ /* update stats */
+ volume_update();
+ power_update();
+ sysinfo_update();
+ /* draw */
+ draw();
+ }
}
/* UNREACHABLE */
@@ -193,6 +236,7 @@ void
cleanup()
{
/* x teardown */
+ XrmDestroyDatabase(XINFO.xrdb);
XClearWindow(XINFO.disp, XINFO.win);
XFreePixmap(XINFO.disp, XINFO.buf);
XDestroyWindow(XINFO.disp, XINFO.win);
@@ -206,51 +250,84 @@ cleanup()
exit(0);
}
+/* get resource from X Resource database */
+const char *
+get_resource(const char *resource)
+{
+ static char name[256], class[256], *type;
+ XrmValue value;
+
+ if (!XINFO.xrdb)
+ return NULL;
+#define RESCLASS "xstatbar"
+#define RESNAME "XStatBar"
+ snprintf(name, sizeof(name), "%s.%s", RESNAME, resource);
+ snprintf(class, sizeof(class), "%s.%s", RESCLASS, resource);
+ XrmGetResource(XINFO.xrdb, name, class, &type, &value);
+ if (value.addr)
+ return value.addr;
+ return NULL;
+}
+
/* setup all colors used */
void
setup_colors()
{
- static char *color_names[] = { "red", "green", "blue", "yellow",
- "magenta", "cyan", "white", "black" };
+ static char *color_names[] = { "black", "red", "green", "blue", "yellow",
+ "magenta", "cyan", "white", "grey" };
- static XColor *xcolors[] = { &COLOR_RED, &COLOR_GREEN, &COLOR_BLUE,
- &COLOR_YELLOW, &COLOR_MAGENTA, &COLOR_CYAN,
- &COLOR_WHITE, &COLOR_BLACK };
+ static XColor *xcolors[] = { &COLOR_BLACK, &COLOR_RED, &COLOR_GREEN,
+ &COLOR_BLUE, &COLOR_YELLOW, &COLOR_MAGENTA, &COLOR_CYAN,
+ &COLOR_WHITE, &COLOR_GREY };
- const int num_colors = 8;
+ const int num_colors = 9;
+ const char *color;
+ char resname[8];
int i;
Colormap cm;
cm = DefaultColormap(XINFO.disp, 0);
for (i = 0; i < num_colors; i++) {
- if (XParseColor(XINFO.disp, cm, color_names[i], xcolors[i]) == 0)
- errx(1, "failed to parse color \"%s\"", color_names[i]);
+ snprintf(resname, sizeof(resname), "color%d", i);
+ color = get_resource(resname);
+ if (XParseColor(XINFO.disp, cm, color ? color : color_names[i], xcolors[i]) == 0)
+ errx(1, "failed to parse color \"%s\"", color ? color : color_names[i]);
if (XAllocColor(XINFO.disp, cm, xcolors[i]) == 0)
- errx(1, "failed to allocate color \"%s\"", color_names[i]);
+ errx(1, "failed to allocate color \"%s\"", color ? color : color_names[i]);
}
}
/* setup x window */
void
-setup_x(int x, int y, int w, int h, const char *font)
+setup_x(int x, int y, int w, int h, int b, const char *font)
{
XSetWindowAttributes x11_window_attributes;
+ Atom type;
+ unsigned long struts[12];
+ char *xrms = NULL;
/* open display */
if (!(XINFO.disp = XOpenDisplay(NULL)))
errx(1, "can't open X11 display.");
-
+ /* initialize resource manager */
+ XrmInitialize();
/* setup various defaults/settings */
XINFO.screen = DefaultScreen(XINFO.disp);
- XINFO.width = w;
+ XINFO.width = w ? w : DisplayWidth(XINFO.disp, XINFO.screen);
XINFO.height = h;
+ XINFO.border = b;
XINFO.depth = DefaultDepth(XINFO.disp, XINFO.screen);
XINFO.vis = DefaultVisual(XINFO.disp, XINFO.screen);
XINFO.gc = DefaultGC(XINFO.disp, XINFO.screen);
- x11_window_attributes.override_redirect = 1;
-
+ x11_window_attributes.event_mask = ExposureMask;
+ x11_window_attributes.override_redirect = 0;
+ if(!(XINFO.xrdb = XrmGetDatabase(XINFO.disp))) {
+ xrms = XResourceManagerString(XINFO.disp);
+ if (xrms)
+ XINFO.xrdb = XrmGetStringDatabase(xrms);
+ }
/* create window */
XINFO.win = XCreateWindow(
XINFO.disp, DefaultRootWindow(XINFO.disp),
@@ -258,9 +335,28 @@ setup_x(int x, int y, int w, int h, const char *font)
XINFO.width, XINFO.height,
1,
CopyFromParent, InputOutput, XINFO.vis,
- CWOverrideRedirect, &x11_window_attributes
+ CWOverrideRedirect|CWEventMask, &x11_window_attributes
);
+ /* setup window manager hints */
+ type = XInternAtom(XINFO.disp, "_NET_WM_WINDOW_TYPE_DOCK", False);
+ XChangeProperty(XINFO.disp, XINFO.win, XInternAtom(XINFO.disp, "_NET_WM_WINDOW_TYPE", False),
+ XA_ATOM, 32, PropModeReplace, (unsigned char*)&type, 1);
+ bzero(struts, sizeof(struts));
+ enum { left, right, top, bottom, left_start_y, left_end_y, right_start_y,
+ right_end_y, top_start_x, top_end_x, bottom_start_x, bottom_end_x };
+ if (y <= DisplayHeight(XINFO.disp, XINFO.screen)/2) {
+ struts[top] = y + XINFO.height;
+ struts[top_start_x] = x;
+ struts[top_end_x] = x + XINFO.width;
+ } else {
+ struts[bottom] = DisplayHeight(XINFO.disp, XINFO.screen) - y;
+ struts[bottom_start_x] = x;
+ struts[bottom_end_x] = x + XINFO.width;
+ }
+ XChangeProperty(XINFO.disp, XINFO.win, XInternAtom(XINFO.disp, "_NET_WM_STRUT_PARTIAL", False),
+ XA_CARDINAL, 32, PropModeReplace, (unsigned char*)struts, 12);
+
/* create pixmap used for double buffering */
XINFO.buf = XCreatePixmap(
XINFO.disp, DefaultRootWindow(XINFO.disp),
@@ -275,9 +371,11 @@ setup_x(int x, int y, int w, int h, const char *font)
XSetFont(XINFO.disp, XINFO.gc, XINFO.font->fid);
+ XStoreName(XINFO.disp, XINFO.win, "xstatbar");
/* connect window to display */
XMapWindow(XINFO.disp, XINFO.win);
+ XMoveWindow(XINFO.disp, XINFO.win, x, y);
/* setup colors */
setup_colors();
}
@@ -298,27 +396,25 @@ void
draw()
{
static int spacing = 10;
- int x, y;
- int cpu;
+ int x, y, h, i, w;
/* paint over the existing pixmap */
- XSetForeground(XINFO.disp, XINFO.gc, BlackPixel(XINFO.disp, XINFO.screen));
+ XSetForeground(XINFO.disp, XINFO.gc, COLOR_BLACK.pixel);
XFillRectangle(XINFO.disp, XINFO.buf, XINFO.gc,
0, 0, XINFO.width, XINFO.height);
/* determine starting x and y */
- y = XINFO.height - XINFO.font->descent;
- x = 0;
-
- /* start drawing stats */
- for (cpu = 0; cpu < sysinfo.ncpu; cpu++)
- x += cpu_draw(cpu, COLOR_WHITE, x, y) + spacing;
-
- x += mem_draw(COLOR_WHITE, x, y) + spacing;
- x += procs_draw(COLOR_WHITE, x, y) + spacing;
- x += power_draw(COLOR_WHITE, x, y) + spacing;
- x += volume_draw(COLOR_WHITE, x, y) + spacing;
- time_draw(COLOR_CYAN, x, y);
+ h = XINFO.font->ascent + XINFO.font->descent;
+ y = (XINFO.height / 2) - (h / 2) + XINFO.font->ascent;
+ x = 2;
+
+ /* draw stats */
+ for (i = 0; i < sizeof(applets)/sizeof(applets[0]); i++) {
+ w = applets[i].draw(*(applets[i].color), x, y);
+ if (w > applets[i].width)
+ applets[i].width = w + spacing;
+ x += applets[i].width;
+ }
/* copy the buffer to the window and flush */
XCopyArea(XINFO.disp, XINFO.buf, XINFO.win, XINFO.gc,
View
4 xstatbar.h
@@ -20,6 +20,8 @@
/* X */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Xresource.h>
#include <X11/extensions/shape.h>
/* structure to wrap all necessary x stuff */
@@ -30,11 +32,13 @@ typedef struct xinfo {
Visual *vis;
GC gc;
XFontStruct *font;
+ XrmDatabase xrdb;
int screen;
int depth;
unsigned int width;
unsigned int height;
+ unsigned int border;
} xinfo_t;
extern xinfo_t XINFO;
Something went wrong with that request. Please try again.