diff --git a/config.def.h b/config.def.h index 9855e21..bc883ad 100644 --- a/config.def.h +++ b/config.def.h @@ -1,6 +1,11 @@ -/* user and group to drop privileges to */ -static const char *user = "nobody"; +/* user and group to drop privileges to */ static const char *user = "nobody"; static const char *group = "nogroup"; +/*Font settings for the time text*/ +static const float textsize=64.0; +static const char* textfamily="serif"; +static const double textcolorred=255; +static const double textcolorgreen=255; +static const double textcolorblue=255; static const char *colorname[NUMCOLS] = { [INIT] = "black", /* after initialization */ diff --git a/config.mk b/config.mk index 514c236..c42e301 100644 --- a/config.mk +++ b/config.mk @@ -12,7 +12,7 @@ X11LIB = /usr/X11R6/lib # includes and libs INCS = -I. -I/usr/include -I${X11INC} -LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lcairo # flags CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H diff --git a/slock.c b/slock.c index b2f14e3..d370a00 100644 --- a/slock.c +++ b/slock.c @@ -5,6 +5,7 @@ #endif #include +#include #include #include #include @@ -18,7 +19,8 @@ #include #include #include - +#include +#include #include "arg.h" #include "util.h" @@ -44,6 +46,14 @@ struct xrandr { int errbase; }; +struct displayData{ + struct lock **locks; + Display* dpy; + int nscreens; + cairo_t **crs; + cairo_surface_t **surfaces; +}; +static pthread_mutex_t mutex= PTHREAD_MUTEX_INITIALIZER; #include "config.h" static void @@ -123,10 +133,46 @@ gethash(void) return hash; } +static void +refresh(Display *dpy, Window win , int screen, struct tm time, cairo_t* cr, cairo_surface_t* sfc) +{/*Function that displays given time on the given screen*/ + static char tm[24]=""; + int xpos,ypos; + xpos=DisplayWidth(dpy, screen)/4; + ypos=DisplayHeight(dpy, screen)/2; + sprintf(tm,"%02d/%02d/%d %02d:%02d",time.tm_mday,time.tm_mon + 1,time.tm_year+1900,time.tm_hour,time.tm_min); + XClearWindow(dpy, win); + cairo_set_source_rgb(cr, textcolorred, textcolorgreen, textcolorblue); + cairo_select_font_face(cr, textfamily, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(cr, textsize); + cairo_move_to(cr, xpos, ypos); + cairo_show_text(cr, tm); + cairo_surface_flush(sfc); + XFlush(dpy); +} +static void* +displayTime(void* input) +{ /*Thread that keeps track of time and refreshes it every 5 seconds */ + struct displayData* displayData=(struct displayData*)input; + while (1){ + pthread_mutex_lock(&mutex); /*Mutex to prevent interference with refreshing screen while typing password*/ + time_t rawtime; + time(&rawtime); + struct tm tm = *localtime(&rawtime); + for (int k=0;knscreens;k++){ + refresh(displayData->dpy, displayData->locks[k]->win, displayData->locks[k]->screen, tm,displayData->crs[k],displayData->surfaces[k]); + } + pthread_mutex_unlock(&mutex); + sleep(5); + } + return NULL; +} + + static void readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, - const char *hash) + const char *hash,cairo_t **crs,cairo_surface_t **surfaces) { XRRScreenChangeNotifyEvent *rre; char buf[32], passwd[256], *inputhash; @@ -189,16 +235,23 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, } color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); if (running && oldc != color) { + pthread_mutex_lock(&mutex); /*Stop the time refresh thread from interfering*/ for (screen = 0; screen < nscreens; screen++) { XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]); XClearWindow(dpy, locks[screen]->win); + time_t rawtime; + time(&rawtime); + refresh(dpy, locks[screen]->win,locks[screen]->screen, *localtime(&rawtime),crs[screen],surfaces[screen]); + /*Redraw the time after screen cleared*/ } + pthread_mutex_unlock(&mutex); oldc = color; } } else if (rr->active && ev.type == rr->evbase + RRScreenChangeNotify) { rre = (XRRScreenChangeNotifyEvent*)&ev; + pthread_mutex_lock(&mutex); /*Stop the time refresh thread from interfering.*/ for (screen = 0; screen < nscreens; screen++) { if (locks[screen]->win == rre->window) { if (rre->rotation == RR_Rotate_90 || @@ -212,6 +265,8 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, break; } } + + pthread_mutex_unlock(&mutex); } else { for (screen = 0; screen < nscreens; screen++) XRaiseWindow(dpy, locks[screen]->win); @@ -343,7 +398,7 @@ main(int argc, char **argv) { errno = 0; if (!crypt("", hash)) die("slock: crypt: %s\n", strerror(errno)); - + XInitThreads(); if (!(dpy = XOpenDisplay(NULL))) die("slock: cannot open display\n"); @@ -389,7 +444,33 @@ main(int argc, char **argv) { } /* everything is now blank. Wait for the correct password */ - readpw(dpy, &rr, locks, nscreens, hash); + pthread_t thredid; + /* Create Cairo drawables upon which the time will be shown. */ + struct displayData displayData; + cairo_surface_t **surfaces; + cairo_t **crs; + if (!(surfaces=calloc(nscreens, sizeof(cairo_surface_t*)))){ + die("Out of memory"); + } + if (!(crs=calloc(nscreens, sizeof(cairo_t*)))){ + die("Out of memory"); + } + for (int k=0;kwin; + int screen=locks[k]->screen; + XMapWindow(dpy, win); + surfaces[k]=cairo_xlib_surface_create(dpy, win, DefaultVisual(dpy, screen),DisplayWidth(dpy, screen) , DisplayHeight(dpy, screen)); + crs[k]=cairo_create(surfaces[k]); + } + displayData.dpy=dpy; + displayData.locks=locks; + displayData.nscreens=nscreens; + displayData.crs=crs; + displayData.surfaces=surfaces; + /*Start the thread that redraws time every 5 seconds*/ + pthread_create(&thredid, NULL, displayTime, &displayData); + /*Wait for the password*/ + readpw(dpy, &rr, locks, nscreens, hash,crs,surfaces); return 0; }