~ubuntu-branches/ubuntu/quantal/nautilus/quantal

« back to all changes in this revision

Viewing changes to libnautilus-private/nautilus-icon-container.c

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2012-07-24 13:00:13 UTC
  • mfrom: (299.1.1 quantal)
  • Revision ID: package-import@ubuntu.com-20120724130013-5qnys60ngsy3hom0
Tags: 1:3.5.4-0ubuntu2
* debian/patches/git_handle_space.patch:
  - "query-editor: make sure not to handle space if we're invisible"
* debian/patches/git_dont_grab_entry_focus.patch:
  - "Don't grab focus away from the search entry box"
* debian/patches/git_entry_grab_keys.patch:
  - "This fixes the search entry grabbing pasted URLs." (lp: #1026659)
* debian/patches/git_focus_on_down_key.patch:
  - "Change focus to the view on down arrow"
* debian/patches/git_desktop_dont_search_on_type.patch:
  - "Don't handle search for desktop windows" (lp: #1028028)

Show diffs side-by-side

added added

removed removed

Lines of Context:
98
98
 
99
99
#define STANDARD_ICON_GRID_WIDTH 155
100
100
 
101
 
#define TEXT_BESIDE_ICON_GRID_WIDTH 205
102
 
 
103
101
/* Desktop layout mode defines */
104
102
#define DESKTOP_PAD_HORIZONTAL  10
105
103
#define DESKTOP_PAD_VERTICAL    10
114
112
 */
115
113
#define ICON_SIZE_FOR_LARGE_EMBEDDED_TEXT 55
116
114
 
117
 
/* From nautilus-icon-canvas-item.c */
118
 
#define MAX_TEXT_WIDTH_BESIDE 90
119
 
 
120
115
#define SNAP_HORIZONTAL(func,x) ((func ((double)((x) - DESKTOP_PAD_HORIZONTAL) / SNAP_SIZE_X) * SNAP_SIZE_X) + DESKTOP_PAD_HORIZONTAL)
121
116
#define SNAP_VERTICAL(func, y) ((func ((double)((y) - DESKTOP_PAD_VERTICAL) / SNAP_SIZE_Y) * SNAP_SIZE_Y) + DESKTOP_PAD_VERTICAL)
122
117
 
203
198
                                   NautilusIcon *icon_b);
204
199
 
205
200
static void store_layout_timestamps_now (NautilusIconContainer *container);
206
 
static void remove_search_entry_timeout (NautilusIconContainer *container);
207
201
 
208
202
static const char *nautilus_icon_container_accessible_action_names[] = {
209
203
        "activate",
1151
1145
static double
1152
1146
get_grid_width (NautilusIconContainer *container)
1153
1147
{
1154
 
        if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
1155
 
                return TEXT_BESIDE_ICON_GRID_WIDTH;
1156
 
        } else {
1157
 
                return STANDARD_ICON_GRID_WIDTH;
1158
 
        }
 
1148
        return STANDARD_ICON_GRID_WIDTH;
1159
1149
}
1160
1150
#endif
1161
1151
typedef struct {
1190
1180
                icon = p->data;
1191
1181
 
1192
1182
                position = &g_array_index (positions, IconPositions, i++);
1193
 
                
1194
 
                if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
1195
 
                        y_offset = (max_height - position->height) / 2;
1196
 
                } else {
1197
 
                        y_offset = position->y_offset;
1198
 
                }
 
1183
                y_offset = position->y_offset;
1199
1184
 
1200
1185
                icon_set_position
1201
1186
                        (icon,
1258
1243
        IconPositions *position;
1259
1244
        EelDRect bounds;
1260
1245
        EelDRect icon_bounds;
1261
 
        EelDRect text_bounds;
1262
1246
        double max_height_above, max_height_below;
1263
1247
        double height_above, height_below;
1264
1248
        double line_width;
1265
1249
        double grid_width;
1266
 
        double max_text_width, max_icon_width;
1267
1250
        int icon_width;
1268
1251
        int i;
1269
1252
        GtkAllocation allocation;
1279
1262
        
1280
1263
        /* Lay out icons a line at a time. */
1281
1264
        canvas_width = CANVAS_WIDTH(container, allocation);
1282
 
        max_icon_width = max_text_width = 0.0;
1283
 
 
1284
 
        if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
1285
 
                /* Would it be worth caching these bounds for the next loop? */
1286
 
                for (p = icons; p != NULL; p = p->next) {
1287
 
                        icon = p->data;
1288
 
 
1289
 
                        icon_bounds = nautilus_icon_canvas_item_get_icon_rectangle (icon->item);
1290
 
                        max_icon_width = MAX (max_icon_width, ceil (icon_bounds.x1 - icon_bounds.x0));
1291
 
 
1292
 
                        text_bounds = nautilus_icon_canvas_item_get_text_rectangle (icon->item, TRUE);
1293
 
                        max_text_width = MAX (max_text_width, ceil (text_bounds.x1 - text_bounds.x0));
1294
 
                }
1295
 
 
1296
 
                grid_width = max_icon_width + max_text_width + ICON_PAD_LEFT + ICON_PAD_RIGHT;
1297
 
        } else {
1298
 
                grid_width = STANDARD_ICON_GRID_WIDTH;
1299
 
        }
1300
 
        
1301
 
        line_width = container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE ? ICON_PAD_LEFT : 0;
 
1265
 
 
1266
        grid_width = STANDARD_ICON_GRID_WIDTH;
 
1267
 
 
1268
        line_width = 0;
1302
1269
        line_start = icons;
1303
1270
        y = start_y + CONTAINER_PAD_TOP;
1304
1271
        i = 0;
1322
1289
 
1323
1290
                /* If this icon doesn't fit, it's time to lay out the line that's queued up. */
1324
1291
                if (line_start != p && line_width + icon_width >= canvas_width ) {
1325
 
                        if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
1326
 
                                y += ICON_PAD_TOP;
1327
 
                        } else {
1328
 
                                /* Advance to the baseline. */
1329
 
                                y += ICON_PAD_TOP + max_height_above;
1330
 
                        }
 
1292
                        /* Advance to the baseline. */
 
1293
                        y += ICON_PAD_TOP + max_height_above;
1331
1294
 
1332
1295
                        lay_down_one_line (container, line_start, p, y, max_height_above, positions, FALSE);
1333
 
                        
1334
 
                        if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
1335
 
                                y += max_height_above + max_height_below + ICON_PAD_BOTTOM;
1336
 
                        } else {
1337
 
                                /* Advance to next line. */
1338
 
                                y += max_height_below + ICON_PAD_BOTTOM;
1339
 
                        }
1340
 
                        
1341
 
                        line_width = container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE ? ICON_PAD_LEFT : 0;
 
1296
 
 
1297
                        /* Advance to next line. */
 
1298
                        y += max_height_below + ICON_PAD_BOTTOM;
 
1299
 
 
1300
                        line_width = 0;
1342
1301
                        line_start = p;
1343
1302
                        i = 0;
1344
1303
                        
1358
1317
                position->width = icon_width;
1359
1318
                position->height = icon_bounds.y1 - icon_bounds.y0;
1360
1319
 
1361
 
                if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
1362
 
                        position->x_offset = max_icon_width + ICON_PAD_LEFT + ICON_PAD_RIGHT - (icon_bounds.x1 - icon_bounds.x0);
1363
 
                        position->y_offset = 0;
1364
 
                } else {
1365
 
                        position->x_offset = (icon_width - (icon_bounds.x1 - icon_bounds.x0)) / 2;
1366
 
                        position->y_offset = icon_bounds.y0 - icon_bounds.y1;
1367
 
                }
 
1320
                position->x_offset = (icon_width - (icon_bounds.x1 - icon_bounds.x0)) / 2;
 
1321
                position->y_offset = icon_bounds.y0 - icon_bounds.y1;
1368
1322
 
1369
1323
                /* Add this icon. */
1370
1324
                line_width += icon_width;
1372
1326
 
1373
1327
        /* Lay down that last line of icons. */
1374
1328
        if (line_start != NULL) {
1375
 
                        if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
1376
 
                                y += ICON_PAD_TOP;
1377
 
                        } else {
1378
 
                                /* Advance to the baseline. */
1379
 
                                y += ICON_PAD_TOP + max_height_above;
1380
 
                        }
1381
 
                
 
1329
                /* Advance to the baseline. */
 
1330
                y += ICON_PAD_TOP + max_height_above;
 
1331
 
1382
1332
                lay_down_one_line (container, line_start, NULL, y, max_height_above, positions, TRUE);
1383
1333
        }
1384
1334
 
1423
1373
        }
1424
1374
}
1425
1375
 
1426
 
/* column-wise layout. At the moment, this only works with label-beside-icon (used by "Compact View"). */
1427
1376
static void
1428
1377
lay_down_icons_vertical (NautilusIconContainer *container,
1429
1378
                         GList *icons,
1454
1403
        int i;
1455
1404
 
1456
1405
        g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
1457
 
        g_assert (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE);
1458
1406
 
1459
1407
        if (icons == NULL) {
1460
1408
                return;
2785
2733
get_cmp_point_x (NautilusIconContainer *container,
2786
2734
                 EelDRect icon_rect)
2787
2735
{
2788
 
        if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
2789
 
                if (gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_RTL) {
2790
 
                        return icon_rect.x0;
2791
 
                } else {
2792
 
                        return icon_rect.x1;
2793
 
                }
2794
 
        } else {
2795
 
                return (icon_rect.x0 + icon_rect.x1) / 2;
2796
 
        }
 
2736
        return (icon_rect.x0 + icon_rect.x1) / 2;
2797
2737
}
2798
2738
 
2799
2739
static int
2800
2740
get_cmp_point_y (NautilusIconContainer *container,
2801
2741
                 EelDRect icon_rect)
2802
2742
{
2803
 
        if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
2804
 
                return (icon_rect.y0 + icon_rect.y1)/2;
2805
 
        } else {
2806
 
                return icon_rect.y1;
2807
 
        }
 
2743
        return icon_rect.y1;
2808
2744
}
2809
2745
 
2810
2746
 
3967
3903
                container->details->size_allocation_count_id = 0;
3968
3904
        }
3969
3905
 
3970
 
        /* destroy interactive search dialog */
3971
 
        if (container->details->search_window) {
3972
 
                gtk_widget_destroy (container->details->search_window);
3973
 
                container->details->search_window = NULL;
3974
 
                container->details->search_entry = NULL;
3975
 
        }
3976
 
 
3977
 
        remove_search_entry_timeout (container);
3978
 
 
3979
3906
        GTK_WIDGET_CLASS (nautilus_icon_container_parent_class)->destroy (object);
3980
3907
}
3981
3908
 
4178
4105
        container = NAUTILUS_ICON_CONTAINER (widget);
4179
4106
 
4180
4107
        nautilus_icon_dnd_fini (container);
4181
 
        remove_search_entry_timeout (container);
4182
4108
 
4183
4109
        GTK_WIDGET_CLASS (nautilus_icon_container_parent_class)->unrealize (widget);
4184
4110
}
4744
4670
}
4745
4671
 
4746
4672
static void
4747
 
nautilus_icon_container_search_position_func (NautilusIconContainer *container,
4748
 
                                              GtkWidget *search_dialog)
4749
 
{
4750
 
        gint x, y;
4751
 
        gint cont_x, cont_y;
4752
 
        gint cont_width, cont_height;
4753
 
        GdkWindow *cont_window;
4754
 
        GdkScreen *screen;
4755
 
        GtkRequisition requisition;
4756
 
        gint monitor_num;
4757
 
        GdkRectangle monitor;
4758
 
 
4759
 
 
4760
 
        cont_window = gtk_widget_get_window (GTK_WIDGET (container));
4761
 
        screen = gdk_window_get_screen (cont_window);
4762
 
 
4763
 
        monitor_num = gdk_screen_get_monitor_at_window (screen, cont_window);
4764
 
        gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4765
 
 
4766
 
        gtk_widget_realize (search_dialog);
4767
 
 
4768
 
        gdk_window_get_origin (cont_window, &cont_x, &cont_y);
4769
 
        cont_width = gdk_window_get_width (cont_window);
4770
 
        cont_height = gdk_window_get_height (cont_window);
4771
 
 
4772
 
        gtk_widget_get_preferred_size (search_dialog, &requisition, NULL);
4773
 
 
4774
 
        if (cont_x + cont_width > gdk_screen_get_width (screen)) {
4775
 
                x = gdk_screen_get_width (screen) - requisition.width;
4776
 
        } else if (cont_x + cont_width - requisition.width < 0) {
4777
 
                x = 0;
4778
 
        } else {
4779
 
                x = cont_x + cont_width - requisition.width;
4780
 
        }
4781
 
 
4782
 
        if (cont_y + cont_height + requisition.height > gdk_screen_get_height (screen)) {
4783
 
                y = gdk_screen_get_height (screen) - requisition.height;
4784
 
        } else if (cont_y + cont_height < 0) { /* isn't really possible ... */
4785
 
                y = 0;
4786
 
        } else {
4787
 
                y = cont_y + cont_height;
4788
 
        }
4789
 
 
4790
 
        gdk_window_move (gtk_widget_get_window (search_dialog), x, y);
4791
 
}
4792
 
 
4793
 
/* Cut and paste from gtkwindow.c */
4794
 
static void
4795
 
send_focus_change (GtkWidget *widget, gboolean in)
4796
 
{
4797
 
        GdkEvent *fevent;
4798
 
        
4799
 
        fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4800
 
 
4801
 
        g_object_ref (widget);
4802
 
        ((GdkEventFocus *) fevent)->in = in;
4803
 
 
4804
 
        gtk_widget_send_focus_change (widget, fevent);
4805
 
 
4806
 
        fevent->focus_change.type = GDK_FOCUS_CHANGE;
4807
 
        fevent->focus_change.window = g_object_ref (gtk_widget_get_window (widget));
4808
 
        fevent->focus_change.in = in;
4809
 
 
4810
 
        gtk_widget_event (widget, fevent);
4811
 
 
4812
 
        g_object_notify (G_OBJECT (widget), "has-focus");
4813
 
 
4814
 
        g_object_unref (widget);
4815
 
        gdk_event_free (fevent);
4816
 
}
4817
 
 
4818
 
static void
4819
 
nautilus_icon_container_search_dialog_hide (GtkWidget *search_dialog,
4820
 
                                            NautilusIconContainer *container)
4821
 
{
4822
 
        if (container->details->search_entry_changed_id) {
4823
 
                g_signal_handler_disconnect (container->details->search_entry,
4824
 
                                             container->details->search_entry_changed_id);
4825
 
                container->details->search_entry_changed_id = 0;
4826
 
        }
4827
 
 
4828
 
        remove_search_entry_timeout (container);
4829
 
 
4830
 
        /* send focus-in event */
4831
 
        send_focus_change (GTK_WIDGET (container->details->search_entry), FALSE);
4832
 
        gtk_widget_hide (search_dialog);
4833
 
        gtk_entry_set_text (GTK_ENTRY (container->details->search_entry), "");
4834
 
}
4835
 
 
4836
 
static gboolean
4837
 
nautilus_icon_container_search_entry_flush_timeout (gpointer data)
4838
 
{
4839
 
        NautilusIconContainer *container = data;
4840
 
 
4841
 
        container->details->typeselect_flush_timeout = 0;
4842
 
        nautilus_icon_container_search_dialog_hide (container->details->search_window, container);
4843
 
 
4844
 
        return FALSE;
4845
 
}
4846
 
 
4847
 
static void
4848
 
add_search_entry_timeout (NautilusIconContainer *container)
4849
 
{
4850
 
        container->details->typeselect_flush_timeout =
4851
 
                g_timeout_add_seconds (NAUTILUS_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT,
4852
 
                                       nautilus_icon_container_search_entry_flush_timeout,
4853
 
                                       container);
4854
 
}
4855
 
 
4856
 
static void
4857
 
remove_search_entry_timeout (NautilusIconContainer *container)
4858
 
{
4859
 
        if (container->details->typeselect_flush_timeout) {
4860
 
                g_source_remove (container->details->typeselect_flush_timeout);
4861
 
                container->details->typeselect_flush_timeout = 0;
4862
 
        }
4863
 
}
4864
 
 
4865
 
static void
4866
 
reset_search_entry_timeout (NautilusIconContainer *container)
4867
 
{
4868
 
        remove_search_entry_timeout (container);
4869
 
        add_search_entry_timeout (container);
4870
 
}
4871
 
 
4872
 
/* Because we're visible but offscreen, we just set a flag in the preedit
4873
 
 * callback.
4874
 
 */
4875
 
static void
4876
 
nautilus_icon_container_search_preedit_changed (GtkEntry *entry,
4877
 
                                                gchar *preedit,
4878
 
                                                NautilusIconContainer *container)
4879
 
{
4880
 
        container->details->imcontext_changed = 1;
4881
 
        reset_search_entry_timeout (container);
4882
 
}
4883
 
 
4884
 
static void
4885
 
nautilus_icon_container_search_activate (GtkEntry *entry,
4886
 
                                         NautilusIconContainer *container)
4887
 
{
4888
 
        nautilus_icon_container_search_dialog_hide (container->details->search_window,
4889
 
                                                    container);
4890
 
 
4891
 
        activate_selected_items (container);
4892
 
}
4893
 
 
4894
 
static gboolean
4895
 
nautilus_icon_container_search_delete_event (GtkWidget *widget,
4896
 
                                             GdkEventAny *event,
4897
 
                                             NautilusIconContainer *container)
4898
 
{
4899
 
        nautilus_icon_container_search_dialog_hide (widget, container);
4900
 
 
4901
 
        return TRUE;
4902
 
}
4903
 
 
4904
 
static gboolean
4905
 
nautilus_icon_container_search_button_press_event (GtkWidget *widget,
4906
 
                                                   GdkEventButton *event,
4907
 
                                                   NautilusIconContainer *container)
4908
 
{
4909
 
        nautilus_icon_container_search_dialog_hide (widget, container);
4910
 
 
4911
 
        if (event->window == gtk_layout_get_bin_window (GTK_LAYOUT (container))) {
4912
 
                button_press_event (GTK_WIDGET (container), event);
4913
 
        }
4914
 
 
4915
 
        return TRUE;
4916
 
}
4917
 
 
4918
 
static gboolean
4919
 
nautilus_icon_container_search_entry_button_press_event (GtkWidget *widget,
4920
 
                                                         GdkEventButton *event,
4921
 
                                                         NautilusIconContainer *container)
4922
 
{
4923
 
        reset_search_entry_timeout (container);
4924
 
 
4925
 
        return FALSE;
4926
 
}
4927
 
 
4928
 
static void
4929
 
nautilus_icon_container_search_populate_popup (GtkEntry *entry,
4930
 
                                               GtkMenu *menu,
4931
 
                                               NautilusIconContainer *container)
4932
 
{
4933
 
        remove_search_entry_timeout (container);
4934
 
        g_signal_connect_swapped (menu, "hide",
4935
 
                                  G_CALLBACK (add_search_entry_timeout), container);
4936
 
}
4937
 
 
4938
 
static void
4939
4673
nautilus_icon_container_get_icon_text (NautilusIconContainer *container,
4940
4674
                                       NautilusIconData      *data,
4941
4675
                                       char                 **editable_text,
4951
4685
}
4952
4686
 
4953
4687
static gboolean
4954
 
nautilus_icon_container_search_iter (NautilusIconContainer *container,
4955
 
                                     const char *key, gint n)
4956
 
{
4957
 
        GList *p;
4958
 
        NautilusIcon *icon;
4959
 
        char *name;
4960
 
        int count;
4961
 
        char *normalized_key, *case_normalized_key;
4962
 
        char *normalized_name, *case_normalized_name;
4963
 
        
4964
 
        g_assert (key != NULL);
4965
 
        g_assert (n >= 1);
4966
 
        
4967
 
        normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
4968
 
        if (!normalized_key) {
4969
 
                return FALSE;
4970
 
        }
4971
 
        case_normalized_key = g_utf8_casefold (normalized_key, -1);
4972
 
        g_free (normalized_key);
4973
 
        if (!case_normalized_key) {
4974
 
                return FALSE;
4975
 
        }
4976
 
        
4977
 
        icon = NULL;
4978
 
        name = NULL;
4979
 
        count = 0;
4980
 
        for (p = container->details->icons; p != NULL && count != n; p = p->next) {
4981
 
                icon = p->data;
4982
 
                nautilus_icon_container_get_icon_text (container, icon->data, &name,
4983
 
                                                       NULL, TRUE);
4984
 
                
4985
 
                /* This can happen if a key event is handled really early while
4986
 
                 * loading the icon container, before the items have all been
4987
 
                 * updated once.
4988
 
                 */
4989
 
                if (!name) {
4990
 
                        continue;
4991
 
                }
4992
 
                        
4993
 
                normalized_name = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
4994
 
                if (!normalized_name) {
4995
 
                        continue;
4996
 
                }
4997
 
                case_normalized_name = g_utf8_casefold (normalized_name, -1);
4998
 
                g_free (normalized_name);
4999
 
                if (!case_normalized_name) {
5000
 
                        continue;
5001
 
                }
5002
 
                
5003
 
                if (strncmp (case_normalized_key, case_normalized_name,
5004
 
                             strlen (case_normalized_key)) == 0) {
5005
 
                        count++;
5006
 
                }
5007
 
 
5008
 
                g_free (case_normalized_name);
5009
 
                g_free (name);
5010
 
                name = NULL;
5011
 
        }
5012
 
 
5013
 
        g_free (case_normalized_key);
5014
 
 
5015
 
        if (count == n) {
5016
 
                if (select_one_unselect_others (container, icon)) {
5017
 
                        g_signal_emit (container, signals[SELECTION_CHANGED], 0);
5018
 
                }
5019
 
                schedule_keyboard_icon_reveal (container, icon);
5020
 
                
5021
 
                return TRUE;
5022
 
        }
5023
 
        
5024
 
        return FALSE;
5025
 
}
5026
 
 
5027
 
static void
5028
 
nautilus_icon_container_search_move (GtkWidget *window,
5029
 
                                     NautilusIconContainer *container,
5030
 
                                     gboolean up)
5031
 
{
5032
 
        gboolean ret;
5033
 
        gint len;
5034
 
        const gchar *text;
5035
 
 
5036
 
        text = gtk_entry_get_text (GTK_ENTRY (container->details->search_entry));
5037
 
 
5038
 
        g_assert (text != NULL);
5039
 
 
5040
 
        if (container->details->selected_iter == 0) {
5041
 
                return;
5042
 
        }
5043
 
        
5044
 
        if (up && container->details->selected_iter == 1) {
5045
 
                return;
5046
 
        }
5047
 
 
5048
 
        len = strlen (text);
5049
 
 
5050
 
        if (len < 1) {
5051
 
                return;
5052
 
        }
5053
 
 
5054
 
        /* search */
5055
 
        unselect_all (container);
5056
 
 
5057
 
        ret = nautilus_icon_container_search_iter (container, text,
5058
 
                up?((container->details->selected_iter) - 1):((container->details->selected_iter + 1)));
5059
 
 
5060
 
        if (ret) {
5061
 
                /* found */
5062
 
                container->details->selected_iter += up?(-1):(1);
5063
 
        } else {
5064
 
                /* return to old iter */
5065
 
                nautilus_icon_container_search_iter (container, text,
5066
 
                                        container->details->selected_iter);
5067
 
        }
5068
 
}
5069
 
 
5070
 
static gboolean
5071
 
nautilus_icon_container_search_scroll_event (GtkWidget *widget,
5072
 
                                             GdkEventScroll *event,
5073
 
                                             NautilusIconContainer *container)
5074
 
{
5075
 
        gboolean retval = FALSE;
5076
 
 
5077
 
        if (event->direction == GDK_SCROLL_UP) {
5078
 
                nautilus_icon_container_search_move (widget, container, TRUE);
5079
 
                retval = TRUE;
5080
 
        } else if (event->direction == GDK_SCROLL_DOWN) {
5081
 
                nautilus_icon_container_search_move (widget, container, FALSE);
5082
 
                retval = TRUE;
5083
 
        }
5084
 
 
5085
 
        reset_search_entry_timeout (container);
5086
 
 
5087
 
        return retval;
5088
 
}
5089
 
 
5090
 
static gboolean
5091
 
nautilus_icon_container_search_key_press_event (GtkWidget *widget,
5092
 
                                                GdkEventKey *event,
5093
 
                                                NautilusIconContainer *container)
5094
 
{
5095
 
        gboolean retval = FALSE;
5096
 
 
5097
 
        g_assert (GTK_IS_WIDGET (widget));
5098
 
        g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
5099
 
 
5100
 
        /* close window and cancel the search */
5101
 
        if (event->keyval == GDK_KEY_Escape || event->keyval == GDK_KEY_Tab) {
5102
 
                nautilus_icon_container_search_dialog_hide (widget, container);
5103
 
                return TRUE;
5104
 
        }
5105
 
 
5106
 
        /* close window and activate alternate */
5107
 
        if (event->keyval == GDK_KEY_Return && event->state & GDK_SHIFT_MASK) {
5108
 
                nautilus_icon_container_search_dialog_hide (widget,
5109
 
                                                            container);
5110
 
 
5111
 
                activate_selected_items_alternate (container, NULL);
5112
 
                return TRUE;
5113
 
        }
5114
 
 
5115
 
        /* select previous matching iter */
5116
 
        if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up) {
5117
 
                nautilus_icon_container_search_move (widget, container, TRUE);
5118
 
                retval = TRUE;
5119
 
        }
5120
 
 
5121
 
        if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
5122
 
            && (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G)) {
5123
 
                nautilus_icon_container_search_move (widget, container, TRUE);
5124
 
                retval = TRUE;
5125
 
        }
5126
 
 
5127
 
        /* select next matching iter */
5128
 
        if (event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down) {
5129
 
                nautilus_icon_container_search_move (widget, container, FALSE);
5130
 
                retval = TRUE;
5131
 
        }
5132
 
 
5133
 
        if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
5134
 
            && (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G)) {
5135
 
                nautilus_icon_container_search_move (widget, container, FALSE);
5136
 
                retval = TRUE;
5137
 
        }
5138
 
 
5139
 
        reset_search_entry_timeout (container);
5140
 
 
5141
 
        return retval;
5142
 
}
5143
 
 
5144
 
static void
5145
 
nautilus_icon_container_search_init (GtkWidget   *entry,
5146
 
                                     NautilusIconContainer *container)
5147
 
{
5148
 
        gint ret;
5149
 
        gint len;
5150
 
        const gchar *text;
5151
 
 
5152
 
        g_assert (GTK_IS_ENTRY (entry));
5153
 
        g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
5154
 
 
5155
 
        text = gtk_entry_get_text (GTK_ENTRY (entry));
5156
 
        len = strlen (text);
5157
 
 
5158
 
        /* search */
5159
 
        unselect_all (container);
5160
 
        reset_search_entry_timeout (container);
5161
 
 
5162
 
        if (len < 1) {
5163
 
                return;
5164
 
        }
5165
 
 
5166
 
        ret = nautilus_icon_container_search_iter (container, text, 1);
5167
 
 
5168
 
        if (ret) {
5169
 
                container->details->selected_iter = 1;
5170
 
        }
5171
 
}
5172
 
 
5173
 
static void
5174
 
nautilus_icon_container_ensure_interactive_directory (NautilusIconContainer *container)
5175
 
{
5176
 
        GtkWidget *frame, *vbox;
5177
 
 
5178
 
        if (container->details->search_window != NULL) {
5179
 
                return;
5180
 
        }
5181
 
 
5182
 
        container->details->search_window = gtk_window_new (GTK_WINDOW_POPUP);
5183
 
 
5184
 
        gtk_window_set_modal (GTK_WINDOW (container->details->search_window), TRUE);
5185
 
        gtk_window_set_type_hint (GTK_WINDOW (container->details->search_window),
5186
 
                                  GDK_WINDOW_TYPE_HINT_COMBO);
5187
 
 
5188
 
        g_signal_connect (container->details->search_window, "delete_event",
5189
 
                          G_CALLBACK (nautilus_icon_container_search_delete_event),
5190
 
                          container);
5191
 
        g_signal_connect (container->details->search_window, "key_press_event",
5192
 
                          G_CALLBACK (nautilus_icon_container_search_key_press_event),
5193
 
                          container);
5194
 
        g_signal_connect (container->details->search_window, "button_press_event",
5195
 
                          G_CALLBACK (nautilus_icon_container_search_button_press_event),
5196
 
                          container);
5197
 
        g_signal_connect (container->details->search_window, "scroll_event",
5198
 
                          G_CALLBACK (nautilus_icon_container_search_scroll_event),
5199
 
                          container);
5200
 
 
5201
 
        frame = gtk_frame_new (NULL);
5202
 
        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
5203
 
        gtk_widget_show (frame);
5204
 
        gtk_container_add (GTK_CONTAINER (container->details->search_window), frame);
5205
 
 
5206
 
        vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
5207
 
        gtk_widget_show (vbox);
5208
 
        gtk_container_add (GTK_CONTAINER (frame), vbox);
5209
 
        gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
5210
 
 
5211
 
        /* add entry */
5212
 
        container->details->search_entry = gtk_entry_new ();
5213
 
        gtk_widget_show (container->details->search_entry);
5214
 
        g_signal_connect (container->details->search_entry, "populate-popup",
5215
 
                          G_CALLBACK (nautilus_icon_container_search_populate_popup),
5216
 
                          container);
5217
 
        g_signal_connect (container->details->search_entry, "activate",
5218
 
                          G_CALLBACK (nautilus_icon_container_search_activate),
5219
 
                          container);
5220
 
        g_signal_connect (container->details->search_entry, "preedit-changed",
5221
 
                          G_CALLBACK (nautilus_icon_container_search_preedit_changed),
5222
 
                          container);
5223
 
        g_signal_connect (container->details->search_entry, "button-press-event",
5224
 
                          G_CALLBACK (nautilus_icon_container_search_entry_button_press_event),
5225
 
                          container);
5226
 
        gtk_container_add (GTK_CONTAINER (vbox), container->details->search_entry);
5227
 
 
5228
 
        gtk_widget_realize (container->details->search_entry);
5229
 
}
5230
 
 
5231
 
/* Pops up the interactive search entry.  If keybinding is TRUE then the user
5232
 
 * started this by typing the start_interactive_search keybinding.  Otherwise, it came from 
5233
 
 */
5234
 
static gboolean
5235
 
nautilus_icon_container_start_interactive_search (NautilusIconContainer *container)
5236
 
{
5237
 
        /* We only start interactive search if we have focus.  If one of our
5238
 
         * children have focus, we don't want to start the search.
5239
 
         */
5240
 
        GtkWidgetClass *entry_parent_class;
5241
 
 
5242
 
        if (container->details->search_window != NULL &&
5243
 
            gtk_widget_get_visible (container->details->search_window)) {
5244
 
                return TRUE;
5245
 
        }
5246
 
 
5247
 
        if (!gtk_widget_has_focus (GTK_WIDGET (container))) {
5248
 
                return FALSE;
5249
 
        }
5250
 
 
5251
 
        nautilus_icon_container_ensure_interactive_directory (container);
5252
 
 
5253
 
        /* done, show it */
5254
 
        nautilus_icon_container_search_position_func (container, container->details->search_window);
5255
 
        gtk_widget_show (container->details->search_window);
5256
 
        if (container->details->search_entry_changed_id == 0) {
5257
 
                container->details->search_entry_changed_id =
5258
 
                        g_signal_connect (container->details->search_entry, "changed",
5259
 
                                G_CALLBACK (nautilus_icon_container_search_init),
5260
 
                                container);
5261
 
        }
5262
 
 
5263
 
        /* Grab focus will select all the text.  We don't want that to happen, so we
5264
 
        * call the parent instance and bypass the selection change.  This is probably
5265
 
        * really non-kosher. */
5266
 
        entry_parent_class = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (container->details->search_entry));
5267
 
        (entry_parent_class->grab_focus) (container->details->search_entry);
5268
 
 
5269
 
        /* send focus-in event */
5270
 
        send_focus_change (container->details->search_entry, TRUE);
5271
 
 
5272
 
        /* search first matching iter */
5273
 
        nautilus_icon_container_search_init (container->details->search_entry, container);
5274
 
 
5275
 
        return TRUE;
5276
 
}
5277
 
 
5278
 
static gboolean
5279
4688
handle_popups (NautilusIconContainer *container,
5280
4689
               GdkEventKey           *event,
5281
4690
               const char            *signal)
5314
4723
                default:
5315
4724
                        break;
5316
4725
                }
5317
 
        } else if (container->details->search_window != NULL &&
5318
 
                   gtk_widget_get_visible (container->details->search_window)) {
5319
 
                /* Workaround for BGO #662591, where container is still focused
5320
 
                 * although we're in search mode. Forward events to
5321
 
                 * search_entry, where they belong. */
5322
 
                GdkEvent *new_event = gdk_event_copy ((GdkEvent *) event);
5323
 
                GdkWindow *window = ((GdkEventKey *) new_event)->window;
5324
 
                ((GdkEventKey *) new_event)->window = gtk_widget_get_window (container->details->search_entry);
5325
 
 
5326
 
                handled = gtk_widget_event (container->details->search_window, new_event);
5327
 
 
5328
 
                ((GdkEventKey *) new_event)->window = window;
5329
 
                gdk_event_free(new_event);
5330
4726
        } else {
5331
4727
                switch (event->keyval) {
5332
4728
                case GDK_KEY_Home:
5431
4827
        if (!handled) {
5432
4828
                handled = GTK_WIDGET_CLASS (nautilus_icon_container_parent_class)->key_press_event (widget, event);
5433
4829
        }
5434
 
        
5435
 
        /* We pass the event to the search_entry.  If its text changes, then we
5436
 
         * start the typeahead find capabilities.
5437
 
         * Copied from NautilusIconContainer */
5438
 
        if (!handled &&
5439
 
            event->keyval != GDK_KEY_slash /* don't steal slash key event, used for "go to" */ &&
5440
 
            event->keyval != GDK_KEY_BackSpace &&
5441
 
            event->keyval != GDK_KEY_Delete) {
5442
 
                GdkEvent *new_event;
5443
 
                GdkWindow *window;
5444
 
                char *old_text;
5445
 
                const char *new_text;
5446
 
                gboolean retval;
5447
 
                GdkScreen *screen;
5448
 
                gboolean text_modified;
5449
 
                gulong popup_menu_id;
5450
 
 
5451
 
                nautilus_icon_container_ensure_interactive_directory (container);
5452
 
 
5453
 
                /* Make a copy of the current text */
5454
 
                old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (container->details->search_entry)));
5455
 
                new_event = gdk_event_copy ((GdkEvent *) event);
5456
 
                window = ((GdkEventKey *) new_event)->window;
5457
 
                ((GdkEventKey *) new_event)->window = gtk_widget_get_window (container->details->search_entry);
5458
 
                gtk_widget_realize (container->details->search_window);
5459
 
 
5460
 
                popup_menu_id = g_signal_connect (container->details->search_entry, 
5461
 
                                                  "popup_menu", G_CALLBACK (gtk_true), NULL);
5462
 
 
5463
 
                /* Move the entry off screen */
5464
 
                screen = gtk_widget_get_screen (GTK_WIDGET (container));
5465
 
                gtk_window_move (GTK_WINDOW (container->details->search_window),
5466
 
                gdk_screen_get_width (screen) + 1,
5467
 
                gdk_screen_get_height (screen) + 1);
5468
 
                gtk_widget_show (container->details->search_window);
5469
 
 
5470
 
                /* Send the event to the window.  If the preedit_changed signal is emitted
5471
 
                 * during this event, we will set priv->imcontext_changed  */
5472
 
                container->details->imcontext_changed = FALSE;
5473
 
                retval = gtk_widget_event (container->details->search_entry, new_event);
5474
 
                gtk_widget_hide (container->details->search_window);
5475
 
 
5476
 
                g_signal_handler_disconnect (container->details->search_entry, 
5477
 
                                             popup_menu_id);
5478
 
 
5479
 
                /* We check to make sure that the entry tried to handle the text, and that
5480
 
                 * the text has changed. */
5481
 
                new_text = gtk_entry_get_text (GTK_ENTRY (container->details->search_entry));
5482
 
                text_modified = strcmp (old_text, new_text) != 0;
5483
 
                g_free (old_text);
5484
 
                if (container->details->imcontext_changed ||    /* we're in a preedit */
5485
 
                    (retval && text_modified)) {                /* ...or the text was modified */
5486
 
                        if (nautilus_icon_container_start_interactive_search (container)) {
5487
 
                                gtk_widget_grab_focus (GTK_WIDGET (container));
5488
 
                                return TRUE;
5489
 
                        } else {
5490
 
                                gtk_entry_set_text (GTK_ENTRY (container->details->search_entry), "");
5491
 
                                return FALSE;
5492
 
                        }
5493
 
                }
5494
 
 
5495
 
                ((GdkEventKey *) new_event)->window = window;
5496
 
                gdk_event_free (new_event);
5497
 
        }
5498
4830
 
5499
4831
        return handled;
5500
4832
}
8093
7425
        NautilusIconContainerDetails *details;
8094
7426
        NautilusIcon *icon;
8095
7427
        EelDRect icon_rect;
8096
 
        EelDRect text_rect;
8097
7428
        PangoContext *context;
8098
7429
        PangoFontDescription *desc;
8099
7430
        const char *editable_text;
8148
7479
                eel_editable_label_set_line_wrap_mode (EEL_EDITABLE_LABEL (details->rename_widget), PANGO_WRAP_WORD_CHAR);
8149
7480
                eel_editable_label_set_draw_outline (EEL_EDITABLE_LABEL (details->rename_widget), TRUE);
8150
7481
 
8151
 
                if (details->label_position != NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
8152
 
                        eel_editable_label_set_justify (EEL_EDITABLE_LABEL (details->rename_widget), GTK_JUSTIFY_CENTER);
8153
 
                }
 
7482
                eel_editable_label_set_justify (EEL_EDITABLE_LABEL (details->rename_widget), GTK_JUSTIFY_CENTER);
8154
7483
 
8155
7484
                gtk_misc_set_padding (GTK_MISC (details->rename_widget), 1, 1);
8156
7485
                gtk_layout_put (GTK_LAYOUT (container),
8172
7501
        pango_font_description_free (desc);
8173
7502
        
8174
7503
        icon_rect = nautilus_icon_canvas_item_get_icon_rectangle (icon->item);
8175
 
        text_rect = nautilus_icon_canvas_item_get_text_rectangle (icon->item, TRUE);
8176
 
 
8177
 
        if (nautilus_icon_container_is_layout_vertical (container) &&
8178
 
            container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
8179
 
                /* for one-line editables, the width changes dynamically */
8180
 
                width = -1;
8181
 
        } else {
8182
 
                width = nautilus_icon_canvas_item_get_max_text_width (icon->item);
8183
 
        }
8184
 
 
8185
 
        if (details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
8186
 
                eel_canvas_w2c (EEL_CANVAS_ITEM (icon->item)->canvas,
8187
 
                                text_rect.x0,
8188
 
                                text_rect.y0,
8189
 
                                &x, &y);
8190
 
        } else {
8191
 
                eel_canvas_w2c (EEL_CANVAS_ITEM (icon->item)->canvas,
8192
 
                                (icon_rect.x0 + icon_rect.x1) / 2,
8193
 
                                icon_rect.y1,
8194
 
                                &x, &y);
8195
 
                x = x - width / 2 - 1;
8196
 
        }
 
7504
 
 
7505
        width = nautilus_icon_canvas_item_get_max_text_width (icon->item);
 
7506
 
 
7507
        eel_canvas_w2c (EEL_CANVAS_ITEM (icon->item)->canvas,
 
7508
                        (icon_rect.x0 + icon_rect.x1) / 2,
 
7509
                        icon_rect.y1,
 
7510
                        &x, &y);
 
7511
        x = x - width / 2 - 1;
8197
7512
 
8198
7513
        gtk_layout_move (GTK_LAYOUT (container),
8199
7514
                         details->rename_widget,