diff options
Diffstat (limited to 'mate-panel/panel-run-dialog.c')
-rw-r--r-- | mate-panel/panel-run-dialog.c | 387 |
1 files changed, 230 insertions, 157 deletions
diff --git a/mate-panel/panel-run-dialog.c b/mate-panel/panel-run-dialog.c index fcd482ee..49c4e761 100644 --- a/mate-panel/panel-run-dialog.c +++ b/mate-panel/panel-run-dialog.c @@ -2,6 +2,7 @@ * panel-run-dialog.c: * * Copyright (C) 2003 Frank Worsley <[email protected]> + * Copyright (C) 2012-2021 MATE Developers * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -38,6 +39,7 @@ #include <unistd.h> #include <glib/gi18n.h> +#include <glib.h> #include <gio/gio.h> #include <gdk/gdkkeysyms.h> #include <matemenu-tree.h> @@ -88,7 +90,7 @@ typedef struct { GHashTable *dir_hash; GList *possible_executables; GList *completion_items; - GCompletion *completion; + GtkEntryCompletion *completion; int add_items_idle_id; int find_command_idle_id; @@ -105,6 +107,8 @@ typedef struct { enum { COLUMN_GICON, COLUMN_NAME, + COLUMN_ACCELERATOR_MASK, + COLUMN_ACCELERATOR_KEY_VALUE, COLUMN_COMMENT, COLUMN_PATH, COLUMN_EXEC, @@ -112,6 +116,28 @@ enum { NUM_COLUMNS }; +typedef struct { + gint list_item_idx; + GdkModifierType modifier; + guint key_id; +} AcceleratorKeyMapping; + +const AcceleratorKeyMapping accelerator_key_mapping[] = +{ + {0, GDK_MOD1_MASK, GDK_KEY_1 }, + {1, GDK_MOD1_MASK, GDK_KEY_2 }, + {2, GDK_MOD1_MASK, GDK_KEY_3 }, + {3, GDK_MOD1_MASK, GDK_KEY_4 }, + {4, GDK_MOD1_MASK, GDK_KEY_5 }, + {5, GDK_MOD1_MASK, GDK_KEY_6 }, + {6, GDK_MOD1_MASK, GDK_KEY_7 }, + {7, GDK_MOD1_MASK, GDK_KEY_8 }, + {8, GDK_MOD1_MASK, GDK_KEY_9 }, + {9, GDK_MOD1_MASK, GDK_KEY_0 }, +}; + +static GHashTable *accelerator_keys_to_tree_iter_map = NULL; + static PanelRunDialog *static_dialog = NULL; static void panel_run_dialog_disconnect_pixmap (PanelRunDialog *dialog); @@ -136,9 +162,7 @@ _panel_run_get_recent_programs_list (PanelRunDialog *dialog) history_max_size = g_settings_get_uint (dialog->settings, PANEL_RUN_HISTORY_MAX_SIZE_KEY); history_reverse = g_settings_get_boolean (dialog->settings, PANEL_RUN_HISTORY_REVERSE_KEY); items = g_settings_get_strv (dialog->settings, PANEL_RUN_HISTORY_KEY); - for (i = 0; - items[i] && i < history_max_size; - i++) { + for (i = 0; i < history_max_size && items[i]; i++) { GtkTreeIter iter; /* add history in reverse */ if (history_reverse) @@ -158,22 +182,19 @@ _panel_run_save_recent_programs_list (PanelRunDialog *dialog, GtkComboBox *entry, char *lastcommand) { - GtkTreeModel *model; - GtkTreeIter iter; - guint history_max_size; - gboolean history_reverse; - - history_reverse = g_settings_get_boolean (dialog->settings, PANEL_RUN_HISTORY_REVERSE_KEY); - history_max_size = g_settings_get_uint (dialog->settings, PANEL_RUN_HISTORY_MAX_SIZE_KEY); + gboolean history_reverse = + g_settings_get_boolean (dialog->settings, PANEL_RUN_HISTORY_REVERSE_KEY); + guint history_max_size = + g_settings_get_uint (dialog->settings, PANEL_RUN_HISTORY_MAX_SIZE_KEY); if (history_max_size == 0) g_settings_set_strv (dialog->settings, PANEL_RUN_HISTORY_KEY, NULL); else { - model = gtk_combo_box_get_model (GTK_COMBO_BOX (entry)); - + GtkTreeIter iter; + GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (entry)); /* reasonable upper bound for zero-terminated array with new command */ - gchar *items[gtk_tree_model_iter_n_children (model, NULL) + 2]; - guint items_added = 0; + gchar *items[gtk_tree_model_iter_n_children (model, NULL) + 2]; + guint items_added = 0; items[0] = lastcommand; @@ -201,8 +222,7 @@ _panel_run_save_recent_programs_list (PanelRunDialog *dialog, } if (history_max_size < items_added + 1) { - g_free (items[history_max_size]); - items[history_max_size] = NULL; + g_clear_pointer (&items[history_max_size], g_free); } else { items[items_added + 1] = NULL; } @@ -223,11 +243,9 @@ panel_run_dialog_destroy (PanelRunDialog *dialog) g_object_unref (dialog->program_list_box); - g_clear_object (&(dialog->icon)); - g_free (dialog->desktop_path); - dialog->desktop_path = NULL; - g_free (dialog->item_name); - dialog->item_name = NULL; + g_clear_object (&dialog->icon); + g_clear_pointer (&dialog->desktop_path, g_free); + g_clear_pointer (&dialog->item_name, g_free); if (dialog->add_items_idle_id) g_source_remove (dialog->add_items_idle_id); @@ -237,14 +255,16 @@ panel_run_dialog_destroy (PanelRunDialog *dialog) g_source_remove (dialog->find_command_idle_id); dialog->find_command_idle_id = 0; - if (dialog->settings != NULL) - g_object_unref (dialog->settings); - dialog->settings = NULL; + g_clear_object (&dialog->settings); if (dialog->dir_hash) g_hash_table_destroy (dialog->dir_hash); dialog->dir_hash = NULL; + if (accelerator_keys_to_tree_iter_map) + g_hash_table_destroy (accelerator_keys_to_tree_iter_map); + accelerator_keys_to_tree_iter_map = NULL; + for (l = dialog->possible_executables; l; l = l->next) g_free (l->data); g_list_free (dialog->possible_executables); @@ -255,10 +275,6 @@ panel_run_dialog_destroy (PanelRunDialog *dialog) g_list_free (dialog->completion_items); dialog->completion_items = NULL; - if (dialog->completion) - g_completion_free (dialog->completion); - dialog->completion = NULL; - panel_run_dialog_disconnect_pixmap (dialog); g_free (dialog); @@ -338,6 +354,9 @@ command_is_executable (const char *command, char ***argvp) { gboolean result; + GRegex *regex = NULL; + gsize argv_len; + g_autofree gchar *home_path = NULL; char **argv; char *path; int argc; @@ -347,6 +366,18 @@ command_is_executable (const char *command, if (!result) return FALSE; + regex = g_regex_new ("^~/", 0, 0, NULL); + argv_len = g_strv_length (argv); + home_path = g_build_filename (g_get_home_dir (), "/", NULL); + for (gsize i = 0; i < argv_len; i++) + { + gchar *tmp_argv = NULL; + + tmp_argv = g_regex_replace_literal (regex, argv[i], -1, 0, home_path, 0, NULL); + g_free (argv[i]); + argv[i] = tmp_argv; + } + g_regex_unref (regex); path = g_find_program_in_path (argv[0]); if (!path) { @@ -376,15 +407,6 @@ command_is_executable (const char *command, return TRUE; } -/* - * Set the DISPLAY variable, to be use by g_spawn_async. - */ -static void -set_environment (gpointer display) -{ - g_setenv ("DISPLAY", display, TRUE); -} - static void dummy_child_watch (GPid pid, gint status, @@ -401,32 +423,24 @@ panel_run_dialog_launch_command (PanelRunDialog *dialog, const char *command, const char *locale_command) { - GdkDisplay *display; - GdkScreen *screen; gboolean result; GError *error = NULL; char **argv; int argc; - char *display_name; GPid pid; if (!command_is_executable (locale_command, &argc, &argv)) return FALSE; - screen = gtk_window_get_screen (GTK_WINDOW (dialog->run_dialog)); - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->terminal_checkbox))) mate_desktop_prepend_terminal_to_vector (&argc, &argv); - display = gdk_screen_get_display (screen); - display_name = g_strdup (gdk_display_get_name (display)); - result = g_spawn_async (NULL, /* working directory */ argv, NULL, /* envp */ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, - set_environment, - display_name, + NULL, + NULL, &pid, &error); @@ -446,7 +460,6 @@ panel_run_dialog_launch_command (PanelRunDialog *dialog, } g_strfreev (argv); - g_free (display_name); return result; } @@ -572,7 +585,7 @@ panel_run_dialog_append_file_utf8 (PanelRunDialog *dialog, const char *file) { const char *text; - char *quoted, *temp; + char *quoted; GtkWidget *entry; /* Don't allow filenames beginning with '-' */ @@ -583,7 +596,7 @@ panel_run_dialog_append_file_utf8 (PanelRunDialog *dialog, entry = gtk_bin_get_child (GTK_BIN (dialog->combobox)); text = gtk_entry_get_text (GTK_ENTRY (entry)); if (text && text [0]) { - temp = g_strconcat (text, " ", quoted, NULL); + char *temp = g_strconcat (text, " ", quoted, NULL); gtk_entry_set_text (GTK_ENTRY (entry), temp); g_free (temp); } else @@ -660,19 +673,6 @@ fuzzy_command_match (const char *cmd1, } static gboolean -panel_run_dialog_make_all_list_visible (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer data) -{ - gtk_list_store_set (GTK_LIST_STORE (model), iter, - COLUMN_VISIBLE, TRUE, - -1); - - return FALSE; -} - -static gboolean panel_run_dialog_find_command_idle (PanelRunDialog *dialog) { GtkTreeIter iter; @@ -682,6 +682,7 @@ panel_run_dialog_find_command_idle (PanelRunDialog *dialog) GIcon *found_icon; char *found_name; gboolean fuzzy; + gint visible_program_idx = 0; model = GTK_TREE_MODEL (dialog->program_list_store); path = gtk_tree_path_new_first (); @@ -700,12 +701,14 @@ panel_run_dialog_find_command_idle (PanelRunDialog *dialog) found_icon = NULL; found_name = NULL; fuzzy = FALSE; + g_hash_table_remove_all (accelerator_keys_to_tree_iter_map); do { char *exec = NULL; GIcon *icon = NULL; char *name = NULL; char *comment = NULL; + gboolean visible = FALSE; gtk_tree_model_get (model, &iter, COLUMN_EXEC, &exec, @@ -740,6 +743,23 @@ panel_run_dialog_find_command_idle (PanelRunDialog *dialog) -1); } + gtk_tree_model_get (model, &iter, COLUMN_VISIBLE, &visible, -1); + if (visible && visible_program_idx < G_N_ELEMENTS (accelerator_key_mapping)) { + gtk_list_store_set (dialog->program_list_store, + &iter, + COLUMN_ACCELERATOR_MASK, (gint)accelerator_key_mapping[visible_program_idx].modifier, + COLUMN_ACCELERATOR_KEY_VALUE, accelerator_key_mapping[visible_program_idx].key_id, + -1); + g_hash_table_insert (accelerator_keys_to_tree_iter_map, GUINT_TO_POINTER(accelerator_key_mapping[visible_program_idx].key_id), GINT_TO_POINTER(visible_program_idx)); + visible_program_idx++; + } else { + gtk_list_store_set (dialog->program_list_store, + &iter, + COLUMN_ACCELERATOR_MASK, 0, + COLUMN_ACCELERATOR_KEY_VALUE, 0, + -1); + } + g_free (exec); if (icon != NULL) g_object_unref (icon); @@ -891,6 +911,8 @@ panel_run_dialog_add_items_idle (PanelRunDialog *dialog) dialog->program_list_store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_ICON, G_TYPE_STRING, + G_TYPE_INT, // For accelerator modifier mask + G_TYPE_UINT, // For accelerator key value G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, @@ -918,6 +940,9 @@ panel_run_dialog_add_items_idle (PanelRunDialog *dialog) } } + gint i = 0; + g_hash_table_remove_all (accelerator_keys_to_tree_iter_map); + for (l = all_applications; l; l = l->next) { MateMenuTreeEntry *entry = l->data; GtkTreeIter iter; @@ -936,6 +961,19 @@ panel_run_dialog_add_items_idle (PanelRunDialog *dialog) COLUMN_PATH, matemenu_tree_entry_get_desktop_file_path (entry), COLUMN_VISIBLE, TRUE, -1); + if (i < G_N_ELEMENTS (accelerator_key_mapping)) { + gtk_list_store_set (dialog->program_list_store, &iter, + COLUMN_ACCELERATOR_MASK, (gint)accelerator_key_mapping[i].modifier, + COLUMN_ACCELERATOR_KEY_VALUE, accelerator_key_mapping[i].key_id, + -1); + g_hash_table_insert (accelerator_keys_to_tree_iter_map, GUINT_TO_POINTER(accelerator_key_mapping[i].key_id), GINT_TO_POINTER(i)); + i++; + } else { + gtk_list_store_set (dialog->program_list_store, &iter, + COLUMN_ACCELERATOR_MASK, (gint)GDK_MOD1_MASK, + COLUMN_ACCELERATOR_KEY_VALUE, 0, + -1); + } } g_slist_free_full (all_applications, matemenu_tree_item_unref); @@ -959,11 +997,23 @@ panel_run_dialog_add_items_idle (PanelRunDialog *dialog) NULL); renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_column_pack_start (column, renderer, TRUE); + gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "text", COLUMN_NAME, NULL); + gtk_tree_view_column_set_sizing (column, + GTK_TREE_VIEW_COLUMN_AUTOSIZE); + + gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->program_list), column); + + renderer = gtk_cell_renderer_accel_new (); + g_object_set (renderer, "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_GTK, + "editable", FALSE, NULL); + + column = gtk_tree_view_column_new_with_attributes ("Shortcut", renderer, + "accel-mods", COLUMN_ACCELERATOR_MASK, "accel-key", + COLUMN_ACCELERATOR_KEY_VALUE, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->program_list), column); dialog->add_items_idle_id = 0; @@ -1018,7 +1068,7 @@ program_list_selection_changed (GtkTreeSelection *selection, GtkTreeIter iter; GtkTreeIter filter_iter; char *temp; - char *path, *stripped; + char *path; gboolean terminal; GKeyFile *key_file; GtkWidget *entry; @@ -1050,12 +1100,9 @@ program_list_selection_changed (GtkTreeSelection *selection, } dialog->use_program_list = TRUE; - if (dialog->desktop_path) - g_free (dialog->desktop_path); + g_free (dialog->desktop_path); dialog->desktop_path = g_strdup (path); - if (dialog->item_name) - g_free (dialog->item_name); - dialog->item_name = NULL; + g_clear_pointer (&dialog->item_name, g_free); /* Order is important here. We have to set the text first so that the * drag source is enabled, otherwise the drag icon can't be set by @@ -1064,7 +1111,7 @@ program_list_selection_changed (GtkTreeSelection *selection, entry = gtk_bin_get_child (GTK_BIN (dialog->combobox)); temp = panel_key_file_get_string (key_file, "Exec"); if (temp) { - stripped = remove_parameters (temp); + char *stripped = remove_parameters (temp); gtk_entry_set_text (GTK_ENTRY (entry), stripped); g_free (stripped); } else { @@ -1111,13 +1158,10 @@ program_list_selection_activated (GtkTreeView *view, gtk_dialog_response (GTK_DIALOG (dialog->run_dialog), GTK_RESPONSE_OK); } - static void panel_run_dialog_setup_program_list (PanelRunDialog *dialog, GtkBuilder *gui) { - GtkTreeSelection *selection; - dialog->program_list = PANEL_GTK_BUILDER_GET (gui, "program_list"); dialog->program_list_box = PANEL_GTK_BUILDER_GET (gui, "program_list_box"); dialog->program_label = PANEL_GTK_BUILDER_GET (gui, "program_label"); @@ -1131,7 +1175,9 @@ panel_run_dialog_setup_program_list (PanelRunDialog *dialog, g_object_ref (dialog->program_list_box); if (panel_profile_get_enable_program_list ()) { - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->program_list)); + GtkTreeSelection *selection = + gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->program_list)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); g_signal_connect (selection, "changed", @@ -1248,10 +1294,9 @@ file_button_browse_response (GtkWidget *chooser, gint response, PanelRunDialog *dialog) { - char *file; if (response == GTK_RESPONSE_OK) { - file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser)); + char *file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser)); panel_run_dialog_append_file (dialog, file); g_free (file); } @@ -1318,8 +1363,7 @@ fill_files_from (const char *dirname, char *item; const char *suffix; - if (!dent->d_name || - dent->d_name [0] != prefix) + if (dent->d_name [0] != prefix) continue; file = g_build_filename (dirname, dent->d_name, NULL); @@ -1367,7 +1411,6 @@ fill_possible_executables (void) for (i = 0; pathv [i]; i++) { const char *file; - char *filename; GDir *dir; dir = g_dir_open (pathv [i], 0, NULL); @@ -1376,8 +1419,7 @@ fill_possible_executables (void) continue; while ((file = g_dir_read_name (dir))) { - filename = g_build_filename (pathv [i], file, NULL); - list = g_list_prepend (list, filename); + list = g_list_prepend (list, g_build_filename (pathv [i], file, NULL)); } g_dir_close (dir); @@ -1424,6 +1466,33 @@ fill_executables (GList *possible_executables, return list; } +static GtkTreeModel * +create_completion_model (GList *list) +{ + GtkListStore *store; + GtkTreeIter iter; + GList *l; + + store = gtk_list_store_new (1, G_TYPE_STRING); + for (l = list; l; l = l->next) + { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, l->data, -1); + } + + return GTK_TREE_MODEL (store); +} + +static void +completion_add_items (GtkEntryCompletion *completion, GList *list) +{ + GtkTreeModel *completion_model; + + completion_model = create_completion_model (list); + gtk_entry_completion_set_model (completion, completion_model); + g_object_unref (completion_model); +} + static void panel_run_dialog_update_completion (PanelRunDialog *dialog, const char *text) @@ -1441,14 +1510,6 @@ panel_run_dialog_update_completion (PanelRunDialog *dialog, list = NULL; executables = NULL; - if (!dialog->completion) { - dialog->completion = g_completion_new (NULL); - dialog->possible_executables = fill_possible_executables (); - dialog->dir_hash = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, NULL); - } - buf = g_path_get_basename (text); prefix = buf[0]; g_free (buf); @@ -1492,8 +1553,7 @@ panel_run_dialog_update_completion (PanelRunDialog *dialog, if (list == NULL) return; - g_completion_add_items (dialog->completion, list); - + completion_add_items (dialog->completion, list); dialog->completion_items = g_list_concat (dialog->completion_items, list); } @@ -1503,10 +1563,8 @@ entry_event (GtkEditable *entry, GdkEventKey *event, PanelRunDialog *dialog) { - GtkTreeSelection *selection; char *prefix; char *nospace_prefix; - char *nprefix; char *temp; int pos, tmp; @@ -1518,7 +1576,7 @@ entry_event (GtkEditable *entry, */ dialog->use_program_list = FALSE; if (panel_profile_get_enable_program_list ()) { - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->program_list)); + GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->program_list)); gtk_tree_selection_unselect_all (selection); } @@ -1532,7 +1590,7 @@ entry_event (GtkEditable *entry, if (dialog->completion_started && pos != tmp && pos != 1 && - tmp == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) { + ((size_t) tmp) == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) { gtk_editable_select_region (entry, 0, 0); gtk_editable_set_position (entry, -1); @@ -1545,12 +1603,12 @@ entry_event (GtkEditable *entry, if (dialog->completion_started && pos != tmp && pos != 0 && - tmp == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) { + ((size_t) tmp) == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) { temp = gtk_editable_get_chars (entry, 0, pos); prefix = g_strconcat (temp, event->string, NULL); g_free (temp); } else if (pos == tmp && - tmp == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) { + ((size_t) tmp) == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) { prefix = g_strconcat (gtk_entry_get_text (GTK_ENTRY (entry)), event->string, NULL); } else { @@ -1571,43 +1629,6 @@ entry_event (GtkEditable *entry, return FALSE; } - pos = strlen (prefix); - nprefix = NULL; - - g_completion_complete_utf8 (dialog->completion, nospace_prefix, - &nprefix); - - if (nprefix) { - int insertpos; - insertpos = 0; - - temp = g_strndup (prefix, nospace_prefix - prefix); - g_free (prefix); - - prefix = g_strconcat (temp, nprefix, NULL); - - g_signal_handler_block (dialog->combobox, - dialog->changed_id); - gtk_editable_delete_text (entry, 0, -1); - g_signal_handler_unblock (dialog->combobox, - dialog->changed_id); - - gtk_editable_insert_text (entry, - prefix, strlen (prefix), - &insertpos); - - gtk_editable_set_position (entry, pos); - gtk_editable_select_region (entry, pos, -1); - - dialog->completion_started = TRUE; - - g_free (temp); - g_free (nprefix); - g_free (prefix); - - return TRUE; - } - g_free (prefix); } @@ -1618,13 +1639,9 @@ static void combobox_changed (GtkComboBox *combobox, PanelRunDialog *dialog) { - char *text; - char *start; - char *msg; + char *text = g_strdup (panel_run_dialog_get_combo_text (dialog)); + char *start = text; - text = g_strdup (panel_run_dialog_get_combo_text (dialog)); - - start = text; while (*start != '\0' && g_ascii_isspace (*start)) start++; @@ -1641,7 +1658,7 @@ combobox_changed (GtkComboBox *combobox, } /* desensitize run button if no text entered */ - if (!start || !start [0]) { + if (!start [0]) { g_free (text); gtk_widget_set_sensitive (dialog->run_button, FALSE); @@ -1659,12 +1676,31 @@ combobox_changed (GtkComboBox *combobox, } if (panel_profile_get_enable_program_list ()) { - GtkTreeIter iter; - GtkTreePath *path; - - gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->program_list_store), - panel_run_dialog_make_all_list_visible, - NULL); + GtkTreeIter iter; + GtkTreePath *path; + GtkTreeModel *model; + gint i = 0; + gboolean valid = FALSE; + + g_hash_table_remove_all (accelerator_keys_to_tree_iter_map); + model = GTK_TREE_MODEL (dialog->program_list_store); + for (valid = gtk_tree_model_get_iter_first (model, &iter); valid; valid = gtk_tree_model_iter_next (model, &iter)) { + if (i < G_N_ELEMENTS (accelerator_key_mapping)) { + gtk_list_store_set (GTK_LIST_STORE (GTK_TREE_MODEL (dialog->program_list_store)), &iter, + COLUMN_VISIBLE, TRUE, + COLUMN_ACCELERATOR_MASK, (gint)accelerator_key_mapping[i].modifier, + COLUMN_ACCELERATOR_KEY_VALUE, accelerator_key_mapping[i].key_id, + -1); + g_hash_table_insert (accelerator_keys_to_tree_iter_map, GUINT_TO_POINTER (accelerator_key_mapping[i].key_id), GINT_TO_POINTER(i)); + i++; + } else { + gtk_list_store_set (GTK_LIST_STORE (GTK_TREE_MODEL (dialog->program_list_store)), &iter, + COLUMN_VISIBLE, TRUE, + COLUMN_ACCELERATOR_MASK, (gint)GDK_MOD1_MASK, + COLUMN_ACCELERATOR_KEY_VALUE, 0, + -1); + } + } path = gtk_tree_path_new_first (); if (gtk_tree_model_get_iter (gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->program_list)), @@ -1687,8 +1723,8 @@ combobox_changed (GtkComboBox *combobox, if (panel_profile_get_enable_program_list () && !dialog->use_program_list) { - msg = g_strdup_printf (_("Will run command: '%s'"), - start); + char *msg = g_strdup_printf (_("Will run command: '%s'"), + start); gtk_label_set_text (GTK_LABEL (dialog->program_label), msg); g_free (msg); } @@ -1759,10 +1795,18 @@ panel_run_dialog_setup_entry (PanelRunDialog *dialog, GtkWidget *entry; dialog->combobox = PANEL_GTK_BUILDER_GET (gui, "comboboxentry"); + dialog->possible_executables = fill_possible_executables (); + dialog->dir_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); entry = gtk_bin_get_child (GTK_BIN (dialog->combobox)); gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); + dialog->completion = gtk_entry_completion_new (); + gtk_entry_completion_set_inline_completion (dialog->completion, TRUE); + gtk_entry_completion_set_popup_completion (dialog->completion, FALSE); + gtk_entry_set_completion (GTK_ENTRY (entry), dialog->completion); + gtk_entry_completion_set_text_column (dialog->completion, 0); + gtk_combo_box_set_model (GTK_COMBO_BOX (dialog->combobox), _panel_run_get_recent_programs_list (dialog)); gtk_combo_box_set_entry_text_column @@ -1789,7 +1833,7 @@ panel_run_dialog_setup_entry (PanelRunDialog *dialog, GDK_ACTION_COPY); gtk_drag_dest_add_uri_targets (dialog->combobox); - g_signal_connect (dialog->combobox, "drag_data_received", + g_signal_connect (dialog->combobox, "drag-data-received", G_CALLBACK (entry_drag_data_received), dialog); } @@ -1858,10 +1902,8 @@ panel_run_dialog_create_desktop_file (PanelRunDialog *dialog) save_uri = panel_make_unique_desktop_uri (g_get_tmp_dir (), name); disk = g_filename_from_uri (save_uri, NULL, NULL); - if (!disk || !panel_key_file_to_file (key_file, disk, NULL)) { - g_free (save_uri); - save_uri = NULL; - } + if (!disk || !panel_key_file_to_file (key_file, disk, NULL)) + g_clear_pointer (&save_uri, g_free); g_key_file_free (key_file); g_free (disk); @@ -1934,7 +1976,7 @@ panel_run_dialog_setup_pixmap (PanelRunDialog *dialog, G_CALLBACK (panel_run_dialog_screen_changed), dialog); - g_signal_connect (dialog->run_dialog, "drag_data_get", + g_signal_connect (dialog->run_dialog, "drag-data-get", G_CALLBACK (pixmap_drag_data_get), dialog); } @@ -1968,6 +2010,22 @@ key_press_event (GtkWidget *run_dialog, return FALSE; } +static void +panel_run_dialog_accelerator_key_pressed (GtkAccelGroup *accel_group, + GObject *acceleratable, + guint keyval, + GdkModifierType modifier, + PanelRunDialog *dialog) +{ + GtkTreePath *path; + gpointer index_of_entry; + gboolean found = g_hash_table_lookup_extended (accelerator_keys_to_tree_iter_map, GUINT_TO_POINTER(keyval), NULL, &index_of_entry); + if (!found) return; + path = gtk_tree_path_new_from_indices(GPOINTER_TO_INT(index_of_entry), -1); + gtk_tree_view_set_cursor (GTK_TREE_VIEW (dialog->program_list), path, NULL, FALSE); + gtk_widget_grab_focus (dialog->program_list); +} + static PanelRunDialog * panel_run_dialog_new (GdkScreen *screen, GtkBuilder *gui, @@ -1985,6 +2043,20 @@ panel_run_dialog_new (GdkScreen *screen, g_signal_connect_swapped (dialog->run_dialog, "destroy", G_CALLBACK (panel_run_dialog_destroy), dialog); + GtkAccelGroup* accel_group = gtk_accel_group_new (); + gtk_window_add_accel_group (GTK_WINDOW(dialog->run_dialog), accel_group); + g_object_unref (accel_group); + for (gint i = 0; i < G_N_ELEMENTS (accelerator_key_mapping); i++) + { + GClosure *closure_key = g_cclosure_new ( + G_CALLBACK (panel_run_dialog_accelerator_key_pressed), dialog, NULL); + gtk_accel_group_connect (accel_group, + accelerator_key_mapping[i].key_id, + accelerator_key_mapping[i].modifier, + 0, + closure_key); + } + dialog->run_button = PANEL_GTK_BUILDER_GET (gui, "run_button"); dialog->terminal_checkbox = PANEL_GTK_BUILDER_GET (gui, "terminal_checkbox"); @@ -2046,6 +2118,7 @@ panel_run_dialog_present (GdkScreen *screen, guint32 activate_time) { GtkBuilder *gui; + accelerator_keys_to_tree_iter_map = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); if (panel_lockdown_get_disable_command_line ()) return; |