25

If I want to open or save a file in an gtk3 app (eg firefox) I get an unwanted search function after tiping a character.

Old and productive behaviour: typing d gives me the first file beginning with d, typing de gives me the first file with de.

New and unwanted behaviour: typing d starts a search process and gives me /home/myuser/Downloads/somestuff/DETLEFF or some other file somewhere in the system.

Example: Gtk3FileChooser

How can I change back to the old and productive behaviour?

My system: archliux64, Gtk3: 3.18.6, windowmanager: fluxbox

19
+100

The feature you are looking for is called "typeahead" and it is disabled in GtkFileChooserDialog. gtk3-typeahead from the AUR restores the previous behavior.

The package author says disabling typeahead is hardcoded in GTK+ and in a bug report it was stated: "It's not a bug; the removal of the type-ahead search was very much intentional."

Note there is now some (partially broken) tab-completion in the name/address field mimicking the behavior of the shell.

| improve this answer | |
7

Updated answer:

As of 2019, I have since hopped to using Arch's AUR repository (But still on my Debian system). I've also done this on FreeBSD, now, with small (somewhat trivial) patch. This is NOT a "switch to Arch" answer.

It was a bit hard to set up at first, but the gist of it is that you can in fact compile Arch's makepkg program and use it to compile AUR repositories on Debian. I did this like so (though I may have forgotten some dependencies):

My old answer is still present after the separator near the bottom.

1) Building makepkg:

sudo apt-get install bsdtar # pacman depends on bsdtar (libarchive) these days
git clone git://projects.archlinux.org/pacman.git
cd pacman
./configure --sysconfdir=/etc --localstatedir=/var --prefix=/opt/arch # Put built program outside of the usual '/usr/local' when installed to avoid conflicts
make
sudo make install # Install pacman/makepkg

# Make a directory pacman expects to exist to dodge makepkg errors
sudo mkdir -p /var/cache/pacman/pkg

2) Preparation to compile the GTK3 sources:

Now, to build and install gtk3-typeahead. To get all the (debian) build dependencies, which more or less are the same as the Arch ones, you must first have a deb-src line in your sources.list so that apt-get build-dep will successfully fetch the necessary -dev packages.

My sources.list contains the following line to do that. Change the line based on your release and nearest server.

deb-src http://ftp.us.debian.org/debian/ sid main contrib

3) Building gtk3-typeahead:

Then, you can run the following to build gtk3-typeahead:

sudo apt-get update
sudo apt-get build-dep 'gtk+3.0' # install gtk3 build dependencies

mkdir /path/to/put/arch/git/repo/into
cd /path/to/put/arch/git/repo/into
git clone https://aur.archlinux.org/gtk3-typeahead.git gtk3-typeahead
cd gtk3-typeahead

# Tack onto configure script arguments so that libraries overwrite the official
# Debian ones in /usr/lib/x86_64-linux-gnu, instead of installing to /usr/lib. 
# CHANGE THIS APPROPRIATELY IF RUNNING 32-BIT (or some other architecture like POWER/MIPS)
sed '/\-\-sysconfdir=/a\
        --libdir=/usr/lib/x86_64-linux-gnu \\' PKGBUILD > PKGBUILD2
mv PKGBUILD2 PKGBUILD

# temporarily add archlinux programs to PATH so we can use 'makepkg'
PATH="/opt/arch/bin:""$PATH"

# Don't check pacman dependencies, since our dependency libraries weren't
# installed via pacman like makepkg expects!
makepkg --nodeps

After doing this, the binaries will be packed up in a .tar.gz archive one level above the git tree. In my example, this would be the into directory.

To install it:

TARBALLPATH="$(readlink -f gtk3-typeahead-*.tar.gz | sort | tail -n 1)" # get full path to tarball of most recent build, if multiple are available
cd /
bsdtar xf "$TARBALLPATH"

This is highly scriptable, and a bit less finnicky than dealing with my old scripts in my humble opinion. It also no longer depends on debian.


Original answer:

It's been a year and this still annoys me, since the GTK3 folks decided to hardcode this behaviour in, with no way to revert it without recompiling.

However, typeahead was patched back in to gtk3 as distributed in Ubuntu.

Ubuntu also made the file chooser require a doubleclick to choose a file, instead of only requiring a single click if the file was already selected. If you are OK with patching the gtk3 source code, I have made a patch which works as of gtk+ 3.22.7 combining the ubuntu patches and updating them to a more current version of GTK.

Additionally, I made a script for my debian system which automatically downloads the source for the latest version in the package manager, patches it, and compiles it. Runs correctly on Debian Sid, and should work fine for other Debian distros, too.

| improve this answer | |
4

On Debian unstable, you can get the typeahead functionality by pressing ctrl-l when the window is open (l for lookahead), but only for file open dialogues, not file save dialogues. For file save dialogues, ctrl-l will only highlight the name of the file to be saved. To navigate in a more intelligent way, you can type ~, /,. in the correct combinations to get your home directory, current directory, or a directory path from root. Also hitting the back arrow key can deselect the name and keep the cursor in the box so you don't loose the current name (as would occur in a "Save As" operation).

It seems to be that the old behavior was much better :)

| improve this answer | |
0

For Debian: the following short script creates and installs a (patched) regular debian-package which may be preferred over make install. The patch is taken from here with the first block removed as it is reported to cause problems. I successfully tested it on Debian 10 Buster.

#!/usr/bin/env bash
set -e

# provide the patch path
path_patch=typeahead.patch

sudo apt-get build-dep libgtk-3-dev
apt-get source libgtk-3-dev
cd $(find gtk* -maxdepth 0 -type d)
patch gtk/gtkfilechooserwidget.c < "$path_patch"
debuild -b  -us -uc  --no-pre-clean
cd ..
sudo dpkg -i libgtk-3-0_*.deb
# do not update (dist-upgrade)
sudo apt-mark hold libgtk-3-0

Store this as typeahead.patch:

@@ -1399,12 +1405,6 @@
           return TRUE;
         }
     }
-  else if (gtk_search_entry_handle_event (GTK_SEARCH_ENTRY (priv->search_entry), (GdkEvent *)event))
-    {
-      if (priv->operation_mode != OPERATION_MODE_SEARCH)
-        operation_mode_set (impl, OPERATION_MODE_SEARCH);
-      return TRUE;
-    }

   if (GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->key_press_event (widget, event))
     return TRUE;
@@ -2427,7 +2427,7 @@
 {
   GtkFileChooserWidgetPrivate *priv = impl->priv;

-  gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), -1);
+  gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), MODEL_COL_NAME);

   gtk_tree_view_column_set_sort_column_id (priv->list_name_column, MODEL_COL_NAME);
   gtk_tree_view_column_set_sort_column_id (priv->list_time_column, MODEL_COL_TIME);
@@ -4338,6 +4338,7 @@
   gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
                            GTK_TREE_MODEL (priv->browse_files_model));
   update_columns (impl, FALSE, _("Modified"));
+  gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->browse_files_tree_view), TRUE);
   file_list_set_sort_column_ids (impl);
   set_sort_column (impl);
   profile_msg ("    gtk_tree_view_set_model end", NULL);
@@ -7098,10 +7099,6 @@
 {
   GList *l, *files, *files_with_info, *infos;
   GFile *file;
-  gboolean select = FALSE;
-
-  if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (impl->priv->search_model), NULL) == 0)
-    select = TRUE;

   files = NULL;
   files_with_info = NULL;
@@ -7129,8 +7126,6 @@
   g_list_free_full (infos, g_object_unref);

   gtk_stack_set_visible_child_name (GTK_STACK (impl->priv->browse_files_stack), "list");
-  if (select)
-    gtk_widget_grab_focus (impl->priv->browse_files_tree_view);
 }

 /* Callback used from GtkSearchEngine when the query is done running */
@@ -7427,6 +7422,7 @@
   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->recent_model),
                                         GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
                                         GTK_SORT_DESCENDING);
+  gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->browse_files_tree_view), TRUE);
 }

 typedef struct
@@ -7444,7 +7440,7 @@

   gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
                            GTK_TREE_MODEL (priv->recent_model));
-  gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), -1);
+  gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), MODEL_COL_NAME);

   gtk_tree_view_column_set_sort_column_id (priv->list_name_column, -1);
   gtk_tree_view_column_set_sort_column_id (priv->list_time_column, -1);
| improve this answer | |
0

while this answer does not get you back the exact old behavior, it solves the main problem which is having to either do a recursive search or use the mouse.

I found out by looking into the code in gtkfilechooserwidget.c that if you start typing a path that contains a slash it shows you an interactive file list to choose from with autocomplete (just like emacs ivy) and with recursive search disabled.

so for example you can start typing ./, ../, ~/ or / and it will just work.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.