Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 533640
Collapse All | Expand All

(-)nautilus-3.8.2.orig/libnautilus-private/nautilus-global-preferences.h (+1 lines)
Lines 160-165 Link Here
160
/* Recent files */
160
/* Recent files */
161
#define NAUTILUS_PREFERENCES_RECENT_FILES_ENABLED          "remember-recent-files"
161
#define NAUTILUS_PREFERENCES_RECENT_FILES_ENABLED          "remember-recent-files"
162
162
163
#define NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH		"enable-interactive-search"
163
164
164
void nautilus_global_preferences_init                      (void);
165
void nautilus_global_preferences_init                      (void);
165
char *nautilus_global_preferences_get_default_folder_viewer_preference_as_iid (void);
166
char *nautilus_global_preferences_get_default_folder_viewer_preference_as_iid (void);
(-)nautilus-3.8.2.orig/libnautilus-private/org.gnome.nautilus.gschema.xml.in (+5 lines)
Lines 164-169 Link Here
164
      <_summary>Bulk rename utility</_summary>
164
      <_summary>Bulk rename utility</_summary>
165
      <_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>
165
      <_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>
166
    </key>
166
    </key>
167
    <key name="enable-interactive-search" type="b">
168
      <default>false</default>
169
      <_summary>Enable interactive (type-ahead) search</_summary>
170
      <_description>If set to true, enables interactive search, similar to Nautilus 3.4.</_description>
171
    </key>
167
  </schema>
172
  </schema>
168
173
169
  <schema id="org.gnome.nautilus.icon-view" path="/org/gnome/nautilus/icon-view/" gettext-domain="nautilus">
174
  <schema id="org.gnome.nautilus.icon-view" path="/org/gnome/nautilus/icon-view/" gettext-domain="nautilus">
(-)nautilus-3.8.2.orig/src/nautilus-list-view.c (-1 / +11 lines)
Lines 2364-2369 Link Here
2364
	GList *node;
2364
	GList *node;
2365
	GList *iters, *l;
2365
	GList *iters, *l;
2366
	NautilusFile *file;
2366
	NautilusFile *file;
2367
	GtkTreePath *path = NULL;
2367
	
2368
	
2368
	list_view = NAUTILUS_LIST_VIEW (view);
2369
	list_view = NAUTILUS_LIST_VIEW (view);
2369
	tree_selection = gtk_tree_view_get_selection (list_view->details->tree_view);
2370
	tree_selection = gtk_tree_view_get_selection (list_view->details->tree_view);
Lines 2378-2387 Link Here
2378
		for (l = iters; l != NULL; l = l->next) {
2379
		for (l = iters; l != NULL; l = l->next) {
2379
			gtk_tree_selection_select_iter (tree_selection,
2380
			gtk_tree_selection_select_iter (tree_selection,
2380
							(GtkTreeIter *)l->data);
2381
							(GtkTreeIter *)l->data);
2382
			if (!path)
2383
				path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_view->details->model), (GtkTreeIter *)l->data);
2381
		}
2384
		}
2382
		g_list_free_full (iters, g_free);
2385
		g_list_free_full (iters, g_free);
2383
	}
2386
	}
2384
2387
	if (path) {
2388
		gtk_tree_view_set_cursor_on_cell (list_view->details->tree_view,
2389
			  path,
2390
			  list_view->details->file_name_column,
2391
		  	GTK_CELL_RENDERER (list_view->details->file_name_cell),
2392
		  	TRUE);
2393
		gtk_tree_path_free (path);
2394
	}
2385
	g_signal_handlers_unblock_by_func (tree_selection, list_selection_changed_callback, view);
2395
	g_signal_handlers_unblock_by_func (tree_selection, list_selection_changed_callback, view);
2386
	nautilus_view_notify_selection_changed (view);
2396
	nautilus_view_notify_selection_changed (view);
2387
}
2397
}
(-)nautilus-3.8.2.orig/src/nautilus-window-slot.c (-6 / +890 lines)
Lines 128-133 Link Here
128
	gboolean tried_mount;
128
	gboolean tried_mount;
129
	NautilusWindowGoToCallback open_callback;
129
	NautilusWindowGoToCallback open_callback;
130
	gpointer open_callback_user_data;
130
	gpointer open_callback_user_data;
131
132
	/* Interactive search */
133
	gboolean isearch_enable;
134
	gboolean isearch_imcontext_changed;
135
	gboolean isearch_disable_hide;
136
	NautilusFile *isearch_selected_file;
137
	GtkWidget *isearch_window;
138
	GtkWidget *isearch_entry;
139
	gulong isearch_entry_changed_id;
140
	guint isearch_timeout_id;
141
	gulong isearch_configure_event_id;
131
};
142
};
132
143
133
static guint signals[LAST_SIGNAL] = { 0 };
144
static guint signals[LAST_SIGNAL] = { 0 };
Lines 138-143 Link Here
138
static void nautilus_window_slot_connect_new_content_view (NautilusWindowSlot *slot);
149
static void nautilus_window_slot_connect_new_content_view (NautilusWindowSlot *slot);
139
static void nautilus_window_slot_emit_location_change (NautilusWindowSlot *slot, GFile *from, GFile *to);
150
static void nautilus_window_slot_emit_location_change (NautilusWindowSlot *slot, GFile *from, GFile *to);
140
151
152
/* Interactive search */
153
static void isearch_ensure (NautilusWindowSlot *slot);
154
static gboolean isearch_start (NautilusWindowSlot *slot, GdkDevice *device);
155
static void isearch_enable_changed (gpointer callback_data);
156
static void isearch_dispose (NautilusWindowSlot *slot);
157
static void isearch_hide (NautilusWindowSlot *slot,
158
			GdkDevice   *device);
159
160
#define ISEARCH_TIMEOUT 	5000
161
141
static void
162
static void
142
nautilus_window_slot_sync_search_widgets (NautilusWindowSlot *slot)
163
nautilus_window_slot_sync_search_widgets (NautilusWindowSlot *slot)
143
{
164
{
Lines 442-458 Link Here
442
463
443
	retval = FALSE;
464
	retval = FALSE;
444
	window = nautilus_window_slot_get_window (slot);
465
	window = nautilus_window_slot_get_window (slot);
445
	if (!NAUTILUS_IS_DESKTOP_WINDOW (window)) {
446
		retval = nautilus_query_editor_handle_event (slot->details->query_editor, event);
447
	}
448
466
449
	if (retval) {
467
	if (slot->details->isearch_enable) {
450
		nautilus_window_slot_set_search_visible (slot, TRUE);
468
		GdkEvent *new_event;
451
	}
469
		char *old_text;
470
		const char *new_text;
471
		gboolean retval;
472
		GdkScreen *screen;
473
		gboolean text_modified;
474
		gulong popup_menu_id;
475
476
		isearch_ensure (slot);
477
478
		/* Make a copy of the current text */
479
		old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (slot->details->isearch_entry)));
480
		new_event = gdk_event_copy ((GdkEvent *) event);
481
		g_object_unref (((GdkEventKey *) new_event)->window);
482
		((GdkEventKey *) new_event)->window = g_object_ref (gtk_widget_get_window (slot->details->isearch_window));
483
		gtk_widget_realize (slot->details->isearch_window);
484
485
		popup_menu_id = g_signal_connect (slot->details->isearch_entry, 
486
			"popup-menu", G_CALLBACK (gtk_true),
487
			NULL);
488
489
		/* Move the entry off screen */
490
		screen = gtk_widget_get_screen (GTK_WIDGET (slot));
491
		gtk_window_move (GTK_WINDOW (slot->details->isearch_window),
492
		gdk_screen_get_width (screen) + 1,
493
		gdk_screen_get_height (screen) + 1);
494
		gtk_widget_show (slot->details->isearch_window);
495
496
		/* Send the event to the window.  If the preedit_changed signal is emitted
497
		* during this event, we will set priv->imcontext_changed  */
498
		slot->details->isearch_imcontext_changed = FALSE;
499
		retval = gtk_widget_event (slot->details->isearch_window, new_event);
500
		gdk_event_free (new_event);
501
		gtk_widget_hide (slot->details->isearch_window);
502
503
		g_signal_handler_disconnect (slot->details->isearch_entry, 
504
			popup_menu_id);
505
506
		/* We check to make sure that the entry tried to handle the text, and that
507
		* the text has changed.
508
		*/
509
		new_text = gtk_entry_get_text (GTK_ENTRY (slot->details->isearch_entry));
510
		text_modified = strcmp (old_text, new_text) != 0;
511
		g_free (old_text);
512
		if (slot->details->isearch_imcontext_changed ||
513
			(retval && text_modified))
514
		{
515
			if (isearch_start (slot,
516
					gdk_event_get_device ((GdkEvent *) event)))	{
517
				gtk_widget_grab_focus (GTK_WIDGET (slot));
518
				return TRUE;
519
			}
520
			else {
521
				gtk_entry_set_text (GTK_ENTRY (slot->details->isearch_entry), "");
522
				return FALSE;
523
			}
524
		}
525
	} else {
526
		if (!NAUTILUS_IS_DESKTOP_WINDOW (window)) {
527
			retval = nautilus_query_editor_handle_event (slot->details->query_editor, event);
528
		}
452
529
530
		if (retval) {
531
			nautilus_window_slot_set_search_visible (slot, TRUE);
532
		}
533
	}
453
	return retval;
534
	return retval;
454
}
535
}
455
536
537
static gboolean
538
configure_event_cb (GtkWidget         *widget,
539
                    GdkEventConfigure *event,
540
                    NautilusWindowSlot *slot)
541
{
542
	isearch_hide (slot, NULL);
543
	return FALSE;
544
}
545
456
static void
546
static void
457
real_active (NautilusWindowSlot *slot)
547
real_active (NautilusWindowSlot *slot)
458
{
548
{
Lines 477-482 Link Here
477
		nautilus_window_slot_sync_view_as_menus (slot);
567
		nautilus_window_slot_sync_view_as_menus (slot);
478
		nautilus_window_load_extension_menus (window);
568
		nautilus_window_load_extension_menus (window);
479
	}
569
	}
570
	if (slot->details->isearch_configure_event_id == 0) {
571
		slot->details->isearch_configure_event_id =
572
			g_signal_connect (GTK_WIDGET (slot->details->window),
573
			"configure-event",
574
			G_CALLBACK (configure_event_cb),
575
			slot);
576
	}
480
}
577
}
481
578
482
static void
579
static void
Lines 486-491 Link Here
486
583
487
	window = nautilus_window_slot_get_window (slot);
584
	window = nautilus_window_slot_get_window (slot);
488
	g_assert (slot == nautilus_window_get_active_slot (window));
585
	g_assert (slot == nautilus_window_get_active_slot (window));
586
	isearch_hide (slot, NULL);
587
	if (slot->details->isearch_configure_event_id != 0) {
588
		g_signal_handler_disconnect (GTK_WIDGET (slot->details->window),
589
			slot->details->isearch_configure_event_id);
590
		slot->details->isearch_configure_event_id = 0;
591
	}
489
}
592
}
490
593
491
static void
594
static void
Lines 612-617 Link Here
612
{
715
{
613
	slot->details = G_TYPE_INSTANCE_GET_PRIVATE
716
	slot->details = G_TYPE_INSTANCE_GET_PRIVATE
614
		(slot, NAUTILUS_TYPE_WINDOW_SLOT, NautilusWindowSlotDetails);
717
		(slot, NAUTILUS_TYPE_WINDOW_SLOT, NautilusWindowSlotDetails);
718
719
	slot->details->isearch_enable =
720
		g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH);
721
722
	g_signal_connect_swapped (nautilus_preferences,
723
				  "changed::" NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH, 
724
				  G_CALLBACK(isearch_enable_changed), slot);
725
}
726
727
static void
728
nautilus_window_slot_finalize (GObject *object)
729
{
730
	NautilusWindowSlot *slot;
731
732
	slot = NAUTILUS_WINDOW_SLOT (object);
733
734
	g_signal_handlers_disconnect_by_func (nautilus_preferences,
735
					      isearch_enable_changed, slot);
736
737
	G_OBJECT_CLASS (nautilus_window_slot_parent_class)->finalize (object);
615
}
738
}
616
739
617
static void
740
static void
Lines 2415-2420 Link Here
2415
2538
2416
	slot = NAUTILUS_WINDOW_SLOT (object);
2539
	slot = NAUTILUS_WINDOW_SLOT (object);
2417
2540
2541
	isearch_dispose (slot);
2542
2418
	nautilus_window_slot_clear_forward_list (slot);
2543
	nautilus_window_slot_clear_forward_list (slot);
2419
	nautilus_window_slot_clear_back_list (slot);
2544
	nautilus_window_slot_clear_back_list (slot);
2420
2545
Lines 2491-2496 Link Here
2491
	oclass->constructed = nautilus_window_slot_constructed;
2614
	oclass->constructed = nautilus_window_slot_constructed;
2492
	oclass->set_property = nautilus_window_slot_set_property;
2615
	oclass->set_property = nautilus_window_slot_set_property;
2493
	oclass->get_property = nautilus_window_slot_get_property;
2616
	oclass->get_property = nautilus_window_slot_get_property;
2617
	oclass->finalize = nautilus_window_slot_finalize;
2494
2618
2495
	signals[ACTIVE] =
2619
	signals[ACTIVE] =
2496
		g_signal_new ("active",
2620
		g_signal_new ("active",
Lines 2847-2849 Link Here
2847
			     "window", window,
2971
			     "window", window,
2848
			     NULL);
2972
			     NULL);
2849
}
2973
}
2974
2975
/* Interactive search */
2976
2977
static void
2978
isearch_ensure (NautilusWindowSlot *slot);
2979
static gboolean
2980
isearch_timeout (gpointer user_data);
2981
static void
2982
isearch_timeout_destroy (gpointer user_data);
2983
static void
2984
isearch_timeout_restart (NautilusWindowSlot *slot);
2985
static gboolean
2986
isearch_window_delete_event (GtkWidget *widget,
2987
				   GdkEventAny *event,
2988
				   NautilusWindowSlot *slot);
2989
static gboolean
2990
isearch_window_button_press_event (GtkWidget *widget,
2991
					 GdkEventButton *event,
2992
					 NautilusWindowSlot *slot);
2993
static gboolean
2994
isearch_window_scroll_event (GtkWidget *widget,
2995
				   GdkEventScroll *event,
2996
				   NautilusWindowSlot *slot);
2997
static void
2998
isearch_activate_items_alternate (NautilusWindowSlot *slot);
2999
static gboolean
3000
isearch_window_key_press_event (GtkWidget *widget,
3001
				      GdkEventKey *event,
3002
				      NautilusWindowSlot *slot);
3003
static void
3004
isearch_disable_hide (GtkEntry *entry,
3005
				      GtkMenu  *menu,
3006
				      gpointer  data);
3007
static void
3008
isearch_preedit_changed (GtkEntry *entry,
3009
						gchar *preedit,
3010
						NautilusWindowSlot *slot);
3011
static void
3012
isearch_activate_event (GtkEntry    *entry,
3013
						NautilusWindowSlot *slot);
3014
static gboolean
3015
isearch_enable_hide_real (gpointer data);
3016
static void
3017
isearch_enable_hide (GtkWidget *widget,
3018
				     gpointer   data);
3019
static void
3020
send_focus_change (GtkWidget *widget,
3021
					GdkDevice *device,
3022
					gboolean   in);
3023
static void
3024
isearch_hide (NautilusWindowSlot *slot,
3025
			GdkDevice   *device);
3026
static void
3027
isearch_entry_changed (GtkWidget   *entry,
3028
			   NautilusWindowSlot *slot);
3029
static gboolean
3030
isearch_start (NautilusWindowSlot *slot, GdkDevice *device);
3031
static void
3032
isearch_position (NautilusWindowSlot *slot);
3033
static gboolean
3034
isearch_compare_filename (const gchar *f1, const gchar *f2, guint length);
3035
static int
3036
compare_files (gconstpointer a, gconstpointer b, gpointer callback_data);
3037
static GList *
3038
isearch_get_sorted_files (NautilusWindowSlot *slot);
3039
static NautilusFile *
3040
isearch_find (NautilusWindowSlot *slot, const gchar *text);
3041
static NautilusFile *
3042
isearch_find_next (NautilusWindowSlot *slot, const gchar *text);
3043
static NautilusFile *
3044
isearch_find_prev (NautilusWindowSlot *slot, const gchar *text);
3045
static gboolean
3046
isearch_move_next (NautilusWindowSlot *slot);
3047
static gboolean
3048
isearch_move_prev (NautilusWindowSlot *slot);
3049
static void
3050
isearch_set_selection (NautilusWindowSlot *slot, NautilusFile *file);
3051
static void
3052
isearch_enable_changed (gpointer callback_data);
3053
static void
3054
isearch_dispose (NautilusWindowSlot *slot);
3055
3056
static void
3057
isearch_ensure (NautilusWindowSlot *slot)
3058
{
3059
	GtkWidget *frame, *vbox, *toplevel;
3060
	GdkScreen *screen;
3061
3062
	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (slot));
3063
	screen = gtk_widget_get_screen (GTK_WIDGET (slot));
3064
3065
	if (slot->details->isearch_window != NULL)
3066
	{
3067
		if (gtk_window_has_group (GTK_WINDOW (toplevel)))
3068
			gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
3069
				GTK_WINDOW (slot->details->isearch_window));
3070
		else if (gtk_window_has_group (GTK_WINDOW (slot->details->isearch_window)))
3071
			gtk_window_group_remove_window (gtk_window_get_group (GTK_WINDOW (slot->details->isearch_window)),
3072
				GTK_WINDOW (slot->details->isearch_window));
3073
3074
		gtk_window_set_screen (GTK_WINDOW (slot->details->isearch_window), screen);
3075
		return;
3076
	}
3077
	slot->details->isearch_window = gtk_window_new (GTK_WINDOW_POPUP);
3078
	gtk_window_set_screen (GTK_WINDOW (slot->details->isearch_window), screen);
3079
3080
	if (gtk_window_has_group (GTK_WINDOW (toplevel)))
3081
		gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
3082
			GTK_WINDOW (slot->details->isearch_window));
3083
3084
	gtk_window_set_type_hint (GTK_WINDOW (slot->details->isearch_window),
3085
		GDK_WINDOW_TYPE_HINT_UTILITY);
3086
	gtk_window_set_modal (GTK_WINDOW (slot->details->isearch_window), TRUE);
3087
	g_signal_connect (slot->details->isearch_window, "delete-event",
3088
	G_CALLBACK (isearch_window_delete_event),
3089
		slot);
3090
	g_signal_connect (slot->details->isearch_window, "key-press-event",
3091
	G_CALLBACK (isearch_window_key_press_event),
3092
		slot);
3093
	g_signal_connect (slot->details->isearch_window, "button-press-event",
3094
	G_CALLBACK (isearch_window_button_press_event),
3095
		slot);
3096
	g_signal_connect (slot->details->isearch_window, "scroll-event",
3097
	G_CALLBACK (isearch_window_scroll_event),
3098
		slot);
3099
3100
	frame = gtk_frame_new (NULL);
3101
	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
3102
	gtk_widget_show (frame);
3103
	gtk_container_add (GTK_CONTAINER (slot->details->isearch_window), frame);
3104
3105
	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3106
	gtk_widget_show (vbox);
3107
	gtk_container_add (GTK_CONTAINER (frame), vbox);
3108
	gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
3109
3110
	/* add entry */
3111
	slot->details->isearch_entry = gtk_entry_new ();
3112
	gtk_widget_show (slot->details->isearch_entry);
3113
	g_signal_connect (slot->details->isearch_entry, "populate-popup",
3114
		G_CALLBACK (isearch_disable_hide),
3115
		slot);
3116
	g_signal_connect (slot->details->isearch_entry,
3117
		"activate", G_CALLBACK (isearch_activate_event),
3118
		slot);
3119
3120
	g_signal_connect (G_OBJECT (slot->details->isearch_entry),
3121
		"preedit-changed",
3122
		G_CALLBACK (isearch_preedit_changed),
3123
		slot);
3124
	gtk_container_add (GTK_CONTAINER (vbox),
3125
		slot->details->isearch_entry);
3126
3127
	gtk_widget_realize (slot->details->isearch_entry);
3128
}
3129
3130
static gboolean
3131
isearch_timeout (gpointer user_data)
3132
{
3133
	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (user_data);
3134
3135
	if (!g_source_is_destroyed (g_main_current_source ()))
3136
		isearch_hide (slot, NULL);
3137
3138
	return FALSE;
3139
}
3140
3141
static void
3142
isearch_timeout_destroy (gpointer user_data)
3143
{
3144
	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (user_data);
3145
3146
	slot->details->isearch_timeout_id = 0;
3147
}
3148
3149
static void
3150
isearch_timeout_restart (NautilusWindowSlot *slot)
3151
{
3152
	if (slot->details->isearch_timeout_id != 0) {
3153
		g_source_remove (slot->details->isearch_timeout_id);
3154
3155
		slot->details->isearch_timeout_id = gdk_threads_add_timeout_full (
3156
			G_PRIORITY_LOW, ISEARCH_TIMEOUT,
3157
			isearch_timeout,
3158
			slot,
3159
			isearch_timeout_destroy);
3160
	}
3161
}
3162
3163
static gboolean
3164
isearch_window_delete_event (GtkWidget *widget,
3165
				   GdkEventAny *event,
3166
				   NautilusWindowSlot *slot)
3167
{
3168
	g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
3169
3170
	isearch_hide (slot, NULL);
3171
	return TRUE;
3172
}
3173
3174
static gboolean
3175
isearch_window_button_press_event (GtkWidget *widget,
3176
					 GdkEventButton *event,
3177
					 NautilusWindowSlot *slot)
3178
{
3179
	GdkDevice *keyb_device;
3180
3181
	g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
3182
3183
	keyb_device = gdk_device_get_associated_device (event->device);
3184
	isearch_hide (slot, keyb_device);
3185
3186
	/* A bit of hackery here */
3187
	if (NAUTILUS_IS_CANVAS_VIEW (slot->details->content_view)) {
3188
		NautilusCanvasContainer *cc = nautilus_canvas_view_get_canvas_container (NAUTILUS_CANVAS_VIEW (slot->details->content_view));
3189
		gboolean retval;
3190
3191
		if (event->window == gtk_layout_get_bin_window (GTK_LAYOUT (cc)))
3192
			g_signal_emit_by_name (GTK_WIDGET (cc), "button-press-event", event, &retval);
3193
3194
		return retval;
3195
	} else if (NAUTILUS_IS_LIST_VIEW (slot->details->content_view)) {
3196
		NautilusListView *lv = NAUTILUS_LIST_VIEW (slot->details->content_view);
3197
		GtkTreeView *tv = nautilus_list_view_get_tree_view (NAUTILUS_LIST_VIEW (slot->details->content_view));
3198
		gboolean retval;
3199
3200
		if (event->window == gtk_tree_view_get_bin_window (tv))
3201
			g_signal_emit_by_name (GTK_WIDGET (tv), "button-press-event", event, &retval);
3202
3203
		return retval;
3204
	}
3205
	return TRUE;
3206
}
3207
3208
static gboolean
3209
isearch_window_scroll_event (GtkWidget *widget,
3210
				   GdkEventScroll *event,
3211
				   NautilusWindowSlot *slot)
3212
{
3213
	gboolean retval = FALSE;
3214
3215
	if (event->direction == GDK_SCROLL_UP) {
3216
		isearch_move_prev (slot);
3217
		retval = TRUE;
3218
	}
3219
	else if (event->direction == GDK_SCROLL_DOWN) {
3220
		isearch_move_next (slot);
3221
		retval = TRUE;
3222
	}
3223
	if (retval)
3224
		isearch_timeout_restart (slot);
3225
3226
	return retval;
3227
}
3228
3229
static void
3230
isearch_activate_items_alternate (NautilusWindowSlot *slot)
3231
{
3232
	GList *file_list;
3233
3234
	file_list = nautilus_view_get_selection (slot->details->content_view);
3235
	nautilus_view_activate_files (NAUTILUS_VIEW (slot->details->content_view),
3236
		file_list,
3237
		NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB,
3238
		TRUE);
3239
	nautilus_file_list_free (file_list);
3240
}
3241
3242
static gboolean
3243
isearch_window_key_press_event (GtkWidget *widget,
3244
				      GdkEventKey *event,
3245
				      NautilusWindowSlot *slot)
3246
{
3247
	GdkModifierType default_accel;
3248
	gboolean        retval = FALSE;
3249
3250
	g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
3251
	g_return_val_if_fail (NAUTILUS_IS_WINDOW_SLOT (slot), FALSE);
3252
3253
	/* close window and cancel the search */
3254
	if (event->keyval == GDK_KEY_Escape ||
3255
		event->keyval == GDK_KEY_Tab ||
3256
		event->keyval == GDK_KEY_KP_Tab ||
3257
		event->keyval == GDK_KEY_ISO_Left_Tab) {
3258
3259
		isearch_hide (slot,	gdk_event_get_device ((GdkEvent *) event));
3260
		return TRUE;
3261
	}
3262
3263
	default_accel = gtk_widget_get_modifier_mask (widget,
3264
		GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR);
3265
3266
	/* select previous matching iter */
3267
	if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up) {
3268
		if (!isearch_move_prev (slot))
3269
			gtk_widget_error_bell (widget);
3270
3271
		retval = TRUE;
3272
	}
3273
	if (((event->state & (default_accel | GDK_SHIFT_MASK)) == (default_accel | GDK_SHIFT_MASK))
3274
		&& (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G)) {
3275
		if (!isearch_move_prev (slot))
3276
			gtk_widget_error_bell (widget);
3277
3278
		retval = TRUE;
3279
	}
3280
	/* select next matching iter */
3281
	if (event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down) {
3282
		if (!isearch_move_next (slot))
3283
			gtk_widget_error_bell (widget);
3284
3285
		retval = TRUE;
3286
	}
3287
	if (((event->state & (default_accel | GDK_SHIFT_MASK)) == default_accel)
3288
		&& (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G)) {
3289
		if (!isearch_move_next (slot))
3290
			gtk_widget_error_bell (widget);
3291
3292
		retval = TRUE;
3293
	}
3294
3295
	/* Alternate activation (Shift+Enter).
3296
	 * Regular activation (Enter) is handled by the entry activate signal.
3297
	 */
3298
	if ((event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter) &&
3299
			(event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) {
3300
		isearch_activate_items_alternate (slot);
3301
		isearch_hide (slot, gdk_event_get_device ((GdkEvent*)event));
3302
		retval = TRUE;
3303
	}
3304
	isearch_timeout_restart (slot);
3305
	return retval;
3306
}
3307
3308
static void
3309
isearch_disable_hide (GtkEntry *entry,
3310
				      GtkMenu  *menu,
3311
				      gpointer  data)
3312
{
3313
	NautilusWindowSlot *slot = (NautilusWindowSlot *)data;
3314
3315
	slot->details->isearch_disable_hide = 1;
3316
	g_signal_connect (menu, "hide",
3317
		G_CALLBACK (isearch_enable_hide), data);
3318
}
3319
3320
static void
3321
isearch_preedit_changed (GtkEntry *entry,
3322
						gchar *preedit,
3323
						NautilusWindowSlot *slot)
3324
{
3325
	slot->details->isearch_imcontext_changed = 1;
3326
	isearch_timeout_restart (slot);
3327
}
3328
3329
static void
3330
isearch_activate_event (GtkEntry    *entry,
3331
						NautilusWindowSlot *slot)
3332
{
3333
  GtkTreePath *path;
3334
3335
  isearch_hide (slot, gtk_get_current_event_device ());
3336
  nautilus_view_activate_selection (slot->details->content_view);
3337
}
3338
3339
static gboolean
3340
isearch_enable_hide_real (gpointer data)
3341
{
3342
	NautilusWindowSlot *slot = (NautilusWindowSlot *)data;
3343
	slot->details->isearch_disable_hide = 0;
3344
	return FALSE;
3345
}
3346
3347
static void
3348
isearch_enable_hide (GtkWidget *widget,
3349
				     gpointer   data)
3350
{
3351
	gdk_threads_add_timeout_full (G_PRIORITY_HIGH, 200, isearch_enable_hide_real, g_object_ref (data), g_object_unref);
3352
}
3353
3354
static void
3355
send_focus_change (GtkWidget *widget,
3356
					GdkDevice *device,
3357
					gboolean   in)
3358
{
3359
	GdkDeviceManager *device_manager;
3360
	GList *devices, *d;
3361
3362
	device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
3363
	devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
3364
	devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
3365
	devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
3366
3367
	for (d = devices; d; d = d->next)
3368
	{
3369
		GdkDevice *dev = d->data;
3370
		GdkEvent *fevent;
3371
		GdkWindow *window;
3372
3373
		if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
3374
			continue;
3375
3376
		window = gtk_widget_get_window (widget);
3377
3378
		/* Skip non-master keyboards that haven't
3379
		* selected for events from this window
3380
		*/
3381
		if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
3382
				!gdk_window_get_device_events (window, dev))
3383
			continue;
3384
3385
		fevent = gdk_event_new (GDK_FOCUS_CHANGE);
3386
3387
		fevent->focus_change.type = GDK_FOCUS_CHANGE;
3388
		fevent->focus_change.window = g_object_ref (window);
3389
		fevent->focus_change.in = in;
3390
		gdk_event_set_device (fevent, device);
3391
3392
		gtk_widget_send_focus_change (widget, fevent);
3393
3394
		gdk_event_free (fevent);
3395
	}
3396
3397
	g_list_free (devices);
3398
}
3399
3400
static void
3401
isearch_hide (NautilusWindowSlot *slot,
3402
			GdkDevice   *device)
3403
{
3404
	if (slot->details->isearch_disable_hide)
3405
		return;
3406
3407
	if (!slot->details->isearch_enable)
3408
		return;
3409
3410
	if (slot->details->isearch_entry_changed_id)
3411
	{
3412
		g_signal_handler_disconnect (slot->details->isearch_entry,
3413
				   slot->details->isearch_entry_changed_id);
3414
		slot->details->isearch_entry_changed_id = 0;
3415
	}
3416
	if (slot->details->isearch_timeout_id)
3417
	{
3418
		g_source_remove (slot->details->isearch_timeout_id);
3419
		slot->details->isearch_timeout_id = 0;
3420
	}
3421
	if (slot->details->isearch_window != NULL
3422
		&& gtk_widget_get_visible (slot->details->isearch_window))
3423
	{
3424
		/* send focus-in event */
3425
		send_focus_change (GTK_WIDGET (slot->details->isearch_entry), device, FALSE);
3426
		gtk_widget_hide (slot->details->isearch_window);
3427
		gtk_entry_set_text (GTK_ENTRY (slot->details->isearch_entry), "");
3428
		send_focus_change (GTK_WIDGET (slot), device, TRUE);
3429
	}
3430
}
3431
3432
static void
3433
isearch_entry_changed (GtkWidget   *entry,
3434
			   NautilusWindowSlot *slot)
3435
{
3436
	gint ret;
3437
	const gchar *text;
3438
3439
	g_return_if_fail (GTK_IS_ENTRY (entry));
3440
	g_return_if_fail (NAUTILUS_IS_WINDOW_SLOT (slot));
3441
3442
	text = gtk_entry_get_text (GTK_ENTRY (entry));
3443
3444
	/* unselect all */
3445
	nautilus_view_set_selection (slot->details->content_view, NULL);
3446
3447
	isearch_timeout_restart (slot);
3448
3449
	if (*text == '\0')
3450
		return;
3451
3452
	isearch_set_selection (slot, isearch_find (slot, text));
3453
}
3454
3455
static gboolean
3456
isearch_start (NautilusWindowSlot *slot, GdkDevice *device)
3457
{
3458
	GTypeClass *klass;
3459
	GList *list;
3460
	gboolean found_focus = FALSE;
3461
3462
	if (!slot->details->isearch_enable)
3463
		return FALSE;
3464
3465
	if (slot->details->isearch_window != NULL &&
3466
			gtk_widget_get_visible (slot->details->isearch_window))
3467
		return TRUE;
3468
3469
	if (nautilus_view_get_loading (slot->details->content_view))
3470
		return FALSE;
3471
3472
	isearch_ensure (slot);
3473
3474
	/* done, show it */
3475
	isearch_position (slot);
3476
	gtk_widget_show (slot->details->isearch_window);
3477
	if (slot->details->isearch_entry_changed_id == 0)
3478
	{
3479
		slot->details->isearch_entry_changed_id =
3480
			g_signal_connect (slot->details->isearch_entry, "changed",
3481
			G_CALLBACK (isearch_entry_changed),
3482
			slot);
3483
	}
3484
	slot->details->isearch_timeout_id = gdk_threads_add_timeout_full (
3485
		G_PRIORITY_LOW,
3486
		ISEARCH_TIMEOUT,
3487
		isearch_timeout,
3488
		slot,
3489
		isearch_timeout_destroy);
3490
3491
	/* Grab focus without selecting all the text. */
3492
	klass = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (slot->details->isearch_entry));
3493
	(*GTK_WIDGET_CLASS (klass)->grab_focus) (slot->details->isearch_entry);
3494
3495
	/* send focus-in event */
3496
	send_focus_change (slot->details->isearch_entry, device, TRUE);
3497
3498
	/* search first matching iter */
3499
	isearch_entry_changed (slot->details->isearch_entry, slot);
3500
	return TRUE;
3501
}
3502
3503
static void
3504
isearch_position (NautilusWindowSlot *slot)
3505
{
3506
	gint x, y;
3507
	gint window_x, window_y;
3508
	gint window_width, window_height;
3509
	GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (slot));
3510
	GdkScreen *screen = gdk_window_get_screen (window);
3511
	GtkRequisition requisition;
3512
	gint monitor_num;
3513
	GdkRectangle monitor;
3514
3515
	monitor_num = gdk_screen_get_monitor_at_window (screen, window);
3516
	gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
3517
3518
	gtk_widget_realize (slot->details->isearch_window);
3519
3520
	gdk_window_get_origin (window, &window_x, &window_y);
3521
	window_width = gdk_window_get_width (window);
3522
	window_height = gdk_window_get_height (window);
3523
	gtk_widget_get_preferred_size (slot->details->isearch_window, &requisition, NULL);
3524
3525
	if (window_x + window_width > gdk_screen_get_width (screen))
3526
		x = gdk_screen_get_width (screen) - requisition.width;
3527
	else if (window_x + window_width - requisition.width < 0)
3528
		x = 0;
3529
	else
3530
		x = window_x + window_width - requisition.width;
3531
3532
	if (window_y + window_height + requisition.height > gdk_screen_get_height (screen))
3533
		y = gdk_screen_get_height (screen) - requisition.height;
3534
	else if (window_y + window_height < 0) /* isn't really possible ... */
3535
		y = 0;
3536
	else
3537
		y = window_y + window_height;
3538
3539
	gtk_window_move (GTK_WINDOW (slot->details->isearch_window), x, y);
3540
}
3541
3542
static gboolean
3543
isearch_compare_filename (const gchar *f1, const gchar *f2, guint length)
3544
{
3545
	gchar *normalized_f1;
3546
	gchar *normalized_f2;
3547
	gchar *case_normalized_f1;
3548
	gchar *case_normalized_f2;
3549
	gboolean retval = FALSE;
3550
3551
	normalized_f1 = g_utf8_normalize (f1, -1, G_NORMALIZE_ALL);
3552
	normalized_f2 = g_utf8_normalize (f2, -1, G_NORMALIZE_ALL);
3553
3554
	if (G_LIKELY (normalized_f1 != NULL && normalized_f2 != NULL)) {
3555
		case_normalized_f1 = g_utf8_casefold (normalized_f1, -1);
3556
		case_normalized_f2 = g_utf8_casefold (normalized_f2, -1);
3557
3558
		retval = (strncmp (case_normalized_f1, case_normalized_f2, length) == 0);
3559
	}
3560
	g_free (normalized_f1);
3561
	g_free (normalized_f2);
3562
	g_free (case_normalized_f1);
3563
	g_free (case_normalized_f2);
3564
	return retval;
3565
}
3566
3567
static int
3568
compare_files (gconstpointer a, gconstpointer b, gpointer callback_data)
3569
{
3570
	NautilusView *view = NAUTILUS_VIEW (callback_data);
3571
	NautilusFile *f1 = NAUTILUS_FILE (a);
3572
	NautilusFile *f2 = NAUTILUS_FILE (b);
3573
3574
	return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compare_files (view, f1, f2);
3575
}
3576
3577
static GList *
3578
isearch_get_sorted_files (NautilusWindowSlot *slot)
3579
{
3580
	NautilusView *view = slot->details->content_view;
3581
	NautilusDirectory *dir = nautilus_view_get_model (view);
3582
	GList *list = nautilus_directory_get_file_list (dir);
3583
	GList *sorted_list;
3584
3585
	sorted_list = g_list_sort_with_data (list, compare_files, view);
3586
	return sorted_list;
3587
}
3588
3589
static NautilusFile *
3590
isearch_find (NautilusWindowSlot *slot, const gchar *text)
3591
{
3592
	GList *files = isearch_get_sorted_files (slot);
3593
	GList *l;
3594
	NautilusFile *found = NULL;
3595
3596
	for (l = files; l; l = g_list_next (l)) {
3597
		NautilusFile *file = NAUTILUS_FILE (l->data);
3598
		gchar *filename = nautilus_file_get_display_name (file);
3599
3600
		if (isearch_compare_filename (filename, text, strlen (text)))
3601
			found = file;
3602
3603
		g_free (filename);
3604
		if (found)
3605
			break;
3606
	}
3607
	return found;
3608
}
3609
3610
static NautilusFile *
3611
isearch_find_next (NautilusWindowSlot *slot, const gchar *text)
3612
{
3613
	GList *files = isearch_get_sorted_files (slot);
3614
	NautilusFile *found = NULL;
3615
	GList *current;
3616
	GList *l;
3617
3618
	current = g_list_find (files, slot->details->isearch_selected_file);
3619
	for (l = g_list_next (current); l; l = g_list_next (l)) {
3620
		NautilusFile *file = NAUTILUS_FILE (l->data);
3621
		gchar *display_name = nautilus_file_get_display_name (file);
3622
3623
		if (isearch_compare_filename (display_name, text, strlen (text)))
3624
			found = file;
3625
3626
		g_free (display_name);
3627
		if (found)
3628
			break;
3629
	}
3630
	return found;
3631
}
3632
3633
static NautilusFile *
3634
isearch_find_prev (NautilusWindowSlot *slot, const gchar *text)
3635
{
3636
	GList *files = isearch_get_sorted_files (slot);
3637
	NautilusFile *found = NULL;
3638
	GList *current;
3639
	GList *l;
3640
3641
	current = g_list_find (files, slot->details->isearch_selected_file);
3642
	for (l = g_list_previous (current); l; l = g_list_previous (l)) {
3643
		NautilusFile *file = NAUTILUS_FILE (l->data);
3644
		gchar *display_name = nautilus_file_get_display_name (file);
3645
3646
		if (isearch_compare_filename (display_name, text, strlen (text)))
3647
			found = file;
3648
3649
		g_free (display_name);
3650
		if (found)
3651
			break;
3652
	}
3653
	return found;
3654
}
3655
3656
static gboolean
3657
isearch_move_next (NautilusWindowSlot *slot)
3658
{
3659
	const gchar *text;
3660
	NautilusFile *iter;
3661
3662
	text = gtk_entry_get_text (GTK_ENTRY (slot->details->isearch_entry));
3663
	iter = isearch_find_next (slot, text);
3664
	if (iter)
3665
		isearch_set_selection (slot, iter);
3666
3667
	return iter != NULL;
3668
}
3669
3670
static gboolean
3671
isearch_move_prev (NautilusWindowSlot *slot)
3672
{
3673
	const gchar *text;
3674
	NautilusFile *iter;
3675
3676
	text = gtk_entry_get_text (GTK_ENTRY (slot->details->isearch_entry));
3677
	iter = isearch_find_prev (slot, text);
3678
	if (iter)
3679
		isearch_set_selection (slot, iter);
3680
3681
	return iter != NULL;
3682
}
3683
3684
static void
3685
isearch_set_selection (NautilusWindowSlot *slot, NautilusFile *file)
3686
{
3687
	GList *list = g_list_append (list, file);
3688
3689
	slot->details->isearch_selected_file = file;
3690
	nautilus_view_set_selection (slot->details->content_view, list);
3691
	g_list_free (list);
3692
}
3693
3694
static void
3695
isearch_enable_changed (gpointer callback_data)
3696
{
3697
	NautilusWindowSlot *slot;
3698
	gboolean enable;
3699
3700
	slot = NAUTILUS_WINDOW_SLOT (callback_data);
3701
3702
	enable = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH);
3703
3704
	if (enable != slot->details->isearch_enable) {
3705
		if (!enable)
3706
			isearch_dispose (slot);
3707
3708
		slot->details->isearch_enable = enable;
3709
	}
3710
}
3711
3712
static void
3713
isearch_dispose (NautilusWindowSlot *slot)
3714
{
3715
	if (!slot->details->isearch_enable)
3716
		return;
3717
3718
	if (slot->details->isearch_entry_changed_id != 0) {
3719
		g_signal_handler_disconnect (G_OBJECT (slot->details->isearch_entry), slot->details->isearch_entry_changed_id);
3720
		slot->details->isearch_entry_changed_id = 0;
3721
	}
3722
	if (slot->details->isearch_timeout_id != 0) {
3723
		g_source_remove (slot->details->isearch_timeout_id);
3724
		slot->details->isearch_timeout_id = 0;
3725
	}
3726
	if (slot->details->isearch_window != NULL) {
3727
		gtk_widget_destroy (slot->details->isearch_window);
3728
		slot->details->isearch_window = NULL;
3729
		slot->details->isearch_entry = NULL;
3730
	}
3731
}

Return to bug 533640