diff options
author | Dave Davenport <qball@gmpclient.org> | 2015-07-28 22:22:18 +0200 |
---|---|---|
committer | Dave Davenport <qball@gmpclient.org> | 2015-07-28 22:22:18 +0200 |
commit | 93c01ccbd55497d1f70aef447d7a0aa04e7ecf57 (patch) | |
tree | b80df6cc9e025523f6e52a3a67fa30e6343b20fb /source | |
parent | b3a77589eb4210058e7ecda66eb8d6996d5bdf9c (diff) |
Add new event handling
Diffstat (limited to 'source')
-rw-r--r-- | source/helper.c | 44 | ||||
-rw-r--r-- | source/rofi.c | 233 |
2 files changed, 211 insertions, 66 deletions
diff --git a/source/helper.c b/source/helper.c index 1845022c..229d4ac1 100644 --- a/source/helper.c +++ b/source/helper.c @@ -148,11 +148,7 @@ int helper_parse_setup ( char * string, char ***output, int *length, ... ) if ( error ) { char *msg = g_strdup_printf ( "Failed to parse: '%s'\nError: '%s'", string, error->message ); -#ifdef error_dialog - error_dialog ( msg ); -#else - fputs ( msg, stderr ); -#endif + error_dialog ( msg, FALSE ); g_free ( msg ); // print error. g_error_free ( error ); @@ -396,11 +392,7 @@ int execute_generator ( const char * cmd ) if ( error != NULL ) { char *msg = g_strdup_printf ( "Failed to execute: '%s'\nError: '%s'", cmd, error->message ); -#ifdef error_dialog - error_dialog ( msg ); -#else - fputs ( msg, stderr ); -#endif + error_dialog ( msg, FALSE ); g_free ( msg ); // print error. g_error_free ( error ); @@ -464,23 +456,37 @@ void config_sanity_check ( ) "Please see the manpage: %s -help for the correct syntax.", stored_argv[0] ); exit ( EXIT_FAILURE ); } + int found_error = FALSE; + GString *msg = g_string_new ( "<big><b>The configuration failed to validate:</b></big>\n" ); if ( config.element_height < 1 ) { - fprintf ( stderr, "config.element_height is invalid. It needs to be atleast 1 line high.\n" ); - exit ( 1 ); + g_string_append_printf ( msg, "\t<b>config.element_height</b>=%d is invalid. An element needs to be atleast 1 line high.\n", + config.element_height ); + config.element_height = 1; + found_error = TRUE; } if ( config.menu_columns == 0 ) { - fprintf ( stderr, "config.menu_columns is invalid. You need at least one visible column.\n" ); - exit ( 1 ); + g_string_append_printf ( msg, "\t<b>config.menu_columns</b>=%d is invalid. You need at least one visible column.\n", + config.menu_columns ); + config.menu_columns = 1; + found_error = TRUE; } if ( config.menu_width == 0 ) { - fprintf ( stderr, "config.menu_width is invalid. You cannot have a window with no width.\n" ); - exit ( 1 ); + show_error_message ( "<b>config.menu_width</b>=0 is invalid. You cannot have a window with no width.", TRUE ); + config.menu_columns = 50; + found_error = TRUE; } if ( !( config.location >= WL_CENTER && config.location <= WL_WEST ) ) { - fprintf ( stderr, "config.location is invalid. ( %d >= %d >= %d) does not hold.\n", - WL_WEST, config.location, WL_CENTER ); - exit ( 1 ); + g_string_append_printf ( msg, "\t<b>config.location</b>=%d is invalid. Value should be between %d and %d.\n", + config.location, WL_CENTER, WL_WEST ); + config.location = WL_CENTER; + found_error = 1; + } + if ( found_error ) { + g_string_append ( msg, "Please update your configuration." ); + show_error_message ( msg->str, TRUE ); } + + g_string_free ( msg, TRUE ); // If alternative row is not set, copy the normal background color. if ( config.menu_bg_alt == NULL ) { config.menu_bg_alt = config.menu_bg; diff --git a/source/rofi.c b/source/rofi.c index ea2e50f1..5bfd2622 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -1483,31 +1483,28 @@ static int run_dmenu () XFreeColormap ( display, map ); map = None; } + // Release the window. + release_keyboard ( display ); + if ( main_window != None ) { + XUnmapWindow ( display, main_window ); + XDestroyWindow ( display, main_window ); + main_window = None; + XFreeGC ( display, gc ); + gc = NULL; + } + // Cleanup pid file. + if ( pidfile ) { + unlink ( pidfile ); + } return ret_state; } -static void run_switcher ( int do_fork, SwitcherMode mode ) +static void run_switcher ( SwitcherMode mode ) { - // we fork because it's technically possible to have multiple window - // lists up at once on a zaphod multihead X setup. - // this also happens to isolate the Xft font stuff in a child process - // that gets cleaned up every time. That library shows some valgrind - // strangeness... - if ( do_fork == TRUE ) { - if ( fork () ) { - return; - } - - display = XOpenDisplay ( display_str ); - XSync ( display, True ); - } // Create pid file to avoid multiple instances. create_pid_file ( pidfile ); // Create the colormap and the main visual. create_visual_and_colormap ( display ); - - // Because of the above fork, we want to do this here. - // Make sure this is isolated to its own thread. textbox_setup ( &vinfo, map ); // Otherwise check if requested mode is enabled. char *input = NULL; @@ -1548,13 +1545,23 @@ static void run_switcher ( int do_fork, SwitcherMode mode ) // Cleanup font setup. textbox_cleanup ( ); + + // Release the window. + release_keyboard ( display ); + if ( main_window != None ) { + XUnmapWindow ( display, main_window ); + XDestroyWindow ( display, main_window ); + main_window = None; + XFreeGC ( display, gc ); + gc = NULL; + } if ( map != None ) { XFreeColormap ( display, map ); map = None; } - - if ( do_fork == TRUE ) { - exit ( EXIT_SUCCESS ); + // Cleanup pid file. + if ( pidfile ) { + unlink ( pidfile ); } } @@ -1568,7 +1575,7 @@ static void handle_keypress ( XEvent *ev ) KeySym key = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 ); index = locate_switcher ( key, ev->xkey.state ); if ( index >= 0 ) { - run_switcher ( TRUE, index ); + run_switcher ( index ); } else { fprintf ( stderr, "Warning: Unhandled keypress in global keyhandler, keycode = %u mask = %u\n", ev->xkey.keycode, ev->xkey.state ); @@ -1604,10 +1611,7 @@ static void cleanup () XCloseDisplay ( display ); } } - // Cleanup pid file. - if ( pidfile ) { - unlink ( pidfile ); - } + // Cleaning up memory allocated by the Xresources file. config_xresource_free (); @@ -1716,7 +1720,7 @@ static inline void load_configuration_dynamic ( Display *display ) } -static void show_error_message ( const char *msg, int markup ) +void show_error_message ( const char *msg, int markup ) { // Create pid file create_pid_file ( pidfile ); @@ -1730,6 +1734,79 @@ static void show_error_message ( const char *msg, int markup ) XFreeColormap ( display, map ); map = None; } + // Cleanup font setup. + textbox_cleanup ( ); + + // Release the window. + release_keyboard ( display ); + if ( main_window != None ) { + XUnmapWindow ( display, main_window ); + XDestroyWindow ( display, main_window ); + main_window = None; + XFreeGC ( display, gc ); + gc = NULL; + } + if ( map != None ) { + XFreeColormap ( display, map ); + map = None; + } + // Cleanup pid file. + if ( pidfile ) { + unlink ( pidfile ); + } +} + +static void * pthread_signal_process ( void *arg ) +{ + int pfd = *( (int *) arg ); + + // Create same mask again. + sigset_t set; + sigemptyset ( &set ); + sigaddset ( &set, SIGHUP ); + sigaddset ( &set, SIGINT ); + sigaddset ( &set, SIGUSR1 ); + // loop forever. + while ( 1 ) { + siginfo_t info; + int sig = sigwaitinfo ( &set, &info ); + if ( sig < 0 ) { + perror ( "sigwaitinfo failed" ); + } + else { + // Send message to main thread. + if ( sig == SIGHUP ) { + write ( pfd, "c", 1 ); + } + if ( sig == SIGUSR1 ) { + write ( pfd, "i", 1 ); + } + else if ( sig == SIGINT ) { + write ( pfd, "q", 1 ); + // Close my end and exit. + return NULL; + } + } + } +} + + +static void reload_configuration () +{ + if ( find_arg ( "-no-config" ) < 0 ) { + // We need to open a new connection to X11, otherwise we get old + // configuration + Display *display = XOpenDisplay ( display_str ); + if ( display ) { + load_configuration ( display ); + load_configuration_dynamic ( display ); + + // Sanity check + config_sanity_check ( ); + parse_keys_abe (); + XCloseDisplay ( display ); + } + } } int main ( int argc, char *argv[] ) @@ -1816,6 +1893,15 @@ int main ( int argc, char *argv[] ) // Reload for dynamic part. load_configuration_dynamic ( display ); } + + // Set up X interaction. + const struct sigaction sigchld_action = { + .sa_handler = catch_exit + }; + sigaction ( SIGCHLD, &sigchld_action, NULL ); + + x11_setup ( display ); + // Sanity check config_sanity_check ( ); // Dump. @@ -1826,14 +1912,6 @@ int main ( int argc, char *argv[] ) // Parse the keybindings. parse_keys_abe (); - // Set up X interaction. - const struct sigaction sigchld_action = { - .sa_handler = catch_exit - }; - sigaction ( SIGCHLD, &sigchld_action, NULL ); - - x11_setup ( display ); - char *msg = NULL; if ( find_arg_str ( "-e", &( msg ) ) ) { int markup = FALSE; @@ -1866,7 +1944,7 @@ int main ( int argc, char *argv[] ) if ( find_arg_str ( "-show", &sname ) == TRUE ) { int index = switcher_get ( sname ); if ( index >= 0 ) { - run_switcher ( FALSE, index ); + run_switcher ( index ); } else { fprintf ( stderr, "The %s switcher has not been enabled\n", sname ); @@ -1909,24 +1987,85 @@ int main ( int argc, char *argv[] ) } } + sigset_t set; + + // Create a pipe to communicate between signal thread an main thread. + int pfds[2]; + pipe ( pfds ); + // Block all HUP signals. + // In this and other child (they inherit mask) + sigemptyset ( &set ); + sigaddset ( &set, SIGHUP ); + sigaddset ( &set, SIGINT ); + sigaddset ( &set, SIGUSR1 ); + sigprocmask ( SIG_BLOCK, &set, NULL ); + // Create signal handler process. + GThread *pid_signal_proc = g_thread_new ( + "signal_process", + pthread_signal_process, + (void *) &( pfds[1] ) ); + // Application Main loop. // This listens in the background for any events on the Xserver // catching global key presses. + // It also listens from messages from the signal process. + XSelectInput ( display, DefaultRootWindow ( display ), KeyPressMask ); + XFlush ( display ); + int x11_fd = ConnectionNumber ( display ); for (;; ) { - XEvent ev; - - // block and wait for something - XNextEvent ( display, &ev ); - // If we get an event that does not belong to a window: - // Ignore it. - if ( ev.xany.window == None ) { - continue; - } - // If keypress, handle it. - if ( ev.type == KeyPress ) { - handle_keypress ( &ev ); + fd_set in_fds; + // Create a File Description Set containing x11_fd + FD_ZERO ( &in_fds ); + FD_SET ( x11_fd, &in_fds ); + FD_SET ( pfds[0], &in_fds ); + + // Wait for X Event or a Timer + if ( select ( MAX ( x11_fd, pfds[0] ) + 1, &in_fds, 0, 0, NULL ) >= 0 ) { + if ( FD_ISSET ( x11_fd, &in_fds ) ) { + // X11 produced an event. Consume them. + XEvent ev; + while ( XPending ( display ) ) { + // block and wait for something + XNextEvent ( display, &ev ); + // If we get an event that does not belong to a window: + // Ignore it. + if ( ev.xany.window == None ) { + continue; + } + // If keypress, handle it. + if ( ev.type == KeyPress ) { + handle_keypress ( &ev ); + } + } + } + if ( FD_ISSET ( pfds[0], &in_fds ) ) { + // The signal thread send us a message. Process it. + char c; + read ( pfds[0], &c, 1 ); + // Reload configuration. + if ( c == 'c' ) { + fprintf ( stdout, "Reload configuration\n" ); + reload_configuration (); + } + // Got message to quit. + else if ( c == 'q' ) { + // Break out of loop. + break; + } + // Got message to print info + else if ( c == 'i' ) { + xresource_dump (); + } + } } } + // Join the signal process thread. (at this point it should have exited). + // this also unrefs (de-allocs) the GThread object. + g_thread_join ( pid_signal_proc ); + // Close pipe + close ( pfds[0] ); + close ( pfds[1] ); + fprintf ( stdout, "Quit from daemon mode.\n" ); } return EXIT_SUCCESS; |