static int eventLoop(struct aOpts* opts, struct aXInfo* xi) { Display* dpy = xi->display; XEvent ev; KeySym ks; char cbuf[10]; char rbuf[50]; unsigned int clen, rlen = 0; long current_time = 0; long last_key_time = 0; const long penalty = 1000; long timeout = 0; int mode = INITIAL; struct aFrame* frame = alock_create_frame(xi, 0, 0, xi->width_of_root[0], xi->height_of_root[0], 10); for(;;) { current_time = elapsedTime(); // check for any keypresses if (XCheckWindowEvent(dpy, xi->window[0], KeyPressMask|KeyReleaseMask, &ev) == True) { switch (ev.type) { case KeyPress: last_key_time = current_time; if (last_key_time < timeout) { XBell(dpy, 0); break; } // swallow up first keypress to indicate "enter mode" if (mode == INITIAL) { mode = TYPING; break; } mode = TYPING; 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; // some auth() methods have their own penalty system // so we draw a 'yellow' frame to show 'checking' state. alock_draw_frame(frame, "yellow"); XSync(dpy, True); if (opts->auth->auth(rbuf)) { alock_free_frame(frame); return 1; } XBell(dpy, 0); mode = WRONG; timeout = elapsedTime() + penalty; rlen = 0; break; default: if (clen != 1) break; if (rlen < (sizeof(rbuf) - 1)) { rbuf[rlen] = cbuf[0]; rlen++; } break; } break; case Expose: { XExposeEvent* eev = (XExposeEvent*)&ev; XClearWindow(xi->display, eev->window); } break; default: break; } } else { // wait a bit long delta = current_time - last_key_time; if (mode == TYPING && (delta > 10000)) { // user fell asleep while typing .) mode = INITIAL; } else if (mode == WRONG && (current_time > timeout)) { // end of timeout for wrong password mode = TYPING; last_key_time = timeout; // start 'idle' timer correctly by a fake keypress } visualFeedback(frame, mode); poll(NULL, 0, 25); } } // normally, we shouldnt arrive here at all alock_free_frame(frame); return 0; }
static int eventLoop(struct aOpts* opts, struct aXInfo* xi) { Display* dpy = xi->display; KeySym ks; XEvent ev; char cbuf[30]; unsigned int clen, rlen = 0; long current_time = 0; long last_key_time = 0; const long penalty = 1000; long timeout = 0; int toggle = 0; int mode = INITIAL; char nameref[STRING_LIMIT]; char pwdref[STRING_LIMIT]; char shpwdref[STRING_LIMIT]; int i = 0; int revert = 0; int tabpos = -1; char * const argv[] = { "/usr/bin/gnome-screensaver-command", "-l", NULL }; char * const focus[] = { nameref, pwdref, NULL }; for (i = 0; i < STRING_LIMIT; i++) { nameref[i] = 0; pwdref[i] = 0; shpwdref[i] = 0; } LOG("create visual response frame"); struct aFrame* frame = tlock_create_frame(xi, 0, 0, xi->width_of_root[0], xi->height_of_root[0], 10); LOG("enter dialog creation"); struct aDialog* dialog = tlock_create_dialog(xi, 50, 50, 320, 110, 10); LOG("completed dialog creation");LOG("entering event loop"); for (;;) { current_time = elapsedTime(); // check for any keypresses if (XCheckWindowEvent(xi->display, xi->window[0], KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask, &ev) == True) { DEBUG_EVENT_LOOP_BLANK; //PRINT(fprintf(stderr, "event.type %d \n", ev.xany.type);) switch (ev.xany.type) { case KeyPress: { last_key_time = current_time; if (last_key_time < timeout) { XBell(dpy, 0); break; } // swallow up first keypress to indicate "enter mode" if (mode == INITIAL) { mode = TYPING; break; } mode = TYPING; clen = XLookupString(&ev.xkey, cbuf, 15, &ks, 0); _PRINTF_( "key=%c \n", cbuf[0]); switch (ks) { case XK_Tab: // if previous tab // store previous tabpos++; if (tabpos > 1) { tabpos = 0; } rlen = strlen(focus[tabpos]); flag_redraw(dialog); _PRINTF_( "TAB_: tabpos = %d, %d = %s\n", tabpos, rlen, focus[tabpos] ); visualFeedback(xi, dialog, frame, mode, toggle, nameref, shpwdref); break; case XK_Escape: case XK_Clear: rlen = 0; CLEAN_TAB_ENTRY(tabpos) ; flag_redraw(dialog); visualFeedback(xi, dialog, frame, mode, toggle, nameref, shpwdref); break; case XK_Delete: case XK_BackSpace: if (tabpos >= 0 && rlen > 0) { focus[tabpos][rlen] = 0; if (tabpos == 1 ){ shpwdref[rlen] = 0; } rlen--; focus[tabpos][rlen] = 0; if (tabpos == 1 ){ shpwdref[rlen] = 0; } } flag_redraw(dialog); visualFeedback(xi, dialog, frame, mode, toggle, nameref, shpwdref); _PRINTF_("BACK: tabpos = %d, %d = %s\n", tabpos, rlen, focus[tabpos] ); break; case XK_Linefeed: case XK_Return: if (tabpos >= 0 && rlen == 0) { CLEAN_TAB_ENTRY(tabpos); break; } // if nothing was entered and enter/return was // pressed, clear buffer and exit out of routine. if (tabpos < 0) { CLEAN_TAB_ENTRY(0); CLEAN_TAB_ENTRY(1); break; } if (rlen < sizeof(focus[tabpos])) { focus[tabpos][rlen] = 0; if (tabpos == 1) { shpwdref[rlen] = 0; } } // some auth() methods have their own penalty system // so we draw a 'yellow' frame to show 'checking' state. DEBUG_EVENT_LOOP_BLANK; tlock_draw_frame(xi, frame, "yellow"); DEBUG_EVENT_LOOP_BLANK; XSync(dpy, True); DEBUG_EVENT_LOOP_BLANK; // copy buffer in focussed value array if (challenge_response_feedback(opts, xi, frame, nameref, pwdref)) { return 1; } else { flag_redraw(dialog); } // CLEAN_TAB_ENTRY(tabpos) ; //XBell(dpy, 0); DEBUG_EVENT_LOOP_BLANK; mode = WRONG; timeout = elapsedTime() + penalty; break; default: if (clen != 1) break; _PRINTF_("%d, len=%l, f=%l\n", tabpos, rlen, sizeof(nameref)); if (tabpos >= 0 && rlen < (sizeof(nameref) - 1)) { focus[tabpos][rlen] = cbuf[0]; if (tabpos == 1) { shpwdref[rlen]='*'; } _PRINTF_("%d, focus=%s\n", tabpos, focus[tabpos]); rlen++; } break; } } break; case Expose: { XExposeEvent* eev = (XExposeEvent*) &ev; _PRINTF_( "expose event %d\n", eev->type); XClearWindow(xi->display, eev->window); exit(400); } break; case ButtonPress: { } break; case ButtonRelease: { // reset the focus position to unknown. if (BUTTON_PRESSED("user_field")) { // if current tab pos != user_field // store its value in the right pointer tabpos = 0; } else { if (BUTTON_PRESSED("password_field")) { // if current tab pos != user_field // store its value in the right pointer tabpos = 1; } else { if (BUTTON_PRESSED("cancel_button")) { tabpos = -1; tabpos = -1; CLEAN_TAB_ENTRY(0); CLEAN_TAB_ENTRY(1); /// // reset mode for loop event mode = INITIAL; visualFeedback(xi, dialog, frame, mode, toggle, nameref, shpwdref); // syslog( // LOG_NOTICE, "switch_button release detected\n"); // int ret = execvp("gnome-screensaver-command", argv); // syslog( // LOG_NOTICE, "Return not expected. Must be an execvp() error [exit=%d].\n", ret); // exit(0); } else { if (BUTTON_PRESSED("clear_button")) { tabpos = -1; CLEAN_TAB_ENTRY(0); CLEAN_TAB_ENTRY(1); /// // reset mode for loop event mode = TYPING; visualFeedback(xi, dialog, frame, mode, toggle, nameref, shpwdref); } } } } } // case BUTTON RELEASE end break; default: break; }DEBUG_EVENT_LOOP_BLANK; } else { // wait a bit DEBUG_EVENT_LOOP_BLANK; long delta = current_time - last_key_time; if (mode == TYPING && (delta > 10000)) { // user fell asleep while typing .) mode = INITIAL; } else if (mode == WRONG && (current_time > timeout)) { // end of timeout for wrong password mode = TYPING; last_key_time = timeout; // start 'idle' timer correctly by a fake keypress } if (delta > 1000) { toggle = 2; if (opts->flash) { toggle = (delta / 1000) % 2; } }DEBUG_EVENT_LOOP_BLANK; visualFeedback(xi, dialog, frame, mode, toggle, nameref, shpwdref); DEBUG_EVENT_LOOP_BLANK; poll(NULL, 0, 25); } } // normally, we shouldn't arrive here at all tlock_free_frame(xi, frame); #ifdef HAVE_DIALOG tlock_free_dialog(xi, dialog); #endif return 0; }