first version with visual feedback (still rough)

--HG--
extra : convert_revision : svn%3Aeebe1cee-a9af-4fe4-bd26-ad572b19c5ab/trunk%4078
This commit is contained in:
mathias.gumz 2008-10-04 11:14:58 +00:00
parent 5e74642877
commit 3586877dc0
13 changed files with 377 additions and 102 deletions

View file

@ -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

View file

@ -1,11 +1,11 @@
ALOCK(1)
========
Mathias Gumz <akira@fluxbox.org>
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
-------

View file

@ -1,11 +1,11 @@
ALOCK(1)
========
Mathias Gumz <akira@fluxbox.org>
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
-------

View file

@ -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

View file

@ -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' ]

View file

@ -11,6 +11,7 @@
\* ---------------------------------------------------------------- */
#include "alock.h"
#include "alock_frame.h"
#include <X11/Xutil.h>
#include <X11/Xproto.h>
@ -21,6 +22,7 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <poll.h>
/*----------------------------------------------*\
\*----------------------------------------------*/
@ -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;
}

View file

@ -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);

152
src/alock_frame.c Normal file
View file

@ -0,0 +1,152 @@
/* ---------------------------------------------------------------- *\
file : alock_frame.c
author : m. gumz <akira at fluxbox dot org>
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 <X11/Xlib.h>
#include <stdlib.h>
/* ---------------------------------------------------------------- *\
\* ---------------------------------------------------------------- */
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);
}
}
/* ---------------------------------------------------------------- *\
\* ---------------------------------------------------------------- */

36
src/alock_frame.h Normal file
View file

@ -0,0 +1,36 @@
#ifndef _ALOCK_FRAME_H_
#define _ALOCK_FRAME_H_
/* ---------------------------------------------------------------- *\
file : alock_frame.h
author : m. gumz <akira at fluxbox dot org>
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_

View file

@ -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;
}

View file

@ -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 */

View file

@ -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 */

View file

@ -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];