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