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 |
} |