diff --git a/Makefile.am b/Makefile.am index e3af6059..a0a94446 100644 --- a/Makefile.am +++ b/Makefile.am @@ -224,6 +224,8 @@ test-x: ${bin_PROGRAMS} $(top_srcdir)/test/run_test.sh 217 $(top_srcdir)/test/run_fuzzy_test.sh $(top_builddir) echo "Test config dump" $(top_srcdir)/test/run_test.sh 218 $(top_srcdir)/test/xr_config_test.sh $(top_builddir) $(top_srcdir) + echo "Test issue 333" + $(top_srcdir)/test/run_test.sh 221 $(top_srcdir)/test/run_ssue_333.sh $(top_builddir) test-x1: ${bin_PROGRAMS} echo "Test dmenu-normal-window" diff --git a/script/rofi-sensible-terminal b/script/rofi-sensible-terminal index ca86148d..c88e0c52 100755 --- a/script/rofi-sensible-terminal +++ b/script/rofi-sensible-terminal @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This code is released in public domain by Han Boetes # Updated by Dave Davenport diff --git a/source/dialogs/dmenu.c b/source/dialogs/dmenu.c index cb59f853..04f54f7b 100644 --- a/source/dialogs/dmenu.c +++ b/source/dialogs/dmenu.c @@ -427,25 +427,28 @@ int dmenu_switcher_dialog ( void ) * Select item mode. */ restart = 1; - if ( ( mretv & ( MENU_OK | MENU_QUICK_SWITCH ) ) && cmd_list[pd->selected_line] != NULL ) { - dmenu_output_formatted_line ( pd->format, cmd_list[pd->selected_line], pd->selected_line, input ); - retv = TRUE; - if ( ( mretv & MENU_QUICK_SWITCH ) ) { - retv = 10 + ( mretv & MENU_LOWER_MASK ); - } - return retv; - } - else if ( ( mretv & MENU_CANCEL ) == MENU_CANCEL ) { + // Skip if no valid item is selected. + if ( ( mretv & MENU_CANCEL ) == MENU_CANCEL ) { // In no custom mode we allow canceling. restart = ( find_arg ( "-only-match" ) >= 0 ); } - pd->selected_line = next_pos - 1; + else if ( pd->selected_line != UINT32_MAX ) { + if ( ( mretv & ( MENU_OK | MENU_QUICK_SWITCH ) ) && cmd_list[pd->selected_line] != NULL ) { + dmenu_output_formatted_line ( pd->format, cmd_list[pd->selected_line], pd->selected_line, input ); + retv = TRUE; + if ( ( mretv & MENU_QUICK_SWITCH ) ) { + retv = 10 + ( mretv & MENU_LOWER_MASK ); + } + return retv; + } + pd->selected_line = next_pos - 1; + } continue; } // We normally do not want to restart the loop. restart = FALSE; // Normal mode - if ( ( mretv & MENU_OK ) && cmd_list[pd->selected_line] != NULL ) { + if ( ( mretv & MENU_OK ) && pd->selected_line != UINT32_MAX && cmd_list[pd->selected_line] != NULL ) { dmenu_output_formatted_line ( pd->format, cmd_list[pd->selected_line], pd->selected_line, input ); if ( ( mretv & MENU_SHIFT ) ) { restart = TRUE; diff --git a/source/i3-support.c b/source/i3-support.c index f8bd3ea0..278d5f72 100644 --- a/source/i3-support.c +++ b/source/i3-support.c @@ -50,7 +50,7 @@ char *i3_socket_path = NULL; void i3_support_focus_window ( Window id ) { i3_ipc_header_t head; - int s, len; + int s; ssize_t t; struct sockaddr_un remote; size_t upm = sizeof ( remote.sun_path ); @@ -68,9 +68,8 @@ void i3_support_focus_window ( Window id ) remote.sun_family = AF_UNIX; g_strlcpy ( remote.sun_path, i3_socket_path, upm ); - len = strlen ( remote.sun_path ) + sizeof ( remote.sun_family ); - if ( connect ( s, ( struct sockaddr * ) &remote, len ) == -1 ) { + if ( connect ( s, ( struct sockaddr * ) &remote, sizeof ( struct sockaddr_un ) ) == -1 ) { fprintf ( stderr, "Failed to connect to I3 (%s): %s\n", i3_socket_path, strerror ( errno ) ); close ( s ); return; diff --git a/source/rofi.c b/source/rofi.c index b74f8528..9d33af19 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -1422,6 +1422,7 @@ static void menu_mainloop_iter ( MenuState *state, XEvent *ev ) } for ( unsigned int a = CUSTOM_1; a <= CUSTOM_19; a++ ) { if ( abe_test_action ( a, ev->xkey.state, key ) ) { + state->selected_line = UINT32_MAX; if ( state->selected < state->filtered_lines ) { ( state->selected_line ) = state->line_map[state->selected]; } @@ -1446,6 +1447,7 @@ static void menu_mainloop_iter ( MenuState *state, XEvent *ev ) int shift = ( ( ev->xkey.state & ShiftMask ) == ShiftMask ); // If a valid item is selected, return that.. + state->selected_line = UINT32_MAX; if ( state->selected < state->filtered_lines ) { ( state->selected_line ) = state->line_map[state->selected]; if ( strlen ( state->text->text ) > 0 && rc == -2 ) { @@ -1613,8 +1615,7 @@ MenuState *menu ( Mode *sw, state->top_offset = state->border * 1 + state->line_height + 2 + config.line_margin * 2; // Move indicator to end. - widget_move ( WIDGET ( state->case_indicator ), state->border + textbox_get_width ( state->prompt_tb ) + entrybox_width, - state->border ); + widget_move ( WIDGET ( state->case_indicator ), state->border + textbox_get_width ( state->prompt_tb ) + entrybox_width, state->border ); textbox_text ( state->case_indicator, get_matching_state () ); state->message_tb = NULL; @@ -1779,6 +1780,7 @@ void error_dialog ( const char *msg, int markup ) } menu_state_set_active ( NULL ); menu_state_free ( state ); + release_keyboard ( display ); } /** @@ -2075,6 +2077,60 @@ static void cleanup () * First the three build-in modi are checked: window, run, ssh * if that fails, a script-switcher is created. */ +static int add_mode ( const char * token ) +{ + unsigned int index = num_modi; + // Resize and add entry. + modi = (ModeHolder *) g_realloc ( modi, sizeof ( ModeHolder ) * ( num_modi + 1 ) ); + modi[num_modi].tb = NULL; + + // Window switcher. +#ifdef WINDOW_MODE + if ( strcasecmp ( token, "window" ) == 0 ) { + modi[num_modi].sw = &window_mode; + num_modi++; + } + else if ( strcasecmp ( token, "windowcd" ) == 0 ) { + modi[num_modi].sw = &window_mode_cd; + num_modi++; + } + else +#endif // WINDOW_MODE + // SSh dialog + if ( strcasecmp ( token, "ssh" ) == 0 ) { + modi[num_modi].sw = &ssh_mode; + num_modi++; + } + // Run dialog + else if ( strcasecmp ( token, "run" ) == 0 ) { + modi[num_modi].sw = &run_mode; + num_modi++; + } + else if ( strcasecmp ( token, "drun" ) == 0 ) { + modi[num_modi].sw = &drun_mode; + num_modi++; + } + // combi dialog + else if ( strcasecmp ( token, "combi" ) == 0 ) { + modi[num_modi].sw = &combi_mode; + num_modi++; + } + else { + // If not build in, use custom modi. + Mode *sw = script_switcher_parse_setup ( token ); + if ( sw != NULL ) { + modi[num_modi].sw = sw; + mode_set_config ( sw ); + num_modi++; + } + else{ + // Report error, don't continue. + fprintf ( stderr, "Invalid script switcher: %s\n", token ); + token = NULL; + } + } + return ( index == num_modi ) ? -1 : (int) index; +} static void setup_modi ( void ) { char *savept = NULL; @@ -2082,56 +2138,7 @@ static void setup_modi ( void ) char *switcher_str = g_strdup ( config.modi ); // Split token on ','. This modifies switcher_str. for ( char *token = strtok_r ( switcher_str, ",", &savept ); token != NULL; token = strtok_r ( NULL, ",", &savept ) ) { - // Resize and add entry. - modi = (ModeHolder *) g_realloc ( modi, sizeof ( ModeHolder ) * ( num_modi + 1 ) ); - modi[num_modi].tb = NULL; - - // Window switcher. - #ifdef WINDOW_MODE - if ( strcasecmp ( token, "window" ) == 0 ) { - modi[num_modi].sw = &window_mode; - num_modi++; - } - else if ( strcasecmp ( token, "windowcd" ) == 0 ) { - modi[num_modi].sw = &window_mode_cd; - num_modi++; - } - else - #endif // WINDOW_MODE - // SSh dialog - if ( strcasecmp ( token, "ssh" ) == 0 ) { - modi[num_modi].sw = &ssh_mode; - num_modi++; - } - // Run dialog - else if ( strcasecmp ( token, "run" ) == 0 ) { - modi[num_modi].sw = &run_mode; - num_modi++; - } - else if ( strcasecmp ( token, "drun" ) == 0 ) { - modi[num_modi].sw = &drun_mode; - num_modi++; - } - // combi dialog - else if ( strcasecmp ( token, "combi" ) == 0 ) { - modi[num_modi].sw = &combi_mode; - num_modi++; - } - else { - // If not build in, use custom modi. - Mode *sw = script_switcher_parse_setup ( token ); - if ( sw != NULL ) { - modi[num_modi].sw = sw; - mode_set_config ( sw ); - num_modi++; - } - else{ - // Report error, don't continue. - fprintf ( stderr, "Invalid script switcher: %s\n", token ); - token = NULL; - } - } - // Keybinding. + add_mode ( token ); } // Free string that was modified by strtok_r g_free ( switcher_str ); @@ -2207,6 +2214,8 @@ static void reload_configuration () } } + + /** * Process X11 events in the main-loop (gui-thread) of the application. */ @@ -2495,6 +2504,17 @@ int main ( int argc, char *argv[] ) char *sname = NULL; if ( find_arg_str ( "-show", &sname ) == TRUE ) { int index = switcher_get ( sname ); + if ( index < 0 ) { + // Add it to the list + index = add_mode ( sname ); + // Complain + if ( index >= 0 ) { + fprintf ( stdout, "Mode %s not enabled. Please add it to the list of enabled modi: %s\n", + sname, config.modi ); + fprintf ( stdout, "Adding mode: %s\n", sname ); + } + // Run it anyway if found. + } if ( index >= 0 ) { run_switcher ( index ); g_idle_add ( delayed_start, GINT_TO_POINTER ( index ) ); diff --git a/test/run_issue333_test.sh b/test/run_issue333_test.sh new file mode 100755 index 00000000..1fb98548 --- /dev/null +++ b/test/run_issue333_test.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# wait till it is up, run rofi with error message +rm -f output.txt +sleep 1; +echo -e -n "aap\nnoot\nmies" | rofi -dmenu -no-custom -kb-custom-1 F5 -kb-custom-2 "Control+a" > output.txt & +RPID=$! + +# send enter. +sleep 5; +xdotool key 'q' +sleep 0.4 +xdotool key Return +sleep 0.4 +xdotool key F5 +sleep 0.4 +xdotool key "Control+a" +sleep 0.4 +xdotool key Escape + +# Get result, kill xvfb +wait ${RPID} +RETV=$? +OUTPUT=$(cat output.txt | tr '\n' ' ') +if [ "${OUTPUT}" != '' ] +then + echo "Got: '${OUTPUT}' expected nothing" + exit 1 +fi +if [ ${RETV} != 1 ] +then + exit 1 +fi