mirror of https://github.com/i3/i3lock.git
Re-raise i3lock when obscured in a separate process
This is cleaner than commitpull/1/heada305e62
(running authentication in a separate process) because we don’t lose the feature that X11 will buffer KeyPresses for us while the process blocks on PAM. See http://cr.i3wm.org/patch/305 for the amount of code (and new known bugs) that would have to be introduced to makea305e62
work.
parent
d7fd058f0c
commit
ac8bbad523
73
i3lock.c
73
i3lock.c
|
@ -364,7 +364,8 @@ static void handle_key_press(xcb_key_press_event_t *event) {
|
|||
* hiding us) gets hidden.
|
||||
*
|
||||
*/
|
||||
static void handle_visibility_notify(xcb_visibility_notify_event_t *event) {
|
||||
static void handle_visibility_notify(xcb_connection_t *conn,
|
||||
xcb_visibility_notify_event_t *event) {
|
||||
if (event->state != XCB_VISIBILITY_UNOBSCURED) {
|
||||
uint32_t values[] = { XCB_STACK_MODE_ABOVE };
|
||||
xcb_configure_window(conn, event->window, XCB_CONFIG_WINDOW_STACK_MODE, values);
|
||||
|
@ -501,7 +502,7 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
|
|||
break;
|
||||
|
||||
case XCB_VISIBILITY_NOTIFY:
|
||||
handle_visibility_notify((xcb_visibility_notify_event_t*)event);
|
||||
handle_visibility_notify(conn, (xcb_visibility_notify_event_t*)event);
|
||||
break;
|
||||
|
||||
case XCB_MAP_NOTIFY:
|
||||
|
@ -531,6 +532,63 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called from a fork()ed child and will raise the i3lock
|
||||
* window when the window is obscured, even when the main i3lock process is
|
||||
* blocked due to PAM.
|
||||
*
|
||||
*/
|
||||
static void raise_loop(xcb_window_t window) {
|
||||
xcb_connection_t *conn;
|
||||
xcb_generic_event_t *event;
|
||||
int screens;
|
||||
|
||||
if ((conn = xcb_connect(NULL, &screens)) == NULL ||
|
||||
xcb_connection_has_error(conn))
|
||||
errx(EXIT_FAILURE, "Cannot open display\n");
|
||||
|
||||
/* We need to know about the window being obscured or getting destroyed. */
|
||||
xcb_change_window_attributes(conn, window, XCB_CW_EVENT_MASK,
|
||||
(uint32_t[]){
|
||||
XCB_EVENT_MASK_VISIBILITY_CHANGE |
|
||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY
|
||||
});
|
||||
xcb_flush(conn);
|
||||
|
||||
DEBUG("Watching window 0x%08x\n", window);
|
||||
while ((event = xcb_wait_for_event(conn)) != NULL) {
|
||||
if (event->response_type == 0) {
|
||||
xcb_generic_error_t *error = (xcb_generic_error_t*)event;
|
||||
DEBUG("X11 Error received! sequence 0x%x, error_code = %d\n",
|
||||
error->sequence, error->error_code);
|
||||
free(event);
|
||||
continue;
|
||||
}
|
||||
/* Strip off the highest bit (set if the event is generated) */
|
||||
int type = (event->response_type & 0x7F);
|
||||
DEBUG("Read event of type %d\n", type);
|
||||
switch (type) {
|
||||
case XCB_VISIBILITY_NOTIFY:
|
||||
handle_visibility_notify(conn, (xcb_visibility_notify_event_t*)event);
|
||||
break;
|
||||
case XCB_UNMAP_NOTIFY:
|
||||
DEBUG("UnmapNotify for 0x%08x\n", (((xcb_unmap_notify_event_t*)event)->window));
|
||||
if (((xcb_unmap_notify_event_t*)event)->window == window)
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case XCB_DESTROY_NOTIFY:
|
||||
DEBUG("DestroyNotify for 0x%08x\n", (((xcb_destroy_notify_event_t*)event)->window));
|
||||
if (((xcb_destroy_notify_event_t*)event)->window == window)
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
default:
|
||||
DEBUG("Unhandled event type %d\n", type);
|
||||
break;
|
||||
}
|
||||
free(event);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *username;
|
||||
char *image_path = NULL;
|
||||
|
@ -692,6 +750,17 @@ int main(int argc, char *argv[]) {
|
|||
win = open_fullscreen_window(conn, screen, color, bg_pixmap);
|
||||
xcb_free_pixmap(conn, bg_pixmap);
|
||||
|
||||
pid_t pid = fork();
|
||||
/* The pid == -1 case is intentionally ignored here:
|
||||
* While the child process is useful for preventing other windows from
|
||||
* popping up while i3lock blocks, it is not critical. */
|
||||
if (pid == 0) {
|
||||
/* Child */
|
||||
close(xcb_get_file_descriptor(conn));
|
||||
raise_loop(win);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
cursor = create_cursor(conn, screen, win, curs_choice);
|
||||
|
||||
grab_pointer_and_keyboard(conn, screen, cursor);
|
||||
|
|
Loading…
Reference in New Issue