@ -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 ) ;