From c68ab67dd88c48d0f2b61a7aff606104a86e71ca Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Wed, 29 Jul 2015 09:37:40 +0200 Subject: [PATCH] Add some comments and cleanups, allow reeloading of keybindings at run-time --- include/x11-helper.h | 9 +++++ source/rofi.c | 92 ++++++++++++++++++++++++++++++++------------ source/x11-helper.c | 17 +++++++- 3 files changed, 92 insertions(+), 26 deletions(-) diff --git a/include/x11-helper.h b/include/x11-helper.h index 110b230d..4531dfa1 100644 --- a/include/x11-helper.h +++ b/include/x11-helper.h @@ -92,6 +92,15 @@ int take_keyboard ( Display *display, Window w ); */ void x11_grab_key ( Display *display, unsigned int modmask, KeySym key ); +/** + * @param display Connection to the X server. + * @param modmask Modifier mask. + * @param key Key. + * + * Ungrab key on display. + */ +void x11_ungrab_key ( Display *display, unsigned int modmask, KeySym key ); + /** * @param combo String representing the key combo * @param mod [out] The modifier specified (or AnyModifier if not specified) diff --git a/source/rofi.c b/source/rofi.c index 463451ac..b0a33da6 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -1605,11 +1605,15 @@ static void cleanup () // Cleanup if ( display != NULL ) { if ( main_window != None ) { + // We should never hit this code. release_keyboard ( display ); XFreeGC ( display, gc ); + gc = NULL; XDestroyWindow ( display, main_window ); - XCloseDisplay ( display ); + main_window = None; } + XCloseDisplay ( display ); + display = NULL; } @@ -1753,7 +1757,18 @@ void show_error_message ( const char *msg, int markup ) } } -static void * pthread_signal_process ( void *arg ) +/** + * Separate thread that handles signals being send to rofi. + * Currently it listens for three signals: + * * HUP: reload the configuration. + * * INT: Quit the program. + * * USR1: Dump the current configuration to stdout. + * + * These messages are relayed to the main thread via a pipe, the write side of the pipe is passed + * as argument to this thread. + * When receiving a sig-int the thread quits. + */ +static gpointer pthread_signal_process ( gpointer arg ) { int pfd = *( (int *) arg ); @@ -1781,27 +1796,56 @@ static void * pthread_signal_process ( void *arg ) else if ( sig == SIGINT ) { write ( pfd, "q", 1 ); // Close my end and exit. - return NULL; + g_thread_exit ( NULL ); } } } } +static void release_global_keybindings () +{ + for ( unsigned int i = 0; i < num_switchers; i++ ) { + if ( switchers[i]->keystr != NULL ) { + // No need to parse key, this should be done when grabbing. + if ( switchers[i]->keysym != NoSymbol ) { + x11_ungrab_key ( display, switchers[i]->modmask, switchers[i]->keysym ); + } + } + } +} +static int grab_global_keybindings () +{ + int key_bound = FALSE; + for ( unsigned int i = 0; i < num_switchers; i++ ) { + if ( switchers[i]->keystr != NULL ) { + x11_parse_key ( switchers[i]->keystr, &( switchers[i]->modmask ), &( switchers[i]->keysym ) ); + if ( switchers[i]->keysym != NoSymbol ) { + x11_grab_key ( display, switchers[i]->modmask, switchers[i]->keysym ); + key_bound = TRUE; + } + } + } + return key_bound; +} 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 ); + Display *temp_display = XOpenDisplay ( display_str ); + if ( temp_display ) { + load_configuration ( temp_display ); + load_configuration_dynamic ( temp_display ); // Sanity check config_sanity_check ( ); parse_keys_abe (); - XCloseDisplay ( display ); + XCloseDisplay ( temp_display ); + } + else { + fprintf ( stderr, "Failed to get a new connection to the X11 server. No point in continuing.\n" ); + abort (); } } } @@ -1970,24 +2014,14 @@ int main ( int argc, char *argv[] ) } } else{ - int key_bound = FALSE; - unsigned int key_length = 0; // Daemon mode, Listen to key presses.. - for ( unsigned int i = 0; i < num_switchers; i++ ) { - key_length = MAX ( key_length, strlen ( switchers[i]->name ) ); - if ( switchers[i]->keystr != NULL ) { - x11_parse_key ( switchers[i]->keystr, &( switchers[i]->modmask ), &( switchers[i]->keysym ) ); - x11_grab_key ( display, switchers[i]->modmask, switchers[i]->keysym ); - key_bound = TRUE; - } - } - if ( !key_bound ) { + if ( !grab_global_keybindings () ) { fprintf ( stderr, "Rofi was launched in daemon mode, but no key-binding was specified.\n" ); fprintf ( stderr, "Please check the manpage on how to specify a key-binding.\n" ); fprintf ( stderr, "The following modi are enabled and keys can be specified:\n" ); for ( unsigned int i = 0; i < num_switchers; i++ ) { - fprintf ( stderr, "\t* "color_bold "%*s"color_reset ": -key-%s \n", - key_length, switchers[i]->name, switchers[i]->name ); + fprintf ( stderr, "\t* "color_bold "%s"color_reset ": -key-%s \n", + switchers[i]->name, switchers[i]->name ); } return EXIT_FAILURE; } @@ -1996,12 +2030,12 @@ int main ( int argc, char *argv[] ) fprintf ( stdout, "listening to the following keys:\n" ); for ( unsigned int i = 0; i < num_switchers; i++ ) { if ( switchers[i]->keystr != NULL ) { - fprintf ( stdout, "\t* "color_bold "%*s"color_reset " on %s\n", - key_length, switchers[i]->name, switchers[i]->keystr ); + fprintf ( stdout, "\t* "color_bold "%s"color_reset " on %s\n", + switchers[i]->name, switchers[i]->keystr ); } else { - fprintf ( stdout, "\t* "color_bold "%*s"color_reset " on \n", - key_length, switchers[i]->name ); + fprintf ( stdout, "\t* "color_bold "%s"color_reset " on \n", + switchers[i]->name ); } } } @@ -2057,7 +2091,13 @@ int main ( int argc, char *argv[] ) // Reload configuration. if ( c == 'c' ) { fprintf ( stdout, "Reload configuration\n" ); + // Release the keybindings. + release_global_keybindings (); + // Reload config reload_configuration (); + // Grab the possibly new keybindings. + grab_global_keybindings (); + XFlush ( display ); } // Got message to quit. else if ( c == 'q' ) { @@ -2071,6 +2111,8 @@ int main ( int argc, char *argv[] ) } } } + + release_global_keybindings (); // 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 ); diff --git a/source/x11-helper.c b/source/x11-helper.c index dd43f7b7..2c574e3e 100644 --- a/source/x11-helper.c +++ b/source/x11-helper.c @@ -276,6 +276,21 @@ void x11_grab_key ( Display *display, unsigned int modmask, KeySym key ) } } +void x11_ungrab_key ( Display *display, unsigned int modmask, KeySym key ) +{ + Screen *screen = DefaultScreenOfDisplay ( display ); + Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) ); + KeyCode keycode = XKeysymToKeycode ( display, key ); + + // unbind to combinations of mod and lock masks, so caps and numlock don't confuse people + XUngrabKey ( display, keycode, modmask, root ); + XUngrabKey ( display, keycode, modmask | LockMask, root ); + + if ( NumlockMask ) { + XUngrabKey ( display, keycode, modmask | NumlockMask, root ); + XUngrabKey ( display, keycode, modmask | NumlockMask | LockMask, root ); + } +} /** * @param display The connection to the X server. * @@ -345,8 +360,8 @@ void x11_parse_key ( char *combo, unsigned int *mod, KeySym *key ) KeySym sym = XStringToKeysym ( combo + i ); if ( sym == NoSymbol || ( !modmask && ( strchr ( combo, '-' ) || strchr ( combo, '+' ) ) ) ) { + // TODO popup fprintf ( stderr, "sorry, cannot understand key combination: %s\n", combo ); - exit ( EXIT_FAILURE ); } *key = sym;