#include #include #include #include #include #include #include #include #include "client.h" static Display *display; static int scr_num; static Colormap cmap; static unsigned long black, notred, red, green, orange, grey; static unsigned long greenfeint, greyfeint; static Window root, toplevel; static Window machwin; static Window frame, holder; static Window slide1, slide2; static Pixmap pixmap1, pixmap2; static GC gc; static int winpos=0; static XFontStruct *font; static int th; static char *defgeom="116x76"; static int width=116; static int height=76; static int pixwidth=256; static int pixheight=100; static int frameheight; static int stripe=6; static int connectionfd; static int display_machstatus=VALUE_UNDEFINED; static int countdown=0; static int countup; static unsigned long machcol; static struct timeval state_change; static int vscale=1, new_vscale, new_vscale2; int screen_need_rescale=0; static int xid_rescale=0, xid_rescale_active=0; int xid_display_first=0, xid_display_last=-1; static int done_recalc; extern int port; static unsigned long alloc_col(char *name) { XColor exact, rgbdef; if (!XAllocNamedColor(display, cmap, name, &exact, &rgbdef)) { fprintf(stderr, "Failed to allocate %s\n", name); exit(1); } return exact.pixel; } void display_init(int argc, char *argv[]) { XWindowAttributes attr; XSetWindowAttributes setattr; XGCValues values; XSizeHints *sizehints; XClassHint *classhint; XWMHints *wmhints; char *title; char *blackname, *greenname; char *orangename, *redname; char *notredname, *greyname; char *greyfeintname, *greenfeintname; char *fontname; char *stripesize; char *geom; int x=0, y=0; int geomval, grav; char *portnumber; if (!(display=XOpenDisplay(displayname))) { fprintf(stderr, "Couldn't open display '%s'\n", XDisplayName(displayname)); exit(1); } options_xrdb(display); connectionfd=ConnectionNumber(display); scr_num=DefaultScreen(display); cmap=DefaultColormap(display, scr_num); root=RootWindow(display, scr_num); stripesize=options_get(".stripe", ".Stripe", "6"); stripe=str_to_int(stripesize, "stripe", 2, 63); free(stripesize); blackname=options_get(".foreground", ".Foreground", "black"); greenname=options_get(".ready", ".Ready", "green"); orangename=options_get(".standby", ".Standby", "orange"); redname=options_get(".alert", ".Alert", "red"); notredname=options_get(".alertFlash", ".AlertFlash", "white"); greyname=options_get(".background", ".Background", "grey"); greyfeintname=options_get(".feint", ".Feint", "light grey"); greenfeintname=options_get(".readyFeint", ".ReadyFeint",greyfeintname); portnumber=options_get(".port", ".Port", "400"); port=str_to_int(portnumber, "port", 1, 65535); free(portnumber); black=alloc_col(blackname); green=alloc_col(greenname); orange=alloc_col(orangename); red=alloc_col(redname); notred=alloc_col(notredname); grey=alloc_col(greyname); greyfeint=alloc_col(greyfeintname); greenfeint=alloc_col(greenfeintname); free(blackname); free(greenname); free(orangename); free(redname); free(notredname); free(greyname); free(greyfeintname); free(greenfeintname); sizehints=XAllocSizeHints(); sizehints->flags=PMaxSize|PResizeInc; sizehints->x=x; sizehints->y=y; sizehints->max_width=pixwidth; sizehints->max_height=pixheight+th; sizehints->width_inc=1; sizehints->height_inc=1; geom=options_get(".geometry", ".Geometry", NULL); geomval=XWMGeometry(display, scr_num, geom, defgeom, 1, sizehints, &x, &y, &width, &height, &grav); sizehints->flags |= PWinGravity; sizehints->win_gravity=grav; if (geomval & (XValue|YValue)) sizehints->flags |= USPosition; if (width<1) width=1; if (height<1) height=1; fontname=options_get(".font", ".Font", "fixed"); if (!(font=XLoadQueryFont(display, fontname))) { fprintf(stderr, "Couldn't load font '%s'\n", fontname); exit(1); } free(fontname); th=font->ascent+font->descent; if (width>pixwidth) pixwidth=width; if (height>pixheight) pixheight=height-th; toplevel=XCreateSimpleWindow(display, root, x,y,width,height, 1, black, notred); classhint=XAllocClassHint(); wmhints=XAllocWMHints(); classhint->res_name=progname; classhint->res_class="LoadMonitor"; wmhints->flags=InputHint|StateHint; wmhints->input=False; wmhints->initial_state=NormalState; XSetWMProperties(display, toplevel, NULL, NULL, argv, argc, sizehints, wmhints, classhint); XFree(sizehints); XFree(classhint); values.font=font->fid; gc=XCreateGC(display, toplevel, GCFont, &values); frameheight=height-th; frame=XCreateSimpleWindow(display, toplevel, 0, th, width, frameheight, 0, black, notred); machwin=XCreateSimpleWindow(display, toplevel, 0, 0, width, th, 0, black, grey); XSelectInput(display, toplevel, StructureNotifyMask); XSelectInput(display, machwin, ExposureMask|ButtonPressMask); if (!XGetWindowAttributes(display, frame, &attr)) { fprintf(stderr, "Couldn't get window attributes for frame\n"); exit(1); } pixmap1=XCreatePixmap(display, frame, pixwidth, pixheight, attr.depth); pixmap2=XCreatePixmap(display, frame, pixwidth, pixheight, attr.depth); holder=XCreateWindow(display, frame, 0, 0, 2*pixwidth, frameheight, 0, CopyFromParent, CopyFromParent, CopyFromParent, 0, &setattr); setattr.background_pixmap=pixmap1; slide1=XCreateWindow(display, holder, 0, 0, pixwidth, pixheight, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixmap, &setattr); setattr.background_pixmap=pixmap2; slide2=XCreateWindow(display, holder, pixwidth, 0, pixwidth, pixheight, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixmap, &setattr); XSetForeground(display, gc, grey); XFillRectangle(display, pixmap1, gc, 0, 0, pixwidth, pixheight); XFillRectangle(display, pixmap2, gc, 0, 0, pixwidth, pixheight); XSetForeground(display, gc, black); /* XDrawLine(display, pixmap1, gc, 0, 0, pixwidth, 0); XDrawLine(display, pixmap2, gc, 0, 0, pixwidth, 0); XDrawLine(display, pixmap1, gc, 0, stripe, pixwidth, stripe); XDrawLine(display, pixmap2, gc, 0, stripe, pixwidth, stripe); */ machcol=grey; title=malloc(16+strlen(leafname)); strcpy(title, "Load monitor ("); strcat(title, leafname); strcat(title, ")"); XStoreName(display, toplevel, title); free(title); XStoreName(display, machwin, "machine"); XStoreName(display, frame, "frame"); XStoreName(display, holder, "holder"); XStoreName(display, slide1, "slide1"); XStoreName(display, slide2, "slide2"); XMapSubwindows(display, holder); XMapSubwindows(display, frame); XMapSubwindows(display, toplevel); XMapWindow(display, toplevel); } void screen_rotate(int delta) { int newwinpos=(winpos+delta)%(2*pixwidth); if (newwinpos<0) newwinpos+=2*pixwidth; if (newwinpos>=pixwidth) { Window tempw; Pixmap tempp; XReparentWindow(display, slide1, frame, -winpos,0); XReparentWindow(display, slide2, frame, pixwidth-winpos,0); XMoveWindow(display, holder, -winpos, 0); XReparentWindow(display, slide1, holder, pixwidth, 0); XReparentWindow(display, slide2, holder, 0, 0); newwinpos-=pixwidth; tempw=slide1; slide1=slide2; slide2=tempw; tempp=pixmap1; pixmap1=pixmap2; pixmap2=tempp; } XMoveWindow(display, holder, -newwinpos, 0); winpos=newwinpos; xid_display_last+=delta; xid_display_first=xid_display_last-width; /* printf("screen_rotate: rescale xid_display_first: %i, xid_rescale: %i\n", xid_display_first, xid_rescale); */ if (xid_rescale_active && xid_display_first>xid_rescale) { /* printf("screen_rotate: rescale down\n"); */ xid_rescale_active=0; screen_need_rescale=1; new_vscale=new_vscale2; screen_recalc(); } } static void display_machwin(unsigned int col) { int boundary=width/2; char *name=field_name(); XRectangle rect = {0,0,0,0}; rect.width=boundary-1, rect.height=th; machcol=col; XSetWindowBackground(display, machwin, (machcol==green)?grey:machcol); XClearWindow(display, machwin); XSetForeground(display, gc, black); XSetClipRectangles(display, gc, 0, 0, &rect, 1, Unsorted); XDrawString(display, machwin, gc, 1, font->ascent, leafname, strlen(leafname)); rect.width=width-boundary-1; XSetClipRectangles(display, gc, boundary, 0, &rect, 1, Unsorted); XDrawString(display, machwin, gc, boundary+2, font->ascent, name, strlen(name)); XSetClipMask(display, gc, None); /* XDrawLine(display, machwin, gc, boundary, 0, boundary, th); */ } static void display_new_status(unsigned long col, int alert) { display_machwin(col); if (alert) { /* printf("Alert state change\n"); */ countdown=16; countup=1; gettimeofday(&state_change, NULL); } else { countdown=0; } } void screen_update(int xid) { unsigned int col=grey; unsigned int feint=greyfeint; double fvalue=0; int value=0; int offset; int status=VALUE_UNDEFINED; Pixmap pixmap=pixmap2; int i; int dense; offset=winpos-(xid_display_last-xid)+width-1-pixwidth; if (offset>=pixwidth) return; if (offset<0) { pixmap=pixmap1; offset+=pixwidth; } if (offset>=pixwidth) return; if (offset<0) return; status=value_type(xid); switch(status) { case VALUE_UNAVAILABLE: col=red; feint=greyfeint; fvalue=0; break; case VALUE_UNKNOWN: col=orange; feint=greyfeint; fvalue=0; break; case VALUE_KNOWN: col=green; feint=greenfeint; fvalue=value_get(xid); break; } if (fvalue>=vscale) { int new_new_vscale=(int)fvalue+1; /* printf("screen_update: rescale required, xid=%i\n", xid); */ if (!screen_need_rescale || new_new_vscale>new_vscale) { new_vscale=new_new_vscale; xid_rescale=xid; xid_rescale_active=0; } screen_need_rescale=1; } if (!xid_rescale_active && xid>xid_rescale && fvalue=frameheight-stripe); value=fvalue*(frameheight-stripe)/vscale; if (value>=frameheight-stripe) value=frameheight-stripe-1; XSetForeground(display, gc, dense?feint:col); XDrawLine(display, pixmap, gc, offset, 1, offset, stripe-1); if (value>0) XDrawLine(display, pixmap, gc, offset, frameheight-value, offset, frameheight); if (stripe+11 && !dense) { unsigned int col=feint; for (i=1; istripe) { if (y>=frameheight-value) { if (i==1 || col!=feint) XSetForeground(display, gc, col=feint); } else { if (i==1 || col!=greyfeint) XSetForeground(display, gc, col=greyfeint); } XDrawPoint(display, pixmap, gc, offset, y); } } } } void screen_recalc(void) { int xid; if (screen_need_rescale) { vscale=new_vscale; screen_need_rescale=0; } for (xid=xid_display_first; xid<=xid_display_last; xid++) screen_update(xid); if (screen_need_rescale) { vscale=new_vscale; screen_need_rescale=0; for (xid=xid_display_first; xid<=xid_display_last; xid++) screen_update(xid); } XClearWindow(display,slide1); XClearWindow(display,slide2); done_recalc=1; } static void display_pending(void) { while (XPending(display)) { XEvent event; XNextEvent(display, &event); if (event.type==Expose && event.xexpose.window==machwin && event.xexpose.count==0) { display_machwin(machcol); } if (event.type==ConfigureNotify && event.xconfigure.window==toplevel) { int delta_width=0, delta_height=0; if (width==event.xconfigure.width && height==event.xconfigure.height) continue; delta_width=event.xconfigure.width-width; delta_height=event.xconfigure.height-height; width=event.xconfigure.width; height=event.xconfigure.height; frameheight=height-th; if (delta_height) XResizeWindow(display, holder, 2*pixwidth, frameheight); XResizeWindow(display, frame, width, frameheight); if (delta_width) { XResizeWindow(display, machwin, width, th); display_machwin(machcol); xid_display_last+=delta_width; } done_recalc=0; if (delta_width) screen_rotate(-delta_width); if (!done_recalc) screen_recalc(); } if (event.type==ButtonPress && event.xbutton.window==machwin) { if (event.xbutton.button==Button3) field_prev(); else field_next(); display_machwin(machcol); screen_need_rescale=1; new_vscale=1; screen_recalc(); } } } void display_preselect(int *maxfd, fd_set *fds, fd_set *dummy, struct timeval *tvp) { dummy=dummy; /* Keep compiler quiet */ /* printf(" [display %i]", connectionfd); */ FD_SET(connectionfd, fds); if (*maxfd=1000000) { tv.tv_sec++; tv.tv_usec-=1000000; } tv_expire(tvp, &tv); } display_pending(); } void display_postselect(fd_set *fds, fd_set *dummy) { dummy=dummy; /* Keep compiler quiet */ if (!FD_ISSET(connectionfd, fds)) { struct timeval now, tv; gettimeofday(&now, NULL); if (countdown) { tv.tv_sec=state_change.tv_sec+countup/2-now.tv_sec; tv.tv_usec=state_change.tv_usec+500000*(countup&1) -now.tv_usec-1; if (tv.tv_usec<0) { tv.tv_sec--; tv.tv_usec+=1000000; } if (tv.tv_usec>=1000000) { tv.tv_sec++; tv.tv_usec-=1000000; } if (tv.tv_sec<0) { display_machwin((countup++&1)?notred:red); countdown--; } } return; } display_pending(); }