#ifdef __OpenBSD__
#include <strings.h> /* explicit_bzero(3) */
#endif
+#include <xcb/xcb_aux.h>
#include "i3lock.h"
#include "xcb.h"
DEBUG("successfully authenticated\n");
clear_password_memory();
- exit(0);
+ ev_break(EV_DEFAULT, EVBREAK_ALL);
+ return;
}
#else
if (pam_authenticate(pam_handle, 0) == PAM_SUCCESS) {
pam_setcred(pam_handle, PAM_REFRESH_CRED);
pam_end(pam_handle, PAM_SUCCESS);
- exit(0);
+ ev_break(EV_DEFAULT, EVBREAK_ALL);
+ return;
}
#endif
ksym == XKB_KEY_Escape) {
DEBUG("C-u pressed\n");
clear_input();
- /* Hide the unlock indicator after a bit if the password buffer is
- * empty. */
- if (unlock_indicator) {
- START_TIMER(clear_indicator_timeout, 1.0, clear_indicator_cb);
- unlock_state = STATE_BACKSPACE_ACTIVE;
- redraw_screen();
- unlock_state = STATE_KEY_PRESSED;
- }
+ /* Also hide the unlock indicator */
+ if (unlock_indicator)
+ clear_indicator();
return;
}
break;
#endif
int curs_choice = CURS_NONE;
int o;
- int optind = 0;
+ int longoptind = 0;
struct option longopts[] = {
{"version", no_argument, NULL, 'v'},
{"nofork", no_argument, NULL, 'n'},
errx(EXIT_FAILURE, "pw->pw_name is NULL.\n");
char *optstring = "hvnbdc:p:ui:teI:f";
- while ((o = getopt_long(argc, argv, optstring, longopts, &optind)) != -1) {
+ while ((o = getopt_long(argc, argv, optstring, longopts, &longoptind)) != -1) {
switch (o) {
case 'v':
errx(EXIT_SUCCESS, "version " VERSION " © 2010 Michael Stapelberg");
ignore_empty_password = true;
break;
case 0:
- if (strcmp(longopts[optind].name, "debug") == 0)
+ if (strcmp(longopts[longoptind].name, "debug") == 0)
debug_mode = true;
break;
case 'f':
errx(EXIT_FAILURE, "Could not load keymap");
const char *locale = getenv("LC_ALL");
- if (!locale)
+ if (!locale || !*locale)
locale = getenv("LC_CTYPE");
- if (!locale)
+ if (!locale || !*locale)
locale = getenv("LANG");
- if (!locale) {
+ if (!locale || !*locale) {
if (debug_mode)
fprintf(stderr, "Can't detect your locale, fallback to C\n");
locale = "C";
/* Pixmap on which the image is rendered to (if any) */
xcb_pixmap_t bg_pixmap = draw_image(last_resolution);
+ xcb_window_t stolen_focus = find_focused_window(conn, screen->root);
+
/* Open the fullscreen window, already with the correct pixmap in place */
win = open_fullscreen_window(conn, screen, color, bg_pixmap);
xcb_free_pixmap(conn, bg_pixmap);
/* Display the "locking…" message while trying to grab the pointer/keyboard. */
auth_state = STATE_AUTH_LOCK;
- grab_pointer_and_keyboard(conn, screen, cursor);
+ if (!grab_pointer_and_keyboard(conn, screen, cursor, 1000)) {
+ DEBUG("stole focus from X11 window 0x%08x\n", stolen_focus);
+
+ /* Set the focus to i3lock, possibly closing context menus which would
+ * otherwise prevent us from grabbing keyboard/pointer.
+ *
+ * We cannot use set_focused_window because _NET_ACTIVE_WINDOW only
+ * works for managed windows, but i3lock uses an unmanaged window
+ * (override_redirect=1). */
+ xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT /* revert_to */, win, XCB_CURRENT_TIME);
+ if (!grab_pointer_and_keyboard(conn, screen, cursor, 9000)) {
+ auth_state = STATE_I3LOCK_LOCK_FAILED;
+ redraw_screen();
+ sleep(1);
+ errx(EXIT_FAILURE, "Cannot grab pointer/keyboard");
+ }
+ }
pid_t pid = fork();
/* The pid == -1 case is intentionally ignored here:
* file descriptor becomes readable). */
ev_invoke(main_loop, xcb_check, 0);
ev_loop(main_loop, 0);
+
+ if (stolen_focus == XCB_NONE) {
+ return 0;
+ }
+
+ DEBUG("restoring focus to X11 window 0x%08x\n", stolen_focus);
+ xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
+ xcb_ungrab_keyboard(conn, XCB_CURRENT_TIME);
+ xcb_destroy_window(conn, win);
+ set_focused_window(conn, screen->root, stolen_focus);
+ xcb_aux_sync(conn);
+
+ return 0;
}