[nautilus] Enable "just type" searching
- From: William Jon McCann <mccann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus] Enable "just type" searching
- Date: Sat, 14 Jul 2012 18:18:08 +0000 (UTC)
commit 469eb89117e199a450aec3411183ed2e9f10f893
Author: William Jon McCann <jmccann redhat com>
Date: Fri Jul 13 19:04:29 2012 -0400
Enable "just type" searching
https://bugzilla.gnome.org/show_bug.cgi?id=679900
libnautilus-private/nautilus-icon-container.c | 585 -------------------------
src/nautilus-list-view.c | 2 +-
src/nautilus-query-editor.c | 142 ++++++-
src/nautilus-query-editor.h | 4 +
src/nautilus-window-slot.c | 76 ++--
src/nautilus-window-slot.h | 4 +
src/nautilus-window.c | 16 +-
7 files changed, 192 insertions(+), 637 deletions(-)
---
diff --git a/libnautilus-private/nautilus-icon-container.c b/libnautilus-private/nautilus-icon-container.c
index 3abffe7..c82b4af 100644
--- a/libnautilus-private/nautilus-icon-container.c
+++ b/libnautilus-private/nautilus-icon-container.c
@@ -198,7 +198,6 @@ static int compare_icons_vertical (NautilusIconContainer *container,
NautilusIcon *icon_b);
static void store_layout_timestamps_now (NautilusIconContainer *container);
-static void remove_search_entry_timeout (NautilusIconContainer *container);
static const char *nautilus_icon_container_accessible_action_names[] = {
"activate",
@@ -3911,8 +3910,6 @@ destroy (GtkWidget *object)
container->details->search_entry = NULL;
}
- remove_search_entry_timeout (container);
-
GTK_WIDGET_CLASS (nautilus_icon_container_parent_class)->destroy (object);
}
@@ -4115,7 +4112,6 @@ unrealize (GtkWidget *widget)
container = NAUTILUS_ICON_CONTAINER (widget);
nautilus_icon_dnd_fini (container);
- remove_search_entry_timeout (container);
GTK_WIDGET_CLASS (nautilus_icon_container_parent_class)->unrealize (widget);
}
@@ -4681,198 +4677,6 @@ motion_notify_event (GtkWidget *widget,
}
static void
-nautilus_icon_container_search_position_func (NautilusIconContainer *container,
- GtkWidget *search_dialog)
-{
- gint x, y;
- gint cont_x, cont_y;
- gint cont_width, cont_height;
- GdkWindow *cont_window;
- GdkScreen *screen;
- GtkRequisition requisition;
- gint monitor_num;
- GdkRectangle monitor;
-
-
- cont_window = gtk_widget_get_window (GTK_WIDGET (container));
- screen = gdk_window_get_screen (cont_window);
-
- monitor_num = gdk_screen_get_monitor_at_window (screen, cont_window);
- gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
-
- gtk_widget_realize (search_dialog);
-
- gdk_window_get_origin (cont_window, &cont_x, &cont_y);
- cont_width = gdk_window_get_width (cont_window);
- cont_height = gdk_window_get_height (cont_window);
-
- gtk_widget_get_preferred_size (search_dialog, &requisition, NULL);
-
- if (cont_x + cont_width > gdk_screen_get_width (screen)) {
- x = gdk_screen_get_width (screen) - requisition.width;
- } else if (cont_x + cont_width - requisition.width < 0) {
- x = 0;
- } else {
- x = cont_x + cont_width - requisition.width;
- }
-
- if (cont_y + cont_height + requisition.height > gdk_screen_get_height (screen)) {
- y = gdk_screen_get_height (screen) - requisition.height;
- } else if (cont_y + cont_height < 0) { /* isn't really possible ... */
- y = 0;
- } else {
- y = cont_y + cont_height;
- }
-
- gdk_window_move (gtk_widget_get_window (search_dialog), x, y);
-}
-
-/* Cut and paste from gtkwindow.c */
-static void
-send_focus_change (GtkWidget *widget, gboolean in)
-{
- GdkEvent *fevent;
-
- fevent = gdk_event_new (GDK_FOCUS_CHANGE);
-
- g_object_ref (widget);
- ((GdkEventFocus *) fevent)->in = in;
-
- gtk_widget_send_focus_change (widget, fevent);
-
- fevent->focus_change.type = GDK_FOCUS_CHANGE;
- fevent->focus_change.window = g_object_ref (gtk_widget_get_window (widget));
- fevent->focus_change.in = in;
-
- gtk_widget_event (widget, fevent);
-
- g_object_notify (G_OBJECT (widget), "has-focus");
-
- g_object_unref (widget);
- gdk_event_free (fevent);
-}
-
-static void
-nautilus_icon_container_search_dialog_hide (GtkWidget *search_dialog,
- NautilusIconContainer *container)
-{
- if (container->details->search_entry_changed_id) {
- g_signal_handler_disconnect (container->details->search_entry,
- container->details->search_entry_changed_id);
- container->details->search_entry_changed_id = 0;
- }
-
- remove_search_entry_timeout (container);
-
- /* send focus-in event */
- send_focus_change (GTK_WIDGET (container->details->search_entry), FALSE);
- gtk_widget_hide (search_dialog);
- gtk_entry_set_text (GTK_ENTRY (container->details->search_entry), "");
-}
-
-static gboolean
-nautilus_icon_container_search_entry_flush_timeout (gpointer data)
-{
- NautilusIconContainer *container = data;
-
- container->details->typeselect_flush_timeout = 0;
- nautilus_icon_container_search_dialog_hide (container->details->search_window, container);
-
- return FALSE;
-}
-
-static void
-add_search_entry_timeout (NautilusIconContainer *container)
-{
- container->details->typeselect_flush_timeout =
- g_timeout_add_seconds (NAUTILUS_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT,
- nautilus_icon_container_search_entry_flush_timeout,
- container);
-}
-
-static void
-remove_search_entry_timeout (NautilusIconContainer *container)
-{
- if (container->details->typeselect_flush_timeout) {
- g_source_remove (container->details->typeselect_flush_timeout);
- container->details->typeselect_flush_timeout = 0;
- }
-}
-
-static void
-reset_search_entry_timeout (NautilusIconContainer *container)
-{
- remove_search_entry_timeout (container);
- add_search_entry_timeout (container);
-}
-
-/* Because we're visible but offscreen, we just set a flag in the preedit
- * callback.
- */
-static void
-nautilus_icon_container_search_preedit_changed (GtkEntry *entry,
- gchar *preedit,
- NautilusIconContainer *container)
-{
- container->details->imcontext_changed = 1;
- reset_search_entry_timeout (container);
-}
-
-static void
-nautilus_icon_container_search_activate (GtkEntry *entry,
- NautilusIconContainer *container)
-{
- nautilus_icon_container_search_dialog_hide (container->details->search_window,
- container);
-
- activate_selected_items (container);
-}
-
-static gboolean
-nautilus_icon_container_search_delete_event (GtkWidget *widget,
- GdkEventAny *event,
- NautilusIconContainer *container)
-{
- nautilus_icon_container_search_dialog_hide (widget, container);
-
- return TRUE;
-}
-
-static gboolean
-nautilus_icon_container_search_button_press_event (GtkWidget *widget,
- GdkEventButton *event,
- NautilusIconContainer *container)
-{
- nautilus_icon_container_search_dialog_hide (widget, container);
-
- if (event->window == gtk_layout_get_bin_window (GTK_LAYOUT (container))) {
- button_press_event (GTK_WIDGET (container), event);
- }
-
- return TRUE;
-}
-
-static gboolean
-nautilus_icon_container_search_entry_button_press_event (GtkWidget *widget,
- GdkEventButton *event,
- NautilusIconContainer *container)
-{
- reset_search_entry_timeout (container);
-
- return FALSE;
-}
-
-static void
-nautilus_icon_container_search_populate_popup (GtkEntry *entry,
- GtkMenu *menu,
- NautilusIconContainer *container)
-{
- remove_search_entry_timeout (container);
- g_signal_connect_swapped (menu, "hide",
- G_CALLBACK (add_search_entry_timeout), container);
-}
-
-static void
nautilus_icon_container_get_icon_text (NautilusIconContainer *container,
NautilusIconData *data,
char **editable_text,
@@ -4888,331 +4692,6 @@ nautilus_icon_container_get_icon_text (NautilusIconContainer *container,
}
static gboolean
-nautilus_icon_container_search_iter (NautilusIconContainer *container,
- const char *key, gint n)
-{
- GList *p;
- NautilusIcon *icon;
- char *name;
- int count;
- char *normalized_key, *case_normalized_key;
- char *normalized_name, *case_normalized_name;
-
- g_assert (key != NULL);
- g_assert (n >= 1);
-
- normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
- if (!normalized_key) {
- return FALSE;
- }
- case_normalized_key = g_utf8_casefold (normalized_key, -1);
- g_free (normalized_key);
- if (!case_normalized_key) {
- return FALSE;
- }
-
- icon = NULL;
- name = NULL;
- count = 0;
- for (p = container->details->icons; p != NULL && count != n; p = p->next) {
- icon = p->data;
- nautilus_icon_container_get_icon_text (container, icon->data, &name,
- NULL, TRUE);
-
- /* This can happen if a key event is handled really early while
- * loading the icon container, before the items have all been
- * updated once.
- */
- if (!name) {
- continue;
- }
-
- normalized_name = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
- if (!normalized_name) {
- continue;
- }
- case_normalized_name = g_utf8_casefold (normalized_name, -1);
- g_free (normalized_name);
- if (!case_normalized_name) {
- continue;
- }
-
- if (strncmp (case_normalized_key, case_normalized_name,
- strlen (case_normalized_key)) == 0) {
- count++;
- }
-
- g_free (case_normalized_name);
- g_free (name);
- name = NULL;
- }
-
- g_free (case_normalized_key);
-
- if (count == n) {
- if (select_one_unselect_others (container, icon)) {
- g_signal_emit (container, signals[SELECTION_CHANGED], 0);
- }
- schedule_keyboard_icon_reveal (container, icon);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-nautilus_icon_container_search_move (GtkWidget *window,
- NautilusIconContainer *container,
- gboolean up)
-{
- gboolean ret;
- gint len;
- const gchar *text;
-
- text = gtk_entry_get_text (GTK_ENTRY (container->details->search_entry));
-
- g_assert (text != NULL);
-
- if (container->details->selected_iter == 0) {
- return;
- }
-
- if (up && container->details->selected_iter == 1) {
- return;
- }
-
- len = strlen (text);
-
- if (len < 1) {
- return;
- }
-
- /* search */
- unselect_all (container);
-
- ret = nautilus_icon_container_search_iter (container, text,
- up?((container->details->selected_iter) - 1):((container->details->selected_iter + 1)));
-
- if (ret) {
- /* found */
- container->details->selected_iter += up?(-1):(1);
- } else {
- /* return to old iter */
- nautilus_icon_container_search_iter (container, text,
- container->details->selected_iter);
- }
-}
-
-static gboolean
-nautilus_icon_container_search_scroll_event (GtkWidget *widget,
- GdkEventScroll *event,
- NautilusIconContainer *container)
-{
- gboolean retval = FALSE;
-
- if (event->direction == GDK_SCROLL_UP) {
- nautilus_icon_container_search_move (widget, container, TRUE);
- retval = TRUE;
- } else if (event->direction == GDK_SCROLL_DOWN) {
- nautilus_icon_container_search_move (widget, container, FALSE);
- retval = TRUE;
- }
-
- reset_search_entry_timeout (container);
-
- return retval;
-}
-
-static gboolean
-nautilus_icon_container_search_key_press_event (GtkWidget *widget,
- GdkEventKey *event,
- NautilusIconContainer *container)
-{
- gboolean retval = FALSE;
-
- g_assert (GTK_IS_WIDGET (widget));
- g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
-
- /* close window and cancel the search */
- if (event->keyval == GDK_KEY_Escape || event->keyval == GDK_KEY_Tab) {
- nautilus_icon_container_search_dialog_hide (widget, container);
- return TRUE;
- }
-
- /* close window and activate alternate */
- if (event->keyval == GDK_KEY_Return && event->state & GDK_SHIFT_MASK) {
- nautilus_icon_container_search_dialog_hide (widget,
- container);
-
- activate_selected_items_alternate (container, NULL);
- return TRUE;
- }
-
- /* select previous matching iter */
- if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up) {
- nautilus_icon_container_search_move (widget, container, TRUE);
- 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)) {
- nautilus_icon_container_search_move (widget, container, TRUE);
- retval = TRUE;
- }
-
- /* select next matching iter */
- if (event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down) {
- nautilus_icon_container_search_move (widget, container, FALSE);
- retval = TRUE;
- }
-
- if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
- && (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G)) {
- nautilus_icon_container_search_move (widget, container, FALSE);
- retval = TRUE;
- }
-
- reset_search_entry_timeout (container);
-
- return retval;
-}
-
-static void
-nautilus_icon_container_search_init (GtkWidget *entry,
- NautilusIconContainer *container)
-{
- gint ret;
- gint len;
- const gchar *text;
-
- g_assert (GTK_IS_ENTRY (entry));
- g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
-
- text = gtk_entry_get_text (GTK_ENTRY (entry));
- len = strlen (text);
-
- /* search */
- unselect_all (container);
- reset_search_entry_timeout (container);
-
- if (len < 1) {
- return;
- }
-
- ret = nautilus_icon_container_search_iter (container, text, 1);
-
- if (ret) {
- container->details->selected_iter = 1;
- }
-}
-
-static void
-nautilus_icon_container_ensure_interactive_directory (NautilusIconContainer *container)
-{
- GtkWidget *frame, *vbox;
-
- if (container->details->search_window != NULL) {
- return;
- }
-
- container->details->search_window = gtk_window_new (GTK_WINDOW_POPUP);
-
- gtk_window_set_modal (GTK_WINDOW (container->details->search_window), TRUE);
- gtk_window_set_type_hint (GTK_WINDOW (container->details->search_window),
- GDK_WINDOW_TYPE_HINT_COMBO);
-
- g_signal_connect (container->details->search_window, "delete_event",
- G_CALLBACK (nautilus_icon_container_search_delete_event),
- container);
- g_signal_connect (container->details->search_window, "key_press_event",
- G_CALLBACK (nautilus_icon_container_search_key_press_event),
- container);
- g_signal_connect (container->details->search_window, "button_press_event",
- G_CALLBACK (nautilus_icon_container_search_button_press_event),
- container);
- g_signal_connect (container->details->search_window, "scroll_event",
- G_CALLBACK (nautilus_icon_container_search_scroll_event),
- container);
-
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
- gtk_widget_show (frame);
- gtk_container_add (GTK_CONTAINER (container->details->search_window), frame);
-
- vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_widget_show (vbox);
- gtk_container_add (GTK_CONTAINER (frame), vbox);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
-
- /* add entry */
- container->details->search_entry = gtk_entry_new ();
- gtk_widget_show (container->details->search_entry);
- g_signal_connect (container->details->search_entry, "populate-popup",
- G_CALLBACK (nautilus_icon_container_search_populate_popup),
- container);
- g_signal_connect (container->details->search_entry, "activate",
- G_CALLBACK (nautilus_icon_container_search_activate),
- container);
- g_signal_connect (container->details->search_entry, "preedit-changed",
- G_CALLBACK (nautilus_icon_container_search_preedit_changed),
- container);
- g_signal_connect (container->details->search_entry, "button-press-event",
- G_CALLBACK (nautilus_icon_container_search_entry_button_press_event),
- container);
- gtk_container_add (GTK_CONTAINER (vbox), container->details->search_entry);
-
- gtk_widget_realize (container->details->search_entry);
-}
-
-/* Pops up the interactive search entry. If keybinding is TRUE then the user
- * started this by typing the start_interactive_search keybinding. Otherwise, it came from
- */
-static gboolean
-nautilus_icon_container_start_interactive_search (NautilusIconContainer *container)
-{
- /* We only start interactive search if we have focus. If one of our
- * children have focus, we don't want to start the search.
- */
- GtkWidgetClass *entry_parent_class;
-
- if (container->details->search_window != NULL &&
- gtk_widget_get_visible (container->details->search_window)) {
- return TRUE;
- }
-
- if (!gtk_widget_has_focus (GTK_WIDGET (container))) {
- return FALSE;
- }
-
- nautilus_icon_container_ensure_interactive_directory (container);
-
- /* done, show it */
- nautilus_icon_container_search_position_func (container, container->details->search_window);
- gtk_widget_show (container->details->search_window);
- if (container->details->search_entry_changed_id == 0) {
- container->details->search_entry_changed_id =
- g_signal_connect (container->details->search_entry, "changed",
- G_CALLBACK (nautilus_icon_container_search_init),
- container);
- }
-
- /* Grab focus will select all the text. We don't want that to happen, so we
- * call the parent instance and bypass the selection change. This is probably
- * really non-kosher. */
- entry_parent_class = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (container->details->search_entry));
- (entry_parent_class->grab_focus) (container->details->search_entry);
-
- /* send focus-in event */
- send_focus_change (container->details->search_entry, TRUE);
-
- /* search first matching iter */
- nautilus_icon_container_search_init (container->details->search_entry, container);
-
- return TRUE;
-}
-
-static gboolean
handle_popups (NautilusIconContainer *container,
GdkEventKey *event,
const char *signal)
@@ -5355,70 +4834,6 @@ key_press_event (GtkWidget *widget,
if (!handled) {
handled = GTK_WIDGET_CLASS (nautilus_icon_container_parent_class)->key_press_event (widget, event);
}
-
- /* We pass the event to the search_entry. If its text changes, then we
- * start the typeahead find capabilities.
- * Copied from NautilusIconContainer */
- if (!handled &&
- event->keyval != GDK_KEY_slash /* don't steal slash key event, used for "go to" */ &&
- event->keyval != GDK_KEY_BackSpace &&
- event->keyval != GDK_KEY_Delete) {
- GdkEvent *new_event;
- GdkWindow *window;
- char *old_text;
- const char *new_text;
- gboolean retval;
- GdkScreen *screen;
- gboolean text_modified;
- gulong popup_menu_id;
-
- nautilus_icon_container_ensure_interactive_directory (container);
-
- /* Make a copy of the current text */
- old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (container->details->search_entry)));
- new_event = gdk_event_copy ((GdkEvent *) event);
- window = ((GdkEventKey *) new_event)->window;
- ((GdkEventKey *) new_event)->window = gtk_widget_get_window (container->details->search_entry);
- gtk_widget_realize (container->details->search_window);
-
- popup_menu_id = g_signal_connect (container->details->search_entry,
- "popup_menu", G_CALLBACK (gtk_true), NULL);
-
- /* Move the entry off screen */
- screen = gtk_widget_get_screen (GTK_WIDGET (container));
- gtk_window_move (GTK_WINDOW (container->details->search_window),
- gdk_screen_get_width (screen) + 1,
- gdk_screen_get_height (screen) + 1);
- gtk_widget_show (container->details->search_window);
-
- /* Send the event to the window. If the preedit_changed signal is emitted
- * during this event, we will set priv->imcontext_changed */
- container->details->imcontext_changed = FALSE;
- retval = gtk_widget_event (container->details->search_entry, new_event);
- gtk_widget_hide (container->details->search_window);
-
- g_signal_handler_disconnect (container->details->search_entry,
- popup_menu_id);
-
- /* We check to make sure that the entry tried to handle the text, and that
- * the text has changed. */
- new_text = gtk_entry_get_text (GTK_ENTRY (container->details->search_entry));
- text_modified = strcmp (old_text, new_text) != 0;
- g_free (old_text);
- if (container->details->imcontext_changed || /* we're in a preedit */
- (retval && text_modified)) { /* ...or the text was modified */
- if (nautilus_icon_container_start_interactive_search (container)) {
- gtk_widget_grab_focus (GTK_WIDGET (container));
- return TRUE;
- } else {
- gtk_entry_set_text (GTK_ENTRY (container->details->search_entry), "");
- return FALSE;
- }
- }
-
- ((GdkEventKey *) new_event)->window = window;
- gdk_event_free (new_event);
- }
return handled;
}
diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c
index e482eed..7fceecb 100644
--- a/src/nautilus-list-view.c
+++ b/src/nautilus-list-view.c
@@ -1547,7 +1547,7 @@ create_and_set_up_tree_view (NautilusListView *view)
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify) g_object_unref);
- gtk_tree_view_set_enable_search (view->details->tree_view, TRUE);
+ gtk_tree_view_set_enable_search (view->details->tree_view, FALSE);
/* Don't handle backspace key. It's used to open the parent folder. */
binding_set = gtk_binding_set_by_class (GTK_WIDGET_GET_CLASS (view->details->tree_view));
diff --git a/src/nautilus-query-editor.c b/src/nautilus-query-editor.c
index 0fb4bd9..b993830 100644
--- a/src/nautilus-query-editor.c
+++ b/src/nautilus-query-editor.c
@@ -74,6 +74,7 @@ struct NautilusQueryEditorDetails {
GList *rows;
char *last_set_query_text;
+ gboolean got_preedit;
};
enum {
@@ -112,6 +113,118 @@ static NautilusQueryEditorRowOps row_type[] = {
G_DEFINE_TYPE (NautilusQueryEditor, nautilus_query_editor, GTK_TYPE_BOX);
+/* taken from gtk/gtktreeview.c */
+static void
+send_focus_change (GtkWidget *widget,
+ GdkDevice *device,
+ gboolean in)
+{
+ GdkDeviceManager *device_manager;
+ GList *devices, *d;
+
+ device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
+ devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
+ devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
+ devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
+
+ for (d = devices; d; d = d->next) {
+ GdkDevice *dev = d->data;
+ GdkEvent *fevent;
+ GdkWindow *window;
+
+ if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
+ continue;
+
+ window = gtk_widget_get_window (widget);
+
+ /* Skip non-master keyboards that haven't
+ * selected for events from this window
+ */
+ if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
+ !gdk_window_get_device_events (window, dev))
+ continue;
+
+ fevent = gdk_event_new (GDK_FOCUS_CHANGE);
+
+ fevent->focus_change.type = GDK_FOCUS_CHANGE;
+ fevent->focus_change.window = g_object_ref (window);
+ fevent->focus_change.in = in;
+ gdk_event_set_device (fevent, device);
+
+ gtk_widget_send_focus_change (widget, fevent);
+
+ gdk_event_free (fevent);
+ }
+
+ g_list_free (devices);
+}
+
+static void
+entry_focus_hack (GtkWidget *entry,
+ GdkDevice *device)
+{
+ GtkEntryClass *entry_class;
+ GtkWidgetClass *entry_parent_class;
+
+ /* Grab focus will select all the text. We don't want that to happen, so we
+ * call the parent instance and bypass the selection change. This is probably
+ * really non-kosher. */
+ entry_class = g_type_class_peek (GTK_TYPE_ENTRY);
+ entry_parent_class = g_type_class_peek_parent (entry_class);
+ (entry_parent_class->grab_focus) (entry);
+
+ /* send focus-in event */
+ send_focus_change (entry, device, TRUE);
+}
+
+static void
+entry_preedit_changed_cb (GtkEntry *entry,
+ gchar *preedit,
+ NautilusQueryEditor *editor)
+{
+ editor->details->got_preedit = TRUE;
+}
+
+gboolean
+nautilus_query_editor_handle_event (NautilusQueryEditor *editor,
+ GdkEventKey *event)
+{
+ GdkEvent *new_event;
+ gboolean handled = FALSE;
+ gulong id;
+ gboolean retval;
+ gboolean text_changed;
+ char *old_text;
+ const char *new_text;
+
+ editor->details->got_preedit = FALSE;
+
+ old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (editor->details->entry)));
+
+ id = g_signal_connect (editor->details->entry, "preedit-changed",
+ G_CALLBACK (entry_preedit_changed_cb), editor);
+
+ new_event = gdk_event_copy ((GdkEvent *) event);
+ ((GdkEventKey *) new_event)->window = gtk_widget_get_window (editor->details->entry);
+
+ gtk_widget_realize (editor->details->entry);
+ retval = gtk_widget_event (editor->details->entry, new_event);
+ gdk_event_free (new_event);
+
+ g_signal_handler_disconnect (editor->details->entry, id);
+
+ new_text = gtk_entry_get_text (GTK_ENTRY (editor->details->entry));
+ text_changed = strcmp (old_text, new_text) != 0;
+ g_free (old_text);
+
+ handled = (editor->details->got_preedit
+ || (retval && text_changed));
+
+ editor->details->got_preedit = FALSE;
+
+ return handled;
+}
+
static void
nautilus_query_editor_dispose (GObject *object)
{
@@ -995,7 +1108,7 @@ void
nautilus_query_editor_grab_focus (NautilusQueryEditor *editor)
{
if (editor->details->is_visible) {
- gtk_widget_grab_focus (editor->details->entry);
+ entry_focus_hack (editor->details->entry, gtk_get_current_event_device ());
}
}
@@ -1072,19 +1185,11 @@ nautilus_query_editor_new (void)
}
static void
-update_location (NautilusQueryEditor *editor,
- NautilusQuery *query)
+update_location (NautilusQueryEditor *editor)
{
- char *uri;
NautilusFile *file;
- uri = nautilus_query_get_location (query);
- if (uri == NULL) {
- return;
- }
- g_free (editor->details->current_uri);
- editor->details->current_uri = uri;
- file = nautilus_file_get_by_uri (uri);
+ file = nautilus_file_get_by_uri (editor->details->current_uri);
if (file != NULL) {
char *name;
@@ -1105,6 +1210,15 @@ update_location (NautilusQueryEditor *editor,
}
void
+nautilus_query_editor_set_location (NautilusQueryEditor *editor,
+ GFile *location)
+{
+ g_free (editor->details->current_uri);
+ editor->details->current_uri = g_file_get_uri (location);
+ update_location (editor);
+}
+
+void
nautilus_query_editor_set_query (NautilusQueryEditor *editor, NautilusQuery *query)
{
NautilusQueryEditorRowType type;
@@ -1122,9 +1236,13 @@ nautilus_query_editor_set_query (NautilusQueryEditor *editor, NautilusQuery *que
}
editor->details->change_frozen = TRUE;
+
gtk_entry_set_text (GTK_ENTRY (editor->details->entry), text);
- update_location (editor, query);
+ g_free (editor->details->current_uri);
+ editor->details->current_uri = nautilus_query_get_location (query);
+
+ update_location (editor);
for (type = 0; type < NAUTILUS_QUERY_EDITOR_ROW_LAST; type++) {
row_type[type].add_rows_from_query (editor, query);
diff --git a/src/nautilus-query-editor.h b/src/nautilus-query-editor.h
index 7cdbaa6..cc3bf1f 100644
--- a/src/nautilus-query-editor.h
+++ b/src/nautilus-query-editor.h
@@ -64,11 +64,15 @@ void nautilus_query_editor_set_default_query (NautilusQueryEditor *editor)
void nautilus_query_editor_grab_focus (NautilusQueryEditor *editor);
void nautilus_query_editor_clear_query (NautilusQueryEditor *editor);
+gboolean nautilus_query_editor_handle_event (NautilusQueryEditor *editor,
+ GdkEventKey *event);
NautilusQuery *nautilus_query_editor_get_query (NautilusQueryEditor *editor);
void nautilus_query_editor_set_query (NautilusQueryEditor *editor,
NautilusQuery *query);
GFile * nautilus_query_editor_get_location (NautilusQueryEditor *editor);
+void nautilus_query_editor_set_location (NautilusQueryEditor *editor,
+ GFile *location);
void nautilus_query_editor_set_visible (NautilusQueryEditor *editor,
gboolean visible);
diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c
index 407c49b..0fbfb9d 100644
--- a/src/nautilus-window-slot.c
+++ b/src/nautilus-window-slot.c
@@ -52,6 +52,13 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
+gboolean
+nautilus_window_slot_handle_event (NautilusWindowSlot *slot,
+ GdkEventKey *event)
+{
+ return nautilus_query_editor_handle_event (slot->query_editor, event);
+}
+
static void
sync_search_directory (NautilusWindowSlot *slot)
{
@@ -143,56 +150,34 @@ update_query_editor (NautilusWindowSlot *slot)
{
NautilusDirectory *directory;
NautilusSearchDirectory *search_directory;
- NautilusQuery *query;
directory = nautilus_directory_get (slot->location);
- query = NULL;
-
if (NAUTILUS_IS_SEARCH_DIRECTORY (directory)) {
+ NautilusQuery *query;
search_directory = NAUTILUS_SEARCH_DIRECTORY (directory);
query = nautilus_search_directory_get_query (search_directory);
+ if (query != NULL) {
+ nautilus_query_editor_set_query (slot->query_editor,
+ query);
+ g_object_unref (query);
+ }
+ } else {
+ nautilus_query_editor_set_location (slot->query_editor, slot->location);
}
- if (query == NULL) {
- char *uri;
- uri = g_file_get_uri (slot->location);
- query = nautilus_query_new ();
- nautilus_query_set_location (query, uri);
- g_free (uri);
- }
- nautilus_query_editor_set_query (slot->query_editor,
- query);
- g_object_unref (query);
-
nautilus_directory_unref (directory);
}
static void
ensure_query_editor (NautilusWindowSlot *slot)
{
- GtkWidget *query_editor;
+ g_assert (slot->query_editor != NULL);
- if (slot->query_editor != NULL) {
- return;
- }
-
- query_editor = nautilus_query_editor_new ();
- slot->query_editor = NAUTILUS_QUERY_EDITOR (query_editor);
-
- nautilus_window_slot_add_extra_location_widget (slot, query_editor);
- gtk_widget_show (query_editor);
+ gtk_widget_show (GTK_WIDGET (slot->query_editor));
nautilus_query_editor_grab_focus (slot->query_editor);
update_query_editor (slot);
-
- g_signal_connect_object (slot->query_editor, "changed",
- G_CALLBACK (query_editor_changed_callback), slot, 0);
- g_signal_connect_object (slot->query_editor, "cancel",
- G_CALLBACK (query_editor_cancel_callback), slot, 0);
-
- g_object_add_weak_pointer (G_OBJECT (slot->query_editor),
- (gpointer *) &slot->query_editor);
}
void
@@ -201,13 +186,24 @@ nautilus_window_slot_set_query_editor_visible (NautilusWindowSlot *slot,
{
if (visible) {
ensure_query_editor (slot);
+ gtk_widget_show (GTK_WIDGET (slot->query_editor));
nautilus_query_editor_set_visible (slot->query_editor, TRUE);
nautilus_query_editor_grab_focus (slot->query_editor);
+
+ if (slot->qe_changed_id == 0)
+ slot->qe_changed_id = g_signal_connect (slot->query_editor, "changed",
+ G_CALLBACK (query_editor_changed_callback), slot);
+ if (slot->qe_cancel_id == 0)
+ slot->qe_cancel_id = g_signal_connect (slot->query_editor, "cancel",
+ G_CALLBACK (query_editor_cancel_callback), slot);
+
} else {
- if (slot->query_editor != NULL) {
- gtk_widget_destroy (GTK_WIDGET (slot->query_editor));
- g_assert (slot->query_editor == NULL);
- }
+ gtk_widget_hide (GTK_WIDGET (slot->query_editor));
+ g_signal_handler_disconnect (slot->query_editor, slot->qe_changed_id);
+ slot->qe_changed_id = 0;
+ g_signal_handler_disconnect (slot->query_editor, slot->qe_cancel_id);
+ slot->qe_cancel_id = 0;
+ nautilus_query_editor_clear_query (slot->query_editor);
}
}
@@ -270,6 +266,11 @@ nautilus_window_slot_init (NautilusWindowSlot *slot)
gtk_box_pack_start (GTK_BOX (slot), extras_vbox, FALSE, FALSE, 0);
gtk_widget_show (extras_vbox);
+ slot->query_editor = NAUTILUS_QUERY_EDITOR (nautilus_query_editor_new ());
+ nautilus_window_slot_add_extra_location_widget (slot, GTK_WIDGET (slot->query_editor));
+ g_object_add_weak_pointer (G_OBJECT (slot->query_editor),
+ (gpointer *) &slot->query_editor);
+
slot->view_overlay = gtk_overlay_new ();
gtk_widget_add_events (slot->view_overlay,
GDK_ENTER_NOTIFY_MASK |
@@ -666,8 +667,7 @@ remove_all_extra_location_widgets (GtkWidget *widget,
NautilusDirectory *directory;
directory = nautilus_directory_get (slot->location);
- if (!NAUTILUS_IS_SEARCH_DIRECTORY (directory)
- || (widget != GTK_WIDGET (slot->query_editor))) {
+ if (widget != GTK_WIDGET (slot->query_editor)) {
gtk_container_remove (GTK_CONTAINER (slot->extra_location_widgets), widget);
}
diff --git a/src/nautilus-window-slot.h b/src/nautilus-window-slot.h
index 42586f1..c925c4e 100644
--- a/src/nautilus-window-slot.h
+++ b/src/nautilus-window-slot.h
@@ -90,6 +90,8 @@ struct NautilusWindowSlot {
gboolean allow_stop;
NautilusQueryEditor *query_editor;
+ gulong qe_changed_id;
+ gulong qe_cancel_id;
/* New location. */
NautilusLocationChangeType location_change_type;
@@ -122,6 +124,8 @@ void nautilus_window_slot_update_title (NautilusWindowSlot *slot);
void nautilus_window_slot_update_icon (NautilusWindowSlot *slot);
void nautilus_window_slot_set_query_editor_visible (NautilusWindowSlot *slot,
gboolean visible);
+gboolean nautilus_window_slot_handle_event (NautilusWindowSlot *slot,
+ GdkEventKey *event);
GFile * nautilus_window_slot_get_location (NautilusWindowSlot *slot);
char * nautilus_window_slot_get_location_uri (NautilusWindowSlot *slot);
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index 7ee9a82..7d5b712 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -1449,6 +1449,7 @@ nautilus_window_key_press_event (GtkWidget *widget,
NautilusView *view;
GtkWidget *focus_widget;
int i;
+ gboolean handled = FALSE;
window = NAUTILUS_WINDOW (widget);
@@ -1500,7 +1501,20 @@ nautilus_window_key_press_event (GtkWidget *widget,
}
}
- return GTK_WIDGET_CLASS (nautilus_window_parent_class)->key_press_event (widget, event);
+ if (!handled &&
+ event->keyval != GDK_KEY_slash /* don't steal slash key event, used for "go to" */ &&
+ event->keyval != GDK_KEY_BackSpace &&
+ event->keyval != GDK_KEY_Delete) {
+ if (nautilus_window_slot_handle_event (window->details->active_slot, event)) {
+ toggle_toolbar_search_button (window, TRUE);
+ return TRUE;
+ }
+ }
+
+ if (!handled)
+ handled = GTK_WIDGET_CLASS (nautilus_window_parent_class)->key_press_event (widget, event);
+
+ return handled;
}
/*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]