diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 35b09ce..dbc28bf 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,8 @@ Version 1.0 ---------------------------------------------------------------------- +2008-10-04: + * first version with visual feedback (still rough) + 2008-09-13: * disallow running multiple instances on the same xserver at the same time diff --git a/README.txt b/README.txt index 58150d1..1fbe642 100644 --- a/README.txt +++ b/README.txt @@ -1,11 +1,11 @@ ALOCK(1) ======== Mathias Gumz -v1.0, 24 June 2008 +v1.0, 04 October 2008 NAME ---- -alock - locks the local X display until a password is entered. +alock - locks the local X display until the correct password is entered. SYNOPSIS -------- @@ -13,12 +13,19 @@ SYNOPSIS DESCRIPTION ----------- -'alock' locks the X server till the user enters a password at the -keyboard. If the authentification was successful the X server is +'alock' locks the X server until the user enters the correct password at the +keyboard. If the authentification was successful, the X server is unlocked and the user can continue to work. 'alock' does not provide fancy animations like 'xlock' and 'xscreensaver' -and never will. Its just for locking the current X session. +and never will. It's just for locking the current X session. + +When 'alock' is started it just waits for the first keypress. This first +keypress is to indicate that the user now wants to type in the password. +A colored frame is draw around the screen and the user can now type in +his password. If it was typed in incorrectly, the colored frame turns red and +the user has to wait a certain timeout. Then he can activate the typeing mode +again. OPTIONS ------- diff --git a/alock.txt b/alock.txt index 58150d1..1fbe642 100644 --- a/alock.txt +++ b/alock.txt @@ -1,11 +1,11 @@ ALOCK(1) ======== Mathias Gumz -v1.0, 24 June 2008 +v1.0, 04 October 2008 NAME ---- -alock - locks the local X display until a password is entered. +alock - locks the local X display until the correct password is entered. SYNOPSIS -------- @@ -13,12 +13,19 @@ SYNOPSIS DESCRIPTION ----------- -'alock' locks the X server till the user enters a password at the -keyboard. If the authentification was successful the X server is +'alock' locks the X server until the user enters the correct password at the +keyboard. If the authentification was successful, the X server is unlocked and the user can continue to work. 'alock' does not provide fancy animations like 'xlock' and 'xscreensaver' -and never will. Its just for locking the current X session. +and never will. It's just for locking the current X session. + +When 'alock' is started it just waits for the first keypress. This first +keypress is to indicate that the user now wants to type in the password. +A colored frame is draw around the screen and the user can now type in +his password. If it was typed in incorrectly, the colored frame turns red and +the user has to wait a certain timeout. Then he can activate the typeing mode +again. OPTIONS ------- diff --git a/src/GNUmakefile b/src/GNUmakefile index 51dc973..83b0401 100644 --- a/src/GNUmakefile +++ b/src/GNUmakefile @@ -28,7 +28,7 @@ LDFLAGS ?= LIBS ?= -lX11 ########################## -SRC = alock.c alock_utils.c \ +SRC = alock.c alock_utils.c alock_frame.c \ auth_none.c \ bg_none.c bg_blank.c \ cursor_none.c cursor_glyph.c cursor_theme.c diff --git a/src/SConscript b/src/SConscript index a949827..df6f6f3 100644 --- a/src/SConscript +++ b/src/SConscript @@ -5,7 +5,7 @@ # ########################################################## -alock_sources = [ 'alock.c', 'alock_utils.c' ] +alock_sources = [ 'alock.c', 'alock_utils.c', 'alock_frame.c' ] auth_sources = [ 'auth_none.c' ] bg_sources = [ 'bg_none.c', 'bg_blank.c' ] diff --git a/src/alock.c b/src/alock.c index 94b99ce..e6919d3 100644 --- a/src/alock.c +++ b/src/alock.c @@ -11,6 +11,7 @@ \* ---------------------------------------------------------------- */ #include "alock.h" +#include "alock_frame.h" #include #include @@ -21,6 +22,7 @@ #include #include #include +#include /*----------------------------------------------*\ \*----------------------------------------------*/ @@ -120,7 +122,7 @@ static void displayUsage() { /*------------------------------------------------------------------*\ \*------------------------------------------------------------------*/ -static void initXInfo(struct aXInfo* xinfo) { +static void initXInfo(struct aXInfo* xi) { Display* dpy = XOpenDisplay(NULL); @@ -130,101 +132,173 @@ static void initXInfo(struct aXInfo* xinfo) { } { - xinfo->display = dpy; - xinfo->pid_atom = XInternAtom(dpy, "_ALOCK_PID", False); - xinfo->nr_screens = ScreenCount(dpy); - xinfo->window = (Window*)calloc((size_t)xinfo->nr_screens, sizeof(Window)); - xinfo->root = (Window*)calloc((size_t)xinfo->nr_screens, sizeof(Window)); - xinfo->colormap = (Colormap*)calloc((size_t)xinfo->nr_screens, sizeof(Colormap)); - xinfo->cursor = (Cursor*)calloc((size_t)xinfo->nr_screens, sizeof(Cursor)); + xi->display = dpy; + xi->pid_atom = XInternAtom(dpy, "_ALOCK_PID", False); + xi->nr_screens = ScreenCount(dpy); + xi->window = (Window*)calloc((size_t)xi->nr_screens, sizeof(Window)); + xi->root = (Window*)calloc((size_t)xi->nr_screens, sizeof(Window)); + xi->colormap = (Colormap*)calloc((size_t)xi->nr_screens, sizeof(Colormap)); + xi->cursor = (Cursor*)calloc((size_t)xi->nr_screens, sizeof(Cursor)); + xi->width_of_root = calloc(xi->nr_screens, sizeof(int)); + xi->height_of_root = calloc(xi->nr_screens, sizeof(int)); } { + XWindowAttributes xgwa; int scr; - for (scr = 0; scr < xinfo->nr_screens; scr++) { - xinfo->window[scr] = None; - xinfo->root[scr] = RootWindow(dpy, scr); - xinfo->colormap[scr] = DefaultColormap(dpy, scr); + for (scr = 0; scr < xi->nr_screens; scr++) { + xi->window[scr] = None; + xi->root[scr] = RootWindow(dpy, scr); + xi->colormap[scr] = DefaultColormap(dpy, scr); + + XGetWindowAttributes(dpy, xi->root[scr], &xgwa); + xi->width_of_root[scr] = xgwa.width; + xi->height_of_root[scr] = xgwa.height; } } } -static int eventLoop(struct aOpts* opts, struct aXInfo* xinfo) { +enum { + INITIAL = 0, + READY, + TYPING, + WRONG +}; +static void visualFeedback(struct aFrame* frame, int mode) { + + static int old_mode = INITIAL; + int redraw = 0; + + if (old_mode != mode) + redraw = 1; + + old_mode = mode; + + switch (mode) { + case READY: + if (redraw) { + alock_draw_frame(frame, "green"); + } + fprintf(stderr, "READY\n"); + break; + case TYPING: + fprintf(stderr, "TYPING\n"); + break; + case WRONG: + if (redraw) { + alock_draw_frame(frame, "red"); + } + fprintf(stderr, "WRONG\n"); + break; + }; +} + +static int eventLoop(struct aOpts* opts, struct aXInfo* xi) { + + Display* dpy = xi->display; XEvent ev; KeySym ks; - char cbuf[10], rbuf[50]; + char cbuf[10]; + char rbuf[50]; unsigned int clen, rlen = 0; const long max_goodwill = 5 * 30000; /* 150 seconds */ long goodwill = max_goodwill; long timeout = 0; + int mode = READY; + + struct aFrame* frame = alock_create_frame(xi, 0, 0, xi->width_of_root[0], xi->height_of_root[0], 10); for(;;) { - XNextEvent(xinfo->display, &ev); - switch (ev.type) { - case KeyPress: + // check for any keypresses + if (XCheckWindowEvent(dpy, xi->window[0], KeyPressMask|KeyReleaseMask, &ev) == True) { - if (ev.xkey.time < timeout) { - XBell(xinfo->display, 0); - break; - } + switch (ev.type) { + case KeyPress: - clen = XLookupString(&ev.xkey, cbuf, 9, &ks, 0); - switch (ks) { - case XK_Escape: - case XK_Clear: - rlen = 0; - break; - case XK_Delete: - case XK_BackSpace: - if (rlen > 0) - rlen--; - break; - case XK_Linefeed: - case XK_Return: - if (rlen == 0) + if (ev.xkey.time < timeout) { + XBell(dpy, 0); break; - if (rlen < sizeof(rbuf)) - rbuf[rlen] = 0; - - if (opts->auth->auth(rbuf)) - return 1; - - XSync(xinfo->display, True); /* discard pending events to start really fresh */ - XBell(xinfo->display, 0); - rlen = 0; - - if (timeout) { - goodwill += ev.xkey.time - timeout; - if (goodwill > max_goodwill) { - goodwill = max_goodwill; - } } - { - long offset; + // swallow up first keypress after timeout + if (mode == WRONG) { + mode = READY; + break; + } + else + mode = TYPING; - offset = goodwill * 0.3; - goodwill = goodwill - offset; - timeout = ev.xkey.time + 30000 - offset; + clen = XLookupString(&ev.xkey, cbuf, 9, &ks, 0); + switch (ks) { + case XK_Escape: + case XK_Clear: + rlen = 0; + break; + case XK_Delete: + case XK_BackSpace: + if (rlen > 0) + rlen--; + break; + case XK_Linefeed: + case XK_Return: + if (rlen == 0) + break; + if (rlen < sizeof(rbuf)) + rbuf[rlen] = 0; + + if (opts->auth->auth(rbuf)) { + alock_free_frame(frame); + return 1; + } + + mode = WRONG; + + XSync(dpy, True); /* discard pending events to start really fresh */ + XBell(dpy, 0); + rlen = 0; + + if (timeout) { + goodwill += ev.xkey.time - timeout; + if (goodwill > max_goodwill) { + goodwill = max_goodwill; + } + } + + { + long offset; + + offset = goodwill * 0.3; + goodwill = goodwill - offset; + timeout = ev.xkey.time + 30000 - offset; + } + break; + default: + if (clen != 1) + break; + if (rlen < (sizeof(rbuf) - 1)) { + rbuf[rlen] = cbuf[0]; + rlen++; + } + break; } break; default: - if (clen != 1) - break; - if (rlen < (sizeof(rbuf) - 1)) { - rbuf[rlen] = cbuf[0]; - rlen++; - } break; } - break; - default: - break; + + } else { // wait a bit + poll(NULL, 0, 25); + + //fprintf(stderr, "timeout: %ld <=> \n", timeout, ); fflush(stderr); + visualFeedback(frame, mode); } + } + // normally, we shouldnt arrive here at all + alock_free_frame(frame); return 0; } @@ -236,8 +310,8 @@ static pid_t getPidAtom(struct aXInfo* xinfo) { unsigned long nr_bytes_left; pid_t* ret_data; - if (XGetWindowProperty(xinfo->display, xinfo->root[0], - xinfo->pid_atom, 0L, 1L, False, XA_CARDINAL, + if (XGetWindowProperty(xinfo->display, xinfo->root[0], + xinfo->pid_atom, 0L, 1L, False, XA_CARDINAL, &ret_type, &ret_fmt, &nr_read, &nr_bytes_left, (unsigned char**)&ret_data) == Success && ret_type != None && ret_data) { pid_t pid = *ret_data; @@ -269,7 +343,7 @@ static int registerInstance(struct aXInfo* xinfo) { pid_t pid = getpid(); XChangeProperty(xinfo->display, xinfo->root[0], xinfo->pid_atom, XA_CARDINAL, - sizeof(pid_t) * 8, PropModeReplace, + sizeof(pid_t) * 8, PropModeReplace, (unsigned char*)&pid, 1); return 1; } diff --git a/src/alock.h b/src/alock.h index 008cd36..5415b28 100644 --- a/src/alock.h +++ b/src/alock.h @@ -40,6 +40,9 @@ struct aXInfo { int nr_screens; + int* width_of_root; + int* height_of_root; + Window* root; Colormap* colormap; @@ -72,12 +75,11 @@ struct aOpts { struct aBackground* background; }; - /*------------------------------------------------------------------*\ \*------------------------------------------------------------------*/ void alock_string2lower(char* string); int alock_native_byte_order(void); -int alock_alloc_color(const struct aXInfo* xinfo, const int scr, +int alock_alloc_color(const struct aXInfo* xinfo, int scr, const char* color_name, const char* fallback_name, XColor* result); diff --git a/src/alock_frame.c b/src/alock_frame.c new file mode 100644 index 0000000..98d091a --- /dev/null +++ b/src/alock_frame.c @@ -0,0 +1,152 @@ +/* ---------------------------------------------------------------- *\ + + file : alock_frame.c + author : m. gumz + copyr : copyright (c) 2008 by m. gumz + + license : see LICENSE + + start : Sa 04 Okt 2008 12:47:35 CEST + +\* ---------------------------------------------------------------- */ +/* ---------------------------------------------------------------- *\ + + about : + +\* ---------------------------------------------------------------- */ + +/* ---------------------------------------------------------------- *\ + includes +\* ---------------------------------------------------------------- */ +#include "alock_frame.h" +#include "alock.h" + +#include +#include + +/* ---------------------------------------------------------------- *\ +\* ---------------------------------------------------------------- */ + +struct aSide { + Window win; + int width; + int height; + GC gc; +}; + +struct aFrame { + struct aSide top; + struct aSide left; + struct aSide right; + struct aSide bottom; + XColor color; + struct aXInfo* xi; +}; + +/* ---------------------------------------------------------------- *\ +\* ---------------------------------------------------------------- */ + +struct aFrame* alock_create_frame(struct aXInfo* xi, int x, int y, int width, int height, int line_width) { + + Display* dpy = xi->display; + struct aFrame* frame; + struct aSide* side; + int i; + XSetWindowAttributes xswa; + xswa.override_redirect = True; + xswa.colormap = xi->colormap[0]; + + frame = (struct aFrame*)calloc(1, sizeof(struct aFrame)); + + if (frame == 0) + return 0; + + frame->xi = xi; + /* + + ascii - kungfoo + + p1 ------------------------------------------------- p2 + | top | + p3 --------------------------------------------------p4 + p4 --- p5 p6 --- p7 + | l | | r | + | e | | i | + | f | | g | + | t | | h | + | | | t | + p8 --- p9 pa --- pb + pc ------------------------------------------------- pd + | bottom | + pe ------------------------------------------------- pf + + */ + + frame->top.width = width; + frame->top.height = line_width; + frame->top.win = XCreateWindow(dpy, xi->root[0], + x, y, frame->top.width, frame->top.height, + 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWColormap, &xswa); + frame->bottom.width = width; + frame->bottom.height = line_width; + frame->bottom.win = XCreateWindow(dpy, xi->root[0], + x, y + height - line_width, frame->bottom.width, frame->bottom.height, + 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWColormap, &xswa); + + frame->left.width = line_width; + frame->left.height = height - line_width - 1; + frame->left.win = XCreateWindow(dpy, xi->root[0], + x, y + line_width, frame->left.width, frame->left.height, + 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWColormap, &xswa); + frame->right.width = line_width; + frame->right.height = height - line_width - 1; + frame->right.win = XCreateWindow(dpy, xi->root[0], + x + width - line_width, y + line_width, frame->right.width, frame->right.height, + 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWColormap, &xswa); + + + side = (struct aSide*)&frame->top; + for (i = 0; i < 4; i++) { + XMapWindow(dpy, side[i].win); + XRaiseWindow(dpy, side[i].win); + side[i].gc = XCreateGC(dpy, side[i].win, 0, 0); + } + + return frame; +} + +void alock_free_frame(struct aFrame* frame) { + struct aSide* side = (struct aSide*)&frame->top; + struct aXInfo* xi = frame->xi; + int i; + + for (i = 0; i < 4; i++) { + XFreeGC(xi->display, side[i].gc); + XDestroyWindow(xi->display, side[i].win); + } + + free(frame); +} + +void alock_draw_frame(struct aFrame* frame, const char* color_name) { + + struct aSide* side = (struct aSide*)&frame->top; + struct aXInfo* xi = frame->xi; + Display* dpy = xi->display; + XGCValues gcvals; + XColor tmp; + int i; + + XAllocNamedColor(dpy, xi->colormap[0], color_name, &frame->color, &tmp); + gcvals.foreground = frame->color.pixel; + + for (i = 0; i < 4; i++) { + XChangeGC(dpy, side[i].gc, GCForeground, &gcvals); + XFillRectangle(dpy, side[i].win, side[i].gc, 0, 0, side[i].width, side[i].height); + } +} + +/* ---------------------------------------------------------------- *\ +\* ---------------------------------------------------------------- */ + + diff --git a/src/alock_frame.h b/src/alock_frame.h new file mode 100644 index 0000000..5afa446 --- /dev/null +++ b/src/alock_frame.h @@ -0,0 +1,36 @@ + +#ifndef _ALOCK_FRAME_H_ +#define _ALOCK_FRAME_H_ + +/* ---------------------------------------------------------------- *\ + + file : alock_frame.h + author : m. gumz + copyr : copyright (c) 2008 by m. gumz + + license : see LICENSE + + start : Sa 04 Okt 2008 12:45:46 CEST + +\* ---------------------------------------------------------------- */ +/* ---------------------------------------------------------------- *\ + + about : functions to render a colored frame to the screen + mostly for visual feedback purposes :) + +\* ---------------------------------------------------------------- */ + +/* ---------------------------------------------------------------- *\ +\* ---------------------------------------------------------------- */ + +struct aXInfo; +struct aFrame; + +struct aFrame* alock_create_frame(struct aXInfo* xi, int x, int y, int width, int height, int line_width); +void alock_draw_frame(struct aFrame* frame, const char* color_name); +void alock_free_frame(struct aFrame* frame); + +/* ---------------------------------------------------------------- *\ +\* ---------------------------------------------------------------- */ +#endif // _ALOCK_FRAME_H_ + diff --git a/src/alock_utils.c b/src/alock_utils.c index 88e7159..0ff255d 100644 --- a/src/alock_utils.c +++ b/src/alock_utils.c @@ -38,7 +38,7 @@ void alock_string2lower(char* string) { /* ---------------------------------------------------------------- *\ \* ---------------------------------------------------------------- */ -int alock_alloc_color(const struct aXInfo* xinfo, const int scr, const char* color_name, +int alock_alloc_color(const struct aXInfo* xinfo, int scr, const char* color_name, const char* fallback_name, XColor* result) { static XColor tmp; @@ -57,7 +57,7 @@ int alock_alloc_color(const struct aXInfo* xinfo, const int scr, const char* col /*------------------------------------------------------------------*\ \*------------------------------------------------------------------*/ int alock_native_byte_order() { - int x = 1; + int x = 1; return (*((char *) &x) == 1) ? LSBFirst : MSBFirst; } diff --git a/src/bg_blank.c b/src/bg_blank.c index 6722d17..553edb9 100644 --- a/src/bg_blank.c +++ b/src/bg_blank.c @@ -34,7 +34,6 @@ static XColor* color = NULL; static int alock_bg_blank_init(const char* args, struct aXInfo* xinfo) { - XWindowAttributes xgwa; XSetWindowAttributes xswa; long xsmask = 0; char* color_name = strdup("black"); @@ -69,8 +68,6 @@ static int alock_bg_blank_init(const char* args, struct aXInfo* xinfo) { alock_alloc_color(xinfo, scr, color_name, "black", &color[scr]); - XGetWindowAttributes(xinfo->display, xinfo->root[scr], &xgwa); - xswa.override_redirect = True; xswa.colormap = xinfo->colormap[scr]; xswa.background_pixel = color[scr].pixel; @@ -80,7 +77,8 @@ static int alock_bg_blank_init(const char* args, struct aXInfo* xinfo) { xsmask |= CWColormap; window[scr] = XCreateWindow(xinfo->display, xinfo->root[scr], - 0, 0, xgwa.width, xgwa.height, + 0, 0, + xinfo->width_of_root[scr], xinfo->height_of_root[scr], 0, /* borderwidth */ CopyFromParent, /* depth */ InputOutput, /* class */ diff --git a/src/bg_image.c b/src/bg_image.c index 0a8fad7..c255c8f 100644 --- a/src/bg_image.c +++ b/src/bg_image.c @@ -42,7 +42,6 @@ static XColor* color = NULL; static int alock_bg_image_init(const char* args, struct aXInfo* xinfo) { - XWindowAttributes xgwa; XSetWindowAttributes xswa; long xsmask = 0; long options = ALOCK_SCALE; @@ -108,10 +107,10 @@ static int alock_bg_image_init(const char* args, struct aXInfo* xinfo) { int scr; for (scr = 0; scr < xinfo->nr_screens; scr++) { + const int rwidth = xinfo->width_of_root[scr]; + const int rheight = xinfo->height_of_root[scr]; alock_alloc_color(xinfo, scr, color_name, "black", &color[scr]); - XGetWindowAttributes(xinfo->display, xinfo->root[scr], &xgwa); - { /* get image and set it as the background pixmap for the window */ Imlib_Context context = NULL; Imlib_Image image = NULL; @@ -131,7 +130,7 @@ static int alock_bg_image_init(const char* args, struct aXInfo* xinfo) { int h; pixmap[scr] = XCreatePixmap(xinfo->display, xinfo->root[scr], - xgwa.width, xgwa.height, + rwidth, rheight, DefaultDepth(xinfo->display, scr)); imlib_context_set_drawable(pixmap[scr]); @@ -147,7 +146,7 @@ static int alock_bg_image_init(const char* args, struct aXInfo* xinfo) { gcval.foreground = color[scr].pixel; gc = XCreateGC(xinfo->display, xinfo->root[scr], GCForeground, &gcval); - XFillRectangle(xinfo->display, pixmap[scr], gc, 0, 0, xgwa.width, xgwa.height); + XFillRectangle(xinfo->display, pixmap[scr], gc, 0, 0, rwidth, rheight); XFreeGC(xinfo->display, gc); } @@ -181,7 +180,7 @@ static int alock_bg_image_init(const char* args, struct aXInfo* xinfo) { } if (options & ALOCK_CENTER) { - imlib_render_image_on_drawable((xgwa.width - w)/2, (xgwa.height - h)/2); + imlib_render_image_on_drawable((rwidth - w)/2, (rheight - h)/2); } else if (options & ALOCK_TILED) { Pixmap tile; GC gc; @@ -195,12 +194,12 @@ static int alock_bg_image_init(const char* args, struct aXInfo* xinfo) { gcval.fill_style = FillTiled; gcval.tile = tile; gc = XCreateGC(xinfo->display, tile, GCFillStyle|GCTile, &gcval); - XFillRectangle(xinfo->display, pixmap[scr], gc, 0, 0, xgwa.width, xgwa.height); + XFillRectangle(xinfo->display, pixmap[scr], gc, 0, 0, rwidth, rheight); XFreeGC(xinfo->display, gc); XFreePixmap(xinfo->display, tile); } else {/* fallback is ALOCK_SCALE */ - imlib_render_image_on_drawable_at_size(0, 0, xgwa.width, xgwa.height); + imlib_render_image_on_drawable_at_size(0, 0, rwidth, rheight); } imlib_free_image_and_decache(); @@ -225,7 +224,7 @@ static int alock_bg_image_init(const char* args, struct aXInfo* xinfo) { xsmask |= CWBackPixmap; window[scr] = XCreateWindow(xinfo->display, xinfo->root[scr], - 0, 0, xgwa.width, xgwa.height, + 0, 0, rwidth, rheight, 0, /* borderwidth */ CopyFromParent, /* depth */ InputOutput, /* class */ diff --git a/src/bg_shade.c b/src/bg_shade.c index 6e5342a..63c4127 100644 --- a/src/bg_shade.c +++ b/src/bg_shade.c @@ -93,12 +93,9 @@ static int alock_bg_shade_init(const char* args, struct aXInfo* xinfo) { /* get a color from color_name */ alock_alloc_color(xinfo, scr, color_name, "black", &color[scr]); - { /* get dimension of the screen */ - XWindowAttributes xgwa; - XGetWindowAttributes(xinfo->display, xinfo->root[scr], &xgwa); - width = xgwa.width; - height = xgwa.height; - } + width = xinfo->width_of_root[scr]; + height = xinfo->height_of_root[scr]; + { /* xrender stuff */ Display* dpy = xinfo->display; Window root = xinfo->root[scr];