From 011908e1ffda06d09c9f163867cb6a7d68fd6c20 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Sun, 13 Sep 2020 21:56:25 +0200 Subject: [PATCH] issue 1187: If error on launching application, show error message and return to list` (#1193) * Show error message, then possibly pop back to main window. Fix drun/run dialog to use this for command execution. Issue #1187 * [Combi] When no line selected, handle using the first entry. * [Window] Add execute on invalid input to window dialog. * Update view.h doxygen docu * Update manpage with running application changes. --- doc/rofi.1 | 7 +++++++ doc/rofi.1.markdown | 5 +++++ include/view.h | 15 +++++++++++++-- source/dialogs/combi.c | 3 +++ source/dialogs/drun.c | 7 ++++++- source/dialogs/run.c | 22 +++++++++++++++------- source/dialogs/window.c | 17 +++++++++++++++++ source/rofi.c | 10 ++++++++-- source/view.c | 12 ++++++++++++ 9 files changed, 86 insertions(+), 12 deletions(-) diff --git a/doc/rofi.1 b/doc/rofi.1 index e31017f7..3a6143d1 100644 --- a/doc/rofi.1 +++ b/doc/rofi.1 @@ -1518,6 +1518,9 @@ Pressing the \fB\fCdelete\-entry\fR binding (\fB\fCshift\-delete\fR) will kill t Pressing the \fB\fCaccept\-custom\fR binding (\fB\fCcontrol\-enter\fR or \fB\fCshift\-enter\fR) will run a command on the window. (See option \fB\fCwindow\-command\fR ); +.PP +If there is no match, it will try to launch the input. + .SS run .PP Shows a list of executables in \fB\fC$PATH\fR and can launch them (optional in a terminal). @@ -1529,6 +1532,7 @@ Pressing the \fB\fCaccept\-custom\fR binding (\fB\fCcontrol\-enter\fR or \fB\fCs Same as the \fBrun\fP launches, but the list is created from the installed desktop files. It automatically launches them in a terminal if specified in the Desktop File. Pressing the \fB\fCdelete\-entry\fR binding (\fB\fCshift\-delete\fR) will remove this entry from the run history. +Pressing the \fB\fCaccept\-custom\fR binding (\fB\fCcontrol\-enter\fR or \fB\fCshift\-enter\fR) will run the command in a terminal. .SS ssh .PP @@ -1553,6 +1557,9 @@ For example, say you have specified \fB\fC\-combi\-modi run,window,windowcd\fR\& query begins with the bang \fB\fC!w\fR, only results from the \fB\fCwindow\fR and \fB\fCwindowcd\fR modi are shown, even if the rest of the input text would match results from \fB\fCrun\fR\&. +.PP +If no match, the input is handled by the first combined modi. + .SH FAQ .SS The text in the window switcher is not nicely aligned. .PP diff --git a/doc/rofi.1.markdown b/doc/rofi.1.markdown index 78152e40..d2965270 100644 --- a/doc/rofi.1.markdown +++ b/doc/rofi.1.markdown @@ -921,6 +921,8 @@ Pressing the `delete-entry` binding (`shift-delete`) will kill the window. Pressing the `accept-custom` binding (`control-enter` or `shift-enter`) will run a command on the window. (See option `window-command` ); +If there is no match, it will try to launch the input. + ### run Shows a list of executables in `$PATH` and can launch them (optional in a terminal). @@ -932,6 +934,7 @@ Pressing the `accept-custom` binding (`control-enter` or `shift-enter`) will run Same as the **run** launches, but the list is created from the installed desktop files. It automatically launches them in a terminal if specified in the Desktop File. Pressing the `delete-entry` binding (`shift-delete`) will remove this entry from the run history. +Pressing the `accept-custom` binding (`control-enter` or `shift-enter`) will run the command in a terminal. ### ssh @@ -955,6 +958,8 @@ For example, say you have specified `-combi-modi run,window,windowcd`. If your query begins with the bang `!w`, only results from the `window` and `windowcd` modi are shown, even if the rest of the input text would match results from `run`. +If no match, the input is handled by the first combined modi. + ## FAQ ### The text in the window switcher is not nicely aligned. diff --git a/include/view.h b/include/view.h index f5deac96..a91d0e3d 100644 --- a/include/view.h +++ b/include/view.h @@ -187,13 +187,23 @@ void rofi_view_free ( RofiViewState *state ); RofiViewState * rofi_view_get_active ( void ); /** - * @param state the new active view handle, NULL to clear. + * @param state the new active view handle. * - * Set the current active view Handle. + * Set the current active view Handle, If NULL passed a queued view is popped + * from stack. * */ + void rofi_view_set_active ( RofiViewState *state ); +/** + * @param state remove view handle. + * + * remove state handle from queue, if current view, pop view from + * stack. + * + */ +void rofi_view_remove_active ( RofiViewState *state ); /** * @param msg The error message to show. * @param markup The error message uses pango markup. @@ -265,6 +275,7 @@ void rofi_view_clear_input ( RofiViewState *state ); * TODO: Internal call to view exposed. */ void __create_window ( MenuFlags menu_flags ); + /** * Get the handle of the main window. * diff --git a/source/dialogs/combi.c b/source/dialogs/combi.c index 86d92ba5..ab6a9a62 100644 --- a/source/dialogs/combi.c +++ b/source/dialogs/combi.c @@ -180,6 +180,9 @@ static ModeMode combi_mode_result ( Mode *sw, int mretv, char **input, unsigned return mode_result ( pd->switchers[i].mode, mretv, input, selected_line - pd->starts[i] ); } } + if ( ( mretv & MENU_CUSTOM_INPUT ) ) { + return mode_result ( pd->switchers[0].mode, mretv, input, selected_line ); + } return MODE_EXIT; } static int combi_mode_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index ) diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index aac7a934..94200cbc 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -1041,7 +1041,12 @@ static ModeMode drun_mode_result ( Mode *sw, int mretv, char **input, unsigned i } } else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) { - retv = RELOAD_DIALOG; + RofiHelperExecuteContext context = { .name = NULL }; + gboolean run_in_term = ( ( mretv & MENU_CUSTOM_ACTION ) == MENU_CUSTOM_ACTION ); + // FIXME: We assume startup notification in terminals, not in others + if ( ! helper_execute_command ( NULL, *input, run_in_term, run_in_term ? &context : NULL ) ) { + retv = RELOAD_DIALOG; + } } else if ( ( mretv & MENU_ENTRY_DELETE ) && selected_line < rmpd->cmd_list_length ) { // Possitive sort index means it is in history. diff --git a/source/dialogs/run.c b/source/dialogs/run.c index 0d223052..5e0c064a 100644 --- a/source/dialogs/run.c +++ b/source/dialogs/run.c @@ -78,18 +78,18 @@ typedef struct * * Execute command and add to history. */ -static void exec_cmd ( const char *cmd, int run_in_term ) +static gboolean exec_cmd ( const char *cmd, int run_in_term ) { GError *error = NULL; if ( !cmd || !cmd[0] ) { - return; + return FALSE; } gsize lf_cmd_size = 0; gchar *lf_cmd = g_locale_from_utf8 ( cmd, -1, NULL, &lf_cmd_size, &error ); if ( error != NULL ) { g_warning ( "Failed to convert command to locale encoding: %s", error->message ); g_error_free ( error ); - return; + return FALSE; } char *path = g_build_filename ( cache_dir, RUN_CACHE_FILE, NULL ); @@ -102,12 +102,16 @@ static void exec_cmd ( const char *cmd, int run_in_term ) */ history_set ( path, cmd ); + g_free ( path ); + g_free ( lf_cmd ); + return TRUE; } else { history_remove ( path, cmd ); + g_free ( path ); + g_free ( lf_cmd ); + return FALSE; } - g_free ( path ); - g_free ( lf_cmd ); } /** @@ -371,10 +375,14 @@ static ModeMode run_mode_result ( Mode *sw, int mretv, char **input, unsigned in gboolean run_in_term = ( ( mretv & MENU_CUSTOM_ACTION ) == MENU_CUSTOM_ACTION ); if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line] != NULL ) { - exec_cmd ( rmpd->cmd_list[selected_line], run_in_term ); + if ( !exec_cmd ( rmpd->cmd_list[selected_line], run_in_term ) ) { + retv = RELOAD_DIALOG; + } } else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) { - exec_cmd ( *input, run_in_term ); + if ( !exec_cmd ( *input, run_in_term ) ) { + retv = RELOAD_DIALOG; + } } else if ( ( mretv & MENU_ENTRY_DELETE ) && rmpd->cmd_list[selected_line] ) { delete_entry ( rmpd->cmd_list[selected_line] ); diff --git a/source/dialogs/window.c b/source/dialogs/window.c index 1060068e..e0eff96a 100644 --- a/source/dialogs/window.c +++ b/source/dialogs/window.c @@ -697,6 +697,23 @@ static ModeMode window_mode_result ( Mode *sw, int mretv, G_GNUC_UNUSED char **i xcb_ewmh_request_close_window ( &( xcb->ewmh ), xcb->screen_nbr, rmpd->ids->array[selected_line], XCB_CURRENT_TIME, XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER ); xcb_flush ( xcb->connection ); } + else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) { + GError *error = NULL; + gboolean run_in_term = ( ( mretv & MENU_CUSTOM_ACTION ) == MENU_CUSTOM_ACTION ); + gsize lf_cmd_size = 0; + gchar *lf_cmd = g_locale_from_utf8 ( *input, -1, NULL, &lf_cmd_size, &error ); + if ( error != NULL ) { + g_warning ( "Failed to convert command to locale encoding: %s", error->message ); + g_error_free ( error ); + return RELOAD_DIALOG; + } + + RofiHelperExecuteContext context = { .name = NULL }; + if ( ! helper_execute_command ( NULL, lf_cmd, run_in_term, run_in_term ? &context : NULL ) ) { + retv = RELOAD_DIALOG; + } + g_free ( lf_cmd ); + } return retv; } diff --git a/source/rofi.c b/source/rofi.c index 314ea097..6eaa5b06 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -208,7 +208,7 @@ static void run_switcher ( ModeMode mode ) void process_result ( RofiViewState *state ) { Mode *sw = state->sw; - rofi_view_set_active ( NULL ); + // rofi_view_set_active ( NULL ); if ( sw != NULL ) { unsigned int selected_line = rofi_view_get_selected_line ( state );; MenuReturn mretv = rofi_view_get_return_value ( state ); @@ -246,11 +246,17 @@ void process_result ( RofiViewState *state ) * Load in the new mode. */ rofi_view_switch_mode ( state, modi[mode] ); - rofi_view_set_active ( state ); curr_switcher = mode; return; + } else { + // On exit, free current view, and pop to one above. + rofi_view_remove_active ( state ); + rofi_view_free ( state ); + return; } } +// rofi_view_set_active ( NULL ); + rofi_view_remove_active ( state ); rofi_view_free ( state ); } diff --git a/source/view.c b/source/view.c index 44ce9328..5ba1309a 100644 --- a/source/view.c +++ b/source/view.c @@ -415,6 +415,9 @@ static void rofi_view_calculate_window_position ( RofiViewState *state ) static void rofi_view_window_update_size ( RofiViewState * state ) { + if ( state == NULL ) { + return; + } uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; uint32_t vals[] = { state->x, state->y, state->width, state->height }; @@ -490,6 +493,15 @@ RofiViewState * rofi_view_get_active ( void ) return current_active_menu; } +void rofi_view_remove_active ( RofiViewState *state ) +{ + if ( state == current_active_menu ) { + rofi_view_set_active ( NULL ); + } + else if ( state ) { + g_queue_remove ( &(CacheState.views ), state); + } +} void rofi_view_set_active ( RofiViewState *state ) { if ( current_active_menu != NULL && state != NULL ) {