Example #1
0
static void eventLoop(struct aOpts *opts, struct aXInfo *xi) {

    Display *dpy = xi->display;
    XEvent ev;
    KeySym ks;
    char cbuf[10];
    wchar_t pass[128];
    unsigned int clen;
    unsigned int pass_pos = 0, pass_len = 0;
    unsigned long keypress_time = 0;
    char rbuf[sizeof(pass)];

    debug("entering event main loop");
    for (;;) {

        if (keypress_time) {
            /* check for any key press event */
            if (XCheckWindowEvent(dpy, xi->window[0], KeyPressMask, &ev) == False) {

                /* user fell asleep while typing (5 seconds inactivity) */
                if (alock_mtime() - keypress_time > 5000) {
                    opts->input->setstate(AINPUT_STATE_NONE);
                    keypress_time = 0;
                }

                /* wait a bit */
                usleep(25000);
                continue;
            }
        }
        else {
            /* block until any key press event arrives */
            XWindowEvent(dpy, xi->window[0], KeyPressMask, &ev);
        }

        switch (ev.type) {
        case KeyPress:

            /* swallow up first key press to indicate "enter mode" */
            if (keypress_time == 0) {
                opts->input->setstate(AINPUT_STATE_INIT);
                keypress_time = alock_mtime();
                pass_pos = pass_len = 0;
                pass[0] = '\0';
                break;
            }

            keypress_time = alock_mtime();
            clen = XLookupString(&ev.xkey, cbuf, sizeof(cbuf), &ks, NULL);
            debug("key input: %lx, %d, `%s`", ks, clen, cbuf);

            /* translate key press symbol */
            ks = opts->input->keypress(ks);

            switch (ks) {
            case NoSymbol:
                break;

            /* clear/initialize input buffer */
            case XK_Escape:
            case XK_Clear:
                pass_pos = pass_len = 0;
                pass[0] = '\0';
                break;

            /* input position navigation */
            case XK_Begin:
            case XK_Home:
                pass_pos = 0;
                break;
            case XK_End:
                pass_pos = pass_len;
                break;
            case XK_Left:
                if (pass_pos > 0)
                    pass_pos--;
                break;
            case XK_Right:
                if (pass_pos < pass_len)
                    pass_pos++;
                break;

            /* remove entered characters */
            case XK_Delete:
                if (pass_pos < pass_len) {
                    wmemmove(&pass[pass_pos], &pass[pass_pos + 1], pass_len - pass_pos);
                    pass_len--;
                }
                break;
            case XK_BackSpace:
                if (pass_pos > 0) {
                    wmemmove(&pass[pass_pos - 1], &pass[pass_pos], pass_len - pass_pos + 1);
                    pass_pos--;
                    pass_len--;
                }
                break;

            /* input confirmation and authentication test */
            case XK_Linefeed:
            case XK_Return:
                opts->input->setstate(AINPUT_STATE_CHECK);
                wcstombs(rbuf, pass, sizeof(rbuf));
                if (opts->auth->auth(rbuf)) {
                    opts->input->setstate(AINPUT_STATE_VALID);
                    return;
                }
                opts->input->setstate(AINPUT_STATE_ERROR);
                opts->input->setstate(AINPUT_STATE_INIT);
                keypress_time = alock_mtime();
                pass_pos = pass_len = 0;
                pass[0] = '\0';
                break;

            /* input new character at the current input position */
            default:
                if (clen > 0 && !iscntrl(cbuf[0]) && pass_len < (sizeof(pass) / sizeof(*pass) - 1)) {
                    wmemmove(&pass[pass_pos + 1], &pass[pass_pos], pass_len - pass_pos + 1);
                    mbtowc(&pass[pass_pos], cbuf, clen);
                    pass_pos++;
                    pass_len++;
                }
                break;
            }

            debug("entered phrase [%zu]: `%ls`", wcslen(pass), pass);
            break;

        case Expose:
            XClearWindow(xi->display, ((XExposeEvent*)&ev)->window);
            break;
        }
    }
}
Example #2
0
File: main.c Project: Arkq/alock
static void eventLoop(Display *display, struct aModules *modules) {

    XEvent ev;
    KeySym ks;
    char cbuf[10];
    wchar_t pass[128];
    unsigned int clen;
    unsigned int pass_pos = 0, pass_len = 0;
    unsigned long keypress_time = 0;

    /* if possible do not page this address to the swap area */
    mlock(pass, sizeof(pass));

    debug("entering event main loop");
    for (;;) {

        if (keypress_time) {
            /* check for any key press event (or root window state change) */
            if (XCheckMaskEvent(display, KeyPressMask | StructureNotifyMask, &ev) == False) {

                /* user fell asleep while typing (5 seconds inactivity) */
                if (alock_mtime() - keypress_time > 5000) {
                    modules->input->setstate(AINPUT_STATE_NONE);
                    keypress_time = 0;
                }

                /* wait a bit */
                usleep(25000);
                continue;
            }
        }
        else {

#if WITH_XBLIGHT
            /* dim out display backlight */
            if (modules->backlight != -1)
                setBacklightBrightness(0);
#endif /* WITH_XBLIGHT */

            /* block until any key press event arrives */
            XMaskEvent(display, KeyPressMask | StructureNotifyMask, &ev);

#if WITH_XBLIGHT
            /* restore original backlight brightness value */
            if (modules->backlight != -1)
                setBacklightBrightness(modules->backlight);
#endif /* WITH_XBLIGHT */
        }

        switch (ev.type) {
        case KeyPress:

            /* swallow up first key press to indicate "enter mode" */
            if (keypress_time == 0) {
                modules->input->setstate(AINPUT_STATE_INIT);
                keypress_time = alock_mtime();
                pass_pos = pass_len = 0;
                pass[0] = '\0';
                break;
            }

            keypress_time = alock_mtime();
            clen = XLookupString(&ev.xkey, cbuf, sizeof(cbuf), &ks, NULL);
            debug("key input: %lx, %d, `%.*s`", ks, clen, clen, cbuf);

            /* terminal-like key remapping */
            if (clen == 1 && iscntrl(cbuf[0]))
                switch (cbuf[0]) {
                case 0x03 /* Ctrl-C */ :
                    ks = XK_Escape;
                    break;
                case 0x08 /* Ctrl-H */ :
                    ks = XK_BackSpace;
                    break;
                case 0x0A /* Ctrl-J */ :
                case 0x0D /* Ctrl-M */ :
                    ks = XK_Return;
                    break;
                }

            /* translate key press symbol */
            ks = modules->input->keypress(ks);

            switch (ks) {
            case NoSymbol:
                break;

            /* clear/initialize input buffer */
            case XK_Escape:
            case XK_Clear:
                pass_pos = pass_len = 0;
                pass[0] = '\0';
                break;

            /* input position navigation */
            case XK_Begin:
            case XK_Home:
                pass_pos = 0;
                break;
            case XK_End:
                pass_pos = pass_len;
                break;
            case XK_Left:
                if (pass_pos > 0)
                    pass_pos--;
                break;
            case XK_Right:
                if (pass_pos < pass_len)
                    pass_pos++;
                break;

            /* remove entered characters */
            case XK_Delete:
                if (pass_pos < pass_len) {
                    wmemmove(&pass[pass_pos], &pass[pass_pos + 1], pass_len - pass_pos);
                    pass_len--;
                }
                break;
            case XK_BackSpace:
                if (pass_pos > 0) {
                    wmemmove(&pass[pass_pos - 1], &pass[pass_pos], pass_len - pass_pos + 1);
                    pass_pos--;
                    pass_len--;
                }
                break;

            /* input confirmation and authentication test */
            case XK_KP_Enter:
            case XK_Linefeed:
            case XK_Return: {

                char rbuf[sizeof(pass)];
                int rv;

                modules->input->setstate(AINPUT_STATE_CHECK);

                wcstombs(rbuf, pass, sizeof(rbuf));
                rv = modules->auth->authenticate(rbuf);

                memset(rbuf, 0, sizeof(rbuf));
                memset(pass, 0, sizeof(pass));
                pass_pos = pass_len = 0;

                if (rv == 0) { /* successful authentication */
                    modules->input->setstate(AINPUT_STATE_VALID);
                    return;
                }

                modules->input->setstate(AINPUT_STATE_ERROR);
                modules->input->setstate(AINPUT_STATE_INIT);
                keypress_time = alock_mtime();

                break;
            }

            /* input new character at the current input position */
            default:
                if (clen > 0 && !iscntrl(cbuf[0]) && pass_len < (sizeof(pass) / sizeof(*pass) - 1)) {
                    wmemmove(&pass[pass_pos + 1], &pass[pass_pos], pass_len - pass_pos + 1);
                    mbtowc(&pass[pass_pos], cbuf, clen);
                    pass_pos++;
                    pass_len++;
                }
                break;
            }

            debug("entered phrase [%zu]: `%ls`", wcslen(pass), pass);
            break;

        case ConfigureNotify:
            /* NOTE: This event should be generated for the root window upon
             *       the display reconfiguration (e.g. resolution change). */

            debug("received configure notify event");
            break;

#if 0
        case Expose:
            XClearWindow(dpy, ((XExposeEvent*)&ev)->window);
            break;
#endif

        }
    }
}