/* * Instead of polling the X connection socket we leave this to * xcb_poll_for_event() which knows better than we can ever know. * */ static void xcb_check_cb(EV_P_ ev_check *w, int revents) { xcb_generic_event_t *event; while ((event = xcb_poll_for_event(conn)) != NULL) { if (event->response_type == 0) { xcb_generic_error_t *error = (xcb_generic_error_t*)event; if (debug_mode) fprintf(stderr, "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); switch (type) { case XCB_KEY_PRESS: handle_key_press((xcb_key_press_event_t*)event); break; case XCB_KEY_RELEASE: handle_key_release((xcb_key_release_event_t*)event); /* If this was the backspace or escape key we are back at an * empty input, so turn off the screen if DPMS is enabled */ if (dpms && input_position == 0) dpms_turn_off_screen(conn); break; case XCB_VISIBILITY_NOTIFY: handle_visibility_notify((xcb_visibility_notify_event_t*)event); break; case XCB_MAP_NOTIFY: if (!dont_fork) { /* After the first MapNotify, we never fork again. We don’t * expect to get another MapNotify, but better be sure… */ dont_fork = true; /* In the parent process, we exit */ if (fork() != 0) exit(0); ev_loop_fork(EV_DEFAULT); } break; case XCB_MAPPING_NOTIFY: handle_mapping_notify((xcb_mapping_notify_event_t*)event); break; case XCB_CONFIGURE_NOTIFY: handle_screen_resize(); break; } free(event); } }
/* * Instead of polling the X connection socket we leave this to * xcb_poll_for_event() which knows better than we can ever know. * */ static void xcb_check_cb(EV_P_ ev_check *w, int revents) { xcb_generic_event_t *event; while ((event = xcb_poll_for_event(conn)) != NULL) { if (event->response_type == 0) { xcb_generic_error_t *error = (xcb_generic_error_t*)event; if (debug_mode) fprintf(stderr, "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); switch (type) { case XCB_KEY_PRESS: handle_key_press((xcb_key_press_event_t*)event); break; case XCB_KEY_RELEASE: /* If this was the backspace or escape key we are back at an * empty input, so turn off the screen if DPMS is enabled, but * only do that after some timeout: maybe user mistyped and * will type again right away */ START_TIMER(dpms_timeout, TSTAMP_N_SECS(inactivity_timeout), turn_off_monitors_cb); break; case XCB_VISIBILITY_NOTIFY: handle_visibility_notify(conn, (xcb_visibility_notify_event_t*)event); break; case XCB_MAP_NOTIFY: if (!dont_fork) { /* After the first MapNotify, we never fork again. We don’t * expect to get another MapNotify, but better be sure… */ dont_fork = true; /* In the parent process, we exit */ if (fork() != 0) exit(0); ev_loop_fork(EV_DEFAULT); } break; case XCB_CONFIGURE_NOTIFY: handle_screen_resize(); break; default: if (type == xkb_base_event) process_xkb_event(event); } free(event); } }
/* * Instead of polling the X connection socket we leave this to * xcb_poll_for_event() which knows better than we can ever know. * */ static void xcb_check_cb(EV_P_ ev_check *w, int revents) { xcb_generic_event_t *event; if (xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "X11 connection broke, did your server terminate?\n"); while ((event = xcb_poll_for_event(conn)) != NULL) { if (event->response_type == 0) { xcb_generic_error_t *error = (xcb_generic_error_t *)event; if (debug_mode) fprintf(stderr, "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); switch (type) { case XCB_BUTTON_PRESS: handle_button_press((xcb_button_press_event_t *)event); break; case XCB_KEY_PRESS: handle_key_press((xcb_key_press_event_t *)event); break; case XCB_VISIBILITY_NOTIFY: handle_visibility_notify(conn, (xcb_visibility_notify_event_t *)event); break; case XCB_MAP_NOTIFY: if (!dont_fork) { /* After the first MapNotify, we never fork again. We don’t * expect to get another MapNotify, but better be sure… */ dont_fork = true; /* In the parent process, we exit */ if (fork() != 0) exit(0); ev_loop_fork(EV_DEFAULT); } break; case XCB_CONFIGURE_NOTIFY: handle_screen_resize(); break; default: if (type == xkb_base_event) process_xkb_event(event); } free(event); } }
/* * 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); } }
/* * Instead of polling the X connection socket we leave this to * xcb_poll_for_event() which knows better than we can ever know. * */ static void xcb_check_cb(EV_P_ ev_check *w, int revents) { xcb_generic_event_t *event; if (xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "X11 connection broke, did your server terminate?\n"); while ((event = xcb_poll_for_event(conn)) != NULL) { if (event->response_type == 0) { xcb_generic_error_t *error = (xcb_generic_error_t *)event; /* Ignore errors when damage report is about destroyed window * or damage object is created for already destroyed window */ if (error->major_code == dam_ext_data->major_opcode && (error->minor_code == XCB_DAMAGE_SUBTRACT || error->minor_code == XCB_DAMAGE_CREATE)) { free(event); continue; } if (debug_mode) fprintf(stderr, "X11 Error received! sequence 0x%x, error_code " "= %d, major = 0x%x, minor = 0x%x\n", error->sequence, error->error_code, error->major_code, error->minor_code); free(event); continue; } if (fuzzy && event->response_type == dam_ext_data->first_event + XCB_DAMAGE_NOTIFY) { xcb_damage_notify_event_t *ev = (xcb_damage_notify_event_t *)event; xcb_damage_subtract(conn, ev->damage, XCB_NONE, XCB_NONE); redraw_screen(); } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_KEY_PRESS: handle_key_press((xcb_key_press_event_t *)event); break; case XCB_VISIBILITY_NOTIFY: handle_visibility_notify( conn, (xcb_visibility_notify_event_t *)event); break; case XCB_MAP_NOTIFY: handle_map_notify((xcb_map_notify_event_t *)event); break; case XCB_CONFIGURE_NOTIFY: handle_screen_resize(); break; default: if (type == xkb_base_event) process_xkb_event(event); } free(event); } }