--- src/nautilus-window-slot.h.typeahead	2015-05-15 12:45:10.919152102 +0200
+++ src/nautilus-window-slot.h	2015-05-15 12:49:09.011030303 +0200
@@ -125,4 +125,6 @@
 							    const char         *detail_status);
 void nautilus_window_slot_sync_view_mode (NautilusWindowSlot *slot);
 
+gboolean nautilus_window_slot_isearch_key_press (NautilusWindowSlot *slot, GdkEventKey *event);
+
 #endif /* NAUTILUS_WINDOW_SLOT_H */
--- src/nautilus-window-slot.c.typeahead	2015-05-13 19:24:43.000000000 +0200
+++ src/nautilus-window-slot.c	2015-05-15 12:45:10.920152104 +0200
@@ -124,6 +124,15 @@
 	gboolean tried_mount;
 	NautilusWindowGoToCallback open_callback;
 	gpointer open_callback_user_data;
+
+        /* Interactive search */
+        gboolean isearch_enable;
+        gboolean isearch_imcontext_changed;
+        NautilusFile *isearch_iter;
+        gint isearch_timeout_id;
+        gint isearch_entry_changed_id;
+        GtkWidget *isearch_entry;
+        GtkWidget *isearch_window;
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -135,6 +144,20 @@
 static void nautilus_window_slot_emit_location_change (NautilusWindowSlot *slot, GFile *from, GFile *to);
 
 static void
+isearch_ensure (NautilusWindowSlot *slot);
+static gboolean
+isearch_start (NautilusWindowSlot *slot);
+static gboolean
+nautilus_window_slot_scroll_event (GtkWidget *widget,
+                      GdkEventScroll  *event);
+static void
+isearch_hide (NautilusWindowSlot *slot);
+static void
+isearch_dispose (NautilusWindowSlot *slot);
+static void
+isearch_enable_changed (gpointer callback_data);
+
+static void
 nautilus_window_slot_sync_search_widgets (NautilusWindowSlot *slot)
 {
 	NautilusDirectory *directory;
@@ -442,14 +465,76 @@
 
 	retval = FALSE;
 	window = nautilus_window_slot_get_window (slot);
-	if (!NAUTILUS_IS_DESKTOP_WINDOW (window)) {
-		retval = nautilus_query_editor_handle_event (slot->details->query_editor, event);
-	}
 
-	if (retval) {
-		nautilus_window_slot_set_search_visible (slot, TRUE);
-	}
+	if (slot->details->isearch_enable) {
+		GdkScreen *screen;
+		GtkWidget *search_window;
+		GtkWidget *search_entry;
+		gchar *old_text;
+		gchar *new_text;
+		gulong popup_menu_id;
+		GdkEvent *new_event;
+
+		isearch_ensure (slot);
+		search_window = slot->details->isearch_window;
+		search_entry = slot->details->isearch_entry;
+
+		if (gtk_widget_get_visible (slot->details->isearch_window)) {
+			GdkEvent *new_event = gdk_event_copy ((GdkEvent *) event);
+			GdkWindow *window = event->window;
+			((GdkEventKey *) new_event)->window = gtk_widget_get_window (slot->details->isearch_entry);
+			retval = gtk_widget_event (slot->details->isearch_window, new_event);
+			((GdkEventKey *) new_event)->window = window;
+			gdk_event_free (new_event);
+			return retval;
+		}
+
+		gtk_widget_realize (search_window);
+
+		old_text = gtk_editable_get_chars (GTK_EDITABLE (search_entry), 0, -1);
+
+		popup_menu_id = g_signal_connect (G_OBJECT (search_entry), "popup-menu", G_CALLBACK (gtk_true), NULL);
+		screen = gtk_widget_get_screen (GTK_WIDGET (slot));
+		gtk_window_move (GTK_WINDOW (search_window),
+						gdk_screen_get_width (screen) + 1,
+						gdk_screen_get_height (screen) + 1);
+		gtk_widget_show (search_window);
+
+		new_event = gdk_event_copy ((GdkEvent *)event);
+		g_object_unref (G_OBJECT (new_event->key.window));
+		new_event->key.window = g_object_ref (G_OBJECT (gtk_widget_get_window (search_entry)));
+
+		slot->details->isearch_imcontext_changed = FALSE;
+		retval = gtk_widget_event (search_entry, new_event);
+		gtk_widget_hide (search_window);
+
+		gdk_event_free (new_event);
+
+		g_signal_handler_disconnect (G_OBJECT (search_entry), popup_menu_id);
+
+		new_text = gtk_editable_get_chars (GTK_EDITABLE (search_entry), 0, -1);
+		retval = retval && (strcmp (old_text, new_text) != 0);
+		g_free (old_text);
+		g_free (new_text);
+
+		if (slot->details->isearch_imcontext_changed || retval) {
+			if (isearch_start (slot)) {
+				gtk_widget_grab_focus (GTK_WIDGET (slot->details->window));
+				return TRUE;
+			} else {
+				gtk_entry_set_text (GTK_ENTRY (search_entry), "");
+				return FALSE;
+			}
+		}
+	} else {
+		if (!NAUTILUS_IS_DESKTOP_WINDOW (window)) {
+			retval = nautilus_query_editor_handle_event (slot->details->query_editor, event);
+		}
 
+		if (retval) {
+			nautilus_window_slot_set_search_visible (slot, TRUE);
+		}
+	}
 	return retval;
 }
 
@@ -481,6 +566,7 @@
 
 	window = nautilus_window_slot_get_window (slot);
 	g_assert (slot == nautilus_window_get_active_slot (window));
+        isearch_hide (slot);
 }
 
 static void
@@ -609,6 +695,26 @@
 {
 	slot->details = G_TYPE_INSTANCE_GET_PRIVATE
 		(slot, NAUTILUS_TYPE_WINDOW_SLOT, NautilusWindowSlotDetails);
+
+	slot->details->isearch_enable =
+		g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH);
+
+	g_signal_connect_swapped (nautilus_preferences,
+				  "changed::" NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH, 
+				  G_CALLBACK(isearch_enable_changed), slot);
+}
+
+static void
+nautilus_window_slot_finalize (GObject *object)
+{
+	NautilusWindowSlot *slot;
+
+	slot = NAUTILUS_WINDOW_SLOT (object);
+
+	g_signal_handlers_disconnect_by_func (nautilus_preferences,
+					      isearch_enable_changed, slot);
+
+	G_OBJECT_CLASS (nautilus_window_slot_parent_class)->finalize (object);
 }
 
 static void
@@ -2047,6 +2153,7 @@
 	g_signal_emit_by_name (slot, "location-changed", from_uri, to_uri);
 	g_free (to_uri);
 	g_free (from_uri);
+        isearch_hide (slot);
 }
 
 static void
@@ -2433,6 +2540,7 @@
 		g_source_remove (slot->details->loading_timeout_id);
 		slot->details->loading_timeout_id = 0;
 	}
+        isearch_dispose (slot);
 
 	nautilus_window_slot_set_viewed_file (slot, NULL);
 	/* TODO? why do we unref here? the file is NULL.
@@ -2478,6 +2586,7 @@
 	oclass->constructed = nautilus_window_slot_constructed;
 	oclass->set_property = nautilus_window_slot_set_property;
 	oclass->get_property = nautilus_window_slot_get_property;
+        oclass->finalize = nautilus_window_slot_finalize;
 
 	signals[ACTIVE] =
 		g_signal_new ("active",
@@ -2833,3 +2942,578 @@
 			     "window", window,
 			     NULL);
 }
+
+/* Interactive search */
+
+#define ISEARCH_TIMEOUT 5000
+
+static gboolean
+isearch_key_press_event (GtkWidget *widget,
+								GdkEventKey *event,
+								NautilusWindowSlot *slot);
+static gboolean
+isearch_button_press_event (GtkWidget *widget,
+                            GdkEvent  *event,
+                            gpointer   user_data);
+static gboolean
+isearch_scroll_event (GtkWidget *widget,
+                      GdkEventScroll  *event,
+                      gpointer   user_data);
+static gboolean
+isearch_delete_event (GtkWidget *widget,
+                      GdkEvent  *event,
+                      gpointer   user_data);
+static void
+isearch_activate (GtkEntry *entry,
+                  NautilusWindowSlot *slot);
+static void
+isearch_preedit_changed (GtkEntry *entry,
+                         gchar    *preedit,
+                         NautilusWindowSlot *slot);
+static void
+isearch_changed (GtkEditable *editable,
+                 NautilusWindowSlot *slot);
+gboolean nautilus_window_slot_handle_scroll (NautilusWindowSlot *slot,
+								GdkEventScroll *event);
+
+static gboolean
+isearch_timeout (gpointer user_data);
+static void
+isearch_timeout_destroy (gpointer user_data);
+static void
+isearch_timeout_restart (NautilusWindowSlot *slot);
+
+static void
+isearch_send_focus_change (GtkWidget *widget, gboolean in);
+
+static void
+isearch_hide (NautilusWindowSlot *slot);
+static void
+isearch_ensure (NautilusWindowSlot *slot);
+
+static NautilusFile *
+isearch_find (NautilusWindowSlot *slot, const gchar *text);
+static NautilusFile *
+isearch_find_next (NautilusWindowSlot *slot, const gchar *text);
+static NautilusFile *
+isearch_find_prev (NautilusWindowSlot *slot, const gchar *text);
+static void
+isearch_move_next (NautilusWindowSlot *slot);
+static void
+isearch_move_prev (NautilusWindowSlot *slot);
+static void
+isearch_set_selection (NautilusWindowSlot *slot, NautilusFile *iter);
+
+static void
+isearch_enable_changed (gpointer callback_data)
+{
+	NautilusWindowSlot *slot;
+	gboolean enable;
+
+	slot = NAUTILUS_WINDOW_SLOT (callback_data);
+
+	enable =
+		g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH);
+
+	if (enable != slot->details->isearch_enable) {
+		if (!enable)
+			isearch_dispose (slot);
+
+		slot->details->isearch_enable = enable;
+	}
+}
+
+static gboolean
+isearch_button_press_event (GtkWidget *widget,
+                            GdkEvent  *event,
+                            gpointer   user_data)
+{
+	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (user_data);
+	isearch_hide (slot);
+}
+
+static gboolean
+isearch_delete_event (GtkWidget *widget,
+                      GdkEvent  *event,
+                      gpointer   user_data)
+{
+	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (user_data);
+
+	isearch_hide (slot);
+}
+
+static void
+isearch_activate (GtkEntry *entry,
+                  NautilusWindowSlot *slot)
+{
+	isearch_hide (slot);
+}
+
+static void
+isearch_preedit_changed (GtkEntry *entry,
+                         gchar    *preedit,
+                         NautilusWindowSlot *slot)
+{
+	slot->details->isearch_imcontext_changed = TRUE;
+}
+
+static void
+isearch_changed (GtkEditable *editable,
+                 NautilusWindowSlot *slot)
+{
+	const gchar *text;
+	NautilusFile *iter;
+
+	text = gtk_entry_get_text (GTK_ENTRY (slot->details->isearch_entry));
+	if (G_UNLIKELY (text == NULL))
+		return;
+
+	nautilus_view_set_selection (slot->details->content_view, NULL);
+	isearch_timeout_restart (slot);
+
+	if (strlen (text) < 1)
+		return;
+
+	isearch_set_selection (slot,  isearch_find (slot, text));
+}
+
+static int
+compare_files (gconstpointer a, gconstpointer b, gpointer callback_data)
+{
+	NautilusView *view = NAUTILUS_VIEW (callback_data);
+	NautilusFile *f1 = NAUTILUS_FILE (a);
+	NautilusFile *f2 = NAUTILUS_FILE (b);
+
+	return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compare_files (view, f1, f2);
+}
+
+static GList *
+isearch_get_sorted_files (NautilusWindowSlot *slot)
+{
+	NautilusView *view = slot->details->content_view;
+	NautilusDirectory *dir = nautilus_view_get_model (view);
+	GList *list = nautilus_directory_get_file_list (dir);
+	GList *sorted_list;
+
+	sorted_list = g_list_sort_with_data (list, compare_files, view);
+	return sorted_list;
+}
+
+gboolean isearch_key_press_event (GtkWidget *widget,
+								GdkEventKey *event,
+								NautilusWindowSlot *slot)
+{
+	gboolean retval = FALSE;
+
+	if (!slot->details->isearch_enable)
+		return FALSE;
+
+	isearch_ensure (slot);
+
+	if (slot->details->isearch_window == NULL
+			|| !gtk_widget_get_visible (slot->details->isearch_window)) {
+		return FALSE;
+	}
+
+	if (event->keyval == GDK_KEY_Escape || event->keyval == GDK_KEY_Tab) {
+		isearch_hide (slot);
+		retval = TRUE;
+	}
+	if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter) {
+		isearch_hide (slot);
+		retval = FALSE;
+	}
+	if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up) {
+		isearch_move_prev (slot);
+		retval = TRUE;
+	}
+	if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
+			&& (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G)) {
+		isearch_move_prev (slot);
+		retval = TRUE;
+	}
+	if (event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down) {
+		isearch_move_next (slot);
+		retval = TRUE;
+	}
+	if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
+			&& (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G)) {
+		isearch_move_next (slot);
+		retval = TRUE;
+	}
+	if (retval)
+		isearch_timeout_restart (slot);
+
+	return retval;
+}
+
+gboolean nautilus_window_slot_isearch_key_press (NautilusWindowSlot *slot, GdkEventKey *event)
+{
+	return isearch_key_press_event (NULL, event, slot);
+}
+
+gboolean isearch_handle_scroll_event (GtkWidget *widget,
+                       GdkEventScroll  *event,
+                       NautilusWindowSlot *slot)
+{
+	gboolean retval = FALSE;
+
+	if (!slot->details->isearch_enable)
+		return FALSE;
+
+	isearch_ensure (slot);
+
+	if (slot->details->isearch_window == NULL
+			|| !gtk_widget_get_visible (slot->details->isearch_window)) {
+		return FALSE;
+	}
+	if (event->direction == GDK_SCROLL_UP) {
+		isearch_move_prev (slot);
+		retval = TRUE;
+	}
+	else if (event->direction == GDK_SCROLL_DOWN) {
+		isearch_move_next (slot);
+		retval = TRUE;
+	}
+
+	if (retval)
+		isearch_timeout_restart (slot);
+
+	return retval;
+}
+
+static gboolean
+isearch_timeout (gpointer user_data)
+{
+	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (user_data);
+
+	if (!g_source_is_destroyed (g_main_current_source ()))
+		isearch_hide (slot);
+
+	return FALSE;
+}
+
+static void
+isearch_timeout_destroy (gpointer user_data)
+{
+	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (user_data);
+
+	slot->details->isearch_timeout_id = 0;
+}
+
+static void
+isearch_timeout_restart (NautilusWindowSlot *slot)
+{
+	if (slot->details->isearch_timeout_id != 0) {
+		g_source_remove (slot->details->isearch_timeout_id);
+		slot->details->isearch_timeout_id = gdk_threads_add_timeout_full (
+			G_PRIORITY_LOW, ISEARCH_TIMEOUT,
+			isearch_timeout,
+			slot,
+			isearch_timeout_destroy);
+	}
+}
+
+static void
+isearch_send_focus_change (GtkWidget *widget, gboolean in)
+{
+	GdkEvent *event;
+
+	g_object_ref (G_OBJECT (widget));
+	gtk_widget_set_can_focus (widget, in);
+
+	event = gdk_event_new (GDK_FOCUS_CHANGE);
+	event->focus_change.type = GDK_FOCUS_CHANGE;
+	event->focus_change.window = g_object_ref (gtk_widget_get_window (widget));
+	event->focus_change.in = in;
+
+	gtk_widget_event (widget, event);
+
+	g_object_notify (G_OBJECT (widget), "has-focus");
+	g_object_unref (G_OBJECT (widget));
+	gdk_event_free (event);
+}
+
+static void
+isearch_hide (NautilusWindowSlot *slot)
+{
+	if (!slot->details->isearch_enable)
+		return;
+
+	if (slot->details->isearch_window == NULL)
+		return;
+
+	if (slot->details->isearch_entry_changed_id != 0) {
+		g_signal_handler_disconnect (G_OBJECT (slot->details->isearch_entry), slot->details->isearch_entry_changed_id);
+		slot->details->isearch_entry_changed_id = 0;
+	}
+	if (slot->details->isearch_timeout_id != 0) {
+		g_source_remove (slot->details->isearch_timeout_id);
+		slot->details->isearch_timeout_id = 0;
+	}
+	isearch_send_focus_change (slot->details->isearch_entry, FALSE);
+	gtk_widget_hide (slot->details->isearch_window);
+	gtk_entry_set_text (GTK_ENTRY (slot->details->isearch_entry), "");
+}
+
+static void
+isearch_dispose (NautilusWindowSlot *slot)
+{
+	if (!slot->details->isearch_enable)
+		return;
+
+	if (slot->details->isearch_entry_changed_id != 0) {
+		g_signal_handler_disconnect (G_OBJECT (slot->details->isearch_entry), slot->details->isearch_entry_changed_id);
+		slot->details->isearch_entry_changed_id = 0;
+	}
+
+	if (slot->details->isearch_timeout_id != 0) {
+		g_source_remove (slot->details->isearch_timeout_id);
+		slot->details->isearch_timeout_id = 0;
+	}
+	if (slot->details->isearch_window != NULL) {
+		gtk_widget_destroy (slot->details->isearch_window);
+		slot->details->isearch_window = NULL;
+		slot->details->isearch_entry = NULL;
+	}
+}
+
+static void
+isearch_ensure (NautilusWindowSlot *slot)
+{
+	GtkWidget *search_window;
+	GtkWidget *search_entry;
+	GtkWidget *frame;
+	GtkWidget *vbox;
+	GtkWindowGroup *group;
+
+	if (G_LIKELY (slot->details->isearch_window != NULL))
+		return;
+
+	search_window = gtk_window_new (GTK_WINDOW_POPUP);
+	gtk_window_set_screen (GTK_WINDOW (search_window), gtk_widget_get_screen (GTK_WIDGET (slot->details->window)));
+
+	g_signal_connect (G_OBJECT (search_window), "button-press-event", G_CALLBACK (isearch_button_press_event), slot);
+	g_signal_connect (G_OBJECT (search_window), "delete-event", G_CALLBACK (isearch_delete_event), slot);
+	g_signal_connect (G_OBJECT (search_window), "key-press-event", G_CALLBACK (isearch_key_press_event), slot);
+
+	frame = g_object_new (GTK_TYPE_FRAME, "shadow-type", GTK_SHADOW_ETCHED_IN, NULL);
+	gtk_container_add (GTK_CONTAINER (search_window), frame);
+	gtk_widget_show (frame);
+
+	vbox = g_object_new (GTK_TYPE_BOX, "border-width", 3, NULL);
+	gtk_container_add (GTK_CONTAINER (frame), vbox);
+	gtk_widget_show (vbox);
+
+	search_entry = gtk_entry_new ();
+	g_signal_connect (G_OBJECT (search_entry), "activate", G_CALLBACK (isearch_activate), slot);
+	g_signal_connect (G_OBJECT (search_entry), "preedit-changed", G_CALLBACK (isearch_preedit_changed), slot);
+	gtk_box_pack_start (GTK_BOX (vbox), search_entry, TRUE, TRUE, 0);
+	gtk_widget_realize (search_entry);
+	gtk_widget_show (search_entry);
+
+	slot->details->isearch_window = search_window;
+	slot->details->isearch_entry = search_entry;
+}
+
+static void
+isearch_position (NautilusWindowSlot *slot)
+{
+	GtkRequisition requisition;
+	GdkRectangle monitor;
+	GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (slot));
+	GdkScreen *screen = gdk_window_get_screen (window);
+	gint view_width, view_height;
+	gint view_x, view_y;
+	gint monitor_num;
+	gint x, y;
+
+	monitor_num = gdk_screen_get_monitor_at_window (screen, window);
+	gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+
+	gtk_widget_realize (slot->details->isearch_window);
+
+	gdk_window_get_origin (window, &view_x, &view_y);
+	view_width = gdk_window_get_width (window);
+	view_height = gdk_window_get_height (window);
+	gtk_widget_get_preferred_size (slot->details->isearch_window, NULL, &requisition);
+
+	if (view_x + view_width - requisition.width > gdk_screen_get_width (screen))
+		x = gdk_screen_get_width (screen) - requisition.width;
+	else if (view_x + view_width - requisition.width < 0)
+		x = 0;
+	else
+		x = view_x + view_width - requisition.width;
+
+	if (view_y + view_height > gdk_screen_get_height (screen))
+		y = gdk_screen_get_height (screen) - requisition.height;
+	else if (view_y + view_height < 0)
+		y = 0;
+	else
+		y = view_y + view_height - requisition.height;
+
+	gtk_window_move (GTK_WINDOW (slot->details->isearch_window), x, y);
+}
+
+static gboolean
+isearch_start (NautilusWindowSlot *slot)
+{
+	GTypeClass *klass;
+
+	if (G_UNLIKELY (!slot->details->isearch_enable))
+		return FALSE;
+
+	if (slot->details->isearch_window != NULL && gtk_widget_get_visible (slot->details->isearch_window))
+		return TRUE;
+
+	isearch_ensure (slot);
+	isearch_position (slot);
+	gtk_widget_show (slot->details->isearch_window);
+
+	if (G_UNLIKELY (slot->details->isearch_entry_changed_id == 0)) {
+		slot->details->isearch_entry_changed_id = g_signal_connect (
+			G_OBJECT (slot->details->isearch_entry),
+			"changed",
+			G_CALLBACK (isearch_changed),
+			slot);
+	}
+	slot->details->isearch_timeout_id = gdk_threads_add_timeout_full (
+		G_PRIORITY_LOW,
+		ISEARCH_TIMEOUT,
+		isearch_timeout,
+		slot,
+		isearch_timeout_destroy);
+
+	klass = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (slot->details->isearch_entry));
+	(*GTK_WIDGET_CLASS (klass)->grab_focus) (slot->details->isearch_entry);
+
+	isearch_send_focus_change (slot->details->isearch_entry, TRUE);
+	isearch_changed (GTK_EDITABLE (slot->details->isearch_entry), slot);
+	return TRUE;
+}
+
+static gboolean
+isearch_compare_filename (const gchar *f1, const gchar *f2, guint length)
+{
+	gchar *normalized_f1;
+	gchar *normalized_f2;
+	gchar *case_normalized_f1;
+	gchar *case_normalized_f2;
+	gboolean retval = FALSE;
+
+	normalized_f1 = g_utf8_normalize (f1, -1, G_NORMALIZE_ALL);
+	normalized_f2 = g_utf8_normalize (f2, -1, G_NORMALIZE_ALL);
+
+	if (G_LIKELY (normalized_f1 != NULL && normalized_f2 != NULL)) {
+		case_normalized_f1 = g_utf8_casefold (normalized_f1, -1);
+		case_normalized_f2 = g_utf8_casefold (normalized_f2, -1);
+
+		retval = (strncmp (case_normalized_f1, case_normalized_f2, length) == 0);
+	}
+	g_free (normalized_f1);
+	g_free (normalized_f2);
+	g_free (case_normalized_f1);
+	g_free (case_normalized_f2);
+	return retval;
+}
+
+static NautilusFile *
+isearch_find (NautilusWindowSlot *slot, const gchar *text)
+{
+	GList *files = isearch_get_sorted_files (slot);
+	GList *l;
+	NautilusFile *found = NULL;
+
+	for (l = files; l; l = g_list_next (l)) {
+		NautilusFile *file = NAUTILUS_FILE (l->data);
+		gchar *filename = nautilus_file_get_display_name (file);
+
+		if (isearch_compare_filename (filename, text, strlen (text)))
+			found = file;
+
+		g_free (filename);
+		if (found)
+			break;
+	}
+	return found;
+}
+
+static NautilusFile *
+isearch_find_next (NautilusWindowSlot *slot, const gchar *text)
+{
+	GList *files = isearch_get_sorted_files (slot);
+	NautilusFile *found = NULL;
+	GList *current;
+	GList *l;
+
+	current = g_list_find (files, slot->details->isearch_iter);
+	for (l = g_list_next (current); l; l = g_list_next (l)) {
+		NautilusFile *file = NAUTILUS_FILE (l->data);
+		gchar *display_name = nautilus_file_get_display_name (file);
+
+		if (isearch_compare_filename (display_name, text, strlen (text)))
+			found = file;
+
+		g_free (display_name);
+		if (found)
+			break;
+	}
+	return found;
+}
+
+static NautilusFile *
+isearch_find_prev (NautilusWindowSlot *slot, const gchar *text)
+{
+	GList *files = isearch_get_sorted_files (slot);
+	NautilusFile *found = NULL;
+	GList *current;
+	GList *l;
+
+	current = g_list_find (files, slot->details->isearch_iter);
+	for (l = g_list_previous (current); l; l = g_list_previous (l)) {
+		NautilusFile *file = NAUTILUS_FILE (l->data);
+		gchar *display_name = nautilus_file_get_display_name (file);
+
+		if (isearch_compare_filename (display_name, text, strlen (text)))
+			found = file;
+
+		g_free (display_name);
+		if (found)
+			break;
+	}
+	return found;
+}
+
+static void
+isearch_move_next (NautilusWindowSlot *slot)
+{
+	const gchar *text;
+	NautilusFile *iter;
+
+	text = gtk_entry_get_text (GTK_ENTRY (slot->details->isearch_entry));
+	iter = isearch_find_next (slot, text);
+	if (iter)
+		isearch_set_selection (slot, iter);
+}
+
+static void
+isearch_move_prev (NautilusWindowSlot *slot)
+{
+	const gchar *text;
+	NautilusFile *iter;
+
+	text = gtk_entry_get_text (GTK_ENTRY (slot->details->isearch_entry));
+	iter = isearch_find_prev (slot, text);
+	if (iter)
+		isearch_set_selection (slot, iter);
+}
+
+static void
+isearch_set_selection (NautilusWindowSlot *slot, NautilusFile *file)
+{
+	GList *list = g_list_append (list, file);
+
+	slot->details->isearch_iter = file;
+	nautilus_view_set_selection (slot->details->content_view, list);
+	g_list_free (list);
+}
--- src/nautilus-window.c.typeahead	2015-05-15 12:45:10.921152106 +0200
+++ src/nautilus-window.c	2015-05-15 12:51:43.804824080 +0200
@@ -2293,6 +2293,9 @@
 		}
 	}
 
+	if (nautilus_window_slot_isearch_key_press (active_slot, event))
+		return TRUE;
+
 	for (i = 0; i < G_N_ELEMENTS (extra_window_keybindings); i++) {
 		if (extra_window_keybindings[i].keyval == event->keyval) {
 			const GActionGroup *action_group;
--- libnautilus-private/nautilus-global-preferences.h.typeahead	2015-05-15 12:45:10.922152108 +0200
+++ libnautilus-private/nautilus-global-preferences.h	2015-05-15 12:53:39.649800686 +0200
@@ -158,6 +158,8 @@
 /* Recent files */
 #define NAUTILUS_PREFERENCES_RECENT_FILES_ENABLED          "remember-recent-files"
 
+/* Interactive Search (typeahead) */
+#define NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH     "enable-interactive-search"
 
 /* Move to trash shorcut changed dialog */
 #define NAUTILUS_PREFERENCES_SHOW_MOVE_TO_TRASH_SHORTCUT_CHANGED_DIALOG "show-move-to-trash-shortcut-changed-dialog"
--- libnautilus-private/org.gnome.nautilus.gschema.xml.in.typeahead	2015-05-13 19:24:43.000000000 +0200
+++ libnautilus-private/org.gnome.nautilus.gschema.xml.in	2015-05-15 12:45:10.922152108 +0200
@@ -166,6 +166,11 @@
       <_summary>Bulk rename utility</_summary>
       <_description>If set, Nautilus will append URIs of selected files and treat the result as a command line for bulk renaming. Bulk rename applications can register themselves in this key by setting the key to a space-separated string of their executable name and any command line options. If the executable name is not set to a full path, it will be searched for in the search path.</_description>
     </key>
+    <key name="enable-interactive-search" type="b">
+      <default>false</default>
+      <_summary>Enable interactive (type-ahead) search</_summary>
+      <_description>If set to true, enables interactive search, similar to Nautilus 3.4.</_description>
+    </key>
   </schema>
 
   <schema id="org.gnome.nautilus.icon-view" path="/org/gnome/nautilus/icon-view/" gettext-domain="nautilus">
